wds.c revision 1.13 1 /* $NetBSD: wds.c,v 1.13 1996/11/03 16:20:31 mycroft 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
290 #ifdef NEWCONFIG
291 isa_establish(&sc->sc_id, &sc->sc_dev);
292 #endif
293 sc->sc_ih = isa_intr_establish(ia->ia_ic, sc->sc_irq, IST_EDGE,
294 IPL_BIO, wdsintr, sc);
295
296 /*
297 * ask the adapter what subunits are present
298 */
299 config_found(self, &sc->sc_link, scsiprint);
300 }
301
302 integrate void
303 wds_finish_scbs(sc)
304 struct wds_softc *sc;
305 {
306 struct wds_mbx_in *wmbi;
307 struct wds_scb *scb;
308 int i;
309
310 wmbi = wmbx->tmbi;
311
312 if (wmbi->stat == WDS_MBI_FREE) {
313 for (i = 0; i < WDS_MBX_SIZE; i++) {
314 if (wmbi->stat != WDS_MBI_FREE) {
315 printf("%s: mbi not in round-robin order\n",
316 sc->sc_dev.dv_xname);
317 goto AGAIN;
318 }
319 wds_nextmbx(wmbi, wmbx, mbi);
320 }
321 #ifdef WDSDIAGnot
322 printf("%s: mbi interrupt with no full mailboxes\n",
323 sc->sc_dev.dv_xname);
324 #endif
325 return;
326 }
327
328 AGAIN:
329 do {
330 scb = wds_scb_phys_kv(sc, phystol(wmbi->scb_addr));
331 if (!scb) {
332 printf("%s: bad mbi scb pointer; skipping\n",
333 sc->sc_dev.dv_xname);
334 goto next;
335 }
336
337 #ifdef WDSDEBUG
338 if (wds_debug) {
339 u_char *cp = &scb->scsi_cmd;
340 printf("op=%x %x %x %x %x %x\n",
341 cp[0], cp[1], cp[2], cp[3], cp[4], cp[5]);
342 printf("stat %x for mbi addr = 0x%08x, ",
343 wmbi->stat, wmbi);
344 printf("scb addr = 0x%x\n", scb);
345 }
346 #endif /* WDSDEBUG */
347
348 untimeout(wds_timeout, scb);
349 wds_done(sc, scb, wmbi->stat);
350
351 next:
352 wmbi->stat = WDS_MBI_FREE;
353 wds_nextmbx(wmbi, wmbx, mbi);
354 } while (wmbi->stat != WDS_MBI_FREE);
355
356 wmbx->tmbi = wmbi;
357 }
358
359 /*
360 * Process an interrupt.
361 */
362 int
363 wdsintr(arg)
364 void *arg;
365 {
366 struct wds_softc *sc = arg;
367 int iobase = sc->sc_iobase;
368 u_char c;
369
370 /* Was it really an interrupt from the board? */
371 if ((inb(iobase + WDS_STAT) & WDSS_IRQ) == 0)
372 return 0;
373
374 /* Get the interrupt status byte. */
375 c = inb(iobase + WDS_IRQSTAT) & WDSI_MASK;
376
377 /* Acknowledge (which resets) the interrupt. */
378 outb(iobase + WDS_IRQACK, 0x00);
379
380 switch (c) {
381 case WDSI_MSVC:
382 wds_finish_scbs(sc);
383 break;
384
385 case WDSI_MFREE:
386 wds_start_scbs(sc);
387 break;
388
389 default:
390 printf("%s: unrecognized interrupt type %02x",
391 sc->sc_dev.dv_xname, c);
392 break;
393 }
394
395 return 1;
396 }
397
398 integrate void
399 wds_reset_scb(sc, scb)
400 struct wds_softc *sc;
401 struct wds_scb *scb;
402 {
403
404 scb->flags = 0;
405 }
406
407 /*
408 * Free the command structure, the outgoing mailbox and the data buffer.
409 */
410 void
411 wds_free_scb(sc, scb)
412 struct wds_softc *sc;
413 struct wds_scb *scb;
414 {
415 int s;
416
417 if (scb->buf != 0) {
418 wds_free_buf(sc, scb->buf);
419 scb->buf = 0;
420 }
421
422 s = splbio();
423
424 wds_reset_scb(sc, scb);
425 TAILQ_INSERT_HEAD(&sc->sc_free_scb, scb, chain);
426
427 /*
428 * If there were none, wake anybody waiting for one to come free,
429 * starting with queued entries.
430 */
431 if (scb->chain.tqe_next == 0)
432 wakeup(&sc->sc_free_scb);
433
434 splx(s);
435 }
436
437 void
438 wds_free_buf(sc, buf)
439 struct wds_softc *sc;
440 struct wds_buf *buf;
441 {
442 int s;
443
444 s = splbio();
445
446 buf->busy = 0;
447 TAILQ_INSERT_HEAD(&wds_free_buffer, buf, chain);
448
449 /*
450 * If there were none, wake anybody waiting for one to come free,
451 * starting with queued entries.
452 */
453 if (buf->chain.tqe_next == 0)
454 wakeup(&wds_free_buffer);
455
456 splx(s);
457 }
458
459 integrate void
460 wds_init_scb(sc, scb)
461 struct wds_softc *sc;
462 struct wds_scb *scb;
463 {
464 int hashnum;
465
466 bzero(scb, sizeof(struct wds_scb));
467 /*
468 * put in the phystokv hash table
469 * Never gets taken out.
470 */
471 scb->hashkey = KVTOPHYS(scb);
472 hashnum = SCB_HASH(scb->hashkey);
473 scb->nexthash = sc->sc_scbhash[hashnum];
474 sc->sc_scbhash[hashnum] = scb;
475 wds_reset_scb(sc, scb);
476 }
477
478 /*
479 * Get a free scb
480 *
481 * If there are none, see if we can allocate a new one. If so, put it in
482 * the hash table too otherwise either return an error or sleep.
483 */
484 struct wds_scb *
485 wds_get_scb(sc, flags, needbuffer)
486 struct wds_softc *sc;
487 int flags;
488 int needbuffer;
489 {
490 struct wds_scb *scb;
491 int s;
492
493 s = splbio();
494
495 /*
496 * If we can and have to, sleep waiting for one to come free
497 * but only if we can't allocate a new one.
498 */
499 for (;;) {
500 scb = sc->sc_free_scb.tqh_first;
501 if (scb) {
502 TAILQ_REMOVE(&sc->sc_free_scb, scb, chain);
503 break;
504 }
505 if (sc->sc_numscbs < WDS_SCB_MAX) {
506 scb = (struct wds_scb *) malloc(sizeof(struct wds_scb),
507 M_TEMP, M_NOWAIT);
508 if (!scb) {
509 printf("%s: can't malloc scb\n",
510 sc->sc_dev.dv_xname);
511 goto out;
512 }
513 wds_init_scb(sc, scb);
514 sc->sc_numscbs++;
515 break;
516 }
517 if ((flags & SCSI_NOSLEEP) != 0)
518 goto out;
519 tsleep(&sc->sc_free_scb, PRIBIO, "wdsscb", 0);
520 }
521
522 scb->flags |= SCB_ALLOC;
523
524 if (needbuffer) {
525 scb->buf = wds_get_buf(sc, flags);
526 if (scb->buf == 0) {
527 wds_free_scb(sc, scb);
528 scb = 0;
529 }
530 }
531
532 out:
533 splx(s);
534 return (scb);
535 }
536
537 struct wds_buf *
538 wds_get_buf(sc, flags)
539 struct wds_softc *sc;
540 int flags;
541 {
542 struct wds_buf *buf;
543 int s;
544
545 s = splbio();
546
547 for (;;) {
548 buf = wds_free_buffer.tqh_first;
549 if (buf) {
550 TAILQ_REMOVE(&wds_free_buffer, buf, chain);
551 break;
552 }
553 if ((flags & SCSI_NOSLEEP) != 0)
554 goto out;
555 tsleep(&wds_free_buffer, PRIBIO, "wdsbuf", 0);
556 }
557
558 buf->busy = 1;
559
560 out:
561 splx(s);
562 return (buf);
563 }
564
565 struct wds_scb *
566 wds_scb_phys_kv(sc, scb_phys)
567 struct wds_softc *sc;
568 u_long scb_phys;
569 {
570 int hashnum = SCB_HASH(scb_phys);
571 struct wds_scb *scb = sc->sc_scbhash[hashnum];
572
573 while (scb) {
574 if (scb->hashkey == scb_phys)
575 break;
576 /* XXX Check to see if it matches the sense command block. */
577 if (scb->hashkey == (scb_phys - sizeof(struct wds_cmd)))
578 break;
579 scb = scb->nexthash;
580 }
581 return scb;
582 }
583
584 /*
585 * Queue a SCB to be sent to the controller, and send it if possible.
586 */
587 void
588 wds_queue_scb(sc, scb)
589 struct wds_softc *sc;
590 struct wds_scb *scb;
591 {
592
593 TAILQ_INSERT_TAIL(&sc->sc_waiting_scb, scb, chain);
594 wds_start_scbs(sc);
595 }
596
597 /*
598 * Garbage collect mailboxes that are no longer in use.
599 */
600 void
601 wds_collect_mbo(sc)
602 struct wds_softc *sc;
603 {
604 struct wds_mbx_out *wmbo; /* Mail Box Out pointer */
605 #ifdef WDSDIAG
606 struct wds_scb *scb;
607 #endif
608
609 wmbo = wmbx->cmbo;
610
611 while (sc->sc_mbofull > 0) {
612 if (wmbo->cmd != WDS_MBO_FREE)
613 break;
614
615 #ifdef WDSDIAG
616 scb = wds_scb_phys_kv(sc, phystol(wmbo->scb_addr));
617 scb->flags &= ~SCB_SENDING;
618 #endif
619
620 --sc->sc_mbofull;
621 wds_nextmbx(wmbo, wmbx, mbo);
622 }
623
624 wmbx->cmbo = wmbo;
625 }
626
627 /*
628 * Send as many SCBs as we have empty mailboxes for.
629 */
630 void
631 wds_start_scbs(sc)
632 struct wds_softc *sc;
633 {
634 int iobase = sc->sc_iobase;
635 struct wds_mbx_out *wmbo; /* Mail Box Out pointer */
636 struct wds_scb *scb;
637 u_char c;
638
639 wmbo = wmbx->tmbo;
640
641 while ((scb = sc->sc_waiting_scb.tqh_first) != NULL) {
642 if (sc->sc_mbofull >= WDS_MBX_SIZE) {
643 wds_collect_mbo(sc);
644 if (sc->sc_mbofull >= WDS_MBX_SIZE) {
645 c = WDSC_IRQMFREE;
646 wds_cmd(iobase, &c, sizeof c);
647 break;
648 }
649 }
650
651 TAILQ_REMOVE(&sc->sc_waiting_scb, scb, chain);
652 #ifdef WDSDIAG
653 scb->flags |= SCB_SENDING;
654 #endif
655
656 /* Link scb to mbo. */
657 if (scb->flags & SCB_SENSE)
658 ltophys(KVTOPHYS(&scb->sense), wmbo->scb_addr);
659 else
660 ltophys(KVTOPHYS(&scb->cmd), wmbo->scb_addr);
661 /* XXX What about aborts? */
662 wmbo->cmd = WDS_MBO_START;
663
664 /* Tell the card to poll immediately. */
665 c = WDSC_MSTART(wmbo - wmbx->mbo);
666 wds_cmd(sc->sc_iobase, &c, sizeof c);
667
668 if ((scb->flags & SCB_POLLED) == 0)
669 timeout(wds_timeout, scb, (scb->timeout * hz) / 1000);
670
671 ++sc->sc_mbofull;
672 wds_nextmbx(wmbo, wmbx, mbo);
673 }
674
675 wmbx->tmbo = wmbo;
676 }
677
678 /*
679 * Process the result of a SCSI command.
680 */
681 void
682 wds_done(sc, scb, stat)
683 struct wds_softc *sc;
684 struct wds_scb *scb;
685 u_char stat;
686 {
687 struct scsi_xfer *xs = scb->xs;
688
689 /* XXXXX */
690
691 /* Don't release the SCB if it was an internal command. */
692 if (xs == 0) {
693 scb->flags |= SCB_DONE;
694 return;
695 }
696
697 /* Sense handling. */
698 if (xs->error == XS_SENSE) {
699 bcopy(&scb->sense_data, &xs->sense, sizeof (struct scsi_sense_data));
700 } else {
701 if (xs->error == XS_NOERROR) {
702 /* If all went well, or an error is acceptable. */
703 if (stat == WDS_MBI_OK) {
704 /* OK, set the result */
705 xs->resid = 0;
706 } else {
707 /* Check the mailbox status. */
708 switch (stat) {
709 case WDS_MBI_OKERR:
710 /* SCSI error recorded in scb, counts as WDS_MBI_OK */
711 switch (scb->cmd.venderr) {
712 case 0x00:
713 printf("%s: Is this an error?\n", sc->sc_dev.dv_xname);
714 xs->error = XS_DRIVER_STUFFUP; /* Experiment */
715 break;
716 case 0x01:
717 /*printf("%s: OK, see SCSI error field.\n", sc->sc_dev.dv_xname);*/
718 if (scb->cmd.stat == SCSI_CHECK) {
719 /* Do sense. */
720 wds_sense (sc, scb);
721 return;
722 } else if (scb->cmd.stat == SCSI_BUSY) {
723 xs->error = XS_BUSY;
724 }
725 break;
726 case 0x40:
727 /*printf("%s: DMA underrun!\n", sc->sc_dev.dv_xname);*/
728 /* Hits this if the target returns fewer that datalen bytes (eg my CD-ROM,
729 which returns a short version string, or if DMA is turned off etc. */
730 xs->resid = 0;
731 break;
732 default:
733 printf("%s: VENDOR ERROR %02x, scsi %02x\n", sc->sc_dev.dv_xname, scb->cmd.venderr, scb->cmd.stat);
734 xs->error = XS_DRIVER_STUFFUP; /* Experiment */
735 break;
736 }
737 break;
738 case WDS_MBI_ETIME:
739 /*
740 * The documentation isn't clear on
741 * what conditions might generate this,
742 * but selection timeouts are the only
743 * one I can think of.
744 */
745 xs->error = XS_SELTIMEOUT;
746 break;
747 case WDS_MBI_ERESET:
748 case WDS_MBI_ETARCMD:
749 case WDS_MBI_ERESEL:
750 case WDS_MBI_ESEL:
751 case WDS_MBI_EABORT:
752 case WDS_MBI_ESRESET:
753 case WDS_MBI_EHRESET:
754 xs->error = XS_DRIVER_STUFFUP;
755 break;
756 }
757 }
758 } /* else sense */
759
760 if (NEEDBUFFER(sc) && xs->datalen) {
761 if (xs->flags & SCSI_DATA_IN)
762 bcopy(scb->buf->data, xs->data, xs->datalen);
763 }
764 } /* XS_NOERROR */
765
766 wds_free_scb(sc, scb);
767 xs->flags |= ITSDONE;
768 scsi_done(xs);
769 }
770
771 int
772 wds_find(ia, sc)
773 struct isa_attach_args *ia;
774 struct wds_softc *sc;
775 {
776 int iobase = ia->ia_iobase;
777 u_char c;
778 int i;
779
780 /* XXXXX */
781
782 /*
783 * Sending a command causes the CMDRDY bit to clear.
784 */
785 c = inb(iobase + WDS_STAT);
786 for (i = 0; i < 4; i++)
787 if ((inb(iobase+WDS_STAT) & WDSS_RDY) != 0) {
788 goto ready;
789 delay(10);
790 }
791 return 1;
792
793 ready:
794 outb(iobase + WDS_CMD, WDSC_NOOP);
795 if (inb(iobase + WDS_STAT) & WDSS_RDY)
796 return 1;
797
798 outb(iobase + WDS_HCR, WDSH_SCSIRESET|WDSH_ASCRESET);
799 delay(10000);
800 outb(iobase + WDS_HCR, 0x00);
801 delay(500000);
802 wds_wait(iobase + WDS_STAT, WDSS_RDY, WDSS_RDY);
803 if (inb(iobase + WDS_IRQSTAT) != 1)
804 if (inb(iobase + WDS_IRQSTAT) != 7)
805 printf("%s: failed reset!!! %2x\n", sc->sc_dev.dv_xname, inb(iobase + WDS_IRQSTAT));
806
807 if ((inb(iobase + WDS_STAT) & (WDSS_RDY)) != WDSS_RDY) {
808 printf("%s: waiting for controller to become ready.", sc->sc_dev.dv_xname);
809 for (i = 0; i < 20; i++) {
810 if ((inb(iobase + WDS_STAT) & (WDSS_RDY)) == WDSS_RDY)
811 break;
812 printf(".");
813 delay(10000);
814 }
815 if ((inb(iobase + WDS_STAT) & (WDSS_RDY)) != WDSS_RDY) {
816 printf(" failed\n");
817 return 1;
818 }
819 printf("\n");
820 }
821
822 if (sc != NULL) {
823 /* XXX Can we do this better? */
824 /* who are we on the scsi bus? */
825 sc->sc_scsi_dev = 7;
826
827 sc->sc_iobase = iobase;
828 sc->sc_irq = ia->ia_irq;
829 sc->sc_drq = ia->ia_drq;
830 }
831
832 return 0;
833 }
834
835 /*
836 * Initialise the board and driver.
837 */
838 void
839 wds_init(sc)
840 struct wds_softc *sc;
841 {
842 int iobase = sc->sc_iobase;
843 struct wds_setup init;
844 u_char c;
845 int i;
846
847 /*
848 * Set up initial mail box for round-robin operation.
849 */
850 for (i = 0; i < WDS_MBX_SIZE; i++) {
851 wmbx->mbo[i].cmd = WDS_MBO_FREE;
852 wmbx->mbi[i].stat = WDS_MBI_FREE;
853 }
854 wmbx->cmbo = wmbx->tmbo = &wmbx->mbo[0];
855 wmbx->tmbi = &wmbx->mbi[0];
856 sc->sc_mbofull = 0;
857
858 /* Clear the buffers. */
859 TAILQ_INIT(&wds_free_buffer);
860 for (i = 0; i < BUFCNT; i++) {
861 wds_buffer[i].busy = 0;
862 TAILQ_INSERT_HEAD(&wds_free_buffer, &wds_buffer[i], chain);
863 }
864
865 init.opcode = WDSC_INIT;
866 init.scsi_id = sc->sc_scsi_dev;
867 /* Record scsi id of controller for use in scsi_attach */
868 sc->sc_scsi_dev = init.scsi_id;
869 init.buson_t = 48;
870 init.busoff_t = 24;
871 init.xx = 0;
872 ltophys(KVTOPHYS(wmbx), init.mbaddr);
873 init.nomb = init.nimb = WDS_MBX_SIZE;
874 wds_cmd(iobase, (u_char *)&init, sizeof init);
875
876 wds_wait(iobase + WDS_STAT, WDSS_INIT, WDSS_INIT);
877
878 c = WDSC_DISUNSOL;
879 wds_cmd(iobase, &c, sizeof c);
880
881 outb(iobase + WDS_HCR, WDSH_DRQEN);
882 }
883
884 /*
885 * Read the board's firmware revision information.
886 */
887 void
888 wds_inquire_setup_information(sc)
889 struct wds_softc *sc;
890 {
891 struct wds_scb *scb;
892 int iobase;
893 u_char *j;
894 int s;
895
896 iobase = sc->sc_iobase;
897
898 if ((scb = wds_get_scb(sc, SCSI_NOSLEEP, 0)) == NULL) {
899 printf("%s: no request slot available in getvers()!\n", sc->sc_dev.dv_xname);
900 return;
901 }
902 scb->xs = NULL;
903 scb->timeout = 40;
904
905 bzero(&scb->cmd, sizeof scb->cmd);
906 scb->cmd.write = 0x80;
907 scb->cmd.opcode = WDSX_GETFIRMREV;
908
909 /* Will poll card, await result. */
910 outb(iobase + WDS_HCR, WDSH_DRQEN);
911 scb->flags |= SCB_POLLED;
912
913 s = splbio();
914 wds_queue_scb(sc, scb);
915 splx(s);
916
917 if (wds_ipoll(sc, scb, scb->timeout))
918 goto out;
919
920 /* Print the version number. */
921 printf(": version %x.%02x ", scb->cmd.targ, scb->cmd.scb.opcode);
922 sc->sc_revision = (scb->cmd.targ << 8) | scb->cmd.scb.opcode;
923 /* Print out the version string. */
924 j = 2 + &(scb->cmd.targ);
925 while ((*j >= 32) && (*j < 128)) {
926 printf("%c", *j);
927 j++;
928 }
929
930 out:
931 printf("\n");
932 wds_free_scb(sc, scb);
933 }
934
935 void
936 wdsminphys(bp)
937 struct buf *bp;
938 {
939
940 if (bp->b_bcount > ((WDS_NSEG - 1) << PGSHIFT))
941 bp->b_bcount = ((WDS_NSEG - 1) << PGSHIFT);
942 minphys(bp);
943 }
944
945 /*
946 * Send a SCSI command.
947 */
948 int
949 wds_scsi_cmd(xs)
950 struct scsi_xfer *xs;
951 {
952 struct scsi_link *sc_link = xs->sc_link;
953 struct wds_softc *sc = sc_link->adapter_softc;
954 struct wds_scb *scb;
955 struct wds_scat_gath *sg;
956 int seg;
957 u_long thiskv, thisphys, nextphys;
958 int bytes_this_seg, bytes_this_page, datalen, flags;
959 #ifdef TFS
960 struct iovec *iovp;
961 #endif
962 int s;
963
964 int iobase;
965
966 iobase = sc->sc_iobase;
967
968 if (xs->flags & SCSI_RESET) {
969 /* XXX Fix me! */
970 printf("%s: reset!\n", sc->sc_dev.dv_xname);
971 wds_init(sc);
972 return COMPLETE;
973 }
974
975 flags = xs->flags;
976 if ((scb = wds_get_scb(sc, flags, NEEDBUFFER(sc))) == NULL) {
977 xs->error = XS_DRIVER_STUFFUP;
978 return TRY_AGAIN_LATER;
979 }
980 scb->xs = xs;
981 scb->timeout = xs->timeout;
982
983 if (xs->flags & SCSI_DATA_UIO) {
984 /* XXX Fix me! */
985 /* Let's not worry about UIO. There isn't any code for the *
986 * non-SG boards anyway! */
987 printf("%s: UIO is untested and disabled!\n", sc->sc_dev.dv_xname);
988 goto bad;
989 }
990
991 /* Zero out the command structure. */
992 bzero(&scb->cmd, sizeof scb->cmd);
993 bcopy(xs->cmd, &scb->cmd.scb, xs->cmdlen < 12 ? xs->cmdlen : 12);
994
995 /* Set up some of the command fields. */
996 scb->cmd.targ = (xs->sc_link->target << 5) | xs->sc_link->lun;
997
998 /* NOTE: cmd.write may be OK as 0x40 (disable direction checking)
999 * on boards other than the WD-7000V-ASE. Need this for the ASE:
1000 */
1001 scb->cmd.write = (xs->flags & SCSI_DATA_IN) ? 0x80 : 0x00;
1002
1003 if (!NEEDBUFFER(sc) && xs->datalen) {
1004 sg = scb->scat_gath;
1005 seg = 0;
1006 #ifdef TFS
1007 if (flags & SCSI_DATA_UIO) {
1008 iovp = ((struct uio *)xs->data)->uio_iov;
1009 datalen = ((struct uio *)xs->data)->uio_iovcnt;
1010 xs->datalen = 0;
1011 while (datalen && seg < WDS_NSEG) {
1012 ltophys(iovp->iov_base, sg->seg_addr);
1013 ltophys(iovp->iov_len, sg->seg_len);
1014 xs->datalen += iovp->iov_len;
1015 SC_DEBUGN(sc_link, SDEV_DB4, ("UIO(0x%x@0x%x)",
1016 iovp->iov_len, iovp->iov_base));
1017 sg++;
1018 iovp++;
1019 seg++;
1020 datalen--;
1021 }
1022 } else
1023 #endif /* TFS */
1024 {
1025 /*
1026 * Set up the scatter-gather block.
1027 */
1028 SC_DEBUG(sc_link, SDEV_DB4,
1029 ("%d @0x%x:- ", xs->datalen, xs->data));
1030
1031 datalen = xs->datalen;
1032 thiskv = (int)xs->data;
1033 thisphys = KVTOPHYS(xs->data);
1034
1035 while (datalen && seg < WDS_NSEG) {
1036 bytes_this_seg = 0;
1037
1038 /* put in the base address */
1039 ltophys(thisphys, sg->seg_addr);
1040
1041 SC_DEBUGN(sc_link, SDEV_DB4, ("0x%x", thisphys));
1042
1043 /* do it at least once */
1044 nextphys = thisphys;
1045 while (datalen && thisphys == nextphys) {
1046 /*
1047 * This page is contiguous (physically)
1048 * with the the last, just extend the
1049 * length
1050 */
1051 /* check it fits on the ISA bus */
1052 if (thisphys > 0xFFFFFF) {
1053 printf("%s: DMA beyond"
1054 " end of ISA\n",
1055 sc->sc_dev.dv_xname);
1056 goto bad;
1057 }
1058 /* how far to the end of the page */
1059 nextphys = (thisphys & ~PGOFSET) + NBPG;
1060 bytes_this_page = nextphys - thisphys;
1061 /**** or the data ****/
1062 bytes_this_page = min(bytes_this_page,
1063 datalen);
1064 bytes_this_seg += bytes_this_page;
1065 datalen -= bytes_this_page;
1066
1067 /* get more ready for the next page */
1068 thiskv = (thiskv & ~PGOFSET) + NBPG;
1069 if (datalen)
1070 thisphys = KVTOPHYS(thiskv);
1071 }
1072 /*
1073 * next page isn't contiguous, finish the seg
1074 */
1075 SC_DEBUGN(sc_link, SDEV_DB4,
1076 ("(0x%x)", bytes_this_seg));
1077 ltophys(bytes_this_seg, sg->seg_len);
1078 sg++;
1079 seg++;
1080 }
1081 }
1082 /* end of iov/kv decision */
1083 SC_DEBUGN(sc_link, SDEV_DB4, ("\n"));
1084 if (datalen) {
1085 /*
1086 * there's still data, must have run out of segs!
1087 */
1088 printf("%s: wds_scsi_cmd, more than %d dma segs\n",
1089 sc->sc_dev.dv_xname, WDS_NSEG);
1090 goto bad;
1091 }
1092 scb->cmd.opcode = WDSX_SCSISG;
1093 ltophys(KVTOPHYS(scb->scat_gath), scb->cmd.data);
1094 ltophys(seg * sizeof(struct wds_scat_gath), scb->cmd.len);
1095 } else if (xs->datalen > 0) {
1096 /* The board is an ASC or ASE. Do not use scatter/gather. */
1097 if (xs->datalen > BUFLEN) {
1098 printf("%s: wds_scsi_cmd, I/O too large for bounce buffer\n",
1099 sc->sc_dev.dv_xname);
1100 goto bad;
1101 }
1102 if (xs->flags & SCSI_DATA_OUT)
1103 bcopy(xs->data, scb->buf->data, xs->datalen);
1104 else
1105 bzero(scb->buf->data, xs->datalen);
1106 scb->cmd.opcode = WDSX_SCSICMD;
1107 ltophys(KVTOPHYS(scb->buf->data), scb->cmd.data);
1108 ltophys(xs->datalen, scb->cmd.len);
1109 } else {
1110 scb->cmd.opcode = WDSX_SCSICMD;
1111 ltophys(0, scb->cmd.data);
1112 ltophys(0, scb->cmd.len);
1113 }
1114
1115 scb->cmd.stat = 0x00;
1116 scb->cmd.venderr = 0x00;
1117 ltophys(0, scb->cmd.link);
1118
1119 /* XXX Do we really want to do this? */
1120 if (flags & SCSI_POLL) {
1121 /* Will poll card, await result. */
1122 outb(iobase + WDS_HCR, WDSH_DRQEN);
1123 scb->flags |= SCB_POLLED;
1124 } else {
1125 /* Will send command, let interrupt routine handle result. */
1126 outb(iobase + WDS_HCR, WDSH_IRQEN | WDSH_DRQEN);
1127 }
1128
1129 s = splbio();
1130 wds_queue_scb(sc, scb);
1131 splx(s);
1132
1133 if ((flags & SCSI_POLL) == 0)
1134 return SUCCESSFULLY_QUEUED;
1135
1136 if (wds_poll(sc, xs, scb->timeout)) {
1137 wds_timeout(scb);
1138 if (wds_poll(sc, xs, scb->timeout))
1139 wds_timeout(scb);
1140 }
1141 return COMPLETE;
1142
1143 bad:
1144 xs->error = XS_DRIVER_STUFFUP;
1145 wds_free_scb(sc, scb);
1146 return COMPLETE;
1147 }
1148
1149 /*
1150 * Send a sense request.
1151 */
1152 void
1153 wds_sense(sc, scb)
1154 struct wds_softc *sc;
1155 struct wds_scb *scb;
1156 {
1157 struct scsi_xfer *xs = scb->xs;
1158 struct scsi_sense *ss = (void *)&scb->sense.scb;
1159 int s;
1160
1161 /* XXXXX */
1162
1163 /* Send sense request SCSI command. */
1164 xs->error = XS_SENSE;
1165 scb->flags |= SCB_SENSE;
1166
1167 /* First, save the return values */
1168 if (NEEDBUFFER(sc) && xs->datalen) {
1169 if (xs->flags & SCSI_DATA_IN)
1170 bcopy(scb->buf->data, xs->data, xs->datalen);
1171 }
1172
1173 /* Next, setup a request sense command block */
1174 bzero(ss, sizeof(*ss));
1175 ss->opcode = REQUEST_SENSE;
1176 ss->byte2 = xs->sc_link->lun << 5;
1177 ss->length = sizeof(struct scsi_sense_data);
1178
1179 /* Set up some of the command fields. */
1180 scb->sense.targ = scb->cmd.targ;
1181 scb->sense.write = 0x80;
1182 scb->sense.opcode = WDSX_SCSICMD;
1183 ltophys(KVTOPHYS(&scb->sense_data), scb->sense.data);
1184 ltophys(sizeof(struct scsi_sense_data), scb->sense.len);
1185
1186 s = splbio();
1187 wds_queue_scb(sc, scb);
1188 splx(s);
1189
1190 /*
1191 * There's no reason for us to poll here. There are two cases:
1192 * 1) If it's a polling operation, then we're called from the interrupt
1193 * handler, and we return and continue polling.
1194 * 2) If it's an interrupt-driven operation, then it gets completed
1195 * later on when the REQUEST SENSE finishes.
1196 */
1197 }
1198
1199 /*
1200 * Poll a particular unit, looking for a particular scb
1201 */
1202 int
1203 wds_poll(sc, xs, count)
1204 struct wds_softc *sc;
1205 struct scsi_xfer *xs;
1206 int count;
1207 {
1208 int iobase = sc->sc_iobase;
1209
1210 /* timeouts are in msec, so we loop in 1000 usec cycles */
1211 while (count) {
1212 /*
1213 * If we had interrupts enabled, would we
1214 * have got an interrupt?
1215 */
1216 if (inb(iobase + WDS_STAT) & WDSS_IRQ)
1217 wdsintr(sc);
1218 if (xs->flags & ITSDONE)
1219 return 0;
1220 delay(1000); /* only happens in boot so ok */
1221 count--;
1222 }
1223 return 1;
1224 }
1225
1226 /*
1227 * Poll a particular unit, looking for a particular scb
1228 */
1229 int
1230 wds_ipoll(sc, scb, count)
1231 struct wds_softc *sc;
1232 struct wds_scb *scb;
1233 int count;
1234 {
1235 int iobase = sc->sc_iobase;
1236
1237 /* timeouts are in msec, so we loop in 1000 usec cycles */
1238 while (count) {
1239 /*
1240 * If we had interrupts enabled, would we
1241 * have got an interrupt?
1242 */
1243 if (inb(iobase + WDS_STAT) & WDSS_IRQ)
1244 wdsintr(sc);
1245 if (scb->flags & SCB_DONE)
1246 return 0;
1247 delay(1000); /* only happens in boot so ok */
1248 count--;
1249 }
1250 return 1;
1251 }
1252
1253 void
1254 wds_timeout(arg)
1255 void *arg;
1256 {
1257 struct wds_scb *scb = arg;
1258 struct scsi_xfer *xs = scb->xs;
1259 struct scsi_link *sc_link = xs->sc_link;
1260 struct wds_softc *sc = sc_link->adapter_softc;
1261 int s;
1262
1263 sc_print_addr(sc_link);
1264 printf("timed out");
1265
1266 s = splbio();
1267
1268 #ifdef WDSDIAG
1269 /*
1270 * If The scb's mbx is not free, then the board has gone south?
1271 */
1272 wds_collect_mbo(sc);
1273 if (scb->flags & SCB_SENDING) {
1274 printf("%s: not taking commands!\n", sc->sc_dev.dv_xname);
1275 Debugger();
1276 }
1277 #endif
1278
1279 /*
1280 * If it has been through before, then
1281 * a previous abort has failed, don't
1282 * try abort again
1283 */
1284 if (scb->flags & SCB_ABORT) {
1285 /* abort timed out */
1286 printf(" AGAIN\n");
1287 /* XXX Must reset! */
1288 } else {
1289 /* abort the operation that has timed out */
1290 printf("\n");
1291 scb->xs->error = XS_TIMEOUT;
1292 scb->timeout = WDS_ABORT_TIMEOUT;
1293 scb->flags |= SCB_ABORT;
1294 wds_queue_scb(sc, scb);
1295 }
1296
1297 splx(s);
1298 }
1299