From 9b600c5c50a525eba0be656ef08993b702947807 Mon Sep 17 00:00:00 2001 From: imp Date: Thu, 16 Feb 2017 21:56:27 +0000 Subject: [PATCH] Remove the ahb driver for the EISA Adaptec 174x. --- share/man/man4/Makefile | 1 - share/man/man4/ahb.4 | 92 --- sys/conf/NOTES | 2 - sys/conf/files | 1 - sys/dev/ahb/ahb.c | 1315 -------------------------------------- sys/dev/ahb/ahbreg.h | 284 -------- sys/modules/Makefile | 4 - sys/modules/ahb/Makefile | 8 - 8 files changed, 1707 deletions(-) delete mode 100644 share/man/man4/ahb.4 delete mode 100644 sys/dev/ahb/ahb.c delete mode 100644 sys/dev/ahb/ahbreg.h delete mode 100644 sys/modules/ahb/Makefile diff --git a/share/man/man4/Makefile b/share/man/man4/Makefile index 3debe5895aeb..0369e9efff7f 100644 --- a/share/man/man4/Makefile +++ b/share/man/man4/Makefile @@ -29,7 +29,6 @@ MAN= aac.4 \ age.4 \ agp.4 \ aha.4 \ - ahb.4 \ ahc.4 \ ahci.4 \ ahd.4 \ diff --git a/share/man/man4/ahb.4 b/share/man/man4/ahb.4 deleted file mode 100644 index fab6fecb258a..000000000000 --- a/share/man/man4/ahb.4 +++ /dev/null @@ -1,92 +0,0 @@ -.\" -.\" Copyright (c) 1994 Wilko Bulte -.\" All rights reserved. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" 3. The name of the author may not be used to endorse or promote products -.\" derived from this software without specific prior written permission -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR -.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, -.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -.\" -.\" $FreeBSD$ -.\" -.Dd July 4, 2004 -.Dt AHB 4 -.Os -.Sh NAME -.Nm ahb -.Nd Adaptec EISA SCSI host adapter driver -.Sh SYNOPSIS -To compile this driver into the kernel, -place the following lines in your -kernel configuration file: -.Bd -ragged -offset indent -.Cd "device scbus" -.Cd "device ahb" -.Ed -.Pp -Alternatively, to load the driver as a -module at boot time, place the following line in -.Xr loader.conf 5 : -.Bd -literal -offset indent -ahb_load="YES" -.Ed -.Sh DESCRIPTION -This driver provides access to the -.Tn SCSI -bus connected to an Adaptec -AHA-174X host adapters in -.Dq Em enhanced -mode. -Tagged queueing and synchronous SCSI transfers are supported. -.Sh HARDWARE -The -.Nm -driver supports the following SCSI host adapters: -.Pp -.Bl -bullet -compact -.It -Adaptec AHA-1740 -.It -Adaptec AHA-1742 -.It -Adaptec AHA-1740A -.It -Adaptec AHA-1742A -.El -.Sh SEE ALSO -.Xr aha 4 , -.Xr ahc 4 , -.Xr aic 4 , -.Xr cd 4 , -.Xr da 4 , -.Xr sa 4 , -.Xr scsi 4 -.Sh AUTHORS -The -.Nm -driver was written by -.An Justin T. Gibbs . -.Sh CAVEATS -The Adaptec 174X is very sensitive to SCSI bus termination and cable -length. -It may also have difficulties operating with some modern devices -that, due to their speed, expose timing problems in the controller. -There are no known mechanisms for working around device incompatibilities of -this nature. diff --git a/sys/conf/NOTES b/sys/conf/NOTES index 256c0ea86bca..4e1210897a37 100644 --- a/sys/conf/NOTES +++ b/sys/conf/NOTES @@ -1530,7 +1530,6 @@ options TERMINAL_KERN_ATTR=(FG_LIGHTRED|BG_BLACK) # adv: All Narrow SCSI bus AdvanSys controllers. # adw: Second Generation AdvanSys controllers including the ADV940UW. # aha: Adaptec 154x/1535/1640 -# ahb: Adaptec 174x EISA controllers # ahc: Adaptec 274x/284x/2910/293x/294x/394x/3950x/3960x/398X/4944/ # 19160x/29160x, aic7770/aic78xx # ahd: Adaptec 29320/39320 Controllers. @@ -1570,7 +1569,6 @@ device aha hint.aha.0.at="isa" device aic hint.aic.0.at="isa" -device ahb device ahc device ahd device esp diff --git a/sys/conf/files b/sys/conf/files index 99565e940d77..c84fd424565a 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -694,7 +694,6 @@ dev/agp/agp.c optional agp pci dev/agp/agp_if.m optional agp pci dev/aha/aha.c optional aha dev/aha/aha_isa.c optional aha isa -dev/ahb/ahb.c optional ahb eisa dev/ahci/ahci.c optional ahci dev/ahci/ahciem.c optional ahci dev/ahci/ahci_pci.c optional ahci pci diff --git a/sys/dev/ahb/ahb.c b/sys/dev/ahb/ahb.c deleted file mode 100644 index b6665009d9af..000000000000 --- a/sys/dev/ahb/ahb.c +++ /dev/null @@ -1,1315 +0,0 @@ -/*- - * CAM SCSI device driver for the Adaptec 174X SCSI Host adapter - * - * Copyright (c) 1998 Justin T. Gibbs - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice immediately at the beginning of the file, without modification, - * this list of conditions, and the following disclaimer. - * 2. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $FreeBSD$ - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include -#include -#include - -#include - -#include - -#include - -#define ccb_ecb_ptr spriv_ptr0 -#define ccb_ahb_ptr spriv_ptr1 - -#define ahb_inb(ahb, port) \ - bus_read_1((ahb)->res, port) - -#define ahb_inl(ahb, port) \ - bus_read_4((ahb)->res, port) - -#define ahb_outb(ahb, port, value) \ - bus_write_1((ahb)->res, port, value) - -#define ahb_outl(ahb, port, value) \ - bus_write_4((ahb)->res, port, value) - -static const char *ahbmatch(eisa_id_t type); -static struct ahb_softc *ahballoc(device_t dev, struct resource *res); -static void ahbfree(struct ahb_softc *ahb); -static int ahbreset(struct ahb_softc *ahb); -static void ahbmapecbs(void *arg, bus_dma_segment_t *segs, - int nseg, int error); -static int ahbxptattach(struct ahb_softc *ahb); -static void ahbhandleimmed(struct ahb_softc *ahb, - u_int32_t mbox, u_int intstat); -static void ahbcalcresid(struct ahb_softc *ahb, - struct ecb *ecb, union ccb *ccb); -static __inline void ahbdone(struct ahb_softc *ahb, u_int32_t mbox, - u_int intstat); -static void ahbintr(void *arg); -static void ahbintr_locked(struct ahb_softc *ahb); -static bus_dmamap_callback_t ahbexecuteecb; -static void ahbaction(struct cam_sim *sim, union ccb *ccb); -static void ahbpoll(struct cam_sim *sim); - -/* Our timeout handler */ -static void ahbtimeout(void *arg); - -static __inline struct ecb* ahbecbget(struct ahb_softc *ahb); -static __inline void ahbecbfree(struct ahb_softc* ahb, - struct ecb* ecb); -static __inline u_int32_t ahbecbvtop(struct ahb_softc *ahb, - struct ecb *ecb); -static __inline struct ecb* ahbecbptov(struct ahb_softc *ahb, - u_int32_t ecb_addr); -static __inline u_int32_t ahbstatuspaddr(u_int32_t ecb_paddr); -static __inline u_int32_t ahbsensepaddr(u_int32_t ecb_paddr); -static __inline u_int32_t ahbsgpaddr(u_int32_t ecb_paddr); -static __inline void ahbqueuembox(struct ahb_softc *ahb, - u_int32_t mboxval, - u_int attn_code); - -static __inline struct ecb* -ahbecbget(struct ahb_softc *ahb) -{ - struct ecb* ecb; - - if (!dumping) - mtx_assert(&ahb->lock, MA_OWNED); - if ((ecb = SLIST_FIRST(&ahb->free_ecbs)) != NULL) - SLIST_REMOVE_HEAD(&ahb->free_ecbs, links); - - return (ecb); -} - -static __inline void -ahbecbfree(struct ahb_softc* ahb, struct ecb* ecb) -{ - - if (!dumping) - mtx_assert(&ahb->lock, MA_OWNED); - ecb->state = ECB_FREE; - SLIST_INSERT_HEAD(&ahb->free_ecbs, ecb, links); -} - -static __inline u_int32_t -ahbecbvtop(struct ahb_softc *ahb, struct ecb *ecb) -{ - return (ahb->ecb_physbase - + (u_int32_t)((caddr_t)ecb - (caddr_t)ahb->ecb_array)); -} - -static __inline struct ecb* -ahbecbptov(struct ahb_softc *ahb, u_int32_t ecb_addr) -{ - return (ahb->ecb_array - + ((struct ecb*)(uintptr_t)ecb_addr - - (struct ecb*)(uintptr_t)ahb->ecb_physbase)); -} - -static __inline u_int32_t -ahbstatuspaddr(u_int32_t ecb_paddr) -{ - return (ecb_paddr + offsetof(struct ecb, status)); -} - -static __inline u_int32_t -ahbsensepaddr(u_int32_t ecb_paddr) -{ - return (ecb_paddr + offsetof(struct ecb, sense)); -} - -static __inline u_int32_t -ahbsgpaddr(u_int32_t ecb_paddr) -{ - return (ecb_paddr + offsetof(struct ecb, sg_list)); -} - -static __inline void -ahbqueuembox(struct ahb_softc *ahb, u_int32_t mboxval, u_int attn_code) -{ - u_int loopmax = 300; - while (--loopmax) { - u_int status; - - status = ahb_inb(ahb, HOSTSTAT); - if ((status & (HOSTSTAT_MBOX_EMPTY|HOSTSTAT_BUSY)) - == HOSTSTAT_MBOX_EMPTY) - break; - DELAY(20); - } - if (loopmax == 0) - panic("%s: adapter not taking commands\n", - device_get_nameunit(ahb->dev)); - - ahb_outl(ahb, MBOXOUT0, mboxval); - ahb_outb(ahb, ATTN, attn_code); -} - -static const char * -ahbmatch(eisa_id_t type) -{ - switch(type & 0xfffffe00) { - case EISA_DEVICE_ID_ADAPTEC_1740: - return ("Adaptec 174x SCSI host adapter"); - break; - default: - break; - } - return (NULL); -} - -static int -ahbprobe(device_t dev) -{ - const char *desc; - u_int32_t iobase; - u_int32_t irq; - u_int8_t intdef; - int shared; - - desc = ahbmatch(eisa_get_id(dev)); - if (!desc) - return (ENXIO); - device_set_desc(dev, desc); - - iobase = (eisa_get_slot(dev) * EISA_SLOT_SIZE) + - AHB_EISA_SLOT_OFFSET; - - eisa_add_iospace(dev, iobase, AHB_EISA_IOSIZE, RESVADDR_NONE); - - intdef = inb(INTDEF + iobase); - switch (intdef & 0x7) { - case INT9: - irq = 9; - break; - case INT10: - irq = 10; - break; - case INT11: - irq = 11; - break; - case INT12: - irq = 12; - break; - case INT14: - irq = 14; - break; - case INT15: - irq = 15; - break; - default: - printf("Adaptec 174X at slot %d: illegal " - "irq setting %d\n", eisa_get_slot(dev), - (intdef & 0x7)); - irq = 0; - break; - } - if (irq == 0) - return ENXIO; - - shared = (inb(INTDEF + iobase) & INTLEVEL) ? - EISA_TRIGGER_LEVEL : EISA_TRIGGER_EDGE; - - eisa_add_intr(dev, irq, shared); - - return 0; -} - -static int -ahbattach(device_t dev) -{ - /* - * find unit and check we have that many defined - */ - struct ahb_softc *ahb; - struct ecb* next_ecb; - struct resource *io; - struct resource *irq; - int rid; - void *ih; - - irq = NULL; - rid = 0; - io = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &rid, RF_ACTIVE); - if (io == NULL) { - device_printf(dev, "No I/O space?!\n"); - return ENOMEM; - } - - ahb = ahballoc(dev, io); - - if (ahbreset(ahb) != 0) - goto error_exit; - - rid = 0; - irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_ACTIVE); - if (irq == NULL) { - device_printf(dev, "Can't allocate interrupt\n"); - goto error_exit; - } - - /* - * Create our DMA tags. These tags define the kinds of device - * accessible memory allocations and memory mappings we will - * need to perform during normal operation. - */ - /* DMA tag for mapping buffers into device visible space. */ - if (bus_dma_tag_create( /* parent */ bus_get_dma_tag(dev), - /* alignment */ 1, - /* boundary */ 0, - /* lowaddr */ BUS_SPACE_MAXADDR_32BIT, - /* highaddr */ BUS_SPACE_MAXADDR, - /* filter */ NULL, - /* filterarg */ NULL, - /* maxsize */ DFLTPHYS, - /* nsegments */ AHB_NSEG, - /* maxsegsz */ BUS_SPACE_MAXSIZE_32BIT, - /* flags */ BUS_DMA_ALLOCNOW, - /* lockfunc */ busdma_lock_mutex, - /* lockarg */ &ahb->lock, - &ahb->buffer_dmat) != 0) - goto error_exit; - - ahb->init_level++; - - /* DMA tag for our ccb structures and ha inquiry data */ - if (bus_dma_tag_create( /* parent */ bus_get_dma_tag(dev), - /* alignment */ 1, - /* boundary */ 0, - /* lowaddr */ BUS_SPACE_MAXADDR_32BIT, - /* highaddr */ BUS_SPACE_MAXADDR, - /* filter */ NULL, - /* filterarg */ NULL, - /* maxsize */ (AHB_NECB * - sizeof(struct ecb)) - + sizeof(*ahb->ha_inq_data), - /* nsegments */ 1, - /* maxsegsz */ BUS_SPACE_MAXSIZE_32BIT, - /* flags */ 0, - /* lockfunc */ NULL, - /* lockarg */ NULL, - &ahb->ecb_dmat) != 0) - goto error_exit; - - ahb->init_level++; - - /* Allocation for our ccbs */ - if (bus_dmamem_alloc(ahb->ecb_dmat, (void **)&ahb->ecb_array, - BUS_DMA_NOWAIT, &ahb->ecb_dmamap) != 0) - goto error_exit; - - ahb->ha_inq_data = (struct ha_inquiry_data *)&ahb->ecb_array[AHB_NECB]; - - ahb->init_level++; - - /* And permanently map them */ - bus_dmamap_load(ahb->ecb_dmat, ahb->ecb_dmamap, - ahb->ecb_array, AHB_NSEG * sizeof(struct ecb), - ahbmapecbs, ahb, /*flags*/0); - - ahb->init_level++; - - /* Allocate the buffer dmamaps for each of our ECBs */ - bzero(ahb->ecb_array, (AHB_NECB * sizeof(struct ecb)) - + sizeof(*ahb->ha_inq_data)); - next_ecb = ahb->ecb_array; - while (ahb->num_ecbs < AHB_NECB) { - u_int32_t ecb_paddr; - - if (bus_dmamap_create(ahb->buffer_dmat, /*flags*/0, - &next_ecb->dmamap)) - break; - callout_init_mtx(&next_ecb->timer, &ahb->lock, 0); - ecb_paddr = ahbecbvtop(ahb, next_ecb); - next_ecb->hecb.status_ptr = ahbstatuspaddr(ecb_paddr); - next_ecb->hecb.sense_ptr = ahbsensepaddr(ecb_paddr); - ahb->num_ecbs++; - ahbecbfree(ahb, next_ecb); - next_ecb++; - } - - ahb->init_level++; - - /* - * Now that we know we own the resources we need, register - * our bus with the XPT. - */ - if (ahbxptattach(ahb)) - goto error_exit; - - /* Enable our interrupt */ - if (bus_setup_intr(dev, irq, INTR_TYPE_CAM|INTR_ENTROPY|INTR_MPSAFE, - NULL, ahbintr, ahb, &ih) != 0) - goto error_exit; - - return (0); - -error_exit: - /* - * The board's IRQ line will not be left enabled - * if we can't initialize correctly, so its safe - * to release the irq. - */ - ahbfree(ahb); - if (irq != NULL) - bus_release_resource(dev, SYS_RES_IRQ, 0, irq); - bus_release_resource(dev, SYS_RES_IOPORT, 0, io); - return (-1); -} - -static struct ahb_softc * -ahballoc(device_t dev, struct resource *res) -{ - struct ahb_softc *ahb; - - ahb = device_get_softc(dev); - SLIST_INIT(&ahb->free_ecbs); - LIST_INIT(&ahb->pending_ccbs); - ahb->res = res; - ahb->disc_permitted = ~0; - ahb->tags_permitted = ~0; - ahb->dev = dev; - mtx_init(&ahb->lock, "ahb", NULL, MTX_DEF); - - return (ahb); -} - -static void -ahbfree(struct ahb_softc *ahb) -{ - switch (ahb->init_level) { - default: - case 4: - bus_dmamap_unload(ahb->ecb_dmat, ahb->ecb_dmamap); - case 3: - bus_dmamem_free(ahb->ecb_dmat, ahb->ecb_array, - ahb->ecb_dmamap); - case 2: - bus_dma_tag_destroy(ahb->ecb_dmat); - case 1: - bus_dma_tag_destroy(ahb->buffer_dmat); - case 0: - break; - } - mtx_destroy(&ahb->lock); -} - -/* - * reset board, If it doesn't respond, return failure - */ -static int -ahbreset(struct ahb_softc *ahb) -{ - int wait = 1000; /* 1 sec enough? */ - int test; - - if ((ahb_inb(ahb, PORTADDR) & PORTADDR_ENHANCED) == 0) { - printf("ahb_reset: Controller not in enhanced mode\n"); - return (-1); - } - - ahb_outb(ahb, CONTROL, CNTRL_HARD_RST); - DELAY(1000); - ahb_outb(ahb, CONTROL, 0); - while (--wait) { - DELAY(1000); - if ((ahb_inb(ahb, HOSTSTAT) & HOSTSTAT_BUSY) == 0) - break; - } - - if (wait == 0) { - printf("ahbreset: No answer from aha1742 board\n"); - return (-1); - } - if ((test = ahb_inb(ahb, MBOXIN0)) != 0) { - printf("ahb_reset: self test failed, val = 0x%x\n", test); - return (-1); - } - while (ahb_inb(ahb, HOSTSTAT) & HOSTSTAT_INTPEND) { - ahb_outb(ahb, CONTROL, CNTRL_CLRINT); - DELAY(10000); - } - return (0); -} - -static void -ahbmapecbs(void *arg, bus_dma_segment_t *segs, int nseg, int error) -{ - struct ahb_softc* ahb; - - ahb = (struct ahb_softc*)arg; - ahb->ecb_physbase = segs->ds_addr; - /* - * Space for adapter inquiry information is on the - * tail of the ecb array. - */ - ahb->ha_inq_physbase = ahbecbvtop(ahb, &ahb->ecb_array[AHB_NECB]); -} - -static int -ahbxptattach(struct ahb_softc *ahb) -{ - struct cam_devq *devq; - struct ecb *ecb; - u_int i; - - mtx_lock(&ahb->lock); - - /* Remember who are we on the scsi bus */ - ahb->scsi_id = ahb_inb(ahb, SCSIDEF) & HSCSIID; - - /* Use extended translation?? */ - ahb->extended_trans = ahb_inb(ahb, RESV1) & EXTENDED_TRANS; - - /* Fetch adapter inquiry data */ - ecb = ahbecbget(ahb); /* Always succeeds - no outstanding commands */ - ecb->hecb.opcode = ECBOP_READ_HA_INQDATA; - ecb->hecb.flag_word1 = FW1_SUPPRESS_URUN_ERR|FW1_ERR_STATUS_BLK_ONLY; - ecb->hecb.data_ptr = ahb->ha_inq_physbase; - ecb->hecb.data_len = sizeof(struct ha_inquiry_data); - ecb->hecb.sense_ptr = 0; - ecb->state = ECB_ACTIVE; - - /* Tell the adapter about this command */ - ahbqueuembox(ahb, ahbecbvtop(ahb, ecb), - ATTN_STARTECB|ahb->scsi_id); - - /* Poll for interrupt completion */ - for (i = 1000; ecb->state != ECB_FREE && i != 0; i--) { - ahbintr_locked(ahb); - DELAY(1000); - } - - ahb->num_ecbs = MIN(ahb->num_ecbs, - ahb->ha_inq_data->scsi_data.spc2_flags); - device_printf(ahb->dev, - "%.8s %s SCSI Adapter, FW Rev. %.4s, ID=%d, %d ECBs\n", - ahb->ha_inq_data->scsi_data.product, - (ahb->ha_inq_data->scsi_data.flags & 0x4) ? "Differential" - : "Single Ended", - ahb->ha_inq_data->scsi_data.revision, - ahb->scsi_id, ahb->num_ecbs); - - /* Restore sense paddr for future CCB clients */ - ecb->hecb.sense_ptr = ahbsensepaddr(ahbecbvtop(ahb, ecb)); - - ahbecbfree(ahb, ecb); - - /* - * Create the device queue for our SIM. - */ - devq = cam_simq_alloc(ahb->num_ecbs); - if (devq == NULL) { - mtx_unlock(&ahb->lock); - return (ENOMEM); - } - - /* - * Construct our SIM entry - */ - ahb->sim = cam_sim_alloc(ahbaction, ahbpoll, "ahb", ahb, - device_get_unit(ahb->dev), &ahb->lock, 2, ahb->num_ecbs, devq); - if (ahb->sim == NULL) { - cam_simq_free(devq); - mtx_unlock(&ahb->lock); - return (ENOMEM); - } - - if (xpt_bus_register(ahb->sim, ahb->dev, 0) != CAM_SUCCESS) { - cam_sim_free(ahb->sim, /*free_devq*/TRUE); - mtx_unlock(&ahb->lock); - return (ENXIO); - } - - if (xpt_create_path(&ahb->path, /*periph*/NULL, - cam_sim_path(ahb->sim), CAM_TARGET_WILDCARD, - CAM_LUN_WILDCARD) != CAM_REQ_CMP) { - xpt_bus_deregister(cam_sim_path(ahb->sim)); - cam_sim_free(ahb->sim, /*free_devq*/TRUE); - mtx_unlock(&ahb->lock); - return (ENXIO); - } - - /* - * Allow the board to generate interrupts. - */ - ahb_outb(ahb, INTDEF, ahb_inb(ahb, INTDEF) | INTEN); - mtx_unlock(&ahb->lock); - - return (0); -} - -static void -ahbhandleimmed(struct ahb_softc *ahb, u_int32_t mbox, u_int intstat) -{ - struct ccb_hdr *ccb_h; - u_int target_id; - - if (ahb->immed_cmd == 0) { - device_printf(ahb->dev, "Immediate Command complete with no " - " pending command\n"); - return; - } - - target_id = intstat & INTSTAT_TARGET_MASK; - - ccb_h = LIST_FIRST(&ahb->pending_ccbs); - while (ccb_h != NULL) { - struct ecb *pending_ecb; - union ccb *ccb; - - pending_ecb = (struct ecb *)ccb_h->ccb_ecb_ptr; - ccb = pending_ecb->ccb; - ccb_h = LIST_NEXT(ccb_h, sim_links.le); - if (ccb->ccb_h.target_id == target_id - || target_id == ahb->scsi_id) { - callout_stop(&pending_ecb->timer); - LIST_REMOVE(&ccb->ccb_h, sim_links.le); - if ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) - bus_dmamap_unload(ahb->buffer_dmat, - pending_ecb->dmamap); - if (pending_ecb == ahb->immed_ecb) - ccb->ccb_h.status = - CAM_CMD_TIMEOUT|CAM_RELEASE_SIMQ; - else if (target_id == ahb->scsi_id) - ccb->ccb_h.status = CAM_SCSI_BUS_RESET; - else - ccb->ccb_h.status = CAM_BDR_SENT; - ahbecbfree(ahb, pending_ecb); - xpt_done(ccb); - } else if (ahb->immed_ecb != NULL) { - /* Re-instate timeout */ - callout_reset_sbt(&pending_ecb->timer, - SBT_1MS * ccb->ccb_h.timeout, 0, ahbtimeout, - pending_ecb, 0); - } - } - - if (ahb->immed_ecb != NULL) { - ahb->immed_ecb = NULL; - device_printf(ahb->dev, "No longer in timeout\n"); - } else if (target_id == ahb->scsi_id) - device_printf(ahb->dev, "SCSI Bus Reset Delivered\n"); - else - device_printf(ahb->dev, - "Bus Device Reset Delivered to target %d\n", target_id); - - ahb->immed_cmd = 0; -} - -static void -ahbcalcresid(struct ahb_softc *ahb, struct ecb *ecb, union ccb *ccb) -{ - if (ecb->status.data_overrun != 0) { - /* - * Overrun Condition. The hardware doesn't - * provide a meaningful byte count in this case - * (the residual is always 0). Tell the XPT - * layer about the error. - */ - ccb->ccb_h.status = CAM_DATA_RUN_ERR; - } else { - ccb->csio.resid = ecb->status.resid_count; - - if ((ecb->hecb.flag_word1 & FW1_SG_ECB) != 0) { - /* - * For S/G transfers, the adapter provides a pointer - * to the address in the last S/G element used and a - * residual for that element. So, we need to sum up - * the elements that follow it in order to get a real - * residual number. If we have an overrun, the residual - * reported will be 0 and we already know that all S/G - * segments have been exhausted, so we can skip this - * step. - */ - ahb_sg_t *sg; - int num_sg; - - num_sg = ecb->hecb.data_len / sizeof(ahb_sg_t); - - /* Find the S/G the adapter was working on */ - for (sg = ecb->sg_list; - num_sg != 0 && sg->addr != ecb->status.resid_addr; - num_sg--, sg++) - ; - - /* Skip it */ - num_sg--; - sg++; - - /* Sum the rest */ - for (; num_sg != 0; num_sg--, sg++) - ccb->csio.resid += sg->len; - } - /* Underruns are not errors */ - ccb->ccb_h.status = CAM_REQ_CMP; - } -} - -static void -ahbprocesserror(struct ahb_softc *ahb, struct ecb *ecb, union ccb *ccb) -{ - struct hardware_ecb *hecb; - struct ecb_status *status; - - hecb = &ecb->hecb; - status = &ecb->status; - switch (status->ha_status) { - case HS_OK: - ccb->csio.scsi_status = status->scsi_status; - if (status->scsi_status != 0) { - ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR; - if (status->sense_stored) { - ccb->ccb_h.status |= CAM_AUTOSNS_VALID; - ccb->csio.sense_resid = - ccb->csio.sense_len - status->sense_len; - bcopy(&ecb->sense, &ccb->csio.sense_data, - status->sense_len); - } - } - break; - case HS_TARGET_NOT_ASSIGNED: - ccb->ccb_h.status = CAM_PATH_INVALID; - break; - case HS_SEL_TIMEOUT: - ccb->ccb_h.status = CAM_SEL_TIMEOUT; - break; - case HS_DATA_RUN_ERR: - ahbcalcresid(ahb, ecb, ccb); - break; - case HS_UNEXPECTED_BUSFREE: - ccb->ccb_h.status = CAM_UNEXP_BUSFREE; - break; - case HS_INVALID_PHASE: - ccb->ccb_h.status = CAM_SEQUENCE_FAIL; - break; - case HS_REQUEST_SENSE_FAILED: - ccb->ccb_h.status = CAM_AUTOSENSE_FAIL; - break; - case HS_TAG_MSG_REJECTED: - { - struct ccb_trans_settings neg; - struct ccb_trans_settings_scsi *scsi = &neg.proto_specific.scsi; - - xpt_print_path(ccb->ccb_h.path); - printf("refuses tagged commands. Performing " - "non-tagged I/O\n"); - memset(&neg, 0, sizeof (neg)); - neg.protocol = PROTO_SCSI; - neg.protocol_version = SCSI_REV_2; - neg.transport = XPORT_SPI; - neg.transport_version = 2; - scsi->flags = CTS_SCSI_VALID_TQ; - xpt_setup_ccb(&neg.ccb_h, ccb->ccb_h.path, /*priority*/1); - xpt_async(AC_TRANSFER_NEG, ccb->ccb_h.path, &neg); - ahb->tags_permitted &= ~(0x01 << ccb->ccb_h.target_id); - ccb->ccb_h.status = CAM_MSG_REJECT_REC; - break; - } - case HS_FIRMWARE_LOAD_REQ: - case HS_HARDWARE_ERR: - /* - * Tell the system that the Adapter - * is no longer functional. - */ - ccb->ccb_h.status = CAM_NO_HBA; - break; - case HS_CMD_ABORTED_HOST: - case HS_CMD_ABORTED_ADAPTER: - case HS_ATN_TARGET_FAILED: - case HS_SCSI_RESET_ADAPTER: - case HS_SCSI_RESET_INCOMING: - ccb->ccb_h.status = CAM_SCSI_BUS_RESET; - break; - case HS_INVALID_ECB_PARAM: - device_printf(ahb->dev, - "opcode 0x%02x, flag_word1 0x%02x, flag_word2 0x%02x\n", - hecb->opcode, hecb->flag_word1, hecb->flag_word2); - ccb->ccb_h.status = CAM_SCSI_BUS_RESET; - break; - case HS_DUP_TCB_RECEIVED: - case HS_INVALID_OPCODE: - case HS_INVALID_CMD_LINK: - case HS_PROGRAM_CKSUM_ERROR: - panic("%s: Can't happen host status %x occurred", - device_get_nameunit(ahb->dev), status->ha_status); - break; - } - if (ccb->ccb_h.status != CAM_REQ_CMP) { - xpt_freeze_devq(ccb->ccb_h.path, /*count*/1); - ccb->ccb_h.status |= CAM_DEV_QFRZN; - } -} - -static void -ahbdone(struct ahb_softc *ahb, u_int32_t mbox, u_int intstat) -{ - struct ecb *ecb; - union ccb *ccb; - - ecb = ahbecbptov(ahb, mbox); - - if ((ecb->state & ECB_ACTIVE) == 0) - panic("ecb not active"); - - ccb = ecb->ccb; - - if (ccb != NULL) { - callout_stop(&ecb->timer); - LIST_REMOVE(&ccb->ccb_h, sim_links.le); - - if ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) { - bus_dmasync_op_t op; - - if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) - op = BUS_DMASYNC_POSTREAD; - else - op = BUS_DMASYNC_POSTWRITE; - bus_dmamap_sync(ahb->buffer_dmat, ecb->dmamap, op); - bus_dmamap_unload(ahb->buffer_dmat, ecb->dmamap); - } - - if ((intstat & INTSTAT_MASK) == INTSTAT_ECB_OK) { - ccb->ccb_h.status = CAM_REQ_CMP; - ccb->csio.resid = 0; - } else { - ahbprocesserror(ahb, ecb, ccb); - } - ahbecbfree(ahb, ecb); - xpt_done(ccb); - } else { - /* Non CCB Command */ - if ((intstat & INTSTAT_MASK) != INTSTAT_ECB_OK) { - device_printf(ahb->dev, "Command 0%x Failed %x:%x:%x\n", - ecb->hecb.opcode, - *((u_int16_t*)&ecb->status), - ecb->status.ha_status, ecb->status.resid_count); - } - /* Client owns this ECB and will release it. */ - } -} - -/* - * Catch an interrupt from the adaptor - */ -static void -ahbintr(void *arg) -{ - struct ahb_softc *ahb; - - ahb = arg; - mtx_lock(&ahb->lock); - ahbintr_locked(ahb); - mtx_unlock(&ahb->lock); -} - -static void -ahbintr_locked(struct ahb_softc *ahb) -{ - u_int intstat; - u_int32_t mbox; - - while (ahb_inb(ahb, HOSTSTAT) & HOSTSTAT_INTPEND) { - /* - * Fetch information about this interrupt. - */ - intstat = ahb_inb(ahb, INTSTAT); - mbox = ahb_inl(ahb, MBOXIN0); - - /* - * Reset interrupt latch. - */ - ahb_outb(ahb, CONTROL, CNTRL_CLRINT); - - /* - * Process the completed operation - */ - switch (intstat & INTSTAT_MASK) { - case INTSTAT_ECB_OK: - case INTSTAT_ECB_CMPWRETRY: - case INTSTAT_ECB_CMPWERR: - ahbdone(ahb, mbox, intstat); - break; - case INTSTAT_AEN_OCCURED: - if ((intstat & INTSTAT_TARGET_MASK) == ahb->scsi_id) { - /* Bus Reset */ - xpt_print_path(ahb->path); - switch (mbox) { - case HS_SCSI_RESET_ADAPTER: - printf("Host Adapter Initiated " - "Bus Reset occurred\n"); - break; - case HS_SCSI_RESET_INCOMING: - printf("Bus Reset Initiated " - "by another device occurred\n"); - break; - } - /* Notify the XPT */ - xpt_async(AC_BUS_RESET, ahb->path, NULL); - break; - } - printf("Unsupported initiator selection AEN occurred\n"); - break; - case INTSTAT_IMMED_OK: - case INTSTAT_IMMED_ERR: - ahbhandleimmed(ahb, mbox, intstat); - break; - case INTSTAT_HW_ERR: - panic("Unrecoverable hardware Error Occurred\n"); - } - } -} - -static void -ahbexecuteecb(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error) -{ - struct ecb *ecb; - union ccb *ccb; - struct ahb_softc *ahb; - u_int32_t ecb_paddr; - - ecb = (struct ecb *)arg; - ccb = ecb->ccb; - ahb = (struct ahb_softc *)ccb->ccb_h.ccb_ahb_ptr; - mtx_assert(&ahb->lock, MA_OWNED); - - if (error != 0) { - if (error != EFBIG) - device_printf(ahb->dev, - "Unexepected error 0x%x returned from " - "bus_dmamap_load\n", error); - if (ccb->ccb_h.status == CAM_REQ_INPROG) { - xpt_freeze_devq(ccb->ccb_h.path, /*count*/1); - ccb->ccb_h.status = CAM_REQ_TOO_BIG|CAM_DEV_QFRZN; - } - ahbecbfree(ahb, ecb); - xpt_done(ccb); - return; - } - - ecb_paddr = ahbecbvtop(ahb, ecb); - - if (nseg != 0) { - ahb_sg_t *sg; - bus_dma_segment_t *end_seg; - bus_dmasync_op_t op; - - end_seg = dm_segs + nseg; - - /* Copy the segments into our SG list */ - sg = ecb->sg_list; - while (dm_segs < end_seg) { - sg->addr = dm_segs->ds_addr; - sg->len = dm_segs->ds_len; - sg++; - dm_segs++; - } - - if (nseg > 1) { - ecb->hecb.flag_word1 |= FW1_SG_ECB; - ecb->hecb.data_ptr = ahbsgpaddr(ecb_paddr); - ecb->hecb.data_len = sizeof(ahb_sg_t) * nseg; - } else { - ecb->hecb.data_ptr = ecb->sg_list->addr; - ecb->hecb.data_len = ecb->sg_list->len; - } - - if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) { -/* ecb->hecb.flag_word2 |= FW2_DATA_DIR_IN; */ - op = BUS_DMASYNC_PREREAD; - } else { - op = BUS_DMASYNC_PREWRITE; - } - /* ecb->hecb.flag_word2 |= FW2_CHECK_DATA_DIR; */ - - bus_dmamap_sync(ahb->buffer_dmat, ecb->dmamap, op); - - } else { - ecb->hecb.data_ptr = 0; - ecb->hecb.data_len = 0; - } - - /* - * Last time we need to check if this CCB needs to - * be aborted. - */ - if (ccb->ccb_h.status != CAM_REQ_INPROG) { - if (nseg != 0) - bus_dmamap_unload(ahb->buffer_dmat, ecb->dmamap); - ahbecbfree(ahb, ecb); - xpt_done(ccb); - return; - } - - ecb->state = ECB_ACTIVE; - ccb->ccb_h.status |= CAM_SIM_QUEUED; - LIST_INSERT_HEAD(&ahb->pending_ccbs, &ccb->ccb_h, sim_links.le); - - /* Tell the adapter about this command */ - ahbqueuembox(ahb, ecb_paddr, ATTN_STARTECB|ccb->ccb_h.target_id); - - callout_reset_sbt(&ecb->timer, SBT_1MS * ccb->ccb_h.timeout, 0, - ahbtimeout, ecb, 0); -} - -static void -ahbaction(struct cam_sim *sim, union ccb *ccb) -{ - struct ahb_softc *ahb; - - CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE, ("ahbaction\n")); - - ahb = (struct ahb_softc *)cam_sim_softc(sim); - mtx_assert(&ahb->lock, MA_OWNED); - - switch (ccb->ccb_h.func_code) { - /* Common cases first */ - case XPT_SCSI_IO: /* Execute the requested I/O operation */ - { - struct ecb *ecb; - struct hardware_ecb *hecb; - int error; - - /* - * get an ecb to use. - */ - if ((ecb = ahbecbget(ahb)) == NULL) { - /* Should never occur */ - panic("Failed to get an ecb"); - } - - /* - * So we can find the ECB when an abort is requested - */ - ecb->ccb = ccb; - ccb->ccb_h.ccb_ecb_ptr = ecb; - ccb->ccb_h.ccb_ahb_ptr = ahb; - - /* - * Put all the arguments for the xfer in the ecb - */ - hecb = &ecb->hecb; - hecb->opcode = ECBOP_INITIATOR_SCSI_CMD; - hecb->flag_word1 = FW1_AUTO_REQUEST_SENSE - | FW1_ERR_STATUS_BLK_ONLY; - hecb->flag_word2 = ccb->ccb_h.target_lun - | FW2_NO_RETRY_ON_BUSY; - if ((ccb->ccb_h.flags & CAM_TAG_ACTION_VALID) != 0) { - hecb->flag_word2 |= FW2_TAG_ENB - | ((ccb->csio.tag_action & 0x3) - << FW2_TAG_TYPE_SHIFT); - } - if ((ccb->ccb_h.flags & CAM_DIS_DISCONNECT) != 0) - hecb->flag_word2 |= FW2_DISABLE_DISC; - hecb->sense_len = ccb->csio.sense_len; - hecb->cdb_len = ccb->csio.cdb_len; - if ((ccb->ccb_h.flags & CAM_CDB_POINTER) != 0) { - if ((ccb->ccb_h.flags & CAM_CDB_PHYS) == 0) { - bcopy(ccb->csio.cdb_io.cdb_ptr, - hecb->cdb, hecb->cdb_len); - } else { - /* I guess I could map it in... */ - ccb->ccb_h.status = CAM_REQ_INVALID; - ahbecbfree(ahb, ecb); - xpt_done(ccb); - return; - } - } else { - bcopy(ccb->csio.cdb_io.cdb_bytes, - hecb->cdb, hecb->cdb_len); - } - - error = bus_dmamap_load_ccb( - ahb->buffer_dmat, - ecb->dmamap, - ccb, - ahbexecuteecb, - ecb, /*flags*/0); - if (error == EINPROGRESS) { - /* - * So as to maintain ordering, freeze the controller - * queue until our mapping is returned. - */ - xpt_freeze_simq(ahb->sim, 1); - ccb->ccb_h.status |= CAM_RELEASE_SIMQ; - } - break; - } - case XPT_EN_LUN: /* Enable LUN as a target */ - case XPT_TARGET_IO: /* Execute target I/O request */ - case XPT_ACCEPT_TARGET_IO: /* Accept Host Target Mode CDB */ - case XPT_CONT_TARGET_IO: /* Continue Host Target I/O Connection*/ - case XPT_ABORT: /* Abort the specified CCB */ - /* XXX Implement */ - ccb->ccb_h.status = CAM_REQ_INVALID; - xpt_done(ccb); - break; - case XPT_SET_TRAN_SETTINGS: - { - ccb->ccb_h.status = CAM_FUNC_NOTAVAIL; - xpt_done(ccb); - break; - } - case XPT_GET_TRAN_SETTINGS: - /* Get default/user set transfer settings for the target */ - { - struct ccb_trans_settings *cts = &ccb->cts; - u_int target_mask = 0x01 << ccb->ccb_h.target_id; - struct ccb_trans_settings_scsi *scsi = - &cts->proto_specific.scsi; - struct ccb_trans_settings_spi *spi = - &cts->xport_specific.spi; - - if (cts->type == CTS_TYPE_USER_SETTINGS) { - cts->protocol = PROTO_SCSI; - cts->protocol_version = SCSI_REV_2; - cts->transport = XPORT_SPI; - cts->transport_version = 2; - - scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB; - spi->flags &= ~CTS_SPI_FLAGS_DISC_ENB; - if ((ahb->disc_permitted & target_mask) != 0) - spi->flags |= CTS_SPI_FLAGS_DISC_ENB; - if ((ahb->tags_permitted & target_mask) != 0) - scsi->flags |= CTS_SCSI_FLAGS_TAG_ENB; - spi->bus_width = MSG_EXT_WDTR_BUS_8_BIT; - spi->sync_period = 25; /* 10MHz */ - - if (spi->sync_period != 0) - spi->sync_offset = 15; - - spi->valid = CTS_SPI_VALID_SYNC_RATE - | CTS_SPI_VALID_SYNC_OFFSET - | CTS_SPI_VALID_BUS_WIDTH - | CTS_SPI_VALID_DISC; - scsi->valid = CTS_SCSI_VALID_TQ; - ccb->ccb_h.status = CAM_REQ_CMP; - } else { - ccb->ccb_h.status = CAM_FUNC_NOTAVAIL; - } - xpt_done(ccb); - break; - } - case XPT_RESET_DEV: /* Bus Device Reset the specified SCSI device */ - { - int i; - - ahb->immed_cmd = IMMED_RESET; - ahbqueuembox(ahb, IMMED_RESET, ATTN_IMMED|ccb->ccb_h.target_id); - /* Poll for interrupt completion */ - for (i = 1000; ahb->immed_cmd != 0 && i != 0; i--) { - DELAY(1000); - ahbintr_locked(cam_sim_softc(sim)); - } - break; - } - case XPT_CALC_GEOMETRY: - { - cam_calc_geometry(&ccb->ccg, ahb->extended_trans); - xpt_done(ccb); - break; - } - case XPT_RESET_BUS: /* Reset the specified SCSI bus */ - { - int i; - - ahb->immed_cmd = IMMED_RESET; - ahbqueuembox(ahb, IMMED_RESET, ATTN_IMMED|ahb->scsi_id); - /* Poll for interrupt completion */ - for (i = 1000; ahb->immed_cmd != 0 && i != 0; i--) - DELAY(1000); - ccb->ccb_h.status = CAM_REQ_CMP; - xpt_done(ccb); - break; - } - case XPT_TERM_IO: /* Terminate the I/O process */ - /* XXX Implement */ - ccb->ccb_h.status = CAM_REQ_INVALID; - xpt_done(ccb); - break; - case XPT_PATH_INQ: /* Path routing inquiry */ - { - struct ccb_pathinq *cpi = &ccb->cpi; - - cpi->version_num = 1; /* XXX??? */ - cpi->hba_inquiry = PI_SDTR_ABLE|PI_TAG_ABLE; - cpi->target_sprt = 0; - cpi->hba_misc = 0; - cpi->hba_eng_cnt = 0; - cpi->max_target = 7; - cpi->max_lun = 7; - cpi->initiator_id = ahb->scsi_id; - cpi->bus_id = cam_sim_bus(sim); - cpi->base_transfer_speed = 3300; - strlcpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN); - strlcpy(cpi->hba_vid, "Adaptec", HBA_IDLEN); - strlcpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN); - cpi->unit_number = cam_sim_unit(sim); - cpi->transport = XPORT_SPI; - cpi->transport_version = 2; - cpi->protocol = PROTO_SCSI; - cpi->protocol_version = SCSI_REV_2; - cpi->ccb_h.status = CAM_REQ_CMP; - xpt_done(ccb); - break; - } -#if 0 - /* Need these??? */ - case XPT_IMMED_NOTIFY: /* Notify Host Target driver of event */ - case XPT_NOTIFY_ACK: /* Acknowledgement of event */ -#endif - default: - ccb->ccb_h.status = CAM_REQ_INVALID; - xpt_done(ccb); - break; - } -} - -static void -ahbpoll(struct cam_sim *sim) -{ - ahbintr(cam_sim_softc(sim)); -} - -static void -ahbtimeout(void *arg) -{ - struct ecb *ecb; - union ccb *ccb; - struct ahb_softc *ahb; - - ecb = (struct ecb *)arg; - ccb = ecb->ccb; - ahb = (struct ahb_softc *)ccb->ccb_h.ccb_ahb_ptr; - mtx_assert(&ahb->lock, MA_OWNED); - xpt_print_path(ccb->ccb_h.path); - printf("ECB %p - timed out\n", (void *)ecb); - - if ((ecb->state & ECB_ACTIVE) == 0) { - xpt_print_path(ccb->ccb_h.path); - printf("ECB %p - timed out ECB already completed\n", - (void *)ecb); - return; - } - /* - * In order to simplify the recovery process, we ask the XPT - * layer to halt the queue of new transactions and we traverse - * the list of pending CCBs and remove their timeouts. This - * means that the driver attempts to clear only one error - * condition at a time. In general, timeouts that occur - * close together are related anyway, so there is no benefit - * in attempting to handle errors in parallel. Timeouts will - * be reinstated when the recovery process ends. - */ - if ((ecb->state & ECB_DEVICE_RESET) == 0) { - struct ccb_hdr *ccb_h; - - if ((ecb->state & ECB_RELEASE_SIMQ) == 0) { - xpt_freeze_simq(ahb->sim, /*count*/1); - ecb->state |= ECB_RELEASE_SIMQ; - } - - LIST_FOREACH(ccb_h, &ahb->pending_ccbs, sim_links.le) { - struct ecb *pending_ecb; - - pending_ecb = (struct ecb *)ccb_h->ccb_ecb_ptr; - callout_stop(&pending_ecb->timer); - } - - /* Store for our interrupt handler */ - ahb->immed_ecb = ecb; - - /* - * Send a Bus Device Reset message: - * The target that is holding up the bus may not - * be the same as the one that triggered this timeout - * (different commands have different timeout lengths), - * but we have no way of determining this from our - * timeout handler. Our strategy here is to queue a - * BDR message to the target of the timed out command. - * If this fails, we'll get another timeout 2 seconds - * later which will attempt a bus reset. - */ - xpt_print_path(ccb->ccb_h.path); - printf("Queuing BDR\n"); - ecb->state |= ECB_DEVICE_RESET; - callout_reset(&ecb->timer, 2 * hz, ahbtimeout, ecb); - - ahb->immed_cmd = IMMED_RESET; - ahbqueuembox(ahb, IMMED_RESET, ATTN_IMMED|ccb->ccb_h.target_id); - } else if ((ecb->state & ECB_SCSIBUS_RESET) != 0) { - /* - * Try a SCSI bus reset. We do this only if we - * have already attempted to clear the condition with a BDR. - */ - xpt_print_path(ccb->ccb_h.path); - printf("Attempting SCSI Bus reset\n"); - ecb->state |= ECB_SCSIBUS_RESET; - callout_reset(&ecb->timer, 2 * hz, ahbtimeout, ecb); - ahb->immed_cmd = IMMED_RESET; - ahbqueuembox(ahb, IMMED_RESET, ATTN_IMMED|ahb->scsi_id); - } else { - /* Bring out the hammer... */ - ahbreset(ahb); - - /* Simulate the reset complete interrupt */ - ahbhandleimmed(ahb, 0, ahb->scsi_id|INTSTAT_IMMED_OK); - } -} - -static device_method_t ahb_eisa_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, ahbprobe), - DEVMETHOD(device_attach, ahbattach), - - { 0, 0 } -}; - -static driver_t ahb_eisa_driver = { - "ahb", - ahb_eisa_methods, - sizeof(struct ahb_softc), -}; - -static devclass_t ahb_devclass; - -DRIVER_MODULE(ahb, eisa, ahb_eisa_driver, ahb_devclass, 0, 0); -MODULE_DEPEND(ahb, eisa, 1, 1, 1); -MODULE_DEPEND(ahb, cam, 1, 1, 1); diff --git a/sys/dev/ahb/ahbreg.h b/sys/dev/ahb/ahbreg.h deleted file mode 100644 index dabf409a3d8f..000000000000 --- a/sys/dev/ahb/ahbreg.h +++ /dev/null @@ -1,284 +0,0 @@ -/*- - * Hardware structure definitions for the Adaptec 174X CAM SCSI device driver. - * - * Copyright (c) 1998 Justin T. Gibbs - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice immediately at the beginning of the file, without modification, - * this list of conditions, and the following disclaimer. - * 2. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $FreeBSD$ - */ - -/* Resource Constatns */ -#define AHB_NECB 64 -#define AHB_NSEG 32 - -/* AHA1740 EISA ID, IO port range size, and offset from slot base */ -#define EISA_DEVICE_ID_ADAPTEC_1740 0x04900000 -#define AHB_EISA_IOSIZE 0x100 -#define AHB_EISA_SLOT_OFFSET 0xc00 - -/* AHA1740 EISA board control registers (Offset from slot base) */ -#define EBCTRL 0x084 -#define CDEN 0x01 - -/* - * AHA1740 EISA board mode registers (Offset from slot base) - */ -#define PORTADDR 0x0C0 -#define PORTADDR_ENHANCED 0x80 - -#define BIOSADDR 0x0C1 - -#define INTDEF 0x0C2 -#define INT9 0x00 -#define INT10 0x01 -#define INT11 0x02 -#define INT12 0x03 -#define INT14 0x05 -#define INT15 0x06 -#define INTLEVEL 0x08 -#define INTEN 0x10 - -#define SCSIDEF 0x0C3 -#define HSCSIID 0x0F /* our SCSI ID */ -#define RSTBUS 0x10 - -#define BUSDEF 0x0C4 -#define B0uS 0x00 /* give up bus immediately */ -#define B4uS 0x01 /* delay 4uSec. */ -#define B8uS 0x02 /* delay 8uSec. */ - -#define RESV0 0x0C5 - -#define RESV1 0x0C6 -#define EXTENDED_TRANS 0x01 - -#define RESV2 0x0C7 - -/* - * AHA1740 ENHANCED mode mailbox control regs (Offset from slot base) - */ -#define MBOXOUT0 0x0D0 -#define MBOXOUT1 0x0D1 -#define MBOXOUT2 0x0D2 -#define MBOXOUT3 0x0D3 - -#define ATTN 0x0D4 -#define ATTN_TARGMASK 0x0F -#define ATTN_IMMED 0x10 -#define ATTN_STARTECB 0x40 -#define ATTN_ABORTECB 0x50 -#define ATTN_TARG_RESET 0x80 - -#define CONTROL 0x0D5 -#define CNTRL_SET_HRDY 0x20 -#define CNTRL_CLRINT 0x40 -#define CNTRL_HARD_RST 0x80 - -#define INTSTAT 0x0D6 -#define INTSTAT_TARGET_MASK 0x0F -#define INTSTAT_MASK 0xF0 -#define INTSTAT_ECB_OK 0x10 /* ECB Completed w/out error */ -#define INTSTAT_ECB_CMPWRETRY 0x50 /* ECB Completed w/retries */ -#define INTSTAT_HW_ERR 0x70 /* Adapter Hardware Failure */ -#define INTSTAT_IMMED_OK 0xA0 /* Immediate command complete */ -#define INTSTAT_ECB_CMPWERR 0xC0 /* ECB Completed w/error */ -#define INTSTAT_AEN_OCCURED 0xD0 /* Async Event Notification */ -#define INTSTAT_IMMED_ERR 0xE0 /* Immediate command failed */ - -#define HOSTSTAT 0x0D7 -#define HOSTSTAT_MBOX_EMPTY 0x04 -#define HOSTSTAT_INTPEND 0x02 -#define HOSTSTAT_BUSY 0x01 - - -#define MBOXIN0 0x0D8 -#define MBOXIN1 0x0D9 -#define MBOXIN2 0x0DA -#define MBOXIN3 0x0DB - -#define STATUS2 0x0DC -#define STATUS2_HOST_READY 0x01 - -typedef enum { - IMMED_RESET = 0x000080, - IMMED_DEVICE_CLEAR_QUEUE = 0x000480, - IMMED_ADAPTER_CLEAR_QUEUE = 0x000880, - IMMED_RESUME = 0x200090 -} immed_cmd; - -struct ecb_status { - /* Status Flags */ - u_int16_t no_error :1, /* Completed with no error */ - data_underrun :1, - :1, - ha_queue_full :1, - spec_check :1, - data_overrun :1, - chain_halted :1, - intr_issued :1, - status_avail :1, /* status bytes 14-31 are valid */ - sense_stored :1, - :1, - init_requied :1, - major_error :1, - :1, - extended_ca :1, - :1; - /* Host Status */ - u_int8_t ha_status; - u_int8_t scsi_status; - int32_t resid_count; - u_int32_t resid_addr; - u_int16_t addit_status; - u_int8_t sense_len; - u_int8_t unused[9]; - u_int8_t cdb[6]; -}; - -typedef enum { - HS_OK = 0x00, - HS_CMD_ABORTED_HOST = 0x04, - HS_CMD_ABORTED_ADAPTER = 0x05, - HS_FIRMWARE_LOAD_REQ = 0x08, - HS_TARGET_NOT_ASSIGNED = 0x0A, - HS_SEL_TIMEOUT = 0x11, - HS_DATA_RUN_ERR = 0x12, - HS_UNEXPECTED_BUSFREE = 0x13, - HS_INVALID_PHASE = 0x14, - HS_INVALID_OPCODE = 0x16, - HS_INVALID_CMD_LINK = 0x17, - HS_INVALID_ECB_PARAM = 0x18, - HS_DUP_TCB_RECEIVED = 0x19, - HS_REQUEST_SENSE_FAILED = 0x1A, - HS_TAG_MSG_REJECTED = 0x1C, - HS_HARDWARE_ERR = 0x20, - HS_ATN_TARGET_FAILED = 0x21, - HS_SCSI_RESET_ADAPTER = 0x22, - HS_SCSI_RESET_INCOMING = 0x23, - HS_PROGRAM_CKSUM_ERROR = 0x80 -} host_status; - -typedef enum { - ECBOP_NOP = 0x00, - ECBOP_INITIATOR_SCSI_CMD = 0x01, - ECBOP_RUN_DIAGNOSTICS = 0x05, - ECBOP_INITIALIZE_SCSI = 0x06, /* Set syncrate/disc/parity */ - ECBOP_READ_SENSE = 0x08, - ECBOP_DOWNLOAD_FIRMWARE = 0x09, - ECBOP_READ_HA_INQDATA = 0x0a, - ECBOP_TARGET_SCSI_CMD = 0x10 -} ecb_op; - -struct ha_inquiry_data { - struct scsi_inquiry_data scsi_data; - u_int8_t release_date[8]; - u_int8_t release_time[8]; - u_int16_t firmware_cksum; - u_int16_t reserved; - u_int16_t target_data[16]; -}; - -struct hardware_ecb { - u_int16_t opcode; - u_int16_t flag_word1; -#define FW1_LINKED_CMD 0x0001 -#define FW1_DISABLE_INTR 0x0080 -#define FW1_SUPPRESS_URUN_ERR 0x0400 -#define FW1_SG_ECB 0x1000 -#define FW1_ERR_STATUS_BLK_ONLY 0x4000 -#define FW1_AUTO_REQUEST_SENSE 0x8000 - u_int16_t flag_word2; -#define FW2_LUN_MASK 0x0007 -#define FW2_TAG_ENB 0x0008 -#define FW2_TAG_TYPE 0x0030 -#define FW2_TAG_TYPE_SHIFT 4 -#define FW2_DISABLE_DISC 0x0040 -#define FW2_CHECK_DATA_DIR 0x0100 -#define FW2_DATA_DIR_IN 0x0200 -#define FW2_SUPRESS_TRANSFER 0x0400 -#define FW2_CALC_CKSUM 0x0800 -#define FW2_RECOVERY_ECB 0x4000 -#define FW2_NO_RETRY_ON_BUSY 0x8000 - u_int16_t reserved; - u_int32_t data_ptr; - u_int32_t data_len; - u_int32_t status_ptr; - u_int32_t link_ptr; - u_int32_t reserved2; - u_int32_t sense_ptr; - u_int8_t sense_len; - u_int8_t cdb_len; - u_int16_t cksum; - u_int8_t cdb[12]; -}; - -typedef struct { - u_int32_t addr; - u_int32_t len; -} ahb_sg_t; - -typedef enum { - ECB_FREE = 0x0, - ECB_ACTIVE = 0x1, - ECB_DEVICE_RESET = 0x2, - ECB_SCSIBUS_RESET = 0x4, - ECB_RELEASE_SIMQ = 0x8 -} ecb_state; - -struct ecb { - struct hardware_ecb hecb; - struct ecb_status status; - struct scsi_sense_data sense; - ahb_sg_t sg_list[AHB_NSEG]; - SLIST_ENTRY(ecb) links; - ecb_state state; - union ccb *ccb; - bus_dmamap_t dmamap; - struct callout timer; -}; - -struct ahb_softc { - device_t dev; - struct resource *res; - struct mtx lock; - struct cam_sim *sim; - struct cam_path *path; - SLIST_HEAD(,ecb) free_ecbs; - LIST_HEAD(,ccb_hdr) pending_ccbs; - struct ecb *ecb_array; - u_int32_t ecb_physbase; - bus_dma_tag_t buffer_dmat; /* dmat for buffer I/O */ - bus_dma_tag_t ecb_dmat; /* dmat for our ecb array */ - bus_dmamap_t ecb_dmamap; - volatile u_int32_t immed_cmd; - struct ecb *immed_ecb; - struct ha_inquiry_data *ha_inq_data; - u_int32_t ha_inq_physbase; - u_int init_level; - u_int scsi_id; - u_int num_ecbs; - u_int extended_trans; - u_int8_t disc_permitted; - u_int8_t tags_permitted; -}; diff --git a/sys/modules/Makefile b/sys/modules/Makefile index 20f23387648f..976690e97992 100644 --- a/sys/modules/Makefile +++ b/sys/modules/Makefile @@ -27,7 +27,6 @@ SUBDIR= \ age \ ${_agp} \ aha \ - ${_ahb} \ ahci \ ${_aic} \ aic7xxx \ @@ -736,9 +735,6 @@ _sbni= sbni _streams= streams _stg= stg _svr4= svr4 -.if ${MK_EISA} != "no" -_ahb= ahb -.endif _cm= cm .if ${MK_SOURCELESS_UCODE} != "no" _ctau= ctau diff --git a/sys/modules/ahb/Makefile b/sys/modules/ahb/Makefile deleted file mode 100644 index f3d7498d6c2d..000000000000 --- a/sys/modules/ahb/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -# $FreeBSD$ - -.PATH: ${.CURDIR}/../../dev/ahb - -KMOD= ahb -SRCS= ahb.c opt_cam.h device_if.h bus_if.h eisa_if.h - -.include