The cam_sim structure was being deallocated unconditionally by device
[dragonfly.git] / sys / dev / disk / ahb / ahb.c
1 /*
2  * CAM SCSI device driver for the Adaptec 174X SCSI Host adapter
3  *
4  * Copyright (c) 1998 Justin T. Gibbs
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice immediately at the beginning of the file, without modification,
12  *    this list of conditions, and the following disclaimer.
13  * 2. The name of the author may not be used to endorse or promote products
14  *    derived from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
20  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  *
28  * $FreeBSD: src/sys/dev/ahb/ahb.c,v 1.18.2.3 2001/03/05 13:08:55 obrien Exp $
29  * $DragonFly: src/sys/dev/disk/ahb/ahb.c,v 1.5 2004/03/15 01:10:38 dillon Exp $
30  */
31
32 #include <sys/param.h>
33 #include <sys/systm.h>
34 #include <sys/kernel.h>
35 #include <sys/malloc.h>
36 #include <sys/module.h>
37 #include <sys/bus.h>
38
39 #include <machine/bus_pio.h>
40 #include <machine/bus.h>
41 #include <machine/clock.h>
42 #include <machine/resource.h>
43 #include <sys/rman.h>
44
45 #include <bus/cam/cam.h>
46 #include <bus/cam/cam_ccb.h>
47 #include <bus/cam/cam_sim.h>
48 #include <bus/cam/cam_xpt_sim.h>
49 #include <bus/cam/cam_debug.h>
50
51 #include <bus/cam/scsi/scsi_message.h>
52
53 #include <bus/eisa/eisaconf.h>
54
55 #include "ahbreg.h"
56
57 #define ccb_ecb_ptr spriv_ptr0
58 #define ccb_ahb_ptr spriv_ptr1
59
60 #define ahb_inb(ahb, port)                              \
61         bus_space_read_1((ahb)->tag, (ahb)->bsh, port)
62
63 #define ahb_inl(ahb, port)                              \
64         bus_space_read_4((ahb)->tag, (ahb)->bsh, port)
65
66 #define ahb_outb(ahb, port, value)                      \
67         bus_space_write_1((ahb)->tag, (ahb)->bsh, port, value)
68
69 #define ahb_outl(ahb, port, value)                      \
70         bus_space_write_4((ahb)->tag, (ahb)->bsh, port, value)
71
72 static const char               *ahbmatch(eisa_id_t type);
73 static struct ahb_softc         *ahballoc(u_long unit, struct resource *res);
74 static void                      ahbfree(struct ahb_softc *ahb);
75 static int                       ahbreset(struct ahb_softc *ahb);
76 static void                      ahbmapecbs(void *arg, bus_dma_segment_t *segs,
77                                             int nseg, int error);
78 static int                       ahbxptattach(struct ahb_softc *ahb);
79 static void                      ahbhandleimmed(struct ahb_softc *ahb,
80                                                 u_int32_t mbox, u_int intstat);
81 static void                      ahbcalcresid(struct ahb_softc *ahb,
82                                               struct ecb *ecb, union ccb *ccb);
83 static __inline void             ahbdone(struct ahb_softc *ahb, u_int32_t mbox,
84                                          u_int intstat);
85 static void                      ahbintr(void *arg);
86 static bus_dmamap_callback_t     ahbexecuteecb;
87 static void                      ahbaction(struct cam_sim *sim, union ccb *ccb);
88 static void                      ahbpoll(struct cam_sim *sim);
89
90 /* Our timeout handler */
91 static timeout_t ahbtimeout;
92
93 static __inline struct ecb*     ahbecbget(struct ahb_softc *ahb);
94 static __inline void            ahbecbfree(struct ahb_softc* ahb,
95                                            struct ecb* ecb);
96 static __inline u_int32_t       ahbecbvtop(struct ahb_softc *ahb,
97                                            struct ecb *ecb);
98 static __inline struct ecb*     ahbecbptov(struct ahb_softc *ahb,
99                                            u_int32_t ecb_addr);
100 static __inline u_int32_t       ahbstatuspaddr(u_int32_t ecb_paddr);
101 static __inline u_int32_t       ahbsensepaddr(u_int32_t ecb_paddr);
102 static __inline u_int32_t       ahbsgpaddr(u_int32_t ecb_paddr);
103 static __inline void            ahbqueuembox(struct ahb_softc *ahb,
104                                              u_int32_t mboxval,
105                                              u_int attn_code);
106
107 static __inline struct ecb*
108 ahbecbget(struct ahb_softc *ahb)
109 {
110         struct  ecb* ecb;
111         int     s;
112
113         s = splcam();
114         if ((ecb = SLIST_FIRST(&ahb->free_ecbs)) != NULL)
115                 SLIST_REMOVE_HEAD(&ahb->free_ecbs, links);
116         splx(s);
117
118         return (ecb);
119 }
120
121 static __inline void
122 ahbecbfree(struct ahb_softc* ahb, struct ecb* ecb)
123 {
124         int s;
125
126         s = splcam();
127         ecb->state = ECB_FREE;
128         SLIST_INSERT_HEAD(&ahb->free_ecbs, ecb, links);
129         splx(s);
130 }
131
132 static __inline u_int32_t
133 ahbecbvtop(struct ahb_softc *ahb, struct ecb *ecb)
134 {
135         return (ahb->ecb_physbase
136               + (u_int32_t)((caddr_t)ecb - (caddr_t)ahb->ecb_array));
137 }
138
139 static __inline struct ecb*
140 ahbecbptov(struct ahb_softc *ahb, u_int32_t ecb_addr)
141 {
142         return (ahb->ecb_array
143               + ((struct ecb*)ecb_addr - (struct ecb*)ahb->ecb_physbase));
144 }
145
146 static __inline u_int32_t
147 ahbstatuspaddr(u_int32_t ecb_paddr)
148 {
149         return (ecb_paddr + offsetof(struct ecb, status));
150 }
151
152 static __inline u_int32_t
153 ahbsensepaddr(u_int32_t ecb_paddr)
154 {
155         return (ecb_paddr + offsetof(struct ecb, sense));
156 }
157
158 static __inline u_int32_t
159 ahbsgpaddr(u_int32_t ecb_paddr)
160 {
161         return (ecb_paddr + offsetof(struct ecb, sg_list));
162 }
163
164 static __inline void
165 ahbqueuembox(struct ahb_softc *ahb, u_int32_t mboxval, u_int attn_code)
166 {
167         u_int loopmax = 300;
168         while (--loopmax) {
169                 u_int status;
170
171                 status = ahb_inb(ahb, HOSTSTAT);
172                 if ((status & (HOSTSTAT_MBOX_EMPTY|HOSTSTAT_BUSY))
173                    == HOSTSTAT_MBOX_EMPTY)
174                         break;
175                 DELAY(20);
176         }
177         if (loopmax == 0)
178                 panic("ahb%ld: adapter not taking commands\n", ahb->unit);
179
180         ahb_outl(ahb, MBOXOUT0, mboxval);
181         ahb_outb(ahb, ATTN, attn_code);
182 }
183
184 static const char *
185 ahbmatch(eisa_id_t type)
186 {                         
187         switch(type & 0xfffffe00) {
188                 case EISA_DEVICE_ID_ADAPTEC_1740:
189                         return ("Adaptec 174x SCSI host adapter");
190                         break;
191                 default:
192                         break;
193         }
194         return (NULL);
195
196
197 static int
198 ahbprobe(device_t dev)      
199 {       
200         const char *desc;
201         u_int32_t iobase;
202         u_int32_t irq;
203         u_int8_t  intdef;      
204         int shared;
205                 
206         desc = ahbmatch(eisa_get_id(dev));
207         if (!desc)
208             return (ENXIO);
209         device_set_desc(dev, desc);
210
211         iobase = (eisa_get_slot(dev) * EISA_SLOT_SIZE) +
212             AHB_EISA_SLOT_OFFSET;
213                         
214         eisa_add_iospace(dev, iobase, AHB_EISA_IOSIZE, RESVADDR_NONE);
215                 
216         intdef = inb(INTDEF + iobase);
217         switch (intdef & 0x7) {
218         case INT9:  
219             irq = 9;
220             break;
221         case INT10: 
222             irq = 10;
223             break;
224         case INT11:
225             irq = 11;
226             break;
227         case INT12:
228             irq = 12; 
229             break;
230         case INT14:
231             irq = 14;
232             break;
233         case INT15:
234             irq = 15;
235             break;
236         default:
237             printf("Adaptec 174X at slot %d: illegal "
238                    "irq setting %d\n", eisa_get_slot(dev),
239                    (intdef & 0x7));
240             irq = 0;
241             break;
242         }               
243         if (irq == 0)
244             return ENXIO;
245
246         shared = (inb(INTDEF + iobase) & INTLEVEL) ?
247                  EISA_TRIGGER_LEVEL : EISA_TRIGGER_EDGE;
248
249         eisa_add_intr(dev, irq, shared);
250
251         return 0;   
252 }
253
254 static int
255 ahbattach(device_t dev)
256 {
257         /*
258          * find unit and check we have that many defined
259          */
260         struct      ahb_softc *ahb;
261         struct      ecb* next_ecb;
262         struct      resource *io = 0;
263         struct      resource *irq = 0;
264         int         rid;
265         void        *ih;
266
267         rid = 0;
268         io = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid,
269                                 0, ~0, 1, RF_ACTIVE);
270         if (!io) {
271                 device_printf(dev, "No I/O space?!\n");
272                 return ENOMEM;
273         }
274
275         if ((ahb = ahballoc(device_get_unit(dev), io)) == NULL) {
276                 goto error_exit2;
277         }
278
279         if (ahbreset(ahb) != 0)
280                 goto error_exit;
281
282         rid = 0;
283         irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid,
284                                  0, ~0, 1, RF_ACTIVE);
285         if (!irq) {
286                 device_printf(dev, "Can't allocate interrupt\n");
287                 goto error_exit;
288         }
289
290         /*
291          * Create our DMA tags.  These tags define the kinds of device
292          * accessible memory allocations and memory mappings we will 
293          * need to perform during normal operation.
294          */
295         /* DMA tag for mapping buffers into device visible space. */
296         /* XXX Should be a child of the EISA bus dma tag */
297         if (bus_dma_tag_create(/*parent*/NULL, /*alignment*/1, /*boundary*/0,
298                                /*lowaddr*/BUS_SPACE_MAXADDR_32BIT,
299                                /*highaddr*/BUS_SPACE_MAXADDR,
300                                /*filter*/NULL, /*filterarg*/NULL,
301                                /*maxsize*/MAXBSIZE, /*nsegments*/AHB_NSEG,
302                                /*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT,
303                                /*flags*/BUS_DMA_ALLOCNOW,
304                                &ahb->buffer_dmat) != 0)
305                 goto error_exit;
306
307         ahb->init_level++;
308
309         /* DMA tag for our ccb structures and ha inquiry data */
310         if (bus_dma_tag_create(/*parent*/NULL, /*alignment*/1, /*boundary*/0,
311                                /*lowaddr*/BUS_SPACE_MAXADDR_32BIT,
312                                /*highaddr*/BUS_SPACE_MAXADDR,
313                                /*filter*/NULL, /*filterarg*/NULL,
314                                (AHB_NECB * sizeof(struct ecb))
315                                + sizeof(*ahb->ha_inq_data),
316                                /*nsegments*/1,
317                                /*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT,
318                                /*flags*/0, &ahb->ecb_dmat) != 0)
319                 goto error_exit;
320
321         ahb->init_level++;
322
323         /* Allocation for our ccbs */
324         if (bus_dmamem_alloc(ahb->ecb_dmat, (void **)&ahb->ecb_array,
325                              BUS_DMA_NOWAIT, &ahb->ecb_dmamap) != 0)
326                 goto error_exit;
327
328         ahb->ha_inq_data = (struct ha_inquiry_data *)&ahb->ecb_array[AHB_NECB];
329
330         ahb->init_level++;
331
332         /* And permanently map them */
333         bus_dmamap_load(ahb->ecb_dmat, ahb->ecb_dmamap,
334                         ahb->ecb_array, AHB_NSEG * sizeof(struct ecb),
335                         ahbmapecbs, ahb, /*flags*/0);
336
337         ahb->init_level++;
338
339         /* Allocate the buffer dmamaps for each of our ECBs */
340         bzero(ahb->ecb_array, (AHB_NECB * sizeof(struct ecb))
341               + sizeof(*ahb->ha_inq_data));
342         next_ecb = ahb->ecb_array;
343         while (ahb->num_ecbs < AHB_NECB) {
344                 u_int32_t ecb_paddr;
345
346                 if (bus_dmamap_create(ahb->buffer_dmat, /*flags*/0,
347                                       &next_ecb->dmamap))
348                         break;
349                 ecb_paddr = ahbecbvtop(ahb, next_ecb);
350                 next_ecb->hecb.status_ptr = ahbstatuspaddr(ecb_paddr);
351                 next_ecb->hecb.sense_ptr = ahbsensepaddr(ecb_paddr);
352                 ahb->num_ecbs++;
353                 ahbecbfree(ahb, next_ecb);
354                 next_ecb++;
355         }
356
357         if (ahb->num_ecbs == 0)
358                 goto error_exit;
359
360         ahb->init_level++;
361
362         /*
363          * Now that we know we own the resources we need, register
364          * our bus with the XPT.
365          */
366         if (ahbxptattach(ahb))
367                 goto error_exit;
368
369         /* Enable our interrupt */
370         bus_setup_intr(dev, irq, INTR_TYPE_CAM, ahbintr, ahb, &ih);
371         return (0);
372
373 error_exit:
374         /*
375          * The board's IRQ line will not be left enabled
376          * if we can't intialize correctly, so its safe
377          * to release the irq.
378          */
379         ahbfree(ahb);
380 error_exit2:
381         if (io)
382                 bus_release_resource(dev, SYS_RES_IOPORT, 0, io);
383         if (irq)
384                 bus_release_resource(dev, SYS_RES_IRQ, 0, irq);
385         return (-1);
386 }
387
388 static struct ahb_softc *
389 ahballoc(u_long unit, struct resource *res)
390 {
391         struct  ahb_softc *ahb;
392
393         /*
394          * Allocate a storage area for us
395          */
396         ahb = malloc(sizeof(struct ahb_softc), M_DEVBUF, M_WAITOK | M_ZERO);
397         SLIST_INIT(&ahb->free_ecbs);
398         LIST_INIT(&ahb->pending_ccbs);
399         ahb->unit = unit;
400         ahb->tag = rman_get_bustag(res);
401         ahb->bsh = rman_get_bushandle(res);
402         ahb->disc_permitted = ~0;
403         ahb->tags_permitted = ~0;
404
405         return (ahb);
406 }
407
408 static void    
409 ahbfree(struct ahb_softc *ahb)
410 {
411         switch (ahb->init_level) {
412         default:
413         case 4:
414                 bus_dmamap_unload(ahb->ecb_dmat, ahb->ecb_dmamap);
415         case 3:
416                 bus_dmamem_free(ahb->ecb_dmat, ahb->ecb_array,
417                                 ahb->ecb_dmamap);
418                 bus_dmamap_destroy(ahb->ecb_dmat, ahb->ecb_dmamap);
419         case 2:
420                 bus_dma_tag_destroy(ahb->ecb_dmat);
421         case 1:
422                 bus_dma_tag_destroy(ahb->buffer_dmat);
423         case 0:
424         }
425         free(ahb, M_DEVBUF);
426 }
427
428 /*
429  * reset board, If it doesn't respond, return failure
430  */
431 static int
432 ahbreset(struct ahb_softc *ahb)
433 {
434         int     wait = 1000;    /* 1 sec enough? */
435         int     test;
436
437         if ((ahb_inb(ahb, PORTADDR) & PORTADDR_ENHANCED) == 0) {
438                 printf("ahb_reset: Controller not in enhanced mode\n");
439                 return (-1);
440         }
441
442         ahb_outb(ahb, CONTROL, CNTRL_HARD_RST);
443         DELAY(1000);
444         ahb_outb(ahb, CONTROL, 0);
445         while (--wait) {
446                 DELAY(1000);
447                 if ((ahb_inb(ahb, HOSTSTAT) & HOSTSTAT_BUSY) == 0)
448                         break;
449         }
450
451         if (wait == 0) {
452                 printf("ahbreset: No answer from aha1742 board\n");
453                 return (-1);
454         }
455         if ((test = ahb_inb(ahb, MBOXIN0)) != 0) {
456                 printf("ahb_reset: self test failed, val = 0x%x\n", test);
457                 return (-1);
458         }
459         while (ahb_inb(ahb, HOSTSTAT) & HOSTSTAT_INTPEND) {
460                 ahb_outb(ahb, CONTROL, CNTRL_CLRINT);
461                 DELAY(10000);
462         }
463         return (0);
464 }
465
466 static void
467 ahbmapecbs(void *arg, bus_dma_segment_t *segs, int nseg, int error)
468 {
469         struct ahb_softc* ahb;
470
471         ahb = (struct ahb_softc*)arg;
472         ahb->ecb_physbase = segs->ds_addr;
473         /*
474          * Space for adapter inquiry information is on the
475          * tail of the ecb array.
476          */
477         ahb->ha_inq_physbase = ahbecbvtop(ahb, &ahb->ecb_array[AHB_NECB]);
478 }
479
480 static int
481 ahbxptattach(struct ahb_softc *ahb)
482 {
483         struct ecb *ecb;
484         u_int  i;
485
486         /* Remeber who are we on the scsi bus */
487         ahb->scsi_id = ahb_inb(ahb, SCSIDEF) & HSCSIID;
488
489         /* Use extended translation?? */
490         ahb->extended_trans = ahb_inb(ahb, RESV1) & EXTENDED_TRANS;
491
492         /* Fetch adapter inquiry data */
493         ecb = ahbecbget(ahb);   /* Always succeeds - no outstanding commands */
494         ecb->hecb.opcode = ECBOP_READ_HA_INQDATA;
495         ecb->hecb.flag_word1 = FW1_SUPPRESS_URUN_ERR|FW1_ERR_STATUS_BLK_ONLY;
496         ecb->hecb.data_ptr = ahb->ha_inq_physbase;
497         ecb->hecb.data_len = sizeof(struct ha_inquiry_data);
498         ecb->hecb.sense_ptr = 0;
499         ecb->state = ECB_ACTIVE;
500         
501         /* Tell the adapter about this command */
502         ahbqueuembox(ahb, ahbecbvtop(ahb, ecb),
503                      ATTN_STARTECB|ahb->scsi_id);
504
505         /* Poll for interrupt completion */
506         for (i = 1000; ecb->state != ECB_FREE && i != 0; i--) {
507                 ahbintr(ahb);
508                 DELAY(1000);
509         }
510
511         ahb->num_ecbs = MIN(ahb->num_ecbs,
512                             ahb->ha_inq_data->scsi_data.reserved[1]);
513         printf("ahb%ld: %.8s %s SCSI Adapter, FW Rev. %.4s, ID=%d, %d ECBs\n",
514                ahb->unit, ahb->ha_inq_data->scsi_data.product,
515                (ahb->ha_inq_data->scsi_data.flags & 0x4) ? "Differential"
516                                                          : "Single Ended",
517                ahb->ha_inq_data->scsi_data.revision,
518                ahb->scsi_id, ahb->num_ecbs);
519
520         /* Restore sense paddr for future CCB clients */
521         ecb->hecb.sense_ptr = ahbsensepaddr(ahbecbvtop(ahb, ecb));
522
523         ahbecbfree(ahb, ecb);
524
525         /*
526          * Construct our SIM entry
527          */
528         ahb->sim = cam_sim_alloc(ahbaction, ahbpoll, "ahb", ahb, ahb->unit,
529                                  2, ahb->num_ecbs, NULL);
530         if (ahb->sim == NULL)
531                 return (ENOMEM);
532
533         if (xpt_bus_register(ahb->sim, 0) != CAM_SUCCESS) {
534                 cam_sim_free(ahb->sim);
535                 return (ENXIO);
536         }
537         
538         if (xpt_create_path(&ahb->path, /*periph*/NULL,
539                             cam_sim_path(ahb->sim), CAM_TARGET_WILDCARD,
540                             CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
541                 xpt_bus_deregister(cam_sim_path(ahb->sim));
542                 cam_sim_free(ahb->sim);
543                 return (ENXIO);
544         }
545                 
546         /*
547          * Allow the board to generate interrupts.
548          */
549         ahb_outb(ahb, INTDEF, ahb_inb(ahb, INTDEF) | INTEN);
550
551         return (0);
552 }
553
554 static void
555 ahbhandleimmed(struct ahb_softc *ahb, u_int32_t mbox, u_int intstat)
556 {
557         struct ccb_hdr *ccb_h;
558         u_int target_id;
559
560         if (ahb->immed_cmd == 0) {
561                 printf("ahb%ld: Immediate Command complete with no "
562                        " pending command\n", ahb->unit);
563                 return;
564         }
565
566         target_id = intstat & INTSTAT_TARGET_MASK;
567
568         ccb_h = LIST_FIRST(&ahb->pending_ccbs);
569         while (ccb_h != NULL) {
570                 struct ecb *pending_ecb;
571                 union ccb *ccb;
572
573                 pending_ecb = (struct ecb *)ccb_h->ccb_ecb_ptr;
574                 ccb = pending_ecb->ccb;
575                 ccb_h = LIST_NEXT(ccb_h, sim_links.le);
576                 if (ccb->ccb_h.target_id == target_id
577                  || target_id == ahb->scsi_id) {
578                         untimeout(ahbtimeout, pending_ecb,
579                                   ccb->ccb_h.timeout_ch);
580                         LIST_REMOVE(&ccb->ccb_h, sim_links.le);
581                         if ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE)
582                                 bus_dmamap_unload(ahb->buffer_dmat,
583                                                   pending_ecb->dmamap);
584                         if (pending_ecb == ahb->immed_ecb)
585                                 ccb->ccb_h.status =
586                                     CAM_CMD_TIMEOUT|CAM_RELEASE_SIMQ;
587                         else if (target_id == ahb->scsi_id)
588                                 ccb->ccb_h.status = CAM_SCSI_BUS_RESET;
589                         else
590                                 ccb->ccb_h.status = CAM_BDR_SENT;
591                         ahbecbfree(ahb, pending_ecb);
592                         xpt_done(ccb);
593                 } else if (ahb->immed_ecb != NULL) {
594                         /* Re-instate timeout */
595                         ccb->ccb_h.timeout_ch =
596                             timeout(ahbtimeout, (caddr_t)pending_ecb,
597                                     (ccb->ccb_h.timeout * hz) / 1000);
598                 }
599         }
600
601         if (ahb->immed_ecb != NULL) {
602                 ahb->immed_ecb = NULL;
603                 printf("ahb%ld: No longer in timeout\n", ahb->unit);
604         } else if (target_id == ahb->scsi_id)
605                 printf("ahb%ld: SCSI Bus Reset Delivered\n", ahb->unit);
606         else
607                 printf("ahb%ld:  Bus Device Reset Delibered to target %d\n",
608                        ahb->unit, target_id);
609
610         ahb->immed_cmd = 0;
611 }
612
613 static void
614 ahbcalcresid(struct ahb_softc *ahb, struct ecb *ecb, union ccb *ccb)
615 {
616         if (ecb->status.data_overrun != 0) {
617                 /*
618                  * Overrun Condition.  The hardware doesn't
619                  * provide a meaningful byte count in this case
620                  * (the residual is always 0).  Tell the XPT
621                  * layer about the error.
622                  */
623                 ccb->ccb_h.status = CAM_DATA_RUN_ERR;
624         } else {
625                 ccb->csio.resid = ecb->status.resid_count;
626
627                 if ((ecb->hecb.flag_word1 & FW1_SG_ECB) != 0) {
628                         /*
629                          * For S/G transfers, the adapter provides a pointer
630                          * to the address in the last S/G element used and a
631                          * residual for that element.  So, we need to sum up
632                          * the elements that follow it in order to get a real
633                          * residual number.  If we have an overrun, the residual
634                          * reported will be 0 and we already know that all S/G
635                          * segments have been exhausted, so we can skip this
636                          * step.
637                          */
638                         ahb_sg_t *sg;
639                         int       num_sg;
640
641                         num_sg = ecb->hecb.data_len / sizeof(ahb_sg_t);
642
643                         /* Find the S/G the adapter was working on */
644                         for (sg = ecb->sg_list;
645                              num_sg != 0 && sg->addr != ecb->status.resid_addr;
646                              num_sg--, sg++)
647                                 ;
648
649                         /* Skip it */
650                         num_sg--;
651                         sg++;
652
653                         /* Sum the rest */
654                         for (; num_sg != 0; num_sg--, sg++)
655                                 ccb->csio.resid += sg->len;
656                 }
657                 /* Underruns are not errors */
658                 ccb->ccb_h.status = CAM_REQ_CMP;
659         }
660 }
661
662 static void
663 ahbprocesserror(struct ahb_softc *ahb, struct ecb *ecb, union ccb *ccb)
664 {
665         struct hardware_ecb *hecb;
666         struct ecb_status *status;
667
668         hecb = &ecb->hecb;
669         status = &ecb->status;
670         switch (status->ha_status) {
671         case HS_OK:
672                 ccb->csio.scsi_status = status->scsi_status;
673                 if (status->scsi_status != 0) {
674                         ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR;
675                         if (status->sense_stored) {
676                                 ccb->ccb_h.status |= CAM_AUTOSNS_VALID;
677                                 ccb->csio.sense_resid =
678                                     ccb->csio.sense_len - status->sense_len;
679                                 bcopy(&ecb->sense, &ccb->csio.sense_data,
680                                       status->sense_len);
681                         }
682                 }
683                 break;
684         case HS_TARGET_NOT_ASSIGNED:
685                 ccb->ccb_h.status = CAM_PATH_INVALID;
686                 break;
687         case HS_SEL_TIMEOUT:
688                 ccb->ccb_h.status = CAM_SEL_TIMEOUT;
689                 break;
690         case HS_DATA_RUN_ERR:
691                 ahbcalcresid(ahb, ecb, ccb);
692                 break;
693         case HS_UNEXPECTED_BUSFREE:
694                 ccb->ccb_h.status = CAM_UNEXP_BUSFREE;
695                 break;
696         case HS_INVALID_PHASE:
697                 ccb->ccb_h.status = CAM_SEQUENCE_FAIL;
698                 break;
699         case HS_REQUEST_SENSE_FAILED:
700                 ccb->ccb_h.status = CAM_AUTOSENSE_FAIL;
701                 break;
702         case HS_TAG_MSG_REJECTED:
703         {
704                 struct ccb_trans_settings neg; 
705
706                 xpt_print_path(ccb->ccb_h.path);
707                 printf("refuses tagged commands.  Performing "
708                        "non-tagged I/O\n");
709                 neg.flags = 0;
710                 neg.valid = CCB_TRANS_TQ_VALID;
711                 xpt_setup_ccb(&neg.ccb_h, ccb->ccb_h.path, /*priority*/1); 
712                 xpt_async(AC_TRANSFER_NEG, ccb->ccb_h.path, &neg);
713                 ahb->tags_permitted &= ~(0x01 << ccb->ccb_h.target_id);
714                 ccb->ccb_h.status = CAM_MSG_REJECT_REC;
715                 break;
716         }
717         case HS_FIRMWARE_LOAD_REQ:
718         case HS_HARDWARE_ERR:
719                 /*
720                  * Tell the system that the Adapter
721                  * is no longer functional.
722                  */
723                 ccb->ccb_h.status = CAM_NO_HBA;
724                 break;
725         case HS_CMD_ABORTED_HOST:
726         case HS_CMD_ABORTED_ADAPTER:
727         case HS_ATN_TARGET_FAILED:
728         case HS_SCSI_RESET_ADAPTER:
729         case HS_SCSI_RESET_INCOMING:
730                 ccb->ccb_h.status = CAM_SCSI_BUS_RESET;
731                 break;
732         case HS_INVALID_ECB_PARAM:
733                 printf("ahb%ld: opcode 0x%02x, flag_word1 0x%02x, flag_word2 0x%02x\n",
734                         ahb->unit, hecb->opcode, hecb->flag_word1, hecb->flag_word2);   
735                 ccb->ccb_h.status = CAM_SCSI_BUS_RESET;
736                 break;
737         case HS_DUP_TCB_RECEIVED:
738         case HS_INVALID_OPCODE:
739         case HS_INVALID_CMD_LINK:
740         case HS_PROGRAM_CKSUM_ERROR:
741                 panic("ahb%ld: Can't happen host status %x occurred",
742                       ahb->unit, status->ha_status);
743                 break;
744         }
745         if (ccb->ccb_h.status != CAM_REQ_CMP) {
746                 xpt_freeze_devq(ccb->ccb_h.path, /*count*/1);
747                 ccb->ccb_h.status |= CAM_DEV_QFRZN;
748         }
749 }
750
751 static void
752 ahbdone(struct ahb_softc *ahb, u_int32_t mbox, u_int intstat)
753 {
754         struct ecb *ecb;
755         union ccb *ccb;
756
757         ecb = ahbecbptov(ahb, mbox);
758
759         if ((ecb->state & ECB_ACTIVE) == 0)
760                 panic("ecb not active");
761
762         ccb = ecb->ccb;
763
764         if (ccb != NULL) {
765                 untimeout(ahbtimeout, ecb, ccb->ccb_h.timeout_ch);
766                 LIST_REMOVE(&ccb->ccb_h, sim_links.le);
767
768                 if ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) {
769                         bus_dmasync_op_t op;
770
771                         if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN)
772                                 op = BUS_DMASYNC_POSTREAD;
773                         else
774                                 op = BUS_DMASYNC_POSTWRITE;
775                         bus_dmamap_sync(ahb->buffer_dmat, ecb->dmamap, op);
776                         bus_dmamap_unload(ahb->buffer_dmat, ecb->dmamap);
777                 }
778
779                 if ((intstat & INTSTAT_MASK) == INTSTAT_ECB_OK) {
780                         ccb->ccb_h.status = CAM_REQ_CMP;
781                         ccb->csio.resid = 0;
782                 } else {
783                         ahbprocesserror(ahb, ecb, ccb);
784                 }
785                 ahbecbfree(ahb, ecb);
786                 xpt_done(ccb);
787         } else {
788                 /* Non CCB Command */
789                 if ((intstat & INTSTAT_MASK) != INTSTAT_ECB_OK) {
790                         printf("ahb%ld: Command 0%x Failed %x:%x:%x\n",
791                                ahb->unit, ecb->hecb.opcode,
792                                *((u_int16_t*)&ecb->status),
793                                ecb->status.ha_status, ecb->status.resid_count);
794                 }
795                 /* Client owns this ECB and will release it. */
796         }
797 }
798
799 /*
800  * Catch an interrupt from the adaptor
801  */
802 static void
803 ahbintr(void *arg)
804 {
805         struct    ahb_softc *ahb;
806         u_int     intstat;
807         u_int32_t mbox;
808
809         ahb = (struct ahb_softc *)arg;
810
811         while (ahb_inb(ahb, HOSTSTAT) & HOSTSTAT_INTPEND) {
812                 /*
813                  * Fetch information about this interrupt.
814                  */
815                 intstat = ahb_inb(ahb, INTSTAT);
816                 mbox = ahb_inl(ahb, MBOXIN0);
817
818                 /*
819                  * Reset interrupt latch.
820                  */
821                 ahb_outb(ahb, CONTROL, CNTRL_CLRINT);
822
823                 /*
824                  * Process the completed operation
825                  */
826                 switch (intstat & INTSTAT_MASK) {
827                 case INTSTAT_ECB_OK:
828                 case INTSTAT_ECB_CMPWRETRY:
829                 case INTSTAT_ECB_CMPWERR:
830                         ahbdone(ahb, mbox, intstat);
831                         break;
832                 case INTSTAT_AEN_OCCURED:
833                         if ((intstat & INTSTAT_TARGET_MASK) == ahb->scsi_id) {
834                                 /* Bus Reset */
835                                 xpt_print_path(ahb->path);
836                                 switch (mbox) {
837                                 case HS_SCSI_RESET_ADAPTER:
838                                         printf("Host Adapter Initiated "
839                                                "Bus Reset occurred\n");
840                                         break;
841                                 case HS_SCSI_RESET_INCOMING:
842                                         printf("Bus Reset Initiated "
843                                                "by another device occurred\n");
844                                         break;
845                                 }
846                                 /* Notify the XPT */
847                                 xpt_async(AC_BUS_RESET, ahb->path, NULL);
848                                 break;
849                         }
850                         printf("Unsupported initiator selection AEN occured\n");
851                         break;
852                 case INTSTAT_IMMED_OK:
853                 case INTSTAT_IMMED_ERR:
854                         ahbhandleimmed(ahb, mbox, intstat);
855                         break;
856                 case INTSTAT_HW_ERR:
857                         panic("Unrecoverable hardware Error Occurred\n");
858                 }
859         }
860 }
861
862 static void
863 ahbexecuteecb(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
864 {
865         struct    ecb *ecb;
866         union     ccb *ccb;
867         struct    ahb_softc *ahb;
868         u_int32_t ecb_paddr;
869         int       s;
870
871         ecb = (struct ecb *)arg;
872         ccb = ecb->ccb;
873         ahb = (struct ahb_softc *)ccb->ccb_h.ccb_ahb_ptr;
874
875         if (error != 0) {
876                 if (error != EFBIG)
877                         printf("ahb%ld: Unexepected error 0x%x returned from "
878                                "bus_dmamap_load\n", ahb->unit, error);
879                 if (ccb->ccb_h.status == CAM_REQ_INPROG) {
880                         xpt_freeze_devq(ccb->ccb_h.path, /*count*/1);
881                         ccb->ccb_h.status = CAM_REQ_TOO_BIG|CAM_DEV_QFRZN;
882                 }
883                 ahbecbfree(ahb, ecb);
884                 xpt_done(ccb);
885                 return;
886         }
887                 
888         ecb_paddr = ahbecbvtop(ahb, ecb);
889
890         if (nseg != 0) {
891                 ahb_sg_t *sg;
892                 bus_dma_segment_t *end_seg;
893                 bus_dmasync_op_t op;
894
895                 end_seg = dm_segs + nseg;
896
897                 /* Copy the segments into our SG list */
898                 sg = ecb->sg_list;
899                 while (dm_segs < end_seg) {
900                         sg->addr = dm_segs->ds_addr;
901                         sg->len = dm_segs->ds_len;
902                         sg++;
903                         dm_segs++;
904                 }
905
906                 if (nseg > 1) {
907                         ecb->hecb.flag_word1 |= FW1_SG_ECB;
908                         ecb->hecb.data_ptr = ahbsgpaddr(ecb_paddr);
909                         ecb->hecb.data_len = sizeof(ahb_sg_t) * nseg;
910                 } else {
911                         ecb->hecb.data_ptr = ecb->sg_list->addr;
912                         ecb->hecb.data_len = ecb->sg_list->len;
913                 }
914
915                 if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) {
916 /*                      ecb->hecb.flag_word2 |= FW2_DATA_DIR_IN; */
917                         op = BUS_DMASYNC_PREREAD;
918                 } else {
919                         op = BUS_DMASYNC_PREWRITE;
920                 }
921                 /* ecb->hecb.flag_word2 |= FW2_CHECK_DATA_DIR; */
922
923                 bus_dmamap_sync(ahb->buffer_dmat, ecb->dmamap, op);
924
925         } else {
926                 ecb->hecb.data_ptr = 0;
927                 ecb->hecb.data_len = 0;
928         }
929
930         s = splcam();
931
932         /*
933          * Last time we need to check if this CCB needs to
934          * be aborted.
935          */
936         if (ccb->ccb_h.status != CAM_REQ_INPROG) {
937                 if (nseg != 0)
938                         bus_dmamap_unload(ahb->buffer_dmat, ecb->dmamap);
939                 ahbecbfree(ahb, ecb);
940                 xpt_done(ccb);
941                 splx(s);
942                 return;
943         }
944                 
945         ecb->state = ECB_ACTIVE;
946         ccb->ccb_h.status |= CAM_SIM_QUEUED;
947         LIST_INSERT_HEAD(&ahb->pending_ccbs, &ccb->ccb_h, sim_links.le);
948
949         /* Tell the adapter about this command */
950         ahbqueuembox(ahb, ecb_paddr, ATTN_STARTECB|ccb->ccb_h.target_id);
951
952         ccb->ccb_h.timeout_ch = timeout(ahbtimeout, (caddr_t)ecb,
953                                         (ccb->ccb_h.timeout * hz) / 1000);
954         splx(s);
955 }
956
957 static void
958 ahbaction(struct cam_sim *sim, union ccb *ccb)
959 {
960         struct  ahb_softc *ahb;
961
962         CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE, ("ahbaction\n"));
963         
964         ahb = (struct ahb_softc *)cam_sim_softc(sim);
965         
966         switch (ccb->ccb_h.func_code) {
967         /* Common cases first */
968         case XPT_SCSI_IO:       /* Execute the requested I/O operation */
969         {
970                 struct ecb *ecb;
971                 struct hardware_ecb *hecb;
972
973                 /*
974                  * get an ecb to use.
975                  */
976                 if ((ecb = ahbecbget(ahb)) == NULL) {
977                         /* Should never occur */
978                         panic("Failed to get an ecb");
979                 }
980
981                 /*
982                  * So we can find the ECB when an abort is requested
983                  */
984                 ecb->ccb = ccb;
985                 ccb->ccb_h.ccb_ecb_ptr = ecb;
986                 ccb->ccb_h.ccb_ahb_ptr = ahb;
987
988                 /*
989                  * Put all the arguments for the xfer in the ecb
990                  */
991                 hecb = &ecb->hecb;
992                 hecb->opcode = ECBOP_INITIATOR_SCSI_CMD;
993                 hecb->flag_word1 = FW1_AUTO_REQUEST_SENSE
994                                  | FW1_ERR_STATUS_BLK_ONLY;
995                 hecb->flag_word2 = ccb->ccb_h.target_lun
996                                  | FW2_NO_RETRY_ON_BUSY;
997                 if ((ccb->ccb_h.flags & CAM_TAG_ACTION_VALID) != 0) {
998                         hecb->flag_word2 |= FW2_TAG_ENB
999                                          | ((ccb->csio.tag_action & 0x3)
1000                                             << FW2_TAG_TYPE_SHIFT);
1001                 }
1002                 if ((ccb->ccb_h.flags & CAM_DIS_DISCONNECT) != 0)
1003                         hecb->flag_word2 |= FW2_DISABLE_DISC;
1004                 hecb->sense_len = ccb->csio.sense_len;
1005                 hecb->cdb_len = ccb->csio.cdb_len;
1006                 if ((ccb->ccb_h.flags & CAM_CDB_POINTER) != 0) {
1007                         if ((ccb->ccb_h.flags & CAM_CDB_PHYS) == 0) {
1008                                 bcopy(ccb->csio.cdb_io.cdb_ptr,
1009                                       hecb->cdb, hecb->cdb_len);
1010                         } else {
1011                                 /* I guess I could map it in... */
1012                                 ccb->ccb_h.status = CAM_REQ_INVALID;
1013                                 ahbecbfree(ahb, ecb);
1014                                 xpt_done(ccb);
1015                                 return;
1016                         }
1017                 } else {
1018                         bcopy(ccb->csio.cdb_io.cdb_bytes,
1019                               hecb->cdb, hecb->cdb_len);
1020                 }
1021
1022                 /*
1023                  * If we have any data to send with this command,
1024                  * map it into bus space.
1025                  */
1026                 if ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) {
1027                         if ((ccb->ccb_h.flags & CAM_SCATTER_VALID) == 0) {
1028                                 /*
1029                                  * We've been given a pointer
1030                                  * to a single buffer.
1031                                  */
1032                                 if ((ccb->ccb_h.flags & CAM_DATA_PHYS)==0) {
1033                                         int s;
1034                                         int error;
1035
1036                                         s = splsoftvm();
1037                                         error = bus_dmamap_load(
1038                                             ahb->buffer_dmat,
1039                                             ecb->dmamap,
1040                                             ccb->csio.data_ptr,
1041                                             ccb->csio.dxfer_len,
1042                                             ahbexecuteecb,
1043                                             ecb, /*flags*/0);
1044                                         if (error == EINPROGRESS) {
1045                                                 /*
1046                                                  * So as to maintain ordering,
1047                                                  * freeze the controller queue
1048                                                  * until our mapping is
1049                                                  * returned.
1050                                                  */
1051                                                 xpt_freeze_simq(ahb->sim, 1);
1052                                                 ccb->ccb_h.status |=
1053                                                     CAM_RELEASE_SIMQ;
1054                                         }
1055                                         splx(s);
1056                                 } else {
1057                                         struct bus_dma_segment seg; 
1058
1059                                         /* Pointer to physical buffer */
1060                                         seg.ds_addr =
1061                                             (bus_addr_t)ccb->csio.data_ptr;
1062                                         seg.ds_len = ccb->csio.dxfer_len;
1063                                         ahbexecuteecb(ecb, &seg, 1, 0);
1064                                 }
1065                         } else {
1066                                 struct bus_dma_segment *segs;
1067
1068                                 if ((ccb->ccb_h.flags & CAM_DATA_PHYS) != 0)
1069                                         panic("ahbaction - Physical segment "
1070                                               "pointers unsupported");
1071
1072                                 if ((ccb->ccb_h.flags & CAM_SG_LIST_PHYS) == 0)
1073                                         panic("btaction - Virtual segment "
1074                                               "addresses unsupported");
1075
1076                                 /* Just use the segments provided */
1077                                 segs = (struct bus_dma_segment *)
1078                                     ccb->csio.data_ptr;
1079                                 ahbexecuteecb(ecb, segs, ccb->csio.sglist_cnt,
1080                                              0);
1081                         }
1082                 } else {
1083                         ahbexecuteecb(ecb, NULL, 0, 0);
1084                 }
1085                 break;
1086         }
1087         case XPT_EN_LUN:                /* Enable LUN as a target */
1088         case XPT_TARGET_IO:             /* Execute target I/O request */
1089         case XPT_ACCEPT_TARGET_IO:      /* Accept Host Target Mode CDB */
1090         case XPT_CONT_TARGET_IO:        /* Continue Host Target I/O Connection*/
1091         case XPT_ABORT:                 /* Abort the specified CCB */
1092                 /* XXX Implement */
1093                 ccb->ccb_h.status = CAM_REQ_INVALID;
1094                 xpt_done(ccb);
1095                 break;
1096         case XPT_SET_TRAN_SETTINGS:
1097         {
1098                 ccb->ccb_h.status = CAM_FUNC_NOTAVAIL;
1099                 xpt_done(ccb);
1100                 break;
1101         }
1102         case XPT_GET_TRAN_SETTINGS:
1103         /* Get default/user set transfer settings for the target */
1104         {
1105                 struct  ccb_trans_settings *cts;
1106                 u_int   target_mask;
1107
1108                 cts = &ccb->cts;
1109                 target_mask = 0x01 << ccb->ccb_h.target_id;
1110                 if ((cts->flags & CCB_TRANS_USER_SETTINGS) != 0) {
1111                         cts->flags = 0;
1112                         if ((ahb->disc_permitted & target_mask) != 0)
1113                                 cts->flags |= CCB_TRANS_DISC_ENB;
1114                         if ((ahb->tags_permitted & target_mask) != 0)
1115                                 cts->flags |= CCB_TRANS_TAG_ENB;
1116                         cts->bus_width = MSG_EXT_WDTR_BUS_8_BIT;
1117                         cts->sync_period = 25; /* 10MHz */
1118
1119                         if (cts->sync_period != 0)
1120                                 cts->sync_offset = 15;
1121
1122                         cts->valid = CCB_TRANS_SYNC_RATE_VALID
1123                                    | CCB_TRANS_SYNC_OFFSET_VALID
1124                                    | CCB_TRANS_BUS_WIDTH_VALID
1125                                    | CCB_TRANS_DISC_VALID
1126                                    | CCB_TRANS_TQ_VALID;
1127                         ccb->ccb_h.status = CAM_REQ_CMP;
1128                 } else {
1129                         ccb->ccb_h.status = CAM_FUNC_NOTAVAIL;
1130                 }
1131                 xpt_done(ccb);
1132                 break;
1133         }
1134         case XPT_RESET_DEV:     /* Bus Device Reset the specified SCSI device */
1135         {
1136                 int i;
1137                 int s;
1138
1139                 s = splcam();
1140                 ahb->immed_cmd = IMMED_RESET;
1141                 ahbqueuembox(ahb, IMMED_RESET, ATTN_IMMED|ccb->ccb_h.target_id);
1142                 /* Poll for interrupt completion */
1143                 for (i = 1000; ahb->immed_cmd != 0 && i != 0; i--) {
1144                         DELAY(1000);
1145                         ahbintr(cam_sim_softc(sim));
1146                 }
1147                 splx(s);
1148                 break;
1149         }
1150         case XPT_CALC_GEOMETRY:
1151         {
1152                 struct    ccb_calc_geometry *ccg;
1153                 u_int32_t size_mb;
1154                 u_int32_t secs_per_cylinder;
1155
1156                 ccg = &ccb->ccg;
1157                 size_mb = ccg->volume_size
1158                         / ((1024L * 1024L) / ccg->block_size);
1159                 
1160                 if (size_mb > 1024 && (ahb->extended_trans != 0)) {
1161                         ccg->heads = 255;
1162                         ccg->secs_per_track = 63;
1163                 } else {
1164                         ccg->heads = 64;
1165                         ccg->secs_per_track = 32;
1166                 }
1167                 secs_per_cylinder = ccg->heads * ccg->secs_per_track;
1168                 ccg->cylinders = ccg->volume_size / secs_per_cylinder;
1169                 ccb->ccb_h.status = CAM_REQ_CMP;
1170                 xpt_done(ccb);
1171                 break;
1172         }
1173         case XPT_RESET_BUS:             /* Reset the specified SCSI bus */
1174         {
1175                 int i;
1176
1177                 ahb->immed_cmd = IMMED_RESET;
1178                 ahbqueuembox(ahb, IMMED_RESET, ATTN_IMMED|ahb->scsi_id);
1179                 /* Poll for interrupt completion */
1180                 for (i = 1000; ahb->immed_cmd != 0 && i != 0; i--)
1181                         DELAY(1000);
1182                 ccb->ccb_h.status = CAM_REQ_CMP;
1183                 xpt_done(ccb);
1184                 break;
1185         }
1186         case XPT_TERM_IO:               /* Terminate the I/O process */
1187                 /* XXX Implement */
1188                 ccb->ccb_h.status = CAM_REQ_INVALID;
1189                 xpt_done(ccb);
1190                 break;
1191         case XPT_PATH_INQ:              /* Path routing inquiry */
1192         {
1193                 struct ccb_pathinq *cpi = &ccb->cpi;
1194                 
1195                 cpi->version_num = 1; /* XXX??? */
1196                 cpi->hba_inquiry = PI_SDTR_ABLE|PI_TAG_ABLE;
1197                 cpi->target_sprt = 0;
1198                 cpi->hba_misc = 0;
1199                 cpi->hba_eng_cnt = 0;
1200                 cpi->max_target = 7;
1201                 cpi->max_lun = 7;
1202                 cpi->initiator_id = ahb->scsi_id;
1203                 cpi->bus_id = cam_sim_bus(sim);
1204                 cpi->base_transfer_speed = 3300;
1205                 strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
1206                 strncpy(cpi->hba_vid, "Adaptec", HBA_IDLEN);
1207                 strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN);
1208                 cpi->unit_number = cam_sim_unit(sim);
1209                 cpi->ccb_h.status = CAM_REQ_CMP;
1210                 xpt_done(ccb);
1211                 break;
1212         }
1213 #if 0
1214         /* Need these??? */
1215         case XPT_IMMED_NOTIFY:          /* Notify Host Target driver of event */
1216         case XPT_NOTIFY_ACK:            /* Acknowledgement of event */
1217 #endif
1218         default:
1219                 ccb->ccb_h.status = CAM_REQ_INVALID;
1220                 xpt_done(ccb);
1221                 break;
1222         }
1223 }
1224
1225 static void
1226 ahbpoll(struct cam_sim *sim)
1227 {
1228         ahbintr(cam_sim_softc(sim));
1229 }
1230
1231 static void
1232 ahbtimeout(void *arg)
1233 {
1234         struct ecb       *ecb;
1235         union  ccb       *ccb;
1236         struct ahb_softc *ahb;
1237         int               s;
1238
1239         ecb = (struct ecb *)arg;
1240         ccb = ecb->ccb;
1241         ahb = (struct ahb_softc *)ccb->ccb_h.ccb_ahb_ptr;
1242         xpt_print_path(ccb->ccb_h.path);
1243         printf("ECB %p - timed out\n", (void *)ecb);
1244
1245         s = splcam();
1246
1247         if ((ecb->state & ECB_ACTIVE) == 0) {
1248                 xpt_print_path(ccb->ccb_h.path);
1249                 printf("ECB %p - timed out ECB already completed\n",
1250                        (void *)ecb);
1251                 splx(s);
1252                 return;
1253         }
1254         /*
1255          * In order to simplify the recovery process, we ask the XPT
1256          * layer to halt the queue of new transactions and we traverse
1257          * the list of pending CCBs and remove their timeouts. This
1258          * means that the driver attempts to clear only one error
1259          * condition at a time.  In general, timeouts that occur
1260          * close together are related anyway, so there is no benefit
1261          * in attempting to handle errors in parrallel.  Timeouts will
1262          * be reinstated when the recovery process ends.
1263          */
1264         if ((ecb->state & ECB_DEVICE_RESET) == 0) {
1265                 struct ccb_hdr *ccb_h;
1266
1267                 if ((ecb->state & ECB_RELEASE_SIMQ) == 0) {
1268                         xpt_freeze_simq(ahb->sim, /*count*/1);
1269                         ecb->state |= ECB_RELEASE_SIMQ;
1270                 }
1271
1272                 ccb_h = LIST_FIRST(&ahb->pending_ccbs);
1273                 while (ccb_h != NULL) {
1274                         struct ecb *pending_ecb;
1275
1276                         pending_ecb = (struct ecb *)ccb_h->ccb_ecb_ptr;
1277                         untimeout(ahbtimeout, pending_ecb, ccb_h->timeout_ch);
1278                         ccb_h = LIST_NEXT(ccb_h, sim_links.le);
1279                 }
1280
1281                 /* Store for our interrupt handler */
1282                 ahb->immed_ecb = ecb;
1283
1284                 /*    
1285                  * Send a Bus Device Reset message:
1286                  * The target that is holding up the bus may not
1287                  * be the same as the one that triggered this timeout
1288                  * (different commands have different timeout lengths),
1289                  * but we have no way of determining this from our
1290                  * timeout handler.  Our strategy here is to queue a
1291                  * BDR message to the target of the timed out command.
1292                  * If this fails, we'll get another timeout 2 seconds
1293                  * later which will attempt a bus reset.
1294                  */
1295                 xpt_print_path(ccb->ccb_h.path);
1296                 printf("Queuing BDR\n");
1297                 ecb->state |= ECB_DEVICE_RESET;
1298                 ccb->ccb_h.timeout_ch =
1299                     timeout(ahbtimeout, (caddr_t)ecb, 2 * hz);
1300
1301                 ahb->immed_cmd = IMMED_RESET;
1302                 ahbqueuembox(ahb, IMMED_RESET, ATTN_IMMED|ccb->ccb_h.target_id);
1303         } else if ((ecb->state & ECB_SCSIBUS_RESET) != 0) {
1304                 /*
1305                  * Try a SCSI bus reset.  We do this only if we
1306                  * have already attempted to clear the condition with a BDR.
1307                  */
1308                 xpt_print_path(ccb->ccb_h.path);
1309                 printf("Attempting SCSI Bus reset\n");
1310                 ecb->state |= ECB_SCSIBUS_RESET;
1311                 ccb->ccb_h.timeout_ch =
1312                     timeout(ahbtimeout, (caddr_t)ecb, 2 * hz);
1313                 ahb->immed_cmd = IMMED_RESET;
1314                 ahbqueuembox(ahb, IMMED_RESET, ATTN_IMMED|ahb->scsi_id);
1315         } else {
1316                 /* Bring out the hammer... */
1317                 ahbreset(ahb);
1318
1319                 /* Simulate the reset complete interrupt */
1320                 ahbhandleimmed(ahb, 0, ahb->scsi_id|INTSTAT_IMMED_OK);
1321         }
1322
1323         splx(s);
1324 }
1325
1326 static device_method_t ahb_eisa_methods[] = {
1327         /* Device interface */
1328         DEVMETHOD(device_probe,         ahbprobe),
1329         DEVMETHOD(device_attach,        ahbattach),
1330
1331         { 0, 0 }
1332 };
1333
1334 static driver_t ahb_eisa_driver = {
1335         "ahb",
1336         ahb_eisa_methods,
1337         1,                      /* unused */
1338 };
1339
1340 static devclass_t ahb_devclass;
1341
1342 DRIVER_MODULE(ahb, eisa, ahb_eisa_driver, ahb_devclass, 0, 0);