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