xref: /NextBSD/sys/dev/aha/aha.c (revision 287e3b14e9552995def1802ec9c5034f4adf28ec)
1 /*
2  * Generic register and struct definitions for the Adaptech 154x/164x
3  * SCSI host adapters. Product specific probe and attach routines can
4  * be found in:
5  *      aha 1542A/1542B/1542C/1542CF/1542CP	aha_isa.c
6  *      aha 1640			aha_mca.c
7  */
8 /*-
9  * Copyright (c) 1998 M. Warner Losh.
10  * All Rights Reserved.
11  *
12  * Redistribution and use in source and binary forms, with or without
13  * modification, are permitted provided that the following conditions
14  * are met:
15  * 1. Redistributions of source code must retain the above copyright
16  *    notice, this list of conditions and the following disclaimer.
17  * 2. Redistributions in binary form must reproduce the above copyright
18  *    notice, this list of conditions and the following disclaimer in the
19  *    documentation and/or other materials provided with the distribution.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  *
33  * Derived from bt.c written by:
34  *
35  * Copyright (c) 1998 Justin T. Gibbs.
36  * All rights reserved.
37  *
38  * Redistribution and use in source and binary forms, with or without
39  * modification, are permitted provided that the following conditions
40  * are met:
41  * 1. Redistributions of source code must retain the above copyright
42  *    notice, this list of conditions, and the following disclaimer,
43  *    without modification, immediately at the beginning of the file.
44  * 2. The name of the author may not be used to endorse or promote products
45  *    derived from this software without specific prior written permission.
46  *
47  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
48  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
49  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
50  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
51  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
52  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
53  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
54  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
55  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
56  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
57  * SUCH DAMAGE.
58  */
59 
60 #include <sys/cdefs.h>
61 __FBSDID("$FreeBSD$");
62 
63 #include <sys/param.h>
64 #include <sys/conf.h>
65 #include <sys/bus.h>
66 #include <sys/systm.h>
67 #include <sys/malloc.h>
68 #include <sys/kernel.h>
69 #include <sys/lock.h>
70 #include <sys/module.h>
71 #include <sys/mutex.h>
72 #include <sys/rman.h>
73 
74 #include <machine/bus.h>
75 
76 #include <cam/cam.h>
77 #include <cam/cam_ccb.h>
78 #include <cam/cam_sim.h>
79 #include <cam/cam_xpt_sim.h>
80 #include <cam/cam_debug.h>
81 
82 #include <cam/scsi/scsi_message.h>
83 
84 #include <dev/aha/ahareg.h>
85 
86 #define	PRVERB(x) do { if (bootverbose) device_printf x; } while (0)
87 
88 /* Macro to determine that a rev is potentially a new valid one
89  * so that the driver doesn't keep breaking on new revs as it
90  * did for the CF and CP.
91  */
92 #define PROBABLY_NEW_BOARD(REV) (REV > 0x43 && REV < 0x56)
93 
94 /* MailBox Management functions */
95 static __inline void	ahanextinbox(struct aha_softc *aha);
96 static __inline void	ahanextoutbox(struct aha_softc *aha);
97 
98 #define aha_name(aha)	device_get_nameunit(aha->dev)
99 
100 static __inline void
ahanextinbox(struct aha_softc * aha)101 ahanextinbox(struct aha_softc *aha)
102 {
103 	if (aha->cur_inbox == aha->last_inbox)
104 		aha->cur_inbox = aha->in_boxes;
105 	else
106 		aha->cur_inbox++;
107 }
108 
109 static __inline void
ahanextoutbox(struct aha_softc * aha)110 ahanextoutbox(struct aha_softc *aha)
111 {
112 	if (aha->cur_outbox == aha->last_outbox)
113 		aha->cur_outbox = aha->out_boxes;
114 	else
115 		aha->cur_outbox++;
116 }
117 
118 #define ahautoa24(u,s3)			\
119 	(s3)[0] = ((u) >> 16) & 0xff;	\
120 	(s3)[1] = ((u) >> 8) & 0xff;	\
121 	(s3)[2] = (u) & 0xff;
122 
123 #define aha_a24tou(s3) \
124 	(((s3)[0] << 16) | ((s3)[1] << 8) | (s3)[2])
125 
126 /* CCB Management functions */
127 static __inline uint32_t		ahaccbvtop(struct aha_softc *aha,
128 						  struct aha_ccb *accb);
129 static __inline struct aha_ccb*		ahaccbptov(struct aha_softc *aha,
130 						  uint32_t ccb_addr);
131 
132 static __inline uint32_t
ahaccbvtop(struct aha_softc * aha,struct aha_ccb * accb)133 ahaccbvtop(struct aha_softc *aha, struct aha_ccb *accb)
134 {
135 	return (aha->aha_ccb_physbase
136 	      + (uint32_t)((caddr_t)accb - (caddr_t)aha->aha_ccb_array));
137 }
138 static __inline struct aha_ccb *
ahaccbptov(struct aha_softc * aha,uint32_t ccb_addr)139 ahaccbptov(struct aha_softc *aha, uint32_t ccb_addr)
140 {
141 	return (aha->aha_ccb_array +
142 	      + ((struct aha_ccb*)(uintptr_t)ccb_addr -
143 	         (struct aha_ccb*)(uintptr_t)aha->aha_ccb_physbase));
144 }
145 
146 static struct aha_ccb*	ahagetccb(struct aha_softc *aha);
147 static __inline void	ahafreeccb(struct aha_softc *aha, struct aha_ccb *accb);
148 static void		ahaallocccbs(struct aha_softc *aha);
149 static bus_dmamap_callback_t ahaexecuteccb;
150 static void		ahadone(struct aha_softc *aha, struct aha_ccb *accb,
151 			       aha_mbi_comp_code_t comp_code);
152 static void		aha_intr_locked(struct aha_softc *aha);
153 
154 /* Host adapter command functions */
155 static int	ahareset(struct aha_softc* aha, int hard_reset);
156 
157 /* Initialization functions */
158 static int			ahainitmboxes(struct aha_softc *aha);
159 static bus_dmamap_callback_t	ahamapmboxes;
160 static bus_dmamap_callback_t	ahamapccbs;
161 static bus_dmamap_callback_t	ahamapsgs;
162 
163 /* Transfer Negotiation Functions */
164 static void ahafetchtransinfo(struct aha_softc *aha,
165 			     struct ccb_trans_settings *cts);
166 
167 /* CAM SIM entry points */
168 #define ccb_accb_ptr spriv_ptr0
169 #define ccb_aha_ptr spriv_ptr1
170 static void	ahaaction(struct cam_sim *sim, union ccb *ccb);
171 static void	ahapoll(struct cam_sim *sim);
172 
173 /* Our timeout handler */
174 static void	ahatimeout(void *arg);
175 
176 /* Exported functions */
177 void
aha_alloc(struct aha_softc * aha)178 aha_alloc(struct aha_softc *aha)
179 {
180 
181 	SLIST_INIT(&aha->free_aha_ccbs);
182 	LIST_INIT(&aha->pending_ccbs);
183 	SLIST_INIT(&aha->sg_maps);
184 	aha->ccb_sg_opcode = INITIATOR_SG_CCB_WRESID;
185 	aha->ccb_ccb_opcode = INITIATOR_CCB_WRESID;
186 	mtx_init(&aha->lock, "aha", NULL, MTX_DEF);
187 }
188 
189 void
aha_free(struct aha_softc * aha)190 aha_free(struct aha_softc *aha)
191 {
192 	switch (aha->init_level) {
193 	default:
194 	case 8:
195 	{
196 		struct sg_map_node *sg_map;
197 
198 		while ((sg_map = SLIST_FIRST(&aha->sg_maps))!= NULL) {
199 			SLIST_REMOVE_HEAD(&aha->sg_maps, links);
200 			bus_dmamap_unload(aha->sg_dmat, sg_map->sg_dmamap);
201 			bus_dmamem_free(aha->sg_dmat, sg_map->sg_vaddr,
202 			    sg_map->sg_dmamap);
203 			free(sg_map, M_DEVBUF);
204 		}
205 		bus_dma_tag_destroy(aha->sg_dmat);
206 	}
207 	case 7:
208 		bus_dmamap_unload(aha->ccb_dmat, aha->ccb_dmamap);
209 	case 6:
210 		bus_dmamem_free(aha->ccb_dmat, aha->aha_ccb_array,
211 		    aha->ccb_dmamap);
212 	case 5:
213 		bus_dma_tag_destroy(aha->ccb_dmat);
214 	case 4:
215 		bus_dmamap_unload(aha->mailbox_dmat, aha->mailbox_dmamap);
216 	case 3:
217 		bus_dmamem_free(aha->mailbox_dmat, aha->in_boxes,
218 		    aha->mailbox_dmamap);
219 	case 2:
220 		bus_dma_tag_destroy(aha->buffer_dmat);
221 	case 1:
222 		bus_dma_tag_destroy(aha->mailbox_dmat);
223 	case 0:
224 		break;
225 	}
226 	mtx_destroy(&aha->lock);
227 }
228 
229 /*
230  * Probe the adapter and verify that the card is an Adaptec.
231  */
232 int
aha_probe(struct aha_softc * aha)233 aha_probe(struct aha_softc* aha)
234 {
235 	u_int	 status;
236 	u_int	 intstat;
237 	int	 error;
238 	board_id_data_t	board_id;
239 
240 	/*
241 	 * See if the three I/O ports look reasonable.
242 	 * Touch the minimal number of registers in the
243 	 * failure case.
244 	 */
245 	status = aha_inb(aha, STATUS_REG);
246 	if ((status == 0) ||
247 	    (status & (DIAG_ACTIVE|CMD_REG_BUSY | STATUS_REG_RSVD)) != 0) {
248 		PRVERB((aha->dev, "status reg test failed %x\n", status));
249 		return (ENXIO);
250 	}
251 
252 	intstat = aha_inb(aha, INTSTAT_REG);
253 	if ((intstat & INTSTAT_REG_RSVD) != 0) {
254 		PRVERB((aha->dev, "Failed Intstat Reg Test\n"));
255 		return (ENXIO);
256 	}
257 
258 	/*
259 	 * Looking good so far.  Final test is to reset the
260 	 * adapter and fetch the board ID and ensure we aren't
261 	 * looking at a BusLogic.
262 	 */
263 	if ((error = ahareset(aha, /*hard_reset*/TRUE)) != 0) {
264 		PRVERB((aha->dev, "Failed Reset\n"));
265 		return (ENXIO);
266 	}
267 
268 	/*
269 	 * Get the board ID.  We use this to see if we're dealing with
270 	 * a buslogic card or an aha card (or clone).
271 	 */
272 	error = aha_cmd(aha, AOP_INQUIRE_BOARD_ID, NULL, /*parmlen*/0,
273 	    (uint8_t*)&board_id, sizeof(board_id), DEFAULT_CMD_TIMEOUT);
274 	if (error != 0) {
275 		PRVERB((aha->dev, "INQUIRE failed %x\n", error));
276 		return (ENXIO);
277 	}
278 	aha->fw_major = board_id.firmware_rev_major;
279 	aha->fw_minor = board_id.firmware_rev_minor;
280 	aha->boardid = board_id.board_type;
281 
282 	/*
283 	 * The Buslogic cards have an id of either 0x41 or 0x42.  So
284 	 * if those come up in the probe, we test the geometry register
285 	 * of the board.  Adaptec boards that are this old will not have
286 	 * this register, and return 0xff, while buslogic cards will return
287 	 * something different.
288 	 *
289 	 * It appears that for reasons unknow, for the for the
290 	 * aha-1542B cards, we need to wait a little bit before trying
291 	 * to read the geometry register.  I picked 10ms since we have
292 	 * reports that a for loop to 1000 did the trick, and this
293 	 * errs on the side of conservatism.  Besides, no one will
294 	 * notice a 10mS delay here, even the 1542B card users :-)
295 	 *
296 	 * Some compatible cards return 0 here.  Some cards also
297 	 * seem to return 0x7f.
298 	 *
299 	 * XXX I'm not sure how this will impact other cloned cards
300 	 *
301 	 * This really should be replaced with the esetup command, since
302 	 * that appears to be more reliable.  This becomes more and more
303 	 * true over time as we discover more cards that don't read the
304 	 * geometry register consistantly.
305 	 */
306 	if (aha->boardid <= 0x42) {
307 		/* Wait 10ms before reading */
308 		DELAY(10000);
309 		status = aha_inb(aha, GEOMETRY_REG);
310 		if (status != 0xff && status != 0x00 && status != 0x7f) {
311 			PRVERB((aha->dev, "Geometry Register test failed %#x\n",
312 				status));
313 			return (ENXIO);
314 		}
315 	}
316 
317 	return (0);
318 }
319 
320 /*
321  * Pull the boards setup information and record it in our softc.
322  */
323 int
aha_fetch_adapter_info(struct aha_softc * aha)324 aha_fetch_adapter_info(struct aha_softc *aha)
325 {
326 	setup_data_t	setup_info;
327 	config_data_t config_data;
328 	uint8_t length_param;
329 	int	 error;
330 	struct	aha_extbios extbios;
331 
332 	switch (aha->boardid) {
333 	case BOARD_1540_16HEAD_BIOS:
334 		snprintf(aha->model, sizeof(aha->model), "1540 16 head BIOS");
335 		break;
336 	case BOARD_1540_64HEAD_BIOS:
337 		snprintf(aha->model, sizeof(aha->model), "1540 64 head BIOS");
338 		break;
339 	case BOARD_1542:
340 		snprintf(aha->model, sizeof(aha->model), "1540/1542 64 head BIOS");
341 		break;
342 	case BOARD_1640:
343 		snprintf(aha->model, sizeof(aha->model), "1640");
344 		break;
345 	case BOARD_1740:
346 		snprintf(aha->model, sizeof(aha->model), "1740A/1742A/1744");
347 		break;
348 	case BOARD_1542C:
349 		snprintf(aha->model, sizeof(aha->model), "1542C");
350 		break;
351 	case BOARD_1542CF:
352 		snprintf(aha->model, sizeof(aha->model), "1542CF");
353 		break;
354 	case BOARD_1542CP:
355 		snprintf(aha->model, sizeof(aha->model), "1542CP");
356 		break;
357 	default:
358 		snprintf(aha->model, sizeof(aha->model), "Unknown");
359 		break;
360 	}
361 	/*
362 	 * If we are a new type of 1542 board (anything newer than a 1542C)
363 	 * then disable the extended bios so that the
364 	 * mailbox interface is unlocked.
365 	 * This is also true for the 1542B Version 3.20. First Adaptec
366 	 * board that supports >1Gb drives.
367 	 * No need to check the extended bios flags as some of the
368 	 * extensions that cause us problems are not flagged in that byte.
369 	 */
370 	if (PROBABLY_NEW_BOARD(aha->boardid) ||
371 		(aha->boardid == 0x41
372 		&& aha->fw_major == 0x31 &&
373 		aha->fw_minor >= 0x34)) {
374 		error = aha_cmd(aha, AOP_RETURN_EXT_BIOS_INFO, NULL,
375 		    /*paramlen*/0, (u_char *)&extbios, sizeof(extbios),
376 		    DEFAULT_CMD_TIMEOUT);
377 		if (error != 0) {
378 			device_printf(aha->dev,
379 			    "AOP_RETURN_EXT_BIOS_INFO - Failed.");
380 			return (error);
381 		}
382 		error = aha_cmd(aha, AOP_MBOX_IF_ENABLE, (uint8_t *)&extbios,
383 		    /*paramlen*/2, NULL, 0, DEFAULT_CMD_TIMEOUT);
384 		if (error != 0) {
385 			device_printf(aha->dev, "AOP_MBOX_IF_ENABLE - Failed.");
386 			return (error);
387 		}
388 	}
389 	if (aha->boardid < 0x41)
390 		device_printf(aha->dev, "Warning: aha-1542A won't work.\n");
391 
392 	aha->max_sg = 17;		/* Need >= 17 to do 64k I/O */
393 	aha->diff_bus = 0;
394 	aha->extended_lun = 0;
395 	aha->extended_trans = 0;
396 	aha->max_ccbs = 16;
397 	/* Determine Sync/Wide/Disc settings */
398 	length_param = sizeof(setup_info);
399 	error = aha_cmd(aha, AOP_INQUIRE_SETUP_INFO, &length_param,
400 	    /*paramlen*/1, (uint8_t*)&setup_info, sizeof(setup_info),
401 	    DEFAULT_CMD_TIMEOUT);
402 	if (error != 0) {
403 		device_printf(aha->dev, "aha_fetch_adapter_info - Failed "
404 		    "Get Setup Info\n");
405 		return (error);
406 	}
407 	if (setup_info.initiate_sync != 0) {
408 		aha->sync_permitted = ALL_TARGETS;
409 	}
410 	aha->disc_permitted = ALL_TARGETS;
411 
412 	/* We need as many mailboxes as we can have ccbs */
413 	aha->num_boxes = aha->max_ccbs;
414 
415 	/* Determine our SCSI ID */
416 	error = aha_cmd(aha, AOP_INQUIRE_CONFIG, NULL, /*parmlen*/0,
417 	    (uint8_t*)&config_data, sizeof(config_data), DEFAULT_CMD_TIMEOUT);
418 	if (error != 0) {
419 		device_printf(aha->dev,
420 		    "aha_fetch_adapter_info - Failed Get Config\n");
421 		return (error);
422 	}
423 	aha->scsi_id = config_data.scsi_id;
424 	return (0);
425 }
426 
427 /*
428  * Start the board, ready for normal operation
429  */
430 int
aha_init(struct aha_softc * aha)431 aha_init(struct aha_softc* aha)
432 {
433 	/* Announce the Adapter */
434 	device_printf(aha->dev, "AHA-%s FW Rev. %c.%c (ID=%x) ",
435 	    aha->model, aha->fw_major, aha->fw_minor, aha->boardid);
436 
437 	if (aha->diff_bus != 0)
438 		printf("Diff ");
439 
440 	printf("SCSI Host Adapter, SCSI ID %d, %d CCBs\n", aha->scsi_id,
441 	    aha->max_ccbs);
442 
443 	/*
444 	 * Create our DMA tags.  These tags define the kinds of device
445 	 * accessible memory allocations and memory mappings we will
446 	 * need to perform during normal operation.
447 	 *
448 	 * Unless we need to further restrict the allocation, we rely
449 	 * on the restrictions of the parent dmat, hence the common
450 	 * use of MAXADDR and MAXSIZE.
451 	 */
452 
453 	/* DMA tag for mapping buffers into device visible space. */
454 	if (bus_dma_tag_create( /* parent	*/ aha->parent_dmat,
455 				/* alignment	*/ 1,
456 				/* boundary	*/ 0,
457 				/* lowaddr	*/ BUS_SPACE_MAXADDR,
458 				/* highaddr	*/ BUS_SPACE_MAXADDR,
459 				/* filter	*/ NULL,
460 				/* filterarg	*/ NULL,
461 				/* maxsize	*/ DFLTPHYS,
462 				/* nsegments	*/ AHA_NSEG,
463 				/* maxsegsz	*/ BUS_SPACE_MAXSIZE_24BIT,
464 				/* flags	*/ BUS_DMA_ALLOCNOW,
465 				/* lockfunc	*/ busdma_lock_mutex,
466 				/* lockarg	*/ &aha->lock,
467 				&aha->buffer_dmat) != 0) {
468 		goto error_exit;
469 	}
470 
471 	aha->init_level++;
472 	/* DMA tag for our mailboxes */
473 	if (bus_dma_tag_create(	/* parent	*/ aha->parent_dmat,
474 				/* alignment	*/ 1,
475 				/* boundary	*/ 0,
476 				/* lowaddr	*/ BUS_SPACE_MAXADDR,
477 				/* highaddr	*/ BUS_SPACE_MAXADDR,
478 				/* filter	*/ NULL,
479 				/* filterarg	*/ NULL,
480 				/* maxsize	*/ aha->num_boxes *
481 						   (sizeof(aha_mbox_in_t) +
482 						    sizeof(aha_mbox_out_t)),
483 				/* nsegments	*/ 1,
484 				/* maxsegsz	*/ BUS_SPACE_MAXSIZE_24BIT,
485 				/* flags	*/ 0,
486 				/* lockfunc	*/ NULL,
487 				/* lockarg	*/ NULL,
488 				&aha->mailbox_dmat) != 0) {
489 		goto error_exit;
490         }
491 
492 	aha->init_level++;
493 
494 	/* Allocation for our mailboxes */
495 	if (bus_dmamem_alloc(aha->mailbox_dmat, (void **)&aha->out_boxes,
496 	    BUS_DMA_NOWAIT, &aha->mailbox_dmamap) != 0)
497 		goto error_exit;
498 
499 	aha->init_level++;
500 
501 	/* And permanently map them */
502 	bus_dmamap_load(aha->mailbox_dmat, aha->mailbox_dmamap,
503 	    aha->out_boxes, aha->num_boxes * (sizeof(aha_mbox_in_t) +
504 	    sizeof(aha_mbox_out_t)), ahamapmboxes, aha, /*flags*/0);
505 
506 	aha->init_level++;
507 
508 	aha->in_boxes = (aha_mbox_in_t *)&aha->out_boxes[aha->num_boxes];
509 
510 	ahainitmboxes(aha);
511 
512 	/* DMA tag for our ccb structures */
513 	if (bus_dma_tag_create(	/* parent	*/ aha->parent_dmat,
514 				/* alignment	*/ 1,
515 				/* boundary	*/ 0,
516 				/* lowaddr	*/ BUS_SPACE_MAXADDR,
517 				/* highaddr	*/ BUS_SPACE_MAXADDR,
518 				/* filter	*/ NULL,
519 				/* filterarg	*/ NULL,
520 				/* maxsize	*/ aha->max_ccbs *
521 						   sizeof(struct aha_ccb),
522 				/* nsegments	*/ 1,
523 				/* maxsegsz	*/ BUS_SPACE_MAXSIZE_24BIT,
524 				/* flags	*/ 0,
525 				/* lockfunc	*/ NULL,
526 				/* lockarg	*/ NULL,
527 				&aha->ccb_dmat) != 0) {
528 		goto error_exit;
529         }
530 
531 	aha->init_level++;
532 
533 	/* Allocation for our ccbs */
534 	if (bus_dmamem_alloc(aha->ccb_dmat, (void **)&aha->aha_ccb_array,
535 	    BUS_DMA_NOWAIT, &aha->ccb_dmamap) != 0)
536 		goto error_exit;
537 
538 	aha->init_level++;
539 
540 	/* And permanently map them */
541 	bus_dmamap_load(aha->ccb_dmat, aha->ccb_dmamap, aha->aha_ccb_array,
542 	    aha->max_ccbs * sizeof(struct aha_ccb), ahamapccbs, aha, /*flags*/0);
543 
544 	aha->init_level++;
545 
546 	/* DMA tag for our S/G structures.  We allocate in page sized chunks */
547 	if (bus_dma_tag_create(	/* parent	*/ aha->parent_dmat,
548 				/* alignment	*/ 1,
549 				/* boundary	*/ 0,
550 				/* lowaddr	*/ BUS_SPACE_MAXADDR,
551 				/* highaddr	*/ BUS_SPACE_MAXADDR,
552 				/* filter	*/ NULL,
553 				/* filterarg	*/ NULL,
554 				/* maxsize	*/ PAGE_SIZE,
555 				/* nsegments	*/ 1,
556 				/* maxsegsz	*/ BUS_SPACE_MAXSIZE_24BIT,
557 				/* flags	*/ 0,
558 				/* lockfunc	*/ NULL,
559 				/* lockarg	*/ NULL,
560 				&aha->sg_dmat) != 0)
561 		goto error_exit;
562 
563 	aha->init_level++;
564 
565 	/* Perform initial CCB allocation */
566 	bzero(aha->aha_ccb_array, aha->max_ccbs * sizeof(struct aha_ccb));
567 	ahaallocccbs(aha);
568 
569 	if (aha->num_ccbs == 0) {
570 		device_printf(aha->dev,
571 		    "aha_init - Unable to allocate initial ccbs\n");
572 		goto error_exit;
573 	}
574 
575 	/*
576 	 * Note that we are going and return (to probe)
577 	 */
578 	return (0);
579 
580 error_exit:
581 
582 	return (ENXIO);
583 }
584 
585 int
aha_attach(struct aha_softc * aha)586 aha_attach(struct aha_softc *aha)
587 {
588 	int tagged_dev_openings;
589 	struct cam_devq *devq;
590 
591 	/*
592 	 * We don't do tagged queueing, since the aha cards don't
593 	 * support it.
594 	 */
595 	tagged_dev_openings = 0;
596 
597 	/*
598 	 * Create the device queue for our SIM.
599 	 */
600 	devq = cam_simq_alloc(aha->max_ccbs - 1);
601 	if (devq == NULL)
602 		return (ENOMEM);
603 
604 	/*
605 	 * Construct our SIM entry
606 	 */
607 	aha->sim = cam_sim_alloc(ahaaction, ahapoll, "aha", aha,
608 	    device_get_unit(aha->dev), &aha->lock, 2, tagged_dev_openings,
609 	    devq);
610 	if (aha->sim == NULL) {
611 		cam_simq_free(devq);
612 		return (ENOMEM);
613 	}
614 	mtx_lock(&aha->lock);
615 	if (xpt_bus_register(aha->sim, aha->dev, 0) != CAM_SUCCESS) {
616 		cam_sim_free(aha->sim, /*free_devq*/TRUE);
617 		mtx_unlock(&aha->lock);
618 		return (ENXIO);
619 	}
620 	if (xpt_create_path(&aha->path, /*periph*/NULL, cam_sim_path(aha->sim),
621 	    CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
622 		xpt_bus_deregister(cam_sim_path(aha->sim));
623 		cam_sim_free(aha->sim, /*free_devq*/TRUE);
624 		mtx_unlock(&aha->lock);
625 		return (ENXIO);
626 	}
627 	mtx_unlock(&aha->lock);
628 
629 	return (0);
630 }
631 
632 static void
ahaallocccbs(struct aha_softc * aha)633 ahaallocccbs(struct aha_softc *aha)
634 {
635 	struct aha_ccb *next_ccb;
636 	struct sg_map_node *sg_map;
637 	bus_addr_t physaddr;
638 	aha_sg_t *segs;
639 	int newcount;
640 	int i;
641 
642 	next_ccb = &aha->aha_ccb_array[aha->num_ccbs];
643 
644 	sg_map = malloc(sizeof(*sg_map), M_DEVBUF, M_NOWAIT);
645 
646 	if (sg_map == NULL)
647 		return;
648 
649 	/* Allocate S/G space for the next batch of CCBS */
650 	if (bus_dmamem_alloc(aha->sg_dmat, (void **)&sg_map->sg_vaddr,
651 	    BUS_DMA_NOWAIT, &sg_map->sg_dmamap) != 0) {
652 		free(sg_map, M_DEVBUF);
653 		return;
654 	}
655 
656 	SLIST_INSERT_HEAD(&aha->sg_maps, sg_map, links);
657 
658 	bus_dmamap_load(aha->sg_dmat, sg_map->sg_dmamap, sg_map->sg_vaddr,
659 	    PAGE_SIZE, ahamapsgs, aha, /*flags*/0);
660 
661 	segs = sg_map->sg_vaddr;
662 	physaddr = sg_map->sg_physaddr;
663 
664 	newcount = (PAGE_SIZE / (AHA_NSEG * sizeof(aha_sg_t)));
665 	for (i = 0; aha->num_ccbs < aha->max_ccbs && i < newcount; i++) {
666 		int error;
667 
668 		next_ccb->sg_list = segs;
669 		next_ccb->sg_list_phys = physaddr;
670 		next_ccb->flags = ACCB_FREE;
671 		callout_init_mtx(&next_ccb->timer, &aha->lock, 0);
672 		error = bus_dmamap_create(aha->buffer_dmat, /*flags*/0,
673 		    &next_ccb->dmamap);
674 		if (error != 0)
675 			break;
676 		SLIST_INSERT_HEAD(&aha->free_aha_ccbs, next_ccb, links);
677 		segs += AHA_NSEG;
678 		physaddr += (AHA_NSEG * sizeof(aha_sg_t));
679 		next_ccb++;
680 		aha->num_ccbs++;
681 	}
682 
683 	/* Reserve a CCB for error recovery */
684 	if (aha->recovery_accb == NULL) {
685 		aha->recovery_accb = SLIST_FIRST(&aha->free_aha_ccbs);
686 		SLIST_REMOVE_HEAD(&aha->free_aha_ccbs, links);
687 	}
688 }
689 
690 static __inline void
ahafreeccb(struct aha_softc * aha,struct aha_ccb * accb)691 ahafreeccb(struct aha_softc *aha, struct aha_ccb *accb)
692 {
693 
694 	if (!dumping)
695 		mtx_assert(&aha->lock, MA_OWNED);
696 	if ((accb->flags & ACCB_ACTIVE) != 0)
697 		LIST_REMOVE(&accb->ccb->ccb_h, sim_links.le);
698 	if (aha->resource_shortage != 0
699 	    && (accb->ccb->ccb_h.status & CAM_RELEASE_SIMQ) == 0) {
700 		accb->ccb->ccb_h.status |= CAM_RELEASE_SIMQ;
701 		aha->resource_shortage = FALSE;
702 	}
703 	accb->flags = ACCB_FREE;
704 	SLIST_INSERT_HEAD(&aha->free_aha_ccbs, accb, links);
705 	aha->active_ccbs--;
706 }
707 
708 static struct aha_ccb*
ahagetccb(struct aha_softc * aha)709 ahagetccb(struct aha_softc *aha)
710 {
711 	struct	aha_ccb* accb;
712 
713 	if (!dumping)
714 		mtx_assert(&aha->lock, MA_OWNED);
715 	if ((accb = SLIST_FIRST(&aha->free_aha_ccbs)) != NULL) {
716 		SLIST_REMOVE_HEAD(&aha->free_aha_ccbs, links);
717 		aha->active_ccbs++;
718 	} else if (aha->num_ccbs < aha->max_ccbs) {
719 		ahaallocccbs(aha);
720 		accb = SLIST_FIRST(&aha->free_aha_ccbs);
721 		if (accb == NULL)
722 			device_printf(aha->dev, "Can't malloc ACCB\n");
723 		else {
724 			SLIST_REMOVE_HEAD(&aha->free_aha_ccbs, links);
725 			aha->active_ccbs++;
726 		}
727 	}
728 
729 	return (accb);
730 }
731 
732 static void
ahaaction(struct cam_sim * sim,union ccb * ccb)733 ahaaction(struct cam_sim *sim, union ccb *ccb)
734 {
735 	struct	aha_softc *aha;
736 
737 	CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE, ("ahaaction\n"));
738 
739 	aha = (struct aha_softc *)cam_sim_softc(sim);
740 	mtx_assert(&aha->lock, MA_OWNED);
741 
742 	switch (ccb->ccb_h.func_code) {
743 	/* Common cases first */
744 	case XPT_SCSI_IO:	/* Execute the requested I/O operation */
745 	case XPT_RESET_DEV:	/* Bus Device Reset the specified SCSI device */	{
746 		struct	aha_ccb	*accb;
747 		struct	aha_hccb *hccb;
748 
749 		/*
750 		 * Get an accb to use.
751 		 */
752 		if ((accb = ahagetccb(aha)) == NULL) {
753 			aha->resource_shortage = TRUE;
754 			xpt_freeze_simq(aha->sim, /*count*/1);
755 			ccb->ccb_h.status = CAM_REQUEUE_REQ;
756 			xpt_done(ccb);
757 			return;
758 		}
759 		hccb = &accb->hccb;
760 
761 		/*
762 		 * So we can find the ACCB when an abort is requested
763 		 */
764 		accb->ccb = ccb;
765 		ccb->ccb_h.ccb_accb_ptr = accb;
766 		ccb->ccb_h.ccb_aha_ptr = aha;
767 
768 		/*
769 		 * Put all the arguments for the xfer in the accb
770 		 */
771 		hccb->target = ccb->ccb_h.target_id;
772 		hccb->lun = ccb->ccb_h.target_lun;
773 		hccb->ahastat = 0;
774 		hccb->sdstat = 0;
775 
776 		if (ccb->ccb_h.func_code == XPT_SCSI_IO) {
777 			struct ccb_scsiio *csio;
778 			struct ccb_hdr *ccbh;
779 			int error;
780 
781 			csio = &ccb->csio;
782 			ccbh = &csio->ccb_h;
783 			hccb->opcode = aha->ccb_ccb_opcode;
784 			hccb->datain = (ccb->ccb_h.flags & CAM_DIR_IN) != 0;
785 			hccb->dataout = (ccb->ccb_h.flags & CAM_DIR_OUT) != 0;
786 			hccb->cmd_len = csio->cdb_len;
787 			if (hccb->cmd_len > sizeof(hccb->scsi_cdb)) {
788 				ccb->ccb_h.status = CAM_REQ_INVALID;
789 				ahafreeccb(aha, accb);
790 				xpt_done(ccb);
791 				return;
792 			}
793 			hccb->sense_len = csio->sense_len;
794 			if ((ccbh->flags & CAM_CDB_POINTER) != 0) {
795 				if ((ccbh->flags & CAM_CDB_PHYS) == 0) {
796 					bcopy(csio->cdb_io.cdb_ptr,
797 					      hccb->scsi_cdb, hccb->cmd_len);
798 				} else {
799 					/* I guess I could map it in... */
800 					ccbh->status = CAM_REQ_INVALID;
801 					ahafreeccb(aha, accb);
802 					xpt_done(ccb);
803 					return;
804 				}
805 			} else {
806 				bcopy(csio->cdb_io.cdb_bytes,
807 				      hccb->scsi_cdb, hccb->cmd_len);
808 			}
809 			/*
810 			 * If we have any data to send with this command,
811 			 * map it into bus space.
812 			 */
813 
814 			error = bus_dmamap_load_ccb(
815 			    aha->buffer_dmat,
816 			    accb->dmamap,
817 			    ccb,
818 			    ahaexecuteccb,
819 			    accb,
820 			    /*flags*/0);
821 			if (error == EINPROGRESS) {
822 				/*
823 				 * So as to maintain ordering, freeze the
824 				 * controller queue until our mapping is
825 				 * returned.
826 				 */
827 				xpt_freeze_simq(aha->sim, 1);
828 				csio->ccb_h.status |= CAM_RELEASE_SIMQ;
829 			}
830 		} else {
831 			hccb->opcode = INITIATOR_BUS_DEV_RESET;
832 			/* No data transfer */
833 			hccb->datain = TRUE;
834 			hccb->dataout = TRUE;
835 			hccb->cmd_len = 0;
836 			hccb->sense_len = 0;
837 			ahaexecuteccb(accb, NULL, 0, 0);
838 		}
839 		break;
840 	}
841 	case XPT_EN_LUN:		/* Enable LUN as a target */
842 	case XPT_TARGET_IO:		/* Execute target I/O request */
843 	case XPT_ACCEPT_TARGET_IO:	/* Accept Host Target Mode CDB */
844 	case XPT_CONT_TARGET_IO:	/* Continue Host Target I/O Connection*/
845 	case XPT_ABORT:			/* Abort the specified CCB */
846 		/* XXX Implement */
847 		ccb->ccb_h.status = CAM_REQ_INVALID;
848 		xpt_done(ccb);
849 		break;
850 	case XPT_SET_TRAN_SETTINGS:
851 		/* XXX Implement */
852 		ccb->ccb_h.status = CAM_PROVIDE_FAIL;
853 		xpt_done(ccb);
854 		break;
855 	case XPT_GET_TRAN_SETTINGS:
856 	/* Get default/user set transfer settings for the target */
857 	{
858 		struct	ccb_trans_settings *cts = &ccb->cts;
859 		u_int	target_mask = 0x01 << ccb->ccb_h.target_id;
860 		struct ccb_trans_settings_scsi *scsi =
861 		    &cts->proto_specific.scsi;
862 		struct ccb_trans_settings_spi *spi =
863 		    &cts->xport_specific.spi;
864 
865 		cts->protocol = PROTO_SCSI;
866 		cts->protocol_version = SCSI_REV_2;
867 		cts->transport = XPORT_SPI;
868 		cts->transport_version = 2;
869 		if (cts->type == CTS_TYPE_USER_SETTINGS) {
870 			spi->flags = 0;
871 			if ((aha->disc_permitted & target_mask) != 0)
872 				spi->flags |= CTS_SPI_FLAGS_DISC_ENB;
873 			spi->bus_width = MSG_EXT_WDTR_BUS_8_BIT;
874 			if ((aha->sync_permitted & target_mask) != 0) {
875 				if (aha->boardid >= BOARD_1542CF)
876 					spi->sync_period = 25;
877 				else
878 					spi->sync_period = 50;
879 			} else {
880 				spi->sync_period = 0;
881 			}
882 
883 			if (spi->sync_period != 0)
884 				spi->sync_offset = 15;
885 
886 			spi->valid = CTS_SPI_VALID_SYNC_RATE
887 				   | CTS_SPI_VALID_SYNC_OFFSET
888 				   | CTS_SPI_VALID_BUS_WIDTH
889 				   | CTS_SPI_VALID_DISC;
890 			scsi->valid = CTS_SCSI_VALID_TQ;
891 		} else {
892 			ahafetchtransinfo(aha, cts);
893 		}
894 
895 		ccb->ccb_h.status = CAM_REQ_CMP;
896 		xpt_done(ccb);
897 		break;
898 	}
899 	case XPT_CALC_GEOMETRY:
900 	{
901 		struct	  ccb_calc_geometry *ccg;
902 		uint32_t size_mb;
903 		uint32_t secs_per_cylinder;
904 
905 		ccg = &ccb->ccg;
906 		size_mb = ccg->volume_size
907 			/ ((1024L * 1024L) / ccg->block_size);
908 		if (size_mb >= 1024 && (aha->extended_trans != 0)) {
909 			if (size_mb >= 2048) {
910 				ccg->heads = 255;
911 				ccg->secs_per_track = 63;
912 			} else {
913 				ccg->heads = 128;
914 				ccg->secs_per_track = 32;
915 			}
916 		} else {
917 			ccg->heads = 64;
918 			ccg->secs_per_track = 32;
919 		}
920 		secs_per_cylinder = ccg->heads * ccg->secs_per_track;
921 		ccg->cylinders = ccg->volume_size / secs_per_cylinder;
922 		ccb->ccb_h.status = CAM_REQ_CMP;
923 		xpt_done(ccb);
924 		break;
925 	}
926 	case XPT_RESET_BUS:		/* Reset the specified SCSI bus */
927 		ahareset(aha, /*hardreset*/TRUE);
928 		ccb->ccb_h.status = CAM_REQ_CMP;
929 		xpt_done(ccb);
930 		break;
931 	case XPT_TERM_IO:		/* Terminate the I/O process */
932 		/* XXX Implement */
933 		ccb->ccb_h.status = CAM_REQ_INVALID;
934 		xpt_done(ccb);
935 		break;
936 	case XPT_PATH_INQ:		/* Path routing inquiry */
937 	{
938 		struct ccb_pathinq *cpi = &ccb->cpi;
939 
940 		cpi->version_num = 1; /* XXX??? */
941 		cpi->hba_inquiry = PI_SDTR_ABLE;
942 		cpi->target_sprt = 0;
943 		cpi->hba_misc = 0;
944 		cpi->hba_eng_cnt = 0;
945 		cpi->max_target = 7;
946 		cpi->max_lun = 7;
947 		cpi->initiator_id = aha->scsi_id;
948 		cpi->bus_id = cam_sim_bus(sim);
949 		cpi->base_transfer_speed = 3300;
950 		strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
951 		strncpy(cpi->hba_vid, "Adaptec", HBA_IDLEN);
952 		strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN);
953 		cpi->unit_number = cam_sim_unit(sim);
954                 cpi->transport = XPORT_SPI;
955                 cpi->transport_version = 2;
956                 cpi->protocol = PROTO_SCSI;
957                 cpi->protocol_version = SCSI_REV_2;
958 		cpi->ccb_h.status = CAM_REQ_CMP;
959 		xpt_done(ccb);
960 		break;
961 	}
962 	default:
963 		ccb->ccb_h.status = CAM_REQ_INVALID;
964 		xpt_done(ccb);
965 		break;
966 	}
967 }
968 
969 static void
ahaexecuteccb(void * arg,bus_dma_segment_t * dm_segs,int nseg,int error)970 ahaexecuteccb(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
971 {
972 	struct	 aha_ccb *accb;
973 	union	 ccb *ccb;
974 	struct	 aha_softc *aha;
975 	uint32_t paddr;
976 
977 	accb = (struct aha_ccb *)arg;
978 	ccb = accb->ccb;
979 	aha = (struct aha_softc *)ccb->ccb_h.ccb_aha_ptr;
980 
981 	if (error != 0) {
982 		if (error != EFBIG)
983 			device_printf(aha->dev,
984 			    "Unexepected error 0x%x returned from "
985 			    "bus_dmamap_load\n", error);
986 		if (ccb->ccb_h.status == CAM_REQ_INPROG) {
987 			xpt_freeze_devq(ccb->ccb_h.path, /*count*/1);
988 			ccb->ccb_h.status = CAM_REQ_TOO_BIG|CAM_DEV_QFRZN;
989 		}
990 		ahafreeccb(aha, accb);
991 		xpt_done(ccb);
992 		return;
993 	}
994 
995 	if (nseg != 0) {
996 		aha_sg_t *sg;
997 		bus_dma_segment_t *end_seg;
998 		bus_dmasync_op_t op;
999 
1000 		end_seg = dm_segs + nseg;
1001 
1002 		/* Copy the segments into our SG list */
1003 		sg = accb->sg_list;
1004 		while (dm_segs < end_seg) {
1005 			ahautoa24(dm_segs->ds_len, sg->len);
1006 			ahautoa24(dm_segs->ds_addr, sg->addr);
1007 			sg++;
1008 			dm_segs++;
1009 		}
1010 
1011 		if (nseg > 1) {
1012 			accb->hccb.opcode = aha->ccb_sg_opcode;
1013 			ahautoa24((sizeof(aha_sg_t) * nseg),
1014 			    accb->hccb.data_len);
1015 			ahautoa24(accb->sg_list_phys, accb->hccb.data_addr);
1016 		} else {
1017 			bcopy(accb->sg_list->len, accb->hccb.data_len, 3);
1018 			bcopy(accb->sg_list->addr, accb->hccb.data_addr, 3);
1019 		}
1020 
1021 		if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN)
1022 			op = BUS_DMASYNC_PREREAD;
1023 		else
1024 			op = BUS_DMASYNC_PREWRITE;
1025 
1026 		bus_dmamap_sync(aha->buffer_dmat, accb->dmamap, op);
1027 
1028 	} else {
1029 		accb->hccb.opcode = INITIATOR_CCB;
1030 		ahautoa24(0, accb->hccb.data_len);
1031 		ahautoa24(0, accb->hccb.data_addr);
1032 	}
1033 
1034 	/*
1035 	 * Last time we need to check if this CCB needs to
1036 	 * be aborted.
1037 	 */
1038 	if (ccb->ccb_h.status != CAM_REQ_INPROG) {
1039 		if (nseg != 0)
1040 			bus_dmamap_unload(aha->buffer_dmat, accb->dmamap);
1041 		ahafreeccb(aha, accb);
1042 		xpt_done(ccb);
1043 		return;
1044 	}
1045 
1046 	accb->flags = ACCB_ACTIVE;
1047 	ccb->ccb_h.status |= CAM_SIM_QUEUED;
1048 	LIST_INSERT_HEAD(&aha->pending_ccbs, &ccb->ccb_h, sim_links.le);
1049 
1050 	callout_reset_sbt(&accb->timer, SBT_1MS * ccb->ccb_h.timeout, 0,
1051 	    ahatimeout, accb, 0);
1052 
1053 	/* Tell the adapter about this command */
1054 	if (aha->cur_outbox->action_code != AMBO_FREE) {
1055 		/*
1056 		 * We should never encounter a busy mailbox.
1057 		 * If we do, warn the user, and treat it as
1058 		 * a resource shortage.  If the controller is
1059 		 * hung, one of the pending transactions will
1060 		 * timeout causing us to start recovery operations.
1061 		 */
1062 		device_printf(aha->dev,
1063 		    "Encountered busy mailbox with %d out of %d "
1064 		    "commands active!!!", aha->active_ccbs, aha->max_ccbs);
1065 		callout_stop(&accb->timer);
1066 		if (nseg != 0)
1067 			bus_dmamap_unload(aha->buffer_dmat, accb->dmamap);
1068 		ahafreeccb(aha, accb);
1069 		aha->resource_shortage = TRUE;
1070 		xpt_freeze_simq(aha->sim, /*count*/1);
1071 		ccb->ccb_h.status = CAM_REQUEUE_REQ;
1072 		xpt_done(ccb);
1073 		return;
1074 	}
1075 	paddr = ahaccbvtop(aha, accb);
1076 	ahautoa24(paddr, aha->cur_outbox->ccb_addr);
1077 	aha->cur_outbox->action_code = AMBO_START;
1078 	aha_outb(aha, COMMAND_REG, AOP_START_MBOX);
1079 
1080 	ahanextoutbox(aha);
1081 }
1082 
1083 void
aha_intr(void * arg)1084 aha_intr(void *arg)
1085 {
1086 	struct	aha_softc *aha;
1087 
1088 	aha = arg;
1089 	mtx_lock(&aha->lock);
1090 	aha_intr_locked(aha);
1091 	mtx_unlock(&aha->lock);
1092 }
1093 
1094 void
aha_intr_locked(struct aha_softc * aha)1095 aha_intr_locked(struct aha_softc *aha)
1096 {
1097 	u_int	intstat;
1098 	uint32_t paddr;
1099 
1100 	while (((intstat = aha_inb(aha, INTSTAT_REG)) & INTR_PENDING) != 0) {
1101 		if ((intstat & CMD_COMPLETE) != 0) {
1102 			aha->latched_status = aha_inb(aha, STATUS_REG);
1103 			aha->command_cmp = TRUE;
1104 		}
1105 
1106 		aha_outb(aha, CONTROL_REG, RESET_INTR);
1107 
1108 		if ((intstat & IMB_LOADED) != 0) {
1109 			while (aha->cur_inbox->comp_code != AMBI_FREE) {
1110 				paddr = aha_a24tou(aha->cur_inbox->ccb_addr);
1111 				ahadone(aha, ahaccbptov(aha, paddr),
1112 				    aha->cur_inbox->comp_code);
1113 				aha->cur_inbox->comp_code = AMBI_FREE;
1114 				ahanextinbox(aha);
1115 			}
1116 		}
1117 
1118 		if ((intstat & SCSI_BUS_RESET) != 0) {
1119 			ahareset(aha, /*hardreset*/FALSE);
1120 		}
1121 	}
1122 }
1123 
1124 static void
ahadone(struct aha_softc * aha,struct aha_ccb * accb,aha_mbi_comp_code_t comp_code)1125 ahadone(struct aha_softc *aha, struct aha_ccb *accb, aha_mbi_comp_code_t comp_code)
1126 {
1127 	union  ccb	  *ccb;
1128 	struct ccb_scsiio *csio;
1129 
1130 	ccb = accb->ccb;
1131 	csio = &accb->ccb->csio;
1132 
1133 	if ((accb->flags & ACCB_ACTIVE) == 0) {
1134 		device_printf(aha->dev,
1135 		    "ahadone - Attempt to free non-active ACCB %p\n",
1136 		    (void *)accb);
1137 		return;
1138 	}
1139 
1140 	if ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) {
1141 		bus_dmasync_op_t op;
1142 
1143 		if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN)
1144 			op = BUS_DMASYNC_POSTREAD;
1145 		else
1146 			op = BUS_DMASYNC_POSTWRITE;
1147 		bus_dmamap_sync(aha->buffer_dmat, accb->dmamap, op);
1148 		bus_dmamap_unload(aha->buffer_dmat, accb->dmamap);
1149 	}
1150 
1151 	if (accb == aha->recovery_accb) {
1152 		/*
1153 		 * The recovery ACCB does not have a CCB associated
1154 		 * with it, so short circuit the normal error handling.
1155 		 * We now traverse our list of pending CCBs and process
1156 		 * any that were terminated by the recovery CCBs action.
1157 		 * We also reinstate timeouts for all remaining, pending,
1158 		 * CCBs.
1159 		 */
1160 		struct cam_path *path;
1161 		struct ccb_hdr *ccb_h;
1162 		cam_status error;
1163 
1164 		/* Notify all clients that a BDR occured */
1165 		error = xpt_create_path(&path, /*periph*/NULL,
1166 		    cam_sim_path(aha->sim), accb->hccb.target,
1167 		    CAM_LUN_WILDCARD);
1168 
1169 		if (error == CAM_REQ_CMP) {
1170 			xpt_async(AC_SENT_BDR, path, NULL);
1171 			xpt_free_path(path);
1172 		}
1173 
1174 		ccb_h = LIST_FIRST(&aha->pending_ccbs);
1175 		while (ccb_h != NULL) {
1176 			struct aha_ccb *pending_accb;
1177 
1178 			pending_accb = (struct aha_ccb *)ccb_h->ccb_accb_ptr;
1179 			if (pending_accb->hccb.target == accb->hccb.target) {
1180 				pending_accb->hccb.ahastat = AHASTAT_HA_BDR;
1181 				ccb_h = LIST_NEXT(ccb_h, sim_links.le);
1182 				ahadone(aha, pending_accb, AMBI_ERROR);
1183 			} else {
1184 				callout_reset_sbt(&pending_accb->timer,
1185 				    SBT_1MS * ccb_h->timeout, 0, ahatimeout,
1186 				    pending_accb, 0);
1187 				ccb_h = LIST_NEXT(ccb_h, sim_links.le);
1188 			}
1189 		}
1190 		device_printf(aha->dev, "No longer in timeout\n");
1191 		return;
1192 	}
1193 
1194 	callout_stop(&accb->timer);
1195 
1196 	switch (comp_code) {
1197 	case AMBI_FREE:
1198 		device_printf(aha->dev,
1199 		    "ahadone - CCB completed with free status!\n");
1200 		break;
1201 	case AMBI_NOT_FOUND:
1202 		device_printf(aha->dev,
1203 		    "ahadone - CCB Abort failed to find CCB\n");
1204 		break;
1205 	case AMBI_ABORT:
1206 	case AMBI_ERROR:
1207 		/* An error occured */
1208 		if (accb->hccb.opcode < INITIATOR_CCB_WRESID)
1209 			csio->resid = 0;
1210 		else
1211 			csio->resid = aha_a24tou(accb->hccb.data_len);
1212 		switch(accb->hccb.ahastat) {
1213 		case AHASTAT_DATARUN_ERROR:
1214 		{
1215 			if (csio->resid <= 0) {
1216 				csio->ccb_h.status = CAM_DATA_RUN_ERR;
1217 				break;
1218 			}
1219 			/* FALLTHROUGH */
1220 		}
1221 		case AHASTAT_NOERROR:
1222 			csio->scsi_status = accb->hccb.sdstat;
1223 			csio->ccb_h.status |= CAM_SCSI_STATUS_ERROR;
1224 			switch(csio->scsi_status) {
1225 			case SCSI_STATUS_CHECK_COND:
1226 			case SCSI_STATUS_CMD_TERMINATED:
1227 				csio->ccb_h.status |= CAM_AUTOSNS_VALID;
1228 				/*
1229 				 * The aha writes the sense data at different
1230 				 * offsets based on the scsi cmd len
1231 				 */
1232 				bcopy((caddr_t) &accb->hccb.scsi_cdb +
1233 				    accb->hccb.cmd_len,
1234 				    (caddr_t) &csio->sense_data,
1235 				    accb->hccb.sense_len);
1236 				break;
1237 			default:
1238 				break;
1239 			case SCSI_STATUS_OK:
1240 				csio->ccb_h.status = CAM_REQ_CMP;
1241 				break;
1242 			}
1243 			break;
1244 		case AHASTAT_SELTIMEOUT:
1245 			csio->ccb_h.status = CAM_SEL_TIMEOUT;
1246 			break;
1247 		case AHASTAT_UNEXPECTED_BUSFREE:
1248 			csio->ccb_h.status = CAM_UNEXP_BUSFREE;
1249 			break;
1250 		case AHASTAT_INVALID_PHASE:
1251 			csio->ccb_h.status = CAM_SEQUENCE_FAIL;
1252 			break;
1253 		case AHASTAT_INVALID_ACTION_CODE:
1254 			panic("%s: Inavlid Action code", aha_name(aha));
1255 			break;
1256 		case AHASTAT_INVALID_OPCODE:
1257 			if (accb->hccb.opcode < INITIATOR_CCB_WRESID)
1258 				panic("%s: Invalid CCB Opcode %x hccb = %p",
1259 				    aha_name(aha), accb->hccb.opcode,
1260 				    &accb->hccb);
1261 			device_printf(aha->dev,
1262 			    "AHA-1540A compensation failed\n");
1263 			xpt_freeze_devq(ccb->ccb_h.path, /*count*/1);
1264 			csio->ccb_h.status = CAM_REQUEUE_REQ;
1265 			break;
1266 		case AHASTAT_LINKED_CCB_LUN_MISMATCH:
1267 			/* We don't even support linked commands... */
1268 			panic("%s: Linked CCB Lun Mismatch", aha_name(aha));
1269 			break;
1270 		case AHASTAT_INVALID_CCB_OR_SG_PARAM:
1271 			panic("%s: Invalid CCB or SG list", aha_name(aha));
1272 			break;
1273 		case AHASTAT_HA_SCSI_BUS_RESET:
1274 			if ((csio->ccb_h.status & CAM_STATUS_MASK)
1275 			    != CAM_CMD_TIMEOUT)
1276 				csio->ccb_h.status = CAM_SCSI_BUS_RESET;
1277 			break;
1278 		case AHASTAT_HA_BDR:
1279 			if ((accb->flags & ACCB_DEVICE_RESET) == 0)
1280 				csio->ccb_h.status = CAM_BDR_SENT;
1281 			else
1282 				csio->ccb_h.status = CAM_CMD_TIMEOUT;
1283 			break;
1284 		}
1285 		if (csio->ccb_h.status != CAM_REQ_CMP) {
1286 			xpt_freeze_devq(csio->ccb_h.path, /*count*/1);
1287 			csio->ccb_h.status |= CAM_DEV_QFRZN;
1288 		}
1289 		if ((accb->flags & ACCB_RELEASE_SIMQ) != 0)
1290 			ccb->ccb_h.status |= CAM_RELEASE_SIMQ;
1291 		ahafreeccb(aha, accb);
1292 		xpt_done(ccb);
1293 		break;
1294 	case AMBI_OK:
1295 		/* All completed without incident */
1296 		/* XXX DO WE NEED TO COPY SENSE BYTES HERE???? XXX */
1297 		/* I don't think so since it works???? */
1298 		ccb->ccb_h.status |= CAM_REQ_CMP;
1299 		if ((accb->flags & ACCB_RELEASE_SIMQ) != 0)
1300 			ccb->ccb_h.status |= CAM_RELEASE_SIMQ;
1301 		ahafreeccb(aha, accb);
1302 		xpt_done(ccb);
1303 		break;
1304 	}
1305 }
1306 
1307 static int
ahareset(struct aha_softc * aha,int hard_reset)1308 ahareset(struct aha_softc* aha, int hard_reset)
1309 {
1310 	struct	 ccb_hdr *ccb_h;
1311 	u_int	 status;
1312 	u_int	 timeout;
1313 	uint8_t reset_type;
1314 
1315 	if (hard_reset != 0)
1316 		reset_type = HARD_RESET;
1317 	else
1318 		reset_type = SOFT_RESET;
1319 	aha_outb(aha, CONTROL_REG, reset_type);
1320 
1321 	/* Wait 5sec. for Diagnostic start */
1322 	timeout = 5 * 10000;
1323 	while (--timeout) {
1324 		status = aha_inb(aha, STATUS_REG);
1325 		if ((status & DIAG_ACTIVE) != 0)
1326 			break;
1327 		DELAY(100);
1328 	}
1329 	if (timeout == 0) {
1330 		PRVERB((aha->dev, "ahareset - Diagnostic Active failed to "
1331 		    "assert. status = %#x\n", status));
1332 		return (ETIMEDOUT);
1333 	}
1334 
1335 	/* Wait 10sec. for Diagnostic end */
1336 	timeout = 10 * 10000;
1337 	while (--timeout) {
1338 		status = aha_inb(aha, STATUS_REG);
1339 		if ((status & DIAG_ACTIVE) == 0)
1340 			break;
1341 		DELAY(100);
1342 	}
1343 	if (timeout == 0) {
1344 		panic("%s: ahareset - Diagnostic Active failed to drop. "
1345 		    "status = 0x%x\n", aha_name(aha), status);
1346 		return (ETIMEDOUT);
1347 	}
1348 
1349 	/* Wait for the host adapter to become ready or report a failure */
1350 	timeout = 10000;
1351 	while (--timeout) {
1352 		status = aha_inb(aha, STATUS_REG);
1353 		if ((status & (DIAG_FAIL|HA_READY|DATAIN_REG_READY)) != 0)
1354 			break;
1355 		DELAY(100);
1356 	}
1357 	if (timeout == 0) {
1358 		device_printf(aha->dev, "ahareset - Host adapter failed to "
1359 		    "come ready. status = 0x%x\n", status);
1360 		return (ETIMEDOUT);
1361 	}
1362 
1363 	/* If the diagnostics failed, tell the user */
1364 	if ((status & DIAG_FAIL) != 0
1365 	 || (status & HA_READY) == 0) {
1366 		device_printf(aha->dev, "ahareset - Adapter failed diag\n");
1367 
1368 		if ((status & DATAIN_REG_READY) != 0)
1369 			device_printf(aha->dev, "ahareset - Host Adapter "
1370 			    "Error code = 0x%x\n", aha_inb(aha, DATAIN_REG));
1371 		return (ENXIO);
1372 	}
1373 
1374 	/* If we've attached to the XPT, tell it about the event */
1375 	if (aha->path != NULL)
1376 		xpt_async(AC_BUS_RESET, aha->path, NULL);
1377 
1378 	/*
1379 	 * Perform completion processing for all outstanding CCBs.
1380 	 */
1381 	while ((ccb_h = LIST_FIRST(&aha->pending_ccbs)) != NULL) {
1382 		struct aha_ccb *pending_accb;
1383 
1384 		pending_accb = (struct aha_ccb *)ccb_h->ccb_accb_ptr;
1385 		pending_accb->hccb.ahastat = AHASTAT_HA_SCSI_BUS_RESET;
1386 		ahadone(aha, pending_accb, AMBI_ERROR);
1387 	}
1388 
1389 	/* If we've allocated mailboxes, initialize them */
1390 	/* Must be done after we've aborted our queue, or aha_cmd fails */
1391 	if (aha->init_level > 4)
1392 		ahainitmboxes(aha);
1393 
1394 	return (0);
1395 }
1396 
1397 /*
1398  * Send a command to the adapter.
1399  */
1400 int
aha_cmd(struct aha_softc * aha,aha_op_t opcode,uint8_t * params,u_int param_len,uint8_t * reply_data,u_int reply_len,u_int cmd_timeout)1401 aha_cmd(struct aha_softc *aha, aha_op_t opcode, uint8_t *params,
1402 	u_int param_len, uint8_t *reply_data, u_int reply_len,
1403 	u_int cmd_timeout)
1404 {
1405 	u_int	timeout;
1406 	u_int	status;
1407 	u_int	saved_status;
1408 	u_int	intstat;
1409 	u_int	reply_buf_size;
1410 	int	cmd_complete;
1411 	int	error;
1412 
1413 	/* No data returned to start */
1414 	reply_buf_size = reply_len;
1415 	reply_len = 0;
1416 	intstat = 0;
1417 	cmd_complete = 0;
1418 	saved_status = 0;
1419 	error = 0;
1420 
1421 	/*
1422 	 * All commands except for the "start mailbox" and the "enable
1423 	 * outgoing mailbox read interrupt" commands cannot be issued
1424 	 * while there are pending transactions.  Freeze our SIMQ
1425 	 * and wait for all completions to occur if necessary.
1426 	 */
1427 	timeout = 10000;
1428 	while (LIST_FIRST(&aha->pending_ccbs) != NULL && --timeout) {
1429 		/* Fire the interrupt handler in case interrupts are blocked */
1430 		aha_intr(aha);
1431 		DELAY(10);
1432 	}
1433 
1434 	if (timeout == 0) {
1435 		device_printf(aha->dev,
1436 		    "aha_cmd: Timeout waiting for adapter idle\n");
1437 		return (ETIMEDOUT);
1438 	}
1439 	aha->command_cmp = 0;
1440 	/*
1441 	 * Wait up to 10 sec. for the adapter to become
1442 	 * ready to accept commands.
1443 	 */
1444 	timeout = 100000;
1445 	while (--timeout) {
1446 		status = aha_inb(aha, STATUS_REG);
1447 		if ((status & HA_READY) != 0 && (status & CMD_REG_BUSY) == 0)
1448 			break;
1449 		/*
1450 		 * Throw away any pending data which may be
1451 		 * left over from earlier commands that we
1452 		 * timedout on.
1453 		 */
1454 		if ((status & DATAIN_REG_READY) != 0)
1455 			(void)aha_inb(aha, DATAIN_REG);
1456 		DELAY(100);
1457 	}
1458 	if (timeout == 0) {
1459 		device_printf(aha->dev, "aha_cmd: Timeout waiting for adapter"
1460 		    " ready, status = 0x%x\n", status);
1461 		return (ETIMEDOUT);
1462 	}
1463 
1464 	/*
1465 	 * Send the opcode followed by any necessary parameter bytes.
1466 	 */
1467 	aha_outb(aha, COMMAND_REG, opcode);
1468 
1469 	/*
1470 	 * Wait for up to 1sec to get the parameter list sent
1471 	 */
1472 	timeout = 10000;
1473 	while (param_len && --timeout) {
1474 		DELAY(100);
1475 		status = aha_inb(aha, STATUS_REG);
1476 		intstat = aha_inb(aha, INTSTAT_REG);
1477 
1478 		if ((intstat & (INTR_PENDING|CMD_COMPLETE))
1479 		 == (INTR_PENDING|CMD_COMPLETE)) {
1480 			saved_status = status;
1481 			cmd_complete = 1;
1482 			break;
1483 		}
1484 
1485 		if (aha->command_cmp != 0) {
1486 			saved_status = aha->latched_status;
1487 			cmd_complete = 1;
1488 			break;
1489 		}
1490 		if ((status & DATAIN_REG_READY) != 0)
1491 			break;
1492 		if ((status & CMD_REG_BUSY) == 0) {
1493 			aha_outb(aha, COMMAND_REG, *params++);
1494 			param_len--;
1495 			timeout = 10000;
1496 		}
1497 	}
1498 	if (timeout == 0) {
1499 		device_printf(aha->dev, "aha_cmd: Timeout sending parameters, "
1500 		    "status = 0x%x\n", status);
1501 		error = ETIMEDOUT;
1502 	}
1503 
1504 	/*
1505 	 * For all other commands, we wait for any output data
1506 	 * and the final comand completion interrupt.
1507 	 */
1508 	while (cmd_complete == 0 && --cmd_timeout) {
1509 
1510 		status = aha_inb(aha, STATUS_REG);
1511 		intstat = aha_inb(aha, INTSTAT_REG);
1512 
1513 		if (aha->command_cmp != 0) {
1514 			cmd_complete = 1;
1515 			saved_status = aha->latched_status;
1516 		} else if ((intstat & (INTR_PENDING|CMD_COMPLETE))
1517 			== (INTR_PENDING|CMD_COMPLETE)) {
1518 			/*
1519 			 * Our poll (in case interrupts are blocked)
1520 			 * saw the CMD_COMPLETE interrupt.
1521 			 */
1522 			cmd_complete = 1;
1523 			saved_status = status;
1524 		}
1525 		if ((status & DATAIN_REG_READY) != 0) {
1526 			uint8_t data;
1527 
1528 			data = aha_inb(aha, DATAIN_REG);
1529 			if (reply_len < reply_buf_size) {
1530 				*reply_data++ = data;
1531 			} else {
1532 				device_printf(aha->dev,
1533 				    "aha_cmd - Discarded reply data "
1534 				    "byte for opcode 0x%x\n", opcode);
1535 			}
1536 			/*
1537 			 * Reset timeout to ensure at least a second
1538 			 * between response bytes.
1539 			 */
1540 			cmd_timeout = MAX(cmd_timeout, 10000);
1541 			reply_len++;
1542 		}
1543 		DELAY(100);
1544 	}
1545 	if (cmd_timeout == 0) {
1546 		device_printf(aha->dev, "aha_cmd: Timeout: status = 0x%x, "
1547 		    "intstat = 0x%x, reply_len = %d\n", status, intstat,
1548 		    reply_len);
1549 		return (ETIMEDOUT);
1550 	}
1551 
1552 	/*
1553 	 * Clear any pending interrupts.  Block interrupts so our
1554 	 * interrupt handler is not re-entered.
1555 	 */
1556 	aha_intr(aha);
1557 
1558 	if (error != 0)
1559 		return (error);
1560 
1561 	/*
1562 	 * If the command was rejected by the controller, tell the caller.
1563 	 */
1564 	if ((saved_status & CMD_INVALID) != 0) {
1565 		PRVERB((aha->dev, "Invalid Command 0x%x\n", opcode));
1566 		/*
1567 		 * Some early adapters may not recover properly from
1568 		 * an invalid command.  If it appears that the controller
1569 		 * has wedged (i.e. status was not cleared by our interrupt
1570 		 * reset above), perform a soft reset.
1571       		 */
1572 		DELAY(1000);
1573 		status = aha_inb(aha, STATUS_REG);
1574 		if ((status & (CMD_INVALID|STATUS_REG_RSVD|DATAIN_REG_READY|
1575 			      CMD_REG_BUSY|DIAG_FAIL|DIAG_ACTIVE)) != 0
1576 		 || (status & (HA_READY|INIT_REQUIRED))
1577 		  != (HA_READY|INIT_REQUIRED))
1578 			ahareset(aha, /*hard_reset*/FALSE);
1579 		return (EINVAL);
1580 	}
1581 
1582 	if (param_len > 0) {
1583 		/* The controller did not accept the full argument list */
1584 		PRVERB((aha->dev, "Controller did not accept full argument "
1585 		    "list (%d > 0)\n", param_len));
1586 	 	return (E2BIG);
1587 	}
1588 
1589 	if (reply_len != reply_buf_size) {
1590 		/* Too much or too little data received */
1591 		PRVERB((aha->dev, "data received mismatch (%d != %d)\n",
1592 		    reply_len, reply_buf_size));
1593 		return (EMSGSIZE);
1594 	}
1595 
1596 	/* We were successful */
1597 	return (0);
1598 }
1599 
1600 static int
ahainitmboxes(struct aha_softc * aha)1601 ahainitmboxes(struct aha_softc *aha)
1602 {
1603 	int error;
1604 	init_24b_mbox_params_t init_mbox;
1605 
1606 	bzero(aha->in_boxes, sizeof(aha_mbox_in_t) * aha->num_boxes);
1607 	bzero(aha->out_boxes, sizeof(aha_mbox_out_t) * aha->num_boxes);
1608 	aha->cur_inbox = aha->in_boxes;
1609 	aha->last_inbox = aha->in_boxes + aha->num_boxes - 1;
1610 	aha->cur_outbox = aha->out_boxes;
1611 	aha->last_outbox = aha->out_boxes + aha->num_boxes - 1;
1612 
1613 	/* Tell the adapter about them */
1614 	init_mbox.num_mboxes = aha->num_boxes;
1615 	ahautoa24(aha->mailbox_physbase, init_mbox.base_addr);
1616 	error = aha_cmd(aha, AOP_INITIALIZE_MBOX, (uint8_t *)&init_mbox,
1617 	    /*parmlen*/sizeof(init_mbox), /*reply_buf*/NULL,
1618 	    /*reply_len*/0, DEFAULT_CMD_TIMEOUT);
1619 
1620 	if (error != 0)
1621 		printf("ahainitmboxes: Initialization command failed\n");
1622 	return (error);
1623 }
1624 
1625 /*
1626  * Update the XPT's idea of the negotiated transfer
1627  * parameters for a particular target.
1628  */
1629 static void
ahafetchtransinfo(struct aha_softc * aha,struct ccb_trans_settings * cts)1630 ahafetchtransinfo(struct aha_softc *aha, struct ccb_trans_settings* cts)
1631 {
1632 	setup_data_t	setup_info;
1633 	u_int		target;
1634 	u_int		targ_offset;
1635 	u_int		sync_period;
1636 	int		error;
1637 	uint8_t	param;
1638 	targ_syncinfo_t	sync_info;
1639 	struct ccb_trans_settings_spi *spi = &cts->xport_specific.spi;
1640 
1641 	target = cts->ccb_h.target_id;
1642 	targ_offset = (target & 0x7);
1643 
1644 	/*
1645 	 * Inquire Setup Information.  This command retreives
1646 	 * the sync info for older models.
1647 	 */
1648 	param = sizeof(setup_info);
1649 	error = aha_cmd(aha, AOP_INQUIRE_SETUP_INFO, &param, /*paramlen*/1,
1650 	    (uint8_t*)&setup_info, sizeof(setup_info), DEFAULT_CMD_TIMEOUT);
1651 
1652 	if (error != 0) {
1653 		device_printf(aha->dev,
1654 		    "ahafetchtransinfo - Inquire Setup Info Failed %d\n",
1655 		    error);
1656 		return;
1657 	}
1658 
1659 	sync_info = setup_info.syncinfo[targ_offset];
1660 
1661 	if (sync_info.sync == 0)
1662 		spi->sync_offset = 0;
1663 	else
1664 		spi->sync_offset = sync_info.offset;
1665 
1666 	spi->bus_width = MSG_EXT_WDTR_BUS_8_BIT;
1667 
1668 	if (aha->boardid >= BOARD_1542CF)
1669 		sync_period = 1000;
1670 	else
1671 		sync_period = 2000;
1672 	sync_period += 500 * sync_info.period;
1673 
1674 	/* Convert ns value to standard SCSI sync rate */
1675 	if (spi->sync_offset != 0)
1676 		spi->sync_period = scsi_calc_syncparam(sync_period);
1677 	else
1678 		spi->sync_period = 0;
1679 
1680 	spi->valid = CTS_SPI_VALID_SYNC_RATE
1681 		   | CTS_SPI_VALID_SYNC_OFFSET
1682 		   | CTS_SPI_VALID_BUS_WIDTH;
1683         xpt_async(AC_TRANSFER_NEG, cts->ccb_h.path, cts);
1684 }
1685 
1686 static void
ahamapmboxes(void * arg,bus_dma_segment_t * segs,int nseg,int error)1687 ahamapmboxes(void *arg, bus_dma_segment_t *segs, int nseg, int error)
1688 {
1689 	struct aha_softc* aha;
1690 
1691 	aha = (struct aha_softc*)arg;
1692 	aha->mailbox_physbase = segs->ds_addr;
1693 }
1694 
1695 static void
ahamapccbs(void * arg,bus_dma_segment_t * segs,int nseg,int error)1696 ahamapccbs(void *arg, bus_dma_segment_t *segs, int nseg, int error)
1697 {
1698 	struct aha_softc* aha;
1699 
1700 	aha = (struct aha_softc*)arg;
1701 	aha->aha_ccb_physbase = segs->ds_addr;
1702 }
1703 
1704 static void
ahamapsgs(void * arg,bus_dma_segment_t * segs,int nseg,int error)1705 ahamapsgs(void *arg, bus_dma_segment_t *segs, int nseg, int error)
1706 {
1707 
1708 	struct aha_softc* aha;
1709 
1710 	aha = (struct aha_softc*)arg;
1711 	SLIST_FIRST(&aha->sg_maps)->sg_physaddr = segs->ds_addr;
1712 }
1713 
1714 static void
ahapoll(struct cam_sim * sim)1715 ahapoll(struct cam_sim *sim)
1716 {
1717 	aha_intr_locked(cam_sim_softc(sim));
1718 }
1719 
1720 static void
ahatimeout(void * arg)1721 ahatimeout(void *arg)
1722 {
1723 	struct aha_ccb	*accb;
1724 	union  ccb	*ccb;
1725 	struct aha_softc *aha;
1726 	uint32_t	paddr;
1727 	struct ccb_hdr *ccb_h;
1728 
1729 	accb = (struct aha_ccb *)arg;
1730 	ccb = accb->ccb;
1731 	aha = (struct aha_softc *)ccb->ccb_h.ccb_aha_ptr;
1732 	mtx_assert(&aha->lock, MA_OWNED);
1733 	xpt_print_path(ccb->ccb_h.path);
1734 	printf("CCB %p - timed out\n", (void *)accb);
1735 
1736 	if ((accb->flags & ACCB_ACTIVE) == 0) {
1737 		xpt_print_path(ccb->ccb_h.path);
1738 		printf("CCB %p - timed out CCB already completed\n",
1739 		    (void *)accb);
1740 		return;
1741 	}
1742 
1743 	/*
1744 	 * In order to simplify the recovery process, we ask the XPT
1745 	 * layer to halt the queue of new transactions and we traverse
1746 	 * the list of pending CCBs and remove their timeouts. This
1747 	 * means that the driver attempts to clear only one error
1748 	 * condition at a time.  In general, timeouts that occur
1749 	 * close together are related anyway, so there is no benefit
1750 	 * in attempting to handle errors in parrallel.  Timeouts will
1751 	 * be reinstated when the recovery process ends.
1752 	 */
1753 	if ((accb->flags & ACCB_DEVICE_RESET) == 0) {
1754 		if ((accb->flags & ACCB_RELEASE_SIMQ) == 0) {
1755 			xpt_freeze_simq(aha->sim, /*count*/1);
1756 			accb->flags |= ACCB_RELEASE_SIMQ;
1757 		}
1758 
1759 		ccb_h = LIST_FIRST(&aha->pending_ccbs);
1760 		while (ccb_h != NULL) {
1761 			struct aha_ccb *pending_accb;
1762 
1763 			pending_accb = (struct aha_ccb *)ccb_h->ccb_accb_ptr;
1764 			callout_stop(&pending_accb->timer);
1765 			ccb_h = LIST_NEXT(ccb_h, sim_links.le);
1766 		}
1767 	}
1768 
1769 	if ((accb->flags & ACCB_DEVICE_RESET) != 0
1770 	 || aha->cur_outbox->action_code != AMBO_FREE) {
1771 		/*
1772 		 * Try a full host adapter/SCSI bus reset.
1773 		 * We do this only if we have already attempted
1774 		 * to clear the condition with a BDR, or we cannot
1775 		 * attempt a BDR for lack of mailbox resources.
1776 		 */
1777 		ccb->ccb_h.status = CAM_CMD_TIMEOUT;
1778 		ahareset(aha, /*hardreset*/TRUE);
1779 		device_printf(aha->dev, "No longer in timeout\n");
1780 	} else {
1781 		/*
1782 		 * Send a Bus Device Reset message:
1783 		 * The target that is holding up the bus may not
1784 		 * be the same as the one that triggered this timeout
1785 		 * (different commands have different timeout lengths),
1786 		 * but we have no way of determining this from our
1787 		 * timeout handler.  Our strategy here is to queue a
1788 		 * BDR message to the target of the timed out command.
1789 		 * If this fails, we'll get another timeout 2 seconds
1790 		 * later which will attempt a bus reset.
1791 		 */
1792 		accb->flags |= ACCB_DEVICE_RESET;
1793 		callout_reset(&accb->timer, 2 * hz, ahatimeout, accb);
1794 		aha->recovery_accb->hccb.opcode = INITIATOR_BUS_DEV_RESET;
1795 
1796 		/* No Data Transfer */
1797 		aha->recovery_accb->hccb.datain = TRUE;
1798 		aha->recovery_accb->hccb.dataout = TRUE;
1799 		aha->recovery_accb->hccb.ahastat = 0;
1800 		aha->recovery_accb->hccb.sdstat = 0;
1801 		aha->recovery_accb->hccb.target = ccb->ccb_h.target_id;
1802 
1803 		/* Tell the adapter about this command */
1804 		paddr = ahaccbvtop(aha, aha->recovery_accb);
1805 		ahautoa24(paddr, aha->cur_outbox->ccb_addr);
1806 		aha->cur_outbox->action_code = AMBO_START;
1807 		aha_outb(aha, COMMAND_REG, AOP_START_MBOX);
1808 		ahanextoutbox(aha);
1809 	}
1810 }
1811 
1812 int
aha_detach(struct aha_softc * aha)1813 aha_detach(struct aha_softc *aha)
1814 {
1815 	mtx_lock(&aha->lock);
1816 	xpt_async(AC_LOST_DEVICE, aha->path, NULL);
1817 	xpt_free_path(aha->path);
1818 	xpt_bus_deregister(cam_sim_path(aha->sim));
1819 	cam_sim_free(aha->sim, /*free_devq*/TRUE);
1820 	mtx_unlock(&aha->lock);
1821 	/* XXX: Drain all timers? */
1822 	return (0);
1823 }
1824 MODULE_DEPEND(aha, cam, 1, 1, 1);
1825