Annotation of sys/dev/isa/aha.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: aha.c,v 1.57 2007/08/15 02:04:30 krw Exp $ */
2: /* $NetBSD: aha.c,v 1.11 1996/05/12 23:51:23 mycroft Exp $ */
3:
4: #undef AHADIAG
5:
6: /*
7: * Copyright (c) 1994, 1996 Charles M. Hannum. All rights reserved.
8: *
9: * Redistribution and use in source and binary forms, with or without
10: * modification, are permitted provided that the following conditions
11: * are met:
12: * 1. Redistributions of source code must retain the above copyright
13: * notice, this list of conditions and the following disclaimer.
14: * 2. Redistributions in binary form must reproduce the above copyright
15: * notice, this list of conditions and the following disclaimer in the
16: * documentation and/or other materials provided with the distribution.
17: * 3. All advertising materials mentioning features or use of this software
18: * must display the following acknowledgement:
19: * This product includes software developed by Charles M. Hannum.
20: * 4. The name of the author may not be used to endorse or promote products
21: * derived from this software without specific prior written permission.
22: *
23: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
24: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
25: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
27: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
28: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
32: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33: */
34:
35: /*
36: * Originally written by Julian Elischer (julian@tfs.com)
37: * for TRW Financial Systems for use under the MACH(2.5) operating system.
38: *
39: * TRW Financial Systems, in accordance with their agreement with Carnegie
40: * Mellon University, makes this software available to CMU to distribute
41: * or use in any manner that they see fit as long as this message is kept with
42: * the software. For this reason TFS also grants any other persons or
43: * organisations permission to use or modify this software.
44: *
45: * TFS supplies this software to be publicly redistributed
46: * on the understanding that TFS is not responsible for the correct
47: * functioning of this software in any circumstances.
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 /* ! DDB */
79:
80: /* XXX fixme:
81: * on i386 at least, xfers to/from user memory
82: * cannot be serviced at interrupt time.
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: * Mail box defs etc.
94: * these could be bigger but we need the aha_softc to fit on a single page..
95: */
96: #define AHA_MBX_SIZE 16 /* mail box size */
97:
98: #define AHA_CCB_MAX 16 /* store up to 32 CCBs at one time */
99: #define CCB_HASH_SIZE 16 /* hash table size for phystokv */
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; /* Collection Mail Box out */
113: struct aha_mbx_out *tmbo; /* Target Mail Box out */
114: struct aha_mbx_in *tmbi; /* Target Mail Box in */
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; /* all the mailboxes */
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; /* our scsi id */
135: struct scsi_link sc_link;
136: };
137:
138: #ifdef AHADEBUG
139: int aha_debug = 1;
140: #endif /* AHADEBUG */
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: /* the below structure is so we have a default dev struct for out link struct */
170: struct scsi_device aha_dev = {
171: NULL, /* Use default error handler */
172: NULL, /* have a queue, served by this */
173: NULL, /* have no async handler */
174: NULL, /* Use default 'done' routine */
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 /* time to wait for reset (mSec) */
194: #define AHA_ABORT_TIMEOUT 2000 /* time to wait for abort (mSec) */
195:
196: #include "bha.h"
197:
198: /*
199: * aha_cmd(iobase, sc, icnt, ibuf, ocnt, obuf)
200: *
201: * Activate Adapter command
202: * icnt: number of args (outbound bytes including opcode)
203: * ibuf: argument buffer
204: * ocnt: number of expected returned bytes
205: * obuf: result buffer
206: * wait: number of seconds to wait for response
207: *
208: * Performs an adapter command through the ports. Not to be confused with a
209: * scsi command, which is read in via the dma; one of the adapter commands
210: * tells it to read in a scsi command.
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: * Calculate a reasonable timeout for the command.
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: * Wait for the adapter to go idle, unless it's one of
244: * the commands which don't need this
245: */
246: if (opcode != AHA_MBO_INTR_EN) {
247: for (i = 20000; i; i--) { /* 1 sec? */
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: * Now that it is idle, if we expect output, preflush the
261: * queue feeding to us.
262: */
263: if (ocnt) {
264: while ((inb(iobase + AHA_STAT_PORT)) & AHA_STAT_DF)
265: inb(iobase + AHA_DATA_PORT);
266: }
267: /*
268: * Output the command and the number of arguments given
269: * for each byte, first check the port is empty.
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: * If we expect input, loop that many times, each time,
289: * looking for the data register to have valid data
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: * Wait for the board to report a finished instruction.
309: * We may get an extra interrupt for the HACC signal, but this is
310: * unimportant.
311: */
312: if (opcode != AHA_MBO_INTR_EN) {
313: for (i = 20000; i; i--) { /* 1 sec? */
314: sts = inb(iobase + AHA_INTR_PORT);
315: /* XXX Need to save this in the interrupt handler? */
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: * Check if the device can be found at the port given
341: * and if so, set it up ready for further work
342: * as an argument, takes the isa_device structure from
343: * autoconf.c
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: /* See if there is a unit at this location. */
361: if (aha_find(ia, NULL, 0) != 0)
362: return (0);
363:
364: ia->ia_msize = 0;
365: ia->ia_iosize = 4;
366: /* IRQ and DRQ set by aha_find(). */
367: return (1);
368: }
369:
370: /*
371: * Attach all the sub-devices we can find
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: * fill in the prototype scsi_link.
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: * ask the adapter what subunits are present
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 /* AHADEBUG */
467:
468: switch (wmbi->stat) {
469: case AHA_MBI_OK:
470: case AHA_MBI_ERROR:
471: if ((ccb->flags & CCB_ABORT) != 0) {
472: /*
473: * If we already started an abort, wait for it
474: * to complete before clearing the CCB. We
475: * could instead just clear CCB_SENDING, but
476: * what if the mailbox was already received?
477: * The worst that happens here is that we clear
478: * the CCB a bit later than we need to. BFD.
479: */
480: goto next;
481: }
482: break;
483:
484: case AHA_MBI_ABORT:
485: case AHA_MBI_UNKNOWN:
486: /*
487: * Even if the CCB wasn't found, we clear it anyway.
488: * See preceding comment.
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: * Catch an interrupt from the adaptor
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 /*AHADEBUG */
527:
528: /*
529: * First acknowlege the interrupt, Then if it's not telling about
530: * a completed operation just return.
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: /* Make sure we clear CCB_SENDING before finishing a CCB. */
539: aha_collect_mbo(sc);
540: #endif
541:
542: /* Mail box out empty? */
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: /* Mail box in full? */
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: * A ccb is put onto the free list.
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: /* remove from hash table */
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: * If there were none, wake anybody waiting for one to come free,
604: * starting with queued entries.
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: /* Create a DMA map for the data area. */
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: /* Create a DMA map for the command control block. */
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: * Get a free ccb
647: *
648: * If there are none, see if we can allocate a new one. If so, put it in
649: * the hash table too otherwise either return an error or sleep.
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: * If we can and have to, sleep waiting for one to come free
663: * but only if we can't allocate a new one.
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: * Given a physical address, find the ccb that it corresponds to.
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: * Queue a CCB to be sent to the controller, and send it if possible.
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: * Garbage collect mailboxes that are no longer in use.
741: */
742: void
743: aha_collect_mbo(sc)
744: struct aha_softc *sc;
745: {
746: struct aha_mbx_out *wmbo; /* Mail Box Out pointer */
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: * Send as many CCBs as we have empty mailboxes for.
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; /* Mail Box Out pointer */
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: /* Link ccb to mbo. */
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: /* Tell the card to poll immediately. */
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: * We have a ccb which has been processed by the
831: * adaptor, now we look to see how the operation
832: * went. Wake up the owner if waiting
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: * Otherwise, put the results of the operation
845: * into the xfer and call whoever started it
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: /* No response */
865: xs->error = XS_SELTIMEOUT;
866: break;
867: default: /* Other scsi protocol messes */
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: * Find the board and find its irq/drq
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: * reset board, If it doesn't respond, assume
932: * that it's not there.. good for the probe
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); /* calibrated in msec */
943: }
944: if (!i) {
945: #ifdef AHADEBUG
946: if (aha_debug)
947: printf("aha_find: No answer from adaptec board\n");
948: #endif /* AHADEBUG */
949: return (1);
950: }
951:
952: /*
953: * setup dma channel from jumpers and save int
954: * level
955: */
956: delay(1000); /* for Bustek 545 */
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; /* for EISA/VLB/PCI clones */
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: /* who are we on the scsi bus? */
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: * Start the board, ready for normal operation
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: * XXX
1053: * If we are a 1542C or later, disable the extended BIOS so that the
1054: * mailbox interface is unlocked.
1055: * No need to check the extended BIOS flags as some of the
1056: * extensions that cause us problems are not flagged in that byte.
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 /* AHADEBUG */
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: * Change the bus on/off times to not clash with other dma users.
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: /* Inquire Installed Devices (to force synchronous negotiation). */
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: /* Obtain setup information from. */
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: * Set up initial mail box for round-robin operation.
1118: */
1119:
1120: /*
1121: * XXX - this vm juggling is so wrong. use bus_dma instead!
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: * XXXEND
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: /* Initialize mail box. */
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: * Assume we have a board at this stage, do an adapter inquire
1173: * to find out what type of controller it is. If the command
1174: * fails, we assume it's either a crusty board or an old 1542
1175: * clone, and skip the board-specific stuff.
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: * aha_cmd() already started the reset. It's not clear we
1182: * even need to bother here.
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 /* AHADEBUG */
1194: return;
1195: }
1196: #ifdef AHADEBUG
1197: printf("aha_init: inquire command failed\n");
1198: #endif /* AHADEBUG */
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 /* AHADEBUG */
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: /* Is this 1542C or -CF? */
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: * start a scsi operation given the command and the data address. Also needs
1253: * the unit, target and lu.
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: * get a ccb to use. If the transfer
1273: * is from a buf (possibly from interrupt time)
1274: * then we can't allow it to sleep
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: * Put all the arguments for the xfer in the ccb
1285: */
1286: if (flags & SCSI_RESET) {
1287: ccb->opcode = AHA_RESET_CCB;
1288: ccb->scsi_cmd_length = 0;
1289: } else {
1290: /* can't use S/G if zero length */
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 /* TFS */
1318: {
1319: /*
1320: * Set up the scatter-gather block.
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 { /* No data xfer, use non S/G values */
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: * Usually return SUCCESSFULLY QUEUED
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: * If we can't use interrupts, poll on completion
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: * Poll a particular unit, looking for a particular xs
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: /* timeouts are in msec, so we loop in 1000 usec cycles */
1419: while (count) {
1420: /*
1421: * If we had interrupts enabled, would we
1422: * have got an interrupt?
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); /* only happens in boot so ok */
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: * If The ccb's mbx is not free, then the board has gone south?
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: * If it has been through before, then
1470: * a previous abort has failed, don't
1471: * try abort again
1472: */
1473: if (ccb->flags & CCB_ABORT) {
1474: /* abort timed out */
1475: printf(" AGAIN\n");
1476: /* XXX Must reset! */
1477: } else {
1478: /* abort the operation that has timed out */
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:
CVSweb