This source file includes following definitions.
- aha_cmd
- aha_isapnp_probe
- ahaprobe
- ahaattach
- aha_finish_ccbs
- ahaintr
- aha_reset_ccb
- aha_free_ccb
- aha_init_ccb
- aha_get_ccb
- aha_ccb_phys_kv
- aha_queue_ccb
- aha_collect_mbo
- aha_start_ccbs
- aha_done
- aha_find
- aha_init
- aha_inquire_setup_information
- ahaminphys
- aha_scsi_cmd
- aha_poll
- aha_timeout
1
2
3
4 #undef AHADIAG
5
6
7
8
9
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 #include <sys/types.h>
51 #include <sys/param.h>
52 #include <sys/systm.h>
53 #include <sys/kernel.h>
54 #include <sys/errno.h>
55 #include <sys/ioctl.h>
56 #include <sys/device.h>
57 #include <sys/malloc.h>
58 #include <sys/buf.h>
59 #include <sys/proc.h>
60 #include <sys/user.h>
61 #include <sys/timeout.h>
62
63 #include <uvm/uvm.h>
64 #include <uvm/uvm_extern.h>
65
66 #include <machine/intr.h>
67 #include <machine/bus.h>
68
69 #include <scsi/scsi_all.h>
70 #include <scsi/scsiconf.h>
71
72 #include <dev/isa/isavar.h>
73 #include <dev/isa/isadmavar.h>
74 #include <dev/isa/ahareg.h>
75
76 #ifndef DDB
77 #define Debugger() panic("should call debugger here (aha1542.c)")
78 #endif
79
80
81
82
83
84 #ifdef i386
85 #define VOLATILE_XS(xs) \
86 ((xs)->datalen > 0 && (xs)->bp == NULL && \
87 ((xs)->flags & SCSI_POLL) == 0)
88 #else
89 #define VOLATILE_XS(xs) 0
90 #endif
91
92
93
94
95
96 #define AHA_MBX_SIZE 16
97
98 #define AHA_CCB_MAX 16
99 #define CCB_HASH_SIZE 16
100 #define CCB_HASH_SHIFT 9
101 #define CCB_HASH(x) ((((long)(x))>>CCB_HASH_SHIFT) & (CCB_HASH_SIZE - 1))
102
103 #define aha_nextmbx(wmb, mbx, mbio) \
104 if ((wmb) == &(mbx)->mbio[AHA_MBX_SIZE - 1]) \
105 (wmb) = &(mbx)->mbio[0]; \
106 else \
107 (wmb)++;
108
109 struct aha_mbx {
110 struct aha_mbx_out mbo[AHA_MBX_SIZE];
111 struct aha_mbx_in mbi[AHA_MBX_SIZE];
112 struct aha_mbx_out *cmbo;
113 struct aha_mbx_out *tmbo;
114 struct aha_mbx_in *tmbi;
115 };
116
117 struct aha_softc {
118 struct device sc_dev;
119 struct isadev sc_id;
120 void *sc_ih;
121 bus_dma_tag_t sc_dmat;
122
123 int sc_iobase;
124 int sc_irq, sc_drq;
125
126 char sc_model[18],
127 sc_firmware[4];
128
129 struct aha_mbx *sc_mbx;
130 #define wmbx (sc->sc_mbx)
131 struct aha_ccb *sc_ccbhash[CCB_HASH_SIZE];
132 TAILQ_HEAD(, aha_ccb) sc_free_ccb, sc_waiting_ccb;
133 int sc_numccbs, sc_mbofull;
134 int sc_scsi_dev;
135 struct scsi_link sc_link;
136 };
137
138 #ifdef AHADEBUG
139 int aha_debug = 1;
140 #endif
141
142 int aha_cmd(int, struct aha_softc *, int, u_char *, int, u_char *);
143 void aha_finish_ccbs(struct aha_softc *);
144 int ahaintr(void *);
145 void aha_reset_ccb(struct aha_softc *, struct aha_ccb *);
146 void aha_free_ccb(struct aha_softc *, struct aha_ccb *);
147 int aha_init_ccb(struct aha_softc *, struct aha_ccb *, int);
148 struct aha_ccb *aha_get_ccb(struct aha_softc *, int);
149 struct aha_ccb *aha_ccb_phys_kv(struct aha_softc *, u_long);
150 void aha_queue_ccb(struct aha_softc *, struct aha_ccb *);
151 void aha_collect_mbo(struct aha_softc *);
152 void aha_start_ccbs(struct aha_softc *);
153 void aha_done(struct aha_softc *, struct aha_ccb *);
154 int aha_find(struct isa_attach_args *, struct aha_softc *, int);
155 void aha_init(struct aha_softc *);
156 void aha_inquire_setup_information(struct aha_softc *);
157 void ahaminphys(struct buf *);
158 int aha_scsi_cmd(struct scsi_xfer *);
159 int aha_poll(struct aha_softc *, struct scsi_xfer *, int);
160 void aha_timeout(void *arg);
161
162 struct scsi_adapter aha_switch = {
163 aha_scsi_cmd,
164 ahaminphys,
165 0,
166 0,
167 };
168
169
170 struct scsi_device aha_dev = {
171 NULL,
172 NULL,
173 NULL,
174 NULL,
175 };
176
177 int aha_isapnp_probe(struct device *, void *, void *);
178 int ahaprobe(struct device *, void *, void *);
179 void ahaattach(struct device *, struct device *, void *);
180
181 struct cfattach aha_isapnp_ca = {
182 sizeof(struct aha_softc), aha_isapnp_probe, ahaattach
183 };
184
185 struct cfattach aha_isa_ca = {
186 sizeof(struct aha_softc), ahaprobe, ahaattach
187 };
188
189 struct cfdriver aha_cd = {
190 NULL, "aha", DV_DULL
191 };
192
193 #define AHA_RESET_TIMEOUT 2000
194 #define AHA_ABORT_TIMEOUT 2000
195
196 #include "bha.h"
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212 int
213 aha_cmd(iobase, sc, icnt, ibuf, ocnt, obuf)
214 int iobase;
215 struct aha_softc *sc;
216 int icnt, ocnt;
217 u_char *ibuf, *obuf;
218 {
219 const char *name;
220 register int i;
221 int wait;
222 u_char sts;
223 u_char opcode = ibuf[0];
224
225 if (sc != NULL)
226 name = sc->sc_dev.dv_xname;
227 else
228 name = "(aha probe)";
229
230
231
232
233 switch (opcode) {
234 case AHA_INQUIRE_DEVICES:
235 wait = 15 * 20000;
236 break;
237 default:
238 wait = 1 * 20000;
239 break;
240 }
241
242
243
244
245
246 if (opcode != AHA_MBO_INTR_EN) {
247 for (i = 20000; i; i--) {
248 sts = inb(iobase + AHA_STAT_PORT);
249 if (sts & AHA_STAT_IDLE)
250 break;
251 delay(50);
252 }
253 if (!i) {
254 printf("%s: aha_cmd, host not idle(0x%x)\n",
255 name, sts);
256 return (ENXIO);
257 }
258 }
259
260
261
262
263 if (ocnt) {
264 while ((inb(iobase + AHA_STAT_PORT)) & AHA_STAT_DF)
265 inb(iobase + AHA_DATA_PORT);
266 }
267
268
269
270
271 while (icnt--) {
272 for (i = wait; i; i--) {
273 sts = inb(iobase + AHA_STAT_PORT);
274 if (!(sts & AHA_STAT_CDF))
275 break;
276 delay(50);
277 }
278 if (!i) {
279 if (opcode != AHA_INQUIRE_REVISION)
280 printf("%s: aha_cmd, cmd/data port full\n",
281 name);
282 outb(iobase + AHA_CTRL_PORT, AHA_CTRL_SRST);
283 return (ENXIO);
284 }
285 outb(iobase + AHA_CMD_PORT, *ibuf++);
286 }
287
288
289
290
291 while (ocnt--) {
292 for (i = wait; i; i--) {
293 sts = inb(iobase + AHA_STAT_PORT);
294 if (sts & AHA_STAT_DF)
295 break;
296 delay(50);
297 }
298 if (!i) {
299 if (opcode != AHA_INQUIRE_REVISION)
300 printf("%s: aha_cmd, cmd/data port empty %d\n",
301 name, ocnt);
302 outb(iobase + AHA_CTRL_PORT, AHA_CTRL_SRST);
303 return (ENXIO);
304 }
305 *obuf++ = inb(iobase + AHA_DATA_PORT);
306 }
307
308
309
310
311
312 if (opcode != AHA_MBO_INTR_EN) {
313 for (i = 20000; i; i--) {
314 sts = inb(iobase + AHA_INTR_PORT);
315
316 if (sts & AHA_INTR_HACC)
317 break;
318 delay(50);
319 }
320 if (!i) {
321 printf("%s: aha_cmd, host not finished(0x%x)\n",
322 name, sts);
323 return (ENXIO);
324 }
325 }
326 outb(iobase + AHA_CTRL_PORT, AHA_CTRL_IRST);
327 return (0);
328 }
329
330 int
331 aha_isapnp_probe(parent, match, aux)
332 struct device *parent;
333 void *match, *aux;
334 {
335 return (1);
336 }
337
338
339
340
341
342
343
344
345 int
346 ahaprobe(parent, match, aux)
347 struct device *parent;
348 void *match, *aux;
349 {
350 register struct isa_attach_args *ia = aux;
351 #if NBHA > 0
352 extern int btports[], nbtports;
353 int i;
354
355 for (i = 0; i < nbtports; i++)
356 if (btports[i] == ia->ia_iobase)
357 return (0);
358 #endif
359
360
361 if (aha_find(ia, NULL, 0) != 0)
362 return (0);
363
364 ia->ia_msize = 0;
365 ia->ia_iosize = 4;
366
367 return (1);
368 }
369
370
371
372
373 void
374 ahaattach(parent, self, aux)
375 struct device *parent, *self;
376 void *aux;
377 {
378 struct isa_attach_args *ia = aux;
379 struct aha_softc *sc = (void *)self;
380 struct scsibus_attach_args saa;
381 int isapnp = !strcmp(parent->dv_cfdata->cf_driver->cd_name, "isapnp");
382
383 if (isapnp) {
384 ia->ia_iobase = ia->ipa_io[0].base;
385 isadma_cascade(ia->ia_drq);
386 }
387
388 if (aha_find(ia, sc, isapnp) != 0)
389 panic("ahaattach: aha_find of %s failed", self->dv_xname);
390 sc->sc_iobase = ia->ia_iobase;
391 sc->sc_dmat = ia->ia_dmat;
392
393 if (sc->sc_drq != DRQUNK && isapnp == 0)
394 isadma_cascade(sc->sc_drq);
395
396 aha_inquire_setup_information(sc);
397 aha_init(sc);
398 TAILQ_INIT(&sc->sc_free_ccb);
399 TAILQ_INIT(&sc->sc_waiting_ccb);
400
401
402
403
404 sc->sc_link.adapter_softc = sc;
405 sc->sc_link.adapter_target = sc->sc_scsi_dev;
406 sc->sc_link.adapter = &aha_switch;
407 sc->sc_link.device = &aha_dev;
408 sc->sc_link.openings = 2;
409
410 bzero(&saa, sizeof(saa));
411 saa.saa_sc_link = &sc->sc_link;
412
413 sc->sc_ih = isa_intr_establish(ia->ia_ic, sc->sc_irq, IST_EDGE,
414 IPL_BIO, ahaintr, sc, sc->sc_dev.dv_xname);
415
416
417
418
419 config_found(self, &saa, scsiprint);
420 }
421
422 void
423 aha_finish_ccbs(sc)
424 struct aha_softc *sc;
425 {
426 struct aha_mbx_in *wmbi;
427 struct aha_ccb *ccb;
428 int i;
429
430 wmbi = wmbx->tmbi;
431
432 if (wmbi->stat == AHA_MBI_FREE) {
433 for (i = 0; i < AHA_MBX_SIZE; i++) {
434 if (wmbi->stat != AHA_MBI_FREE) {
435 printf("%s: mbi not in round-robin order\n",
436 sc->sc_dev.dv_xname);
437 goto AGAIN;
438 }
439 aha_nextmbx(wmbi, wmbx, mbi);
440 }
441 #ifdef AHADIAGnot
442 printf("%s: mbi interrupt with no full mailboxes\n",
443 sc->sc_dev.dv_xname);
444 #endif
445 return;
446 }
447
448 AGAIN:
449 do {
450 ccb = aha_ccb_phys_kv(sc, phystol(wmbi->ccb_addr));
451 if (!ccb) {
452 printf("%s: bad mbi ccb pointer; skipping\n",
453 sc->sc_dev.dv_xname);
454 goto next;
455 }
456
457 #ifdef AHADEBUG
458 if (aha_debug) {
459 u_char *cp = (u_char *)&ccb->scsi_cmd;
460 printf("op=%x %x %x %x %x %x\n",
461 cp[0], cp[1], cp[2], cp[3], cp[4], cp[5]);
462 printf("stat %x for mbi addr = 0x%08x, ",
463 wmbi->stat, wmbi);
464 printf("ccb addr = 0x%x\n", ccb);
465 }
466 #endif
467
468 switch (wmbi->stat) {
469 case AHA_MBI_OK:
470 case AHA_MBI_ERROR:
471 if ((ccb->flags & CCB_ABORT) != 0) {
472
473
474
475
476
477
478
479
480 goto next;
481 }
482 break;
483
484 case AHA_MBI_ABORT:
485 case AHA_MBI_UNKNOWN:
486
487
488
489
490 break;
491
492 default:
493 printf("%s: bad mbi status %02x; skipping\n",
494 sc->sc_dev.dv_xname, wmbi->stat);
495 goto next;
496 }
497
498 if ((ccb->xs->flags & SCSI_POLL) == 0)
499 timeout_del(&ccb->xs->stimeout);
500 bus_dmamap_sync(sc->sc_dmat, ccb->ccb_dmam, 0,
501 ccb->ccb_dmam->dm_mapsize, BUS_DMASYNC_POSTREAD);
502 aha_done(sc, ccb);
503
504 next:
505 wmbi->stat = AHA_MBI_FREE;
506 aha_nextmbx(wmbi, wmbx, mbi);
507 } while (wmbi->stat != AHA_MBI_FREE);
508
509 wmbx->tmbi = wmbi;
510 }
511
512
513
514
515 int
516 ahaintr(arg)
517 void *arg;
518 {
519 struct aha_softc *sc = arg;
520 int iobase = sc->sc_iobase;
521 u_char sts;
522
523 #ifdef AHADEBUG
524 if (aha_debug)
525 printf("%s: ahaintr ", sc->sc_dev.dv_xname);
526 #endif
527
528
529
530
531
532 sts = inb(iobase + AHA_INTR_PORT);
533 if ((sts & AHA_INTR_ANYINTR) == 0)
534 return (0);
535 outb(iobase + AHA_CTRL_PORT, AHA_CTRL_IRST);
536
537 #ifdef AHADIAG
538
539 aha_collect_mbo(sc);
540 #endif
541
542
543 if (sts & AHA_INTR_MBOA) {
544 struct aha_toggle toggle;
545
546 toggle.cmd.opcode = AHA_MBO_INTR_EN;
547 toggle.cmd.enable = 0;
548 aha_cmd(iobase, sc, sizeof(toggle.cmd), (u_char *)&toggle.cmd,
549 0, (u_char *)0);
550 aha_start_ccbs(sc);
551 }
552
553
554 if (sts & AHA_INTR_MBIF)
555 aha_finish_ccbs(sc);
556
557 return (1);
558 }
559
560 void
561 aha_reset_ccb(sc, ccb)
562 struct aha_softc *sc;
563 struct aha_ccb *ccb;
564 {
565
566 ccb->flags = 0;
567 }
568
569
570
571
572 void
573 aha_free_ccb(sc, ccb)
574 struct aha_softc *sc;
575 struct aha_ccb *ccb;
576 {
577 int s, hashnum;
578 struct aha_ccb **hashccb;
579
580 s = splbio();
581
582 if (ccb->ccb_dmam->dm_segs[0].ds_addr != 0)
583 bus_dmamap_unload(sc->sc_dmat, ccb->ccb_dmam);
584
585
586
587 hashnum = CCB_HASH(ccb->ccb_dmam->dm_segs[0].ds_addr);
588 hashccb = &sc->sc_ccbhash[hashnum];
589
590 while (*hashccb) {
591 if ((*hashccb)->ccb_dmam->dm_segs[0].ds_addr ==
592 ccb->ccb_dmam->dm_segs[0].ds_addr) {
593 *hashccb = (*hashccb)->nexthash;
594 break;
595 }
596 hashccb = &(*hashccb)->nexthash;
597 }
598
599 aha_reset_ccb(sc, ccb);
600 TAILQ_INSERT_HEAD(&sc->sc_free_ccb, ccb, chain);
601
602
603
604
605
606 if (TAILQ_NEXT(ccb, chain) == NULL)
607 wakeup(&sc->sc_free_ccb);
608
609 splx(s);
610 }
611
612 int
613 aha_init_ccb(sc, ccb, flags)
614 struct aha_softc *sc;
615 struct aha_ccb *ccb;
616 int flags;
617 {
618 int error, wait, state = 0;
619
620 bzero(ccb, sizeof(struct aha_ccb));
621 aha_reset_ccb(sc, ccb);
622
623 wait = (flags & SCSI_NOSLEEP) ? BUS_DMA_NOWAIT : BUS_DMA_WAITOK;
624
625 error = bus_dmamap_create(sc->sc_dmat, MAXPHYS, (MAXPHYS / NBPG) + 1,
626 MAXPHYS, 0, wait | BUS_DMA_ALLOCNOW, &ccb->dmam);
627 if (error)
628 goto fail;
629 state++;
630
631
632 error = bus_dmamap_create(sc->sc_dmat, CCB_PHYS_SIZE, 1, CCB_PHYS_SIZE,
633 0, wait | BUS_DMA_ALLOCNOW, &ccb->ccb_dmam);
634 if (error)
635 goto fail;
636
637 return (0);
638
639 fail:
640 if (state > 0)
641 bus_dmamap_destroy(sc->sc_dmat, ccb->dmam);
642 return (error);
643 }
644
645
646
647
648
649
650
651 struct aha_ccb *
652 aha_get_ccb(sc, flags)
653 struct aha_softc *sc;
654 int flags;
655 {
656 struct aha_ccb *ccb;
657 int hashnum, s;
658
659 s = splbio();
660
661
662
663
664
665 for (;;) {
666 ccb = TAILQ_FIRST(&sc->sc_free_ccb);
667 if (ccb) {
668 TAILQ_REMOVE(&sc->sc_free_ccb, ccb, chain);
669 break;
670 }
671 if (sc->sc_numccbs < AHA_CCB_MAX) {
672 MALLOC(ccb, struct aha_ccb *, sizeof *ccb, M_DEVBUF,
673 (flags & SCSI_NOSLEEP) ? M_NOWAIT : M_WAITOK);
674 if (ccb == NULL) {
675 printf("%s: can't malloc ccb\n",
676 sc->sc_dev.dv_xname);
677 goto out;
678 }
679 if (aha_init_ccb(sc, ccb, flags) == 0) {
680 sc->sc_numccbs++;
681 break;
682 }
683 FREE(ccb, M_DEVBUF);
684 ccb = NULL;
685 }
686 if (flags & SCSI_NOSLEEP)
687 goto out;
688 tsleep(&sc->sc_free_ccb, PRIBIO, "ahaccb", 0);
689 }
690
691 ccb->flags |= CCB_ALLOC;
692
693 if (bus_dmamap_load(sc->sc_dmat, ccb->ccb_dmam, ccb, CCB_PHYS_SIZE,
694 NULL, BUS_DMA_NOWAIT) != 0) {
695 aha_free_ccb(sc, ccb);
696 ccb = NULL;
697 } else {
698 hashnum = CCB_HASH(ccb->ccb_dmam->dm_segs[0].ds_addr);
699 ccb->nexthash = sc->sc_ccbhash[hashnum];
700 sc->sc_ccbhash[hashnum] = ccb;
701 }
702 out:
703 splx(s);
704 return (ccb);
705 }
706
707
708
709
710 struct aha_ccb *
711 aha_ccb_phys_kv(sc, ccb_phys)
712 struct aha_softc *sc;
713 u_long ccb_phys;
714 {
715 int hashnum = CCB_HASH(ccb_phys);
716 struct aha_ccb *ccb = sc->sc_ccbhash[hashnum];
717
718 while (ccb) {
719 if (ccb->ccb_dmam->dm_segs[0].ds_addr == ccb_phys)
720 break;
721 ccb = ccb->nexthash;
722 }
723 return (ccb);
724 }
725
726
727
728
729 void
730 aha_queue_ccb(sc, ccb)
731 struct aha_softc *sc;
732 struct aha_ccb *ccb;
733 {
734
735 TAILQ_INSERT_TAIL(&sc->sc_waiting_ccb, ccb, chain);
736 aha_start_ccbs(sc);
737 }
738
739
740
741
742 void
743 aha_collect_mbo(sc)
744 struct aha_softc *sc;
745 {
746 struct aha_mbx_out *wmbo;
747 #ifdef AHADIAG
748 struct aha_ccb *ccb;
749 #endif
750
751 wmbo = wmbx->cmbo;
752
753 while (sc->sc_mbofull > 0) {
754 if (wmbo->cmd != AHA_MBO_FREE)
755 break;
756
757 #ifdef AHADIAG
758 ccb = aha_ccb_phys_kv(sc, phystol(wmbo->ccb_addr));
759 if (!ccb) {
760 printf("%s: bad mbo ccb pointer; skipping\n",
761 sc->sc_dev.dv_xname);
762 } else
763 ccb->flags &= ~CCB_SENDING;
764 #endif
765
766 --sc->sc_mbofull;
767 aha_nextmbx(wmbo, wmbx, mbo);
768 }
769
770 wmbx->cmbo = wmbo;
771 }
772
773
774
775
776 void
777 aha_start_ccbs(sc)
778 struct aha_softc *sc;
779 {
780 int iobase = sc->sc_iobase;
781 struct aha_mbx_out *wmbo;
782 struct aha_ccb *ccb;
783
784 wmbo = wmbx->tmbo;
785
786 while ((ccb = TAILQ_FIRST(&sc->sc_waiting_ccb)) != NULL) {
787 if (sc->sc_mbofull >= AHA_MBX_SIZE) {
788 aha_collect_mbo(sc);
789 if (sc->sc_mbofull >= AHA_MBX_SIZE) {
790 struct aha_toggle toggle;
791
792 toggle.cmd.opcode = AHA_MBO_INTR_EN;
793 toggle.cmd.enable = 1;
794 aha_cmd(iobase, sc, sizeof(toggle.cmd),
795 (u_char *)&toggle.cmd, 0, (u_char *)0);
796 break;
797 }
798 }
799
800 TAILQ_REMOVE(&sc->sc_waiting_ccb, ccb, chain);
801 #ifdef AHADIAG
802 ccb->flags |= CCB_SENDING;
803 #endif
804
805
806 bus_dmamap_sync(sc->sc_dmat, ccb->ccb_dmam, 0,
807 ccb->ccb_dmam->dm_mapsize, BUS_DMASYNC_PREWRITE);
808 ltophys(ccb->ccb_dmam->dm_segs[0].ds_addr, wmbo->ccb_addr);
809 if (ccb->flags & CCB_ABORT)
810 wmbo->cmd = AHA_MBO_ABORT;
811 else
812 wmbo->cmd = AHA_MBO_START;
813
814
815 outb(iobase + AHA_CMD_PORT, AHA_START_SCSI);
816
817 if ((ccb->xs->flags & SCSI_POLL) == 0) {
818 timeout_set(&ccb->xs->stimeout, aha_timeout, ccb);
819 timeout_add(&ccb->xs->stimeout, (ccb->timeout * hz) / 1000);
820 }
821
822 ++sc->sc_mbofull;
823 aha_nextmbx(wmbo, wmbx, mbo);
824 }
825
826 wmbx->tmbo = wmbo;
827 }
828
829
830
831
832
833
834 void
835 aha_done(sc, ccb)
836 struct aha_softc *sc;
837 struct aha_ccb *ccb;
838 {
839 struct scsi_sense_data *s1, *s2;
840 struct scsi_xfer *xs = ccb->xs;
841
842 SC_DEBUG(xs->sc_link, SDEV_DB2, ("aha_done\n"));
843
844
845
846
847 #ifdef AHADIAG
848 if (ccb->flags & CCB_SENDING) {
849 printf("%s: exiting ccb still in transit!\n",
850 sc->sc_dev.dv_xname);
851 Debugger();
852 return;
853 }
854 #endif
855 if ((ccb->flags & CCB_ALLOC) == 0) {
856 printf("%s: exiting ccb not allocated!\n",
857 sc->sc_dev.dv_xname);
858 Debugger();
859 return;
860 }
861 if (xs->error == XS_NOERROR) {
862 if (ccb->host_stat != AHA_OK) {
863 switch (ccb->host_stat) {
864 case AHA_SEL_TIMEOUT:
865 xs->error = XS_SELTIMEOUT;
866 break;
867 default:
868 printf("%s: host_stat %x\n",
869 sc->sc_dev.dv_xname, ccb->host_stat);
870 xs->error = XS_DRIVER_STUFFUP;
871 break;
872 }
873 } else if (ccb->target_stat != SCSI_OK) {
874 switch (ccb->target_stat) {
875 case SCSI_CHECK:
876 s1 = (struct scsi_sense_data *)
877 (((char *)(&ccb->scsi_cmd)) +
878 ccb->scsi_cmd_length);
879 s2 = &xs->sense;
880 *s2 = *s1;
881 xs->error = XS_SENSE;
882 break;
883 case SCSI_BUSY:
884 xs->error = XS_BUSY;
885 break;
886 default:
887 printf("%s: target_stat %x\n",
888 sc->sc_dev.dv_xname, ccb->target_stat);
889 xs->error = XS_DRIVER_STUFFUP;
890 break;
891 }
892 } else
893 xs->resid = 0;
894 }
895 xs->flags |= ITSDONE;
896
897 if (VOLATILE_XS(xs)) {
898 wakeup(ccb);
899 return;
900 }
901
902 if (ccb->dmam->dm_nsegs > 0) {
903 if (xs->flags & SCSI_DATA_IN)
904 bus_dmamap_sync(sc->sc_dmat, ccb->dmam, 0,
905 ccb->dmam->dm_mapsize, BUS_DMASYNC_POSTREAD);
906 if (xs->flags & SCSI_DATA_OUT)
907 bus_dmamap_sync(sc->sc_dmat, ccb->dmam, 0,
908 ccb->dmam->dm_mapsize, BUS_DMASYNC_POSTWRITE);
909 bus_dmamap_unload(sc->sc_dmat, ccb->dmam);
910 }
911 aha_free_ccb(sc, ccb);
912 scsi_done(xs);
913 }
914
915
916
917
918 int
919 aha_find(ia, sc, isapnp)
920 struct isa_attach_args *ia;
921 struct aha_softc *sc;
922 int isapnp;
923 {
924 int iobase = ia->ia_iobase;
925 int i;
926 u_char sts;
927 struct aha_config config;
928 int irq, drq;
929
930
931
932
933
934
935 outb(iobase + AHA_CTRL_PORT, AHA_CTRL_HRST | AHA_CTRL_SRST);
936
937 delay(100);
938 for (i = AHA_RESET_TIMEOUT; i; i--) {
939 sts = inb(iobase + AHA_STAT_PORT);
940 if (sts == (AHA_STAT_IDLE | AHA_STAT_INIT))
941 break;
942 delay(1000);
943 }
944 if (!i) {
945 #ifdef AHADEBUG
946 if (aha_debug)
947 printf("aha_find: No answer from adaptec board\n");
948 #endif
949 return (1);
950 }
951
952
953
954
955
956 delay(1000);
957 config.cmd.opcode = AHA_INQUIRE_CONFIG;
958 aha_cmd(iobase, sc, sizeof(config.cmd), (u_char *)&config.cmd,
959 sizeof(config.reply), (u_char *)&config.reply);
960 switch (config.reply.chan) {
961 case EISADMA:
962 drq = DRQUNK;
963 break;
964 case CHAN0:
965 drq = 0;
966 break;
967 case CHAN5:
968 drq = 5;
969 break;
970 case CHAN6:
971 drq = 6;
972 break;
973 case CHAN7:
974 drq = 7;
975 break;
976 default:
977 printf("aha_find: illegal drq setting %x\n",
978 config.reply.chan);
979 return (1);
980 }
981 if (isapnp)
982 irq = ia->ia_irq;
983
984 switch (config.reply.intr) {
985 case INT9:
986 irq = 9;
987 break;
988 case INT10:
989 irq = 10;
990 break;
991 case INT11:
992 irq = 11;
993 break;
994 case INT12:
995 irq = 12;
996 break;
997 case INT14:
998 irq = 14;
999 break;
1000 case INT15:
1001 irq = 15;
1002 break;
1003 default:
1004 printf("aha_find: illegal irq setting %x\n",
1005 config.reply.intr);
1006 return (EIO);
1007 }
1008 if (isapnp)
1009 drq = ia->ia_drq;
1010
1011 if (sc != NULL) {
1012
1013 sc->sc_scsi_dev = config.reply.scsi_dev;
1014
1015 sc->sc_iobase = iobase;
1016 sc->sc_irq = irq;
1017 sc->sc_drq = drq;
1018 } else {
1019 if (isapnp)
1020 return (0);
1021 if (ia->ia_irq == IRQUNK)
1022 ia->ia_irq = irq;
1023 else if (ia->ia_irq != irq)
1024 return (1);
1025 if (ia->ia_drq == DRQUNK)
1026 ia->ia_drq = drq;
1027 else if (ia->ia_drq != drq)
1028 return (1);
1029 }
1030
1031 return (0);
1032 }
1033
1034
1035
1036
1037 void
1038 aha_init(sc)
1039 struct aha_softc *sc;
1040 {
1041 int iobase = sc->sc_iobase;
1042 struct aha_devices devices;
1043 struct aha_setup setup;
1044 struct aha_mailbox mailbox;
1045 struct pglist pglist;
1046 struct vm_page *pg;
1047 vaddr_t va;
1048 vsize_t size;
1049 int i;
1050
1051
1052
1053
1054
1055
1056
1057
1058 if (!strncmp(sc->sc_model, "1542C", 5)) {
1059 struct aha_extbios extbios;
1060 struct aha_unlock unlock;
1061
1062 printf("%s: unlocking mailbox interface\n",
1063 sc->sc_dev.dv_xname);
1064 extbios.cmd.opcode = AHA_EXT_BIOS;
1065 aha_cmd(iobase, sc, sizeof(extbios.cmd),
1066 (u_char *)&extbios.cmd, sizeof(extbios.reply),
1067 (u_char *)&extbios.reply);
1068
1069 #ifdef AHADEBUG
1070 printf("%s: flags=%02x, mailboxlock=%02x\n",
1071 sc->sc_dev.dv_xname,
1072 extbios.reply.flags, extbios.reply.mailboxlock);
1073 #endif
1074
1075 unlock.cmd.opcode = AHA_MBX_ENABLE;
1076 unlock.cmd.junk = 0;
1077 unlock.cmd.magic = extbios.reply.mailboxlock;
1078 aha_cmd(iobase, sc, sizeof(unlock.cmd), (u_char *)&unlock.cmd,
1079 0, (u_char *)0);
1080 }
1081
1082 #if 0
1083
1084
1085
1086 aha_cmd(sc, 1, 0, 0, 0, AHA_BUS_ON_TIME_SET, 7);
1087 aha_cmd(sc, 1, 0, 0, 0, AHA_BUS_OFF_TIME_SET, 4);
1088 #endif
1089
1090
1091 devices.cmd.opcode = AHA_INQUIRE_DEVICES;
1092 aha_cmd(iobase, sc, sizeof(devices.cmd), (u_char *)&devices.cmd,
1093 sizeof(devices.reply), (u_char *)&devices.reply);
1094
1095
1096 setup.cmd.opcode = AHA_INQUIRE_SETUP;
1097 setup.cmd.len = sizeof(setup.reply);
1098 aha_cmd(iobase, sc, sizeof(setup.cmd), (u_char *)&setup.cmd,
1099 sizeof(setup.reply), (u_char *)&setup.reply);
1100
1101 printf("%s: %s, %s\n",
1102 sc->sc_dev.dv_xname,
1103 setup.reply.sync_neg ? "sync" : "async",
1104 setup.reply.parity ? "parity" : "no parity");
1105
1106 for (i = 0; i < 8; i++) {
1107 if (!setup.reply.sync[i].valid ||
1108 (!setup.reply.sync[i].offset &&
1109 !setup.reply.sync[i].period))
1110 continue;
1111 printf("%s targ %d: sync, offset %d, period %dnsec\n",
1112 sc->sc_dev.dv_xname, i, setup.reply.sync[i].offset,
1113 setup.reply.sync[i].period * 50 + 200);
1114 }
1115
1116
1117
1118
1119
1120
1121
1122
1123 size = round_page(sizeof(struct aha_mbx));
1124 TAILQ_INIT(&pglist);
1125 if (uvm_pglistalloc(size, 0, 0xffffff, PAGE_SIZE, 0, &pglist, 1, 0) ||
1126 uvm_map(kernel_map, &va, size, NULL, UVM_UNKNOWN_OFFSET, 0,
1127 UVM_MAPFLAG(UVM_PROT_ALL, UVM_PROT_ALL, UVM_INH_NONE,
1128 UVM_ADV_RANDOM, 0)))
1129 panic("aha_init: could not allocate mailbox");
1130
1131 wmbx = (struct aha_mbx *)va;
1132 for (pg = TAILQ_FIRST(&pglist); pg != NULL;
1133 pg = TAILQ_NEXT(pg, pageq)) {
1134 pmap_kenter_pa(va, VM_PAGE_TO_PHYS(pg),
1135 VM_PROT_READ|VM_PROT_WRITE);
1136 va += PAGE_SIZE;
1137 }
1138 pmap_update(pmap_kernel());
1139
1140
1141
1142
1143 for (i = 0; i < AHA_MBX_SIZE; i++) {
1144 wmbx->mbo[i].cmd = AHA_MBO_FREE;
1145 wmbx->mbi[i].stat = AHA_MBI_FREE;
1146 }
1147 wmbx->cmbo = wmbx->tmbo = &wmbx->mbo[0];
1148 wmbx->tmbi = &wmbx->mbi[0];
1149 sc->sc_mbofull = 0;
1150
1151
1152 mailbox.cmd.opcode = AHA_MBX_INIT;
1153 mailbox.cmd.nmbx = AHA_MBX_SIZE;
1154 ltophys(vtophys((vaddr_t)wmbx), mailbox.cmd.addr);
1155 aha_cmd(iobase, sc, sizeof(mailbox.cmd), (u_char *)&mailbox.cmd,
1156 0, (u_char *)0);
1157 }
1158
1159 void
1160 aha_inquire_setup_information(sc)
1161 struct aha_softc *sc;
1162 {
1163 int iobase = sc->sc_iobase;
1164 struct aha_revision revision;
1165 u_char sts;
1166 int i;
1167 char *p;
1168
1169 strlcpy(sc->sc_model, "unknown", sizeof sc->sc_model);
1170
1171
1172
1173
1174
1175
1176
1177 revision.cmd.opcode = AHA_INQUIRE_REVISION;
1178 if (aha_cmd(iobase, sc, sizeof(revision.cmd), (u_char *)&revision.cmd,
1179 sizeof(revision.reply), (u_char *)&revision.reply)) {
1180
1181
1182
1183
1184 for (i = AHA_RESET_TIMEOUT; i; i--) {
1185 sts = inb(iobase + AHA_STAT_PORT);
1186 if (sts == (AHA_STAT_IDLE | AHA_STAT_INIT))
1187 break;
1188 delay(1000);
1189 }
1190 if (!i) {
1191 #ifdef AHADEBUG
1192 printf("aha_init: soft reset failed\n");
1193 #endif
1194 return;
1195 }
1196 #ifdef AHADEBUG
1197 printf("aha_init: inquire command failed\n");
1198 #endif
1199 goto noinquire;
1200 }
1201
1202 #ifdef AHADEBUG
1203 printf("%s: inquire %x, %x, %x, %x\n",
1204 sc->sc_dev.dv_xname,
1205 revision.reply.boardid, revision.reply.spec_opts,
1206 revision.reply.revision_1, revision.reply.revision_2);
1207 #endif
1208
1209 switch (revision.reply.boardid) {
1210 case 0x31:
1211 strlcpy(sc->sc_model, "1540", sizeof sc->sc_model);
1212 break;
1213 case 0x41:
1214 strlcpy(sc->sc_model, "1540A/1542A/1542B", sizeof sc->sc_model);
1215 break;
1216 case 0x42:
1217 strlcpy(sc->sc_model, "1640", sizeof sc->sc_model);
1218 break;
1219 case 0x43:
1220 case 0x44:
1221 strlcpy(sc->sc_model, "1542C", sizeof sc->sc_model);
1222 break;
1223 case 0x45:
1224 strlcpy(sc->sc_model, "1542CF", sizeof sc->sc_model);
1225 break;
1226 case 0x46:
1227 strlcpy(sc->sc_model, "1542CP", sizeof sc->sc_model);
1228 break;
1229 }
1230
1231 p = sc->sc_firmware;
1232 *p++ = revision.reply.revision_1;
1233 *p++ = '.';
1234 *p++ = revision.reply.revision_2;
1235 *p = '\0';
1236
1237 noinquire:
1238 printf(": model AHA-%s, firmware %s\n", sc->sc_model, sc->sc_firmware);
1239 }
1240
1241 void
1242 ahaminphys(bp)
1243 struct buf *bp;
1244 {
1245
1246 if (bp->b_bcount > ((AHA_NSEG - 1) << PGSHIFT))
1247 bp->b_bcount = ((AHA_NSEG - 1) << PGSHIFT);
1248 minphys(bp);
1249 }
1250
1251
1252
1253
1254
1255 int
1256 aha_scsi_cmd(xs)
1257 struct scsi_xfer *xs;
1258 {
1259 struct scsi_link *sc_link = xs->sc_link;
1260 struct aha_softc *sc = sc_link->adapter_softc;
1261 struct aha_ccb *ccb;
1262 struct aha_scat_gath *sg;
1263 int seg, flags;
1264 #ifdef TFS
1265 struct iovec *iovp;
1266 int datalen;
1267 #endif
1268 int s;
1269
1270 SC_DEBUG(sc_link, SDEV_DB2, ("aha_scsi_cmd\n"));
1271
1272
1273
1274
1275
1276 flags = xs->flags;
1277 if ((ccb = aha_get_ccb(sc, flags)) == NULL) {
1278 return (TRY_AGAIN_LATER);
1279 }
1280 ccb->xs = xs;
1281 ccb->timeout = xs->timeout;
1282
1283
1284
1285
1286 if (flags & SCSI_RESET) {
1287 ccb->opcode = AHA_RESET_CCB;
1288 ccb->scsi_cmd_length = 0;
1289 } else {
1290
1291 ccb->opcode =
1292 (xs->datalen ? AHA_INIT_SCAT_GATH_CCB : AHA_INITIATOR_CCB);
1293 bcopy(xs->cmd, &ccb->scsi_cmd,
1294 ccb->scsi_cmd_length = xs->cmdlen);
1295 }
1296
1297 if (xs->datalen) {
1298 sg = ccb->scat_gath;
1299 seg = 0;
1300 #ifdef TFS
1301 if (flags & SCSI_DATA_UIO) {
1302 iovp = ((struct uio *)xs->data)->uio_iov;
1303 datalen = ((struct uio *)xs->data)->uio_iovcnt;
1304 xs->datalen = 0;
1305 while (datalen && seg < AHA_NSEG) {
1306 ltophys(iovp->iov_base, sg->seg_addr);
1307 ltophys(iovp->iov_len, sg->seg_len);
1308 xs->datalen += iovp->iov_len;
1309 SC_DEBUGN(sc_link, SDEV_DB4, ("UIO(0x%x@0x%x)",
1310 iovp->iov_len, iovp->iov_base));
1311 sg++;
1312 iovp++;
1313 seg++;
1314 datalen--;
1315 }
1316 } else
1317 #endif
1318 {
1319
1320
1321
1322 if (bus_dmamap_load(sc->sc_dmat, ccb->dmam, xs->data,
1323 xs->datalen, NULL, BUS_DMA_NOWAIT) != 0) {
1324 aha_free_ccb(sc, ccb);
1325 xs->error = XS_DRIVER_STUFFUP;
1326 return (TRY_AGAIN_LATER);
1327 }
1328 for (seg = 0; seg < ccb->dmam->dm_nsegs; seg++) {
1329 ltophys(ccb->dmam->dm_segs[seg].ds_addr,
1330 sg[seg].seg_addr);
1331 ltophys(ccb->dmam->dm_segs[seg].ds_len,
1332 sg[seg].seg_len);
1333 }
1334 }
1335 if (flags & SCSI_DATA_OUT)
1336 bus_dmamap_sync(sc->sc_dmat, ccb->dmam, 0,
1337 ccb->dmam->dm_mapsize, BUS_DMASYNC_PREWRITE);
1338 if (flags & SCSI_DATA_IN)
1339 bus_dmamap_sync(sc->sc_dmat, ccb->dmam, 0,
1340 ccb->dmam->dm_mapsize, BUS_DMASYNC_PREREAD);
1341 ltophys((unsigned)
1342 ((struct aha_ccb *)(ccb->ccb_dmam->dm_segs[0].ds_addr))->
1343 scat_gath,
1344 ccb->data_addr);
1345 ltophys(ccb->dmam->dm_nsegs * sizeof(struct aha_scat_gath),
1346 ccb->data_length);
1347 } else {
1348 ltophys(0, ccb->data_addr);
1349 ltophys(0, ccb->data_length);
1350 }
1351
1352 ccb->data_out = 0;
1353 ccb->data_in = 0;
1354 ccb->target = sc_link->target;
1355 ccb->lun = sc_link->lun;
1356 ccb->req_sense_length = sizeof(ccb->scsi_sense);
1357 ccb->host_stat = 0x00;
1358 ccb->target_stat = 0x00;
1359 ccb->link_id = 0;
1360 ltophys(0, ccb->link_addr);
1361
1362 s = splbio();
1363 aha_queue_ccb(sc, ccb);
1364
1365
1366
1367
1368 SC_DEBUG(sc_link, SDEV_DB3, ("cmd_sent\n"));
1369
1370 if (VOLATILE_XS(xs)) {
1371 while ((ccb->xs->flags & ITSDONE) == 0) {
1372 tsleep(ccb, PRIBIO, "ahawait", 0);
1373 }
1374 if (ccb->dmam->dm_nsegs > 0) {
1375 if (flags & SCSI_DATA_OUT)
1376 bus_dmamap_sync(sc->sc_dmat, ccb->dmam, 0,
1377 ccb->dmam->dm_mapsize,
1378 BUS_DMASYNC_POSTWRITE);
1379 if (flags & SCSI_DATA_IN)
1380 bus_dmamap_sync(sc->sc_dmat, ccb->dmam, 0,
1381 ccb->dmam->dm_mapsize,
1382 BUS_DMASYNC_POSTREAD);
1383 bus_dmamap_unload(sc->sc_dmat, ccb->dmam);
1384 }
1385 aha_free_ccb(sc, ccb);
1386 scsi_done(xs);
1387 splx(s);
1388 return (COMPLETE);
1389 }
1390 splx(s);
1391
1392 if ((flags & SCSI_POLL) == 0)
1393 return (SUCCESSFULLY_QUEUED);
1394
1395
1396
1397
1398 if (aha_poll(sc, xs, ccb->timeout)) {
1399 aha_timeout(ccb);
1400 if (aha_poll(sc, xs, ccb->timeout))
1401 aha_timeout(ccb);
1402 }
1403 return (COMPLETE);
1404 }
1405
1406
1407
1408
1409 int
1410 aha_poll(sc, xs, count)
1411 struct aha_softc *sc;
1412 struct scsi_xfer *xs;
1413 int count;
1414 {
1415 int iobase = sc->sc_iobase;
1416 int s;
1417
1418
1419 while (count) {
1420
1421
1422
1423
1424 if (inb(iobase + AHA_INTR_PORT) & AHA_INTR_ANYINTR) {
1425 s = splbio();
1426 ahaintr(sc);
1427 splx(s);
1428 }
1429 if (xs->flags & ITSDONE)
1430 return (0);
1431 delay(1000);
1432 count--;
1433 }
1434 return (1);
1435 }
1436
1437 void
1438 aha_timeout(arg)
1439 void *arg;
1440 {
1441 struct aha_ccb *ccb = arg;
1442 struct scsi_xfer *xs;
1443 struct scsi_link *sc_link;
1444 struct aha_softc *sc;
1445 int s;
1446
1447 s = splbio();
1448 bus_dmamap_sync(sc->sc_dmat, ccb->ccb_dmam, 0,
1449 ccb->ccb_dmam->dm_mapsize, BUS_DMASYNC_POSTREAD);
1450 xs = ccb->xs;
1451 sc_link = xs->sc_link;
1452 sc = sc_link->adapter_softc;
1453
1454 sc_print_addr(sc_link);
1455 printf("timed out");
1456
1457 #ifdef AHADIAG
1458
1459
1460
1461 aha_collect_mbo(sc);
1462 if (ccb->flags & CCB_SENDING) {
1463 printf("%s: not taking commands!\n", sc->sc_dev.dv_xname);
1464 Debugger();
1465 }
1466 #endif
1467
1468
1469
1470
1471
1472
1473 if (ccb->flags & CCB_ABORT) {
1474
1475 printf(" AGAIN\n");
1476
1477 } else {
1478
1479 printf("\n");
1480 ccb->xs->error = XS_TIMEOUT;
1481 ccb->timeout = AHA_ABORT_TIMEOUT;
1482 ccb->flags |= CCB_ABORT;
1483 aha_queue_ccb(sc, ccb);
1484 }
1485
1486 splx(s);
1487 }
1488