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