Consolidate usage of MIN/MAX().
[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.3 2003/07/27 01:49:50 hmp 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 <cam/cam.h>
46 #include <cam/cam_ccb.h>
47 #include <cam/cam_sim.h>
48 #include <cam/cam_xpt_sim.h>
49 #include <cam/cam_debug.h>
50
51 #include <cam/scsi/scsi_message.h>
52
53 #include <dev/eisa/eisaconf.h>
54
55 #include <dev/ahb/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_NOWAIT | M_ZERO);
397         if (!ahb) {
398                 printf("ahb%ld: cannot malloc!\n", unit);
399                 return (NULL);
400         }
401         SLIST_INIT(&ahb->free_ecbs);
402         LIST_INIT(&ahb->pending_ccbs);
403         ahb->unit = unit;
404         ahb->tag = rman_get_bustag(res);
405         ahb->bsh = rman_get_bushandle(res);
406         ahb->disc_permitted = ~0;
407         ahb->tags_permitted = ~0;
408
409         return (ahb);
410 }
411
412 static void    
413 ahbfree(struct ahb_softc *ahb)
414 {
415         switch (ahb->init_level) {
416         default:
417         case 4:
418                 bus_dmamap_unload(ahb->ecb_dmat, ahb->ecb_dmamap);
419         case 3:
420                 bus_dmamem_free(ahb->ecb_dmat, ahb->ecb_array,
421                                 ahb->ecb_dmamap);
422                 bus_dmamap_destroy(ahb->ecb_dmat, ahb->ecb_dmamap);
423         case 2:
424                 bus_dma_tag_destroy(ahb->ecb_dmat);
425         case 1:
426                 bus_dma_tag_destroy(ahb->buffer_dmat);
427         case 0:
428         }
429         free(ahb, M_DEVBUF);
430 }
431
432 /*
433  * reset board, If it doesn't respond, return failure
434  */
435 static int
436 ahbreset(struct ahb_softc *ahb)
437 {
438         int     wait = 1000;    /* 1 sec enough? */
439         int     test;
440
441         if ((ahb_inb(ahb, PORTADDR) & PORTADDR_ENHANCED) == 0) {
442                 printf("ahb_reset: Controller not in enhanced mode\n");
443                 return (-1);
444         }
445
446         ahb_outb(ahb, CONTROL, CNTRL_HARD_RST);
447         DELAY(1000);
448         ahb_outb(ahb, CONTROL, 0);
449         while (--wait) {
450                 DELAY(1000);
451                 if ((ahb_inb(ahb, HOSTSTAT) & HOSTSTAT_BUSY) == 0)
452                         break;
453         }
454
455         if (wait == 0) {
456                 printf("ahbreset: No answer from aha1742 board\n");
457                 return (-1);
458         }
459         if ((test = ahb_inb(ahb, MBOXIN0)) != 0) {
460                 printf("ahb_reset: self test failed, val = 0x%x\n", test);
461                 return (-1);
462         }
463         while (ahb_inb(ahb, HOSTSTAT) & HOSTSTAT_INTPEND) {
464                 ahb_outb(ahb, CONTROL, CNTRL_CLRINT);
465                 DELAY(10000);
466         }
467         return (0);
468 }
469
470 static void
471 ahbmapecbs(void *arg, bus_dma_segment_t *segs, int nseg, int error)
472 {
473         struct ahb_softc* ahb;
474
475         ahb = (struct ahb_softc*)arg;
476         ahb->ecb_physbase = segs->ds_addr;
477         /*
478          * Space for adapter inquiry information is on the
479          * tail of the ecb array.
480          */
481         ahb->ha_inq_physbase = ahbecbvtop(ahb, &ahb->ecb_array[AHB_NECB]);
482 }
483
484 static int
485 ahbxptattach(struct ahb_softc *ahb)
486 {
487         struct cam_devq *devq;
488         struct ecb *ecb;
489         u_int  i;
490
491         /* Remeber who are we on the scsi bus */
492         ahb->scsi_id = ahb_inb(ahb, SCSIDEF) & HSCSIID;
493
494         /* Use extended translation?? */
495         ahb->extended_trans = ahb_inb(ahb, RESV1) & EXTENDED_TRANS;
496
497         /* Fetch adapter inquiry data */
498         ecb = ahbecbget(ahb);   /* Always succeeds - no outstanding commands */
499         ecb->hecb.opcode = ECBOP_READ_HA_INQDATA;
500         ecb->hecb.flag_word1 = FW1_SUPPRESS_URUN_ERR|FW1_ERR_STATUS_BLK_ONLY;
501         ecb->hecb.data_ptr = ahb->ha_inq_physbase;
502         ecb->hecb.data_len = sizeof(struct ha_inquiry_data);
503         ecb->hecb.sense_ptr = 0;
504         ecb->state = ECB_ACTIVE;
505         
506         /* Tell the adapter about this command */
507         ahbqueuembox(ahb, ahbecbvtop(ahb, ecb),
508                      ATTN_STARTECB|ahb->scsi_id);
509
510         /* Poll for interrupt completion */
511         for (i = 1000; ecb->state != ECB_FREE && i != 0; i--) {
512                 ahbintr(ahb);
513                 DELAY(1000);
514         }
515
516         ahb->num_ecbs = MIN(ahb->num_ecbs,
517                             ahb->ha_inq_data->scsi_data.reserved[1]);
518         printf("ahb%ld: %.8s %s SCSI Adapter, FW Rev. %.4s, ID=%d, %d ECBs\n",
519                ahb->unit, ahb->ha_inq_data->scsi_data.product,
520                (ahb->ha_inq_data->scsi_data.flags & 0x4) ? "Differential"
521                                                          : "Single Ended",
522                ahb->ha_inq_data->scsi_data.revision,
523                ahb->scsi_id, ahb->num_ecbs);
524
525         /* Restore sense paddr for future CCB clients */
526         ecb->hecb.sense_ptr = ahbsensepaddr(ahbecbvtop(ahb, ecb));
527
528         ahbecbfree(ahb, ecb);
529
530         /*
531          * Create the device queue for our SIM.
532          */
533         devq = cam_simq_alloc(ahb->num_ecbs);
534         if (devq == NULL)
535                 return (ENOMEM);
536
537         /*
538          * Construct our SIM entry
539          */
540         ahb->sim = cam_sim_alloc(ahbaction, ahbpoll, "ahb", ahb, ahb->unit,
541                                  2, ahb->num_ecbs, devq);
542         if (ahb->sim == NULL) {
543                 cam_simq_free(devq);
544                 return (ENOMEM);
545         }
546
547         if (xpt_bus_register(ahb->sim, 0) != CAM_SUCCESS) {
548                 cam_sim_free(ahb->sim, /*free_devq*/TRUE);
549                 return (ENXIO);
550         }
551         
552         if (xpt_create_path(&ahb->path, /*periph*/NULL,
553                             cam_sim_path(ahb->sim), CAM_TARGET_WILDCARD,
554                             CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
555                 xpt_bus_deregister(cam_sim_path(ahb->sim));
556                 cam_sim_free(ahb->sim, /*free_devq*/TRUE);
557                 return (ENXIO);
558         }
559                 
560         /*
561          * Allow the board to generate interrupts.
562          */
563         ahb_outb(ahb, INTDEF, ahb_inb(ahb, INTDEF) | INTEN);
564
565         return (0);
566 }
567
568 static void
569 ahbhandleimmed(struct ahb_softc *ahb, u_int32_t mbox, u_int intstat)
570 {
571         struct ccb_hdr *ccb_h;
572         u_int target_id;
573
574         if (ahb->immed_cmd == 0) {
575                 printf("ahb%ld: Immediate Command complete with no "
576                        " pending command\n", ahb->unit);
577                 return;
578         }
579
580         target_id = intstat & INTSTAT_TARGET_MASK;
581
582         ccb_h = LIST_FIRST(&ahb->pending_ccbs);
583         while (ccb_h != NULL) {
584                 struct ecb *pending_ecb;
585                 union ccb *ccb;
586
587                 pending_ecb = (struct ecb *)ccb_h->ccb_ecb_ptr;
588                 ccb = pending_ecb->ccb;
589                 ccb_h = LIST_NEXT(ccb_h, sim_links.le);
590                 if (ccb->ccb_h.target_id == target_id
591                  || target_id == ahb->scsi_id) {
592                         untimeout(ahbtimeout, pending_ecb,
593                                   ccb->ccb_h.timeout_ch);
594                         LIST_REMOVE(&ccb->ccb_h, sim_links.le);
595                         if ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE)
596                                 bus_dmamap_unload(ahb->buffer_dmat,
597                                                   pending_ecb->dmamap);
598                         if (pending_ecb == ahb->immed_ecb)
599                                 ccb->ccb_h.status =
600                                     CAM_CMD_TIMEOUT|CAM_RELEASE_SIMQ;
601                         else if (target_id == ahb->scsi_id)
602                                 ccb->ccb_h.status = CAM_SCSI_BUS_RESET;
603                         else
604                                 ccb->ccb_h.status = CAM_BDR_SENT;
605                         ahbecbfree(ahb, pending_ecb);
606                         xpt_done(ccb);
607                 } else if (ahb->immed_ecb != NULL) {
608                         /* Re-instate timeout */
609                         ccb->ccb_h.timeout_ch =
610                             timeout(ahbtimeout, (caddr_t)pending_ecb,
611                                     (ccb->ccb_h.timeout * hz) / 1000);
612                 }
613         }
614
615         if (ahb->immed_ecb != NULL) {
616                 ahb->immed_ecb = NULL;
617                 printf("ahb%ld: No longer in timeout\n", ahb->unit);
618         } else if (target_id == ahb->scsi_id)
619                 printf("ahb%ld: SCSI Bus Reset Delivered\n", ahb->unit);
620         else
621                 printf("ahb%ld:  Bus Device Reset Delibered to target %d\n",
622                        ahb->unit, target_id);
623
624         ahb->immed_cmd = 0;
625 }
626
627 static void
628 ahbcalcresid(struct ahb_softc *ahb, struct ecb *ecb, union ccb *ccb)
629 {
630         if (ecb->status.data_overrun != 0) {
631                 /*
632                  * Overrun Condition.  The hardware doesn't
633                  * provide a meaningful byte count in this case
634                  * (the residual is always 0).  Tell the XPT
635                  * layer about the error.
636                  */
637                 ccb->ccb_h.status = CAM_DATA_RUN_ERR;
638         } else {
639                 ccb->csio.resid = ecb->status.resid_count;
640
641                 if ((ecb->hecb.flag_word1 & FW1_SG_ECB) != 0) {
642                         /*
643                          * For S/G transfers, the adapter provides a pointer
644                          * to the address in the last S/G element used and a
645                          * residual for that element.  So, we need to sum up
646                          * the elements that follow it in order to get a real
647                          * residual number.  If we have an overrun, the residual
648                          * reported will be 0 and we already know that all S/G
649                          * segments have been exhausted, so we can skip this
650                          * step.
651                          */
652                         ahb_sg_t *sg;
653                         int       num_sg;
654
655                         num_sg = ecb->hecb.data_len / sizeof(ahb_sg_t);
656
657                         /* Find the S/G the adapter was working on */
658                         for (sg = ecb->sg_list;
659                              num_sg != 0 && sg->addr != ecb->status.resid_addr;
660                              num_sg--, sg++)
661                                 ;
662
663                         /* Skip it */
664                         num_sg--;
665                         sg++;
666
667                         /* Sum the rest */
668                         for (; num_sg != 0; num_sg--, sg++)
669                                 ccb->csio.resid += sg->len;
670                 }
671                 /* Underruns are not errors */
672                 ccb->ccb_h.status = CAM_REQ_CMP;
673         }
674 }
675
676 static void
677 ahbprocesserror(struct ahb_softc *ahb, struct ecb *ecb, union ccb *ccb)
678 {
679         struct hardware_ecb *hecb;
680         struct ecb_status *status;
681
682         hecb = &ecb->hecb;
683         status = &ecb->status;
684         switch (status->ha_status) {
685         case HS_OK:
686                 ccb->csio.scsi_status = status->scsi_status;
687                 if (status->scsi_status != 0) {
688                         ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR;
689                         if (status->sense_stored) {
690                                 ccb->ccb_h.status |= CAM_AUTOSNS_VALID;
691                                 ccb->csio.sense_resid =
692                                     ccb->csio.sense_len - status->sense_len;
693                                 bcopy(&ecb->sense, &ccb->csio.sense_data,
694                                       status->sense_len);
695                         }
696                 }
697                 break;
698         case HS_TARGET_NOT_ASSIGNED:
699                 ccb->ccb_h.status = CAM_PATH_INVALID;
700                 break;
701         case HS_SEL_TIMEOUT:
702                 ccb->ccb_h.status = CAM_SEL_TIMEOUT;
703                 break;
704         case HS_DATA_RUN_ERR:
705                 ahbcalcresid(ahb, ecb, ccb);
706                 break;
707         case HS_UNEXPECTED_BUSFREE:
708                 ccb->ccb_h.status = CAM_UNEXP_BUSFREE;
709                 break;
710         case HS_INVALID_PHASE:
711                 ccb->ccb_h.status = CAM_SEQUENCE_FAIL;
712                 break;
713         case HS_REQUEST_SENSE_FAILED:
714                 ccb->ccb_h.status = CAM_AUTOSENSE_FAIL;
715                 break;
716         case HS_TAG_MSG_REJECTED:
717         {
718                 struct ccb_trans_settings neg; 
719
720                 xpt_print_path(ccb->ccb_h.path);
721                 printf("refuses tagged commands.  Performing "
722                        "non-tagged I/O\n");
723                 neg.flags = 0;
724                 neg.valid = CCB_TRANS_TQ_VALID;
725                 xpt_setup_ccb(&neg.ccb_h, ccb->ccb_h.path, /*priority*/1); 
726                 xpt_async(AC_TRANSFER_NEG, ccb->ccb_h.path, &neg);
727                 ahb->tags_permitted &= ~(0x01 << ccb->ccb_h.target_id);
728                 ccb->ccb_h.status = CAM_MSG_REJECT_REC;
729                 break;
730         }
731         case HS_FIRMWARE_LOAD_REQ:
732         case HS_HARDWARE_ERR:
733                 /*
734                  * Tell the system that the Adapter
735                  * is no longer functional.
736                  */
737                 ccb->ccb_h.status = CAM_NO_HBA;
738                 break;
739         case HS_CMD_ABORTED_HOST:
740         case HS_CMD_ABORTED_ADAPTER:
741         case HS_ATN_TARGET_FAILED:
742         case HS_SCSI_RESET_ADAPTER:
743         case HS_SCSI_RESET_INCOMING:
744                 ccb->ccb_h.status = CAM_SCSI_BUS_RESET;
745                 break;
746         case HS_INVALID_ECB_PARAM:
747                 printf("ahb%ld: opcode 0x%02x, flag_word1 0x%02x, flag_word2 0x%02x\n",
748                         ahb->unit, hecb->opcode, hecb->flag_word1, hecb->flag_word2);   
749                 ccb->ccb_h.status = CAM_SCSI_BUS_RESET;
750                 break;
751         case HS_DUP_TCB_RECEIVED:
752         case HS_INVALID_OPCODE:
753         case HS_INVALID_CMD_LINK:
754         case HS_PROGRAM_CKSUM_ERROR:
755                 panic("ahb%ld: Can't happen host status %x occurred",
756                       ahb->unit, status->ha_status);
757                 break;
758         }
759         if (ccb->ccb_h.status != CAM_REQ_CMP) {
760                 xpt_freeze_devq(ccb->ccb_h.path, /*count*/1);
761                 ccb->ccb_h.status |= CAM_DEV_QFRZN;
762         }
763 }
764
765 static void
766 ahbdone(struct ahb_softc *ahb, u_int32_t mbox, u_int intstat)
767 {
768         struct ecb *ecb;
769         union ccb *ccb;
770
771         ecb = ahbecbptov(ahb, mbox);
772
773         if ((ecb->state & ECB_ACTIVE) == 0)
774                 panic("ecb not active");
775
776         ccb = ecb->ccb;
777
778         if (ccb != NULL) {
779                 untimeout(ahbtimeout, ecb, ccb->ccb_h.timeout_ch);
780                 LIST_REMOVE(&ccb->ccb_h, sim_links.le);
781
782                 if ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) {
783                         bus_dmasync_op_t op;
784
785                         if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN)
786                                 op = BUS_DMASYNC_POSTREAD;
787                         else
788                                 op = BUS_DMASYNC_POSTWRITE;
789                         bus_dmamap_sync(ahb->buffer_dmat, ecb->dmamap, op);
790                         bus_dmamap_unload(ahb->buffer_dmat, ecb->dmamap);
791                 }
792
793                 if ((intstat & INTSTAT_MASK) == INTSTAT_ECB_OK) {
794                         ccb->ccb_h.status = CAM_REQ_CMP;
795                         ccb->csio.resid = 0;
796                 } else {
797                         ahbprocesserror(ahb, ecb, ccb);
798                 }
799                 ahbecbfree(ahb, ecb);
800                 xpt_done(ccb);
801         } else {
802                 /* Non CCB Command */
803                 if ((intstat & INTSTAT_MASK) != INTSTAT_ECB_OK) {
804                         printf("ahb%ld: Command 0%x Failed %x:%x:%x\n",
805                                ahb->unit, ecb->hecb.opcode,
806                                *((u_int16_t*)&ecb->status),
807                                ecb->status.ha_status, ecb->status.resid_count);
808                 }
809                 /* Client owns this ECB and will release it. */
810         }
811 }
812
813 /*
814  * Catch an interrupt from the adaptor
815  */
816 static void
817 ahbintr(void *arg)
818 {
819         struct    ahb_softc *ahb;
820         u_int     intstat;
821         u_int32_t mbox;
822
823         ahb = (struct ahb_softc *)arg;
824
825         while (ahb_inb(ahb, HOSTSTAT) & HOSTSTAT_INTPEND) {
826                 /*
827                  * Fetch information about this interrupt.
828                  */
829                 intstat = ahb_inb(ahb, INTSTAT);
830                 mbox = ahb_inl(ahb, MBOXIN0);
831
832                 /*
833                  * Reset interrupt latch.
834                  */
835                 ahb_outb(ahb, CONTROL, CNTRL_CLRINT);
836
837                 /*
838                  * Process the completed operation
839                  */
840                 switch (intstat & INTSTAT_MASK) {
841                 case INTSTAT_ECB_OK:
842                 case INTSTAT_ECB_CMPWRETRY:
843                 case INTSTAT_ECB_CMPWERR:
844                         ahbdone(ahb, mbox, intstat);
845                         break;
846                 case INTSTAT_AEN_OCCURED:
847                         if ((intstat & INTSTAT_TARGET_MASK) == ahb->scsi_id) {
848                                 /* Bus Reset */
849                                 xpt_print_path(ahb->path);
850                                 switch (mbox) {
851                                 case HS_SCSI_RESET_ADAPTER:
852                                         printf("Host Adapter Initiated "
853                                                "Bus Reset occurred\n");
854                                         break;
855                                 case HS_SCSI_RESET_INCOMING:
856                                         printf("Bus Reset Initiated "
857                                                "by another device occurred\n");
858                                         break;
859                                 }
860                                 /* Notify the XPT */
861                                 xpt_async(AC_BUS_RESET, ahb->path, NULL);
862                                 break;
863                         }
864                         printf("Unsupported initiator selection AEN occured\n");
865                         break;
866                 case INTSTAT_IMMED_OK:
867                 case INTSTAT_IMMED_ERR:
868                         ahbhandleimmed(ahb, mbox, intstat);
869                         break;
870                 case INTSTAT_HW_ERR:
871                         panic("Unrecoverable hardware Error Occurred\n");
872                 }
873         }
874 }
875
876 static void
877 ahbexecuteecb(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
878 {
879         struct    ecb *ecb;
880         union     ccb *ccb;
881         struct    ahb_softc *ahb;
882         u_int32_t ecb_paddr;
883         int       s;
884
885         ecb = (struct ecb *)arg;
886         ccb = ecb->ccb;
887         ahb = (struct ahb_softc *)ccb->ccb_h.ccb_ahb_ptr;
888
889         if (error != 0) {
890                 if (error != EFBIG)
891                         printf("ahb%ld: Unexepected error 0x%x returned from "
892                                "bus_dmamap_load\n", ahb->unit, error);
893                 if (ccb->ccb_h.status == CAM_REQ_INPROG) {
894                         xpt_freeze_devq(ccb->ccb_h.path, /*count*/1);
895                         ccb->ccb_h.status = CAM_REQ_TOO_BIG|CAM_DEV_QFRZN;
896                 }
897                 ahbecbfree(ahb, ecb);
898                 xpt_done(ccb);
899                 return;
900         }
901                 
902         ecb_paddr = ahbecbvtop(ahb, ecb);
903
904         if (nseg != 0) {
905                 ahb_sg_t *sg;
906                 bus_dma_segment_t *end_seg;
907                 bus_dmasync_op_t op;
908
909                 end_seg = dm_segs + nseg;
910
911                 /* Copy the segments into our SG list */
912                 sg = ecb->sg_list;
913                 while (dm_segs < end_seg) {
914                         sg->addr = dm_segs->ds_addr;
915                         sg->len = dm_segs->ds_len;
916                         sg++;
917                         dm_segs++;
918                 }
919
920                 if (nseg > 1) {
921                         ecb->hecb.flag_word1 |= FW1_SG_ECB;
922                         ecb->hecb.data_ptr = ahbsgpaddr(ecb_paddr);
923                         ecb->hecb.data_len = sizeof(ahb_sg_t) * nseg;
924                 } else {
925                         ecb->hecb.data_ptr = ecb->sg_list->addr;
926                         ecb->hecb.data_len = ecb->sg_list->len;
927                 }
928
929                 if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) {
930 /*                      ecb->hecb.flag_word2 |= FW2_DATA_DIR_IN; */
931                         op = BUS_DMASYNC_PREREAD;
932                 } else {
933                         op = BUS_DMASYNC_PREWRITE;
934                 }
935                 /* ecb->hecb.flag_word2 |= FW2_CHECK_DATA_DIR; */
936
937                 bus_dmamap_sync(ahb->buffer_dmat, ecb->dmamap, op);
938
939         } else {
940                 ecb->hecb.data_ptr = 0;
941                 ecb->hecb.data_len = 0;
942         }
943
944         s = splcam();
945
946         /*
947          * Last time we need to check if this CCB needs to
948          * be aborted.
949          */
950         if (ccb->ccb_h.status != CAM_REQ_INPROG) {
951                 if (nseg != 0)
952                         bus_dmamap_unload(ahb->buffer_dmat, ecb->dmamap);
953                 ahbecbfree(ahb, ecb);
954                 xpt_done(ccb);
955                 splx(s);
956                 return;
957         }
958                 
959         ecb->state = ECB_ACTIVE;
960         ccb->ccb_h.status |= CAM_SIM_QUEUED;
961         LIST_INSERT_HEAD(&ahb->pending_ccbs, &ccb->ccb_h, sim_links.le);
962
963         /* Tell the adapter about this command */
964         ahbqueuembox(ahb, ecb_paddr, ATTN_STARTECB|ccb->ccb_h.target_id);
965
966         ccb->ccb_h.timeout_ch = timeout(ahbtimeout, (caddr_t)ecb,
967                                         (ccb->ccb_h.timeout * hz) / 1000);
968         splx(s);
969 }
970
971 static void
972 ahbaction(struct cam_sim *sim, union ccb *ccb)
973 {
974         struct  ahb_softc *ahb;
975
976         CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE, ("ahbaction\n"));
977         
978         ahb = (struct ahb_softc *)cam_sim_softc(sim);
979         
980         switch (ccb->ccb_h.func_code) {
981         /* Common cases first */
982         case XPT_SCSI_IO:       /* Execute the requested I/O operation */
983         {
984                 struct ecb *ecb;
985                 struct hardware_ecb *hecb;
986
987                 /*
988                  * get an ecb to use.
989                  */
990                 if ((ecb = ahbecbget(ahb)) == NULL) {
991                         /* Should never occur */
992                         panic("Failed to get an ecb");
993                 }
994
995                 /*
996                  * So we can find the ECB when an abort is requested
997                  */
998                 ecb->ccb = ccb;
999                 ccb->ccb_h.ccb_ecb_ptr = ecb;
1000                 ccb->ccb_h.ccb_ahb_ptr = ahb;
1001
1002                 /*
1003                  * Put all the arguments for the xfer in the ecb
1004                  */
1005                 hecb = &ecb->hecb;
1006                 hecb->opcode = ECBOP_INITIATOR_SCSI_CMD;
1007                 hecb->flag_word1 = FW1_AUTO_REQUEST_SENSE
1008                                  | FW1_ERR_STATUS_BLK_ONLY;
1009                 hecb->flag_word2 = ccb->ccb_h.target_lun
1010                                  | FW2_NO_RETRY_ON_BUSY;
1011                 if ((ccb->ccb_h.flags & CAM_TAG_ACTION_VALID) != 0) {
1012                         hecb->flag_word2 |= FW2_TAG_ENB
1013                                          | ((ccb->csio.tag_action & 0x3)
1014                                             << FW2_TAG_TYPE_SHIFT);
1015                 }
1016                 if ((ccb->ccb_h.flags & CAM_DIS_DISCONNECT) != 0)
1017                         hecb->flag_word2 |= FW2_DISABLE_DISC;
1018                 hecb->sense_len = ccb->csio.sense_len;
1019                 hecb->cdb_len = ccb->csio.cdb_len;
1020                 if ((ccb->ccb_h.flags & CAM_CDB_POINTER) != 0) {
1021                         if ((ccb->ccb_h.flags & CAM_CDB_PHYS) == 0) {
1022                                 bcopy(ccb->csio.cdb_io.cdb_ptr,
1023                                       hecb->cdb, hecb->cdb_len);
1024                         } else {
1025                                 /* I guess I could map it in... */
1026                                 ccb->ccb_h.status = CAM_REQ_INVALID;
1027                                 ahbecbfree(ahb, ecb);
1028                                 xpt_done(ccb);
1029                                 return;
1030                         }
1031                 } else {
1032                         bcopy(ccb->csio.cdb_io.cdb_bytes,
1033                               hecb->cdb, hecb->cdb_len);
1034                 }
1035
1036                 /*
1037                  * If we have any data to send with this command,
1038                  * map it into bus space.
1039                  */
1040                 if ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) {
1041                         if ((ccb->ccb_h.flags & CAM_SCATTER_VALID) == 0) {
1042                                 /*
1043                                  * We've been given a pointer
1044                                  * to a single buffer.
1045                                  */
1046                                 if ((ccb->ccb_h.flags & CAM_DATA_PHYS)==0) {
1047                                         int s;
1048                                         int error;
1049
1050                                         s = splsoftvm();
1051                                         error = bus_dmamap_load(
1052                                             ahb->buffer_dmat,
1053                                             ecb->dmamap,
1054                                             ccb->csio.data_ptr,
1055                                             ccb->csio.dxfer_len,
1056                                             ahbexecuteecb,
1057                                             ecb, /*flags*/0);
1058                                         if (error == EINPROGRESS) {
1059                                                 /*
1060                                                  * So as to maintain ordering,
1061                                                  * freeze the controller queue
1062                                                  * until our mapping is
1063                                                  * returned.
1064                                                  */
1065                                                 xpt_freeze_simq(ahb->sim, 1);
1066                                                 ccb->ccb_h.status |=
1067                                                     CAM_RELEASE_SIMQ;
1068                                         }
1069                                         splx(s);
1070                                 } else {
1071                                         struct bus_dma_segment seg; 
1072
1073                                         /* Pointer to physical buffer */
1074                                         seg.ds_addr =
1075                                             (bus_addr_t)ccb->csio.data_ptr;
1076                                         seg.ds_len = ccb->csio.dxfer_len;
1077                                         ahbexecuteecb(ecb, &seg, 1, 0);
1078                                 }
1079                         } else {
1080                                 struct bus_dma_segment *segs;
1081
1082                                 if ((ccb->ccb_h.flags & CAM_DATA_PHYS) != 0)
1083                                         panic("ahbaction - Physical segment "
1084                                               "pointers unsupported");
1085
1086                                 if ((ccb->ccb_h.flags & CAM_SG_LIST_PHYS) == 0)
1087                                         panic("btaction - Virtual segment "
1088                                               "addresses unsupported");
1089
1090                                 /* Just use the segments provided */
1091                                 segs = (struct bus_dma_segment *)
1092                                     ccb->csio.data_ptr;
1093                                 ahbexecuteecb(ecb, segs, ccb->csio.sglist_cnt,
1094                                              0);
1095                         }
1096                 } else {
1097                         ahbexecuteecb(ecb, NULL, 0, 0);
1098                 }
1099                 break;
1100         }
1101         case XPT_EN_LUN:                /* Enable LUN as a target */
1102         case XPT_TARGET_IO:             /* Execute target I/O request */
1103         case XPT_ACCEPT_TARGET_IO:      /* Accept Host Target Mode CDB */
1104         case XPT_CONT_TARGET_IO:        /* Continue Host Target I/O Connection*/
1105         case XPT_ABORT:                 /* Abort the specified CCB */
1106                 /* XXX Implement */
1107                 ccb->ccb_h.status = CAM_REQ_INVALID;
1108                 xpt_done(ccb);
1109                 break;
1110         case XPT_SET_TRAN_SETTINGS:
1111         {
1112                 ccb->ccb_h.status = CAM_FUNC_NOTAVAIL;
1113                 xpt_done(ccb);
1114                 break;
1115         }
1116         case XPT_GET_TRAN_SETTINGS:
1117         /* Get default/user set transfer settings for the target */
1118         {
1119                 struct  ccb_trans_settings *cts;
1120                 u_int   target_mask;
1121
1122                 cts = &ccb->cts;
1123                 target_mask = 0x01 << ccb->ccb_h.target_id;
1124                 if ((cts->flags & CCB_TRANS_USER_SETTINGS) != 0) {
1125                         cts->flags = 0;
1126                         if ((ahb->disc_permitted & target_mask) != 0)
1127                                 cts->flags |= CCB_TRANS_DISC_ENB;
1128                         if ((ahb->tags_permitted & target_mask) != 0)
1129                                 cts->flags |= CCB_TRANS_TAG_ENB;
1130                         cts->bus_width = MSG_EXT_WDTR_BUS_8_BIT;
1131                         cts->sync_period = 25; /* 10MHz */
1132
1133                         if (cts->sync_period != 0)
1134                                 cts->sync_offset = 15;
1135
1136                         cts->valid = CCB_TRANS_SYNC_RATE_VALID
1137                                    | CCB_TRANS_SYNC_OFFSET_VALID
1138                                    | CCB_TRANS_BUS_WIDTH_VALID
1139                                    | CCB_TRANS_DISC_VALID
1140                                    | CCB_TRANS_TQ_VALID;
1141                         ccb->ccb_h.status = CAM_REQ_CMP;
1142                 } else {
1143                         ccb->ccb_h.status = CAM_FUNC_NOTAVAIL;
1144                 }
1145                 xpt_done(ccb);
1146                 break;
1147         }
1148         case XPT_RESET_DEV:     /* Bus Device Reset the specified SCSI device */
1149         {
1150                 int i;
1151                 int s;
1152
1153                 s = splcam();
1154                 ahb->immed_cmd = IMMED_RESET;
1155                 ahbqueuembox(ahb, IMMED_RESET, ATTN_IMMED|ccb->ccb_h.target_id);
1156                 /* Poll for interrupt completion */
1157                 for (i = 1000; ahb->immed_cmd != 0 && i != 0; i--) {
1158                         DELAY(1000);
1159                         ahbintr(cam_sim_softc(sim));
1160                 }
1161                 splx(s);
1162                 break;
1163         }
1164         case XPT_CALC_GEOMETRY:
1165         {
1166                 struct    ccb_calc_geometry *ccg;
1167                 u_int32_t size_mb;
1168                 u_int32_t secs_per_cylinder;
1169
1170                 ccg = &ccb->ccg;
1171                 size_mb = ccg->volume_size
1172                         / ((1024L * 1024L) / ccg->block_size);
1173                 
1174                 if (size_mb > 1024 && (ahb->extended_trans != 0)) {
1175                         ccg->heads = 255;
1176                         ccg->secs_per_track = 63;
1177                 } else {
1178                         ccg->heads = 64;
1179                         ccg->secs_per_track = 32;
1180                 }
1181                 secs_per_cylinder = ccg->heads * ccg->secs_per_track;
1182                 ccg->cylinders = ccg->volume_size / secs_per_cylinder;
1183                 ccb->ccb_h.status = CAM_REQ_CMP;
1184                 xpt_done(ccb);
1185                 break;
1186         }
1187         case XPT_RESET_BUS:             /* Reset the specified SCSI bus */
1188         {
1189                 int i;
1190
1191                 ahb->immed_cmd = IMMED_RESET;
1192                 ahbqueuembox(ahb, IMMED_RESET, ATTN_IMMED|ahb->scsi_id);
1193                 /* Poll for interrupt completion */
1194                 for (i = 1000; ahb->immed_cmd != 0 && i != 0; i--)
1195                         DELAY(1000);
1196                 ccb->ccb_h.status = CAM_REQ_CMP;
1197                 xpt_done(ccb);
1198                 break;
1199         }
1200         case XPT_TERM_IO:               /* Terminate the I/O process */
1201                 /* XXX Implement */
1202                 ccb->ccb_h.status = CAM_REQ_INVALID;
1203                 xpt_done(ccb);
1204                 break;
1205         case XPT_PATH_INQ:              /* Path routing inquiry */
1206         {
1207                 struct ccb_pathinq *cpi = &ccb->cpi;
1208                 
1209                 cpi->version_num = 1; /* XXX??? */
1210                 cpi->hba_inquiry = PI_SDTR_ABLE|PI_TAG_ABLE;
1211                 cpi->target_sprt = 0;
1212                 cpi->hba_misc = 0;
1213                 cpi->hba_eng_cnt = 0;
1214                 cpi->max_target = 7;
1215                 cpi->max_lun = 7;
1216                 cpi->initiator_id = ahb->scsi_id;
1217                 cpi->bus_id = cam_sim_bus(sim);
1218                 cpi->base_transfer_speed = 3300;
1219                 strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
1220                 strncpy(cpi->hba_vid, "Adaptec", HBA_IDLEN);
1221                 strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN);
1222                 cpi->unit_number = cam_sim_unit(sim);
1223                 cpi->ccb_h.status = CAM_REQ_CMP;
1224                 xpt_done(ccb);
1225                 break;
1226         }
1227 #if 0
1228         /* Need these??? */
1229         case XPT_IMMED_NOTIFY:          /* Notify Host Target driver of event */
1230         case XPT_NOTIFY_ACK:            /* Acknowledgement of event */
1231 #endif
1232         default:
1233                 ccb->ccb_h.status = CAM_REQ_INVALID;
1234                 xpt_done(ccb);
1235                 break;
1236         }
1237 }
1238
1239 static void
1240 ahbpoll(struct cam_sim *sim)
1241 {
1242         ahbintr(cam_sim_softc(sim));
1243 }
1244
1245 static void
1246 ahbtimeout(void *arg)
1247 {
1248         struct ecb       *ecb;
1249         union  ccb       *ccb;
1250         struct ahb_softc *ahb;
1251         int               s;
1252
1253         ecb = (struct ecb *)arg;
1254         ccb = ecb->ccb;
1255         ahb = (struct ahb_softc *)ccb->ccb_h.ccb_ahb_ptr;
1256         xpt_print_path(ccb->ccb_h.path);
1257         printf("ECB %p - timed out\n", (void *)ecb);
1258
1259         s = splcam();
1260
1261         if ((ecb->state & ECB_ACTIVE) == 0) {
1262                 xpt_print_path(ccb->ccb_h.path);
1263                 printf("ECB %p - timed out ECB already completed\n",
1264                        (void *)ecb);
1265                 splx(s);
1266                 return;
1267         }
1268         /*
1269          * In order to simplify the recovery process, we ask the XPT
1270          * layer to halt the queue of new transactions and we traverse
1271          * the list of pending CCBs and remove their timeouts. This
1272          * means that the driver attempts to clear only one error
1273          * condition at a time.  In general, timeouts that occur
1274          * close together are related anyway, so there is no benefit
1275          * in attempting to handle errors in parrallel.  Timeouts will
1276          * be reinstated when the recovery process ends.
1277          */
1278         if ((ecb->state & ECB_DEVICE_RESET) == 0) {
1279                 struct ccb_hdr *ccb_h;
1280
1281                 if ((ecb->state & ECB_RELEASE_SIMQ) == 0) {
1282                         xpt_freeze_simq(ahb->sim, /*count*/1);
1283                         ecb->state |= ECB_RELEASE_SIMQ;
1284                 }
1285
1286                 ccb_h = LIST_FIRST(&ahb->pending_ccbs);
1287                 while (ccb_h != NULL) {
1288                         struct ecb *pending_ecb;
1289
1290                         pending_ecb = (struct ecb *)ccb_h->ccb_ecb_ptr;
1291                         untimeout(ahbtimeout, pending_ecb, ccb_h->timeout_ch);
1292                         ccb_h = LIST_NEXT(ccb_h, sim_links.le);
1293                 }
1294
1295                 /* Store for our interrupt handler */
1296                 ahb->immed_ecb = ecb;
1297
1298                 /*    
1299                  * Send a Bus Device Reset message:
1300                  * The target that is holding up the bus may not
1301                  * be the same as the one that triggered this timeout
1302                  * (different commands have different timeout lengths),
1303                  * but we have no way of determining this from our
1304                  * timeout handler.  Our strategy here is to queue a
1305                  * BDR message to the target of the timed out command.
1306                  * If this fails, we'll get another timeout 2 seconds
1307                  * later which will attempt a bus reset.
1308                  */
1309                 xpt_print_path(ccb->ccb_h.path);
1310                 printf("Queuing BDR\n");
1311                 ecb->state |= ECB_DEVICE_RESET;
1312                 ccb->ccb_h.timeout_ch =
1313                     timeout(ahbtimeout, (caddr_t)ecb, 2 * hz);
1314
1315                 ahb->immed_cmd = IMMED_RESET;
1316                 ahbqueuembox(ahb, IMMED_RESET, ATTN_IMMED|ccb->ccb_h.target_id);
1317         } else if ((ecb->state & ECB_SCSIBUS_RESET) != 0) {
1318                 /*
1319                  * Try a SCSI bus reset.  We do this only if we
1320                  * have already attempted to clear the condition with a BDR.
1321                  */
1322                 xpt_print_path(ccb->ccb_h.path);
1323                 printf("Attempting SCSI Bus reset\n");
1324                 ecb->state |= ECB_SCSIBUS_RESET;
1325                 ccb->ccb_h.timeout_ch =
1326                     timeout(ahbtimeout, (caddr_t)ecb, 2 * hz);
1327                 ahb->immed_cmd = IMMED_RESET;
1328                 ahbqueuembox(ahb, IMMED_RESET, ATTN_IMMED|ahb->scsi_id);
1329         } else {
1330                 /* Bring out the hammer... */
1331                 ahbreset(ahb);
1332
1333                 /* Simulate the reset complete interrupt */
1334                 ahbhandleimmed(ahb, 0, ahb->scsi_id|INTSTAT_IMMED_OK);
1335         }
1336
1337         splx(s);
1338 }
1339
1340 static device_method_t ahb_eisa_methods[] = {
1341         /* Device interface */
1342         DEVMETHOD(device_probe,         ahbprobe),
1343         DEVMETHOD(device_attach,        ahbattach),
1344
1345         { 0, 0 }
1346 };
1347
1348 static driver_t ahb_eisa_driver = {
1349         "ahb",
1350         ahb_eisa_methods,
1351         1,                      /* unused */
1352 };
1353
1354 static devclass_t ahb_devclass;
1355
1356 DRIVER_MODULE(ahb, eisa, ahb_eisa_driver, ahb_devclass, 0, 0);