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