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