scsi_base.c revision 1.2 1 1.1 mycroft /*
2 1.1 mycroft * Written by Julian Elischer (julian (at) dialix.oz.au)
3 1.2 mycroft * $Id: scsi_base.c,v 1.2 1993/11/24 09:45:04 mycroft Exp $
4 1.1 mycroft */
5 1.1 mycroft
6 1.1 mycroft #include <sys/types.h>
7 1.1 mycroft #include <sys/param.h>
8 1.1 mycroft #include <sys/buf.h>
9 1.1 mycroft #include <sys/uio.h>
10 1.1 mycroft #include <sys/malloc.h>
11 1.1 mycroft #include <sys/errno.h>
12 1.1 mycroft #include <sys/device.h>
13 1.2 mycroft
14 1.1 mycroft #include <scsi/scsi_all.h>
15 1.1 mycroft #include <scsi/scsi_disk.h>
16 1.1 mycroft #include <scsi/scsiconf.h>
17 1.1 mycroft
18 1.1 mycroft #ifdef DDB
19 1.1 mycroft int Debugger();
20 1.1 mycroft #else /* DDB */
21 1.1 mycroft #define Debugger()
22 1.1 mycroft #endif /* DDB */
23 1.1 mycroft
24 1.2 mycroft void sc_print_addr __P((struct scsi_link *sc_link));
25 1.1 mycroft
26 1.1 mycroft struct scsi_xfer *next_free_xs;
27 1.1 mycroft
28 1.1 mycroft /*
29 1.1 mycroft * Get a scsi transfer structure for the caller. Charge the structure
30 1.1 mycroft * to the device that is referenced by the sc_link structure. If the
31 1.1 mycroft * sc_link structure has no 'credits' then the device already has the
32 1.1 mycroft * maximum number or outstanding operations under way. In this stage,
33 1.1 mycroft * wait on the structure so that when one is freed, we are awoken again
34 1.1 mycroft * If the SCSI_NOSLEEP flag is set, then do not wait, but rather, return
35 1.1 mycroft * a NULL pointer, signifying that no slots were available
36 1.1 mycroft * Note in the link structure, that we are waiting on it.
37 1.1 mycroft */
38 1.1 mycroft
39 1.1 mycroft struct scsi_xfer *
40 1.1 mycroft get_xs(sc_link, flags)
41 1.2 mycroft struct scsi_link *sc_link; /* who to charge the xs to */
42 1.1 mycroft u_int32 flags; /* if this call can sleep */
43 1.1 mycroft {
44 1.2 mycroft struct scsi_xfer *xs;
45 1.1 mycroft u_int32 s;
46 1.1 mycroft
47 1.1 mycroft SC_DEBUG(sc_link, SDEV_DB3, ("get_xs\n"));
48 1.1 mycroft s = splbio();
49 1.1 mycroft while (!sc_link->opennings) {
50 1.1 mycroft SC_DEBUG(sc_link, SDEV_DB3, ("sleeping\n"));
51 1.1 mycroft if (flags & SCSI_NOSLEEP) {
52 1.1 mycroft splx(s);
53 1.1 mycroft return 0;
54 1.1 mycroft }
55 1.1 mycroft sc_link->flags |= SDEV_WAITING;
56 1.1 mycroft sleep(sc_link, PRIBIO);
57 1.1 mycroft }
58 1.1 mycroft sc_link->opennings--;
59 1.1 mycroft if (xs = next_free_xs) {
60 1.1 mycroft next_free_xs = xs->next;
61 1.1 mycroft splx(s);
62 1.1 mycroft } else {
63 1.1 mycroft splx(s);
64 1.1 mycroft SC_DEBUG(sc_link, SDEV_DB3, ("making\n"));
65 1.1 mycroft xs = malloc(sizeof(*xs), M_TEMP,
66 1.1 mycroft ((flags & SCSI_NOSLEEP) ? M_NOWAIT : M_WAITOK));
67 1.1 mycroft if (xs == NULL) {
68 1.1 mycroft sc_print_addr(sc_link);
69 1.1 mycroft printf("cannot allocate scsi xs\n");
70 1.1 mycroft return (NULL);
71 1.1 mycroft }
72 1.1 mycroft }
73 1.1 mycroft SC_DEBUG(sc_link, SDEV_DB3, ("returning\n"));
74 1.1 mycroft xs->sc_link = sc_link;
75 1.1 mycroft return (xs);
76 1.1 mycroft }
77 1.1 mycroft
78 1.1 mycroft /*
79 1.1 mycroft * Given a scsi_xfer struct, and a device (referenced through sc_link)
80 1.1 mycroft * return the struct to the free pool and credit the device with it
81 1.1 mycroft * If another process is waiting for an xs, do a wakeup, let it proceed
82 1.1 mycroft */
83 1.1 mycroft void
84 1.1 mycroft free_xs(xs, sc_link, flags)
85 1.1 mycroft struct scsi_xfer *xs;
86 1.1 mycroft struct scsi_link *sc_link; /* who to credit for returning it */
87 1.1 mycroft u_int32 flags;
88 1.1 mycroft {
89 1.1 mycroft xs->next = next_free_xs;
90 1.1 mycroft next_free_xs = xs;
91 1.1 mycroft
92 1.1 mycroft SC_DEBUG(sc_link, SDEV_DB3, ("free_xs\n"));
93 1.1 mycroft /* if was 0 and someone waits, wake them up */
94 1.2 mycroft if ((!sc_link->opennings++) && (sc_link->flags & SDEV_WAITING))
95 1.1 mycroft wakeup(sc_link);
96 1.2 mycroft else
97 1.1 mycroft if (sc_link->device->start) {
98 1.1 mycroft SC_DEBUG(sc_link, SDEV_DB2, ("calling private start()\n"));
99 1.1 mycroft (*(sc_link->device->start)) (sc_link->dev_unit);
100 1.1 mycroft }
101 1.1 mycroft }
102 1.1 mycroft
103 1.1 mycroft /*
104 1.1 mycroft * Find out from the device what its capacity is.
105 1.1 mycroft */
106 1.1 mycroft u_int32
107 1.1 mycroft scsi_size(sc_link, flags)
108 1.1 mycroft struct scsi_link *sc_link;
109 1.1 mycroft u_int32 flags;
110 1.1 mycroft {
111 1.1 mycroft struct scsi_read_cap_data rdcap;
112 1.1 mycroft struct scsi_read_capacity scsi_cmd;
113 1.1 mycroft u_int32 size;
114 1.1 mycroft
115 1.1 mycroft /*
116 1.1 mycroft * make up a scsi command and ask the scsi driver to do
117 1.1 mycroft * it for you.
118 1.1 mycroft */
119 1.1 mycroft bzero(&scsi_cmd, sizeof(scsi_cmd));
120 1.1 mycroft scsi_cmd.op_code = READ_CAPACITY;
121 1.1 mycroft
122 1.1 mycroft /*
123 1.1 mycroft * If the command works, interpret the result as a 4 byte
124 1.1 mycroft * number of blocks
125 1.1 mycroft */
126 1.2 mycroft if (scsi_scsi_cmd(sc_link, (struct scsi_generic *) &scsi_cmd,
127 1.2 mycroft sizeof(scsi_cmd), (u_char *) & rdcap, sizeof(rdcap),
128 1.2 mycroft 2, 20000, NULL, flags | SCSI_DATA_IN) != 0) {
129 1.1 mycroft sc_print_addr(sc_link);
130 1.1 mycroft printf("could not get size\n");
131 1.1 mycroft return (0);
132 1.1 mycroft } else {
133 1.1 mycroft size = rdcap.addr_0 + 1;
134 1.1 mycroft size += rdcap.addr_1 << 8;
135 1.1 mycroft size += rdcap.addr_2 << 16;
136 1.1 mycroft size += rdcap.addr_3 << 24;
137 1.1 mycroft }
138 1.1 mycroft return (size);
139 1.1 mycroft }
140 1.1 mycroft
141 1.1 mycroft /*
142 1.1 mycroft * Get scsi driver to send a "are you ready?" command
143 1.1 mycroft */
144 1.2 mycroft int
145 1.1 mycroft scsi_test_unit_ready(sc_link, flags)
146 1.1 mycroft struct scsi_link *sc_link;
147 1.1 mycroft u_int32 flags;
148 1.1 mycroft {
149 1.1 mycroft struct scsi_test_unit_ready scsi_cmd;
150 1.1 mycroft
151 1.1 mycroft bzero(&scsi_cmd, sizeof(scsi_cmd));
152 1.1 mycroft scsi_cmd.op_code = TEST_UNIT_READY;
153 1.1 mycroft
154 1.2 mycroft return scsi_scsi_cmd(sc_link, (struct scsi_generic *) &scsi_cmd,
155 1.2 mycroft sizeof(scsi_cmd), 0, 0, 2, 100000, NULL, flags);
156 1.1 mycroft }
157 1.1 mycroft
158 1.1 mycroft /*
159 1.1 mycroft * Do a scsi operation, asking a device to run as SCSI-II if it can.
160 1.1 mycroft */
161 1.2 mycroft int
162 1.1 mycroft scsi_change_def(sc_link, flags)
163 1.1 mycroft struct scsi_link *sc_link;
164 1.1 mycroft u_int32 flags;
165 1.1 mycroft {
166 1.1 mycroft struct scsi_changedef scsi_cmd;
167 1.1 mycroft
168 1.1 mycroft bzero(&scsi_cmd, sizeof(scsi_cmd));
169 1.1 mycroft scsi_cmd.op_code = CHANGE_DEFINITION;
170 1.1 mycroft scsi_cmd.how = SC_SCSI_2;
171 1.1 mycroft
172 1.2 mycroft return scsi_scsi_cmd(sc_link, (struct scsi_generic *) &scsi_cmd,
173 1.2 mycroft sizeof(scsi_cmd), 0, 0, 2, 100000, NULL, flags);
174 1.1 mycroft }
175 1.1 mycroft
176 1.1 mycroft /*
177 1.1 mycroft * Do a scsi operation asking a device what it is
178 1.1 mycroft * Use the scsi_cmd routine in the switch table.
179 1.1 mycroft */
180 1.2 mycroft int
181 1.1 mycroft scsi_inquire(sc_link, inqbuf, flags)
182 1.1 mycroft struct scsi_link *sc_link;
183 1.1 mycroft struct scsi_inquiry_data *inqbuf;
184 1.1 mycroft u_int32 flags;
185 1.1 mycroft {
186 1.1 mycroft struct scsi_inquiry scsi_cmd;
187 1.1 mycroft
188 1.1 mycroft bzero(&scsi_cmd, sizeof(scsi_cmd));
189 1.1 mycroft scsi_cmd.op_code = INQUIRY;
190 1.1 mycroft scsi_cmd.length = sizeof(struct scsi_inquiry_data);
191 1.1 mycroft
192 1.2 mycroft return scsi_scsi_cmd(sc_link, (struct scsi_generic *) &scsi_cmd,
193 1.2 mycroft sizeof(scsi_cmd), (u_char *) inqbuf,
194 1.2 mycroft sizeof(struct scsi_inquiry_data), 2, 100000, NULL,
195 1.2 mycroft SCSI_DATA_IN | flags);
196 1.1 mycroft }
197 1.1 mycroft
198 1.1 mycroft /*
199 1.1 mycroft * Prevent or allow the user to remove the media
200 1.1 mycroft */
201 1.2 mycroft int
202 1.1 mycroft scsi_prevent(sc_link, type, flags)
203 1.1 mycroft struct scsi_link *sc_link;
204 1.1 mycroft u_int32 type, flags;
205 1.1 mycroft {
206 1.1 mycroft struct scsi_prevent scsi_cmd;
207 1.1 mycroft
208 1.1 mycroft bzero(&scsi_cmd, sizeof(scsi_cmd));
209 1.1 mycroft scsi_cmd.op_code = PREVENT_ALLOW;
210 1.1 mycroft scsi_cmd.how = type;
211 1.2 mycroft return scsi_scsi_cmd(sc_link, (struct scsi_generic *) &scsi_cmd,
212 1.2 mycroft sizeof(scsi_cmd), 0, 0, 2, 5000, NULL, flags);
213 1.1 mycroft }
214 1.1 mycroft
215 1.1 mycroft /*
216 1.1 mycroft * Get scsi driver to send a "start up" command
217 1.1 mycroft */
218 1.2 mycroft int
219 1.1 mycroft scsi_start_unit(sc_link, flags)
220 1.1 mycroft struct scsi_link *sc_link;
221 1.1 mycroft u_int32 flags;
222 1.1 mycroft {
223 1.1 mycroft struct scsi_start_stop scsi_cmd;
224 1.1 mycroft
225 1.1 mycroft bzero(&scsi_cmd, sizeof(scsi_cmd));
226 1.1 mycroft scsi_cmd.op_code = START_STOP;
227 1.1 mycroft scsi_cmd.how = SSS_START;
228 1.1 mycroft
229 1.2 mycroft return scsi_scsi_cmd(sc_link, (struct scsi_generic *) &scsi_cmd,
230 1.2 mycroft sizeof(scsi_cmd), 0, 0, 2, 2000, NULL, flags);
231 1.1 mycroft }
232 1.1 mycroft
233 1.1 mycroft /*
234 1.1 mycroft * This routine is called by the scsi interrupt when the transfer is complete.
235 1.1 mycroft */
236 1.1 mycroft void
237 1.1 mycroft scsi_done(xs)
238 1.1 mycroft struct scsi_xfer *xs;
239 1.1 mycroft {
240 1.1 mycroft struct scsi_link *sc_link = xs->sc_link;
241 1.1 mycroft struct buf *bp = xs->bp;
242 1.2 mycroft int retval;
243 1.1 mycroft
244 1.1 mycroft SC_DEBUG(sc_link, SDEV_DB2, ("scsi_done\n"));
245 1.1 mycroft #ifdef SCSIDEBUG
246 1.1 mycroft if (sc_link->flags & SDEV_DB1)
247 1.1 mycroft show_scsi_cmd(xs);
248 1.1 mycroft #endif /*SCSIDEBUG */
249 1.1 mycroft /*
250 1.1 mycroft * If it's a user level request, bypass all usual completion processing,
251 1.1 mycroft * let the user work it out.. We take reponsibility for freeing the
252 1.1 mycroft * xs when the user returns. (and restarting the device's queue).
253 1.1 mycroft */
254 1.1 mycroft if (xs->flags & SCSI_USER) {
255 1.1 mycroft biodone(xs->bp);
256 1.1 mycroft #ifdef NOTNOW
257 1.1 mycroft SC_DEBUG(sc_link, SDEV_DB3, ("calling user done()\n"));
258 1.1 mycroft scsi_user_done(xs); /* to take a copy of the sense etc. */
259 1.1 mycroft SC_DEBUG(sc_link, SDEV_DB3, ("returned from user done()\n "));
260 1.1 mycroft #endif
261 1.1 mycroft free_xs(xs, sc_link, SCSI_NOSLEEP); /* restarts queue too */
262 1.1 mycroft SC_DEBUG(sc_link, SDEV_DB3, ("returning to adapter\n"));
263 1.1 mycroft return;
264 1.1 mycroft }
265 1.1 mycroft /*
266 1.1 mycroft * If the device has it's own done routine, call it first.
267 1.1 mycroft * If it returns a legit error value, return that, otherwise
268 1.1 mycroft * it wants us to continue with normal processing.
269 1.1 mycroft */
270 1.1 mycroft
271 1.1 mycroft if (sc_link->device->done) {
272 1.1 mycroft SC_DEBUG(sc_link, SDEV_DB2, ("calling private done()\n"));
273 1.1 mycroft retval = (*sc_link->device->done) (xs);
274 1.1 mycroft if (retval == -1) {
275 1.1 mycroft free_xs(xs, sc_link, SCSI_NOSLEEP); /*XXX */
276 1.1 mycroft return; /* it did it all, finish up */
277 1.1 mycroft }
278 1.2 mycroft if (retval == -2)
279 1.1 mycroft return; /* it did it all, finish up */
280 1.1 mycroft SC_DEBUG(sc_link, SDEV_DB3, ("continuing with generic done()\n"));
281 1.1 mycroft }
282 1.1 mycroft if ((bp = xs->bp) == NULL) {
283 1.1 mycroft /*
284 1.1 mycroft * if it's a normal upper level request, then ask
285 1.1 mycroft * the upper level code to handle error checking
286 1.1 mycroft * rather than doing it here at interrupt time
287 1.1 mycroft */
288 1.1 mycroft wakeup(xs);
289 1.1 mycroft return;
290 1.1 mycroft }
291 1.1 mycroft /*
292 1.1 mycroft * Go and handle errors now.
293 1.1 mycroft * If it returns -1 then we should RETRY
294 1.1 mycroft */
295 1.1 mycroft if ((retval = sc_err1(xs)) == -1) {
296 1.1 mycroft if ((*(sc_link->adapter->scsi_cmd)) (xs)
297 1.2 mycroft == SUCCESSFULLY_QUEUED) /* don't wake the job, ok? */
298 1.1 mycroft return;
299 1.1 mycroft xs->flags |= ITSDONE;
300 1.1 mycroft }
301 1.1 mycroft free_xs(xs, sc_link, SCSI_NOSLEEP); /* does a start if needed */
302 1.1 mycroft biodone(bp);
303 1.1 mycroft }
304 1.1 mycroft
305 1.1 mycroft /*
306 1.1 mycroft * ask the scsi driver to perform a command for us.
307 1.1 mycroft * tell it where to read/write the data, and how
308 1.1 mycroft * long the data is supposed to be. If we have a buf
309 1.1 mycroft * to associate with the transfer, we need that too.
310 1.1 mycroft */
311 1.2 mycroft int
312 1.1 mycroft scsi_scsi_cmd(sc_link, scsi_cmd, cmdlen, data_addr, datalen,
313 1.1 mycroft retries, timeout, bp, flags)
314 1.1 mycroft struct scsi_link *sc_link;
315 1.1 mycroft struct scsi_generic *scsi_cmd;
316 1.1 mycroft u_int32 cmdlen;
317 1.1 mycroft u_char *data_addr;
318 1.1 mycroft u_int32 datalen;
319 1.1 mycroft u_int32 retries;
320 1.1 mycroft u_int32 timeout;
321 1.1 mycroft struct buf *bp;
322 1.1 mycroft u_int32 flags;
323 1.1 mycroft {
324 1.1 mycroft struct scsi_xfer *xs;
325 1.2 mycroft int retval;
326 1.1 mycroft u_int32 s;
327 1.1 mycroft
328 1.2 mycroft if (bp)
329 1.2 mycroft flags |= SCSI_NOSLEEP;
330 1.1 mycroft SC_DEBUG(sc_link, SDEV_DB2, ("scsi_cmd\n"));
331 1.1 mycroft
332 1.1 mycroft xs = get_xs(sc_link, flags); /* should wait unless booting */
333 1.2 mycroft if (!xs)
334 1.2 mycroft return (ENOMEM);
335 1.1 mycroft /*
336 1.1 mycroft * Fill out the scsi_xfer structure. We don't know whose context
337 1.1 mycroft * the cmd is in, so copy it.
338 1.1 mycroft */
339 1.1 mycroft bcopy(scsi_cmd, &(xs->cmdstore), cmdlen);
340 1.1 mycroft xs->flags = INUSE | flags;
341 1.1 mycroft xs->sc_link = sc_link;
342 1.1 mycroft xs->retries = retries;
343 1.1 mycroft xs->timeout = timeout;
344 1.1 mycroft xs->cmd = &xs->cmdstore;
345 1.1 mycroft xs->cmdlen = cmdlen;
346 1.1 mycroft xs->data = data_addr;
347 1.1 mycroft xs->datalen = datalen;
348 1.1 mycroft xs->resid = datalen;
349 1.1 mycroft xs->bp = bp;
350 1.1 mycroft /*XXX*/ /*use constant not magic number */
351 1.1 mycroft if (datalen && ((caddr_t) data_addr < (caddr_t) 0xfe000000)) {
352 1.1 mycroft if (bp) {
353 1.1 mycroft printf("Data buffered space not in kernel context\n");
354 1.1 mycroft #ifdef SCSIDEBUG
355 1.1 mycroft show_scsi_cmd(xs);
356 1.1 mycroft #endif /* SCSIDEBUG */
357 1.1 mycroft retval = EFAULT;
358 1.1 mycroft goto bad;
359 1.1 mycroft }
360 1.1 mycroft xs->data = malloc(datalen, M_TEMP, M_WAITOK);
361 1.1 mycroft /* I think waiting is ok *//*XXX */
362 1.1 mycroft switch (flags & (SCSI_DATA_IN | SCSI_DATA_OUT)) {
363 1.1 mycroft case 0:
364 1.1 mycroft printf("No direction flags, assuming both\n");
365 1.1 mycroft #ifdef SCSIDEBUG
366 1.1 mycroft show_scsi_cmd(xs);
367 1.1 mycroft #endif /* SCSIDEBUG */
368 1.1 mycroft case SCSI_DATA_IN | SCSI_DATA_OUT: /* weird */
369 1.1 mycroft case SCSI_DATA_OUT:
370 1.1 mycroft bcopy(data_addr, xs->data, datalen);
371 1.1 mycroft break;
372 1.1 mycroft case SCSI_DATA_IN:
373 1.1 mycroft bzero(xs->data, datalen);
374 1.1 mycroft }
375 1.1 mycroft }
376 1.1 mycroft retry:
377 1.1 mycroft xs->error = XS_NOERROR;
378 1.1 mycroft #ifdef PARANOID
379 1.2 mycroft if (datalen && ((caddr_t) xs->data < (caddr_t) KERNBASE))
380 1.1 mycroft printf("It's still wrong!\n");
381 1.1 mycroft #endif /*PARANOID*/
382 1.1 mycroft #ifdef SCSIDEBUG
383 1.2 mycroft if (sc_link->flags & SDEV_DB3)
384 1.2 mycroft show_scsi_xs(xs);
385 1.1 mycroft #endif /* SCSIDEBUG */
386 1.1 mycroft /*
387 1.1 mycroft * Do the transfer. If we are polling we will return:
388 1.1 mycroft * COMPLETE, Was poll, and scsi_done has been called
389 1.1 mycroft * TRY_AGAIN_LATER, Adapter short resources, try again
390 1.1 mycroft *
391 1.1 mycroft * if under full steam (interrupts) it will return:
392 1.1 mycroft * SUCCESSFULLY_QUEUED, will do a wakeup when complete
393 1.1 mycroft * TRY_AGAIN_LATER, (as for polling)
394 1.1 mycroft * After the wakeup, we must still check if it succeeded
395 1.1 mycroft *
396 1.1 mycroft * If we have a bp however, all the error proccessing
397 1.1 mycroft * and the buffer code both expect us to return straight
398 1.1 mycroft * to them, so as soon as the command is queued, return
399 1.1 mycroft */
400 1.1 mycroft
401 1.1 mycroft retval = (*(sc_link->adapter->scsi_cmd)) (xs);
402 1.1 mycroft
403 1.1 mycroft switch (retval) {
404 1.1 mycroft case SUCCESSFULLY_QUEUED:
405 1.1 mycroft if (bp)
406 1.1 mycroft return retval; /* will sleep (or not) elsewhere */
407 1.1 mycroft s = splbio();
408 1.1 mycroft while (!(xs->flags & ITSDONE))
409 1.1 mycroft sleep(xs, PRIBIO + 1);
410 1.1 mycroft splx(s);
411 1.1 mycroft /* fall through to check success of completed command */
412 1.1 mycroft case COMPLETE: /* Polling command completed ok */
413 1.1 mycroft /*XXX*/ case HAD_ERROR: /* Polling command completed with error */
414 1.1 mycroft SC_DEBUG(sc_link, SDEV_DB3, ("back in cmd()\n"));
415 1.1 mycroft if ((retval = sc_err1(xs)) == -1)
416 1.1 mycroft goto retry;
417 1.1 mycroft break;
418 1.1 mycroft
419 1.1 mycroft case TRY_AGAIN_LATER: /* adapter resource shortage */
420 1.1 mycroft SC_DEBUG(sc_link, SDEV_DB3, ("will try again \n"));
421 1.1 mycroft /* should sleep 1 sec here */
422 1.1 mycroft if (xs->retries--) {
423 1.1 mycroft xs->flags &= ~ITSDONE;
424 1.1 mycroft goto retry;
425 1.1 mycroft }
426 1.1 mycroft default:
427 1.1 mycroft retval = EIO;
428 1.1 mycroft }
429 1.1 mycroft /*
430 1.1 mycroft * If we had to copy the data out of the user's context,
431 1.1 mycroft * then do the other half (copy it back or whatever)
432 1.1 mycroft * and free the memory buffer
433 1.1 mycroft */
434 1.1 mycroft if (datalen && (xs->data != data_addr)) {
435 1.1 mycroft switch (flags & (SCSI_DATA_IN | SCSI_DATA_OUT)) {
436 1.1 mycroft case 0:
437 1.1 mycroft case SCSI_DATA_IN | SCSI_DATA_OUT: /* weird */
438 1.1 mycroft case SCSI_DATA_IN:
439 1.1 mycroft bcopy(xs->data, data_addr, datalen);
440 1.1 mycroft break;
441 1.1 mycroft }
442 1.1 mycroft free(xs->data, M_TEMP);
443 1.1 mycroft }
444 1.1 mycroft /*
445 1.1 mycroft * we have finished with the xfer stuct, free it and
446 1.1 mycroft * check if anyone else needs to be started up.
447 1.1 mycroft */
448 1.1 mycroft bad:
449 1.1 mycroft free_xs(xs, sc_link, flags); /* includes the 'start' op */
450 1.1 mycroft if (bp && retval) {
451 1.1 mycroft bp->b_error = retval;
452 1.1 mycroft bp->b_flags |= B_ERROR;
453 1.1 mycroft biodone(bp);
454 1.1 mycroft }
455 1.1 mycroft return (retval);
456 1.1 mycroft }
457 1.1 mycroft
458 1.2 mycroft int
459 1.1 mycroft sc_err1(xs)
460 1.1 mycroft struct scsi_xfer *xs;
461 1.1 mycroft {
462 1.1 mycroft struct buf *bp = xs->bp;
463 1.2 mycroft int retval;
464 1.1 mycroft
465 1.1 mycroft SC_DEBUG(xs->sc_link, SDEV_DB3, ("sc_err1,err = 0x%x \n", xs->error));
466 1.1 mycroft /*
467 1.1 mycroft * If it has a buf, we might be working with
468 1.1 mycroft * a request from the buffer cache or some other
469 1.1 mycroft * piece of code that requires us to process
470 1.1 mycroft * errors at inetrrupt time. We have probably
471 1.1 mycroft * been called by scsi_done()
472 1.1 mycroft */
473 1.1 mycroft switch (xs->error) {
474 1.1 mycroft case XS_NOERROR: /* nearly always hit this one */
475 1.2 mycroft retval = 0;
476 1.1 mycroft if (bp) {
477 1.1 mycroft bp->b_error = 0;
478 1.1 mycroft bp->b_resid = 0;
479 1.1 mycroft }
480 1.1 mycroft break;
481 1.1 mycroft
482 1.1 mycroft case XS_SENSE:
483 1.1 mycroft if (bp) {
484 1.1 mycroft bp->b_error = 0;
485 1.1 mycroft bp->b_resid = 0;
486 1.1 mycroft if (retval = (scsi_interpret_sense(xs))) {
487 1.1 mycroft bp->b_flags |= B_ERROR;
488 1.1 mycroft bp->b_error = retval;
489 1.1 mycroft bp->b_resid = bp->b_bcount;
490 1.1 mycroft }
491 1.1 mycroft SC_DEBUG(xs->sc_link, SDEV_DB3,
492 1.1 mycroft ("scsi_interpret_sense (bp) returned %d\n", retval));
493 1.1 mycroft } else {
494 1.1 mycroft retval = (scsi_interpret_sense(xs));
495 1.1 mycroft SC_DEBUG(xs->sc_link, SDEV_DB3,
496 1.1 mycroft ("scsi_interpret_sense (no bp) returned %d\n", retval));
497 1.1 mycroft }
498 1.1 mycroft break;
499 1.1 mycroft
500 1.1 mycroft case XS_BUSY:
501 1.1 mycroft /*should somehow arange for a 1 sec delay here (how?) */
502 1.1 mycroft case XS_TIMEOUT:
503 1.1 mycroft /*
504 1.1 mycroft * If we can, resubmit it to the adapter.
505 1.1 mycroft */
506 1.1 mycroft if (xs->retries--) {
507 1.1 mycroft xs->error = XS_NOERROR;
508 1.1 mycroft xs->flags &= ~ITSDONE;
509 1.1 mycroft goto retry;
510 1.1 mycroft }
511 1.1 mycroft /* fall through */
512 1.1 mycroft case XS_DRIVER_STUFFUP:
513 1.1 mycroft if (bp) {
514 1.1 mycroft bp->b_flags |= B_ERROR;
515 1.1 mycroft bp->b_error = EIO;
516 1.1 mycroft }
517 1.1 mycroft retval = EIO;
518 1.1 mycroft break;
519 1.1 mycroft default:
520 1.1 mycroft retval = EIO;
521 1.1 mycroft sc_print_addr(xs->sc_link);
522 1.1 mycroft printf("unknown error category from scsi driver\n");
523 1.1 mycroft }
524 1.1 mycroft return retval;
525 1.1 mycroft retry:
526 1.1 mycroft return (-1);
527 1.1 mycroft }
528 1.1 mycroft
529 1.1 mycroft /*
530 1.1 mycroft * Look at the returned sense and act on the error, determining
531 1.1 mycroft * the unix error number to pass back. (0 = report no error)
532 1.1 mycroft *
533 1.1 mycroft * THIS IS THE DEFAULT ERROR HANDLER
534 1.1 mycroft */
535 1.2 mycroft int
536 1.1 mycroft scsi_interpret_sense(xs)
537 1.1 mycroft struct scsi_xfer *xs;
538 1.1 mycroft {
539 1.1 mycroft struct scsi_sense_data *sense;
540 1.1 mycroft struct scsi_link *sc_link = xs->sc_link;
541 1.1 mycroft u_int32 key;
542 1.1 mycroft u_int32 silent;
543 1.1 mycroft u_int32 info;
544 1.2 mycroft int error;
545 1.1 mycroft
546 1.1 mycroft static char *error_mes[] =
547 1.1 mycroft {"soft error (corrected)",
548 1.1 mycroft "not ready", "medium error",
549 1.1 mycroft "non-media hardware failure", "illegal request",
550 1.1 mycroft "unit attention", "readonly device",
551 1.1 mycroft "no data found", "vendor unique",
552 1.1 mycroft "copy aborted", "command aborted",
553 1.1 mycroft "search returned equal", "volume overflow",
554 1.1 mycroft "verify miscompare", "unknown error key"
555 1.1 mycroft };
556 1.1 mycroft
557 1.1 mycroft /*
558 1.1 mycroft * If the flags say errs are ok, then always return ok.
559 1.1 mycroft */
560 1.1 mycroft if (xs->flags & SCSI_ERR_OK)
561 1.2 mycroft return (0);
562 1.1 mycroft
563 1.1 mycroft sense = &(xs->sense);
564 1.1 mycroft #ifdef SCSIDEBUG
565 1.1 mycroft if (sc_link->flags & SDEV_DB1) {
566 1.1 mycroft u_int32 count = 0;
567 1.1 mycroft printf("code%x valid%x ",
568 1.1 mycroft sense->error_code & SSD_ERRCODE,
569 1.1 mycroft sense->error_code & SSD_ERRCODE_VALID ? 1 : 0);
570 1.1 mycroft printf("seg%x key%x ili%x eom%x fmark%x\n",
571 1.1 mycroft sense->ext.extended.segment,
572 1.1 mycroft sense->ext.extended.flags & SSD_KEY,
573 1.1 mycroft sense->ext.extended.flags & SSD_ILI ? 1 : 0,
574 1.1 mycroft sense->ext.extended.flags & SSD_EOM ? 1 : 0,
575 1.1 mycroft sense->ext.extended.flags & SSD_FILEMARK ? 1 : 0);
576 1.1 mycroft printf("info: %x %x %x %x followed by %d extra bytes\n",
577 1.1 mycroft sense->ext.extended.info[0],
578 1.1 mycroft sense->ext.extended.info[1],
579 1.1 mycroft sense->ext.extended.info[2],
580 1.1 mycroft sense->ext.extended.info[3],
581 1.1 mycroft sense->ext.extended.extra_len);
582 1.1 mycroft printf("extra: ");
583 1.2 mycroft while (count < sense->ext.extended.extra_len)
584 1.1 mycroft printf("%x ", sense->ext.extended.extra_bytes[count++]);
585 1.1 mycroft printf("\n");
586 1.1 mycroft }
587 1.1 mycroft #endif /*SCSIDEBUG */
588 1.1 mycroft /*
589 1.1 mycroft * If the device has it's own error handler, call it first.
590 1.1 mycroft * If it returns a legit error value, return that, otherwise
591 1.1 mycroft * it wants us to continue with normal error processing.
592 1.1 mycroft */
593 1.1 mycroft if (sc_link->device->err_handler) {
594 1.1 mycroft SC_DEBUG(sc_link, SDEV_DB2, ("calling private err_handler()\n"));
595 1.2 mycroft error = (*sc_link->device->err_handler) (xs);
596 1.2 mycroft if (error != -1)
597 1.2 mycroft return error; /* error >= 0 better ? */
598 1.1 mycroft }
599 1.1 mycroft /* otherwise use the default */
600 1.1 mycroft silent = (xs->flags & SCSI_SILENT);
601 1.1 mycroft switch (sense->error_code & SSD_ERRCODE) {
602 1.1 mycroft /*
603 1.1 mycroft * If it's code 70, use the extended stuff and interpret the key
604 1.1 mycroft */
605 1.1 mycroft case 0x71: /* delayed error */
606 1.1 mycroft sc_print_addr(sc_link);
607 1.1 mycroft key = sense->ext.extended.flags & SSD_KEY;
608 1.1 mycroft printf(" DELAYED ERROR, key = 0x%x\n", key);
609 1.1 mycroft case 0x70:
610 1.2 mycroft if (sense->error_code & SSD_ERRCODE_VALID)
611 1.1 mycroft info = ntohl(*((long *) sense->ext.extended.info));
612 1.2 mycroft else
613 1.1 mycroft info = 0;
614 1.1 mycroft key = sense->ext.extended.flags & SSD_KEY;
615 1.1 mycroft
616 1.1 mycroft if (key && !silent) {
617 1.1 mycroft sc_print_addr(sc_link);
618 1.1 mycroft printf("%s", error_mes[key - 1]);
619 1.1 mycroft if (sense->error_code & SSD_ERRCODE_VALID) {
620 1.1 mycroft switch (key) {
621 1.1 mycroft case 0x2: /* NOT READY */
622 1.1 mycroft case 0x5: /* ILLEGAL REQUEST */
623 1.1 mycroft case 0x6: /* UNIT ATTENTION */
624 1.1 mycroft case 0x7: /* DATA PROTECT */
625 1.1 mycroft break;
626 1.1 mycroft case 0x8: /* BLANK CHECK */
627 1.1 mycroft printf(", requested size: %d (decimal)",
628 1.1 mycroft info);
629 1.1 mycroft break;
630 1.1 mycroft default:
631 1.1 mycroft printf(", info = %d (decimal)", info);
632 1.1 mycroft }
633 1.1 mycroft }
634 1.1 mycroft printf("\n");
635 1.1 mycroft }
636 1.1 mycroft switch (key) {
637 1.1 mycroft case 0x0: /* NO SENSE */
638 1.1 mycroft case 0x1: /* RECOVERED ERROR */
639 1.1 mycroft if (xs->resid == xs->datalen)
640 1.1 mycroft xs->resid = 0; /* not short read */
641 1.1 mycroft case 0xc: /* EQUAL */
642 1.2 mycroft return (0);
643 1.1 mycroft case 0x2: /* NOT READY */
644 1.1 mycroft sc_link->flags &= ~SDEV_MEDIA_LOADED;
645 1.1 mycroft return (EBUSY);
646 1.1 mycroft case 0x5: /* ILLEGAL REQUEST */
647 1.1 mycroft return (EINVAL);
648 1.1 mycroft case 0x6: /* UNIT ATTENTION */
649 1.1 mycroft sc_link->flags &= ~SDEV_MEDIA_LOADED;
650 1.2 mycroft if (sc_link->flags & SDEV_OPEN)
651 1.1 mycroft return (EIO);
652 1.2 mycroft else
653 1.1 mycroft return 0;
654 1.1 mycroft case 0x7: /* DATA PROTECT */
655 1.1 mycroft return (EACCES);
656 1.1 mycroft case 0xd: /* VOLUME OVERFLOW */
657 1.1 mycroft return (ENOSPC);
658 1.1 mycroft case 0x8: /* BLANK CHECK */
659 1.2 mycroft return (0);
660 1.1 mycroft default:
661 1.1 mycroft return (EIO);
662 1.1 mycroft }
663 1.1 mycroft /*
664 1.1 mycroft * Not code 70, just report it
665 1.1 mycroft */
666 1.1 mycroft default:
667 1.1 mycroft if (!silent) {
668 1.1 mycroft sc_print_addr(sc_link);
669 1.1 mycroft printf("error code %d",
670 1.1 mycroft sense->error_code & SSD_ERRCODE);
671 1.1 mycroft if (sense->error_code & SSD_ERRCODE_VALID) {
672 1.1 mycroft printf(" at block no. %d (decimal)",
673 1.1 mycroft (sense->ext.unextended.blockhi << 16) +
674 1.1 mycroft (sense->ext.unextended.blockmed << 8) +
675 1.1 mycroft (sense->ext.unextended.blocklow));
676 1.1 mycroft }
677 1.1 mycroft printf("\n");
678 1.1 mycroft }
679 1.1 mycroft return (EIO);
680 1.1 mycroft }
681 1.1 mycroft }
682 1.1 mycroft
683 1.1 mycroft /*
684 1.1 mycroft * Utility routines often used in SCSI stuff
685 1.1 mycroft */
686 1.1 mycroft
687 1.1 mycroft /*
688 1.1 mycroft * convert a physical address to 3 bytes,
689 1.1 mycroft * MSB at the lowest address,
690 1.1 mycroft * LSB at the highest.
691 1.1 mycroft */
692 1.1 mycroft void
693 1.1 mycroft lto3b(val, bytes)
694 1.1 mycroft int val;
695 1.1 mycroft u_char *bytes;
696 1.1 mycroft {
697 1.1 mycroft *bytes++ = (val & 0xff0000) >> 16;
698 1.1 mycroft *bytes++ = (val & 0xff00) >> 8;
699 1.1 mycroft *bytes = val & 0xff;
700 1.1 mycroft }
701 1.1 mycroft
702 1.1 mycroft /*
703 1.1 mycroft * The reverse of lto3b
704 1.1 mycroft */
705 1.1 mycroft int
706 1.1 mycroft _3btol(bytes)
707 1.1 mycroft u_char *bytes;
708 1.1 mycroft {
709 1.1 mycroft u_int32 rc;
710 1.1 mycroft rc = (*bytes++ << 16);
711 1.1 mycroft rc += (*bytes++ << 8);
712 1.1 mycroft rc += *bytes;
713 1.1 mycroft return ((int) rc);
714 1.1 mycroft }
715 1.1 mycroft
716 1.1 mycroft /*
717 1.1 mycroft * Print out the scsi_link structure's address info.
718 1.1 mycroft */
719 1.1 mycroft void
720 1.1 mycroft sc_print_addr(sc_link)
721 1.1 mycroft struct scsi_link *sc_link;
722 1.1 mycroft {
723 1.1 mycroft
724 1.1 mycroft printf("%s%d(%s:%d:%d): ",
725 1.1 mycroft sc_link->device->name, sc_link->dev_unit,
726 1.1 mycroft ((struct device *)sc_link->adapter_softc)->dv_xname,
727 1.1 mycroft sc_link->target, sc_link->lun);
728 1.1 mycroft }
729 1.1 mycroft
730 1.1 mycroft #ifdef SCSIDEBUG
731 1.1 mycroft /*
732 1.1 mycroft * Given a scsi_xfer, dump the request, in all it's glory
733 1.1 mycroft */
734 1.1 mycroft void
735 1.1 mycroft show_scsi_xs(xs)
736 1.1 mycroft struct scsi_xfer *xs;
737 1.1 mycroft {
738 1.1 mycroft printf("xs(0x%x): ", xs);
739 1.1 mycroft printf("flg(0x%x)", xs->flags);
740 1.1 mycroft printf("sc_link(0x%x)", xs->sc_link);
741 1.1 mycroft printf("retr(0x%x)", xs->retries);
742 1.1 mycroft printf("timo(0x%x)", xs->timeout);
743 1.1 mycroft printf("cmd(0x%x)", xs->cmd);
744 1.1 mycroft printf("len(0x%x)", xs->cmdlen);
745 1.1 mycroft printf("data(0x%x)", xs->data);
746 1.1 mycroft printf("len(0x%x)", xs->datalen);
747 1.1 mycroft printf("res(0x%x)", xs->resid);
748 1.1 mycroft printf("err(0x%x)", xs->error);
749 1.1 mycroft printf("bp(0x%x)", xs->bp);
750 1.1 mycroft show_scsi_cmd(xs);
751 1.1 mycroft }
752 1.1 mycroft
753 1.1 mycroft void
754 1.1 mycroft show_scsi_cmd(struct scsi_xfer *xs)
755 1.1 mycroft {
756 1.1 mycroft u_char *b = (u_char *) xs->cmd;
757 1.1 mycroft int i = 0;
758 1.1 mycroft
759 1.1 mycroft sc_print_addr(xs->sc_link);
760 1.1 mycroft printf("command: ");
761 1.1 mycroft
762 1.1 mycroft if (!(xs->flags & SCSI_RESET)) {
763 1.1 mycroft while (i < xs->cmdlen) {
764 1.1 mycroft if (i)
765 1.1 mycroft printf(",");
766 1.1 mycroft printf("%x", b[i++]);
767 1.1 mycroft }
768 1.1 mycroft printf("-[%d bytes]\n", xs->datalen);
769 1.1 mycroft if (xs->datalen)
770 1.1 mycroft show_mem(xs->data, min(64, xs->datalen));
771 1.2 mycroft } else
772 1.1 mycroft printf("-RESET-\n");
773 1.1 mycroft }
774 1.1 mycroft
775 1.1 mycroft void
776 1.1 mycroft show_mem(address, num)
777 1.1 mycroft unsigned char *address;
778 1.1 mycroft u_int32 num;
779 1.1 mycroft {
780 1.1 mycroft u_int32 x, y;
781 1.1 mycroft printf("------------------------------");
782 1.1 mycroft for (y = 0; y < num; y += 1) {
783 1.1 mycroft if (!(y % 16))
784 1.1 mycroft printf("\n%03d: ", y);
785 1.1 mycroft printf("%02x ", *address++);
786 1.1 mycroft }
787 1.1 mycroft printf("\n------------------------------\n");
788 1.1 mycroft }
789 1.1 mycroft #endif /*SCSIDEBUG */
790