2 #include <minix/vfsif.h>
6 FORWARD
_PROTOTYPE( int safe_io_conversion
, (endpoint_t
, cp_grant_id_t
*,
7 int *, cp_grant_id_t
*, int,
8 endpoint_t
*, void **, int *,
10 FORWARD
_PROTOTYPE( void safe_io_cleanup
, (cp_grant_id_t
, cp_grant_id_t
*,
12 FORWARD
_PROTOTYPE( int gen_opcl
, (endpoint_t driver_e
, int op
,
13 Dev_t dev
, int proc_e
, int flags
));
14 FORWARD
_PROTOTYPE( int gen_io
, (int task_nr
, message
*mess_ptr
));
17 /*===========================================================================*
19 *===========================================================================*/
20 PUBLIC
int fs_new_driver(void)
22 /* New driver endpoint for this device */
23 driver_endpoints
[(fs_m_in
.REQ_DEV
>> MAJOR
) & BYTE
].driver_e
=
29 /*===========================================================================*
30 * safe_io_conversion *
31 *===========================================================================*/
32 PRIVATE
int safe_io_conversion(driver
, gid
, op
, gids
, gids_size
,
33 io_ept
, buf
, vec_grants
, bytes
)
47 static iovec_t new_iovec
[NR_IOREQS
];
49 /* Number of grants allocated in vector I/O. */
52 /* Driver can handle it - change request to a safe one. */
59 /* Change to safe op. */
60 *op
= *op
== MFS_DEV_READ
? DEV_READ_S
: DEV_WRITE_S
;
62 if((*gid
=cpf_grant_direct(driver
, (vir_bytes
) *buf
,
63 bytes
, *op
== DEV_READ_S
? CPF_WRITE
:
66 "cpf_grant_magic of buffer failed\n", NO_NUM
);
72 /* Change to safe op. */
73 *op
= *op
== MFS_DEV_GATHER
?
74 DEV_GATHER_S
: DEV_SCATTER_S
;
76 /* Grant access to my new i/o vector. */
77 if((*gid
= cpf_grant_direct(driver
,
78 (vir_bytes
) new_iovec
, bytes
* sizeof(iovec_t
),
79 CPF_READ
| CPF_WRITE
)) < 0) {
81 "cpf_grant_direct of vector failed", NO_NUM
);
84 /* Grant access to i/o buffers. */
85 for(j
= 0; j
< bytes
; j
++) {
87 panic(__FILE__
, "vec too big", bytes
);
88 new_iovec
[j
].iov_addr
= gids
[j
] =
89 cpf_grant_direct(driver
, (vir_bytes
)
90 v
[j
].iov_addr
, v
[j
].iov_size
,
91 *op
== DEV_GATHER_S
? CPF_WRITE
: CPF_READ
);
92 if(!GRANT_VALID(gids
[j
])) {
93 panic(__FILE__
, "mfs: grant to iovec buf failed",
96 new_iovec
[j
].iov_size
= v
[j
].iov_size
;
100 /* Set user's vector to the new one. */
105 /* If we have converted to a safe operation, I/O
106 * endpoint becomes FS if it wasn't already.
108 if(GRANT_VALID(*gid
)) {
113 /* Not converted to a safe operation (because there is no
114 * copying involved in this operation).
120 /*===========================================================================*
122 *===========================================================================*/
123 PRIVATE
void safe_io_cleanup(gid
, gids
, gids_size
)
128 /* Free resources (specifically, grants) allocated by safe_io_conversion(). */
133 for(j
= 0; j
< gids_size
; j
++)
140 /*===========================================================================*
142 *===========================================================================*/
143 PUBLIC
int dev_open(driver_e
, dev
, proc
, flags
)
145 dev_t dev
; /* device to open */
146 int proc
; /* process to open for */
147 int flags
; /* mode bits and flags */
151 /* Determine the major device number call the device class specific
152 * open/close routine. (This is the only routine that must check the
153 * device number for being in range. All others can trust this check.)
155 major
= (dev
>> MAJOR
) & BYTE
;
156 if (major
>= NR_DEVICES
) major
= 0;
157 r
= gen_opcl(driver_e
, DEV_OPEN
, dev
, proc
, flags
);
158 if (r
== SUSPEND
) panic(__FILE__
,"suspend on open from", NO_NUM
);
163 /*===========================================================================*
165 *===========================================================================*/
166 PUBLIC
int block_dev_io(op
, dev
, proc_e
, buf
, pos
, bytes
, flags
)
167 int op
; /* MFS_DEV_READ, MFS_DEV_WRITE, etc. */
168 dev_t dev
; /* major-minor device number */
169 int proc_e
; /* in whose address space is buf? */
170 void *buf
; /* virtual address of the buffer */
171 u64_t pos
; /* byte position */
172 int bytes
; /* how many bytes to transfer */
173 int flags
; /* special flags, like O_NONBLOCK */
175 /* Read or write from a device. The parameter 'dev' tells which one. */
180 cp_grant_id_t gid
= GRANT_INVALID
;
184 static cp_grant_id_t gids
[NR_IOREQS
];
187 /* Determine driver endpoint for this device */
188 driver_e
= driver_endpoints
[(dev
>> MAJOR
) & BYTE
].driver_e
;
190 /* See if driver is roughly valid. */
191 if (driver_e
== NONE
) return(EDSTDIED
);
193 /* The io vector copying relies on this I/O being for FS itself. */
194 if(proc_e
!= SELF_E
) {
195 printf("ISOFS(%d) doing block_dev_io for non-self %d\n", SELF_E
, proc_e
);
196 panic(__FILE__
, "doing block_dev_io for non-self", proc_e
);
199 /* By default, these are right. */
204 /* Convert parameters to 'safe mode'. */
206 safe
= safe_io_conversion(driver_e
, &gid
,
207 &op_used
, gids
, NR_IOREQS
, &m
.IO_ENDPT
, &buf_used
,
210 /* Set up rest of the message. */
211 if (safe
) m
.IO_GRANT
= (char *) gid
;
214 m
.DEVICE
= (dev
>> MINOR
) & BYTE
;
215 m
.POSITION
= ex64lo(pos
);
217 m
.HIGHPOS
= ex64hi(pos
);
220 r
= sendrec(driver_e
, &m
);
222 /* As block I/O never SUSPENDs, safe cleanup must be done whether
223 * the I/O succeeded or not. */
224 if (safe
) safe_io_cleanup(gid
, gids
, vec_grants
);
227 * - send back dead driver number
228 * - VFS unmaps it, waits for new driver
229 * - VFS sends the new driver endp for the FS proc and the request again
232 if (r
== EDEADSRCDST
|| r
== EDSTDIED
|| r
== ESRCDIED
) {
233 printf("ISOFS(%d) dead driver %d\n", SELF_E
, driver_e
);
234 driver_endpoints
[(dev
>> MAJOR
) & BYTE
].driver_e
= NONE
;
237 else if (r
== ELOCKED
) {
241 panic(__FILE__
,"call_task: can't send/receive", r
);
243 /* Did the process we did the sendrec() for get a result? */
244 if (m
.REP_ENDPT
!= proc_e
) {
245 printf("ISOFS (%d) strange device reply from %d, type = %d, proc = %d (not %d) (2) ignored\n", SELF_E
, m
.m_source
, m
.m_type
, proc_e
, m
.REP_ENDPT
);
250 /* Task has completed. See if call completed. */
251 if (m
.REP_STATUS
== SUSPEND
) {
252 panic(__FILE__
, "ISOFS block_dev_io: driver returned SUSPEND", NO_NUM
);
255 if(buf
!= buf_used
&& r
== OK
) {
256 memcpy(buf
, buf_used
, bytes
* sizeof(iovec_t
));
259 return(m
.REP_STATUS
);
263 /*===========================================================================*
265 *===========================================================================*/
266 PRIVATE
int gen_opcl(driver_e
, op
, dev
, proc_e
, flags
)
268 int op
; /* operation, DEV_OPEN or DEV_CLOSE */
269 dev_t dev
; /* device to open or close */
270 int proc_e
; /* process to open/close for */
271 int flags
; /* mode bits and flags */
273 /* Called from the dmap struct in table.c on opens & closes of special files.*/
276 dev_mess
.m_type
= op
;
277 dev_mess
.DEVICE
= (dev
>> MINOR
) & BYTE
;
278 dev_mess
.IO_ENDPT
= proc_e
;
279 dev_mess
.COUNT
= flags
;
282 gen_io(driver_e
, &dev_mess
);
284 return(dev_mess
.REP_STATUS
);
288 /*===========================================================================*
290 *===========================================================================*/
291 PRIVATE
int gen_io(task_nr
, mess_ptr
)
292 int task_nr
; /* which task to call */
293 message
*mess_ptr
; /* pointer to message for task */
295 /* All file system I/O ultimately comes down to I/O on major/minor device
296 * pairs. These lead to calls on the following routines via the dmap table.
301 proc_e
= mess_ptr
->IO_ENDPT
;
303 r
= sendrec(task_nr
, mess_ptr
);
305 if (r
== EDEADSRCDST
|| r
== EDSTDIED
|| r
== ESRCDIED
) {
306 printf("fs: dead driver %d\n", task_nr
);
307 panic(__FILE__
, "should handle crashed drivers",
309 /* dmap_unmap_by_endpt(task_nr); */
313 printf("fs: ELOCKED talking to %d\n", task_nr
);
316 panic(__FILE__
,"call_task: can't send/receive", r
);
319 /* Did the process we did the sendrec() for get a result? */
320 if (mess_ptr
->REP_ENDPT
!= proc_e
) {
322 "fs: strange device reply from %d, type = %d, proc = %d (not %d) (2) ignored\n",
326 mess_ptr
->REP_ENDPT
);
334 /*===========================================================================*
336 *===========================================================================*/
337 PUBLIC
void dev_close(driver_e
, dev
)
339 dev_t dev
; /* device to close */
341 (void) gen_opcl(driver_e
, DEV_CLOSE
, dev
, 0, 0);