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
:
65 panic("cpf_grant_magic of buffer failed");
71 /* Change to safe op. */
72 *op
= *op
== MFS_DEV_GATHER
?
73 DEV_GATHER_S
: DEV_SCATTER_S
;
75 /* Grant access to my new i/o vector. */
76 if((*gid
= cpf_grant_direct(driver
,
77 (vir_bytes
) new_iovec
, bytes
* sizeof(iovec_t
),
78 CPF_READ
| CPF_WRITE
)) < 0) {
79 panic("cpf_grant_direct of vector failed");
82 /* Grant access to i/o buffers. */
83 for(j
= 0; j
< bytes
; j
++) {
85 panic("vec too big: %d", bytes
);
86 new_iovec
[j
].iov_addr
= gids
[j
] =
87 cpf_grant_direct(driver
, (vir_bytes
)
88 v
[j
].iov_addr
, v
[j
].iov_size
,
89 *op
== DEV_GATHER_S
? CPF_WRITE
: CPF_READ
);
90 if(!GRANT_VALID(gids
[j
])) {
91 panic("mfs: grant to iovec buf failed");
93 new_iovec
[j
].iov_size
= v
[j
].iov_size
;
97 /* Set user's vector to the new one. */
102 /* If we have converted to a safe operation, I/O
103 * endpoint becomes FS if it wasn't already.
105 if(GRANT_VALID(*gid
)) {
110 /* Not converted to a safe operation (because there is no
111 * copying involved in this operation).
117 /*===========================================================================*
119 *===========================================================================*/
120 PRIVATE
void safe_io_cleanup(gid
, gids
, gids_size
)
125 /* Free resources (specifically, grants) allocated by safe_io_conversion(). */
130 for(j
= 0; j
< gids_size
; j
++)
137 /*===========================================================================*
139 *===========================================================================*/
140 PUBLIC
int dev_open(driver_e
, dev
, proc
, flags
)
142 dev_t dev
; /* device to open */
143 int proc
; /* process to open for */
144 int flags
; /* mode bits and flags */
148 /* Determine the major device number call the device class specific
149 * open/close routine. (This is the only routine that must check the
150 * device number for being in range. All others can trust this check.)
152 major
= (dev
>> MAJOR
) & BYTE
;
153 if (major
>= NR_DEVICES
) major
= 0;
154 r
= gen_opcl(driver_e
, DEV_OPEN
, dev
, proc
, flags
);
155 if (r
== SUSPEND
) panic("suspend on open from");
160 /*===========================================================================*
162 *===========================================================================*/
163 PUBLIC
int block_dev_io(op
, dev
, proc_e
, buf
, pos
, bytes
, flags
)
164 int op
; /* MFS_DEV_READ, MFS_DEV_WRITE, etc. */
165 dev_t dev
; /* major-minor device number */
166 int proc_e
; /* in whose address space is buf? */
167 void *buf
; /* virtual address of the buffer */
168 u64_t pos
; /* byte position */
169 int bytes
; /* how many bytes to transfer */
170 int flags
; /* special flags, like O_NONBLOCK */
172 /* Read or write from a device. The parameter 'dev' tells which one. */
177 cp_grant_id_t gid
= GRANT_INVALID
;
181 static cp_grant_id_t gids
[NR_IOREQS
];
184 /* Determine driver endpoint for this device */
185 driver_e
= driver_endpoints
[(dev
>> MAJOR
) & BYTE
].driver_e
;
187 /* See if driver is roughly valid. */
188 if (driver_e
== NONE
) return(EDEADSRCDST
);
190 /* The io vector copying relies on this I/O being for FS itself. */
191 if(proc_e
!= SELF_E
) {
192 printf("ISOFS(%d) doing block_dev_io for non-self %d\n", SELF_E
, proc_e
);
193 panic("doing block_dev_io for non-self: %d", proc_e
);
196 /* By default, these are right. */
201 /* Convert parameters to 'safe mode'. */
203 safe
= safe_io_conversion(driver_e
, &gid
,
204 &op_used
, gids
, NR_IOREQS
, &m
.IO_ENDPT
, &buf_used
,
207 /* Set up rest of the message. */
208 if (safe
) m
.IO_GRANT
= (char *) gid
;
211 m
.DEVICE
= (dev
>> MINOR
) & BYTE
;
212 m
.POSITION
= ex64lo(pos
);
214 m
.HIGHPOS
= ex64hi(pos
);
217 r
= sendrec(driver_e
, &m
);
219 /* As block I/O never SUSPENDs, safe cleanup must be done whether
220 * the I/O succeeded or not. */
221 if (safe
) safe_io_cleanup(gid
, gids
, vec_grants
);
224 * - send back dead driver number
225 * - VFS unmaps it, waits for new driver
226 * - VFS sends the new driver endp for the FS proc and the request again
229 if (r
== EDEADSRCDST
) {
230 printf("ISOFS(%d) dead driver %d\n", SELF_E
, driver_e
);
231 driver_endpoints
[(dev
>> MAJOR
) & BYTE
].driver_e
= NONE
;
234 else if (r
== ELOCKED
) {
238 panic("call_task: can't send/receive: %d", r
);
240 /* Did the process we did the sendrec() for get a result? */
241 if (m
.REP_ENDPT
!= proc_e
) {
242 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
);
247 /* Task has completed. See if call completed. */
248 if (m
.REP_STATUS
== SUSPEND
) {
249 panic("ISOFS block_dev_io: driver returned SUSPEND");
252 if(buf
!= buf_used
&& r
== OK
) {
253 memcpy(buf
, buf_used
, bytes
* sizeof(iovec_t
));
256 return(m
.REP_STATUS
);
260 /*===========================================================================*
262 *===========================================================================*/
263 PRIVATE
int gen_opcl(driver_e
, op
, dev
, proc_e
, flags
)
265 int op
; /* operation, DEV_OPEN or DEV_CLOSE */
266 dev_t dev
; /* device to open or close */
267 int proc_e
; /* process to open/close for */
268 int flags
; /* mode bits and flags */
270 /* Called from the dmap struct in table.c on opens & closes of special files.*/
273 dev_mess
.m_type
= op
;
274 dev_mess
.DEVICE
= (dev
>> MINOR
) & BYTE
;
275 dev_mess
.IO_ENDPT
= proc_e
;
276 dev_mess
.COUNT
= flags
;
279 gen_io(driver_e
, &dev_mess
);
281 return(dev_mess
.REP_STATUS
);
285 /*===========================================================================*
287 *===========================================================================*/
288 PRIVATE
int gen_io(task_nr
, mess_ptr
)
289 int task_nr
; /* which task to call */
290 message
*mess_ptr
; /* pointer to message for task */
292 /* All file system I/O ultimately comes down to I/O on major/minor device
293 * pairs. These lead to calls on the following routines via the dmap table.
298 proc_e
= mess_ptr
->IO_ENDPT
;
300 r
= sendrec(task_nr
, mess_ptr
);
302 if (r
== EDEADSRCDST
) {
303 printf("fs: dead driver %d\n", task_nr
);
304 panic("should handle crashed drivers");
305 /* dmap_unmap_by_endpt(task_nr); */
309 printf("fs: ELOCKED talking to %d\n", task_nr
);
312 panic("call_task: can't send/receive: %d", r
);
315 /* Did the process we did the sendrec() for get a result? */
316 if (mess_ptr
->REP_ENDPT
!= proc_e
) {
318 "fs: strange device reply from %d, type = %d, proc = %d (not %d) (2) ignored\n",
322 mess_ptr
->REP_ENDPT
);
330 /*===========================================================================*
332 *===========================================================================*/
333 PUBLIC
void dev_close(driver_e
, dev
)
335 dev_t dev
; /* device to close */
337 (void) gen_opcl(driver_e
, DEV_CLOSE
, dev
, 0, 0);