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