aha.c revision 1.8 1 /* $NetBSD: aha.c,v 1.8 1997/10/28 18:40:07 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 void 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 void
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;
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 if (bus_dmamap_create(dmat, sizeof(struct aha_ccb), 1,
519 sizeof(struct aha_ccb), 0, BUS_DMA_NOWAIT, &ccb->dmamap_self) ||
520
521 /* XXX What's a good value for this? */
522 bus_dmamap_create(dmat, AHA_MAXXFER, AHA_NSEG, AHA_MAXXFER,
523 0, BUS_DMA_NOWAIT|BUS_DMA_ALLOCNOW, &ccb->dmamap_xfer))
524 panic("aha_init_ccb: can't create DMA maps");
525
526 /*
527 * Load the permanent DMA maps.
528 */
529 if (bus_dmamap_load(dmat, ccb->dmamap_self, ccb,
530 sizeof(struct aha_ccb), NULL, BUS_DMA_NOWAIT))
531 panic("aha_init_ccb: can't load permanent maps");
532
533 /*
534 * put in the phystokv hash table
535 * Never gets taken out.
536 */
537 ccb->hashkey = ccb->dmamap_self->dm_segs[0].ds_addr;
538 hashnum = CCB_HASH(ccb->hashkey);
539 ccb->nexthash = sc->sc_ccbhash[hashnum];
540 sc->sc_ccbhash[hashnum] = ccb;
541 aha_reset_ccb(sc, ccb);
542 }
543
544 /*
545 * Create a set of ccbs and add them to the free list.
546 */
547 int
548 aha_create_ccbs(sc, mem, size, max_ccbs)
549 struct aha_softc *sc;
550 void *mem;
551 size_t size;
552 int max_ccbs;
553 {
554 bus_dma_segment_t seg;
555 struct aha_ccb *ccb;
556 int rseg, error;
557
558 if (sc->sc_numccbs >= AHA_CCB_MAX)
559 return (0);
560
561 if (max_ccbs > AHA_CCB_MAX)
562 max_ccbs = AHA_CCB_MAX;
563
564 if ((ccb = mem) != NULL)
565 goto have_mem;
566
567 size = NBPG;
568 error = bus_dmamem_alloc(sc->sc_dmat, size, NBPG, 0, &seg, 1, &rseg,
569 BUS_DMA_NOWAIT);
570 if (error)
571 return (error);
572
573 error = bus_dmamem_map(sc->sc_dmat, &seg, rseg, size,
574 (caddr_t *)&ccb, BUS_DMA_NOWAIT|BUS_DMAMEM_NOSYNC);
575 if (error) {
576 bus_dmamem_free(sc->sc_dmat, &seg, rseg);
577 return (error);
578 }
579
580 have_mem:
581 bzero(ccb, size);
582 while (size > sizeof(struct aha_ccb) && sc->sc_numccbs < max_ccbs) {
583 aha_init_ccb(sc, ccb);
584 TAILQ_INSERT_TAIL(&sc->sc_free_ccb, ccb, chain);
585 (caddr_t)ccb += ALIGN(sizeof(struct aha_ccb));
586 size -= ALIGN(sizeof(struct aha_ccb));
587 sc->sc_numccbs++;
588 }
589
590 return (0);
591 }
592
593 /*
594 * Get a free ccb
595 *
596 * If there are none, see if we can allocate a new one. If so, put it in
597 * the hash table too otherwise either return an error or sleep.
598 */
599 struct aha_ccb *
600 aha_get_ccb(sc, flags)
601 struct aha_softc *sc;
602 int flags;
603 {
604 struct aha_ccb *ccb;
605 int s;
606
607 s = splbio();
608
609 /*
610 * If we can and have to, sleep waiting for one to come free
611 * but only if we can't allocate a new one.
612 */
613 for (;;) {
614 ccb = sc->sc_free_ccb.tqh_first;
615 if (ccb) {
616 TAILQ_REMOVE(&sc->sc_free_ccb, ccb, chain);
617 break;
618 }
619 if (sc->sc_numccbs < AHA_CCB_MAX) {
620 if (aha_create_ccbs(sc, NULL, 0, AHA_CCB_MAX)) {
621 printf("%s: can't allocate ccbs\n",
622 sc->sc_dev.dv_xname);
623 goto out;
624 }
625 continue;
626 }
627 if ((flags & SCSI_NOSLEEP) != 0)
628 goto out;
629 tsleep(&sc->sc_free_ccb, PRIBIO, "ahaccb", 0);
630 }
631
632 ccb->flags |= CCB_ALLOC;
633
634 out:
635 splx(s);
636 return (ccb);
637 }
638
639 /*
640 * Given a physical address, find the ccb that it corresponds to.
641 */
642 struct aha_ccb *
643 aha_ccb_phys_kv(sc, ccb_phys)
644 struct aha_softc *sc;
645 u_long ccb_phys;
646 {
647 int hashnum = CCB_HASH(ccb_phys);
648 struct aha_ccb *ccb = sc->sc_ccbhash[hashnum];
649
650 while (ccb) {
651 if (ccb->hashkey == ccb_phys)
652 break;
653 ccb = ccb->nexthash;
654 }
655 return (ccb);
656 }
657
658 /*
659 * Queue a CCB to be sent to the controller, and send it if possible.
660 */
661 void
662 aha_queue_ccb(sc, ccb)
663 struct aha_softc *sc;
664 struct aha_ccb *ccb;
665 {
666
667 TAILQ_INSERT_TAIL(&sc->sc_waiting_ccb, ccb, chain);
668 aha_start_ccbs(sc);
669 }
670
671 /*
672 * Garbage collect mailboxes that are no longer in use.
673 */
674 void
675 aha_collect_mbo(sc)
676 struct aha_softc *sc;
677 {
678 struct aha_mbx_out *wmbo; /* Mail Box Out pointer */
679 #ifdef AHADIAG
680 struct aha_ccb *ccb;
681 #endif
682
683 wmbo = wmbx->cmbo;
684
685 while (sc->sc_mbofull > 0) {
686 if (wmbo->cmd != AHA_MBO_FREE)
687 break;
688
689 #ifdef AHADIAG
690 ccb = aha_ccb_phys_kv(sc, phystol(wmbo->ccb_addr));
691 ccb->flags &= ~CCB_SENDING;
692 #endif
693
694 --sc->sc_mbofull;
695 aha_nextmbx(wmbo, wmbx, mbo);
696 }
697
698 wmbx->cmbo = wmbo;
699 }
700
701 /*
702 * Send as many CCBs as we have empty mailboxes for.
703 */
704 void
705 aha_start_ccbs(sc)
706 struct aha_softc *sc;
707 {
708 bus_space_tag_t iot = sc->sc_iot;
709 bus_space_handle_t ioh = sc->sc_ioh;
710 struct aha_mbx_out *wmbo; /* Mail Box Out pointer */
711 struct aha_ccb *ccb;
712
713 wmbo = wmbx->tmbo;
714
715 while ((ccb = sc->sc_waiting_ccb.tqh_first) != NULL) {
716 if (sc->sc_mbofull >= AHA_MBX_SIZE) {
717 aha_collect_mbo(sc);
718 if (sc->sc_mbofull >= AHA_MBX_SIZE) {
719 struct aha_toggle toggle;
720
721 toggle.cmd.opcode = AHA_MBO_INTR_EN;
722 toggle.cmd.enable = 1;
723 aha_cmd(iot, ioh, sc,
724 sizeof(toggle.cmd), (u_char *)&toggle.cmd,
725 0, (u_char *)0);
726 break;
727 }
728 }
729
730 TAILQ_REMOVE(&sc->sc_waiting_ccb, ccb, chain);
731 #ifdef AHADIAG
732 ccb->flags |= CCB_SENDING;
733 #endif
734
735 /* Link ccb to mbo. */
736 ltophys(ccb->dmamap_self->dm_segs[0].ds_addr, wmbo->ccb_addr);
737 if (ccb->flags & CCB_ABORT)
738 wmbo->cmd = AHA_MBO_ABORT;
739 else
740 wmbo->cmd = AHA_MBO_START;
741
742 /* Tell the card to poll immediately. */
743 bus_space_write_1(iot, ioh, AHA_CMD_PORT, AHA_START_SCSI);
744
745 if ((ccb->xs->flags & SCSI_POLL) == 0)
746 timeout(aha_timeout, ccb, (ccb->timeout * hz) / 1000);
747
748 ++sc->sc_mbofull;
749 aha_nextmbx(wmbo, wmbx, mbo);
750 }
751
752 wmbx->tmbo = wmbo;
753 }
754
755 /*
756 * We have a ccb which has been processed by the
757 * adaptor, now we look to see how the operation
758 * went. Wake up the owner if waiting
759 */
760 void
761 aha_done(sc, ccb)
762 struct aha_softc *sc;
763 struct aha_ccb *ccb;
764 {
765 bus_dma_tag_t dmat = sc->sc_dmat;
766 struct scsipi_sense_data *s1, *s2;
767 struct scsipi_xfer *xs = ccb->xs;
768
769 SC_DEBUG(xs->sc_link, SDEV_DB2, ("aha_done\n"));
770
771 /*
772 * If we were a data transfer, unload the map that described
773 * the data buffer.
774 */
775 if (xs->datalen) {
776 bus_dmamap_sync(dmat, ccb->dmamap_xfer,
777 (xs->flags & SCSI_DATA_IN) ? BUS_DMASYNC_POSTREAD :
778 BUS_DMASYNC_POSTWRITE);
779 bus_dmamap_unload(dmat, ccb->dmamap_xfer);
780 }
781
782 /*
783 * Otherwise, put the results of the operation
784 * into the xfer and call whoever started it
785 */
786 #ifdef AHADIAG
787 if (ccb->flags & CCB_SENDING) {
788 printf("%s: exiting ccb still in transit!\n", sc->sc_dev.dv_xname);
789 Debugger();
790 return;
791 }
792 #endif
793 if ((ccb->flags & CCB_ALLOC) == 0) {
794 printf("%s: exiting ccb not allocated!\n", sc->sc_dev.dv_xname);
795 Debugger();
796 return;
797 }
798 if (xs->error == XS_NOERROR) {
799 if (ccb->host_stat != AHA_OK) {
800 switch (ccb->host_stat) {
801 case AHA_SEL_TIMEOUT: /* No response */
802 xs->error = XS_SELTIMEOUT;
803 break;
804 default: /* Other scsi protocol messes */
805 printf("%s: host_stat %x\n",
806 sc->sc_dev.dv_xname, ccb->host_stat);
807 xs->error = XS_DRIVER_STUFFUP;
808 break;
809 }
810 } else if (ccb->target_stat != SCSI_OK) {
811 switch (ccb->target_stat) {
812 case SCSI_CHECK:
813 s1 = (struct scsipi_sense_data *) (((char *) (&ccb->scsi_cmd)) +
814 ccb->scsi_cmd_length);
815 s2 = &xs->sense.scsi_sense;
816 *s2 = *s1;
817 xs->error = XS_SENSE;
818 break;
819 case SCSI_BUSY:
820 xs->error = XS_BUSY;
821 break;
822 default:
823 printf("%s: target_stat %x\n",
824 sc->sc_dev.dv_xname, ccb->target_stat);
825 xs->error = XS_DRIVER_STUFFUP;
826 break;
827 }
828 } else
829 xs->resid = 0;
830 }
831 aha_free_ccb(sc, ccb);
832 xs->flags |= ITSDONE;
833 scsipi_done(xs);
834 }
835
836 /*
837 * Find the board and find its irq/drq
838 */
839 int
840 aha_find(iot, ioh, sc)
841 bus_space_tag_t iot;
842 bus_space_handle_t ioh;
843 struct aha_probe_data *sc;
844 {
845 int i;
846 u_char sts;
847 struct aha_config config;
848 int irq, drq;
849
850 /*
851 * reset board, If it doesn't respond, assume
852 * that it's not there.. good for the probe
853 */
854
855 bus_space_write_1(iot, ioh, AHA_CTRL_PORT, AHA_CTRL_HRST | AHA_CTRL_SRST);
856
857 delay(100);
858 for (i = AHA_RESET_TIMEOUT; i; i--) {
859 sts = bus_space_read_1(iot, ioh, AHA_STAT_PORT);
860 if (sts == (AHA_STAT_IDLE | AHA_STAT_INIT))
861 break;
862 delay(1000); /* calibrated in msec */
863 }
864 if (!i) {
865 #ifdef AHADEBUG
866 if (aha_debug)
867 printf("aha_find: No answer from adaptec board\n");
868 #endif /* AHADEBUG */
869 return (0);
870 }
871
872 /*
873 * setup dma channel from jumpers and save int
874 * level
875 */
876 delay(1000); /* for Bustek 545 */
877 config.cmd.opcode = AHA_INQUIRE_CONFIG;
878 aha_cmd(iot, ioh, (struct aha_softc *)0,
879 sizeof(config.cmd), (u_char *)&config.cmd,
880 sizeof(config.reply), (u_char *)&config.reply);
881 switch (config.reply.chan) {
882 case EISADMA:
883 drq = -1;
884 break;
885 case CHAN0:
886 drq = 0;
887 break;
888 case CHAN5:
889 drq = 5;
890 break;
891 case CHAN6:
892 drq = 6;
893 break;
894 case CHAN7:
895 drq = 7;
896 break;
897 default:
898 printf("aha_find: illegal drq setting %x\n", config.reply.chan);
899 return (0);
900 }
901
902 switch (config.reply.intr) {
903 case INT9:
904 irq = 9;
905 break;
906 case INT10:
907 irq = 10;
908 break;
909 case INT11:
910 irq = 11;
911 break;
912 case INT12:
913 irq = 12;
914 break;
915 case INT14:
916 irq = 14;
917 break;
918 case INT15:
919 irq = 15;
920 break;
921 default:
922 printf("aha_find: illegal irq setting %x\n", config.reply.intr);
923 return (0);
924 }
925
926 if (sc) {
927 sc->sc_irq = irq;
928 sc->sc_drq = drq;
929 sc->sc_scsi_dev = config.reply.scsi_dev;
930 }
931
932 return (1);
933 }
934
935 /*
936 * Start the board, ready for normal operation
937 */
938 void
939 aha_init(sc)
940 struct aha_softc *sc;
941 {
942 bus_space_tag_t iot = sc->sc_iot;
943 bus_space_handle_t ioh = sc->sc_ioh;
944 bus_dma_segment_t seg;
945 struct aha_devices devices;
946 struct aha_setup setup;
947 struct aha_mailbox mailbox;
948 int i, j, initial_ccbs, rseg;
949
950 /*
951 * XXX
952 * If we are a 1542C or later, disable the extended BIOS so that the
953 * mailbox interface is unlocked.
954 * No need to check the extended BIOS flags as some of the
955 * extensions that cause us problems are not flagged in that byte.
956 */
957 if (!strncmp(sc->sc_model, "1542C", 5)) {
958 struct aha_extbios extbios;
959 struct aha_unlock unlock;
960
961 printf("%s: unlocking mailbox interface\n", sc->sc_dev.dv_xname);
962 extbios.cmd.opcode = AHA_EXT_BIOS;
963 aha_cmd(iot, ioh, sc,
964 sizeof(extbios.cmd), (u_char *)&extbios.cmd,
965 sizeof(extbios.reply), (u_char *)&extbios.reply);
966
967 #ifdef AHADEBUG
968 printf("%s: flags=%02x, mailboxlock=%02x\n",
969 sc->sc_dev.dv_xname,
970 extbios.reply.flags, extbios.reply.mailboxlock);
971 #endif /* AHADEBUG */
972
973 unlock.cmd.opcode = AHA_MBX_ENABLE;
974 unlock.cmd.junk = 0;
975 unlock.cmd.magic = extbios.reply.mailboxlock;
976 aha_cmd(iot, ioh, sc,
977 sizeof(unlock.cmd), (u_char *)&unlock.cmd,
978 0, (u_char *)0);
979 }
980
981 #if 0
982 /*
983 * Change the bus on/off times to not clash with other dma users.
984 */
985 aha_cmd(iot, ioh, 1, 0, 0, 0, AHA_BUS_ON_TIME_SET, 7);
986 aha_cmd(iot, ioh, 1, 0, 0, 0, AHA_BUS_OFF_TIME_SET, 4);
987 #endif
988
989 /* Inquire Installed Devices (to force synchronous negotiation). */
990 devices.cmd.opcode = AHA_INQUIRE_DEVICES;
991 aha_cmd(iot, ioh, sc,
992 sizeof(devices.cmd), (u_char *)&devices.cmd,
993 sizeof(devices.reply), (u_char *)&devices.reply);
994
995 /* Count installed units */
996 initial_ccbs = 0;
997 for (i = 0; i < 8; i++) {
998 for (j = 0; j < 8; j++) {
999 if (((devices.reply.lun_map[i] >> j) & 1) == 1)
1000 initial_ccbs += 1;
1001 }
1002 }
1003 initial_ccbs *= sc->sc_link.openings;
1004
1005 /* Obtain setup information from. */
1006 setup.cmd.opcode = AHA_INQUIRE_SETUP;
1007 setup.cmd.len = sizeof(setup.reply);
1008 aha_cmd(iot, ioh, sc,
1009 sizeof(setup.cmd), (u_char *)&setup.cmd,
1010 sizeof(setup.reply), (u_char *)&setup.reply);
1011
1012 printf("%s: %s, %s\n",
1013 sc->sc_dev.dv_xname,
1014 setup.reply.sync_neg ? "sync" : "async",
1015 setup.reply.parity ? "parity" : "no parity");
1016
1017 for (i = 0; i < 8; i++) {
1018 if (!setup.reply.sync[i].valid ||
1019 (!setup.reply.sync[i].offset && !setup.reply.sync[i].period))
1020 continue;
1021 printf("%s targ %d: sync, offset %d, period %dnsec\n",
1022 sc->sc_dev.dv_xname, i,
1023 setup.reply.sync[i].offset, setup.reply.sync[i].period * 50 + 200);
1024 }
1025
1026 /*
1027 * Allocate the mailbox.
1028 */
1029 if (bus_dmamem_alloc(sc->sc_dmat, NBPG, NBPG, 0, &seg, 1,
1030 &rseg, BUS_DMA_NOWAIT) ||
1031 bus_dmamem_map(sc->sc_dmat, &seg, rseg, NBPG,
1032 (caddr_t *)&wmbx, BUS_DMA_NOWAIT|BUS_DMAMEM_NOSYNC))
1033 panic("aha_init: can't create or map mailbox");
1034
1035 /*
1036 * Since DMA memory allocation is always rounded up to a
1037 * page size, create some ccbs from the leftovers.
1038 */
1039 if (aha_create_ccbs(sc, ((caddr_t)wmbx) +
1040 ALIGN(sizeof(struct aha_mbx)),
1041 NBPG - ALIGN(sizeof(struct aha_mbx)), initial_ccbs))
1042 panic("aha_init: can't create ccbs");
1043
1044 /*
1045 * Create and load the mailbox DMA map.
1046 */
1047 if (bus_dmamap_create(sc->sc_dmat, sizeof(struct aha_mbx), 1,
1048 sizeof(struct aha_mbx), 0, BUS_DMA_NOWAIT, &sc->sc_dmamap_mbox) ||
1049 bus_dmamap_load(sc->sc_dmat, sc->sc_dmamap_mbox, wmbx,
1050 sizeof(struct aha_mbx), NULL, BUS_DMA_NOWAIT))
1051 panic("aha_init: can't create or load mailbox dma map");
1052
1053 /*
1054 * Set up initial mail box for round-robin operation.
1055 */
1056 for (i = 0; i < AHA_MBX_SIZE; i++) {
1057 wmbx->mbo[i].cmd = AHA_MBO_FREE;
1058 wmbx->mbi[i].stat = AHA_MBI_FREE;
1059 }
1060 wmbx->cmbo = wmbx->tmbo = &wmbx->mbo[0];
1061 wmbx->tmbi = &wmbx->mbi[0];
1062 sc->sc_mbofull = 0;
1063
1064 /* Initialize mail box. */
1065 mailbox.cmd.opcode = AHA_MBX_INIT;
1066 mailbox.cmd.nmbx = AHA_MBX_SIZE;
1067 ltophys(sc->sc_dmamap_mbox->dm_segs[0].ds_addr, mailbox.cmd.addr);
1068 aha_cmd(iot, ioh, sc,
1069 sizeof(mailbox.cmd), (u_char *)&mailbox.cmd,
1070 0, (u_char *)0);
1071 }
1072
1073 void
1074 aha_inquire_setup_information(sc)
1075 struct aha_softc *sc;
1076 {
1077 bus_space_tag_t iot = sc->sc_iot;
1078 bus_space_handle_t ioh = sc->sc_ioh;
1079 struct aha_revision revision;
1080 u_char sts;
1081 int i;
1082 char *p;
1083
1084 strcpy(sc->sc_model, "unknown");
1085
1086 /*
1087 * Assume we have a board at this stage, do an adapter inquire
1088 * to find out what type of controller it is. If the command
1089 * fails, we assume it's either a crusty board or an old 1542
1090 * clone, and skip the board-specific stuff.
1091 */
1092 revision.cmd.opcode = AHA_INQUIRE_REVISION;
1093 if (aha_cmd(iot, ioh, sc,
1094 sizeof(revision.cmd), (u_char *)&revision.cmd,
1095 sizeof(revision.reply), (u_char *)&revision.reply)) {
1096 /*
1097 * aha_cmd() already started the reset. It's not clear we
1098 * even need to bother here.
1099 */
1100 for (i = AHA_RESET_TIMEOUT; i; i--) {
1101 sts = bus_space_read_1(iot, ioh, AHA_STAT_PORT);
1102 if (sts == (AHA_STAT_IDLE | AHA_STAT_INIT))
1103 break;
1104 delay(1000);
1105 }
1106 if (!i) {
1107 #ifdef AHADEBUG
1108 printf("aha_init: soft reset failed\n");
1109 #endif /* AHADEBUG */
1110 return;
1111 }
1112 #ifdef AHADEBUG
1113 printf("aha_init: inquire command failed\n");
1114 #endif /* AHADEBUG */
1115 goto noinquire;
1116 }
1117
1118 #ifdef AHADEBUG
1119 printf("%s: inquire %x, %x, %x, %x\n",
1120 sc->sc_dev.dv_xname,
1121 revision.reply.boardid, revision.reply.spec_opts,
1122 revision.reply.revision_1, revision.reply.revision_2);
1123 #endif /* AHADEBUG */
1124
1125 switch (revision.reply.boardid) {
1126 case 0x31:
1127 strcpy(sc->sc_model, "1540");
1128 break;
1129 case 0x41:
1130 strcpy(sc->sc_model, "1540A/1542A/1542B");
1131 break;
1132 case 0x42:
1133 strcpy(sc->sc_model, "1640");
1134 break;
1135 case 0x43:
1136 strcpy(sc->sc_model, "1542C");
1137 break;
1138 case 0x44:
1139 case 0x45:
1140 strcpy(sc->sc_model, "1542CF");
1141 break;
1142 case 0x46:
1143 strcpy(sc->sc_model, "1542CP");
1144 break;
1145 }
1146
1147 p = sc->sc_firmware;
1148 *p++ = revision.reply.revision_1;
1149 *p++ = '.';
1150 *p++ = revision.reply.revision_2;
1151 *p = '\0';
1152
1153 noinquire:
1154 printf("%s: model AHA-%s, firmware %s\n",
1155 sc->sc_dev.dv_xname,
1156 sc->sc_model, sc->sc_firmware);
1157 }
1158
1159 void
1160 ahaminphys(bp)
1161 struct buf *bp;
1162 {
1163
1164 if (bp->b_bcount > AHA_MAXXFER)
1165 bp->b_bcount = AHA_MAXXFER;
1166 minphys(bp);
1167 }
1168
1169 /*
1170 * start a scsi operation given the command and the data address. Also needs
1171 * the unit, target and lu.
1172 */
1173 int
1174 aha_scsi_cmd(xs)
1175 struct scsipi_xfer *xs;
1176 {
1177 struct scsipi_link *sc_link = xs->sc_link;
1178 struct aha_softc *sc = sc_link->adapter_softc;
1179 bus_dma_tag_t dmat = sc->sc_dmat;
1180 struct aha_ccb *ccb;
1181 int error, seg, flags, s;
1182
1183 SC_DEBUG(sc_link, SDEV_DB2, ("aha_scsi_cmd\n"));
1184 /*
1185 * get a ccb to use. If the transfer
1186 * is from a buf (possibly from interrupt time)
1187 * then we can't allow it to sleep
1188 */
1189 flags = xs->flags;
1190 if ((ccb = aha_get_ccb(sc, flags)) == NULL) {
1191 xs->error = XS_DRIVER_STUFFUP;
1192 return (TRY_AGAIN_LATER);
1193 }
1194 ccb->xs = xs;
1195 ccb->timeout = xs->timeout;
1196
1197 /*
1198 * Put all the arguments for the xfer in the ccb
1199 */
1200 if (flags & SCSI_RESET) {
1201 ccb->opcode = AHA_RESET_CCB;
1202 ccb->scsi_cmd_length = 0;
1203 } else {
1204 /* can't use S/G if zero length */
1205 ccb->opcode = (xs->datalen ? AHA_INIT_SCAT_GATH_CCB
1206 : AHA_INITIATOR_CCB);
1207 bcopy(xs->cmd, &ccb->scsi_cmd,
1208 ccb->scsi_cmd_length = xs->cmdlen);
1209 }
1210
1211 if (xs->datalen) {
1212 /*
1213 * Map the DMA transfer.
1214 */
1215 #ifdef TFS
1216 if (flags & SCSI_DATA_UIO) {
1217 error = bus_dmamap_load_uio(dmat,
1218 ccb->dmamap_xfer, (struct uio *)xs->data,
1219 (flags & SCSI_NOSLEEP) ? BUS_DMA_NOWAIT :
1220 BUS_DMA_WAITOK);
1221 } else
1222 #endif
1223 {
1224 error = bus_dmamap_load(dmat,
1225 ccb->dmamap_xfer, xs->data, xs->datalen, NULL,
1226 (flags & SCSI_NOSLEEP) ? BUS_DMA_NOWAIT :
1227 BUS_DMA_WAITOK);
1228 }
1229
1230 if (error) {
1231 if (error == EFBIG) {
1232 printf("%s: aha_scsi_cmd, more than %d"
1233 " dma segments\n",
1234 sc->sc_dev.dv_xname, AHA_NSEG);
1235 } else {
1236 printf("%s: aha_scsi_cmd, error %d loading"
1237 " dma map\n",
1238 sc->sc_dev.dv_xname, error);
1239 }
1240 goto bad;
1241 }
1242
1243 bus_dmamap_sync(dmat, ccb->dmamap_xfer,
1244 (flags & SCSI_DATA_IN) ? BUS_DMASYNC_PREREAD :
1245 BUS_DMASYNC_PREWRITE);
1246
1247 /*
1248 * Load the hardware scatter/gather map with the
1249 * contents of the DMA map.
1250 */
1251 for (seg = 0; seg < ccb->dmamap_xfer->dm_nsegs; seg++) {
1252 ltophys(ccb->dmamap_xfer->dm_segs[seg].ds_addr,
1253 ccb->scat_gath[seg].seg_addr);
1254 ltophys(ccb->dmamap_xfer->dm_segs[seg].ds_len,
1255 ccb->scat_gath[seg].seg_len);
1256 }
1257
1258 ltophys(ccb->dmamap_self->dm_segs[0].ds_addr +
1259 offsetof(struct aha_ccb, scat_gath), ccb->data_addr);
1260 ltophys(ccb->dmamap_xfer->dm_nsegs *
1261 sizeof(struct aha_scat_gath), ccb->data_length);
1262 } else {
1263 /*
1264 * No data xfer, use non S/G values.
1265 */
1266 ltophys(0, ccb->data_addr);
1267 ltophys(0, ccb->data_length);
1268 }
1269
1270 ccb->data_out = 0;
1271 ccb->data_in = 0;
1272 ccb->target = sc_link->scsipi_scsi.target;
1273 ccb->lun = sc_link->scsipi_scsi.lun;
1274 ccb->req_sense_length = sizeof(ccb->scsi_sense);
1275 ccb->host_stat = 0x00;
1276 ccb->target_stat = 0x00;
1277 ccb->link_id = 0;
1278 ltophys(0, ccb->link_addr);
1279
1280 s = splbio();
1281 aha_queue_ccb(sc, ccb);
1282 splx(s);
1283
1284 /*
1285 * Usually return SUCCESSFULLY QUEUED
1286 */
1287 SC_DEBUG(sc_link, SDEV_DB3, ("cmd_sent\n"));
1288 if ((flags & SCSI_POLL) == 0)
1289 return (SUCCESSFULLY_QUEUED);
1290
1291 /*
1292 * If we can't use interrupts, poll on completion
1293 */
1294 if (aha_poll(sc, xs, ccb->timeout)) {
1295 aha_timeout(ccb);
1296 if (aha_poll(sc, xs, ccb->timeout))
1297 aha_timeout(ccb);
1298 }
1299 return (COMPLETE);
1300
1301 bad:
1302 xs->error = XS_DRIVER_STUFFUP;
1303 aha_free_ccb(sc, ccb);
1304 return (COMPLETE);
1305 }
1306
1307 /*
1308 * Poll a particular unit, looking for a particular xs
1309 */
1310 int
1311 aha_poll(sc, xs, count)
1312 struct aha_softc *sc;
1313 struct scsipi_xfer *xs;
1314 int count;
1315 {
1316 bus_space_tag_t iot = sc->sc_iot;
1317 bus_space_handle_t ioh = sc->sc_ioh;
1318
1319 /* timeouts are in msec, so we loop in 1000 usec cycles */
1320 while (count) {
1321 /*
1322 * If we had interrupts enabled, would we
1323 * have got an interrupt?
1324 */
1325 if (bus_space_read_1(iot, ioh, AHA_INTR_PORT) & AHA_INTR_ANYINTR)
1326 aha_intr(sc);
1327 if (xs->flags & ITSDONE)
1328 return (0);
1329 delay(1000); /* only happens in boot so ok */
1330 count--;
1331 }
1332 return (1);
1333 }
1334
1335 void
1336 aha_timeout(arg)
1337 void *arg;
1338 {
1339 struct aha_ccb *ccb = arg;
1340 struct scsipi_xfer *xs = ccb->xs;
1341 struct scsipi_link *sc_link = xs->sc_link;
1342 struct aha_softc *sc = sc_link->adapter_softc;
1343 int s;
1344
1345 scsi_print_addr(sc_link);
1346 printf("timed out");
1347
1348 s = splbio();
1349
1350 #ifdef AHADIAG
1351 /*
1352 * If The ccb's mbx is not free, then the board has gone south?
1353 */
1354 aha_collect_mbo(sc);
1355 if (ccb->flags & CCB_SENDING) {
1356 printf("%s: not taking commands!\n", sc->sc_dev.dv_xname);
1357 Debugger();
1358 }
1359 #endif
1360
1361 /*
1362 * If it has been through before, then
1363 * a previous abort has failed, don't
1364 * try abort again
1365 */
1366 if (ccb->flags & CCB_ABORT) {
1367 /* abort timed out */
1368 printf(" AGAIN\n");
1369 /* XXX Must reset! */
1370 } else {
1371 /* abort the operation that has timed out */
1372 printf("\n");
1373 ccb->xs->error = XS_TIMEOUT;
1374 ccb->timeout = AHA_ABORT_TIMEOUT;
1375 ccb->flags |= CCB_ABORT;
1376 aha_queue_ccb(sc, ccb);
1377 }
1378
1379 splx(s);
1380 }
1381