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