aha.c revision 1.9 1 /* $NetBSD: aha.c,v 1.9 1997/10/28 23:31:30 thorpej Exp $ */
2
3 #undef AHADIAG
4 #ifdef DDB
5 #define integrate
6 #else
7 #define integrate static inline
8 #endif
9
10 /*-
11 * Copyright (c) 1997 The NetBSD Foundation, Inc.
12 * All rights reserved.
13 *
14 * This code is derived from software contributed to The NetBSD Foundation
15 * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
16 * NASA Ames Research Center.
17 *
18 * Redistribution and use in source and binary forms, with or without
19 * modification, are permitted provided that the following conditions
20 * are met:
21 * 1. Redistributions of source code must retain the above copyright
22 * notice, this list of conditions and the following disclaimer.
23 * 2. Redistributions in binary form must reproduce the above copyright
24 * notice, this list of conditions and the following disclaimer in the
25 * documentation and/or other materials provided with the distribution.
26 * 3. All advertising materials mentioning features or use of this software
27 * must display the following acknowledgement:
28 * This product includes software developed by the NetBSD
29 * Foundation, Inc. and its contributors.
30 * 4. Neither the name of The NetBSD Foundation nor the names of its
31 * contributors may be used to endorse or promote products derived
32 * from this software without specific prior written permission.
33 *
34 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
35 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
36 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
37 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
38 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
39 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
40 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
41 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
42 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
43 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
44 * POSSIBILITY OF SUCH DAMAGE.
45 */
46
47 /*
48 * Copyright (c) 1994, 1996, 1997 Charles M. Hannum. All rights reserved.
49 *
50 * Redistribution and use in source and binary forms, with or without
51 * modification, are permitted provided that the following conditions
52 * are met:
53 * 1. Redistributions of source code must retain the above copyright
54 * notice, this list of conditions and the following disclaimer.
55 * 2. Redistributions in binary form must reproduce the above copyright
56 * notice, this list of conditions and the following disclaimer in the
57 * documentation and/or other materials provided with the distribution.
58 * 3. All advertising materials mentioning features or use of this software
59 * must display the following acknowledgement:
60 * This product includes software developed by Charles M. Hannum.
61 * 4. The name of the author may not be used to endorse or promote products
62 * derived from this software without specific prior written permission.
63 *
64 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
65 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
66 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
67 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
68 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
69 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
70 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
71 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
72 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
73 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
74 */
75
76 /*
77 * Originally written by Julian Elischer (julian (at) tfs.com)
78 * for TRW Financial Systems for use under the MACH(2.5) operating system.
79 *
80 * TRW Financial Systems, in accordance with their agreement with Carnegie
81 * Mellon University, makes this software available to CMU to distribute
82 * or use in any manner that they see fit as long as this message is kept with
83 * the software. For this reason TFS also grants any other persons or
84 * organisations permission to use or modify this software.
85 *
86 * TFS supplies this software to be publicly redistributed
87 * on the understanding that TFS is not responsible for the correct
88 * functioning of this software in any circumstances.
89 */
90
91 #include <sys/types.h>
92 #include <sys/param.h>
93 #include <sys/systm.h>
94 #include <sys/kernel.h>
95 #include <sys/errno.h>
96 #include <sys/ioctl.h>
97 #include <sys/device.h>
98 #include <sys/malloc.h>
99 #include <sys/buf.h>
100 #include <sys/proc.h>
101 #include <sys/user.h>
102
103 #include <machine/bus.h>
104 #include <machine/intr.h>
105
106 #include <dev/scsipi/scsi_all.h>
107 #include <dev/scsipi/scsipi_all.h>
108 #include <dev/scsipi/scsiconf.h>
109
110 #include <dev/ic/ahareg.h>
111 #include <dev/ic/ahavar.h>
112
113 #ifndef DDB
114 #define Debugger() panic("should call debugger here (aha1542.c)")
115 #endif /* ! DDB */
116
117 #define AHA_MAXXFER ((AHA_NSEG - 1) << PGSHIFT)
118
119 #ifdef AHADEBUG
120 int aha_debug = 1;
121 #endif /* AHADEBUG */
122
123 int aha_cmd __P((bus_space_tag_t, bus_space_handle_t, struct aha_softc *, int,
124 u_char *, int, u_char *));
125 integrate void aha_finish_ccbs __P((struct aha_softc *));
126 integrate void aha_reset_ccb __P((struct aha_softc *, struct aha_ccb *));
127 void aha_free_ccb __P((struct aha_softc *, struct aha_ccb *));
128 integrate int aha_init_ccb __P((struct aha_softc *, struct aha_ccb *));
129 struct aha_ccb *aha_get_ccb __P((struct aha_softc *, int));
130 struct aha_ccb *aha_ccb_phys_kv __P((struct aha_softc *, u_long));
131 void aha_queue_ccb __P((struct aha_softc *, struct aha_ccb *));
132 void aha_collect_mbo __P((struct aha_softc *));
133 void aha_start_ccbs __P((struct aha_softc *));
134 void aha_done __P((struct aha_softc *, struct aha_ccb *));
135 void aha_init __P((struct aha_softc *));
136 void aha_inquire_setup_information __P((struct aha_softc *));
137 void ahaminphys __P((struct buf *));
138 int aha_scsi_cmd __P((struct scsipi_xfer *));
139 int aha_poll __P((struct aha_softc *, struct scsipi_xfer *, int));
140 void aha_timeout __P((void *arg));
141 int aha_create_ccbs __P((struct aha_softc *, void *, size_t, int));
142
143 struct scsipi_adapter aha_switch = {
144 aha_scsi_cmd,
145 ahaminphys,
146 0,
147 0,
148 };
149
150 /* the below structure is so we have a default dev struct for out link struct */
151 struct scsipi_device aha_dev = {
152 NULL, /* Use default error handler */
153 NULL, /* have a queue, served by this */
154 NULL, /* have no async handler */
155 NULL, /* Use default 'done' routine */
156 };
157
158 struct cfdriver aha_cd = {
159 NULL, "aha", DV_DULL
160 };
161
162 #define AHA_RESET_TIMEOUT 2000 /* time to wait for reset (mSec) */
163 #define AHA_ABORT_TIMEOUT 2000 /* time to wait for abort (mSec) */
164
165 /* XXX Should put this in a better place. */
166 #define offsetof(type, member) ((size_t)(&((type *)0)->member))
167
168 /*
169 * aha_cmd(iot, ioh, sc, icnt, ibuf, ocnt, obuf)
170 *
171 * Activate Adapter command
172 * icnt: number of args (outbound bytes including opcode)
173 * ibuf: argument buffer
174 * ocnt: number of expected returned bytes
175 * obuf: result buffer
176 * wait: number of seconds to wait for response
177 *
178 * Performs an adapter command through the ports. Not to be confused with a
179 * scsi command, which is read in via the dma; one of the adapter commands
180 * tells it to read in a scsi command.
181 */
182 int
183 aha_cmd(iot, ioh, sc, icnt, ibuf, ocnt, obuf)
184 bus_space_tag_t iot;
185 bus_space_handle_t ioh;
186 struct aha_softc *sc;
187 int icnt, ocnt;
188 u_char *ibuf, *obuf;
189 {
190 const char *name;
191 register int i;
192 int wait;
193 u_char sts;
194 u_char opcode = ibuf[0];
195
196 if (sc != NULL)
197 name = sc->sc_dev.dv_xname;
198 else
199 name = "(aha probe)";
200
201 /*
202 * Calculate a reasonable timeout for the command.
203 */
204 switch (opcode) {
205 case AHA_INQUIRE_DEVICES:
206 wait = 90 * 20000;
207 break;
208 default:
209 wait = 1 * 20000;
210 break;
211 }
212
213 /*
214 * Wait for the adapter to go idle, unless it's one of
215 * the commands which don't need this
216 */
217 if (opcode != AHA_MBO_INTR_EN) {
218 for (i = 20000; i; i--) { /* 1 sec? */
219 sts = bus_space_read_1(iot, ioh, AHA_STAT_PORT);
220 if (sts & AHA_STAT_IDLE)
221 break;
222 delay(50);
223 }
224 if (!i) {
225 printf("%s: aha_cmd, host not idle(0x%x)\n",
226 name, sts);
227 return (1);
228 }
229 }
230 /*
231 * Now that it is idle, if we expect output, preflush the
232 * queue feeding to us.
233 */
234 if (ocnt) {
235 while ((bus_space_read_1(iot, ioh, AHA_STAT_PORT)) & AHA_STAT_DF)
236 bus_space_read_1(iot, ioh, AHA_DATA_PORT);
237 }
238 /*
239 * Output the command and the number of arguments given
240 * for each byte, first check the port is empty.
241 */
242 while (icnt--) {
243 for (i = wait; i; i--) {
244 sts = bus_space_read_1(iot, ioh, AHA_STAT_PORT);
245 if (!(sts & AHA_STAT_CDF))
246 break;
247 delay(50);
248 }
249 if (!i) {
250 if (opcode != AHA_INQUIRE_REVISION)
251 printf("%s: aha_cmd, cmd/data port full\n", name);
252 bus_space_write_1(iot, ioh, AHA_CTRL_PORT, AHA_CTRL_SRST);
253 return (1);
254 }
255 bus_space_write_1(iot, ioh, AHA_CMD_PORT, *ibuf++);
256 }
257 /*
258 * If we expect input, loop that many times, each time,
259 * looking for the data register to have valid data
260 */
261 while (ocnt--) {
262 for (i = wait; i; i--) {
263 sts = bus_space_read_1(iot, ioh, AHA_STAT_PORT);
264 if (sts & AHA_STAT_DF)
265 break;
266 delay(50);
267 }
268 if (!i) {
269 if (opcode != AHA_INQUIRE_REVISION)
270 printf("%s: aha_cmd, cmd/data port empty %d\n",
271 name, ocnt);
272 bus_space_write_1(iot, ioh, AHA_CTRL_PORT, AHA_CTRL_SRST);
273 return (1);
274 }
275 *obuf++ = bus_space_read_1(iot, ioh, AHA_DATA_PORT);
276 }
277 /*
278 * Wait for the board to report a finished instruction.
279 * We may get an extra interrupt for the HACC signal, but this is
280 * unimportant.
281 */
282 if (opcode != AHA_MBO_INTR_EN) {
283 for (i = 20000; i; i--) { /* 1 sec? */
284 sts = bus_space_read_1(iot, ioh, AHA_INTR_PORT);
285 /* XXX Need to save this in the interrupt handler? */
286 if (sts & AHA_INTR_HACC)
287 break;
288 delay(50);
289 }
290 if (!i) {
291 printf("%s: aha_cmd, host not finished(0x%x)\n",
292 name, sts);
293 return (1);
294 }
295 }
296 bus_space_write_1(iot, ioh, AHA_CTRL_PORT, AHA_CTRL_IRST);
297 return (0);
298 }
299
300 void
301 aha_attach(sc, apd)
302 struct aha_softc *sc;
303 struct aha_probe_data *apd;
304 {
305
306 TAILQ_INIT(&sc->sc_free_ccb);
307 TAILQ_INIT(&sc->sc_waiting_ccb);
308
309 /*
310 * fill in the prototype scsipi_link.
311 */
312 sc->sc_link.scsipi_scsi.channel = SCSI_CHANNEL_ONLY_ONE;
313 sc->sc_link.adapter_softc = sc;
314 sc->sc_link.scsipi_scsi.adapter_target = apd->sc_scsi_dev;
315 sc->sc_link.adapter = &aha_switch;
316 sc->sc_link.device = &aha_dev;
317 sc->sc_link.openings = 2;
318 sc->sc_link.scsipi_scsi.max_target = 7;
319 sc->sc_link.type = BUS_SCSI;
320
321 aha_inquire_setup_information(sc);
322 aha_init(sc);
323
324 /*
325 * ask the adapter what subunits are present
326 */
327 config_found(&sc->sc_dev, &sc->sc_link, scsiprint);
328 }
329
330 integrate void
331 aha_finish_ccbs(sc)
332 struct aha_softc *sc;
333 {
334 struct aha_mbx_in *wmbi;
335 struct aha_ccb *ccb;
336 int i;
337
338 wmbi = wmbx->tmbi;
339
340 if (wmbi->stat == AHA_MBI_FREE) {
341 for (i = 0; i < AHA_MBX_SIZE; i++) {
342 if (wmbi->stat != AHA_MBI_FREE) {
343 printf("%s: mbi not in round-robin order\n",
344 sc->sc_dev.dv_xname);
345 goto AGAIN;
346 }
347 aha_nextmbx(wmbi, wmbx, mbi);
348 }
349 #ifdef AHADIAGnot
350 printf("%s: mbi interrupt with no full mailboxes\n",
351 sc->sc_dev.dv_xname);
352 #endif
353 return;
354 }
355
356 AGAIN:
357 do {
358 ccb = aha_ccb_phys_kv(sc, phystol(wmbi->ccb_addr));
359 if (!ccb) {
360 printf("%s: bad mbi ccb pointer; skipping\n",
361 sc->sc_dev.dv_xname);
362 goto next;
363 }
364
365 #ifdef AHADEBUG
366 if (aha_debug) {
367 u_char *cp = &ccb->scsi_cmd;
368 printf("op=%x %x %x %x %x %x\n",
369 cp[0], cp[1], cp[2], cp[3], cp[4], cp[5]);
370 printf("stat %x for mbi addr = 0x%08x, ",
371 wmbi->stat, wmbi);
372 printf("ccb addr = 0x%x\n", ccb);
373 }
374 #endif /* AHADEBUG */
375
376 switch (wmbi->stat) {
377 case AHA_MBI_OK:
378 case AHA_MBI_ERROR:
379 if ((ccb->flags & CCB_ABORT) != 0) {
380 /*
381 * If we already started an abort, wait for it
382 * to complete before clearing the CCB. We
383 * could instead just clear CCB_SENDING, but
384 * what if the mailbox was already received?
385 * The worst that happens here is that we clear
386 * the CCB a bit later than we need to. BFD.
387 */
388 goto next;
389 }
390 break;
391
392 case AHA_MBI_ABORT:
393 case AHA_MBI_UNKNOWN:
394 /*
395 * Even if the CCB wasn't found, we clear it anyway.
396 * See preceeding comment.
397 */
398 break;
399
400 default:
401 printf("%s: bad mbi status %02x; skipping\n",
402 sc->sc_dev.dv_xname, wmbi->stat);
403 goto next;
404 }
405
406 untimeout(aha_timeout, ccb);
407 aha_done(sc, ccb);
408
409 next:
410 wmbi->stat = AHA_MBI_FREE;
411 aha_nextmbx(wmbi, wmbx, mbi);
412 } while (wmbi->stat != AHA_MBI_FREE);
413
414 wmbx->tmbi = wmbi;
415 }
416
417 /*
418 * Catch an interrupt from the adaptor
419 */
420 int
421 aha_intr(arg)
422 void *arg;
423 {
424 struct aha_softc *sc = arg;
425 bus_space_tag_t iot = sc->sc_iot;
426 bus_space_handle_t ioh = sc->sc_ioh;
427 u_char sts;
428
429 #ifdef AHADEBUG
430 printf("%s: aha_intr ", sc->sc_dev.dv_xname);
431 #endif /*AHADEBUG */
432
433 /*
434 * First acknowlege the interrupt, Then if it's not telling about
435 * a completed operation just return.
436 */
437 sts = bus_space_read_1(iot, ioh, AHA_INTR_PORT);
438 if ((sts & AHA_INTR_ANYINTR) == 0)
439 return (0);
440 bus_space_write_1(iot, ioh, AHA_CTRL_PORT, AHA_CTRL_IRST);
441
442 #ifdef AHADIAG
443 /* Make sure we clear CCB_SENDING before finishing a CCB. */
444 aha_collect_mbo(sc);
445 #endif
446
447 /* Mail box out empty? */
448 if (sts & AHA_INTR_MBOA) {
449 struct aha_toggle toggle;
450
451 toggle.cmd.opcode = AHA_MBO_INTR_EN;
452 toggle.cmd.enable = 0;
453 aha_cmd(iot, ioh, sc,
454 sizeof(toggle.cmd), (u_char *)&toggle.cmd,
455 0, (u_char *)0);
456 aha_start_ccbs(sc);
457 }
458
459 /* Mail box in full? */
460 if (sts & AHA_INTR_MBIF)
461 aha_finish_ccbs(sc);
462
463 return (1);
464 }
465
466 integrate void
467 aha_reset_ccb(sc, ccb)
468 struct aha_softc *sc;
469 struct aha_ccb *ccb;
470 {
471
472 ccb->flags = 0;
473 }
474
475 /*
476 * A ccb is put onto the free list.
477 */
478 void
479 aha_free_ccb(sc, ccb)
480 struct aha_softc *sc;
481 struct aha_ccb *ccb;
482 {
483 int s;
484
485 s = splbio();
486
487 aha_reset_ccb(sc, ccb);
488 TAILQ_INSERT_HEAD(&sc->sc_free_ccb, ccb, chain);
489
490 /*
491 * If there were none, wake anybody waiting for one to come free,
492 * starting with queued entries.
493 */
494 if (ccb->chain.tqe_next == 0)
495 wakeup(&sc->sc_free_ccb);
496
497 splx(s);
498 }
499
500 integrate int
501 aha_init_ccb(sc, ccb)
502 struct aha_softc *sc;
503 struct aha_ccb *ccb;
504 {
505 bus_dma_tag_t dmat = sc->sc_dmat;
506 int hashnum, error;
507
508 /*
509 * XXX Should we put a DIAGNOSTIC check for multiple
510 * XXX CCB inits here?
511 */
512
513 bzero(ccb, sizeof(struct aha_ccb));
514
515 /*
516 * Create DMA maps for this CCB.
517 */
518 error = bus_dmamap_create(dmat, sizeof(struct aha_ccb), 1,
519 sizeof(struct aha_ccb), 0, BUS_DMA_NOWAIT, &ccb->dmamap_self);
520 if (error) {
521 printf("%s: can't create ccb dmamap_self\n",
522 sc->sc_dev.dv_xname);
523 return (error);
524 }
525
526 error = bus_dmamap_create(dmat, AHA_MAXXFER, AHA_NSEG, AHA_MAXXFER,
527 0, BUS_DMA_NOWAIT|BUS_DMA_ALLOCNOW, &ccb->dmamap_xfer);
528 if (error) {
529 printf("%s: can't create ccb dmamap_xfer\n",
530 sc->sc_dev.dv_xname);
531 bus_dmamap_destroy(dmat, ccb->dmamap_self);
532 return (error);
533 }
534
535 /*
536 * Load the permanent DMA maps.
537 */
538 error = bus_dmamap_load(dmat, ccb->dmamap_self, ccb,
539 sizeof(struct aha_ccb), NULL, BUS_DMA_NOWAIT);
540 if (error) {
541 printf("%s: can't load ccb dmamap_self\n",
542 sc->sc_dev.dv_xname);
543 bus_dmamap_destroy(dmat, ccb->dmamap_self);
544 bus_dmamap_destroy(dmat, ccb->dmamap_xfer);
545 return (error);
546 }
547
548 /*
549 * put in the phystokv hash table
550 * Never gets taken out.
551 */
552 ccb->hashkey = ccb->dmamap_self->dm_segs[0].ds_addr;
553 hashnum = CCB_HASH(ccb->hashkey);
554 ccb->nexthash = sc->sc_ccbhash[hashnum];
555 sc->sc_ccbhash[hashnum] = ccb;
556 aha_reset_ccb(sc, ccb);
557 return (0);
558 }
559
560 /*
561 * Create a set of ccbs and add them to the free list.
562 */
563 int
564 aha_create_ccbs(sc, mem, size, max_ccbs)
565 struct aha_softc *sc;
566 void *mem;
567 size_t size;
568 int max_ccbs;
569 {
570 bus_dma_segment_t seg;
571 struct aha_ccb *ccb;
572 int rseg, error;
573
574 if (sc->sc_numccbs >= AHA_CCB_MAX)
575 return (0);
576
577 if (max_ccbs > AHA_CCB_MAX)
578 max_ccbs = AHA_CCB_MAX;
579
580 if ((ccb = mem) != NULL)
581 goto have_mem;
582
583 size = NBPG;
584 error = bus_dmamem_alloc(sc->sc_dmat, size, NBPG, 0, &seg, 1, &rseg,
585 BUS_DMA_NOWAIT);
586 if (error) {
587 printf("%s: can't allocate memory for ccbs\n",
588 sc->sc_dev.dv_xname);
589 return (error);
590 }
591
592 error = bus_dmamem_map(sc->sc_dmat, &seg, rseg, size,
593 (caddr_t *)&ccb, BUS_DMA_NOWAIT|BUS_DMAMEM_NOSYNC);
594 if (error) {
595 printf("%s: can't map memory for ccbs\n",
596 sc->sc_dev.dv_xname);
597 bus_dmamem_free(sc->sc_dmat, &seg, rseg);
598 return (error);
599 }
600
601 have_mem:
602 bzero(ccb, size);
603 while (size > sizeof(struct aha_ccb) && sc->sc_numccbs < max_ccbs) {
604 error = aha_init_ccb(sc, ccb);
605 if (error) {
606 printf("%s: can't initialize ccb\n",
607 sc->sc_dev.dv_xname);
608 return (error);
609 }
610 TAILQ_INSERT_TAIL(&sc->sc_free_ccb, ccb, chain);
611 (caddr_t)ccb += ALIGN(sizeof(struct aha_ccb));
612 size -= ALIGN(sizeof(struct aha_ccb));
613 sc->sc_numccbs++;
614 }
615
616 return (0);
617 }
618
619 /*
620 * Get a free ccb
621 *
622 * If there are none, see if we can allocate a new one. If so, put it in
623 * the hash table too otherwise either return an error or sleep.
624 */
625 struct aha_ccb *
626 aha_get_ccb(sc, flags)
627 struct aha_softc *sc;
628 int flags;
629 {
630 struct aha_ccb *ccb;
631 int s;
632
633 s = splbio();
634
635 /*
636 * If we can and have to, sleep waiting for one to come free
637 * but only if we can't allocate a new one.
638 */
639 for (;;) {
640 ccb = sc->sc_free_ccb.tqh_first;
641 if (ccb) {
642 TAILQ_REMOVE(&sc->sc_free_ccb, ccb, chain);
643 break;
644 }
645 if (sc->sc_numccbs < AHA_CCB_MAX) {
646 /*
647 * aha_create_ccbs() might have managed to create
648 * one before it failed. If so, don't abort,
649 * just grab it and continue to hobble along.
650 */
651 if (aha_create_ccbs(sc, NULL, 0, AHA_CCB_MAX) != 0 &&
652 sc->sc_free_ccb.tqh_first == NULL) {
653 printf("%s: can't allocate ccbs\n",
654 sc->sc_dev.dv_xname);
655 goto out;
656 }
657 continue;
658 }
659 if ((flags & SCSI_NOSLEEP) != 0)
660 goto out;
661 tsleep(&sc->sc_free_ccb, PRIBIO, "ahaccb", 0);
662 }
663
664 ccb->flags |= CCB_ALLOC;
665
666 out:
667 splx(s);
668 return (ccb);
669 }
670
671 /*
672 * Given a physical address, find the ccb that it corresponds to.
673 */
674 struct aha_ccb *
675 aha_ccb_phys_kv(sc, ccb_phys)
676 struct aha_softc *sc;
677 u_long ccb_phys;
678 {
679 int hashnum = CCB_HASH(ccb_phys);
680 struct aha_ccb *ccb = sc->sc_ccbhash[hashnum];
681
682 while (ccb) {
683 if (ccb->hashkey == ccb_phys)
684 break;
685 ccb = ccb->nexthash;
686 }
687 return (ccb);
688 }
689
690 /*
691 * Queue a CCB to be sent to the controller, and send it if possible.
692 */
693 void
694 aha_queue_ccb(sc, ccb)
695 struct aha_softc *sc;
696 struct aha_ccb *ccb;
697 {
698
699 TAILQ_INSERT_TAIL(&sc->sc_waiting_ccb, ccb, chain);
700 aha_start_ccbs(sc);
701 }
702
703 /*
704 * Garbage collect mailboxes that are no longer in use.
705 */
706 void
707 aha_collect_mbo(sc)
708 struct aha_softc *sc;
709 {
710 struct aha_mbx_out *wmbo; /* Mail Box Out pointer */
711 #ifdef AHADIAG
712 struct aha_ccb *ccb;
713 #endif
714
715 wmbo = wmbx->cmbo;
716
717 while (sc->sc_mbofull > 0) {
718 if (wmbo->cmd != AHA_MBO_FREE)
719 break;
720
721 #ifdef AHADIAG
722 ccb = aha_ccb_phys_kv(sc, phystol(wmbo->ccb_addr));
723 ccb->flags &= ~CCB_SENDING;
724 #endif
725
726 --sc->sc_mbofull;
727 aha_nextmbx(wmbo, wmbx, mbo);
728 }
729
730 wmbx->cmbo = wmbo;
731 }
732
733 /*
734 * Send as many CCBs as we have empty mailboxes for.
735 */
736 void
737 aha_start_ccbs(sc)
738 struct aha_softc *sc;
739 {
740 bus_space_tag_t iot = sc->sc_iot;
741 bus_space_handle_t ioh = sc->sc_ioh;
742 struct aha_mbx_out *wmbo; /* Mail Box Out pointer */
743 struct aha_ccb *ccb;
744
745 wmbo = wmbx->tmbo;
746
747 while ((ccb = sc->sc_waiting_ccb.tqh_first) != NULL) {
748 if (sc->sc_mbofull >= AHA_MBX_SIZE) {
749 aha_collect_mbo(sc);
750 if (sc->sc_mbofull >= AHA_MBX_SIZE) {
751 struct aha_toggle toggle;
752
753 toggle.cmd.opcode = AHA_MBO_INTR_EN;
754 toggle.cmd.enable = 1;
755 aha_cmd(iot, ioh, sc,
756 sizeof(toggle.cmd), (u_char *)&toggle.cmd,
757 0, (u_char *)0);
758 break;
759 }
760 }
761
762 TAILQ_REMOVE(&sc->sc_waiting_ccb, ccb, chain);
763 #ifdef AHADIAG
764 ccb->flags |= CCB_SENDING;
765 #endif
766
767 /* Link ccb to mbo. */
768 ltophys(ccb->dmamap_self->dm_segs[0].ds_addr, wmbo->ccb_addr);
769 if (ccb->flags & CCB_ABORT)
770 wmbo->cmd = AHA_MBO_ABORT;
771 else
772 wmbo->cmd = AHA_MBO_START;
773
774 /* Tell the card to poll immediately. */
775 bus_space_write_1(iot, ioh, AHA_CMD_PORT, AHA_START_SCSI);
776
777 if ((ccb->xs->flags & SCSI_POLL) == 0)
778 timeout(aha_timeout, ccb, (ccb->timeout * hz) / 1000);
779
780 ++sc->sc_mbofull;
781 aha_nextmbx(wmbo, wmbx, mbo);
782 }
783
784 wmbx->tmbo = wmbo;
785 }
786
787 /*
788 * We have a ccb which has been processed by the
789 * adaptor, now we look to see how the operation
790 * went. Wake up the owner if waiting
791 */
792 void
793 aha_done(sc, ccb)
794 struct aha_softc *sc;
795 struct aha_ccb *ccb;
796 {
797 bus_dma_tag_t dmat = sc->sc_dmat;
798 struct scsipi_sense_data *s1, *s2;
799 struct scsipi_xfer *xs = ccb->xs;
800
801 SC_DEBUG(xs->sc_link, SDEV_DB2, ("aha_done\n"));
802
803 /*
804 * If we were a data transfer, unload the map that described
805 * the data buffer.
806 */
807 if (xs->datalen) {
808 bus_dmamap_sync(dmat, ccb->dmamap_xfer,
809 (xs->flags & SCSI_DATA_IN) ? BUS_DMASYNC_POSTREAD :
810 BUS_DMASYNC_POSTWRITE);
811 bus_dmamap_unload(dmat, ccb->dmamap_xfer);
812 }
813
814 /*
815 * Otherwise, put the results of the operation
816 * into the xfer and call whoever started it
817 */
818 #ifdef AHADIAG
819 if (ccb->flags & CCB_SENDING) {
820 printf("%s: exiting ccb still in transit!\n", sc->sc_dev.dv_xname);
821 Debugger();
822 return;
823 }
824 #endif
825 if ((ccb->flags & CCB_ALLOC) == 0) {
826 printf("%s: exiting ccb not allocated!\n", sc->sc_dev.dv_xname);
827 Debugger();
828 return;
829 }
830 if (xs->error == XS_NOERROR) {
831 if (ccb->host_stat != AHA_OK) {
832 switch (ccb->host_stat) {
833 case AHA_SEL_TIMEOUT: /* No response */
834 xs->error = XS_SELTIMEOUT;
835 break;
836 default: /* Other scsi protocol messes */
837 printf("%s: host_stat %x\n",
838 sc->sc_dev.dv_xname, ccb->host_stat);
839 xs->error = XS_DRIVER_STUFFUP;
840 break;
841 }
842 } else if (ccb->target_stat != SCSI_OK) {
843 switch (ccb->target_stat) {
844 case SCSI_CHECK:
845 s1 = (struct scsipi_sense_data *) (((char *) (&ccb->scsi_cmd)) +
846 ccb->scsi_cmd_length);
847 s2 = &xs->sense.scsi_sense;
848 *s2 = *s1;
849 xs->error = XS_SENSE;
850 break;
851 case SCSI_BUSY:
852 xs->error = XS_BUSY;
853 break;
854 default:
855 printf("%s: target_stat %x\n",
856 sc->sc_dev.dv_xname, ccb->target_stat);
857 xs->error = XS_DRIVER_STUFFUP;
858 break;
859 }
860 } else
861 xs->resid = 0;
862 }
863 aha_free_ccb(sc, ccb);
864 xs->flags |= ITSDONE;
865 scsipi_done(xs);
866 }
867
868 /*
869 * Find the board and find its irq/drq
870 */
871 int
872 aha_find(iot, ioh, sc)
873 bus_space_tag_t iot;
874 bus_space_handle_t ioh;
875 struct aha_probe_data *sc;
876 {
877 int i;
878 u_char sts;
879 struct aha_config config;
880 int irq, drq;
881
882 /*
883 * reset board, If it doesn't respond, assume
884 * that it's not there.. good for the probe
885 */
886
887 bus_space_write_1(iot, ioh, AHA_CTRL_PORT, AHA_CTRL_HRST | AHA_CTRL_SRST);
888
889 delay(100);
890 for (i = AHA_RESET_TIMEOUT; i; i--) {
891 sts = bus_space_read_1(iot, ioh, AHA_STAT_PORT);
892 if (sts == (AHA_STAT_IDLE | AHA_STAT_INIT))
893 break;
894 delay(1000); /* calibrated in msec */
895 }
896 if (!i) {
897 #ifdef AHADEBUG
898 if (aha_debug)
899 printf("aha_find: No answer from adaptec board\n");
900 #endif /* AHADEBUG */
901 return (0);
902 }
903
904 /*
905 * setup dma channel from jumpers and save int
906 * level
907 */
908 delay(1000); /* for Bustek 545 */
909 config.cmd.opcode = AHA_INQUIRE_CONFIG;
910 aha_cmd(iot, ioh, (struct aha_softc *)0,
911 sizeof(config.cmd), (u_char *)&config.cmd,
912 sizeof(config.reply), (u_char *)&config.reply);
913 switch (config.reply.chan) {
914 case EISADMA:
915 drq = -1;
916 break;
917 case CHAN0:
918 drq = 0;
919 break;
920 case CHAN5:
921 drq = 5;
922 break;
923 case CHAN6:
924 drq = 6;
925 break;
926 case CHAN7:
927 drq = 7;
928 break;
929 default:
930 printf("aha_find: illegal drq setting %x\n", config.reply.chan);
931 return (0);
932 }
933
934 switch (config.reply.intr) {
935 case INT9:
936 irq = 9;
937 break;
938 case INT10:
939 irq = 10;
940 break;
941 case INT11:
942 irq = 11;
943 break;
944 case INT12:
945 irq = 12;
946 break;
947 case INT14:
948 irq = 14;
949 break;
950 case INT15:
951 irq = 15;
952 break;
953 default:
954 printf("aha_find: illegal irq setting %x\n", config.reply.intr);
955 return (0);
956 }
957
958 if (sc) {
959 sc->sc_irq = irq;
960 sc->sc_drq = drq;
961 sc->sc_scsi_dev = config.reply.scsi_dev;
962 }
963
964 return (1);
965 }
966
967 /*
968 * Start the board, ready for normal operation
969 */
970 void
971 aha_init(sc)
972 struct aha_softc *sc;
973 {
974 bus_space_tag_t iot = sc->sc_iot;
975 bus_space_handle_t ioh = sc->sc_ioh;
976 bus_dma_segment_t seg;
977 struct aha_devices devices;
978 struct aha_setup setup;
979 struct aha_mailbox mailbox;
980 int i, j, initial_ccbs, rseg;
981
982 /*
983 * XXX
984 * If we are a 1542C or later, disable the extended BIOS so that the
985 * mailbox interface is unlocked.
986 * No need to check the extended BIOS flags as some of the
987 * extensions that cause us problems are not flagged in that byte.
988 */
989 if (!strncmp(sc->sc_model, "1542C", 5)) {
990 struct aha_extbios extbios;
991 struct aha_unlock unlock;
992
993 printf("%s: unlocking mailbox interface\n", sc->sc_dev.dv_xname);
994 extbios.cmd.opcode = AHA_EXT_BIOS;
995 aha_cmd(iot, ioh, sc,
996 sizeof(extbios.cmd), (u_char *)&extbios.cmd,
997 sizeof(extbios.reply), (u_char *)&extbios.reply);
998
999 #ifdef AHADEBUG
1000 printf("%s: flags=%02x, mailboxlock=%02x\n",
1001 sc->sc_dev.dv_xname,
1002 extbios.reply.flags, extbios.reply.mailboxlock);
1003 #endif /* AHADEBUG */
1004
1005 unlock.cmd.opcode = AHA_MBX_ENABLE;
1006 unlock.cmd.junk = 0;
1007 unlock.cmd.magic = extbios.reply.mailboxlock;
1008 aha_cmd(iot, ioh, sc,
1009 sizeof(unlock.cmd), (u_char *)&unlock.cmd,
1010 0, (u_char *)0);
1011 }
1012
1013 #if 0
1014 /*
1015 * Change the bus on/off times to not clash with other dma users.
1016 */
1017 aha_cmd(iot, ioh, 1, 0, 0, 0, AHA_BUS_ON_TIME_SET, 7);
1018 aha_cmd(iot, ioh, 1, 0, 0, 0, AHA_BUS_OFF_TIME_SET, 4);
1019 #endif
1020
1021 /* Inquire Installed Devices (to force synchronous negotiation). */
1022 devices.cmd.opcode = AHA_INQUIRE_DEVICES;
1023 aha_cmd(iot, ioh, sc,
1024 sizeof(devices.cmd), (u_char *)&devices.cmd,
1025 sizeof(devices.reply), (u_char *)&devices.reply);
1026
1027 /* Count installed units */
1028 initial_ccbs = 0;
1029 for (i = 0; i < 8; i++) {
1030 for (j = 0; j < 8; j++) {
1031 if (((devices.reply.lun_map[i] >> j) & 1) == 1)
1032 initial_ccbs += 1;
1033 }
1034 }
1035 initial_ccbs *= sc->sc_link.openings;
1036
1037 /* Obtain setup information from. */
1038 setup.cmd.opcode = AHA_INQUIRE_SETUP;
1039 setup.cmd.len = sizeof(setup.reply);
1040 aha_cmd(iot, ioh, sc,
1041 sizeof(setup.cmd), (u_char *)&setup.cmd,
1042 sizeof(setup.reply), (u_char *)&setup.reply);
1043
1044 printf("%s: %s, %s\n",
1045 sc->sc_dev.dv_xname,
1046 setup.reply.sync_neg ? "sync" : "async",
1047 setup.reply.parity ? "parity" : "no parity");
1048
1049 for (i = 0; i < 8; i++) {
1050 if (!setup.reply.sync[i].valid ||
1051 (!setup.reply.sync[i].offset && !setup.reply.sync[i].period))
1052 continue;
1053 printf("%s targ %d: sync, offset %d, period %dnsec\n",
1054 sc->sc_dev.dv_xname, i,
1055 setup.reply.sync[i].offset, setup.reply.sync[i].period * 50 + 200);
1056 }
1057
1058 /*
1059 * Allocate the mailbox.
1060 */
1061 if (bus_dmamem_alloc(sc->sc_dmat, NBPG, NBPG, 0, &seg, 1,
1062 &rseg, BUS_DMA_NOWAIT) ||
1063 bus_dmamem_map(sc->sc_dmat, &seg, rseg, NBPG,
1064 (caddr_t *)&wmbx, BUS_DMA_NOWAIT|BUS_DMAMEM_NOSYNC))
1065 panic("aha_init: can't create or map mailbox");
1066
1067 /*
1068 * Since DMA memory allocation is always rounded up to a
1069 * page size, create some ccbs from the leftovers.
1070 */
1071 if (aha_create_ccbs(sc, ((caddr_t)wmbx) +
1072 ALIGN(sizeof(struct aha_mbx)),
1073 NBPG - ALIGN(sizeof(struct aha_mbx)), initial_ccbs))
1074 panic("aha_init: can't create ccbs");
1075
1076 /*
1077 * Create and load the mailbox DMA map.
1078 */
1079 if (bus_dmamap_create(sc->sc_dmat, sizeof(struct aha_mbx), 1,
1080 sizeof(struct aha_mbx), 0, BUS_DMA_NOWAIT, &sc->sc_dmamap_mbox) ||
1081 bus_dmamap_load(sc->sc_dmat, sc->sc_dmamap_mbox, wmbx,
1082 sizeof(struct aha_mbx), NULL, BUS_DMA_NOWAIT))
1083 panic("aha_init: can't create or load mailbox dma map");
1084
1085 /*
1086 * Set up initial mail box for round-robin operation.
1087 */
1088 for (i = 0; i < AHA_MBX_SIZE; i++) {
1089 wmbx->mbo[i].cmd = AHA_MBO_FREE;
1090 wmbx->mbi[i].stat = AHA_MBI_FREE;
1091 }
1092 wmbx->cmbo = wmbx->tmbo = &wmbx->mbo[0];
1093 wmbx->tmbi = &wmbx->mbi[0];
1094 sc->sc_mbofull = 0;
1095
1096 /* Initialize mail box. */
1097 mailbox.cmd.opcode = AHA_MBX_INIT;
1098 mailbox.cmd.nmbx = AHA_MBX_SIZE;
1099 ltophys(sc->sc_dmamap_mbox->dm_segs[0].ds_addr, mailbox.cmd.addr);
1100 aha_cmd(iot, ioh, sc,
1101 sizeof(mailbox.cmd), (u_char *)&mailbox.cmd,
1102 0, (u_char *)0);
1103 }
1104
1105 void
1106 aha_inquire_setup_information(sc)
1107 struct aha_softc *sc;
1108 {
1109 bus_space_tag_t iot = sc->sc_iot;
1110 bus_space_handle_t ioh = sc->sc_ioh;
1111 struct aha_revision revision;
1112 u_char sts;
1113 int i;
1114 char *p;
1115
1116 strcpy(sc->sc_model, "unknown");
1117
1118 /*
1119 * Assume we have a board at this stage, do an adapter inquire
1120 * to find out what type of controller it is. If the command
1121 * fails, we assume it's either a crusty board or an old 1542
1122 * clone, and skip the board-specific stuff.
1123 */
1124 revision.cmd.opcode = AHA_INQUIRE_REVISION;
1125 if (aha_cmd(iot, ioh, sc,
1126 sizeof(revision.cmd), (u_char *)&revision.cmd,
1127 sizeof(revision.reply), (u_char *)&revision.reply)) {
1128 /*
1129 * aha_cmd() already started the reset. It's not clear we
1130 * even need to bother here.
1131 */
1132 for (i = AHA_RESET_TIMEOUT; i; i--) {
1133 sts = bus_space_read_1(iot, ioh, AHA_STAT_PORT);
1134 if (sts == (AHA_STAT_IDLE | AHA_STAT_INIT))
1135 break;
1136 delay(1000);
1137 }
1138 if (!i) {
1139 #ifdef AHADEBUG
1140 printf("aha_init: soft reset failed\n");
1141 #endif /* AHADEBUG */
1142 return;
1143 }
1144 #ifdef AHADEBUG
1145 printf("aha_init: inquire command failed\n");
1146 #endif /* AHADEBUG */
1147 goto noinquire;
1148 }
1149
1150 #ifdef AHADEBUG
1151 printf("%s: inquire %x, %x, %x, %x\n",
1152 sc->sc_dev.dv_xname,
1153 revision.reply.boardid, revision.reply.spec_opts,
1154 revision.reply.revision_1, revision.reply.revision_2);
1155 #endif /* AHADEBUG */
1156
1157 switch (revision.reply.boardid) {
1158 case 0x31:
1159 strcpy(sc->sc_model, "1540");
1160 break;
1161 case 0x41:
1162 strcpy(sc->sc_model, "1540A/1542A/1542B");
1163 break;
1164 case 0x42:
1165 strcpy(sc->sc_model, "1640");
1166 break;
1167 case 0x43:
1168 strcpy(sc->sc_model, "1542C");
1169 break;
1170 case 0x44:
1171 case 0x45:
1172 strcpy(sc->sc_model, "1542CF");
1173 break;
1174 case 0x46:
1175 strcpy(sc->sc_model, "1542CP");
1176 break;
1177 }
1178
1179 p = sc->sc_firmware;
1180 *p++ = revision.reply.revision_1;
1181 *p++ = '.';
1182 *p++ = revision.reply.revision_2;
1183 *p = '\0';
1184
1185 noinquire:
1186 printf("%s: model AHA-%s, firmware %s\n",
1187 sc->sc_dev.dv_xname,
1188 sc->sc_model, sc->sc_firmware);
1189 }
1190
1191 void
1192 ahaminphys(bp)
1193 struct buf *bp;
1194 {
1195
1196 if (bp->b_bcount > AHA_MAXXFER)
1197 bp->b_bcount = AHA_MAXXFER;
1198 minphys(bp);
1199 }
1200
1201 /*
1202 * start a scsi operation given the command and the data address. Also needs
1203 * the unit, target and lu.
1204 */
1205 int
1206 aha_scsi_cmd(xs)
1207 struct scsipi_xfer *xs;
1208 {
1209 struct scsipi_link *sc_link = xs->sc_link;
1210 struct aha_softc *sc = sc_link->adapter_softc;
1211 bus_dma_tag_t dmat = sc->sc_dmat;
1212 struct aha_ccb *ccb;
1213 int error, seg, flags, s;
1214
1215 SC_DEBUG(sc_link, SDEV_DB2, ("aha_scsi_cmd\n"));
1216 /*
1217 * get a ccb to use. If the transfer
1218 * is from a buf (possibly from interrupt time)
1219 * then we can't allow it to sleep
1220 */
1221 flags = xs->flags;
1222 if ((ccb = aha_get_ccb(sc, flags)) == NULL) {
1223 xs->error = XS_DRIVER_STUFFUP;
1224 return (TRY_AGAIN_LATER);
1225 }
1226 ccb->xs = xs;
1227 ccb->timeout = xs->timeout;
1228
1229 /*
1230 * Put all the arguments for the xfer in the ccb
1231 */
1232 if (flags & SCSI_RESET) {
1233 ccb->opcode = AHA_RESET_CCB;
1234 ccb->scsi_cmd_length = 0;
1235 } else {
1236 /* can't use S/G if zero length */
1237 ccb->opcode = (xs->datalen ? AHA_INIT_SCAT_GATH_CCB
1238 : AHA_INITIATOR_CCB);
1239 bcopy(xs->cmd, &ccb->scsi_cmd,
1240 ccb->scsi_cmd_length = xs->cmdlen);
1241 }
1242
1243 if (xs->datalen) {
1244 /*
1245 * Map the DMA transfer.
1246 */
1247 #ifdef TFS
1248 if (flags & SCSI_DATA_UIO) {
1249 error = bus_dmamap_load_uio(dmat,
1250 ccb->dmamap_xfer, (struct uio *)xs->data,
1251 (flags & SCSI_NOSLEEP) ? BUS_DMA_NOWAIT :
1252 BUS_DMA_WAITOK);
1253 } else
1254 #endif
1255 {
1256 error = bus_dmamap_load(dmat,
1257 ccb->dmamap_xfer, xs->data, xs->datalen, NULL,
1258 (flags & SCSI_NOSLEEP) ? BUS_DMA_NOWAIT :
1259 BUS_DMA_WAITOK);
1260 }
1261
1262 if (error) {
1263 if (error == EFBIG) {
1264 printf("%s: aha_scsi_cmd, more than %d"
1265 " dma segments\n",
1266 sc->sc_dev.dv_xname, AHA_NSEG);
1267 } else {
1268 printf("%s: aha_scsi_cmd, error %d loading"
1269 " dma map\n",
1270 sc->sc_dev.dv_xname, error);
1271 }
1272 goto bad;
1273 }
1274
1275 bus_dmamap_sync(dmat, ccb->dmamap_xfer,
1276 (flags & SCSI_DATA_IN) ? BUS_DMASYNC_PREREAD :
1277 BUS_DMASYNC_PREWRITE);
1278
1279 /*
1280 * Load the hardware scatter/gather map with the
1281 * contents of the DMA map.
1282 */
1283 for (seg = 0; seg < ccb->dmamap_xfer->dm_nsegs; seg++) {
1284 ltophys(ccb->dmamap_xfer->dm_segs[seg].ds_addr,
1285 ccb->scat_gath[seg].seg_addr);
1286 ltophys(ccb->dmamap_xfer->dm_segs[seg].ds_len,
1287 ccb->scat_gath[seg].seg_len);
1288 }
1289
1290 ltophys(ccb->dmamap_self->dm_segs[0].ds_addr +
1291 offsetof(struct aha_ccb, scat_gath), ccb->data_addr);
1292 ltophys(ccb->dmamap_xfer->dm_nsegs *
1293 sizeof(struct aha_scat_gath), ccb->data_length);
1294 } else {
1295 /*
1296 * No data xfer, use non S/G values.
1297 */
1298 ltophys(0, ccb->data_addr);
1299 ltophys(0, ccb->data_length);
1300 }
1301
1302 ccb->data_out = 0;
1303 ccb->data_in = 0;
1304 ccb->target = sc_link->scsipi_scsi.target;
1305 ccb->lun = sc_link->scsipi_scsi.lun;
1306 ccb->req_sense_length = sizeof(ccb->scsi_sense);
1307 ccb->host_stat = 0x00;
1308 ccb->target_stat = 0x00;
1309 ccb->link_id = 0;
1310 ltophys(0, ccb->link_addr);
1311
1312 s = splbio();
1313 aha_queue_ccb(sc, ccb);
1314 splx(s);
1315
1316 /*
1317 * Usually return SUCCESSFULLY QUEUED
1318 */
1319 SC_DEBUG(sc_link, SDEV_DB3, ("cmd_sent\n"));
1320 if ((flags & SCSI_POLL) == 0)
1321 return (SUCCESSFULLY_QUEUED);
1322
1323 /*
1324 * If we can't use interrupts, poll on completion
1325 */
1326 if (aha_poll(sc, xs, ccb->timeout)) {
1327 aha_timeout(ccb);
1328 if (aha_poll(sc, xs, ccb->timeout))
1329 aha_timeout(ccb);
1330 }
1331 return (COMPLETE);
1332
1333 bad:
1334 xs->error = XS_DRIVER_STUFFUP;
1335 aha_free_ccb(sc, ccb);
1336 return (COMPLETE);
1337 }
1338
1339 /*
1340 * Poll a particular unit, looking for a particular xs
1341 */
1342 int
1343 aha_poll(sc, xs, count)
1344 struct aha_softc *sc;
1345 struct scsipi_xfer *xs;
1346 int count;
1347 {
1348 bus_space_tag_t iot = sc->sc_iot;
1349 bus_space_handle_t ioh = sc->sc_ioh;
1350
1351 /* timeouts are in msec, so we loop in 1000 usec cycles */
1352 while (count) {
1353 /*
1354 * If we had interrupts enabled, would we
1355 * have got an interrupt?
1356 */
1357 if (bus_space_read_1(iot, ioh, AHA_INTR_PORT) & AHA_INTR_ANYINTR)
1358 aha_intr(sc);
1359 if (xs->flags & ITSDONE)
1360 return (0);
1361 delay(1000); /* only happens in boot so ok */
1362 count--;
1363 }
1364 return (1);
1365 }
1366
1367 void
1368 aha_timeout(arg)
1369 void *arg;
1370 {
1371 struct aha_ccb *ccb = arg;
1372 struct scsipi_xfer *xs = ccb->xs;
1373 struct scsipi_link *sc_link = xs->sc_link;
1374 struct aha_softc *sc = sc_link->adapter_softc;
1375 int s;
1376
1377 scsi_print_addr(sc_link);
1378 printf("timed out");
1379
1380 s = splbio();
1381
1382 #ifdef AHADIAG
1383 /*
1384 * If The ccb's mbx is not free, then the board has gone south?
1385 */
1386 aha_collect_mbo(sc);
1387 if (ccb->flags & CCB_SENDING) {
1388 printf("%s: not taking commands!\n", sc->sc_dev.dv_xname);
1389 Debugger();
1390 }
1391 #endif
1392
1393 /*
1394 * If it has been through before, then
1395 * a previous abort has failed, don't
1396 * try abort again
1397 */
1398 if (ccb->flags & CCB_ABORT) {
1399 /* abort timed out */
1400 printf(" AGAIN\n");
1401 /* XXX Must reset! */
1402 } else {
1403 /* abort the operation that has timed out */
1404 printf("\n");
1405 ccb->xs->error = XS_TIMEOUT;
1406 ccb->timeout = AHA_ABORT_TIMEOUT;
1407 ccb->flags |= CCB_ABORT;
1408 aha_queue_ccb(sc, ccb);
1409 }
1410
1411 splx(s);
1412 }
1413