Fixed extern declaration from pointer to array
[minix.git] / servers / iso9660fs / device.c
blob0b8cf25cd2b7d6c239069dd30ce0126e2d0be362
1 #include "inc.h"
2 #include <minix/vfsif.h>
4 PRIVATE int dummyproc;
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 *,
9 vir_bytes));
10 FORWARD _PROTOTYPE( void safe_io_cleanup, (cp_grant_id_t, cp_grant_id_t *,
11 int));
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 /*===========================================================================*
18 * fs_new_driver *
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 =
24 fs_m_in.REQ_DRIVER_E;
25 return(OK);
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)
34 endpoint_t driver;
35 cp_grant_id_t *gid;
36 int *op;
37 cp_grant_id_t *gids;
38 int gids_size;
39 endpoint_t *io_ept;
40 void **buf;
41 int *vec_grants;
42 vir_bytes bytes;
44 int access = 0, size;
45 int j;
46 iovec_t *v;
47 static iovec_t new_iovec[NR_IOREQS];
49 /* Number of grants allocated in vector I/O. */
50 *vec_grants = 0;
52 /* Driver can handle it - change request to a safe one. */
54 *gid = GRANT_INVALID;
56 switch(*op) {
57 case MFS_DEV_READ:
58 case MFS_DEV_WRITE:
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 :
64 CPF_READ)) < 0) {
65 panic(__FILE__,
66 "cpf_grant_magic of buffer failed\n", NO_NUM);
69 break;
70 case MFS_DEV_GATHER:
71 case MFS_DEV_SCATTER:
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) {
80 panic(__FILE__,
81 "cpf_grant_direct of vector failed", NO_NUM);
83 v = (iovec_t *) *buf;
84 /* Grant access to i/o buffers. */
85 for(j = 0; j < bytes; j++) {
86 if(j >= NR_IOREQS)
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",
94 NO_NUM);
96 new_iovec[j].iov_size = v[j].iov_size;
97 (*vec_grants)++;
100 /* Set user's vector to the new one. */
101 *buf = new_iovec;
102 break;
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)) {
109 *io_ept = SELF_E;
110 return 1;
113 /* Not converted to a safe operation (because there is no
114 * copying involved in this operation).
116 return 0;
120 /*===========================================================================*
121 * safe_io_cleanup *
122 *===========================================================================*/
123 PRIVATE void safe_io_cleanup(gid, gids, gids_size)
124 cp_grant_id_t gid;
125 cp_grant_id_t *gids;
126 int gids_size;
128 /* Free resources (specifically, grants) allocated by safe_io_conversion(). */
129 int j;
131 cpf_revoke(gid);
133 for(j = 0; j < gids_size; j++)
134 cpf_revoke(gids[j]);
136 return;
140 /*===========================================================================*
141 * dev_open *
142 *===========================================================================*/
143 PUBLIC int dev_open(driver_e, dev, proc, flags)
144 endpoint_t driver_e;
145 dev_t dev; /* device to open */
146 int proc; /* process to open for */
147 int flags; /* mode bits and flags */
149 int major, r;
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);
159 return(r);
163 /*===========================================================================*
164 * block_dev_io *
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. */
176 struct dmap *dp;
177 int r, safe;
178 message m;
179 iovec_t *v;
180 cp_grant_id_t gid = GRANT_INVALID;
181 int vec_grants;
182 int op_used;
183 void *buf_used;
184 static cp_grant_id_t gids[NR_IOREQS];
185 endpoint_t driver_e;
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. */
200 m.IO_ENDPT = proc_e;
201 m.ADDRESS = buf;
202 buf_used = buf;
204 /* Convert parameters to 'safe mode'. */
205 op_used = op;
206 safe = safe_io_conversion(driver_e, &gid,
207 &op_used, gids, NR_IOREQS, &m.IO_ENDPT, &buf_used,
208 &vec_grants, bytes);
210 /* Set up rest of the message. */
211 if (safe) m.IO_GRANT = (char *) gid;
213 m.m_type = op_used;
214 m.DEVICE = (dev >> MINOR) & BYTE;
215 m.POSITION = ex64lo(pos);
216 m.COUNT = bytes;
217 m.HIGHPOS = ex64hi(pos);
219 /* Call the task. */
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);
226 /* RECOVERY:
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
231 if (r != OK) {
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;
235 return(r);
237 else if (r == ELOCKED) {
238 return(r);
240 else
241 panic(__FILE__,"call_task: can't send/receive", r);
242 } else {
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);
246 r = EIO;
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 /*===========================================================================*
264 * gen_opcl *
265 *===========================================================================*/
266 PRIVATE int gen_opcl(driver_e, op, dev, proc_e, flags)
267 endpoint_t driver_e;
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.*/
274 message dev_mess;
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;
281 /* Call the task. */
282 gen_io(driver_e, &dev_mess);
284 return(dev_mess.REP_STATUS);
288 /*===========================================================================*
289 * gen_io *
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.
299 int r, proc_e;
301 proc_e = mess_ptr->IO_ENDPT;
303 r = sendrec(task_nr, mess_ptr);
304 if (r != OK) {
305 if (r == EDEADSRCDST || r == EDSTDIED || r == ESRCDIED) {
306 printf("fs: dead driver %d\n", task_nr);
307 panic(__FILE__, "should handle crashed drivers",
308 NO_NUM);
309 /* dmap_unmap_by_endpt(task_nr); */
310 return r;
312 if (r == ELOCKED) {
313 printf("fs: ELOCKED talking to %d\n", task_nr);
314 return r;
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) {
321 printf(
322 "fs: strange device reply from %d, type = %d, proc = %d (not %d) (2) ignored\n",
323 mess_ptr->m_source,
324 mess_ptr->m_type,
325 proc_e,
326 mess_ptr->REP_ENDPT);
327 return(EIO);
330 return(OK);
334 /*===========================================================================*
335 * dev_close *
336 *===========================================================================*/
337 PUBLIC void dev_close(driver_e, dev)
338 endpoint_t driver_e;
339 dev_t dev; /* device to close */
341 (void) gen_opcl(driver_e, DEV_CLOSE, dev, 0, 0);