Annotation of sys/dev/i2o/ioprbs.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: ioprbs.c,v 1.11 2006/11/28 23:59:45 dlg Exp $ */
2:
3: /*
4: * Copyright (c) 2001 Niklas Hallqvist
5: * All rights reserved.
6: *
7: * Redistribution and use in source and binary forms, with or without
8: * modification, are permitted provided that the following conditions
9: * are met:
10: * 1. Redistributions of source code must retain the above copyright
11: * notice, this list of conditions and the following disclaimer.
12: * 2. Redistributions in binary form must reproduce the above copyright
13: * notice, this list of conditions and the following disclaimer in the
14: * documentation and/or other materials provided with the distribution.
15: *
16: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19: * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26: * SUCH DAMAGE.
27: */
28:
29: /*-
30: * Copyright (c) 2000, 2001 The NetBSD Foundation, Inc.
31: * All rights reserved.
32: *
33: * This code is derived from software contributed to The NetBSD Foundation
34: * by Andrew Doran.
35: *
36: * Redistribution and use in source and binary forms, with or without
37: * modification, are permitted provided that the following conditions
38: * are met:
39: * 1. Redistributions of source code must retain the above copyright
40: * notice, this list of conditions and the following disclaimer.
41: * 2. Redistributions in binary form must reproduce the above copyright
42: * notice, this list of conditions and the following disclaimer in the
43: * documentation and/or other materials provided with the distribution.
44: * 3. All advertising materials mentioning features or use of this software
45: * must display the following acknowledgement:
46: * This product includes software developed by the NetBSD
47: * Foundation, Inc. and its contributors.
48: * 4. Neither the name of The NetBSD Foundation nor the names of its
49: * contributors may be used to endorse or promote products derived
50: * from this software without specific prior written permission.
51: *
52: * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
53: * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
54: * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
55: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
56: * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
57: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
58: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
59: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
60: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
61: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
62: * POSSIBILITY OF SUCH DAMAGE.
63: */
64:
65: /*
66: * A driver for I2O "Random block storage" devices, like RAID.
67: */
68:
69: /*
70: * This driver would not have been written if it was not for the hardware
71: * donation from pi.se. I want to thank them for their support. It also
72: * had been much harder without Andrew Doran's work in NetBSD's ld_iop.c
73: * driver, from which I have both gotten inspiration and actual code.
74: * - Niklas Hallqvist
75: */
76:
77: #include <sys/param.h>
78: #include <sys/buf.h>
79: #include <sys/device.h>
80: #include <sys/kernel.h>
81: #include <sys/proc.h>
82: #include <sys/systm.h>
83:
84: #include <machine/bus.h>
85:
86: #include <scsi/scsi_all.h>
87: #include <scsi/scsi_disk.h>
88: #include <scsi/scsiconf.h>
89:
90: #include <dev/i2o/i2o.h>
91: #include <dev/i2o/iopio.h>
92: #include <dev/i2o/iopvar.h>
93: #include <dev/i2o/ioprbsvar.h>
94:
95: #ifdef I2ODEBUG
96: #define DPRINTF(x) printf x
97: #else
98: #define DPRINTF(x)
99: #endif
100:
101: void ioprbsminphys(struct buf *);
102: void ioprbs_adjqparam(struct device *, int);
103: void ioprbs_attach(struct device *, struct device *, void *);
104: void ioprbs_copy_internal_data(struct scsi_xfer *, u_int8_t *,
105: size_t);
106: struct scsi_xfer *ioprbs_dequeue(struct ioprbs_softc *);
107: void ioprbs_enqueue(struct ioprbs_softc *, struct scsi_xfer *, int);
108: void ioprbs_enqueue_ccb(struct ioprbs_softc *, struct ioprbs_ccb *);
109: int ioprbs_exec_ccb(struct ioprbs_ccb *);
110: void ioprbs_free_ccb(struct ioprbs_softc *, struct ioprbs_ccb *);
111: struct ioprbs_ccb *ioprbs_get_ccb(struct ioprbs_softc *, int);
112: void ioprbs_internal_cache_cmd(struct scsi_xfer *);
113: void ioprbs_intr(struct device *, struct iop_msg *, void *);
114: void ioprbs_intr_event(struct device *, struct iop_msg *, void *);
115: int ioprbs_match(struct device *, void *, void *);
116: int ioprbs_scsi_cmd(struct scsi_xfer *);
117: int ioprbs_start(struct ioprbs_ccb *);
118: void ioprbs_start_ccbs(struct ioprbs_softc *);
119: void ioprbs_timeout(void *);
120: void ioprbs_unconfig(struct ioprbs_softc *, int);
121: void ioprbs_watchdog(void *);
122:
123: struct cfdriver ioprbs_cd = {
124: NULL, "ioprbs", DV_DULL
125: };
126:
127: struct cfattach ioprbs_ca = {
128: sizeof(struct ioprbs_softc), ioprbs_match, ioprbs_attach
129: };
130:
131: struct scsi_adapter ioprbs_switch = {
132: ioprbs_scsi_cmd, ioprbsminphys, 0, 0,
133: };
134:
135: struct scsi_device ioprbs_dev = {
136: NULL, NULL, NULL, NULL
137: };
138:
139: #ifdef I2OVERBOSE
140: static const char *const ioprbs_errors[] = {
141: "success",
142: "media error",
143: "access error",
144: "device failure",
145: "device not ready",
146: "media not present",
147: "media locked",
148: "media failure",
149: "protocol failure",
150: "bus failure",
151: "access violation",
152: "media write protected",
153: "device reset",
154: "volume changed, waiting for acknowledgement",
155: "timeout",
156: };
157: #endif
158:
159: /*
160: * Match a supported device.
161: */
162: int
163: ioprbs_match(parent, match, aux)
164: struct device *parent;
165: void *match;
166: void *aux;
167: {
168: struct iop_attach_args *ia = aux;
169:
170: return (ia->ia_class == I2O_CLASS_RANDOM_BLOCK_STORAGE);
171: }
172:
173: /*
174: * Attach a supported device.
175: */
176: void
177: ioprbs_attach(struct device *parent, struct device *self, void *aux)
178: {
179: struct iop_attach_args *ia = aux;
180: struct ioprbs_softc *sc = (struct ioprbs_softc *)self;
181: struct iop_softc *iop = (struct iop_softc *)parent;
182: struct scsibus_attach_args saa;
183: int rv, state = 0;
184: int enable;
185: u_int32_t cachesz;
186: char *typestr, *fixedstr;
187: struct {
188: struct i2o_param_op_results pr;
189: struct i2o_param_read_results prr;
190: union {
191: struct i2o_param_rbs_cache_control cc;
192: struct i2o_param_rbs_device_info bdi;
193: struct i2o_param_rbs_operation op;
194: } p;
195: } param /* XXX gcc __attribute__ ((__packed__)) */;
196: int i;
197:
198: TAILQ_INIT(&sc->sc_free_ccb);
199: TAILQ_INIT(&sc->sc_ccbq);
200: LIST_INIT(&sc->sc_queue);
201:
202: /* Initialize the ccbs */
203: for (i = 0; i < IOPRBS_MAX_CCBS; i++)
204: TAILQ_INSERT_TAIL(&sc->sc_free_ccb, &sc->sc_ccbs[i],
205: ic_chain);
206:
207: /* Register us as an initiator. */
208: sc->sc_ii.ii_dv = self;
209: sc->sc_ii.ii_intr = ioprbs_intr;
210: sc->sc_ii.ii_adjqparam = ioprbs_adjqparam;
211: sc->sc_ii.ii_flags = 0;
212: sc->sc_ii.ii_tid = ia->ia_tid;
213: iop_initiator_register(iop, &sc->sc_ii);
214:
215: /* Register another initiator to handle events from the device. */
216: sc->sc_eventii.ii_dv = self;
217: sc->sc_eventii.ii_intr = ioprbs_intr_event;
218: sc->sc_eventii.ii_flags = II_DISCARD | II_UTILITY;
219: sc->sc_eventii.ii_tid = ia->ia_tid;
220: iop_initiator_register(iop, &sc->sc_eventii);
221:
222: rv = iop_util_eventreg(iop, &sc->sc_eventii,
223: I2O_EVENT_GEN_EVENT_MASK_MODIFIED | I2O_EVENT_GEN_DEVICE_RESET |
224: I2O_EVENT_GEN_STATE_CHANGE | I2O_EVENT_GEN_GENERAL_WARNING);
225: if (rv != 0) {
226: printf("%s: unable to register for events", self->dv_xname);
227: goto bad;
228: }
229: state++;
230:
231: /*
232: * Start out with one queued command. The `iop' driver will adjust
233: * the queue parameters once we're up and running.
234: */
235: sc->sc_maxqueuecnt = 1;
236:
237: sc->sc_maxxfer = IOP_MAX_XFER;
238:
239: /* Say what the device is. */
240: printf(":");
241: iop_print_ident(iop, ia->ia_tid);
242:
243: /*
244: * Claim the device so that we don't get any nasty surprises. Allow
245: * failure.
246: */
247: rv = iop_util_claim(iop, &sc->sc_ii, 0,
248: I2O_UTIL_CLAIM_CAPACITY_SENSITIVE |
249: I2O_UTIL_CLAIM_NO_PEER_SERVICE |
250: I2O_UTIL_CLAIM_NO_MANAGEMENT_SERVICE |
251: I2O_UTIL_CLAIM_PRIMARY_USER);
252: sc->sc_flags = rv ? 0 : IOPRBS_CLAIMED;
253:
254: rv = iop_param_op(iop, ia->ia_tid, NULL, 0, I2O_PARAM_RBS_DEVICE_INFO,
255: ¶m, sizeof param);
256: if (rv != 0) {
257: printf("%s: unable to get parameters (0x%04x; %d)\n",
258: sc->sc_dv.dv_xname, I2O_PARAM_RBS_DEVICE_INFO, rv);
259: goto bad;
260: }
261:
262: sc->sc_secsize = letoh32(param.p.bdi.blocksize);
263: sc->sc_secperunit = (int)
264: (letoh64(param.p.bdi.capacity) / sc->sc_secsize);
265:
266: switch (param.p.bdi.type) {
267: case I2O_RBS_TYPE_DIRECT:
268: typestr = "direct access";
269: enable = 1;
270: break;
271: case I2O_RBS_TYPE_WORM:
272: typestr = "WORM";
273: enable = 0;
274: break;
275: case I2O_RBS_TYPE_CDROM:
276: typestr = "CD-ROM";
277: enable = 0;
278: break;
279: case I2O_RBS_TYPE_OPTICAL:
280: typestr = "optical";
281: enable = 0;
282: break;
283: default:
284: typestr = "unknown";
285: enable = 0;
286: break;
287: }
288:
289: if ((letoh32(param.p.bdi.capabilities) & I2O_RBS_CAP_REMOVABLE_MEDIA)
290: != 0) {
291: /* sc->sc_flags = IOPRBS_REMOVABLE; */
292: fixedstr = "removable";
293: enable = 0;
294: } else
295: fixedstr = "fixed";
296:
297: printf(" %s, %s", typestr, fixedstr);
298:
299: /*
300: * Determine if the device has an private cache. If so, print the
301: * cache size. Even if the device doesn't appear to have a cache,
302: * we perform a flush at shutdown.
303: */
304: rv = iop_param_op(iop, ia->ia_tid, NULL, 0,
305: I2O_PARAM_RBS_CACHE_CONTROL, ¶m, sizeof(param));
306: if (rv != 0) {
307: printf("%s: unable to get parameters (0x%04x; %d)\n",
308: sc->sc_dv.dv_xname, I2O_PARAM_RBS_CACHE_CONTROL, rv);
309: goto bad;
310: }
311:
312: if ((cachesz = letoh32(param.p.cc.totalcachesize)) != 0)
313: printf(", %dkB cache", cachesz >> 10);
314:
315: printf("\n");
316:
317: /*
318: * Configure the DDM's timeout functions to time out all commands
319: * after 30 seconds.
320: */
321: rv = iop_param_op(iop, ia->ia_tid, NULL, 0, I2O_PARAM_RBS_OPERATION,
322: ¶m, sizeof(param));
323: if (rv != 0) {
324: printf("%s: unable to get parameters (0x%04x; %d)\n",
325: sc->sc_dv.dv_xname, I2O_PARAM_RBS_OPERATION, rv);
326: goto bad;
327: }
328:
329: param.p.op.timeoutbase = htole32(IOPRBS_TIMEOUT * 1000);
330: param.p.op.rwvtimeoutbase = htole32(IOPRBS_TIMEOUT * 1000);
331: param.p.op.rwvtimeout = 0;
332:
333: rv = iop_param_op(iop, ia->ia_tid, NULL, 1, I2O_PARAM_RBS_OPERATION,
334: ¶m, sizeof(param));
335: #ifdef notdef
336: /*
337: * Intel RAID adapters don't like the above, but do post a
338: * `parameter changed' event. Perhaps we're doing something
339: * wrong...
340: */
341: if (rv != 0) {
342: printf("%s: unable to set parameters (0x%04x; %d)\n",
343: sc->sc_dv.dv_xname, I2O_PARAM_RBS_OPERATION, rv);
344: goto bad;
345: }
346: #endif
347:
348: if (enable)
349: sc->sc_flags |= IOPRBS_ENABLED;
350: else
351: printf("%s: device not yet supported\n", self->dv_xname);
352:
353: /* Fill in the prototype scsi_link. */
354: sc->sc_link.adapter_softc = sc;
355: sc->sc_link.adapter = &ioprbs_switch;
356: sc->sc_link.device = &ioprbs_dev;
357: sc->sc_link.openings = 1;
358: sc->sc_link.adapter_buswidth = 1;
359: sc->sc_link.adapter_target = 1;
360:
361: bzero(&saa, sizeof(saa));
362: saa.saa_sc_link = &sc->sc_link;
363:
364: config_found(&sc->sc_dv, &saa, scsiprint);
365:
366: return;
367:
368: bad:
369: ioprbs_unconfig(sc, state > 0);
370: }
371:
372: void
373: ioprbs_unconfig(struct ioprbs_softc *sc, int evreg)
374: {
375: struct iop_softc *iop;
376: int s;
377:
378: iop = (struct iop_softc *)sc->sc_dv.dv_parent;
379:
380: if ((sc->sc_flags & IOPRBS_CLAIMED) != 0)
381: iop_util_claim(iop, &sc->sc_ii, 1,
382: I2O_UTIL_CLAIM_PRIMARY_USER);
383:
384: if (evreg) {
385: /*
386: * Mask off events, and wait up to 5 seconds for a reply.
387: * Note that some adapters won't reply to this (XXX We
388: * should check the event capabilities).
389: */
390: sc->sc_flags &= ~IOPRBS_NEW_EVTMASK;
391: iop_util_eventreg(iop, &sc->sc_eventii,
392: I2O_EVENT_GEN_EVENT_MASK_MODIFIED);
393: s = splbio();
394: if ((sc->sc_flags & IOPRBS_NEW_EVTMASK) == 0)
395: tsleep(&sc->sc_eventii, PRIBIO, "ioprbsevt", hz * 5);
396: splx(s);
397: #ifdef I2ODEBUG
398: if ((sc->sc_flags & IOPRBS_NEW_EVTMASK) == 0)
399: printf("%s: didn't reply to event unregister",
400: sc->sc_dv.dv_xname);
401: #endif
402: }
403:
404: iop_initiator_unregister(iop, &sc->sc_eventii);
405: iop_initiator_unregister(iop, &sc->sc_ii);
406: }
407:
408: int
409: ioprbs_scsi_cmd(xs)
410: struct scsi_xfer *xs;
411: {
412: struct scsi_link *link = xs->sc_link;
413: struct ioprbs_softc *sc = link->adapter_softc;
414: struct ioprbs_ccb *ccb;
415: u_int32_t blockno, blockcnt;
416: struct scsi_rw *rw;
417: struct scsi_rw_big *rwb;
418: ioprbs_lock_t lock;
419: int retval = SUCCESSFULLY_QUEUED;
420:
421: lock = IOPRBS_LOCK(sc);
422:
423: /* Don't double enqueue if we came from ioprbs_chain. */
424: if (xs != LIST_FIRST(&sc->sc_queue))
425: ioprbs_enqueue(sc, xs, 0);
426:
427: while ((xs = ioprbs_dequeue(sc))) {
428: xs->error = XS_NOERROR;
429:
430: ccb = NULL;
431:
432: switch (xs->cmd->opcode) {
433: case TEST_UNIT_READY:
434: case REQUEST_SENSE:
435: case INQUIRY:
436: case MODE_SENSE:
437: case START_STOP:
438: case READ_CAPACITY:
439: #if 0
440: case VERIFY:
441: #endif
442: ioprbs_internal_cache_cmd(xs);
443: xs->flags |= ITSDONE;
444: scsi_done(xs);
445: goto ready;
446:
447: case PREVENT_ALLOW:
448: DPRINTF(("PREVENT/ALLOW "));
449: /* XXX Not yet implemented */
450: xs->error = XS_NOERROR;
451: xs->flags |= ITSDONE;
452: scsi_done(xs);
453: goto ready;
454:
455: case SYNCHRONIZE_CACHE:
456: DPRINTF(("SYNCHRONIZE_CACHE "));
457: /* XXX Not yet implemented */
458: xs->error = XS_NOERROR;
459: xs->flags |= ITSDONE;
460: scsi_done(xs);
461: goto ready;
462:
463: default:
464: DPRINTF(("unknown opc %d ", xs->cmd->opcode));
465: /* XXX Not yet implemented */
466: xs->error = XS_DRIVER_STUFFUP;
467: xs->flags |= ITSDONE;
468: scsi_done(xs);
469: goto ready;
470:
471: case READ_COMMAND:
472: case READ_BIG:
473: case WRITE_COMMAND:
474: case WRITE_BIG:
475: DPRINTF(("rw opc %d ", xs->cmd->opcode));
476:
477: if (xs->cmd->opcode != SYNCHRONIZE_CACHE) {
478: /* A read or write operation. */
479: if (xs->cmdlen == 6) {
480: rw = (struct scsi_rw *)xs->cmd;
481: blockno = _3btol(rw->addr) &
482: (SRW_TOPADDR << 16 | 0xffff);
483: blockcnt =
484: rw->length ? rw->length : 0x100;
485: } else {
486: rwb = (struct scsi_rw_big *)xs->cmd;
487: blockno = _4btol(rwb->addr);
488: blockcnt = _2btol(rwb->length);
489: }
490: if (blockno >= sc->sc_secperunit ||
491: blockno + blockcnt > sc->sc_secperunit) {
492: printf(
493: "%s: out of bounds %u-%u >= %u\n",
494: sc->sc_dv.dv_xname, blockno,
495: blockcnt, sc->sc_secperunit);
496: /*
497: * XXX Should be XS_SENSE but that
498: * would require setting up a faked
499: * sense too.
500: */
501: xs->error = XS_DRIVER_STUFFUP;
502: xs->flags |= ITSDONE;
503: scsi_done(xs);
504: goto ready;
505: }
506: }
507:
508: ccb = ioprbs_get_ccb(sc, xs->flags);
509:
510: /*
511: * We are out of commands, try again in a little while.
512: */
513: if (ccb == NULL) {
514: IOPRBS_UNLOCK(sc, lock);
515: return (TRY_AGAIN_LATER);
516: }
517:
518: ccb->ic_blockno = blockno;
519: ccb->ic_blockcnt = blockcnt;
520: ccb->ic_xs = xs;
521: ccb->ic_timeout = xs->timeout;
522:
523: ioprbs_enqueue_ccb(sc, ccb);
524:
525: /* XXX what if enqueue did not start a transfer? */
526: if (xs->flags & SCSI_POLL) {
527: #if 0
528: if (!ioprbs_wait(sc, ccb, ccb->ic_timeout)) {
529: IOPRBS_UNLOCK(sc, lock);
530: printf("%s: command timed out\n",
531: sc->sc_dv.dv_xname);
532: return (TRY_AGAIN_LATER);
533: }
534: xs->flags |= ITSDONE;
535: scsi_done(xs);
536: #endif
537: }
538: }
539:
540: ready:
541: /*
542: * Don't process the queue if we are polling.
543: */
544: if (xs->flags & SCSI_POLL) {
545: retval = COMPLETE;
546: break;
547: }
548: }
549:
550: IOPRBS_UNLOCK(sc, lock);
551: return (retval);
552: }
553:
554: void
555: ioprbsminphys(bp)
556: struct buf *bp;
557: {
558: minphys(bp);
559: }
560:
561: void
562: ioprbs_intr(struct device *dv, struct iop_msg *im, void *reply)
563: {
564: struct i2o_rbs_reply *rb = reply;
565: struct ioprbs_ccb *ccb = im->im_dvcontext;
566: struct buf *bp = ccb->ic_xs->bp;
567: struct ioprbs_softc *sc = (struct ioprbs_softc *)dv;
568: struct iop_softc *iop = (struct iop_softc *)dv->dv_parent;
569: int err, detail;
570: #ifdef I2OVERBOSE
571: const char *errstr;
572: #endif
573:
574: DPRINTF(("ioprbs_intr(%p, %p, %p) ", dv, im, reply));
575:
576: timeout_del(&ccb->ic_xs->stimeout);
577:
578: err = ((rb->msgflags & I2O_MSGFLAGS_FAIL) != 0);
579:
580: if (!err && rb->reqstatus != I2O_STATUS_SUCCESS) {
581: detail = letoh16(rb->detail);
582: #ifdef I2OVERBOSE
583: if (detail > sizeof(ioprbs_errors) / sizeof(ioprbs_errors[0]))
584: errstr = "<unknown>";
585: else
586: errstr = ioprbs_errors[detail];
587: printf("%s: error 0x%04x: %s\n", dv->dv_xname, detail, errstr);
588: #else
589: printf("%s: error 0x%04x\n", dv->dv_xname, detail);
590: #endif
591: err = 1;
592: }
593:
594: if (bp) {
595: if (err) {
596: bp->b_flags |= B_ERROR;
597: bp->b_error = EIO;
598: bp->b_resid = bp->b_bcount;
599: } else
600: bp->b_resid = bp->b_bcount - letoh32(rb->transfercount);
601: }
602:
603: iop_msg_unmap(iop, im);
604: iop_msg_free(iop, im);
605: scsi_done(ccb->ic_xs);
606: ioprbs_free_ccb(sc, ccb);
607: }
608:
609: void
610: ioprbs_intr_event(struct device *dv, struct iop_msg *im, void *reply)
611: {
612: struct i2o_util_event_register_reply *rb;
613: struct ioprbs_softc *sc;
614: u_int event;
615:
616: rb = reply;
617:
618: if ((rb->msgflags & I2O_MSGFLAGS_FAIL) != 0)
619: return;
620:
621: event = letoh32(rb->event);
622: sc = (struct ioprbs_softc *)dv;
623:
624: if (event == I2O_EVENT_GEN_EVENT_MASK_MODIFIED) {
625: sc->sc_flags |= IOPRBS_NEW_EVTMASK;
626: wakeup(&sc->sc_eventii);
627: #ifndef I2ODEBUG
628: return;
629: #endif
630: }
631:
632: printf("%s: event 0x%08x received\n", dv->dv_xname, event);
633: }
634:
635: void
636: ioprbs_adjqparam(struct device *dv, int mpi)
637: {
638: #if 0
639: struct iop_softc *iop;
640:
641: /*
642: * AMI controllers seem to lose the plot if you hand off lots of
643: * queued commands.
644: */
645: iop = (struct iop_softc *)dv->dv_parent;
646: if (letoh16(I2O_ORG_AMI) == iop->sc_status.orgid && mpi > 64)
647: mpi = 64;
648:
649: ldadjqparam((struct ld_softc *)dv, mpi);
650: #endif
651: }
652:
653: /*
654: * Insert a command into the driver queue, either at the front or at the tail.
655: * It's ok to overload the freelist link as these structures are never on
656: * the freelist at this time.
657: */
658: void
659: ioprbs_enqueue(sc, xs, infront)
660: struct ioprbs_softc *sc;
661: struct scsi_xfer *xs;
662: int infront;
663: {
664: if (infront || LIST_FIRST(&sc->sc_queue) == NULL) {
665: if (LIST_FIRST(&sc->sc_queue) == NULL)
666: sc->sc_queuelast = xs;
667: LIST_INSERT_HEAD(&sc->sc_queue, xs, free_list);
668: return;
669: }
670: LIST_INSERT_AFTER(sc->sc_queuelast, xs, free_list);
671: sc->sc_queuelast = xs;
672: }
673:
674: /*
675: * Pull a command off the front of the driver queue.
676: */
677: struct scsi_xfer *
678: ioprbs_dequeue(sc)
679: struct ioprbs_softc *sc;
680: {
681: struct scsi_xfer *xs;
682:
683: xs = LIST_FIRST(&sc->sc_queue);
684: if (xs == NULL)
685: return (NULL);
686: LIST_REMOVE(xs, free_list);
687:
688: if (LIST_FIRST(&sc->sc_queue) == NULL)
689: sc->sc_queuelast = NULL;
690:
691: return (xs);
692: }
693:
694: void
695: ioprbs_copy_internal_data(xs, data, size)
696: struct scsi_xfer *xs;
697: u_int8_t *data;
698: size_t size;
699: {
700: size_t copy_cnt;
701:
702: DPRINTF(("ioprbs_copy_internal_data "));
703:
704: if (!xs->datalen)
705: printf("uio move not yet supported\n");
706: else {
707: copy_cnt = MIN(size, xs->datalen);
708: bcopy(data, xs->data, copy_cnt);
709: }
710: }
711:
712: /* Emulated SCSI operation on cache device */
713: void
714: ioprbs_internal_cache_cmd(xs)
715: struct scsi_xfer *xs;
716: {
717: struct scsi_link *link = xs->sc_link;
718: struct ioprbs_softc *sc = link->adapter_softc;
719: u_int8_t target = link->target;
720: struct scsi_inquiry_data inq;
721: struct scsi_sense_data sd;
722: struct scsi_read_cap_data rcd;
723:
724: DPRINTF(("ioprbs_internal_cache_cmd "));
725:
726: xs->error = XS_NOERROR;
727:
728: if (target > 0 || link->lun != 0) {
729: xs->error = XS_DRIVER_STUFFUP;
730: return;
731: }
732:
733: switch (xs->cmd->opcode) {
734: case TEST_UNIT_READY:
735: case START_STOP:
736: #if 0
737: case VERIFY:
738: #endif
739: DPRINTF(("opc %d tgt %d ", xs->cmd->opcode, target));
740: break;
741:
742: case REQUEST_SENSE:
743: DPRINTF(("REQUEST SENSE tgt %d ", target));
744: bzero(&sd, sizeof sd);
745: sd.error_code = 0x70;
746: sd.segment = 0;
747: sd.flags = SKEY_NO_SENSE;
748: bzero(sd.info, sizeof sd.info);
749: sd.extra_len = 0;
750: ioprbs_copy_internal_data(xs, (u_int8_t *)&sd, sizeof sd);
751: break;
752:
753: case INQUIRY:
754: DPRINTF(("INQUIRY tgt %d", target));
755: bzero(&inq, sizeof inq);
756: /* XXX How do we detect removable/CD-ROM devices? */
757: inq.device = T_DIRECT;
758: inq.dev_qual2 = 0;
759: inq.version = 2;
760: inq.response_format = 2;
761: inq.additional_length = 32;
762: strlcpy(inq.vendor, "I2O", sizeof inq.vendor);
763: snprintf(inq.product, sizeof inq.product, "Container #%02d",
764: target);
765: strlcpy(inq.revision, " ", sizeof inq.revision);
766: ioprbs_copy_internal_data(xs, (u_int8_t *)&inq, sizeof inq);
767: break;
768:
769: case READ_CAPACITY:
770: DPRINTF(("READ CAPACITY tgt %d ", target));
771: bzero(&rcd, sizeof rcd);
772: _lto4b(sc->sc_secperunit - 1, rcd.addr);
773: _lto4b(IOPRBS_BLOCK_SIZE, rcd.length);
774: ioprbs_copy_internal_data(xs, (u_int8_t *)&rcd, sizeof rcd);
775: break;
776:
777: default:
778: DPRINTF(("unsupported scsi command %#x tgt %d ",
779: xs->cmd->opcode, target));
780: xs->error = XS_DRIVER_STUFFUP;
781: return;
782: }
783:
784: xs->error = XS_NOERROR;
785: }
786:
787: struct ioprbs_ccb *
788: ioprbs_get_ccb(sc, flags)
789: struct ioprbs_softc *sc;
790: int flags;
791: {
792: struct ioprbs_ccb *ccb;
793: ioprbs_lock_t lock;
794:
795: DPRINTF(("ioprbs_get_ccb(%p, 0x%x) ", sc, flags));
796:
797: lock = IOPRBS_LOCK(sc);
798:
799: for (;;) {
800: ccb = TAILQ_FIRST(&sc->sc_free_ccb);
801: if (ccb != NULL)
802: break;
803: if (flags & SCSI_NOSLEEP)
804: goto bail_out;
805: tsleep(&sc->sc_free_ccb, PRIBIO, "ioprbs_ccb", 0);
806: }
807:
808: TAILQ_REMOVE(&sc->sc_free_ccb, ccb, ic_chain);
809:
810: /* initialise the command */
811: ccb->ic_flags = 0;
812:
813: bail_out:
814: IOPRBS_UNLOCK(sc, lock);
815: return (ccb);
816: }
817:
818: void
819: ioprbs_free_ccb(sc, ccb)
820: struct ioprbs_softc *sc;
821: struct ioprbs_ccb *ccb;
822: {
823: ioprbs_lock_t lock;
824:
825: DPRINTF(("ioprbs_free_ccb(%p, %p) ", sc, ccb));
826:
827: lock = IOPRBS_LOCK(sc);
828:
829: TAILQ_INSERT_HEAD(&sc->sc_free_ccb, ccb, ic_chain);
830:
831: /* If the free list was empty, wake up potential waiters. */
832: if (TAILQ_NEXT(ccb, ic_chain) == NULL)
833: wakeup(&sc->sc_free_ccb);
834:
835: IOPRBS_UNLOCK(sc, lock);
836: }
837:
838: void
839: ioprbs_enqueue_ccb(sc, ccb)
840: struct ioprbs_softc *sc;
841: struct ioprbs_ccb *ccb;
842: {
843: DPRINTF(("ioprbs_enqueue_ccb(%p, %p) ", sc, ccb));
844:
845: timeout_set(&ccb->ic_xs->stimeout, ioprbs_timeout, ccb);
846: TAILQ_INSERT_TAIL(&sc->sc_ccbq, ccb, ic_chain);
847: ioprbs_start_ccbs(sc);
848: }
849:
850: void
851: ioprbs_start_ccbs(sc)
852: struct ioprbs_softc *sc;
853: {
854: struct ioprbs_ccb *ccb;
855: struct scsi_xfer *xs;
856:
857: DPRINTF(("ioprbs_start_ccbs(%p) ", sc));
858:
859: while ((ccb = TAILQ_FIRST(&sc->sc_ccbq)) != NULL) {
860:
861: xs = ccb->ic_xs;
862: if (ccb->ic_flags & IOPRBS_ICF_WATCHDOG)
863: timeout_del(&xs->stimeout);
864:
865: if (ioprbs_exec_ccb(ccb) == 0) {
866: ccb->ic_flags |= IOPRBS_ICF_WATCHDOG;
867: timeout_set(&ccb->ic_xs->stimeout, ioprbs_watchdog,
868: ccb);
869: timeout_add(&xs->stimeout,
870: (IOPRBS_WATCH_TIMEOUT * hz) / 1000);
871: break;
872: }
873: TAILQ_REMOVE(&sc->sc_ccbq, ccb, ic_chain);
874:
875: if ((xs->flags & SCSI_POLL) == 0) {
876: timeout_set(&ccb->ic_xs->stimeout, ioprbs_timeout,
877: ccb);
878: timeout_add(&xs->stimeout,
879: (ccb->ic_timeout * hz) / 1000);
880: }
881: }
882: }
883:
884: int
885: ioprbs_exec_ccb(ccb)
886: struct ioprbs_ccb *ccb;
887: {
888: struct scsi_xfer *xs = ccb->ic_xs;
889:
890: DPRINTF(("ioprbs_exec_ccb(%p, %p) ", xs, ccb));
891:
892: ioprbs_start(ccb);
893:
894: xs->error = XS_NOERROR;
895: xs->resid = 0;
896: return (1);
897: }
898:
899: /*
900: * Deliver a command to the controller; allocate controller resources at the
901: * last moment when possible.
902: */
903: int
904: ioprbs_start(struct ioprbs_ccb *ccb)
905: {
906: struct scsi_xfer *xs = ccb->ic_xs;
907: struct scsi_link *link = xs->sc_link;
908: struct ioprbs_softc *sc = link->adapter_softc;
909: #ifdef I2ODEBUG
910: u_int8_t target = link->target;
911: #endif
912: struct iop_msg *im;
913: struct iop_softc *iop = (struct iop_softc *)sc->sc_dv.dv_parent;
914: struct i2o_rbs_block_read *mf;
915: u_int rv, flags = 0, mode = I2O_RBS_BLOCK_READ;
916: u_int64_t ba;
917: u_int32_t mb[IOP_MAX_MSG_SIZE / sizeof(u_int32_t)];
918:
919: im = iop_msg_alloc(iop, &sc->sc_ii, 0);
920: im->im_dvcontext = ccb;
921:
922: switch (xs->cmd->opcode) {
923: case PREVENT_ALLOW:
924: case SYNCHRONIZE_CACHE:
925: if (xs->cmd->opcode == PREVENT_ALLOW) {
926: /* XXX PREVENT_ALLOW support goes here */
927: } else {
928: DPRINTF(("SYNCHRONIZE CACHE tgt %d ", target));
929: }
930: break;
931:
932: case WRITE_COMMAND:
933: case WRITE_BIG:
934: flags = I2O_RBS_BLOCK_WRITE_CACHE_WB;
935: mode = I2O_RBS_BLOCK_WRITE;
936: /* FALLTHROUGH */
937:
938: case READ_COMMAND:
939: case READ_BIG:
940: ba = (u_int64_t)ccb->ic_blockno * DEV_BSIZE;
941:
942: /*
943: * Fill the message frame. We can use the block_read
944: * structure for both reads and writes, as it's almost
945: * identical to the * block_write structure.
946: */
947: mf = (struct i2o_rbs_block_read *)mb;
948: mf->msgflags = I2O_MSGFLAGS(i2o_rbs_block_read);
949: mf->msgfunc = I2O_MSGFUNC(sc->sc_ii.ii_tid, mode);
950: mf->msgictx = sc->sc_ii.ii_ictx;
951: mf->msgtctx = im->im_tctx;
952: mf->flags = flags | (1 << 16); /* flags & time multiplier */
953: mf->datasize = ccb->ic_blockcnt * DEV_BSIZE;
954: mf->lowoffset = (u_int32_t)ba;
955: mf->highoffset = (u_int32_t)(ba >> 32);
956:
957: /* Map the data transfer and enqueue the command. */
958: rv = iop_msg_map_bio(iop, im, mb, xs->data,
959: ccb->ic_blockcnt * DEV_BSIZE, mode == I2O_RBS_BLOCK_WRITE);
960: if (rv == 0) {
961: if ((rv = iop_msg_post(iop, im, mb, 0)) != 0) {
962: iop_msg_unmap(iop, im);
963: iop_msg_free(iop, im);
964: }
965: }
966: break;
967: }
968: return (0);
969: }
970:
971: void
972: ioprbs_timeout(arg)
973: void *arg;
974: {
975: struct ioprbs_ccb *ccb = arg;
976: struct scsi_link *link = ccb->ic_xs->sc_link;
977: struct ioprbs_softc *sc = link->adapter_softc;
978: ioprbs_lock_t lock;
979:
980: sc_print_addr(link);
981: printf("timed out\n");
982:
983: /* XXX Test for multiple timeouts */
984:
985: ccb->ic_xs->error = XS_TIMEOUT;
986: lock = IOPRBS_LOCK(sc);
987: ioprbs_enqueue_ccb(sc, ccb);
988: IOPRBS_UNLOCK(sc, lock);
989: }
990:
991: void
992: ioprbs_watchdog(arg)
993: void *arg;
994: {
995: struct ioprbs_ccb *ccb = arg;
996: struct scsi_link *link = ccb->ic_xs->sc_link;
997: struct ioprbs_softc *sc = link->adapter_softc;
998: ioprbs_lock_t lock;
999:
1000: lock = IOPRBS_LOCK(sc);
1001: ccb->ic_flags &= ~IOPRBS_ICF_WATCHDOG;
1002: ioprbs_start_ccbs(sc);
1003: IOPRBS_UNLOCK(sc, lock);
1004: }
CVSweb