iopsp.c revision 1.2 1 /* $NetBSD: iopsp.c,v 1.2 2000/11/09 12:51:36 ad Exp $ */
2
3 /*-
4 * Copyright (c) 2000 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Andrew Doran.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * This product includes software developed by the NetBSD
21 * Foundation, Inc. and its contributors.
22 * 4. Neither the name of The NetBSD Foundation nor the names of its
23 * contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 * POSSIBILITY OF SUCH DAMAGE.
37 */
38
39 /*
40 * Raw SCSI/FC-AL device support for I2O. I2O presents SCSI devices
41 * individually; we group them by controller port.
42 */
43
44 #include "opt_i2o.h"
45
46 #include <sys/param.h>
47 #include <sys/systm.h>
48 #include <sys/kernel.h>
49 #include <sys/device.h>
50 #include <sys/queue.h>
51 #include <sys/proc.h>
52 #include <sys/buf.h>
53 #include <sys/endian.h>
54 #include <sys/malloc.h>
55 #include <sys/scsiio.h>
56
57 #include <machine/bswap.h>
58 #include <machine/bus.h>
59
60 #include <dev/scsipi/scsi_all.h>
61 #include <dev/scsipi/scsi_disk.h>
62 #include <dev/scsipi/scsipi_all.h>
63 #include <dev/scsipi/scsiconf.h>
64
65 #include <dev/i2o/i2o.h>
66 #include <dev/i2o/iopreg.h>
67 #include <dev/i2o/iopvar.h>
68 #include <dev/i2o/iopspvar.h>
69
70 static void iopsp_attach(struct device *, struct device *, void *);
71 static void iopsp_intr(struct device *, struct iop_msg *, void *);
72 static int iopsp_ioctl(struct scsipi_link *, u_long, caddr_t, int,
73 struct proc *);
74 static int iopsp_match(struct device *, struct cfdata *, void *);
75 static void iopsp_minphys(struct buf *);
76 static int iopsp_rescan(struct iopsp_softc *);
77 static void iopsp_scan(struct iopsp_softc *);
78 static int iopsp_scsi_abort(struct iopsp_softc *, struct iop_msg *);
79 static int iopsp_scsi_cmd(struct scsipi_xfer *);
80
81 static struct scsipi_device iopsp_dev = {
82 NULL, /* Use default error handler */
83 NULL, /* have a queue, served by this */
84 NULL, /* have no async handler */
85 NULL, /* Use default 'done' routine */
86 };
87
88 struct cfattach iopsp_ca = {
89 sizeof(struct iopsp_softc), iopsp_match, iopsp_attach
90 };
91
92 /*
93 * Match SCSI and fibre channel ports.
94 */
95 static int
96 iopsp_match(struct device *parent, struct cfdata *match, void *aux)
97 {
98 struct iop_attach_args *ia;
99 struct {
100 struct i2o_param_op_results pr;
101 struct i2o_param_read_results prr;
102 struct i2o_param_hba_ctlr_info ci;
103 } __attribute__ ((__packed__)) param;
104
105 ia = aux;
106
107 if (ia->ia_class != I2O_CLASS_BUS_ADAPTER_PORT)
108 return (0);
109
110 if (iop_params_get((struct iop_softc *)parent, ia->ia_tid,
111 I2O_PARAM_HBA_CTLR_INFO, ¶m, sizeof(param)) != 0)
112 return (0);
113
114 /* XXX */
115 return (param.ci.bustype == I2O_HBA_BUS_SCSI ||
116 param.ci.bustype == I2O_HBA_BUS_FCA);
117 }
118
119 /*
120 * Attach a supported device.
121 */
122 static void
123 iopsp_attach(struct device *parent, struct device *self, void *aux)
124 {
125 struct iop_attach_args *ia;
126 struct iopsp_softc *sc;
127 struct scsipi_link *sc_link;
128 struct iop_softc *iop;
129 struct {
130 struct i2o_param_op_results pr;
131 struct i2o_param_read_results prr;
132 union {
133 struct i2o_param_device_identity di;
134 struct i2o_param_hba_ctlr_info ci;
135 struct i2o_param_hba_scsi_ctlr_info sci;
136 } p;
137 } __attribute__ ((__packed__)) param;
138 char ident[64];
139 int fcal;
140 #ifdef I2OVERBOSE
141 int size;
142 #endif
143
144 ia = (struct iop_attach_args *)aux;
145 sc = (struct iopsp_softc *)self;
146 iop = (struct iop_softc *)parent;
147 sc->sc_tid = ia->ia_tid;
148
149 /* Register us as an initiator. */
150 sc->sc_ii.ii_dv = self;
151 sc->sc_ii.ii_intr = iopsp_intr;
152 sc->sc_ii.ii_flags = 0;
153 if (iop_initiator_register(iop, &sc->sc_ii) != 0) {
154 printf("%s: unable to register as an initiator",
155 sc->sc_dv.dv_xname);
156 return;
157 }
158
159 if (iop_params_get(iop, ia->ia_tid, I2O_PARAM_HBA_CTLR_INFO, ¶m,
160 sizeof(param)) != 0) {
161 printf("%s: unable to retrieve parameters\n",
162 sc->sc_dv.dv_xname);
163 goto bad;
164 }
165
166 fcal = (param.p.ci.bustype == I2O_HBA_BUS_FCA); /* XXX */
167
168 /*
169 * Say what the device is. If we can find out what the controling
170 * device is, say what that is too.
171 */
172 printf(": %s port", fcal ? "FC-AL" : "SCSI");
173 if (iop_params_get(iop, ia->ia_tid, I2O_PARAM_DEVICE_IDENTITY, ¶m,
174 sizeof(param)) == 0) {
175 iop_strvis(param.p.di.vendorinfo,
176 sizeof(param.p.di.vendorinfo), ident, sizeof(ident));
177 printf(" <%s, ", ident);
178 iop_strvis(param.p.di.productinfo,
179 sizeof(param.p.di.productinfo), ident, sizeof(ident));
180 printf("%s, ", ident);
181 iop_strvis(param.p.di.revlevel,
182 sizeof(param.p.di.revlevel), ident, sizeof(ident));
183 printf("%s> ", ident);
184 }
185 printf("\n");
186
187 if (iop_params_get(iop, ia->ia_tid, I2O_PARAM_HBA_SCSI_CTLR_INFO,
188 ¶m, sizeof(param)) != 0) {
189 printf("%s: unable to retrieve controller parameters\n",
190 sc->sc_dv.dv_xname);
191 goto bad;
192 }
193
194 #ifdef I2OVERBOSE
195 printf("%s: %d-bit, max sync rate %dMHz, initiator ID %d\n",
196 sc->sc_dv.dv_xname, param.p.sci.maxdatawidth,
197 (u_int32_t)le64toh(param.p.sci.maxsyncrate) / 1000,
198 le32toh(param.p.sci.initiatorid));
199 #endif
200
201 sc->sc_adapter.scsipi_cmd = iopsp_scsi_cmd;
202 sc->sc_adapter.scsipi_minphys = iopsp_minphys;
203 sc->sc_adapter.scsipi_ioctl = iopsp_ioctl;
204
205 sc_link = &sc->sc_link;
206 sc_link->type = BUS_SCSI;
207 sc_link->device = &iopsp_dev;
208 sc_link->adapter = &sc->sc_adapter;
209 sc_link->adapter_softc = sc;
210 sc_link->scsipi_scsi.channel = 0;
211 sc_link->scsipi_scsi.adapter_target = le32toh(param.p.sci.initiatorid);
212 sc_link->scsipi_scsi.max_target =
213 fcal ? IOPSP_MAX_FCAL_TARGET : param.p.sci.maxdatawidth - 1;
214 sc_link->scsipi_scsi.max_lun = IOPSP_MAX_LUN;
215 sc_link->openings = iop->sc_maxqueuecnt; /* XXX */
216
217 #ifdef I2OVERBOSE
218 /*
219 * Allocate the target map. Currently used for informational
220 * purposes only.
221 */
222 size = (sc_link->scsipi_scsi.max_target + 1) *
223 sizeof(struct iopsp_target);
224 sc->sc_targetmap = malloc(size, M_DEVBUF, M_NOWAIT);
225 memset(sc->sc_targetmap, 0, size);
226 #endif
227
228 /* Build the two maps, and attach to scsipi. */
229 iopsp_scan(sc);
230 config_found(self, sc_link, scsiprint);
231 return;
232
233 bad:
234 iop_initiator_unregister(iop, &sc->sc_ii);
235 }
236
237 /*
238 * Determine which devices we control, and enter them into the maps.
239 */
240 static void
241 iopsp_scan(struct iopsp_softc *sc)
242 {
243 struct iop_softc *iop;
244 struct i2o_lct_entry *le;
245 struct scsipi_link *sc_link;
246 struct {
247 struct i2o_param_op_results pr;
248 struct i2o_param_read_results prr;
249 struct i2o_param_scsi_device_info sdi;
250 } __attribute__ ((__packed__)) param;
251 int tid, nent, i, targ, lun, size;
252 u_short *tidmap;
253 #ifdef I2OVERBOSE
254 struct iopsp_target *it;
255 int syncrate;
256 #endif
257
258 iop = (struct iop_softc *)sc->sc_dv.dv_parent;
259 sc_link = &sc->sc_link;
260
261 /*
262 * Allocate memory for the target/LUN -> TID map. Use zero to
263 * denote absent targets (zero is the TID of the I2O executive,
264 * and we never address that here).
265 */
266 size = (sc_link->scsipi_scsi.max_target + 1) *
267 (IOPSP_MAX_LUN + 1) * sizeof(u_short);
268 tidmap = malloc(size, M_DEVBUF, M_NOWAIT);
269 memset(tidmap, 0, size); /* XXX */
270
271 #ifdef I2OVERBOSE
272 for (i = 0; i <= sc_link->scsipi_scsi.max_target; i++)
273 sc->sc_targetmap[i].it_flags &= ~IT_PRESENT;
274 #endif
275
276 if (iop_lct_lock(iop) != 0)
277 return;
278
279 nent = iop->sc_nlctent;
280 for (i = 0, le = iop->sc_lct->entry; i < nent; i++, le++) {
281 switch (le16toh(le->classid) & 4095) {
282 case I2O_CLASS_SCSI_PERIPHERAL:
283 case I2O_CLASS_FIBRE_CHANNEL_PERIPHERAL:
284 break;
285 default:
286 continue;
287 }
288 if (((le32toh(le->usertid) >> 12) & 4095) != sc->sc_tid)
289 continue;
290
291 tid = le32toh(le->localtid) & 4095;
292
293 if (iop_params_get(iop, tid, I2O_PARAM_SCSI_DEVICE_INFO, ¶m,
294 sizeof(param)) != 0) {
295 printf("%s: unable to retrieve device parameters\n",
296 sc->sc_dv.dv_xname);
297 continue;
298 }
299 targ = le32toh(param.sdi.identifier);
300 lun = param.sdi.luninfo[1];
301
302 /* If the device is in use by another module, ignore it. */
303 if (!iop_tid_inuse(iop, tid)) {
304 #ifdef I2OVERBOSE
305 if (sc->sc_tidmap == NULL ||
306 IOPSP_TIDMAP(sc->sc_tidmap, targ, lun) !=
307 IOPSP_TID_INUSE)
308 printf("%s: target %d,%d (tid %d): in use by"
309 " another module\n", sc->sc_dv.dv_xname,
310 targ, lun, tid);
311 #endif
312 IOPSP_TIDMAP(tidmap, targ, lun) = IOPSP_TID_INUSE;
313 continue;
314 }
315 IOPSP_TIDMAP(tidmap, targ, lun) = (u_short)tid;
316
317 #ifdef I2OVERBOSE
318 /*
319 * If we've already described this target, and nothing has
320 * changed, then don't describe it again.
321 */
322 it = &sc->sc_targetmap[targ];
323 it->it_flags |= IT_PRESENT;
324 syncrate = ((int)le64toh(param.sdi.negsyncrate) + 500) / 1000;
325 if (it->it_width == param.sdi.negdatawidth &&
326 it->it_offset == param.sdi.negoffset &&
327 it->it_syncrate == syncrate)
328 continue;
329
330 it->it_width = param.sdi.negdatawidth;
331 it->it_offset = param.sdi.negoffset;
332 it->it_syncrate = syncrate;
333
334 printf("%s: target %d (tid %d): %d-bit, ", sc->sc_dv.dv_xname,
335 targ, tid, it->it_width);
336 if (it->it_syncrate == 0)
337 printf("asynchronous\n");
338 else
339 printf("synchronous at %dMHz, offset 0x%x\n",
340 it->it_syncrate, it->it_offset);
341 #endif
342 }
343
344 iop_lct_unlock(iop);
345
346 #ifdef I2OVERBOSE
347 for (i = 0; i <= sc_link->scsipi_scsi.max_target; i++)
348 if ((sc->sc_targetmap[i].it_flags & IT_PRESENT) == 0)
349 sc->sc_targetmap[i].it_width = 0;
350 #endif
351
352 /* Swap in the new map and return. */
353 if (sc->sc_tidmap != NULL)
354 free(sc->sc_tidmap, M_DEVBUF);
355 sc->sc_tidmap = tidmap;
356 sc->sc_chgindicator = iop->sc_lct->changeindicator;
357 }
358
359 /*
360 * Adjust the size an I/O request.
361 */
362 static void
363 iopsp_minphys(struct buf *bp)
364 {
365
366 if (bp->b_bcount > IOP_MAX_XFER)
367 bp->b_bcount = IOP_MAX_XFER;
368 minphys(bp);
369 }
370
371 /*
372 * Ask the bus port to perform a rescan. XXX It's unclear whether or not
373 * TIDs for established targets will change.
374 */
375 static int
376 iopsp_rescan(struct iopsp_softc *sc)
377 {
378 struct iop_softc *iop;
379 struct iop_msg *im;
380 struct i2o_hba_bus_scan *mb;
381 int rv;
382
383 iop = (struct iop_softc *)sc->sc_dv.dv_parent;
384
385 if (iop_msg_alloc(iop, &sc->sc_ii, &im, IM_NOINTR) != 0)
386 return (-1);
387
388 mb = (struct i2o_hba_bus_scan *)im->im_msg;
389 mb->msgflags = I2O_MSGFLAGS(i2o_hba_bus_scan);
390 mb->msgfunc = I2O_MSGFUNC(sc->sc_tid, I2O_HBA_BUS_SCAN);
391 mb->msgictx = sc->sc_ii.ii_ictx;
392 mb->msgtctx = im->im_tctx;
393
394 if (iop_msg_enqueue(iop, im) != 0)
395 rv = -1;
396 else if(iop_msg_wait(iop, im, 1000) != 0)
397 rv = -1;
398 else
399 rv = 0;
400 iop_msg_free(iop, &sc->sc_ii, im);
401 if (rv != 0)
402 return (rv);
403
404 /*
405 * Re-read the LCT and determine if it has changed. XXX This should
406 * probably be accomplished by noticing a CHANGED_LCT event from the
407 * executive.
408 */
409 if (iop_lct_get(iop))
410 return (-1);
411 if (iop->sc_lct->changeindicator == sc->sc_chgindicator)
412 return (0);
413
414 /* Rebuild the target/LUN -> TID map, and return. */
415 iopsp_scan(sc);
416 return (0);
417 }
418
419 /*
420 * Start a SCSI command.
421 */
422 static int
423 iopsp_scsi_cmd(struct scsipi_xfer *xs)
424 {
425 struct scsipi_link *sc_link;
426 struct iopsp_softc *sc;
427 struct iop_msg *im;
428 struct iop_softc *iop;
429 struct i2o_scsi_scb_exec *mb;
430 int error, flags, tid;
431
432 sc_link = xs->sc_link;
433 flags = xs->xs_control;
434 sc = sc_link->adapter_softc;
435 iop = (struct iop_softc *)sc->sc_dv.dv_parent;
436
437 tid = IOPSP_TIDMAP(sc->sc_tidmap, sc_link->scsipi_scsi.target,
438 sc_link->scsipi_scsi.lun);
439 if (tid == IOPSP_TID_ABSENT || tid == IOPSP_TID_INUSE) {
440 xs->error = XS_SELTIMEOUT;
441 return (COMPLETE);
442 }
443
444 SC_DEBUG(sc_link, SDEV_DB2, ("iopsp_scsi_cmd\n"));
445
446 /* Need to reset the target? */
447 if ((flags & XS_CTL_RESET) != 0) {
448 if (iop_simple_cmd(iop, tid, I2O_SCSI_DEVICE_RESET,
449 sc->sc_ii.ii_ictx) != 0) {
450 #ifdef I2ODEBUG
451 printf("%s: reset failed\n", sc->sc_dv.dv_xname);
452 #endif
453 xs->error = XS_DRIVER_STUFFUP;
454 }
455 return (COMPLETE);
456 }
457
458 #if defined(I2ODEBUG) || defined(SCSIDEBUG)
459 if (xs->cmdlen > 16) {
460 printf("%s: CDB too large\n", sc->sc_dv.dv_xname);
461 xs->error = XS_DRIVER_STUFFUP;
462 return (COMPLETE);
463 }
464 #endif
465
466 if (iop_msg_alloc(iop, &sc->sc_ii, &im,
467 (flags & (XS_CTL_POLL | XS_CTL_NOSLEEP)) != 0 ? IM_NOWAIT : 0)) {
468 xs->error = XS_DRIVER_STUFFUP;
469 return (TRY_AGAIN_LATER);
470 }
471 im->im_dvcontext = xs;
472
473 mb = (struct i2o_scsi_scb_exec *)im->im_msg;
474 mb->msgflags = I2O_MSGFLAGS(i2o_scsi_scb_exec);
475 mb->msgfunc = I2O_MSGFUNC(tid, I2O_SCSI_SCB_EXEC);
476 mb->msgictx = sc->sc_ii.ii_ictx;
477 mb->msgtctx = im->im_tctx;
478 mb->flags = xs->cmdlen | I2O_SCB_FLAG_ENABLE_DISCONNECT |
479 I2O_SCB_FLAG_SENSE_DATA_IN_MESSAGE;
480 memset(mb->cdb, 0, sizeof(mb->cdb));
481 memcpy(mb->cdb, xs->cmd, xs->cmdlen);
482 mb->datalen = xs->datalen;
483
484 /* XXX */
485 if ((xs->sc_link->quirks & SDEV_NOTAG) == 0 &&
486 xs->cmd->opcode != INQUIRY &&
487 xs->cmd->opcode != TEST_UNIT_READY &&
488 xs->cmd->opcode != REQUEST_SENSE) {
489 if (xs->bp != NULL && (xs->bp->b_flags & B_ASYNC) != 0)
490 mb->flags |= I2O_SCB_FLAG_ORDERED_QUEUE_TAG;
491 else
492 mb->flags |= I2O_SCB_FLAG_SIMPLE_QUEUE_TAG;
493 }
494
495 if (xs->datalen != 0) {
496 error = iop_msg_map(iop, im, xs->data, xs->datalen,
497 (flags & XS_CTL_DATA_OUT) == 0);
498 if (error) {
499 #ifdef I2ODEBUG
500 printf("%s: error %d mapping xfer\n",
501 sc->sc_dv.dv_xname, error);
502 #endif
503 xs->error = XS_DRIVER_STUFFUP;
504 iop_msg_free(iop, &sc->sc_ii, im);
505 return (COMPLETE);
506 }
507 if ((flags & XS_CTL_DATA_IN) == 0)
508 mb->flags |= I2O_SCB_FLAG_XFER_TO_DEVICE;
509 else
510 mb->flags |= I2O_SCB_FLAG_XFER_FROM_DEVICE;
511 }
512
513 /*
514 * If the command is allowed to execute asynchronously, enqueue it
515 * with the IOP. XXX Time out async commands?
516 */
517 if ((flags & XS_CTL_POLL) == 0) {
518 if (iop_msg_enqueue(iop, im)) {
519 iop_msg_unmap(iop, im);
520 iop_msg_free(iop, &sc->sc_ii, im);
521 #ifdef I2ODEBUG
522 printf("%s: can't enqueue msg\n", sc->sc_dv.dv_xname);
523 #endif
524 xs->error = XS_DRIVER_STUFFUP;
525 return (COMPLETE);
526 }
527 return (SUCCESSFULLY_QUEUED);
528 }
529
530 if (iop_msg_send(iop, im, xs->timeout)) {
531 scsi_print_addr(xs->sc_link);
532 printf("timeout; aborting command\n");
533 if (iopsp_scsi_abort(sc, im)) {
534 scsi_print_addr(xs->sc_link);
535 printf("abort failed\n");
536 }
537 xs->error = XS_DRIVER_STUFFUP;
538 }
539 return (COMPLETE);
540 }
541
542 /*
543 * Abort the specified I2O_SCSI_SCB_EXEC message and its associated SCB.
544 */
545 static int
546 iopsp_scsi_abort(struct iopsp_softc *sc, struct iop_msg *aim)
547 {
548 struct iop_msg *im;
549 struct i2o_scsi_scb_abort *mb;
550 struct iop_softc *iop;
551 int rv;
552
553 iop = (struct iop_softc *)sc->sc_dv.dv_parent;
554
555 rv = iop_msg_alloc(iop, &sc->sc_ii, &im, IM_NOWAIT | IM_NOINTR);
556 if (rv != 0)
557 return (rv);
558
559 mb = (struct i2o_scsi_scb_abort *)im->im_msg;
560 mb->msgflags = I2O_MSGFLAGS(i2o_scsi_scb_abort);
561 mb->msgfunc = I2O_MSGFUNC(aim->im_tid, I2O_SCSI_SCB_ABORT);
562 mb->msgictx = sc->sc_ii.ii_ictx;
563 mb->msgtctx = im->im_tctx;
564 mb->tctxabort = aim->im_tctx;
565
566 rv = iop_msg_send(iop, im, 1000);
567 iop_msg_free(iop, &sc->sc_ii, im);
568 return (rv);
569 }
570
571 /*
572 * We have a message which has been processed and replied to by the IOP -
573 * deal with it.
574 */
575 static void
576 iopsp_intr(struct device *dv, struct iop_msg *im, void *reply)
577 {
578 struct scsipi_xfer *xs;
579 struct iopsp_softc *sc;
580 struct i2o_scsi_reply *rb;
581 struct iop_softc *iop;
582 u_int hba_status, scsi_status, detail;
583 int sl;
584
585 sc = (struct iopsp_softc *)dv;
586 xs = (struct scsipi_xfer *)im->im_dvcontext;
587 iop = (struct iop_softc *)dv->dv_parent;
588
589 SC_DEBUG(xs->sc_link, SDEV_DB2, ("iopsp_intr\n"));
590
591 if (xs->error == XS_NOERROR) {
592 rb = reply;
593 detail = le16toh(rb->detail);
594 hba_status = (detail >> 8) & 0xff;
595 scsi_status = detail & 0xff;
596
597 if (hba_status != I2O_SCSI_DSC_SUCCESS) {
598 switch (hba_status) {
599 case I2O_SCSI_DSC_ADAPTER_BUSY:
600 case I2O_SCSI_DSC_SCSI_BUS_RESET:
601 case I2O_SCSI_DSC_BUS_BUSY:
602 xs->error = XS_BUSY;
603 break;
604 case I2O_SCSI_DSC_SELECTION_TIMEOUT:
605 xs->error = XS_SELTIMEOUT;
606 break;
607 case I2O_SCSI_DSC_COMMAND_TIMEOUT:
608 case I2O_SCSI_DSC_DEVICE_NOT_PRESENT:
609 case I2O_SCSI_DSC_LUN_INVALID:
610 case I2O_SCSI_DSC_SCSI_TID_INVALID:
611 xs->error = XS_TIMEOUT;
612 break;
613 default:
614 xs->error = XS_DRIVER_STUFFUP;
615 break;
616 }
617 #ifdef I2ODEBUG
618 printf("%s: HBA status 0x%02x\n", sc->sc_dv.dv_xname,
619 hba_status);
620 #endif
621 } else if (scsi_status != SCSI_OK) {
622 switch (scsi_status) {
623 case SCSI_CHECK:
624 xs->error = XS_SENSE;
625 sl = le32toh(rb->senselen);
626 if (xs->req_sense_length != 0 &&
627 xs->req_sense_length < sl)
628 sl = xs->req_sense_length;
629 if (sl > sizeof(xs->sense.scsi_sense))
630 sl = le32toh(rb->senselen);
631 memcpy(&xs->sense.scsi_sense, rb->sense, sl);
632 break;
633 case SCSI_BUSY:
634 xs->error = XS_BUSY;
635 break;
636 default:
637 xs->error = XS_DRIVER_STUFFUP;
638 break;
639 }
640 } else
641 xs->error = XS_NOERROR;
642
643 xs->resid = le32toh(rb->datalen) - xs->datalen;
644 xs->status = scsi_status;
645 }
646
647 /* Free the message wrapper and pass the news to scsipi. */
648 iop_msg_unmap(iop, im);
649 iop_msg_free(iop, &sc->sc_ii, im);
650 xs->xs_status |= XS_STS_DONE;
651 scsipi_done(xs);
652 }
653
654 /*
655 * ioctl hook; used here only to initiate low-level rescans.
656 */
657 static int
658 iopsp_ioctl(struct scsipi_link *sc_link, u_long cmd, caddr_t data, int flag,
659 struct proc *p)
660 {
661 int rv;
662
663 switch (cmd) {
664 case SCBUSIOLLSCAN:
665 rv = iopsp_rescan(sc_link->adapter_softc);
666 break;
667 default:
668 rv = ENXIO;
669 break;
670 }
671
672 return (rv);
673 }
674