4 #include <minix/callnr.h>
6 #include <minix/endpoint.h>
7 #include <minix/ioctl.h>
8 #include <minix/safecopies.h>
16 #include <minix/vfsif.h>
18 PRIVATE
int dummyproc
;
20 FORWARD
_PROTOTYPE( int safe_io_conversion
, (endpoint_t
,
21 cp_grant_id_t
*, int *, cp_grant_id_t
*, int, endpoint_t
*,
22 void **, int *, vir_bytes
));
23 FORWARD
_PROTOTYPE( void safe_io_cleanup
, (cp_grant_id_t
, cp_grant_id_t
*,
25 FORWARD
_PROTOTYPE( int gen_opcl
, (endpoint_t driver_e
, int op
,
26 Dev_t dev
, int proc_e
, int flags
) );
27 FORWARD
_PROTOTYPE( int gen_io
, (int task_nr
, message
*mess_ptr
) );
30 /*===========================================================================*
32 *===========================================================================*/
33 PUBLIC
int fs_new_driver(void)
35 /* New driver endpoint for this device */
36 driver_endpoints
[(fs_m_in
.REQ_DEV
>> MAJOR
) & BYTE
].driver_e
=
42 /*===========================================================================*
43 * safe_io_conversion *
44 *===========================================================================*/
45 PRIVATE
int safe_io_conversion(driver
, gid
, op
, gids
, gids_size
,
46 io_ept
, buf
, vec_grants
, bytes
)
60 static iovec_t
*new_iovec
;
62 STATICINIT(new_iovec
, NR_IOREQS
);
64 /* Number of grants allocated in vector I/O. */
67 /* Driver can handle it - change request to a safe one. */
74 /* Change to safe op. */
75 *op
= *op
== MFS_DEV_READ
? DEV_READ_S
: DEV_WRITE_S
;
77 if((*gid
=cpf_grant_direct(driver
, (vir_bytes
) *buf
, bytes
,
78 *op
== DEV_READ_S
?CPF_WRITE
:CPF_READ
))<0) {
79 panic(__FILE__
,"cpf_grant_magic of buffer failed\n", NO_NUM
);
85 /* Change to safe op. */
86 *op
= *op
== MFS_DEV_GATHER
? DEV_GATHER_S
: DEV_SCATTER_S
;
88 /* Grant access to my new i/o vector. */
89 if((*gid
= cpf_grant_direct(driver
, (vir_bytes
) new_iovec
,
90 bytes
* sizeof(iovec_t
),
91 CPF_READ
| CPF_WRITE
)) < 0) {
92 panic(__FILE__
, "cpf_grant_direct of vector failed", NO_NUM
);
95 /* Grant access to i/o buffers. */
96 for(j
= 0; j
< bytes
; j
++) {
98 panic(__FILE__
, "vec too big", bytes
);
99 new_iovec
[j
].iov_addr
= gids
[j
] =
100 cpf_grant_direct(driver
, (vir_bytes
) v
[j
].iov_addr
,
102 *op
== DEV_GATHER_S
? CPF_WRITE
: CPF_READ
);
103 if(!GRANT_VALID(gids
[j
])) {
104 panic(__FILE__
, "mfs: grant to iovec buf failed",
107 new_iovec
[j
].iov_size
= v
[j
].iov_size
;
111 /* Set user's vector to the new one. */
116 /* If we have converted to a safe operation, I/O
117 * endpoint becomes FS if it wasn't already.
119 if(GRANT_VALID(*gid
)) {
124 /* Not converted to a safe operation (because there is no
125 * copying involved in this operation).
130 /*===========================================================================*
132 *===========================================================================*/
133 PRIVATE
void safe_io_cleanup(gid
, gids
, gids_size
)
138 /* Free resources (specifically, grants) allocated by safe_io_conversion(). */
143 for(j
= 0; j
< gids_size
; j
++)
149 /*===========================================================================*
151 *===========================================================================*/
152 PUBLIC
int block_dev_io(op
, dev
, proc_e
, buf
, pos
, bytes
, flags
)
153 int op
; /* MFS_DEV_READ, MFS_DEV_WRITE, etc. */
154 dev_t dev
; /* major-minor device number */
155 int proc_e
; /* in whose address space is buf? */
156 void *buf
; /* virtual address of the buffer */
157 u64_t pos
; /* byte position */
158 int bytes
; /* how many bytes to transfer */
159 int flags
; /* special flags, like O_NONBLOCK */
161 /* Read or write from a device. The parameter 'dev' tells which one. */
166 cp_grant_id_t gid
= GRANT_INVALID
;
170 static cp_grant_id_t
*gids
;
173 STATICINIT(gids
, NR_IOREQS
);
175 /* Determine driver endpoint for this device */
176 driver_e
= driver_endpoints
[(dev
>> MAJOR
) & BYTE
].driver_e
;
178 /* See if driver is roughly valid. */
179 if (driver_e
== NONE
) {
180 printf("MFS(%d) block_dev_io: no driver for dev %x\n", SELF_E
, dev
);
184 /* The io vector copying relies on this I/O being for FS itself. */
185 if(proc_e
!= SELF_E
) {
186 printf("MFS(%d) doing block_dev_io for non-self %d\n", SELF_E
, proc_e
);
187 panic(__FILE__
, "doing block_dev_io for non-self", proc_e
);
190 /* By default, these are right. */
195 /* Convert parameters to 'safe mode'. */
197 safe
= safe_io_conversion(driver_e
, &gid
,
198 &op_used
, gids
, NR_IOREQS
, &m
.IO_ENDPT
, &buf_used
,
201 /* Set up rest of the message. */
202 if (safe
) m
.IO_GRANT
= (char *) gid
;
205 m
.DEVICE
= (dev
>> MINOR
) & BYTE
;
206 m
.POSITION
= ex64lo(pos
);
208 m
.HIGHPOS
= ex64hi(pos
);
211 r
= sendrec(driver_e
, &m
);
213 /* As block I/O never SUSPENDs, safe cleanup must be done whether
214 * the I/O succeeded or not. */
215 if (safe
) safe_io_cleanup(gid
, gids
, vec_grants
);
218 * - send back dead driver number
219 * - VFS unmaps it, waits for new driver
220 * - VFS sends the new driver endp for the FS proc and the request again
223 if (r
== EDEADSRCDST
|| r
== EDSTDIED
|| r
== ESRCDIED
) {
224 printf("MFS(%d) dead driver %d\n", SELF_E
, driver_e
);
225 driver_endpoints
[(dev
>> MAJOR
) & BYTE
].driver_e
= NONE
;
227 /*dmap_unmap_by_endpt(task_nr); <- in the VFS proc... */
229 else if (r
== ELOCKED
) {
230 printf("MFS(%d) ELOCKED talking to %d\n", SELF_E
, driver_e
);
234 panic(__FILE__
,"call_task: can't send/receive", r
);
237 /* Did the process we did the sendrec() for get a result? */
238 if (m
.REP_ENDPT
!= proc_e
) {
239 printf("MFS(%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
);
244 /* Task has completed. See if call completed. */
245 if (m
.REP_STATUS
== SUSPEND
) {
246 panic(__FILE__
, "MFS block_dev_io: driver returned SUSPEND", NO_NUM
);
249 if(buf
!= buf_used
&& r
== OK
) {
250 memcpy(buf
, buf_used
, bytes
* sizeof(iovec_t
));
253 return(m
.REP_STATUS
);
256 /*===========================================================================*
258 *===========================================================================*/
259 PUBLIC
int dev_open(driver_e
, dev
, proc
, flags
)
261 dev_t dev
; /* device to open */
262 int proc
; /* process to open for */
263 int flags
; /* mode bits and flags */
267 /* Determine the major device number call the device class specific
268 * open/close routine. (This is the only routine that must check the
269 * device number for being in range. All others can trust this check.)
271 major
= (dev
>> MAJOR
) & BYTE
;
272 if (major
>= NR_DEVICES
) major
= 0;
273 r
= gen_opcl(driver_e
, DEV_OPEN
, dev
, proc
, flags
);
274 if (r
== SUSPEND
) panic(__FILE__
,"suspend on open from", NO_NUM
);
279 /*===========================================================================*
281 *===========================================================================*/
282 PUBLIC
void dev_close(driver_e
, dev
)
284 dev_t dev
; /* device to close */
286 (void) gen_opcl(driver_e
, DEV_CLOSE
, dev
, 0, 0);
290 /*===========================================================================*
292 *===========================================================================*/
293 PRIVATE
int gen_opcl(driver_e
, op
, dev
, proc_e
, flags
)
295 int op
; /* operation, DEV_OPEN or DEV_CLOSE */
296 dev_t dev
; /* device to open or close */
297 int proc_e
; /* process to open/close for */
298 int flags
; /* mode bits and flags */
300 /* Called from the dmap struct in table.c on opens & closes of special files.*/
303 dev_mess
.m_type
= op
;
304 dev_mess
.DEVICE
= (dev
>> MINOR
) & BYTE
;
305 dev_mess
.IO_ENDPT
= proc_e
;
306 dev_mess
.COUNT
= flags
;
309 gen_io(driver_e
, &dev_mess
);
311 return(dev_mess
.REP_STATUS
);
315 /*===========================================================================*
317 *===========================================================================*/
318 PRIVATE
int gen_io(task_nr
, mess_ptr
)
319 int task_nr
; /* which task to call */
320 message
*mess_ptr
; /* pointer to message for task */
322 /* All file system I/O ultimately comes down to I/O on major/minor device
323 * pairs. These lead to calls on the following routines via the dmap table.
328 proc_e
= mess_ptr
->IO_ENDPT
;
330 r
= sendrec(task_nr
, mess_ptr
);
332 if (r
== EDEADSRCDST
|| r
== EDSTDIED
|| r
== ESRCDIED
) {
333 printf("fs: dead driver %d\n", task_nr
);
334 panic(__FILE__
, "should handle crashed drivers",
336 /* dmap_unmap_by_endpt(task_nr); */
340 printf("fs: ELOCKED talking to %d\n", task_nr
);
343 panic(__FILE__
,"call_task: can't send/receive", r
);
346 /* Did the process we did the sendrec() for get a result? */
347 if (mess_ptr
->REP_ENDPT
!= proc_e
) {
349 "fs: strange device reply from %d, type = %d, proc = %d (not %d) (2) ignored\n",
353 mess_ptr
->REP_ENDPT
);