Annotation of sys/dev/isa/wds.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: wds.c,v 1.23 2006/11/28 23:59:45 dlg Exp $ */
2: /* $NetBSD: wds.c,v 1.13 1996/11/03 16:20:31 mycroft Exp $ */
3:
4: #undef WDSDIAG
5: #ifdef DDB
6: #define integrate
7: #else
8: #define integrate static inline
9: #endif
10:
11: /*
12: * XXX
13: * sense data
14: * aborts
15: * resets
16: */
17:
18: /*
19: * Copyright (c) 1994, 1995 Julian Highfield. All rights reserved.
20: * Portions copyright (c) 1994, 1996 Charles M. Hannum. All rights reserved.
21: *
22: * Redistribution and use in source and binary forms, with or without
23: * modification, are permitted provided that the following conditions
24: * are met:
25: * 1. Redistributions of source code must retain the above copyright
26: * notice, this list of conditions and the following disclaimer.
27: * 2. Redistributions in binary form must reproduce the above copyright
28: * notice, this list of conditions and the following disclaimer in the
29: * documentation and/or other materials provided with the distribution.
30: * 3. All advertising materials mentioning features or use of this software
31: * must display the following acknowledgement:
32: * This product includes software developed by Julian Highfield.
33: * 4. The name of the author may not be used to endorse or promote products
34: * derived from this software without specific prior written permission.
35: *
36: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
37: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
38: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
39: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
40: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
41: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
42: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
43: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
44: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
45: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
46: */
47:
48: /*
49: * This driver is for the WD7000 family of SCSI controllers:
50: * the WD7000-ASC, a bus-mastering DMA controller,
51: * the WD7000-FASST2, an -ASC with new firmware and scatter-gather,
52: * and the WD7000-ASE, which was custom manufactured for Apollo
53: * workstations and seems to include an -ASC as well as floppy
54: * and ESDI interfaces.
55: *
56: * Loosely based on Theo Deraadt's unfinished attempt says the NetBSD group
57: * so they decided to delete the copyright that file had on it.
58: */
59:
60: #include <sys/types.h>
61: #include <sys/param.h>
62: #include <sys/systm.h>
63: #include <sys/kernel.h>
64: #include <sys/errno.h>
65: #include <sys/ioctl.h>
66: #include <sys/device.h>
67: #include <sys/malloc.h>
68: #include <sys/buf.h>
69: #include <sys/proc.h>
70: #include <sys/user.h>
71:
72: #include <machine/bus.h>
73: #include <machine/intr.h>
74:
75: #include <scsi/scsi_all.h>
76: #include <scsi/scsiconf.h>
77:
78: #include <dev/isa/isavar.h>
79: #include <dev/isa/isadmavar.h>
80: #include <dev/isa/wdsreg.h>
81:
82: #ifndef DDB
83: #define Debugger() panic("should call debugger here (wds.c)")
84: #endif /* ! DDB */
85:
86: #define WDS_MBX_SIZE 16
87:
88: #define WDS_SCB_MAX 32
89: #define SCB_HASH_SIZE 32 /* hash table size for phystokv */
90: #define SCB_HASH_SHIFT 9
91: #define SCB_HASH(x) ((((long)(x))>>SCB_HASH_SHIFT) & (SCB_HASH_SIZE - 1))
92:
93: #define wds_nextmbx(wmb, mbx, mbio) \
94: if ((wmb) == &(mbx)->mbio[WDS_MBX_SIZE - 1]) \
95: (wmb) = &(mbx)->mbio[0]; \
96: else \
97: (wmb)++;
98:
99: struct wds_mbx {
100: struct wds_mbx_out mbo[WDS_MBX_SIZE];
101: struct wds_mbx_in mbi[WDS_MBX_SIZE];
102: struct wds_mbx_out *cmbo; /* Collection Mail Box out */
103: struct wds_mbx_out *tmbo; /* Target Mail Box out */
104: struct wds_mbx_in *tmbi; /* Target Mail Box in */
105: };
106:
107: #define KVTOPHYS(x) vtophys((vaddr_t)(x))
108:
109: struct wds_softc {
110: struct device sc_dev;
111: struct isadev sc_id;
112: void *sc_ih;
113:
114: bus_space_tag_t sc_iot; /* bus identifier */
115: bus_space_handle_t sc_ioh; /* io handle */
116: int sc_irq, sc_drq;
117:
118: int sc_revision;
119:
120: struct wds_mbx sc_mbx;
121: #define wmbx (&sc->sc_mbx)
122: struct wds_scb *sc_scbhash[SCB_HASH_SIZE];
123: TAILQ_HEAD(, wds_scb) sc_free_scb, sc_waiting_scb;
124: int sc_numscbs, sc_mbofull;
125: int sc_scsi_dev;
126: struct scsi_link sc_link; /* prototype for subdevs */
127: };
128:
129: /* Define the bounce buffer length... */
130: #define BUFLEN (64*1024)
131: /* ..and how many there are. One per device! Non-FASST boards need these. */
132: #define BUFCNT 8
133: /* The macro for deciding whether the board needs a buffer. */
134: #define NEEDBUFFER(sc) (sc->sc_revision < 0x800)
135:
136: struct wds_buf {
137: u_char data[BUFLEN];
138: int busy;
139: TAILQ_ENTRY(wds_buf) chain;
140: } wds_buffer[BUFCNT];
141:
142: TAILQ_HEAD(, wds_buf) wds_free_buffer;
143:
144: #ifdef WDSDEBUG
145: int wds_debug = WDSDEBUG;
146: #endif
147:
148: integrate void wds_wait(bus_space_tag_t, bus_space_handle_t, int, int, int);
149: int wds_cmd(struct wds_softc *, u_char *, int);
150: integrate void wds_finish_scbs(struct wds_softc *);
151: int wdsintr(void *);
152: integrate void wds_reset_scb(struct wds_softc *, struct wds_scb *);
153: void wds_free_scb(struct wds_softc *, struct wds_scb *);
154: void wds_free_buf(struct wds_softc *, struct wds_buf *);
155: integrate void wds_init_scb(struct wds_softc *, struct wds_scb *);
156: struct wds_scb *wds_get_scb(struct wds_softc *, int, int);
157: struct wds_buf *wds_get_buf(struct wds_softc *, int);
158: struct wds_scb *wds_scb_phys_kv(struct wds_softc *, u_long);
159: void wds_queue_scb(struct wds_softc *, struct wds_scb *);
160: void wds_collect_mbo(struct wds_softc *);
161: void wds_start_scbs(struct wds_softc *);
162: void wds_done(struct wds_softc *, struct wds_scb *, u_char);
163: int wds_find(struct isa_attach_args *, struct wds_softc *);
164: void wds_init(struct wds_softc *);
165: void wds_inquire_setup_information(struct wds_softc *);
166: void wdsminphys(struct buf *);
167: int wds_scsi_cmd(struct scsi_xfer *);
168: void wds_sense(struct wds_softc *, struct wds_scb *);
169: int wds_poll(struct wds_softc *, struct scsi_xfer *, int);
170: int wds_ipoll(struct wds_softc *, struct wds_scb *, int);
171: void wds_timeout(void *);
172: int wdsprint(void *, const char *);
173:
174: struct scsi_adapter wds_switch = {
175: wds_scsi_cmd,
176: wdsminphys,
177: 0,
178: 0,
179: };
180:
181: /* the below structure is so we have a default dev struct for our link struct */
182: struct scsi_device wds_dev = {
183: NULL, /* Use default error handler */
184: NULL, /* have a queue, served by this */
185: NULL, /* have no async handler */
186: NULL, /* Use default 'done' routine */
187: };
188:
189: int wdsprobe(struct device *, void *, void *);
190: void wdsattach(struct device *, struct device *, void *);
191:
192: struct cfattach wds_ca = {
193: sizeof(struct wds_softc), wdsprobe, wdsattach
194: };
195:
196: struct cfdriver wds_cd = {
197: NULL, "wds", DV_DULL
198: };
199:
200: #define WDS_ABORT_TIMEOUT 2000 /* time to wait for abort (mSec) */
201:
202: integrate void
203: wds_wait(iot, ioh, port, mask, val)
204: bus_space_tag_t iot;
205: bus_space_handle_t ioh;
206: int port;
207: int mask;
208: int val;
209: {
210: while ((bus_space_read_1(iot, ioh, port) & mask) != val)
211: ;
212: }
213:
214: /*
215: * Write a command to the board's I/O ports.
216: */
217: int
218: wds_cmd(sc, ibuf, icnt)
219: struct wds_softc *sc;
220: u_int8_t *ibuf;
221: int icnt;
222: {
223: bus_space_tag_t iot = sc->sc_iot;
224: bus_space_handle_t ioh = sc->sc_ioh;
225: u_int8_t c;
226:
227: wds_wait(iot, ioh, WDS_STAT, WDSS_RDY, WDSS_RDY);
228:
229: while (icnt--) {
230: bus_space_write_1(iot, ioh, WDS_CMD, *ibuf++);
231: wds_wait(iot, ioh, WDS_STAT, WDSS_RDY, WDSS_RDY);
232: c = bus_space_read_1(iot, ioh, WDS_STAT);
233: if (c & WDSS_REJ)
234: return 1;
235: }
236:
237: return 0;
238: }
239:
240: /*
241: * Check for the presence of a WD7000 SCSI controller.
242: */
243: int
244: wdsprobe(parent, match, aux)
245: struct device *parent;
246: void *match, *aux;
247: {
248: register struct isa_attach_args *ia = aux;
249: bus_space_tag_t iot = ia->ia_iot;
250: bus_space_handle_t ioh;
251: int rv;
252:
253: if (bus_space_map(iot, ia->ia_iobase, WDS_IO_PORTS, 0, &ioh))
254: return (0);
255:
256: /* See if there is a unit at this location. */
257: rv = wds_find(ia, NULL);
258:
259: bus_space_unmap(iot, ioh, WDS_IO_PORTS);
260:
261: if (rv) {
262: ia->ia_msize = 0;
263: ia->ia_iosize = WDS_IO_PORTS;
264: }
265:
266: return (rv);
267: }
268:
269: int
270: wdsprint(aux, name)
271: void *aux;
272: const char *name;
273: {
274:
275: if (name != NULL)
276: printf("%s: scsibus ", name);
277: return UNCONF;
278: }
279:
280: /*
281: * Attach all available units.
282: */
283: void
284: wdsattach(parent, self, aux)
285: struct device *parent, *self;
286: void *aux;
287: {
288: struct isa_attach_args *ia = aux;
289: struct wds_softc *sc = (void *)self;
290: struct scsibus_attach_args saa;
291: bus_space_tag_t iot = ia->ia_iot;
292: bus_space_handle_t ioh;
293:
294: if (bus_space_map(iot, ia->ia_iobase, WDS_IO_PORTS, 0, &ioh)) {
295: printf("%s: can't map i/o space\n", sc->sc_dev.dv_xname);
296: return;
297: }
298:
299: if (!wds_find(ia, sc))
300: panic("wdsattach: wds_find of %s failed", self->dv_xname);
301: wds_init(sc);
302:
303: if (sc->sc_drq != DRQUNK)
304: isadma_cascade(sc->sc_drq);
305:
306: TAILQ_INIT(&sc->sc_free_scb);
307: TAILQ_INIT(&sc->sc_waiting_scb);
308: wds_inquire_setup_information(sc);
309:
310: /*
311: * fill in the prototype scsi_link.
312: */
313: #ifdef notyet
314: sc->sc_link.channel = SCSI_CHANNEL_ONLY_ONE;
315: #endif
316: sc->sc_link.adapter_softc = sc;
317: sc->sc_link.adapter_target = sc->sc_scsi_dev;
318: sc->sc_link.adapter = &wds_switch;
319: sc->sc_link.device = &wds_dev;
320: /* XXX */
321: /* I don't think the -ASE can handle openings > 1. */
322: /* It gives Vendor Error 26 whenever I try it. */
323: sc->sc_link.openings = 1;
324:
325: sc->sc_ih = isa_intr_establish(ia->ia_ic, sc->sc_irq, IST_EDGE,
326: IPL_BIO, wdsintr, sc, sc->sc_dev.dv_xname);
327:
328: bzero(&saa, sizeof(saa));
329: saa.saa_sc_link = &sc->sc_link;
330:
331: /*
332: * ask the adapter what subunits are present
333: */
334: config_found(self, &saa, wdsprint);
335: }
336:
337: integrate void
338: wds_finish_scbs(sc)
339: struct wds_softc *sc;
340: {
341: struct wds_mbx_in *wmbi;
342: struct wds_scb *scb;
343: int i;
344:
345: wmbi = wmbx->tmbi;
346:
347: if (wmbi->stat == WDS_MBI_FREE) {
348: for (i = 0; i < WDS_MBX_SIZE; i++) {
349: if (wmbi->stat != WDS_MBI_FREE) {
350: printf("%s: mbi not in round-robin order\n",
351: sc->sc_dev.dv_xname);
352: goto AGAIN;
353: }
354: wds_nextmbx(wmbi, wmbx, mbi);
355: }
356: #ifdef WDSDIAGnot
357: printf("%s: mbi interrupt with no full mailboxes\n",
358: sc->sc_dev.dv_xname);
359: #endif
360: return;
361: }
362:
363: AGAIN:
364: do {
365: scb = wds_scb_phys_kv(sc, phystol(wmbi->scb_addr));
366: if (!scb) {
367: printf("%s: bad mbi scb pointer; skipping\n",
368: sc->sc_dev.dv_xname);
369: goto next;
370: }
371:
372: #ifdef WDSDEBUG
373: if (wds_debug) {
374: u_int8_t *cp = (u_int8_t *)&scb->cmd.scb;
375: printf("op=%x %x %x %x %x %x\n",
376: cp[0], cp[1], cp[2], cp[3], cp[4], cp[5]);
377: printf("stat %x for mbi addr = 0x%08x, ",
378: wmbi->stat, wmbi);
379: printf("scb addr = 0x%x\n", scb);
380: }
381: #endif /* WDSDEBUG */
382:
383: timeout_del(&scb->xs->stimeout);
384: #ifdef notyet
385: isadma_copyfrombuf((caddr_t)scb, SCB_PHYS_SIZE,
386: 1, scb->scb_phys);
387: #endif
388: wds_done(sc, scb, wmbi->stat);
389:
390: next:
391: wmbi->stat = WDS_MBI_FREE;
392: wds_nextmbx(wmbi, wmbx, mbi);
393: } while (wmbi->stat != WDS_MBI_FREE);
394:
395: wmbx->tmbi = wmbi;
396: }
397:
398: /*
399: * Process an interrupt.
400: */
401: int
402: wdsintr(arg)
403: void *arg;
404: {
405: struct wds_softc *sc = arg;
406: bus_space_tag_t iot = sc->sc_iot;
407: bus_space_handle_t ioh = sc->sc_ioh;
408: u_char c;
409:
410: /* Was it really an interrupt from the board? */
411: if ((bus_space_read_1(iot, ioh, WDS_STAT) & WDSS_IRQ) == 0)
412: return 0;
413:
414: /* Get the interrupt status byte. */
415: c = bus_space_read_1(iot, ioh, WDS_IRQSTAT) & WDSI_MASK;
416:
417: /* Acknowledge (which resets) the interrupt. */
418: bus_space_write_1(iot, ioh, WDS_IRQACK, 0x00);
419:
420: switch (c) {
421: case WDSI_MSVC:
422: wds_finish_scbs(sc);
423: break;
424:
425: case WDSI_MFREE:
426: wds_start_scbs(sc);
427: break;
428:
429: default:
430: printf("%s: unrecognized interrupt type %02x",
431: sc->sc_dev.dv_xname, c);
432: break;
433: }
434:
435: return 1;
436: }
437:
438: integrate void
439: wds_reset_scb(sc, scb)
440: struct wds_softc *sc;
441: struct wds_scb *scb;
442: {
443:
444: scb->flags = 0;
445: }
446:
447: /*
448: * Free the command structure, the outgoing mailbox and the data buffer.
449: */
450: void
451: wds_free_scb(sc, scb)
452: struct wds_softc *sc;
453: struct wds_scb *scb;
454: {
455: int s;
456:
457: if (scb->buf != 0) {
458: wds_free_buf(sc, scb->buf);
459: scb->buf = 0;
460: }
461:
462: s = splbio();
463:
464: #ifdef notyet
465: if (scb->scb_phys[0].addr)
466: isadma_unmap((caddr_t)scb, SCB_PHYS_SIZE, 1, scb->scb_phys);
467: #endif
468:
469: wds_reset_scb(sc, scb);
470: TAILQ_INSERT_HEAD(&sc->sc_free_scb, scb, chain);
471:
472: /*
473: * If there were none, wake anybody waiting for one to come free,
474: * starting with queued entries.
475: */
476: if (TAILQ_NEXT(scb, chain) == NULL)
477: wakeup(&sc->sc_free_scb);
478:
479: splx(s);
480: }
481:
482: void
483: wds_free_buf(sc, buf)
484: struct wds_softc *sc;
485: struct wds_buf *buf;
486: {
487: int s;
488:
489: s = splbio();
490:
491: buf->busy = 0;
492: TAILQ_INSERT_HEAD(&wds_free_buffer, buf, chain);
493:
494: /*
495: * If there were none, wake anybody waiting for one to come free,
496: * starting with queued entries.
497: */
498: if (TAILQ_NEXT(buf, chain) == NULL)
499: wakeup(&wds_free_buffer);
500:
501: splx(s);
502: }
503:
504: integrate void
505: wds_init_scb(sc, scb)
506: struct wds_softc *sc;
507: struct wds_scb *scb;
508: {
509: int hashnum;
510:
511: bzero(scb, sizeof(struct wds_scb));
512: /*
513: * put in the phystokv hash table
514: * Never gets taken out.
515: */
516: scb->hashkey = KVTOPHYS(scb);
517: hashnum = SCB_HASH(scb->hashkey);
518: scb->nexthash = sc->sc_scbhash[hashnum];
519: sc->sc_scbhash[hashnum] = scb;
520: wds_reset_scb(sc, scb);
521: }
522:
523: /*
524: * Get a free scb
525: *
526: * If there are none, see if we can allocate a new one. If so, put it in
527: * the hash table too otherwise either return an error or sleep.
528: */
529: struct wds_scb *
530: wds_get_scb(sc, flags, needbuffer)
531: struct wds_softc *sc;
532: int flags;
533: int needbuffer;
534: {
535: struct wds_scb *scb;
536: int s;
537: #ifdef notyet
538: int mflags, hashnum;
539: #endif
540:
541: s = splbio();
542:
543: #ifdef notyet
544: if (flags & SCSI_NOSLEEP)
545: mflags = ISADMA_MAP_BOUNCE;
546: else
547: mflags = ISADMA_MAP_BOUNCE | ISADMA_MAP_WAITOK;
548: #endif
549:
550: /*
551: * If we can and have to, sleep waiting for one to come free
552: * but only if we can't allocate a new one.
553: */
554: for (;;) {
555: scb = TAILQ_FIRST(&sc->sc_free_scb);
556: if (scb) {
557: TAILQ_REMOVE(&sc->sc_free_scb, scb, chain);
558: break;
559: }
560: if (sc->sc_numscbs < WDS_SCB_MAX) {
561: scb = (struct wds_scb *) malloc(sizeof(struct wds_scb),
562: M_TEMP, M_NOWAIT);
563: if (!scb) {
564: printf("%s: can't malloc scb\n",
565: sc->sc_dev.dv_xname);
566: goto out;
567: }
568: wds_init_scb(sc, scb);
569: sc->sc_numscbs++;
570: break;
571: }
572: if ((flags & SCSI_NOSLEEP) != 0)
573: goto out;
574: tsleep(&sc->sc_free_scb, PRIBIO, "wdsscb", 0);
575: }
576:
577: scb->flags |= SCB_ALLOC;
578:
579: #ifdef notyet
580: if (isadma_map((caddr_t)scb, SCB_PHYS_SIZE, scb->scb_phys,
581: mflags | ISADMA_MAP_CONTIG) == 1) {
582: hashnum = SCB_HASH(scb->scb_phys[0].addr);
583: scb->nexthash = sc->sc_scbhash[hashnum];
584: sc->sc_scbhash[hashnum] = ccb;
585: } else {
586: scb->scb_phys[0].addr = 0;
587: wds_free_scb(sc, scb);
588: scb = 0;
589: }
590: #else
591: if (needbuffer) {
592: scb->buf = wds_get_buf(sc, flags);
593: if (scb->buf == 0) {
594: wds_free_scb(sc, scb);
595: scb = 0;
596: }
597: }
598: #endif
599:
600:
601: out:
602: splx(s);
603: return (scb);
604: }
605:
606: struct wds_buf *
607: wds_get_buf(sc, flags)
608: struct wds_softc *sc;
609: int flags;
610: {
611: struct wds_buf *buf;
612: int s;
613:
614: s = splbio();
615:
616: for (;;) {
617: buf = TAILQ_FIRST(&wds_free_buffer);
618: if (buf) {
619: TAILQ_REMOVE(&wds_free_buffer, buf, chain);
620: break;
621: }
622: if ((flags & SCSI_NOSLEEP) != 0)
623: goto out;
624: tsleep(&wds_free_buffer, PRIBIO, "wdsbuf", 0);
625: }
626:
627: buf->busy = 1;
628:
629: out:
630: splx(s);
631: return (buf);
632: }
633:
634: struct wds_scb *
635: wds_scb_phys_kv(sc, scb_phys)
636: struct wds_softc *sc;
637: u_long scb_phys;
638: {
639: int hashnum = SCB_HASH(scb_phys);
640: struct wds_scb *scb = sc->sc_scbhash[hashnum];
641:
642: while (scb) {
643: if (scb->hashkey == scb_phys)
644: break;
645: /* XXX Check to see if it matches the sense command block. */
646: if (scb->hashkey == (scb_phys - sizeof(struct wds_cmd)))
647: break;
648: scb = scb->nexthash;
649: }
650: return scb;
651: }
652:
653: /*
654: * Queue a SCB to be sent to the controller, and send it if possible.
655: */
656: void
657: wds_queue_scb(sc, scb)
658: struct wds_softc *sc;
659: struct wds_scb *scb;
660: {
661:
662: TAILQ_INSERT_TAIL(&sc->sc_waiting_scb, scb, chain);
663: wds_start_scbs(sc);
664: }
665:
666: /*
667: * Garbage collect mailboxes that are no longer in use.
668: */
669: void
670: wds_collect_mbo(sc)
671: struct wds_softc *sc;
672: {
673: struct wds_mbx_out *wmbo; /* Mail Box Out pointer */
674: #ifdef WDSDIAG
675: struct wds_scb *scb;
676: #endif
677:
678: wmbo = wmbx->cmbo;
679:
680: while (sc->sc_mbofull > 0) {
681: if (wmbo->cmd != WDS_MBO_FREE)
682: break;
683:
684: #ifdef WDSDIAG
685: scb = wds_scb_phys_kv(sc, phystol(wmbo->scb_addr));
686: scb->flags &= ~SCB_SENDING;
687: #endif
688:
689: --sc->sc_mbofull;
690: wds_nextmbx(wmbo, wmbx, mbo);
691: }
692:
693: wmbx->cmbo = wmbo;
694: }
695:
696: /*
697: * Send as many SCBs as we have empty mailboxes for.
698: */
699: void
700: wds_start_scbs(sc)
701: struct wds_softc *sc;
702: {
703: struct wds_mbx_out *wmbo; /* Mail Box Out pointer */
704: struct wds_scb *scb;
705: u_char c;
706:
707: wmbo = wmbx->tmbo;
708:
709: while ((scb = TAILQ_FIRST(&sc->sc_waiting_scb)) != NULL) {
710: if (sc->sc_mbofull >= WDS_MBX_SIZE) {
711: wds_collect_mbo(sc);
712: if (sc->sc_mbofull >= WDS_MBX_SIZE) {
713: c = WDSC_IRQMFREE;
714: wds_cmd(sc, &c, sizeof c);
715: break;
716: }
717: }
718:
719: TAILQ_REMOVE(&sc->sc_waiting_scb, scb, chain);
720: #ifdef WDSDIAG
721: scb->flags |= SCB_SENDING;
722: #endif
723:
724: /* Link scb to mbo. */
725: #ifdef notyet
726: isadma_copytobuf((caddr_t)scb, SCB_PHYS_SIZE,
727: 1, scb->scb_phys);
728: ltophys(scb->scb_phys[0].addr, wmbo->scb_addr);
729: #else
730: if (scb->flags & SCB_SENSE)
731: ltophys(KVTOPHYS(&scb->sense), wmbo->scb_addr);
732: else
733: ltophys(KVTOPHYS(&scb->cmd), wmbo->scb_addr);
734: #endif
735: /* XXX What about aborts? */
736: wmbo->cmd = WDS_MBO_START;
737:
738: /* Tell the card to poll immediately. */
739: c = WDSC_MSTART(wmbo - wmbx->mbo);
740: wds_cmd(sc, &c, sizeof c);
741:
742: if ((scb->flags & SCB_POLLED) == 0) {
743: timeout_set(&scb->xs->stimeout, wds_timeout, scb);
744: timeout_add(&scb->xs->stimeout, (scb->timeout * hz) / 1000);
745: }
746:
747: ++sc->sc_mbofull;
748: wds_nextmbx(wmbo, wmbx, mbo);
749: }
750:
751: wmbx->tmbo = wmbo;
752: }
753:
754: /*
755: * Process the result of a SCSI command.
756: */
757: void
758: wds_done(sc, scb, stat)
759: struct wds_softc *sc;
760: struct wds_scb *scb;
761: u_int8_t stat;
762: {
763: struct scsi_xfer *xs = scb->xs;
764:
765: /* XXXXX */
766:
767: /* Don't release the SCB if it was an internal command. */
768: if (xs == 0) {
769: scb->flags |= SCB_DONE;
770: return;
771: }
772:
773: /* Sense handling. */
774: if (xs->error == XS_SENSE) {
775: bcopy(&scb->sense_data, &xs->sense, sizeof (struct scsi_sense_data));
776: } else {
777: if (xs->error == XS_NOERROR) {
778: /* If all went well, or an error is acceptable. */
779: if (stat == WDS_MBI_OK) {
780: /* OK, set the result */
781: xs->resid = 0;
782: } else {
783: /* Check the mailbox status. */
784: switch (stat) {
785: case WDS_MBI_OKERR:
786: /* SCSI error recorded in scb, counts as WDS_MBI_OK */
787: switch (scb->cmd.venderr) {
788: case 0x00:
789: printf("%s: Is this an error?\n", sc->sc_dev.dv_xname);
790: xs->error = XS_DRIVER_STUFFUP; /* Experiment */
791: break;
792: case 0x01:
793: /*printf("%s: OK, see SCSI error field.\n", sc->sc_dev.dv_xname);*/
794: if (scb->cmd.stat == SCSI_CHECK) {
795: /* Do sense. */
796: wds_sense (sc, scb);
797: return;
798: } else if (scb->cmd.stat == SCSI_BUSY) {
799: xs->error = XS_BUSY;
800: }
801: break;
802: case 0x40:
803: /*printf("%s: DMA underrun!\n", sc->sc_dev.dv_xname);*/
804: /* Hits this if the target returns fewer that datalen bytes (eg my CD-ROM,
805: which returns a short version string, or if DMA is turned off etc. */
806: xs->resid = 0;
807: break;
808: default:
809: printf("%s: VENDOR ERROR %02x, scsi %02x\n", sc->sc_dev.dv_xname, scb->cmd.venderr, scb->cmd.stat);
810: xs->error = XS_DRIVER_STUFFUP; /* Experiment */
811: break;
812: }
813: break;
814: case WDS_MBI_ETIME:
815: /*
816: * The documentation isn't clear on
817: * what conditions might generate this,
818: * but selection timeouts are the only
819: * one I can think of.
820: */
821: xs->error = XS_SELTIMEOUT;
822: break;
823: case WDS_MBI_ERESET:
824: case WDS_MBI_ETARCMD:
825: case WDS_MBI_ERESEL:
826: case WDS_MBI_ESEL:
827: case WDS_MBI_EABORT:
828: case WDS_MBI_ESRESET:
829: case WDS_MBI_EHRESET:
830: xs->error = XS_DRIVER_STUFFUP;
831: break;
832: }
833: }
834: } /* else sense */
835:
836: if (NEEDBUFFER(sc) && xs->datalen) {
837: if (xs->flags & SCSI_DATA_IN)
838: bcopy(scb->buf->data, xs->data, xs->datalen);
839: }
840: } /* XS_NOERROR */
841:
842: #ifdef notyet
843: if (scb->data_nseg) {
844: if (xs->flags & SCSI_DATA_IN)
845: isadma_copyfrombuf(xs->data, xs->datalen,
846: scb->data_nseg, scb->data_phys);
847: isadma_unmap(xs->data, xs->datalen,
848: scb->data_nseg, scb->data_phys);
849: }
850: #endif
851: wds_free_scb(sc, scb);
852: xs->flags |= ITSDONE;
853: scsi_done(xs);
854: }
855:
856: int
857: wds_find(ia, sc)
858: struct isa_attach_args *ia;
859: struct wds_softc *sc;
860: {
861: bus_space_tag_t iot = ia->ia_iot;
862: bus_space_handle_t ioh;
863: u_char c;
864: int i;
865:
866: /*
867: * Sending a command causes the CMDRDY bit to clear.
868: */
869: c = bus_space_read_1(iot, ioh, WDS_STAT);
870: for (i = 0; i < 4; i++)
871: if ((bus_space_read_1(iot, ioh, WDS_STAT) & WDSS_RDY) != 0) {
872: goto ready;
873: delay(10);
874: }
875: return (0);
876:
877: ready:
878: bus_space_write_1(iot, ioh, WDS_CMD, WDSC_NOOP);
879: if (bus_space_read_1(iot, ioh, WDS_STAT) & WDSS_RDY)
880: return (0);
881:
882: bus_space_write_1(iot, ioh, WDS_HCR, WDSH_SCSIRESET|WDSH_ASCRESET);
883: delay(10000);
884: bus_space_write_1(iot, ioh, WDS_HCR, 0x00);
885: delay(500000);
886: wds_wait(iot, ioh, WDS_STAT, WDSS_RDY, WDSS_RDY);
887: if (bus_space_read_1(iot, ioh, WDS_IRQSTAT) != 1)
888: if (bus_space_read_1(iot, ioh, WDS_IRQSTAT) != 7)
889: printf("%s: failed reset!!! %2x\n",
890: sc ? sc->sc_dev.dv_xname : "wds?",
891: bus_space_read_1(iot, ioh, WDS_IRQSTAT));
892:
893: if ((bus_space_read_1(iot, ioh, WDS_STAT) & (WDSS_RDY)) != WDSS_RDY) {
894: printf("%s: waiting for controller to become ready.",
895: sc ? sc->sc_dev.dv_xname : "wds?");
896: for (i = 0; i < 20; i++) {
897: if ((bus_space_read_1(iot, ioh, WDS_STAT) &
898: (WDSS_RDY)) == WDSS_RDY)
899: break;
900: printf(".");
901: delay(10000);
902: }
903: if ((bus_space_read_1(iot, ioh, WDS_STAT) & (WDSS_RDY)) !=
904: WDSS_RDY) {
905: printf(" failed\n");
906: return (0);
907: }
908: printf("\n");
909: }
910:
911: if (sc != NULL) {
912: /* XXX Can we do this better? */
913: /* who are we on the scsi bus? */
914: sc->sc_scsi_dev = 7;
915:
916: sc->sc_iot = iot;
917: sc->sc_ioh = ioh;
918: sc->sc_irq = ia->ia_irq;
919: sc->sc_drq = ia->ia_drq;
920: }
921:
922: return (1);
923: }
924:
925: /*
926: * Initialise the board and driver.
927: */
928: void
929: wds_init(sc)
930: struct wds_softc *sc;
931: {
932: bus_space_tag_t iot = sc->sc_iot;
933: bus_space_handle_t ioh = sc->sc_ioh;
934: struct wds_setup init;
935: u_char c;
936: int i;
937: #ifdef notyet
938: struct isadma_seg mbx_phys[1];
939: #endif
940:
941: /*
942: * Set up initial mail box for round-robin operation.
943: */
944: for (i = 0; i < WDS_MBX_SIZE; i++) {
945: wmbx->mbo[i].cmd = WDS_MBO_FREE;
946: wmbx->mbi[i].stat = WDS_MBI_FREE;
947: }
948: wmbx->cmbo = wmbx->tmbo = &wmbx->mbo[0];
949: wmbx->tmbi = &wmbx->mbi[0];
950: sc->sc_mbofull = 0;
951:
952: /* Clear the buffers. */
953: TAILQ_INIT(&wds_free_buffer);
954: for (i = 0; i < BUFCNT; i++) {
955: wds_buffer[i].busy = 0;
956: TAILQ_INSERT_HEAD(&wds_free_buffer, &wds_buffer[i], chain);
957: }
958:
959: init.opcode = WDSC_INIT;
960: init.scsi_id = sc->sc_scsi_dev;
961: /* Record scsi id of controller for use in scsi_attach */
962: sc->sc_scsi_dev = init.scsi_id;
963: init.buson_t = 48;
964: init.busoff_t = 24;
965: init.xx = 0;
966: #ifdef notyet
967: if (isadma_map((caddr_t)(wmbx), sizeof(struct wds_mbx),
968: mbx_phys, ISADMA_MAP_CONTIG) != 1)
969: panic("wds_init: cannot map mail box");
970: ltophys(mbx_phys[0].addr, init.mbaddr);
971: #else
972: ltophys(KVTOPHYS(wmbx), init.mbaddr);
973: #endif
974: init.nomb = init.nimb = WDS_MBX_SIZE;
975: wds_cmd(sc, (u_char *)&init, sizeof init);
976:
977: wds_wait(iot, ioh, WDS_STAT, WDSS_INIT, WDSS_INIT);
978:
979: c = WDSC_DISUNSOL;
980: wds_cmd(sc, &c, sizeof c);
981:
982: bus_space_write_1(iot, ioh, WDS_HCR, WDSH_DRQEN);
983: }
984:
985: /*
986: * Read the board's firmware revision information.
987: */
988: void
989: wds_inquire_setup_information(sc)
990: struct wds_softc *sc;
991: {
992: struct wds_scb *scb;
993: u_char *j;
994: int s;
995:
996: if ((scb = wds_get_scb(sc, SCSI_NOSLEEP, 0)) == NULL) {
997: printf("%s: no request slot available in getvers()!\n",
998: sc->sc_dev.dv_xname);
999: return;
1000: }
1001: scb->xs = NULL;
1002: scb->timeout = 40;
1003:
1004: bzero(&scb->cmd, sizeof scb->cmd);
1005: scb->cmd.write = 0x80;
1006: scb->cmd.opcode = WDSX_GETFIRMREV;
1007:
1008: /* Will poll card, await result. */
1009: bus_space_write_1(sc->sc_iot, sc->sc_ioh, WDS_HCR, WDSH_DRQEN);
1010: scb->flags |= SCB_POLLED;
1011:
1012: s = splbio();
1013: wds_queue_scb(sc, scb);
1014: splx(s);
1015:
1016: if (wds_ipoll(sc, scb, scb->timeout))
1017: goto out;
1018:
1019: /* Print the version number. */
1020: printf(": version %x.%02x ", scb->cmd.targ, scb->cmd.scb.opcode);
1021: sc->sc_revision = (scb->cmd.targ << 8) | scb->cmd.scb.opcode;
1022: /* Print out the version string. */
1023: j = 2 + &(scb->cmd.targ);
1024: while ((*j >= 32) && (*j < 128)) {
1025: printf("%c", *j);
1026: j++;
1027: }
1028:
1029: out:
1030: printf("\n");
1031: wds_free_scb(sc, scb);
1032: }
1033:
1034: void
1035: wdsminphys(bp)
1036: struct buf *bp;
1037: {
1038: if (bp->b_bcount > ((WDS_NSEG - 1) << PGSHIFT))
1039: bp->b_bcount = ((WDS_NSEG - 1) << PGSHIFT);
1040: minphys(bp);
1041: }
1042:
1043: /*
1044: * Send a SCSI command.
1045: */
1046: int
1047: wds_scsi_cmd(xs)
1048: struct scsi_xfer *xs;
1049: {
1050: struct scsi_link *sc_link = xs->sc_link;
1051: struct wds_softc *sc = sc_link->adapter_softc;
1052: bus_space_tag_t iot = sc->sc_iot;
1053: bus_space_handle_t ioh = sc->sc_ioh;
1054: struct wds_scb *scb;
1055: struct wds_scat_gath *sg;
1056: int seg;
1057: u_long thiskv, thisphys, nextphys;
1058: int bytes_this_seg, bytes_this_page, datalen, flags;
1059: #ifdef TFS
1060: struct iovec *iovp;
1061: #endif
1062: int s;
1063: #ifdef notyet
1064: int mflags;
1065: #endif
1066:
1067: if (xs->flags & SCSI_RESET) {
1068: /* XXX Fix me! */
1069: printf("%s: reset!\n", sc->sc_dev.dv_xname);
1070: wds_init(sc);
1071: return COMPLETE;
1072: }
1073:
1074: flags = xs->flags;
1075: #ifdef notyet
1076: if (flags & SCSI_NOSLEEP)
1077: mflags = ISADMA_MAP_BOUNCE;
1078: else
1079: mflags = ISADMA_MAP_BOUNCE | ISADMA_MAP_WAITOK;
1080: #endif
1081: if ((scb = wds_get_scb(sc, flags, NEEDBUFFER(sc))) == NULL) {
1082: return TRY_AGAIN_LATER;
1083: }
1084: scb->xs = xs;
1085: scb->timeout = xs->timeout;
1086:
1087: if (xs->flags & SCSI_DATA_UIO) {
1088: /* XXX Fix me! */
1089: /* Let's not worry about UIO. There isn't any code for the *
1090: * non-SG boards anyway! */
1091: printf("%s: UIO is untested and disabled!\n", sc->sc_dev.dv_xname);
1092: goto bad;
1093: }
1094:
1095: /* Zero out the command structure. */
1096: bzero(&scb->cmd, sizeof scb->cmd);
1097: bcopy(xs->cmd, &scb->cmd.scb, xs->cmdlen < 12 ? xs->cmdlen : 12);
1098:
1099: /* Set up some of the command fields. */
1100: scb->cmd.targ = (xs->sc_link->target << 5) | xs->sc_link->lun;
1101:
1102: /* NOTE: cmd.write may be OK as 0x40 (disable direction checking)
1103: * on boards other than the WD-7000V-ASE. Need this for the ASE:
1104: */
1105: scb->cmd.write = (xs->flags & SCSI_DATA_IN) ? 0x80 : 0x00;
1106:
1107: if (!NEEDBUFFER(sc) && xs->datalen) {
1108: sg = scb->scat_gath;
1109: seg = 0;
1110: #ifdef TFS
1111: if (flags & SCSI_DATA_UIO) {
1112: iovp = ((struct uio *)xs->data)->uio_iov;
1113: datalen = ((struct uio *)xs->data)->uio_iovcnt;
1114: xs->datalen = 0;
1115: while (datalen && seg < WDS_NSEG) {
1116: ltophys(iovp->iov_base, sg->seg_addr);
1117: ltophys(iovp->iov_len, sg->seg_len);
1118: xs->datalen += iovp->iov_len;
1119: SC_DEBUGN(sc_link, SDEV_DB4, ("UIO(0x%x@0x%x)",
1120: iovp->iov_len, iovp->iov_base));
1121: sg++;
1122: iovp++;
1123: seg++;
1124: datalen--;
1125: }
1126: } else
1127: #endif /* TFS */
1128: {
1129: /*
1130: * Set up the scatter-gather block.
1131: */
1132: SC_DEBUG(sc_link, SDEV_DB4,
1133: ("%d @0x%x:- ", xs->datalen, xs->data));
1134:
1135: #ifdef notyet
1136: scb->data_nseg = isadma_map(xs->data, xs->datalen,
1137: scb->data_phys, mflags);
1138: for (seg = 0; seg < scb->data_nseg; seg++) {
1139: ltophys(scb->data_phys[seg].addr,
1140: sg[seg].seg_addr);
1141: ltophys(scb->data_phys[seg].length,
1142: sg[seg].seg_len);
1143: }
1144: #else
1145: datalen = xs->datalen;
1146: thiskv = (int)xs->data;
1147: thisphys = KVTOPHYS(xs->data);
1148:
1149: while (datalen && seg < WDS_NSEG) {
1150: bytes_this_seg = 0;
1151:
1152: /* put in the base address */
1153: ltophys(thisphys, sg->seg_addr);
1154:
1155: SC_DEBUGN(sc_link, SDEV_DB4, ("0x%x", thisphys));
1156:
1157: /* do it at least once */
1158: nextphys = thisphys;
1159: while (datalen && thisphys == nextphys) {
1160: /*
1161: * This page is contiguous (physically)
1162: * with the last, just extend the
1163: * length
1164: */
1165: /* check it fits on the ISA bus */
1166: if (thisphys > 0xFFFFFF) {
1167: printf("%s: DMA beyond"
1168: " end of ISA\n",
1169: sc->sc_dev.dv_xname);
1170: goto bad;
1171: }
1172: /* how far to the end of the page */
1173: nextphys = (thisphys & ~PGOFSET) + NBPG;
1174: bytes_this_page = nextphys - thisphys;
1175: /**** or the data ****/
1176: bytes_this_page = min(bytes_this_page,
1177: datalen);
1178: bytes_this_seg += bytes_this_page;
1179: datalen -= bytes_this_page;
1180:
1181: /* get more ready for the next page */
1182: thiskv = (thiskv & ~PGOFSET) + NBPG;
1183: if (datalen)
1184: thisphys = KVTOPHYS(thiskv);
1185: }
1186: /*
1187: * next page isn't contiguous, finish the seg
1188: */
1189: SC_DEBUGN(sc_link, SDEV_DB4,
1190: ("(0x%x)", bytes_this_seg));
1191: ltophys(bytes_this_seg, sg->seg_len);
1192: sg++;
1193: seg++;
1194: #endif
1195: }
1196: }
1197: /* end of iov/kv decision */
1198: SC_DEBUGN(sc_link, SDEV_DB4, ("\n"));
1199: if (datalen) {
1200: /*
1201: * there's still data, must have run out of segs!
1202: */
1203: printf("%s: wds_scsi_cmd, more than %d dma segs\n",
1204: sc->sc_dev.dv_xname, WDS_NSEG);
1205: goto bad;
1206: }
1207: #ifdef notyet
1208: if (scb->data_nseg == 0) {
1209: printf("%s: wds_scsi_cmd, cannot map\n",
1210: sc->sc_dev.dv_xname);
1211: goto bad;
1212: } else if (flags & SCSI_DATA_OUT)
1213: isadma_copytobuf(xs->data, xs->datalen,
1214: scb->data_nseg, scb->data_phys);
1215: ltophys((unsigned)((struct wds_scb *)(scb->scb_phys[0].addr))->scat_gath,
1216: scb->data_addr);
1217: ltophys(scb->data_nseg * sizeof(struct wds_scat_gath),
1218: scb->data_length);
1219: #else
1220: scb->cmd.opcode = WDSX_SCSISG;
1221: ltophys(KVTOPHYS(scb->scat_gath), scb->cmd.data);
1222: ltophys(seg * sizeof(struct wds_scat_gath), scb->cmd.len);
1223: #endif
1224: } else if (xs->datalen > 0) {
1225: /* The board is an ASC or ASE. Do not use scatter/gather. */
1226: if (xs->datalen > BUFLEN) {
1227: printf("%s: wds_scsi_cmd, I/O too large for bounce buffer\n",
1228: sc->sc_dev.dv_xname);
1229: goto bad;
1230: }
1231: if (xs->flags & SCSI_DATA_OUT)
1232: bcopy(xs->data, scb->buf->data, xs->datalen);
1233: else
1234: bzero(scb->buf->data, xs->datalen);
1235: scb->cmd.opcode = WDSX_SCSICMD;
1236: ltophys(KVTOPHYS(scb->buf->data), scb->cmd.data);
1237: ltophys(xs->datalen, scb->cmd.len);
1238: } else {
1239: scb->cmd.opcode = WDSX_SCSICMD;
1240: ltophys(0, scb->cmd.data);
1241: ltophys(0, scb->cmd.len);
1242: }
1243:
1244: scb->cmd.stat = 0x00;
1245: scb->cmd.venderr = 0x00;
1246: ltophys(0, scb->cmd.link);
1247:
1248: /* XXX Do we really want to do this? */
1249: if (flags & SCSI_POLL) {
1250: /* Will poll card, await result. */
1251: bus_space_write_1(iot, ioh, WDS_HCR, WDSH_DRQEN);
1252: scb->flags |= SCB_POLLED;
1253: } else {
1254: /* Will send command, let interrupt routine handle result. */
1255: bus_space_write_1(iot, ioh, WDS_HCR, WDSH_IRQEN | WDSH_DRQEN);
1256: }
1257:
1258: s = splbio();
1259: wds_queue_scb(sc, scb);
1260:
1261: #ifdef notyet
1262: if (VOLATILE_XS(xs)) {
1263: while ((scb->xs->flags & ITSDONE) == 0) {
1264: tsleep(scb, PRIBIO, "wdswait", 0);
1265: }
1266: if (scb->data_nseg) {
1267: if (flags & SCSI_DATA_IN)
1268: isadma_copyfrombuf(xs->data, xs->datalen,
1269: scb->data_nseg, scb->data_phys);
1270: isadma_unmap(xs->data, xs->datalen,
1271: scb->data_nseg, scb->data_phys);
1272: }
1273: wds_free_scb(sc, scb);
1274: scsi_done(xs);
1275: splx(s);
1276: return COMPLETE;
1277: }
1278: #endif
1279: splx(s);
1280:
1281: if ((flags & SCSI_POLL) == 0)
1282: return SUCCESSFULLY_QUEUED;
1283:
1284: if (wds_poll(sc, xs, scb->timeout)) {
1285: wds_timeout(scb);
1286: if (wds_poll(sc, xs, scb->timeout))
1287: wds_timeout(scb);
1288: }
1289: return COMPLETE;
1290:
1291: bad:
1292: xs->error = XS_DRIVER_STUFFUP;
1293: wds_free_scb(sc, scb);
1294: return COMPLETE;
1295: }
1296:
1297: /*
1298: * Send a sense request.
1299: */
1300: void
1301: wds_sense(sc, scb)
1302: struct wds_softc *sc;
1303: struct wds_scb *scb;
1304: {
1305: struct scsi_xfer *xs = scb->xs;
1306: struct scsi_sense *ss = (void *)&scb->sense.scb;
1307: int s;
1308:
1309: /* XXXXX */
1310:
1311: /* Send sense request SCSI command. */
1312: xs->error = XS_SENSE;
1313: scb->flags |= SCB_SENSE;
1314:
1315: /* First, save the return values */
1316: if (NEEDBUFFER(sc) && xs->datalen) {
1317: if (xs->flags & SCSI_DATA_IN)
1318: bcopy(scb->buf->data, xs->data, xs->datalen);
1319: }
1320:
1321: /* Next, setup a request sense command block */
1322: bzero(ss, sizeof(*ss));
1323: ss->opcode = REQUEST_SENSE;
1324: ss->byte2 = xs->sc_link->lun << 5;
1325: ss->length = sizeof(struct scsi_sense_data);
1326:
1327: /* Set up some of the command fields. */
1328: scb->sense.targ = scb->cmd.targ;
1329: scb->sense.write = 0x80;
1330: scb->sense.opcode = WDSX_SCSICMD;
1331: ltophys(KVTOPHYS(&scb->sense_data), scb->sense.data);
1332: ltophys(sizeof(struct scsi_sense_data), scb->sense.len);
1333:
1334: s = splbio();
1335: wds_queue_scb(sc, scb);
1336: splx(s);
1337:
1338: /*
1339: * There's no reason for us to poll here. There are two cases:
1340: * 1) If it's a polling operation, then we're called from the interrupt
1341: * handler, and we return and continue polling.
1342: * 2) If it's an interrupt-driven operation, then it gets completed
1343: * later on when the REQUEST SENSE finishes.
1344: */
1345: }
1346:
1347: /*
1348: * Poll a particular unit, looking for a particular scb
1349: */
1350: int
1351: wds_poll(sc, xs, count)
1352: struct wds_softc *sc;
1353: struct scsi_xfer *xs;
1354: int count;
1355: {
1356: bus_space_tag_t iot = sc->sc_iot;
1357: bus_space_handle_t ioh = sc->sc_ioh;
1358:
1359: /* timeouts are in msec, so we loop in 1000 usec cycles */
1360: while (count) {
1361: /*
1362: * If we had interrupts enabled, would we
1363: * have got an interrupt?
1364: */
1365: if (bus_space_read_1(iot, ioh, WDS_STAT) & WDSS_IRQ)
1366: wdsintr(sc);
1367: if (xs->flags & ITSDONE)
1368: return 0;
1369: delay(1000); /* only happens in boot so ok */
1370: count--;
1371: }
1372: return 1;
1373: }
1374:
1375: /*
1376: * Poll a particular unit, looking for a particular scb
1377: */
1378: int
1379: wds_ipoll(sc, scb, count)
1380: struct wds_softc *sc;
1381: struct wds_scb *scb;
1382: int count;
1383: {
1384: bus_space_tag_t iot = sc->sc_iot;
1385: bus_space_handle_t ioh = sc->sc_ioh;
1386:
1387: /* timeouts are in msec, so we loop in 1000 usec cycles */
1388: while (count) {
1389: /*
1390: * If we had interrupts enabled, would we
1391: * have got an interrupt?
1392: */
1393: if (bus_space_read_1(iot, ioh, WDS_STAT) & WDSS_IRQ)
1394: wdsintr(sc);
1395: if (scb->flags & SCB_DONE)
1396: return 0;
1397: delay(1000); /* only happens in boot so ok */
1398: count--;
1399: }
1400: return 1;
1401: }
1402:
1403: void
1404: wds_timeout(arg)
1405: void *arg;
1406: {
1407: struct wds_scb *scb = arg;
1408: struct scsi_xfer *xs;
1409: struct scsi_link *sc_link;
1410: struct wds_softc *sc;
1411: int s;
1412:
1413: s = splbio();
1414: #ifdef notyet
1415: isadma_copyfrombuf((caddr_t)scb, SCB_PHYS_SIZE, 1, scb->scb_phys);
1416: #endif
1417: xs = scb->xs;
1418: sc_link = xs->sc_link;
1419: sc = sc_link->adapter_softc;
1420:
1421: sc_print_addr(sc_link);
1422: printf("timed out");
1423:
1424: #ifdef WDSDIAG
1425: /*
1426: * If The scb's mbx is not free, then the board has gone south?
1427: */
1428: wds_collect_mbo(sc);
1429: if (scb->flags & SCB_SENDING) {
1430: printf("%s: not taking commands!\n", sc->sc_dev.dv_xname);
1431: Debugger();
1432: }
1433: #endif
1434:
1435: /*
1436: * If it has been through before, then
1437: * a previous abort has failed, don't
1438: * try abort again
1439: */
1440: if (scb->flags & SCB_ABORT) {
1441: /* abort timed out */
1442: printf(" AGAIN\n");
1443: /* XXX Must reset! */
1444: } else {
1445: /* abort the operation that has timed out */
1446: printf("\n");
1447: scb->xs->error = XS_TIMEOUT;
1448: scb->timeout = WDS_ABORT_TIMEOUT;
1449: scb->flags |= SCB_ABORT;
1450: wds_queue_scb(sc, scb);
1451: }
1452:
1453: splx(s);
1454: }
CVSweb