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