xref: /netbsd-src/sys/dev/ic/aha.c (revision 06be8101a16cc95f40783b3cb7afd12112103a9a)
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@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