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