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