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