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