diff options
-rw-r--r-- | sys/dev/aic7xxx/ahc_eisa.c | 6 | ||||
-rw-r--r-- | sys/dev/aic7xxx/ahc_pci.c | 72 | ||||
-rw-r--r-- | sys/dev/aic7xxx/ahd_pci.c | 59 | ||||
-rw-r--r-- | sys/dev/aic7xxx/aic7770.c | 9 | ||||
-rw-r--r-- | sys/dev/aic7xxx/aic79xx.c | 1092 | ||||
-rw-r--r-- | sys/dev/aic7xxx/aic79xx.h | 42 | ||||
-rw-r--r-- | sys/dev/aic7xxx/aic79xx.seq | 143 | ||||
-rw-r--r-- | sys/dev/aic7xxx/aic79xx_inline.h | 67 | ||||
-rw-r--r-- | sys/dev/aic7xxx/aic79xx_osm.c | 363 | ||||
-rw-r--r-- | sys/dev/aic7xxx/aic79xx_osm.h | 328 | ||||
-rw-r--r-- | sys/dev/aic7xxx/aic79xx_pci.c | 110 | ||||
-rw-r--r-- | sys/dev/aic7xxx/aic7xxx.c | 576 | ||||
-rw-r--r-- | sys/dev/aic7xxx/aic7xxx.h | 35 | ||||
-rw-r--r-- | sys/dev/aic7xxx/aic7xxx.reg | 4 | ||||
-rw-r--r-- | sys/dev/aic7xxx/aic7xxx.seq | 5 | ||||
-rw-r--r-- | sys/dev/aic7xxx/aic7xxx_93cx6.c | 38 | ||||
-rw-r--r-- | sys/dev/aic7xxx/aic7xxx_inline.h | 26 | ||||
-rw-r--r-- | sys/dev/aic7xxx/aic7xxx_osm.c | 379 | ||||
-rw-r--r-- | sys/dev/aic7xxx/aic7xxx_osm.h | 314 | ||||
-rw-r--r-- | sys/dev/aic7xxx/aic7xxx_pci.c | 169 | ||||
-rw-r--r-- | sys/dev/aic7xxx/aic_osm_lib.c | 169 | ||||
-rw-r--r-- | sys/dev/aic7xxx/aic_osm_lib.h | 426 |
22 files changed, 2267 insertions, 2165 deletions
diff --git a/sys/dev/aic7xxx/ahc_eisa.c b/sys/dev/aic7xxx/ahc_eisa.c index 84b8b03..d51fcdf 100644 --- a/sys/dev/aic7xxx/ahc_eisa.c +++ b/sys/dev/aic7xxx/ahc_eisa.c @@ -26,7 +26,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: ahc_eisa.c,v 1.29 2003/05/03 23:27:57 gibbs Exp $ + * $Id: //depot/aic7xxx/freebsd/dev/aic7xxx/ahc_eisa.c#13 $ */ #include <sys/cdefs.h> @@ -132,7 +132,7 @@ aic7770_attach(device_t dev) /* Allocate a dmatag for our SCB DMA maps */ /* XXX Should be a child of the PCI bus dma tag */ - error = bus_dma_tag_create(/*parent*/NULL, /*alignment*/1, + error = aic_dma_tag_create(ahc, /*parent*/NULL, /*alignment*/1, /*boundary*/0, /*lowaddr*/BUS_SPACE_MAXADDR_32BIT, /*highaddr*/BUS_SPACE_MAXADDR, @@ -141,8 +141,6 @@ aic7770_attach(device_t dev) /*nsegments*/AHC_NSEG, /*maxsegsz*/AHC_MAXTRANSFER_SIZE, /*flags*/0, - /*lockfunc*/busdma_lock_mutex, - /*lockarg*/&Giant, &ahc->parent_dmat); if (error != 0) { diff --git a/sys/dev/aic7xxx/ahc_pci.c b/sys/dev/aic7xxx/ahc_pci.c index aca087b..86e0a60 100644 --- a/sys/dev/aic7xxx/ahc_pci.c +++ b/sys/dev/aic7xxx/ahc_pci.c @@ -28,7 +28,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: ahc_pci.c,v 1.58 2003/11/03 09:22:16 dfr Exp $ + * $Id: //depot/aic7xxx/freebsd/dev/aic7xxx/ahc_pci.c#19 $ */ #include <sys/cdefs.h> @@ -36,9 +36,6 @@ __FBSDID("$FreeBSD$"); #include <dev/aic7xxx/aic7xxx_osm.h> -#define AHC_PCI_IOADDR PCIR_BAR(0) /* I/O Address */ -#define AHC_PCI_MEMADDR PCIR_BAR(1) /* Mem I/O Address */ - static int ahc_pci_probe(device_t dev); static int ahc_pci_attach(device_t dev); @@ -110,7 +107,7 @@ ahc_pci_attach(device_t dev) /* Allocate a dmatag for our SCB DMA maps */ /* XXX Should be a child of the PCI bus dma tag */ - error = bus_dma_tag_create(/*parent*/NULL, /*alignment*/1, + error = aic_dma_tag_create(ahc, /*parent*/NULL, /*alignment*/1, /*boundary*/0, (ahc->flags & AHC_39BIT_ADDRESSING) ? 0x7FFFFFFFFFLL @@ -121,8 +118,6 @@ ahc_pci_attach(device_t dev) /*nsegments*/AHC_NSEG, /*maxsegsz*/AHC_MAXTRANSFER_SIZE, /*flags*/0, - /*lockfunc*/busdma_lock_mutex, - /*lockarg*/&Giant, &ahc->parent_dmat); if (error != 0) { @@ -151,7 +146,7 @@ ahc_pci_map_registers(struct ahc_softc *ahc) int regs_id; int allow_memio; - command = ahc_pci_read_config(ahc->dev_softc, PCIR_COMMAND, /*bytes*/1); + command = aic_pci_read_config(ahc->dev_softc, PCIR_COMMAND, /*bytes*/1); regs = NULL; regs_type = 0; regs_id = 0; @@ -191,15 +186,15 @@ ahc_pci_map_registers(struct ahc_softc *ahc) device_printf(ahc->dev_softc, "PCI Device %d:%d:%d failed memory " "mapped test. Using PIO.\n", - ahc_get_pci_bus(ahc->dev_softc), - ahc_get_pci_slot(ahc->dev_softc), - ahc_get_pci_function(ahc->dev_softc)); + aic_get_pci_bus(ahc->dev_softc), + aic_get_pci_slot(ahc->dev_softc), + aic_get_pci_function(ahc->dev_softc)); bus_release_resource(ahc->dev_softc, regs_type, regs_id, regs); regs = NULL; } else { command &= ~PCIM_CMD_PORTEN; - ahc_pci_write_config(ahc->dev_softc, + aic_pci_write_config(ahc->dev_softc, PCIR_COMMAND, command, /*bytes*/1); } @@ -214,9 +209,22 @@ ahc_pci_map_registers(struct ahc_softc *ahc) if (regs != NULL) { ahc->tag = rman_get_bustag(regs); ahc->bsh = rman_get_bushandle(regs); - command &= ~PCIM_CMD_MEMEN; - ahc_pci_write_config(ahc->dev_softc, PCIR_COMMAND, - command, /*bytes*/1); + if (ahc_pci_test_register_access(ahc) != 0) { + device_printf(ahc->dev_softc, + "PCI Device %d:%d:%d failed I/O " + "mapped test.\n", + aic_get_pci_bus(ahc->dev_softc), + aic_get_pci_slot(ahc->dev_softc), + aic_get_pci_function(ahc->dev_softc)); + bus_release_resource(ahc->dev_softc, regs_type, + regs_id, regs); + regs = NULL; + } else { + command &= ~PCIM_CMD_MEMEN; + aic_pci_write_config(ahc->dev_softc, + PCIR_COMMAND, + command, /*bytes*/1); + } } } if (regs == NULL) { @@ -248,37 +256,3 @@ ahc_pci_map_int(struct ahc_softc *ahc) return (ahc_map_int(ahc)); } -void -ahc_power_state_change(struct ahc_softc *ahc, ahc_power_state new_state) -{ - uint32_t cap; - u_int cap_offset; - - /* - * Traverse the capability list looking for - * the power management capability. - */ - cap = 0; - cap_offset = ahc_pci_read_config(ahc->dev_softc, - PCIR_CAP_PTR, /*bytes*/1); - while (cap_offset != 0) { - - cap = ahc_pci_read_config(ahc->dev_softc, - cap_offset, /*bytes*/4); - if ((cap & 0xFF) == 1 - && ((cap >> 16) & 0x3) > 0) { - uint32_t pm_control; - - pm_control = ahc_pci_read_config(ahc->dev_softc, - cap_offset + 4, - /*bytes*/2); - pm_control &= ~0x3; - pm_control |= new_state; - ahc_pci_write_config(ahc->dev_softc, - cap_offset + 4, - pm_control, /*bytes*/2); - break; - } - cap_offset = (cap >> 8) & 0xFF; - } -} diff --git a/sys/dev/aic7xxx/ahd_pci.c b/sys/dev/aic7xxx/ahd_pci.c index 8abc074..24cd5ab 100644 --- a/sys/dev/aic7xxx/ahd_pci.c +++ b/sys/dev/aic7xxx/ahd_pci.c @@ -28,7 +28,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: ahd_pci.c,v 1.13 2003/11/03 09:22:17 dfr Exp $ + * $Id: //depot/aic7xxx/freebsd/dev/aic7xxx/ahd_pci.c#17 $ */ #include <sys/cdefs.h> @@ -36,10 +36,6 @@ __FBSDID("$FreeBSD$"); #include <dev/aic7xxx/aic79xx_osm.h> -#define AHD_PCI_IOADDR0 PCIR_BAR(0) /* Primary I/O BAR */ -#define AHD_PCI_MEMADDR PCIR_BAR(1) /* Mem I/O Address */ -#define AHD_PCI_IOADDR1 PCIR_BAR(3) /* Secondary I/O BAR */ - static int ahd_pci_probe(device_t dev); static int ahd_pci_attach(device_t dev); @@ -113,10 +109,10 @@ ahd_pci_attach(device_t dev) /* Allocate a dmatag for our SCB DMA maps */ /* XXX Should be a child of the PCI bus dma tag */ - error = bus_dma_tag_create(/*parent*/NULL, /*alignment*/1, + error = aic_dma_tag_create(ahd, /*parent*/NULL, /*alignment*/1, /*boundary*/0, (ahd->flags & AHD_39BIT_ADDRESSING) - ? 0x7FFFFFFFFFLL + ? 0x7FFFFFFFFF : BUS_SPACE_MAXADDR_32BIT, /*highaddr*/BUS_SPACE_MAXADDR, /*filter*/NULL, /*filterarg*/NULL, @@ -124,8 +120,6 @@ ahd_pci_attach(device_t dev) /*nsegments*/AHD_NSEG, /*maxsegsz*/AHD_MAXTRANSFER_SIZE, /*flags*/0, - /*lockfunc*/busdma_lock_mutex, - /*lockarg*/&Giant, &ahd->parent_dmat); if (error != 0) { @@ -156,7 +150,7 @@ ahd_pci_map_registers(struct ahd_softc *ahd) int regs_id2; int allow_memio; - command = ahd_pci_read_config(ahd->dev_softc, PCIR_COMMAND, /*bytes*/1); + command = aic_pci_read_config(ahd->dev_softc, PCIR_COMMAND, /*bytes*/1); regs = NULL; regs2 = NULL; regs_type = 0; @@ -198,15 +192,15 @@ ahd_pci_map_registers(struct ahd_softc *ahd) device_printf(ahd->dev_softc, "PCI Device %d:%d:%d failed memory " "mapped test. Using PIO.\n", - ahd_get_pci_bus(ahd->dev_softc), - ahd_get_pci_slot(ahd->dev_softc), - ahd_get_pci_function(ahd->dev_softc)); + aic_get_pci_bus(ahd->dev_softc), + aic_get_pci_slot(ahd->dev_softc), + aic_get_pci_function(ahd->dev_softc)); bus_release_resource(ahd->dev_softc, regs_type, regs_id, regs); regs = NULL; } else { command &= ~PCIM_CMD_PORTEN; - ahd_pci_write_config(ahd->dev_softc, + aic_pci_write_config(ahd->dev_softc, PCIR_COMMAND, command, /*bytes*/1); } @@ -237,7 +231,7 @@ ahd_pci_map_registers(struct ahd_softc *ahd) ahd->tags[1] = rman_get_bustag(regs2); ahd->bshs[1] = rman_get_bushandle(regs2); command &= ~PCIM_CMD_MEMEN; - ahd_pci_write_config(ahd->dev_softc, PCIR_COMMAND, + aic_pci_write_config(ahd->dev_softc, PCIR_COMMAND, command, /*bytes*/1); ahd->platform_data->regs_res_type[1] = regs_type; ahd->platform_data->regs_res_id[1] = regs_id2; @@ -263,38 +257,3 @@ ahd_pci_map_int(struct ahd_softc *ahd) ahd->platform_data->irq_res_type = SYS_RES_IRQ; return (ahd_map_int(ahd)); } - -void -ahd_power_state_change(struct ahd_softc *ahd, ahd_power_state new_state) -{ - uint32_t cap; - u_int cap_offset; - - /* - * Traverse the capability list looking for - * the power management capability. - */ - cap = 0; - cap_offset = ahd_pci_read_config(ahd->dev_softc, - PCIR_CAP_PTR, /*bytes*/1); - while (cap_offset != 0) { - - cap = ahd_pci_read_config(ahd->dev_softc, - cap_offset, /*bytes*/4); - if ((cap & 0xFF) == 1 - && ((cap >> 16) & 0x3) > 0) { - uint32_t pm_control; - - pm_control = ahd_pci_read_config(ahd->dev_softc, - cap_offset + 4, - /*bytes*/2); - pm_control &= ~0x3; - pm_control |= new_state; - ahd_pci_write_config(ahd->dev_softc, - cap_offset + 4, - pm_control, /*bytes*/2); - break; - } - cap_offset = (cap >> 8) & 0xFF; - } -} diff --git a/sys/dev/aic7xxx/aic7770.c b/sys/dev/aic7xxx/aic7770.c index e8a457a..dfd67bd 100644 --- a/sys/dev/aic7xxx/aic7770.c +++ b/sys/dev/aic7xxx/aic7770.c @@ -37,17 +37,16 @@ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * - * $Id: //depot/aic7xxx/aic7xxx/aic7770.c#32 $ + * $Id: //depot/aic7xxx/aic7xxx/aic7770.c#34 $ */ -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - #ifdef __linux__ #include "aic7xxx_osm.h" #include "aic7xxx_inline.h" #include "aic7xxx_93cx6.h" #else +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); #include <dev/aic7xxx/aic7xxx_osm.h> #include <dev/aic7xxx/aic7xxx_inline.h> #include <dev/aic7xxx/aic7xxx_93cx6.h> @@ -176,7 +175,7 @@ aic7770_config(struct ahc_softc *ahc, struct aic7770_identity *entry, u_int io) case 15: break; default: - printf("aic7770_config: illegal irq setting %d\n", intdef); + printf("aic7770_config: invalid irq setting %d\n", intdef); return (ENXIO); } diff --git a/sys/dev/aic7xxx/aic79xx.c b/sys/dev/aic7xxx/aic79xx.c index 14092d2..b00700a 100644 --- a/sys/dev/aic7xxx/aic79xx.c +++ b/sys/dev/aic7xxx/aic79xx.c @@ -37,17 +37,16 @@ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * - * $Id: //depot/aic7xxx/aic7xxx/aic79xx.c#202 $ + * $Id: //depot/aic7xxx/aic7xxx/aic79xx.c#223 $ */ -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - #ifdef __linux__ #include "aic79xx_osm.h" #include "aic79xx_inline.h" #include "aicasm/aicasm_insformat.h" #else +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); #include <dev/aic7xxx/aic79xx_osm.h> #include <dev/aic7xxx/aic79xx_inline.h> #include <dev/aic7xxx/aicasm/aicasm_insformat.h> @@ -225,6 +224,9 @@ static u_int ahd_resolve_seqaddr(struct ahd_softc *ahd, static void ahd_download_instr(struct ahd_softc *ahd, u_int instrptr, uint8_t *dconsts); static int ahd_probe_stack_size(struct ahd_softc *ahd); +static void ahd_other_scb_timeout(struct ahd_softc *ahd, + struct scb *scb, + struct scb *other_scb); static int ahd_scb_active_in_fifo(struct ahd_softc *ahd, struct scb *scb); static void ahd_run_data_fifo(struct ahd_softc *ahd, @@ -376,13 +378,7 @@ ahd_flush_qoutfifo(struct ahd_softc *ahd) saved_modes = ahd_save_modes(ahd); /* - * Complete any SCBs that just finished being - * DMA'ed into the qoutfifo. - */ - ahd_run_qoutfifo(ahd); - - /* - * Flush the good status FIFO for compelted packetized commands. + * Flush the good status FIFO for completed packetized commands. */ ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); saved_scbptr = ahd_get_scbptr(ahd); @@ -390,8 +386,7 @@ ahd_flush_qoutfifo(struct ahd_softc *ahd) u_int fifo_mode; u_int i; - scbid = (ahd_inb(ahd, GSFIFO+1) << 8) - | ahd_inb(ahd, GSFIFO); + scbid = ahd_inw(ahd, GSFIFO); scb = ahd_lookup_scb(ahd, scbid); if (scb == NULL) { printf("%s: Warning - GSFIFO SCB %d invalid\n", @@ -404,22 +399,38 @@ ahd_flush_qoutfifo(struct ahd_softc *ahd) * the host before completing the command. */ fifo_mode = 0; +rescan_fifos: for (i = 0; i < 2; i++) { /* Toggle to the other mode. */ fifo_mode ^= 1; ahd_set_modes(ahd, fifo_mode, fifo_mode); - if (ahd_scb_active_in_fifo(ahd, scb) == 0) + if (ahd_scb_active_in_fifo(ahd, scb) != 0) continue; ahd_run_data_fifo(ahd, scb); + if (ahd_scb_active_in_fifo(ahd, scb) != 0) { + /* + * Delay a bit so that status has + * a chance to change before we look + * at this FIFO again. + */ + aic_delay(200); + } + /* - * Clearing this transaction in this FIFO may - * cause a CFG4DATA for this same transaction - * to assert in the other FIFO. Make sure we - * loop one more time and check the other FIFO. + * Running this FIFO may cause a CFG4DATA for + * this same transaction to assert in the other + * FIFO or a new snapshot SAVEPTRS interrupt + * in this FIFO. Even running a FIFO may not + * clear the transaction if we are still waiting + * for data to drain to the host. We must loop + * until the transaction is not active in either + * FIFO just to be sure. Reset our loop counter + * so we will visit both FIFOs again before + * declaring this transaction finished. */ - i = 0; + goto rescan_fifos; } ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); ahd_set_scbptr(ahd, scbid); @@ -432,7 +443,7 @@ ahd_flush_qoutfifo(struct ahd_softc *ahd) /* * The transfer completed with a residual. * Place this SCB on the complete DMA list - * so that we Update our in-core copy of the + * so that we update our in-core copy of the * SCB before completing the command. */ ahd_outb(ahd, SCB_SCSI_STATUS, 0); @@ -442,9 +453,7 @@ ahd_flush_qoutfifo(struct ahd_softc *ahd) ahd_outw(ahd, SCB_TAG, SCB_GET_TAG(scb)); comp_head = ahd_inw(ahd, COMPLETE_DMA_SCB_HEAD); ahd_outw(ahd, SCB_NEXT_COMPLETE, comp_head); - if (SCBID_IS_NULL(comp_head)) - ahd_outw(ahd, COMPLETE_DMA_SCB_HEAD, - SCB_GET_TAG(scb)); + ahd_outw(ahd, COMPLETE_DMA_SCB_HEAD, SCB_GET_TAG(scb)); } else ahd_complete_scb(ahd, scb); } @@ -466,11 +475,24 @@ ahd_flush_qoutfifo(struct ahd_softc *ahd) break; } else if ((ccscbctl & CCSCBDONE) != 0) break; - ahd_delay(200); + aic_delay(200); } - if ((ccscbctl & CCSCBDIR) != 0) + /* + * We leave the sequencer to cleanup in the case of DMA's to + * update the qoutfifo. In all other cases (DMA's to the + * chip or a push of an SCB from the COMPLETE_DMA_SCB list), + * we disable the DMA engine so that the sequencer will not + * attempt to handle the DMA completion. + */ + if ((ccscbctl & CCSCBDIR) != 0 || (ccscbctl & ARRDONE) != 0) ahd_outb(ahd, CCSCBCTL, ccscbctl & ~(CCARREN|CCSCBEN)); + /* + * Complete any SCBs that just finished + * being DMA'ed into the qoutfifo. + */ + ahd_run_qoutfifo(ahd); + saved_scbptr = ahd_get_scbptr(ahd); /* * Manually update/complete any completed SCBs that are waiting to be @@ -561,150 +583,146 @@ ahd_run_data_fifo(struct ahd_softc *ahd, struct scb *scb) { u_int seqintsrc; - while (1) { - seqintsrc = ahd_inb(ahd, SEQINTSRC); - if ((seqintsrc & CFG4DATA) != 0) { - uint32_t datacnt; - uint32_t sgptr; - - /* - * Clear full residual flag. - */ - sgptr = ahd_inl_scbram(ahd, SCB_SGPTR) & ~SG_FULL_RESID; - ahd_outb(ahd, SCB_SGPTR, sgptr); + seqintsrc = ahd_inb(ahd, SEQINTSRC); + if ((seqintsrc & CFG4DATA) != 0) { + uint32_t datacnt; + uint32_t sgptr; - /* - * Load datacnt and address. - */ - datacnt = ahd_inl_scbram(ahd, SCB_DATACNT); - if ((datacnt & AHD_DMA_LAST_SEG) != 0) { - sgptr |= LAST_SEG; - ahd_outb(ahd, SG_STATE, 0); - } else - ahd_outb(ahd, SG_STATE, LOADING_NEEDED); - ahd_outq(ahd, HADDR, ahd_inq_scbram(ahd, SCB_DATAPTR)); - ahd_outl(ahd, HCNT, datacnt & AHD_SG_LEN_MASK); - ahd_outb(ahd, SG_CACHE_PRE, sgptr); - ahd_outb(ahd, DFCNTRL, PRELOADEN|SCSIEN|HDMAEN); + /* + * Clear full residual flag. + */ + sgptr = ahd_inl_scbram(ahd, SCB_SGPTR) & ~SG_FULL_RESID; + ahd_outb(ahd, SCB_SGPTR, sgptr); - /* - * Initialize Residual Fields. - */ - ahd_outb(ahd, SCB_RESIDUAL_DATACNT+3, datacnt >> 24); - ahd_outl(ahd, SCB_RESIDUAL_SGPTR, sgptr & SG_PTR_MASK); + /* + * Load datacnt and address. + */ + datacnt = ahd_inl_scbram(ahd, SCB_DATACNT); + if ((datacnt & AHD_DMA_LAST_SEG) != 0) { + sgptr |= LAST_SEG; + ahd_outb(ahd, SG_STATE, 0); + } else + ahd_outb(ahd, SG_STATE, LOADING_NEEDED); + ahd_outq(ahd, HADDR, ahd_inq_scbram(ahd, SCB_DATAPTR)); + ahd_outl(ahd, HCNT, datacnt & AHD_SG_LEN_MASK); + ahd_outb(ahd, SG_CACHE_PRE, sgptr); + ahd_outb(ahd, DFCNTRL, PRELOADEN|SCSIEN|HDMAEN); - /* - * Mark the SCB as having a FIFO in use. - */ - ahd_outb(ahd, SCB_FIFO_USE_COUNT, - ahd_inb_scbram(ahd, SCB_FIFO_USE_COUNT) + 1); + /* + * Initialize Residual Fields. + */ + ahd_outb(ahd, SCB_RESIDUAL_DATACNT+3, datacnt >> 24); + ahd_outl(ahd, SCB_RESIDUAL_SGPTR, sgptr & SG_PTR_MASK); - /* - * Install a "fake" handler for this FIFO. - */ - ahd_outw(ahd, LONGJMP_ADDR, 0); + /* + * Mark the SCB as having a FIFO in use. + */ + ahd_outb(ahd, SCB_FIFO_USE_COUNT, + ahd_inb_scbram(ahd, SCB_FIFO_USE_COUNT) + 1); - /* - * Notify the hardware that we have satisfied - * this sequencer interrupt. - */ - ahd_outb(ahd, CLRSEQINTSRC, CLRCFG4DATA); - } else if ((seqintsrc & SAVEPTRS) != 0) { - uint32_t sgptr; - uint32_t resid; + /* + * Install a "fake" handler for this FIFO. + */ + ahd_outw(ahd, LONGJMP_ADDR, 0); - if ((ahd_inb(ahd, LONGJMP_ADDR+1)&INVALID_ADDR) != 0) { - /* - * Snapshot Save Pointers. Clear - * the snapshot and continue. - */ - ahd_outb(ahd, DFFSXFRCTL, CLRCHN); - continue; - } + /* + * Notify the hardware that we have satisfied + * this sequencer interrupt. + */ + ahd_outb(ahd, CLRSEQINTSRC, CLRCFG4DATA); + } else if ((seqintsrc & SAVEPTRS) != 0) { + uint32_t sgptr; + uint32_t resid; + if ((ahd_inb(ahd, LONGJMP_ADDR+1)&INVALID_ADDR) != 0) { /* - * Disable S/G fetch so the DMA engine - * is available to future users. + * Snapshot Save Pointers. All that + * is necessary to clear the snapshot + * is a CLRCHN. */ - if ((ahd_inb(ahd, SG_STATE) & FETCH_INPROG) != 0) - ahd_outb(ahd, CCSGCTL, 0); - ahd_outb(ahd, SG_STATE, 0); + goto clrchn; + } - /* - * Flush the data FIFO. Strickly only - * necessary for Rev A parts. - */ - ahd_outb(ahd, DFCNTRL, - ahd_inb(ahd, DFCNTRL) | FIFOFLUSH); + /* + * Disable S/G fetch so the DMA engine + * is available to future users. + */ + if ((ahd_inb(ahd, SG_STATE) & FETCH_INPROG) != 0) + ahd_outb(ahd, CCSGCTL, 0); + ahd_outb(ahd, SG_STATE, 0); - /* - * Calculate residual. - */ - sgptr = ahd_inl_scbram(ahd, SCB_RESIDUAL_SGPTR); - resid = ahd_inl(ahd, SHCNT); - resid |= - ahd_inb_scbram(ahd, SCB_RESIDUAL_DATACNT+3) << 24; - ahd_outl(ahd, SCB_RESIDUAL_DATACNT, resid); - if ((ahd_inb(ahd, SG_CACHE_SHADOW) & LAST_SEG) == 0) { - /* - * Must back up to the correct S/G element. - * Typically this just means resetting our - * low byte to the offset in the SG_CACHE, - * but if we wrapped, we have to correct - * the other bytes of the sgptr too. - */ - if ((ahd_inb(ahd, SG_CACHE_SHADOW) & 0x80) != 0 - && (sgptr & 0x80) == 0) - sgptr -= 0x100; - sgptr &= ~0xFF; - sgptr |= ahd_inb(ahd, SG_CACHE_SHADOW) - & SG_ADDR_MASK; - ahd_outl(ahd, SCB_RESIDUAL_SGPTR, sgptr); - ahd_outb(ahd, SCB_RESIDUAL_DATACNT + 3, 0); - } else if ((resid & AHD_SG_LEN_MASK) == 0) { - ahd_outb(ahd, SCB_RESIDUAL_SGPTR, - sgptr | SG_LIST_NULL); - } - /* - * Save Pointers. - */ - ahd_outq(ahd, SCB_DATAPTR, ahd_inq(ahd, SHADDR)); - ahd_outl(ahd, SCB_DATACNT, resid); - ahd_outl(ahd, SCB_SGPTR, sgptr); - ahd_outb(ahd, CLRSEQINTSRC, CLRSAVEPTRS); - ahd_outb(ahd, SEQIMODE, - ahd_inb(ahd, SEQIMODE) | ENSAVEPTRS); - /* - * If the data is to the SCSI bus, we are - * done, otherwise wait for FIFOEMP. - */ - if ((ahd_inb(ahd, DFCNTRL) & DIRECTION) != 0) - break; - } else if ((ahd_inb(ahd, SG_STATE) & LOADING_NEEDED) != 0) { - uint32_t sgptr; - uint64_t data_addr; - uint32_t data_len; - u_int dfcntrl; + /* + * Flush the data FIFO. Strickly only + * necessary for Rev A parts. + */ + ahd_outb(ahd, DFCNTRL, ahd_inb(ahd, DFCNTRL) | FIFOFLUSH); + /* + * Calculate residual. + */ + sgptr = ahd_inl_scbram(ahd, SCB_RESIDUAL_SGPTR); + resid = ahd_inl(ahd, SHCNT); + resid |= ahd_inb_scbram(ahd, SCB_RESIDUAL_DATACNT+3) << 24; + ahd_outl(ahd, SCB_RESIDUAL_DATACNT, resid); + if ((ahd_inb(ahd, SG_CACHE_SHADOW) & LAST_SEG) == 0) { /* - * Disable S/G fetch so the DMA engine - * is available to future users. + * Must back up to the correct S/G element. + * Typically this just means resetting our + * low byte to the offset in the SG_CACHE, + * but if we wrapped, we have to correct + * the other bytes of the sgptr too. */ - if ((ahd_inb(ahd, SG_STATE) & FETCH_INPROG) != 0) { - ahd_outb(ahd, CCSGCTL, 0); - ahd_outb(ahd, SG_STATE, LOADING_NEEDED); - } + if ((ahd_inb(ahd, SG_CACHE_SHADOW) & 0x80) != 0 + && (sgptr & 0x80) == 0) + sgptr -= 0x100; + sgptr &= ~0xFF; + sgptr |= ahd_inb(ahd, SG_CACHE_SHADOW) + & SG_ADDR_MASK; + ahd_outl(ahd, SCB_RESIDUAL_SGPTR, sgptr); + ahd_outb(ahd, SCB_RESIDUAL_DATACNT + 3, 0); + } else if ((resid & AHD_SG_LEN_MASK) == 0) { + ahd_outb(ahd, SCB_RESIDUAL_SGPTR, + sgptr | SG_LIST_NULL); + } + /* + * Save Pointers. + */ + ahd_outq(ahd, SCB_DATAPTR, ahd_inq(ahd, SHADDR)); + ahd_outl(ahd, SCB_DATACNT, resid); + ahd_outl(ahd, SCB_SGPTR, sgptr); + ahd_outb(ahd, CLRSEQINTSRC, CLRSAVEPTRS); + ahd_outb(ahd, SEQIMODE, + ahd_inb(ahd, SEQIMODE) | ENSAVEPTRS); + /* + * If the data is to the SCSI bus, we are + * done, otherwise wait for FIFOEMP. + */ + if ((ahd_inb(ahd, DFCNTRL) & DIRECTION) != 0) + goto clrchn; + } else if ((ahd_inb(ahd, SG_STATE) & LOADING_NEEDED) != 0) { + uint32_t sgptr; + uint64_t data_addr; + uint32_t data_len; + u_int dfcntrl; - /* - * Wait for the DMA engine to notice that the - * host transfer is enabled and that there is - * space in the S/G FIFO for new segments before - * loading more segments. - */ - if ((ahd_inb(ahd, DFSTATUS) & PRELOAD_AVAIL) == 0) - continue; - if ((ahd_inb(ahd, DFCNTRL) & HDMAENACK) == 0) - continue; + /* + * Disable S/G fetch so the DMA engine + * is available to future users. We won't + * be using the DMA engine to load segments. + */ + if ((ahd_inb(ahd, SG_STATE) & FETCH_INPROG) != 0) { + ahd_outb(ahd, CCSGCTL, 0); + ahd_outb(ahd, SG_STATE, LOADING_NEEDED); + } + + /* + * Wait for the DMA engine to notice that the + * host transfer is enabled and that there is + * space in the S/G FIFO for new segments before + * loading more segments. + */ + if ((ahd_inb(ahd, DFSTATUS) & PRELOAD_AVAIL) != 0 + && (ahd_inb(ahd, DFCNTRL) & HDMAENACK) != 0) { /* * Determine the offset of the next S/G @@ -751,7 +769,7 @@ ahd_run_data_fifo(struct ahd_softc *ahd, struct scb *scb) * Advertise the segment to the hardware. */ dfcntrl = ahd_inb(ahd, DFCNTRL)|PRELOADEN|HDMAEN; - if ((ahd->features & AHD_NEW_DFCNTRL_OPTS)!=0) { + if ((ahd->features & AHD_NEW_DFCNTRL_OPTS) != 0) { /* * Use SCSIENWRDIS so that SCSIEN * is never modified by this @@ -760,30 +778,28 @@ ahd_run_data_fifo(struct ahd_softc *ahd, struct scb *scb) dfcntrl |= SCSIENWRDIS; } ahd_outb(ahd, DFCNTRL, dfcntrl); - } else if ((ahd_inb(ahd, SG_CACHE_SHADOW) - & LAST_SEG_DONE) != 0) { - - /* - * Transfer completed to the end of SG list - * and has flushed to the host. - */ - ahd_outb(ahd, SCB_SGPTR, - ahd_inb_scbram(ahd, SCB_SGPTR) | SG_LIST_NULL); - break; - } else if ((ahd_inb(ahd, DFSTATUS) & FIFOEMP) != 0) { - break; } - ahd_delay(200); + } else if ((ahd_inb(ahd, SG_CACHE_SHADOW) & LAST_SEG_DONE) != 0) { + + /* + * Transfer completed to the end of SG list + * and has flushed to the host. + */ + ahd_outb(ahd, SCB_SGPTR, + ahd_inb_scbram(ahd, SCB_SGPTR) | SG_LIST_NULL); + goto clrchn; + } else if ((ahd_inb(ahd, DFSTATUS) & FIFOEMP) != 0) { +clrchn: + /* + * Clear any handler for this FIFO, decrement + * the FIFO use count for the SCB, and release + * the FIFO. + */ + ahd_outb(ahd, LONGJMP_ADDR + 1, INVALID_ADDR); + ahd_outb(ahd, SCB_FIFO_USE_COUNT, + ahd_inb_scbram(ahd, SCB_FIFO_USE_COUNT) - 1); + ahd_outb(ahd, DFFSXFRCTL, CLRCHN); } - /* - * Clear any handler for this FIFO, decrement - * the FIFO use count for the SCB, and release - * the FIFO. - */ - ahd_outb(ahd, LONGJMP_ADDR + 1, INVALID_ADDR); - ahd_outb(ahd, SCB_FIFO_USE_COUNT, - ahd_inb_scbram(ahd, SCB_FIFO_USE_COUNT) - 1); - ahd_outb(ahd, DFFSXFRCTL, CLRCHN); } void @@ -799,7 +815,7 @@ ahd_run_qoutfifo(struct ahd_softc *ahd) while ((ahd->qoutfifo[ahd->qoutfifonext] & QOUTFIFO_ENTRY_VALID_LE) == ahd->qoutfifonext_valid_tag) { - scb_index = ahd_le16toh(ahd->qoutfifo[ahd->qoutfifonext] + scb_index = aic_le16toh(ahd->qoutfifo[ahd->qoutfifonext] & ~QOUTFIFO_ENTRY_VALID_LE); scb = ahd_lookup_scb(ahd, scb_index); if (scb == NULL) { @@ -879,26 +895,6 @@ ahd_handle_seqint(struct ahd_softc *ahd, u_int intstat) ahd_name(ahd), seqintcode); #endif switch (seqintcode) { - case BAD_SCB_STATUS: - { - struct scb *scb; - u_int scbid; - int cmds_pending; - - scbid = ahd_get_scbptr(ahd); - scb = ahd_lookup_scb(ahd, scbid); - if (scb != NULL) { - ahd_complete_scb(ahd, scb); - } else { - printf("%s: WARNING no command for scb %d " - "(bad status)\n", ahd_name(ahd), scbid); - ahd_dump_card_state(ahd); - } - cmds_pending = ahd_inw(ahd, CMDS_PENDING); - if (cmds_pending > 0) - ahd_outw(ahd, CMDS_PENDING, cmds_pending - 1); - break; - } case ENTERING_NONPACK: { struct scb *scb; @@ -1063,11 +1059,11 @@ ahd_handle_seqint(struct ahd_softc *ahd, u_int intstat) ahd_outb(ahd, SAVED_LUN, 0); ahd_outb(ahd, SEQ_FLAGS, 0); ahd_assert_atn(ahd); - scb->flags &= ~(SCB_PACKETIZED); + scb->flags &= ~SCB_PACKETIZED; scb->flags |= SCB_ABORT|SCB_CMDPHASE_ABORT; ahd_freeze_devq(ahd, scb); - ahd_set_transaction_status(scb, CAM_REQUEUE_REQ); - ahd_freeze_scb(scb); + aic_set_transaction_status(scb, CAM_REQUEUE_REQ); + aic_freeze_scb(scb); /* * Allow the sequencer to continue with @@ -1315,7 +1311,7 @@ ahd_handle_seqint(struct ahd_softc *ahd, u_int intstat) "NumSGs = %d.\n", ahd_inb(ahd, SEQ_FLAGS) & DPHASE ? "Have" : "Haven't", - ahd_get_transfer_length(scb), scb->sg_count); + aic_get_transfer_length(scb), scb->sg_count); ahd_dump_sglist(scb); } #endif @@ -1325,8 +1321,8 @@ ahd_handle_seqint(struct ahd_softc *ahd, u_int intstat) * target does a command complete. */ ahd_freeze_devq(ahd, scb); - ahd_set_transaction_status(scb, CAM_DATA_RUN_ERR); - ahd_freeze_scb(scb); + aic_set_transaction_status(scb, CAM_DATA_RUN_ERR); + aic_freeze_scb(scb); break; } case MKMSG_FAILED: @@ -1587,7 +1583,7 @@ ahd_handle_scsiint(struct ahd_softc *ahd, u_int intstat) */ ahd_scb_devinfo(ahd, &devinfo, scb); ahd_force_renegotiation(ahd, &devinfo); - ahd_set_transaction_status(scb, CAM_SEL_TIMEOUT); + aic_set_transaction_status(scb, CAM_SEL_TIMEOUT); ahd_freeze_devq(ahd, scb); } ahd_outb(ahd, CLRINT, CLRSCSIINT); @@ -2034,8 +2030,8 @@ ahd_handle_pkt_busfree(struct ahd_softc *ahd, u_int busfreetime) } scb->crc_retry_count++; } else { - ahd_set_transaction_status(scb, CAM_UNCOR_PARITY); - ahd_freeze_scb(scb); + aic_set_transaction_status(scb, CAM_UNCOR_PARITY); + aic_freeze_scb(scb); ahd_freeze_devq(ahd, scb); } /* Return unpausing the sequencer. */ @@ -2177,7 +2173,7 @@ ahd_handle_nonpkt_busfree(struct ahd_softc *ahd) && ahd_match_scb(ahd, scb, target, 'A', CAM_LUN_WILDCARD, SCB_LIST_NULL, ROLE_INITIATOR)) - ahd_set_transaction_status(scb, CAM_REQ_CMP); + aic_set_transaction_status(scb, CAM_REQ_CMP); #endif ahd_handle_devreset(ahd, &devinfo, CAM_LUN_WILDCARD, CAM_BDR_SENT, "Bus Device Reset", @@ -2268,8 +2264,8 @@ ahd_handle_nonpkt_busfree(struct ahd_softc *ahd) && ((ahd->msg_flags & MSG_FLAG_EXPECT_PPR_BUSFREE) != 0)) { ahd_freeze_devq(ahd, scb); - ahd_set_transaction_status(scb, CAM_REQUEUE_REQ); - ahd_freeze_scb(scb); + aic_set_transaction_status(scb, CAM_REQUEUE_REQ); + aic_freeze_scb(scb); if ((ahd->msg_flags & MSG_FLAG_IU_REQ_CHANGED) != 0) { ahd_abort_scbs(ahd, SCB_GET_TARGET(ahd, scb), SCB_GET_CHANNEL(ahd, scb), @@ -2313,8 +2309,7 @@ ahd_handle_nonpkt_busfree(struct ahd_softc *ahd) "PRGMCNT == 0x%x\n", ahd_lookup_phase_entry(lastphase)->phasemsg, aborted, - ahd_inb(ahd, PRGMCNT) - | (ahd_inb(ahd, PRGMCNT+1) << 8)); + ahd_inw(ahd, PRGMCNT)); ahd_dump_card_state(ahd); } /* Always restart the sequencer. */ @@ -2358,7 +2353,7 @@ ahd_handle_proto_violation(struct ahd_softc *ahd) printf("No SCB found during protocol violation\n"); goto proto_violation_reset; } else { - ahd_set_transaction_status(scb, CAM_SEQUENCE_FAIL); + aic_set_transaction_status(scb, CAM_SEQUENCE_FAIL); if ((seq_flags & NO_CDB_SENT) != 0) { ahd_print_path(ahd, scb); printf("No or incomplete CDB sent to device.\n"); @@ -2477,8 +2472,7 @@ ahd_clear_critical_section(struct ahd_softc *ahd) u_int i; ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); - seqaddr = ahd_inb(ahd, CURADDR) - | (ahd_inb(ahd, CURADDR+1) << 8); + seqaddr = ahd_inw(ahd, CURADDR); cs = ahd->critical_sections; for (i = 0; i < ahd->num_critical_sections; i++, cs++) { @@ -2538,7 +2532,7 @@ ahd_clear_critical_section(struct ahd_softc *ahd) ahd_set_modes(ahd, ahd->saved_src_mode, ahd->saved_dst_mode); ahd_outb(ahd, HCNTRL, ahd->unpause); while (!ahd_is_paused(ahd)) - ahd_delay(200); + aic_delay(200); ahd_update_modes(ahd); } if (stepping) { @@ -2614,10 +2608,10 @@ ahd_print_scb(struct scb *scb) for (i = 0; i < sizeof(hscb->shared_data.idata.cdb); i++) printf("%#02x", hscb->shared_data.idata.cdb[i]); printf(" dataptr:%#x%x datacnt:%#x sgptr:%#x tag:%#x\n", - (uint32_t)((ahd_le64toh(hscb->dataptr) >> 32) & 0xFFFFFFFF), - (uint32_t)(ahd_le64toh(hscb->dataptr) & 0xFFFFFFFF), - ahd_le32toh(hscb->datacnt), - ahd_le32toh(hscb->sgptr), + (uint32_t)((aic_le64toh(hscb->dataptr) >> 32) & 0xFFFFFFFF), + (uint32_t)(aic_le64toh(hscb->dataptr) & 0xFFFFFFFF), + aic_le32toh(hscb->datacnt), + aic_le32toh(hscb->sgptr), SCB_GET_TAG(scb)); ahd_dump_sglist(scb); } @@ -2636,8 +2630,8 @@ ahd_dump_sglist(struct scb *scb) uint64_t addr; uint32_t len; - addr = ahd_le64toh(sg_list[i].addr); - len = ahd_le32toh(sg_list[i].len); + addr = aic_le64toh(sg_list[i].addr); + len = aic_le32toh(sg_list[i].len); printf("sg[%d] - Addr 0x%x%x : Length %d%s\n", i, (uint32_t)((addr >> 32) & 0xFFFFFFFF), @@ -2653,11 +2647,11 @@ ahd_dump_sglist(struct scb *scb) for (i = 0; i < scb->sg_count; i++) { uint32_t len; - len = ahd_le32toh(sg_list[i].len); + len = aic_le32toh(sg_list[i].len); printf("sg[%d] - Addr 0x%x%x : Length %d%s\n", i, (len & AHD_SG_HIGH_ADDR_MASK) >> 24, - ahd_le32toh(sg_list[i].addr), + aic_le32toh(sg_list[i].addr), len & AHD_SG_LEN_MASK, len & AHD_DMA_LAST_SEG ? " Last" : ""); } @@ -3199,14 +3193,25 @@ ahd_update_neg_table(struct ahd_softc *ahd, struct ahd_devinfo *devinfo, iocell_opts[AHD_PRECOMP_SLEW_INDEX] &= ~AHD_PRECOMP_MASK; if ((ahd->features & AHD_NEW_IOCELL_OPTS) != 0 - && (ppr_opts & MSG_EXT_PPR_DT_REQ) != 0) { + && (ppr_opts & MSG_EXT_PPR_DT_REQ) != 0 + && (ppr_opts & MSG_EXT_PPR_IU_REQ) == 0) { /* * Slow down our CRC interval to be - * compatible with devices that can't - * handle a CRC at full speed. + * compatible with non-packetized + * U160 devices that can't handle a + * CRC at full speed. */ con_opts |= ENSLOWCRC; } + + if ((ahd->bugs & AHD_PACED_NEGTABLE_BUG) != 0) { + /* + * On H2A4, revert to a slower slewrate + * on non-paced transfers. + */ + iocell_opts[AHD_PRECOMP_SLEW_INDEX] &= + ~AHD_SLEWRATE_MASK; + } } ahd_outb(ahd, ANNEXCOL, AHD_ANNEXCOL_PRECOMP_SLEW); @@ -4677,7 +4682,7 @@ ahd_handle_msg_reject(struct ahd_softc *ahd, struct ahd_devinfo *devinfo) ahd_outb(ahd, SCB_CONTROL, ahd_inb_scbram(ahd, SCB_CONTROL) & mask); scb->hscb->control &= mask; - ahd_set_transaction_tag(scb, /*enabled*/FALSE, + aic_set_transaction_tag(scb, /*enabled*/FALSE, /*type*/MSG_SIMPLE_TASK); ahd_outb(ahd, MSG_OUT, MSG_IDENTIFYFLAG); ahd_assert_atn(ahd); @@ -4735,7 +4740,7 @@ ahd_handle_ign_wide_residue(struct ahd_softc *ahd, struct ahd_devinfo *devinfo) * Perhaps add datadir to some spare bits in the hscb? */ if ((ahd_inb(ahd, SEQ_FLAGS) & DPHASE) == 0 - || ahd_get_transfer_dir(scb) != CAM_DIR_IN) { + || aic_get_transfer_dir(scb) != CAM_DIR_IN) { /* * Ignore the message if we haven't * seen an appropriate data phase yet. @@ -4790,18 +4795,18 @@ ahd_handle_ign_wide_residue(struct ahd_softc *ahd, struct ahd_devinfo *devinfo) * to load so we must go back one. */ sg--; - sglen = ahd_le32toh(sg->len) & AHD_SG_LEN_MASK; + sglen = aic_le32toh(sg->len) & AHD_SG_LEN_MASK; if (sg != scb->sg_list && sglen < (data_cnt & AHD_SG_LEN_MASK)) { sg--; - sglen = ahd_le32toh(sg->len); + sglen = aic_le32toh(sg->len); /* * Preserve High Address and SG_LIST * bits while setting the count to 1. */ data_cnt = 1|(sglen&(~AHD_SG_LEN_MASK)); - data_addr = ahd_le64toh(sg->addr) + data_addr = aic_le64toh(sg->addr) + (sglen & AHD_SG_LEN_MASK) - 1; @@ -4823,18 +4828,18 @@ ahd_handle_ign_wide_residue(struct ahd_softc *ahd, struct ahd_devinfo *devinfo) * to load so we must go back one. */ sg--; - sglen = ahd_le32toh(sg->len) & AHD_SG_LEN_MASK; + sglen = aic_le32toh(sg->len) & AHD_SG_LEN_MASK; if (sg != scb->sg_list && sglen < (data_cnt & AHD_SG_LEN_MASK)) { sg--; - sglen = ahd_le32toh(sg->len); + sglen = aic_le32toh(sg->len); /* * Preserve High Address and SG_LIST * bits while setting the count to 1. */ data_cnt = 1|(sglen&(~AHD_SG_LEN_MASK)); - data_addr = ahd_le32toh(sg->addr) + data_addr = aic_le32toh(sg->addr) + (sglen & AHD_SG_LEN_MASK) - 1; @@ -4896,7 +4901,7 @@ ahd_reinitialize_dataptrs(struct ahd_softc *ahd) ahd_outb(ahd, DFFSXFRCTL, CLRCHN); wait = 1000; while (--wait && !(ahd_inb(ahd, MDFFSTAT) & FIFOFREE)) - ahd_delay(100); + aic_delay(100); if (wait == 0) { ahd_print_path(ahd, scb); printf("ahd_reinitialize_dataptrs: Forcing FIFO free.\n"); @@ -4912,10 +4917,7 @@ ahd_reinitialize_dataptrs(struct ahd_softc *ahd) * Determine initial values for data_addr and data_cnt * for resuming the data phase. */ - sgptr = (ahd_inb_scbram(ahd, SCB_RESIDUAL_SGPTR + 3) << 24) - | (ahd_inb_scbram(ahd, SCB_RESIDUAL_SGPTR + 2) << 16) - | (ahd_inb_scbram(ahd, SCB_RESIDUAL_SGPTR + 1) << 8) - | ahd_inb_scbram(ahd, SCB_RESIDUAL_SGPTR); + sgptr = ahd_inl_scbram(ahd, SCB_RESIDUAL_SGPTR); sgptr &= SG_PTR_MASK; resid = (ahd_inb_scbram(ahd, SCB_RESIDUAL_DATACNT + 2) << 16) @@ -4930,13 +4932,10 @@ ahd_reinitialize_dataptrs(struct ahd_softc *ahd) /* The residual sg_ptr always points to the next sg */ sg--; - dataptr = ahd_le64toh(sg->addr) - + (ahd_le32toh(sg->len) & AHD_SG_LEN_MASK) + dataptr = aic_le64toh(sg->addr) + + (aic_le32toh(sg->len) & AHD_SG_LEN_MASK) - resid; - ahd_outb(ahd, HADDR + 7, dataptr >> 56); - ahd_outb(ahd, HADDR + 6, dataptr >> 48); - ahd_outb(ahd, HADDR + 5, dataptr >> 40); - ahd_outb(ahd, HADDR + 4, dataptr >> 32); + ahd_outl(ahd, HADDR + 4, dataptr >> 32); } else { struct ahd_dma_seg *sg; @@ -4945,16 +4944,13 @@ ahd_reinitialize_dataptrs(struct ahd_softc *ahd) /* The residual sg_ptr always points to the next sg */ sg--; - dataptr = ahd_le32toh(sg->addr) - + (ahd_le32toh(sg->len) & AHD_SG_LEN_MASK) + dataptr = aic_le32toh(sg->addr) + + (aic_le32toh(sg->len) & AHD_SG_LEN_MASK) - resid; ahd_outb(ahd, HADDR + 4, - (ahd_le32toh(sg->len) & ~AHD_SG_LEN_MASK) >> 24); + (aic_le32toh(sg->len) & ~AHD_SG_LEN_MASK) >> 24); } - ahd_outb(ahd, HADDR + 3, dataptr >> 24); - ahd_outb(ahd, HADDR + 2, dataptr >> 16); - ahd_outb(ahd, HADDR + 1, dataptr >> 8); - ahd_outb(ahd, HADDR, dataptr); + ahd_outl(ahd, HADDR, dataptr); ahd_outb(ahd, HCNT + 2, resid >> 16); ahd_outb(ahd, HCNT + 1, resid >> 8); ahd_outb(ahd, HCNT, resid); @@ -5148,8 +5144,8 @@ ahd_alloc(void *platform_arg, char *name) ahd->bugs = AHD_BUGNONE; ahd->flags = AHD_SPCHK_ENB_A|AHD_RESET_BUS_A|AHD_TERM_ENB_A | AHD_EXTENDED_TRANS_A|AHD_STPWLEVEL_A; - ahd_timer_init(&ahd->reset_timer); - ahd_timer_init(&ahd->stat_timer); + aic_timer_init(&ahd->reset_timer); + aic_timer_init(&ahd->stat_timer); ahd->int_coalescing_timer = AHD_INT_COALESCING_TIMER_DEFAULT; ahd->int_coalescing_maxcmds = AHD_INT_COALESCING_MAXCMDS_DEFAULT; ahd->int_coalescing_mincmds = AHD_INT_COALESCING_MINCMDS_DEFAULT; @@ -5185,24 +5181,24 @@ ahd_softc_insert(struct ahd_softc *ahd) { struct ahd_softc *list_ahd; -#if AHD_PCI_CONFIG > 0 +#if AIC_PCI_CONFIG > 0 /* * Second Function PCI devices need to inherit some * settings from function 0. */ if ((ahd->features & AHD_MULTI_FUNC) != 0) { TAILQ_FOREACH(list_ahd, &ahd_tailq, links) { - ahd_dev_softc_t list_pci; - ahd_dev_softc_t pci; + aic_dev_softc_t list_pci; + aic_dev_softc_t pci; list_pci = list_ahd->dev_softc; pci = ahd->dev_softc; - if (ahd_get_pci_slot(list_pci) == ahd_get_pci_slot(pci) - && ahd_get_pci_bus(list_pci) == ahd_get_pci_bus(pci)) { + if (aic_get_pci_slot(list_pci) == aic_get_pci_slot(pci) + && aic_get_pci_bus(list_pci) == aic_get_pci_bus(pci)) { struct ahd_softc *master; struct ahd_softc *slave; - if (ahd_get_pci_function(list_pci) == 0) { + if (aic_get_pci_function(list_pci) == 0) { master = list_ahd; slave = ahd; } else { @@ -5267,27 +5263,27 @@ ahd_free(struct ahd_softc *ahd) { int i; + ahd_terminate_recovery_thread(ahd); switch (ahd->init_level) { default: case 5: ahd_shutdown(ahd); - TAILQ_REMOVE(&ahd_tailq, ahd, links); /* FALLTHROUGH */ case 4: - ahd_dmamap_unload(ahd, ahd->shared_data_dmat, - ahd->shared_data_dmamap); + aic_dmamap_unload(ahd, ahd->shared_data_dmat, + ahd->shared_data_map.dmamap); /* FALLTHROUGH */ case 3: - ahd_dmamem_free(ahd, ahd->shared_data_dmat, ahd->qoutfifo, - ahd->shared_data_dmamap); - ahd_dmamap_destroy(ahd, ahd->shared_data_dmat, - ahd->shared_data_dmamap); + aic_dmamem_free(ahd, ahd->shared_data_dmat, ahd->qoutfifo, + ahd->shared_data_map.dmamap); + aic_dmamap_destroy(ahd, ahd->shared_data_dmat, + ahd->shared_data_map.dmamap); /* FALLTHROUGH */ case 2: - ahd_dma_tag_destroy(ahd, ahd->shared_data_dmat); + aic_dma_tag_destroy(ahd, ahd->shared_data_dmat); case 1: #ifndef __linux__ - ahd_dma_tag_destroy(ahd, ahd->buffer_dmat); + aic_dma_tag_destroy(ahd, ahd->buffer_dmat); #endif break; case 0: @@ -5295,7 +5291,7 @@ ahd_free(struct ahd_softc *ahd) } #ifndef __linux__ - ahd_dma_tag_destroy(ahd, ahd->parent_dmat); + aic_dma_tag_destroy(ahd, ahd->parent_dmat); #endif ahd_platform_free(ahd); ahd_fini_scbdata(ahd); @@ -5348,8 +5344,8 @@ ahd_shutdown(void *arg) /* * Stop periodic timer callbacks. */ - ahd_timer_stop(&ahd->reset_timer); - ahd_timer_stop(&ahd->stat_timer); + aic_timer_stop(&ahd->reset_timer); + aic_timer_stop(&ahd->stat_timer); /* This will reset most registers to 0, but not all */ ahd_reset(ahd, /*reinit*/FALSE); @@ -5381,7 +5377,7 @@ ahd_reset(struct ahd_softc *ahd, int reinit) ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); sxfrctl1 = ahd_inb(ahd, SXFRCTL1); - cmd = ahd_pci_read_config(ahd->dev_softc, PCIR_COMMAND, /*bytes*/2); + cmd = aic_pci_read_config(ahd->dev_softc, PCIR_COMMAND, /*bytes*/2); if ((ahd->bugs & AHD_PCIX_CHIPRST_BUG) != 0) { uint32_t mod_cmd; @@ -5395,7 +5391,7 @@ ahd_reset(struct ahd_softc *ahd, int reinit) * PERR and SERR responses during the CHIPRST. */ mod_cmd = cmd & ~(PCIM_CMD_PERRESPEN|PCIM_CMD_SERRESPEN); - ahd_pci_write_config(ahd->dev_softc, PCIR_COMMAND, + aic_pci_write_config(ahd->dev_softc, PCIR_COMMAND, mod_cmd, /*bytes*/2); } ahd_outb(ahd, HCNTRL, CHIPRST | ahd->pause); @@ -5408,7 +5404,7 @@ ahd_reset(struct ahd_softc *ahd, int reinit) */ wait = 1000; do { - ahd_delay(1000); + aic_delay(1000); } while (--wait && !(ahd_inb(ahd, HCNTRL) & CHIPRSTACK)); if (wait == 0) { @@ -5422,9 +5418,9 @@ ahd_reset(struct ahd_softc *ahd, int reinit) * Clear any latched PCI error status and restore * previous SERR and PERR response enables. */ - ahd_pci_write_config(ahd->dev_softc, PCIR_STATUS + 1, + aic_pci_write_config(ahd->dev_softc, PCIR_STATUS + 1, 0xFF, /*bytes*/1); - ahd_pci_write_config(ahd->dev_softc, PCIR_COMMAND, + aic_pci_write_config(ahd->dev_softc, PCIR_COMMAND, cmd, /*bytes*/2); } @@ -5551,7 +5547,7 @@ ahd_init_scbdata(struct ahd_softc *ahd) */ /* DMA tag for our hardware scb structures */ - if (ahd_dma_tag_create(ahd, ahd->parent_dmat, /*alignment*/1, + if (aic_dma_tag_create(ahd, ahd->parent_dmat, /*alignment*/1, /*boundary*/BUS_SPACE_MAXADDR_32BIT + 1, /*lowaddr*/BUS_SPACE_MAXADDR_32BIT, /*highaddr*/BUS_SPACE_MAXADDR, @@ -5565,7 +5561,7 @@ ahd_init_scbdata(struct ahd_softc *ahd) scb_data->init_level++; /* DMA tag for our S/G structures. */ - if (ahd_dma_tag_create(ahd, ahd->parent_dmat, /*alignment*/8, + if (aic_dma_tag_create(ahd, ahd->parent_dmat, /*alignment*/8, /*boundary*/BUS_SPACE_MAXADDR_32BIT + 1, /*lowaddr*/BUS_SPACE_MAXADDR_32BIT, /*highaddr*/BUS_SPACE_MAXADDR, @@ -5584,7 +5580,7 @@ ahd_init_scbdata(struct ahd_softc *ahd) scb_data->init_level++; /* DMA tag for our sense buffers. We allocate in page sized chunks */ - if (ahd_dma_tag_create(ahd, ahd->parent_dmat, /*alignment*/1, + if (aic_dma_tag_create(ahd, ahd->parent_dmat, /*alignment*/1, /*boundary*/BUS_SPACE_MAXADDR_32BIT + 1, /*lowaddr*/BUS_SPACE_MAXADDR_32BIT, /*highaddr*/BUS_SPACE_MAXADDR, @@ -5672,13 +5668,13 @@ ahd_fini_scbdata(struct ahd_softc *ahd) while ((sns_map = SLIST_FIRST(&scb_data->sense_maps)) != NULL) { SLIST_REMOVE_HEAD(&scb_data->sense_maps, links); - ahd_dmamap_unload(ahd, scb_data->sense_dmat, + aic_dmamap_unload(ahd, scb_data->sense_dmat, sns_map->dmamap); - ahd_dmamem_free(ahd, scb_data->sense_dmat, + aic_dmamem_free(ahd, scb_data->sense_dmat, sns_map->vaddr, sns_map->dmamap); free(sns_map, M_DEVBUF); } - ahd_dma_tag_destroy(ahd, scb_data->sense_dmat); + aic_dma_tag_destroy(ahd, scb_data->sense_dmat); /* FALLTHROUGH */ } case 6: @@ -5687,13 +5683,13 @@ ahd_fini_scbdata(struct ahd_softc *ahd) while ((sg_map = SLIST_FIRST(&scb_data->sg_maps)) != NULL) { SLIST_REMOVE_HEAD(&scb_data->sg_maps, links); - ahd_dmamap_unload(ahd, scb_data->sg_dmat, + aic_dmamap_unload(ahd, scb_data->sg_dmat, sg_map->dmamap); - ahd_dmamem_free(ahd, scb_data->sg_dmat, + aic_dmamem_free(ahd, scb_data->sg_dmat, sg_map->vaddr, sg_map->dmamap); free(sg_map, M_DEVBUF); } - ahd_dma_tag_destroy(ahd, scb_data->sg_dmat); + aic_dma_tag_destroy(ahd, scb_data->sg_dmat); /* FALLTHROUGH */ } case 5: @@ -5702,13 +5698,13 @@ ahd_fini_scbdata(struct ahd_softc *ahd) while ((hscb_map = SLIST_FIRST(&scb_data->hscb_maps)) != NULL) { SLIST_REMOVE_HEAD(&scb_data->hscb_maps, links); - ahd_dmamap_unload(ahd, scb_data->hscb_dmat, + aic_dmamap_unload(ahd, scb_data->hscb_dmat, hscb_map->dmamap); - ahd_dmamem_free(ahd, scb_data->hscb_dmat, + aic_dmamem_free(ahd, scb_data->hscb_dmat, hscb_map->vaddr, hscb_map->dmamap); free(hscb_map, M_DEVBUF); } - ahd_dma_tag_destroy(ahd, scb_data->hscb_dmat); + aic_dma_tag_destroy(ahd, scb_data->hscb_dmat); /* FALLTHROUGH */ } case 4: @@ -5913,7 +5909,7 @@ ahd_free_scb(struct ahd_softc *ahd, struct scb *scb) scb, links.le); } - ahd_platform_scb_free(ahd, scb); + aic_platform_scb_free(ahd, scb); } void @@ -5944,7 +5940,7 @@ ahd_alloc_scbs(struct ahd_softc *ahd) offset = (PAGE_SIZE / sizeof(*hscb)) - scb_data->scbs_left; hscb_map = SLIST_FIRST(&scb_data->hscb_maps); hscb = &((struct hardware_scb *)hscb_map->vaddr)[offset]; - hscb_busaddr = hscb_map->physaddr + (offset * sizeof(*hscb)); + hscb_busaddr = hscb_map->busaddr + (offset * sizeof(*hscb)); } else { hscb_map = malloc(sizeof(*hscb_map), M_DEVBUF, M_NOWAIT); @@ -5952,7 +5948,7 @@ ahd_alloc_scbs(struct ahd_softc *ahd) return; /* Allocate the next batch of hardware SCBs */ - if (ahd_dmamem_alloc(ahd, scb_data->hscb_dmat, + if (aic_dmamem_alloc(ahd, scb_data->hscb_dmat, (void **)&hscb_map->vaddr, BUS_DMA_NOWAIT, &hscb_map->dmamap) != 0) { free(hscb_map, M_DEVBUF); @@ -5961,12 +5957,12 @@ ahd_alloc_scbs(struct ahd_softc *ahd) SLIST_INSERT_HEAD(&scb_data->hscb_maps, hscb_map, links); - ahd_dmamap_load(ahd, scb_data->hscb_dmat, hscb_map->dmamap, + aic_dmamap_load(ahd, scb_data->hscb_dmat, hscb_map->dmamap, hscb_map->vaddr, PAGE_SIZE, ahd_dmamap_cb, - &hscb_map->physaddr, /*flags*/0); + &hscb_map->busaddr, /*flags*/0); hscb = (struct hardware_scb *)hscb_map->vaddr; - hscb_busaddr = hscb_map->physaddr; + hscb_busaddr = hscb_map->busaddr; scb_data->scbs_left = PAGE_SIZE / sizeof(*hscb); } @@ -5977,7 +5973,7 @@ ahd_alloc_scbs(struct ahd_softc *ahd) - scb_data->sgs_left) * ahd_sglist_size(ahd); sg_map = SLIST_FIRST(&scb_data->sg_maps); segs = sg_map->vaddr + offset; - sg_busaddr = sg_map->physaddr + offset; + sg_busaddr = sg_map->busaddr + offset; } else { sg_map = malloc(sizeof(*sg_map), M_DEVBUF, M_NOWAIT); @@ -5985,7 +5981,7 @@ ahd_alloc_scbs(struct ahd_softc *ahd) return; /* Allocate the next batch of S/G lists */ - if (ahd_dmamem_alloc(ahd, scb_data->sg_dmat, + if (aic_dmamem_alloc(ahd, scb_data->sg_dmat, (void **)&sg_map->vaddr, BUS_DMA_NOWAIT, &sg_map->dmamap) != 0) { free(sg_map, M_DEVBUF); @@ -5994,12 +5990,12 @@ ahd_alloc_scbs(struct ahd_softc *ahd) SLIST_INSERT_HEAD(&scb_data->sg_maps, sg_map, links); - ahd_dmamap_load(ahd, scb_data->sg_dmat, sg_map->dmamap, + aic_dmamap_load(ahd, scb_data->sg_dmat, sg_map->dmamap, sg_map->vaddr, ahd_sglist_allocsize(ahd), - ahd_dmamap_cb, &sg_map->physaddr, /*flags*/0); + ahd_dmamap_cb, &sg_map->busaddr, /*flags*/0); segs = sg_map->vaddr; - sg_busaddr = sg_map->physaddr; + sg_busaddr = sg_map->busaddr; scb_data->sgs_left = ahd_sglist_allocsize(ahd) / ahd_sglist_size(ahd); #ifdef AHD_DEBUG @@ -6014,7 +6010,7 @@ ahd_alloc_scbs(struct ahd_softc *ahd) offset = PAGE_SIZE - (AHD_SENSE_BUFSIZE * scb_data->sense_left); sense_map = SLIST_FIRST(&scb_data->sense_maps); sense_data = sense_map->vaddr + offset; - sense_busaddr = sense_map->physaddr + offset; + sense_busaddr = sense_map->busaddr + offset; } else { sense_map = malloc(sizeof(*sense_map), M_DEVBUF, M_NOWAIT); @@ -6022,7 +6018,7 @@ ahd_alloc_scbs(struct ahd_softc *ahd) return; /* Allocate the next batch of sense buffers */ - if (ahd_dmamem_alloc(ahd, scb_data->sense_dmat, + if (aic_dmamem_alloc(ahd, scb_data->sense_dmat, (void **)&sense_map->vaddr, BUS_DMA_NOWAIT, &sense_map->dmamap) != 0) { free(sense_map, M_DEVBUF); @@ -6031,12 +6027,12 @@ ahd_alloc_scbs(struct ahd_softc *ahd) SLIST_INSERT_HEAD(&scb_data->sense_maps, sense_map, links); - ahd_dmamap_load(ahd, scb_data->sense_dmat, sense_map->dmamap, + aic_dmamap_load(ahd, scb_data->sense_dmat, sense_map->dmamap, sense_map->vaddr, PAGE_SIZE, ahd_dmamap_cb, - &sense_map->physaddr, /*flags*/0); + &sense_map->busaddr, /*flags*/0); sense_data = sense_map->vaddr; - sense_busaddr = sense_map->physaddr; + sense_busaddr = sense_map->busaddr; scb_data->sense_left = PAGE_SIZE / AHD_SENSE_BUFSIZE; #ifdef AHD_DEBUG if (ahd_debug & AHD_SHOW_MEMORY) @@ -6077,7 +6073,7 @@ ahd_alloc_scbs(struct ahd_softc *ahd) next_scb->sense_busaddr = sense_busaddr; memset(hscb, 0, sizeof(*hscb)); next_scb->hscb = hscb; - hscb->hscb_busaddr = ahd_htole32(hscb_busaddr); + hscb->hscb_busaddr = aic_htole32(hscb_busaddr); /* * The sequencer always starts with the second entry. @@ -6092,7 +6088,7 @@ ahd_alloc_scbs(struct ahd_softc *ahd) next_scb->ahd_softc = ahd; next_scb->flags = SCB_FLAG_NONE; #ifndef __linux__ - error = ahd_dmamap_create(ahd, ahd->buffer_dmat, /*flags*/0, + error = aic_dmamap_create(ahd, ahd->buffer_dmat, /*flags*/0, &next_scb->dmamap); if (error != 0) { free(next_scb, M_DEVBUF); @@ -6100,7 +6096,7 @@ ahd_alloc_scbs(struct ahd_softc *ahd) break; } #endif - next_scb->hscb->tag = ahd_htole16(scb_data->numscbs); + next_scb->hscb->tag = aic_htole16(scb_data->numscbs); col_tag = scb_data->numscbs ^ 0x100; next_scb->col_scb = ahd_find_scb_by_tag(ahd, col_tag); if (next_scb->col_scb != NULL) @@ -6160,7 +6156,6 @@ static const char *termstat_strings[] = { int ahd_init(struct ahd_softc *ahd) { - uint8_t *base_vaddr; uint8_t *next_vaddr; bus_addr_t next_baddr; size_t driver_data_size; @@ -6203,7 +6198,7 @@ ahd_init(struct ahd_softc *ahd) #ifndef __linux__ /* DMA tag for mapping buffers into device visible space. */ - if (ahd_dma_tag_create(ahd, ahd->parent_dmat, /*alignment*/1, + if (aic_dma_tag_create(ahd, ahd->parent_dmat, /*alignment*/1, /*boundary*/BUS_SPACE_MAXADDR_32BIT + 1, /*lowaddr*/ahd->flags & AHD_39BIT_ADDRESSING ? (bus_addr_t)0x7FFFFFFFFFULL @@ -6234,7 +6229,7 @@ ahd_init(struct ahd_softc *ahd) driver_data_size += AHD_TMODE_CMDS * sizeof(struct target_cmd); if ((ahd->bugs & AHD_PKT_BITBUCKET_BUG) != 0) driver_data_size += PKT_OVERRUN_BUFSIZE; - if (ahd_dma_tag_create(ahd, ahd->parent_dmat, /*alignment*/1, + if (aic_dma_tag_create(ahd, ahd->parent_dmat, /*alignment*/1, /*boundary*/BUS_SPACE_MAXADDR_32BIT + 1, /*lowaddr*/BUS_SPACE_MAXADDR_32BIT, /*highaddr*/BUS_SPACE_MAXADDR, @@ -6249,21 +6244,24 @@ ahd_init(struct ahd_softc *ahd) ahd->init_level++; /* Allocation of driver data */ - if (ahd_dmamem_alloc(ahd, ahd->shared_data_dmat, - (void **)&base_vaddr, - BUS_DMA_NOWAIT, &ahd->shared_data_dmamap) != 0) { + if (aic_dmamem_alloc(ahd, ahd->shared_data_dmat, + (void **)&ahd->shared_data_map.vaddr, + BUS_DMA_NOWAIT, + &ahd->shared_data_map.dmamap) != 0) { return (ENOMEM); } ahd->init_level++; /* And permanently map it in */ - ahd_dmamap_load(ahd, ahd->shared_data_dmat, ahd->shared_data_dmamap, - base_vaddr, driver_data_size, ahd_dmamap_cb, - &ahd->shared_data_busaddr, /*flags*/0); - ahd->qoutfifo = (uint16_t *)base_vaddr; + aic_dmamap_load(ahd, ahd->shared_data_dmat, ahd->shared_data_map.dmamap, + ahd->shared_data_map.vaddr, driver_data_size, + ahd_dmamap_cb, &ahd->shared_data_map.busaddr, + /*flags*/0); + ahd->qoutfifo = (uint16_t *)ahd->shared_data_map.vaddr; next_vaddr = (uint8_t *)&ahd->qoutfifo[AHD_QOUT_SIZE]; - next_baddr = ahd->shared_data_busaddr + AHD_QOUT_SIZE*sizeof(uint16_t); + next_baddr = ahd->shared_data_map.busaddr + + AHD_QOUT_SIZE*sizeof(uint16_t); if ((ahd->features & AHD_TARGETMODE) != 0) { ahd->targetcmds = (struct target_cmd *)next_vaddr; next_vaddr += AHD_TMODE_CMDS * sizeof(struct target_cmd); @@ -6284,7 +6282,8 @@ ahd_init(struct ahd_softc *ahd) * specially from the DMA safe memory chunk used for the QOUTFIFO. */ ahd->next_queued_hscb = (struct hardware_scb *)next_vaddr; - ahd->next_queued_hscb->hscb_busaddr = ahd_htole32(next_baddr); + ahd->next_queued_hscb_map = &ahd->shared_data_map; + ahd->next_queued_hscb->hscb_busaddr = aic_htole32(next_baddr); ahd->init_level++; @@ -6375,7 +6374,7 @@ ahd_init(struct ahd_softc *ahd) } init_done: ahd_restart(ahd); - ahd_timer_reset(&ahd->stat_timer, AHD_STAT_UPDATE_US, + aic_timer_reset(&ahd->stat_timer, AHD_STAT_UPDATE_US, ahd_stat_timer, ahd); return (0); } @@ -6436,7 +6435,7 @@ ahd_chip_init(struct ahd_softc *ahd) for (wait = 10000; (ahd_inb(ahd, SBLKCTL) & (ENAB40|ENAB20)) == 0 && wait; wait--) - ahd_delay(100); + aic_delay(100); /* Clear any false bus resets due to the transceivers settling */ ahd_outb(ahd, CLRSINT1, CLRSCSIRSTI); @@ -6634,15 +6633,9 @@ ahd_chip_init(struct ahd_softc *ahd) /* * Tell the sequencer where it can find our arrays in memory. */ - busaddr = ahd->shared_data_busaddr; - ahd_outb(ahd, SHARED_DATA_ADDR, busaddr & 0xFF); - ahd_outb(ahd, SHARED_DATA_ADDR + 1, (busaddr >> 8) & 0xFF); - ahd_outb(ahd, SHARED_DATA_ADDR + 2, (busaddr >> 16) & 0xFF); - ahd_outb(ahd, SHARED_DATA_ADDR + 3, (busaddr >> 24) & 0xFF); - ahd_outb(ahd, QOUTFIFO_NEXT_ADDR, busaddr & 0xFF); - ahd_outb(ahd, QOUTFIFO_NEXT_ADDR + 1, (busaddr >> 8) & 0xFF); - ahd_outb(ahd, QOUTFIFO_NEXT_ADDR + 2, (busaddr >> 16) & 0xFF); - ahd_outb(ahd, QOUTFIFO_NEXT_ADDR + 3, (busaddr >> 24) & 0xFF); + busaddr = ahd->shared_data_map.busaddr; + ahd_outl(ahd, SHARED_DATA_ADDR, busaddr); + ahd_outl(ahd, QOUTFIFO_NEXT_ADDR, busaddr); /* * Setup the allowed SCSI Sequences based on operational mode. @@ -6690,11 +6683,8 @@ ahd_chip_init(struct ahd_softc *ahd) /* * Tell the sequencer which SCB will be the next one it receives. */ - busaddr = ahd_le32toh(ahd->next_queued_hscb->hscb_busaddr); - ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 0, busaddr & 0xFF); - ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 1, (busaddr >> 8) & 0xFF); - ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 2, (busaddr >> 16) & 0xFF); - ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 3, (busaddr >> 24) & 0xFF); + busaddr = aic_le32toh(ahd->next_queued_hscb->hscb_busaddr); + ahd_outl(ahd, NEXT_QUEUED_SCB_ADDR, busaddr); /* * Default to coalescing disabled. @@ -7015,6 +7005,12 @@ ahd_pause_and_flushwork(struct ahd_softc *ahd) struct scb *waiting_scb; ahd_unpause(ahd); + /* + * Give the sequencer some time to service + * any active selections. + */ + aic_delay(200); + ahd_intr(ahd); ahd_pause(ahd); ahd_clear_critical_section(ahd); @@ -7226,11 +7222,8 @@ ahd_qinfifo_requeue(struct ahd_softc *ahd, struct scb *prev_scb, if (prev_scb == NULL) { uint32_t busaddr; - busaddr = ahd_le32toh(scb->hscb->hscb_busaddr); - ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 0, busaddr & 0xFF); - ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 1, (busaddr >> 8) & 0xFF); - ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 2, (busaddr >> 16) & 0xFF); - ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 3, (busaddr >> 24) & 0xFF); + busaddr = aic_le32toh(scb->hscb->hscb_busaddr); + ahd_outl(ahd, NEXT_QUEUED_SCB_ADDR, busaddr); } else { prev_scb->hscb->next_hscb_busaddr = scb->hscb->hscb_busaddr; ahd_sync_scb(ahd, prev_scb, @@ -7336,11 +7329,8 @@ ahd_search_qinfifo(struct ahd_softc *ahd, int target, char channel, * for removal will be re-added to the queue as we go. */ ahd->qinfifonext = qinstart; - busaddr = ahd_le32toh(ahd->next_queued_hscb->hscb_busaddr); - ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 0, busaddr & 0xFF); - ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 1, (busaddr >> 8) & 0xFF); - ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 2, (busaddr >> 16) & 0xFF); - ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 3, (busaddr >> 24) & 0xFF); + busaddr = aic_le32toh(ahd->next_queued_hscb->hscb_busaddr); + ahd_outl(ahd, NEXT_QUEUED_SCB_ADDR, busaddr); while (qinpos != qintail) { scb = ahd_lookup_scb(ahd, ahd->qinfifo[qinpos]); @@ -7361,13 +7351,13 @@ ahd_search_qinfifo(struct ahd_softc *ahd, int target, char channel, cam_status ostat; cam_status cstat; - ostat = ahd_get_transaction_status(scb); + ostat = aic_get_transaction_status(scb); if (ostat == CAM_REQ_INPROG) - ahd_set_transaction_status(scb, + aic_set_transaction_status(scb, status); - cstat = ahd_get_transaction_status(scb); + cstat = aic_get_transaction_status(scb); if (cstat != CAM_REQ_CMP) - ahd_freeze_scb(scb); + aic_freeze_scb(scb); if ((scb->flags & SCB_ACTIVE) == 0) printf("Inactive SCB in qinfifo\n"); ahd_done(ahd, scb); @@ -7503,12 +7493,12 @@ ahd_search_scb_list(struct ahd_softc *ahd, int target, char channel, cam_status ostat; cam_status cstat; - ostat = ahd_get_transaction_status(scb); + ostat = aic_get_transaction_status(scb); if (ostat == CAM_REQ_INPROG) - ahd_set_transaction_status(scb, status); - cstat = ahd_get_transaction_status(scb); + aic_set_transaction_status(scb, status); + cstat = aic_get_transaction_status(scb); if (cstat != CAM_REQ_CMP) - ahd_freeze_scb(scb); + aic_freeze_scb(scb); if ((scb->flags & SCB_ACTIVE) == 0) printf("Inactive SCB in Waiting List\n"); ahd_done(ahd, scb); @@ -7699,11 +7689,11 @@ ahd_abort_scbs(struct ahd_softc *ahd, int target, char channel, if (ahd_match_scb(ahd, scbp, target, channel, lun, tag, role)) { cam_status ostat; - ostat = ahd_get_transaction_status(scbp); + ostat = aic_get_transaction_status(scbp); if (ostat == CAM_REQ_INPROG) - ahd_set_transaction_status(scbp, status); - if (ahd_get_transaction_status(scbp) != CAM_REQ_CMP) - ahd_freeze_scb(scbp); + aic_set_transaction_status(scbp, status); + if (aic_get_transaction_status(scbp) != CAM_REQ_CMP) + aic_freeze_scb(scbp); if ((scbp->flags & SCB_ACTIVE) == 0) printf("Inactive SCB on pending list\n"); ahd_done(ahd, scbp); @@ -7726,11 +7716,11 @@ ahd_reset_current_bus(struct ahd_softc *ahd) scsiseq = ahd_inb(ahd, SCSISEQ0) & ~(ENSELO|ENARBO|SCSIRSTO); ahd_outb(ahd, SCSISEQ0, scsiseq | SCSIRSTO); ahd_flush_device_writes(ahd); - ahd_delay(AHD_BUSRESET_DELAY); + aic_delay(AHD_BUSRESET_DELAY); /* Turn off the bus reset */ ahd_outb(ahd, SCSISEQ0, scsiseq); ahd_flush_device_writes(ahd); - ahd_delay(AHD_BUSRESET_DELAY); + aic_delay(AHD_BUSRESET_DELAY); if ((ahd->bugs & AHD_SCSIRST_BUG) != 0) { /* * 2A Razor #474 @@ -7798,7 +7788,7 @@ ahd_reset_channel(struct ahd_softc *ahd, char channel, int initiate_reset) ahd_outb(ahd, DFCNTRL, ahd_inb(ahd, DFCNTRL) & ~(SCSIEN|HDMAEN)); while ((ahd_inb(ahd, DFCNTRL) & HDMAENACK) != 0) - ahd_delay(10); + aic_delay(10); /* * Set CURRFIFO to the now inactive channel. */ @@ -7811,7 +7801,7 @@ ahd_reset_channel(struct ahd_softc *ahd, char channel, int initiate_reset) */ ahd_clear_msg_state(ahd); ahd_outb(ahd, SIMODE1, - ahd_inb(ahd, SIMODE1) & ~(ENBUSFREE|ENSCSIRST|ENBUSFREE)); + ahd_inb(ahd, SIMODE1) & ~(ENBUSFREE|ENSCSIRST)); if (initiate_reset) ahd_reset_current_bus(ahd); @@ -7893,8 +7883,8 @@ ahd_reset_channel(struct ahd_softc *ahd, char channel, int initiate_reset) */ if ((ahd->flags & AHD_RESET_POLL_ACTIVE) == 0) { ahd->flags |= AHD_RESET_POLL_ACTIVE; - ahd_freeze_simq(ahd); - ahd_timer_reset(&ahd->reset_timer, 0, ahd_reset_poll, ahd); + aic_freeze_simq(ahd); + aic_timer_reset(&ahd->reset_timer, 0, ahd_reset_poll, ahd); } return (found); } @@ -7922,7 +7912,7 @@ ahd_reset_poll(void *arg) ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); ahd_outb(ahd, CLRSINT1, CLRSCSIRSTI); if ((ahd_inb(ahd, SSTAT1) & SCSIRSTI) != 0) { - ahd_timer_reset(&ahd->reset_timer, AHD_RESET_POLL_US, + aic_timer_reset(&ahd->reset_timer, AHD_RESET_POLL_US, ahd_reset_poll, ahd); ahd_unpause(ahd); ahd_unlock(ahd, &s); @@ -7937,7 +7927,7 @@ ahd_reset_poll(void *arg) ahd_unpause(ahd); ahd->flags &= ~AHD_RESET_POLL_ACTIVE; ahd_unlock(ahd, &s); - ahd_release_simq(ahd); + aic_release_simq(ahd); ahd_list_unlock(&l); } @@ -7980,7 +7970,7 @@ ahd_stat_timer(void *arg) ahd->cmdcmplt_bucket = (ahd->cmdcmplt_bucket+1) & (AHD_STAT_BUCKETS-1); ahd->cmdcmplt_total -= ahd->cmdcmplt_counts[ahd->cmdcmplt_bucket]; ahd->cmdcmplt_counts[ahd->cmdcmplt_bucket] = 0; - ahd_timer_reset(&ahd->stat_timer, AHD_STAT_UPDATE_US, + aic_timer_reset(&ahd->stat_timer, AHD_STAT_UPDATE_US, ahd_stat_timer, ahd); ahd_unlock(ahd, &s); ahd_list_unlock(&l); @@ -8001,8 +7991,9 @@ ahd_handle_scb_status(struct ahd_softc *ahd, struct scb *scb) void ahd_handle_scsi_status(struct ahd_softc *ahd, struct scb *scb) { - struct hardware_scb *hscb; - u_int qfreeze_cnt; + struct hardware_scb *hscb; + u_int qfreeze_cnt; + int paused; /* * The sequencer freezes its select-out queue @@ -8012,9 +8003,16 @@ ahd_handle_scsi_status(struct ahd_softc *ahd, struct scb *scb) */ hscb = scb->hscb; + if (ahd_is_paused(ahd)) { + paused = 1; + } else { + paused = 0; + ahd_pause(ahd); + } + /* Freeze the queue until the client sees the error. */ ahd_freeze_devq(ahd, scb); - ahd_freeze_scb(scb); + aic_freeze_scb(scb); qfreeze_cnt = ahd_inw(ahd, QFREEZE_COUNT); if (qfreeze_cnt == 0) { printf("%s: Bad status with 0 qfreeze count!\n", ahd_name(ahd)); @@ -8026,6 +8024,9 @@ ahd_handle_scsi_status(struct ahd_softc *ahd, struct scb *scb) ahd_outb(ahd, SEQ_FLAGS2, ahd_inb(ahd, SEQ_FLAGS2) & ~SELECTOUT_QFROZEN); + if (paused == 0) + ahd_unpause(ahd); + /* Don't want to clobber the original sense code */ if ((scb->flags & SCB_SENSE) != 0) { /* @@ -8033,12 +8034,12 @@ ahd_handle_scsi_status(struct ahd_softc *ahd, struct scb *scb) * a normal command completion. */ scb->flags &= ~SCB_SENSE; - ahd_set_transaction_status(scb, CAM_AUTOSENSE_FAIL); + aic_set_transaction_status(scb, CAM_AUTOSENSE_FAIL); ahd_done(ahd, scb); return; } - ahd_set_transaction_status(scb, CAM_SCSI_STATUS_ERROR); - ahd_set_scsi_status(scb, hscb->shared_data.istatus.scsi_status); + aic_set_transaction_status(scb, CAM_SCSI_STATUS_ERROR); + aic_set_scsi_status(scb, hscb->shared_data.istatus.scsi_status); switch (hscb->shared_data.istatus.scsi_status) { case STATUS_PKT_SENSE: { @@ -8046,7 +8047,7 @@ ahd_handle_scsi_status(struct ahd_softc *ahd, struct scb *scb) ahd_sync_sense(ahd, scb, BUS_DMASYNC_POSTREAD); siu = (struct scsi_status_iu_header *)scb->sense_data; - ahd_set_scsi_status(scb, siu->status); + aic_set_scsi_status(scb, siu->status); #ifdef AHD_DEBUG if ((ahd_debug & AHD_SHOW_SENSE) != 0) { ahd_print_path(ahd, scb); @@ -8087,7 +8088,7 @@ ahd_handle_scsi_status(struct ahd_softc *ahd, struct scb *scb) } } if (siu->status == SCSI_STATUS_OK) - ahd_set_transaction_status(scb, + aic_set_transaction_status(scb, CAM_REQ_CMP_ERR); } if ((siu->flags & SIU_SNSVALID) != 0) { @@ -8117,7 +8118,7 @@ ahd_handle_scsi_status(struct ahd_softc *ahd, struct scb *scb) } #endif - if (ahd_perform_autosense(scb) == 0) + if (aic_perform_autosense(scb) == 0) break; ahd_compile_devinfo(&devinfo, SCB_GET_OUR_ID(scb), @@ -8145,7 +8146,7 @@ ahd_handle_scsi_status(struct ahd_softc *ahd, struct scb *scb) #endif scb->sg_count = 0; sg = ahd_sg_setup(ahd, scb, sg, ahd_get_sense_bufaddr(ahd, scb), - ahd_get_sense_bufsize(ahd, scb), + aic_get_sense_bufsize(ahd, scb), /*last*/TRUE); sc->opcode = REQUEST_SENSE; sc->byte2 = 0; @@ -8154,7 +8155,7 @@ ahd_handle_scsi_status(struct ahd_softc *ahd, struct scb *scb) sc->byte2 = SCB_GET_LUN(scb) << 5; sc->unused[0] = 0; sc->unused[1] = 0; - sc->length = ahd_get_sense_bufsize(ahd, scb); + sc->length = aic_get_sense_bufsize(ahd, scb); sc->control = 0; /* @@ -8174,7 +8175,7 @@ ahd_handle_scsi_status(struct ahd_softc *ahd, struct scb *scb) * errors will be reported before any data * phases occur. */ - if (ahd_get_residual(scb) == ahd_get_transfer_length(scb)) { + if (aic_get_residual(scb) == aic_get_transfer_length(scb)) { ahd_update_neg_request(ahd, &devinfo, tstate, targ_info, AHD_NEG_IF_NON_ASYNC); @@ -8193,7 +8194,7 @@ ahd_handle_scsi_status(struct ahd_softc *ahd, struct scb *scb) * Ensure we have enough time to actually * retrieve the sense. */ - ahd_scb_timer_reset(scb, 5 * 1000000); + aic_scb_timer_reset(scb, 5 * 1000000); break; } case SCSI_STATUS_OK: @@ -8235,7 +8236,7 @@ ahd_calc_residual(struct ahd_softc *ahd, struct scb *scb) */ hscb = scb->hscb; - sgptr = ahd_le32toh(hscb->sgptr); + sgptr = aic_le32toh(hscb->sgptr); if ((sgptr & SG_STATUS_VALID) == 0) /* Case 1 */ return; @@ -8252,10 +8253,10 @@ ahd_calc_residual(struct ahd_softc *ahd, struct scb *scb) * regardless of the role for this SCB. */ spkt = &hscb->shared_data.istatus; - resid_sgptr = ahd_le32toh(spkt->residual_sgptr); + resid_sgptr = aic_le32toh(spkt->residual_sgptr); if ((sgptr & SG_FULL_RESID) != 0) { /* Case 3 */ - resid = ahd_get_transfer_length(scb); + resid = aic_get_transfer_length(scb); } else if ((resid_sgptr & SG_LIST_NULL) != 0) { /* Case 4 */ return; @@ -8264,8 +8265,8 @@ ahd_calc_residual(struct ahd_softc *ahd, struct scb *scb) printf("data overrun detected Tag == 0x%x.\n", SCB_GET_TAG(scb)); ahd_freeze_devq(ahd, scb); - ahd_set_transaction_status(scb, CAM_DATA_RUN_ERR); - ahd_freeze_scb(scb); + aic_set_transaction_status(scb, CAM_DATA_RUN_ERR); + aic_freeze_scb(scb); return; } else if ((resid_sgptr & ~SG_PTR_MASK) != 0) { panic("Bogus resid sgptr value 0x%x\n", resid_sgptr); @@ -8277,7 +8278,7 @@ ahd_calc_residual(struct ahd_softc *ahd, struct scb *scb) * Remainder of the SG where the transfer * stopped. */ - resid = ahd_le32toh(spkt->residual_datacnt) & AHD_SG_LEN_MASK; + resid = aic_le32toh(spkt->residual_datacnt) & AHD_SG_LEN_MASK; sg = ahd_sg_bus_to_virt(ahd, scb, resid_sgptr & SG_PTR_MASK); /* The residual sg_ptr always points to the next sg */ @@ -8288,15 +8289,15 @@ ahd_calc_residual(struct ahd_softc *ahd, struct scb *scb) * SG segments that are after the SG where * the transfer stopped. */ - while ((ahd_le32toh(sg->len) & AHD_DMA_LAST_SEG) == 0) { + while ((aic_le32toh(sg->len) & AHD_DMA_LAST_SEG) == 0) { sg++; - resid += ahd_le32toh(sg->len) & AHD_SG_LEN_MASK; + resid += aic_le32toh(sg->len) & AHD_SG_LEN_MASK; } } if ((scb->flags & SCB_SENSE) == 0) - ahd_set_residual(scb, resid); + aic_set_residual(scb, resid); else - ahd_set_sense_residual(scb, resid); + aic_set_sense_residual(scb, resid); #ifdef AHD_DEBUG if ((ahd_debug & AHD_SHOW_MISC) != 0) { @@ -8408,8 +8409,7 @@ ahd_dumpseq(struct ahd_softc* ahd) max_prog = 2048; ahd_outb(ahd, SEQCTL0, PERRORDIS|FAILDIS|FASTMODE|LOADRAM); - ahd_outb(ahd, PRGMCNT, 0); - ahd_outb(ahd, PRGMCNT+1, 0); + ahd_outw(ahd, PRGMCNT, 0); for (i = 0; i < max_prog; i++) { uint8_t ins_bytes[4]; @@ -8524,8 +8524,7 @@ ahd_loadseq(struct ahd_softc *ahd) downloaded = 0; skip_addr = 0; ahd_outb(ahd, SEQCTL0, PERRORDIS|FAILDIS|FASTMODE|LOADRAM); - ahd_outb(ahd, PRGMCNT, 0); - ahd_outb(ahd, PRGMCNT+1, 0); + ahd_outw(ahd, PRGMCNT, 0); for (i = 0; i < sizeof(seqprog)/4; i++) { if (ahd_check_patch(ahd, &cur_patch, i, &skip_addr) == 0) { @@ -8654,7 +8653,7 @@ ahd_download_instr(struct ahd_softc *ahd, u_int instrptr, uint8_t *dconsts) /* * The firmware is always compiled into a little endian format. */ - instr.integer = ahd_le32toh(*(uint32_t*)&seqprog[instrptr * 4]); + instr.integer = aic_le32toh(*(uint32_t*)&seqprog[instrptr * 4]); fmt1_ins = &instr.format1; fmt3_ins = NULL; @@ -8702,7 +8701,7 @@ ahd_download_instr(struct ahd_softc *ahd, u_int instrptr, uint8_t *dconsts) instr.format1.parity = 1; /* The sequencer is a little endian cpu */ - instr.integer = ahd_htole32(instr.integer); + instr.integer = aic_htole32(instr.integer); ahd_outsb(ahd, SEQRAM, instr.bytes, 4); break; } @@ -8828,7 +8827,7 @@ ahd_dump_card_state(struct ahd_softc *ahd) printf(">>>>>>>>>>>>>>>>>> Dump Card State Begins <<<<<<<<<<<<<<<<<\n" "%s: Dumping Card State at program address 0x%x Mode 0x%x\n", ahd_name(ahd), - ahd_inb(ahd, CURADDR) | (ahd_inb(ahd, CURADDR+1) << 8), + ahd_inw(ahd, CURADDR), ahd_build_mode_state(ahd, ahd->saved_src_mode, ahd->saved_dst_mode)); if (paused) @@ -9073,6 +9072,280 @@ ahd_dump_scbs(struct ahd_softc *ahd) ahd_restore_modes(ahd, saved_modes); } + +/*************************** Timeout Handling *********************************/ +void +ahd_timeout(struct scb *scb) +{ + struct ahd_softc *ahd; + + ahd = scb->ahd_softc; + if ((scb->flags & SCB_ACTIVE) != 0) { + if ((scb->flags & SCB_TIMEDOUT) == 0) { + LIST_INSERT_HEAD(&ahd->timedout_scbs, scb, + timedout_links); + scb->flags |= SCB_TIMEDOUT; + } + ahd_wakeup_recovery_thread(ahd); + } +} + +/* + * ahd_recover_commands determines if any of the commands that have currently + * timedout are the root cause for this timeout. Innocent commands are given + * a new timeout while we wait for the command executing on the bus to timeout. + * This routine is invoked from a thread context so we are allowed to sleep. + * Our lock is not held on entry. + */ +void +ahd_recover_commands(struct ahd_softc *ahd) +{ + struct scb *scb; + struct scb *active_scb; + long s; + int found; + int was_paused; + u_int active_scbptr; + u_int last_phase; + + ahd_lock(ahd, &s); + + /* + * Pause the controller and manually flush any + * commands that have just completed but that our + * interrupt handler has yet to see. + */ + was_paused = ahd_is_paused(ahd); + ahd_pause_and_flushwork(ahd); + + if (LIST_EMPTY(&ahd->timedout_scbs) != 0) { + /* + * The timedout commands have already + * completed. This typically means + * that either the timeout value was on + * the hairy edge of what the device + * requires or - more likely - interrupts + * are not happening. + */ + printf("%s: Timedout SCBs already complete. " + "Interrupts may not be functioning.\n", ahd_name(ahd)); + ahd_unpause(ahd); + ahd_unlock(ahd, &s); + return; + } + + printf("%s: Recovery Initiated - Card was %spaused\n", ahd_name(ahd), + was_paused ? "" : "not "); + ahd_dump_card_state(ahd); + + /* + * Determine identity of SCB acting on the bus. + * This test only catches non-packetized transactions. + * Due to the fleeting nature of packetized operations, + * we can't easily determine that a packetized operation + * is on the bus. + */ + ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); + last_phase = ahd_inb(ahd, LASTPHASE); + active_scbptr = ahd_get_scbptr(ahd); + active_scb = NULL; + if (last_phase != P_BUSFREE + || (ahd_inb(ahd, SEQ_FLAGS) & NOT_IDENTIFIED) == 0) + active_scb = ahd_lookup_scb(ahd, active_scbptr); + + while ((scb = LIST_FIRST(&ahd->timedout_scbs)) != NULL) { + int target; + int lun; + char channel; + + target = SCB_GET_TARGET(ahd, scb); + channel = SCB_GET_CHANNEL(ahd, scb); + lun = SCB_GET_LUN(scb); + + ahd_print_path(ahd, scb); + printf("SCB 0x%x - timed out\n", scb->hscb->tag); + + if (scb->flags & (SCB_DEVICE_RESET|SCB_ABORT)) { + /* + * Been down this road before. + * Do a full bus reset. + */ + aic_set_transaction_status(scb, CAM_CMD_TIMEOUT); +bus_reset: + found = ahd_reset_channel(ahd, channel, + /*Initiate Reset*/TRUE); + printf("%s: Issued Channel %c Bus Reset. " + "%d SCBs aborted\n", ahd_name(ahd), channel, + found); + continue; + } + + /* + * Remove the command from the timedout list in + * preparation for requeing it. + */ + LIST_REMOVE(scb, timedout_links); + scb->flags &= ~SCB_TIMEDOUT; + + if (active_scb != NULL) { + + if (active_scb != scb) { + /* + * If the active SCB is not us, assume that + * the active SCB has a longer timeout than + * the timedout SCB, and wait for the active + * SCB to timeout. + */ + ahd_other_scb_timeout(ahd, scb, active_scb); + continue; + } + + /* + * We're active on the bus, so assert ATN + * and hope that the target responds. + */ + ahd_set_recoveryscb(ahd, active_scb); + active_scb->flags |= SCB_RECOVERY_SCB|SCB_DEVICE_RESET; + ahd_outb(ahd, MSG_OUT, HOST_MSG); + ahd_outb(ahd, SCSISIGO, last_phase|ATNO); + ahd_print_path(ahd, active_scb); + printf("BDR message in message buffer\n"); + aic_scb_timer_reset(scb, 2 * 1000000); + break; + } else if (last_phase != P_BUSFREE + && ahd_inb(ahd, SCSIPHASE) == 0) { + /* + * SCB is not identified, there + * is no pending REQ, and the sequencer + * has not seen a busfree. Looks like + * a stuck connection waiting to + * go busfree. Reset the bus. + */ + printf("%s: Connection stuck awaiting busfree or " + "Identify Msg.\n", ahd_name(ahd)); + goto bus_reset; + } else if (ahd_search_qinfifo(ahd, target, channel, lun, + scb->hscb->tag, ROLE_INITIATOR, + /*status*/0, SEARCH_COUNT) > 0) { + + /* + * We haven't even gone out on the bus + * yet, so the timeout must be due to + * some other command. Reset the timer + * and go on. + */ + ahd_other_scb_timeout(ahd, scb, scb); + } else { + /* + * This SCB is for a disconnected transaction + * and we haven't found a better candidate on + * the bus to explain this timeout. + */ + ahd_set_recoveryscb(ahd, scb); + + /* + * Actually re-queue this SCB in an attempt + * to select the device before it reconnects. + * In either case (selection or reselection), + * we will now issue a target reset to the + * timed-out device. + * + * Set the MK_MESSAGE control bit indicating + * that we desire to send a message. We + * also set the disconnected flag since + * in the paging case there is no guarantee + * that our SCB control byte matches the + * version on the card. We don't want the + * sequencer to abort the command thinking + * an unsolicited reselection occurred. + */ + scb->flags |= SCB_DEVICE_RESET; + scb->hscb->cdb_len = 0; + scb->hscb->task_attribute = 0; + scb->hscb->task_management = SIU_TASKMGMT_ABORT_TASK; + + ahd_set_scbptr(ahd, SCB_GET_TAG(scb)); + if ((scb->flags & SCB_PACKETIZED) != 0) { + /* + * Mark the SCB has having an outstanding + * task management function. Should the command + * complete normally before the task management + * function can be sent, the host will be + * notified to abort our requeued SCB. + */ + ahd_outb(ahd, SCB_TASK_MANAGEMENT, + scb->hscb->task_management); + } else { + /* + * If non-packetized, set the MK_MESSAGE control + * bit indicating that we desire to send a + * message. We also set the disconnected flag + * since there is no guarantee that our SCB + * control byte matches the version on the + * card. We don't want the sequencer to abort + * the command thinking an unsolicited + * reselection occurred. + */ + scb->hscb->control |= MK_MESSAGE|DISCONNECTED; + + /* + * The sequencer will never re-reference the + * in-core SCB. To make sure we are notified + * during reslection, set the MK_MESSAGE flag in + * the card's copy of the SCB. + */ + ahd_outb(ahd, SCB_CONTROL, + ahd_inb(ahd, SCB_CONTROL)|MK_MESSAGE); + } + + /* + * Clear out any entries in the QINFIFO first + * so we are the next SCB for this target + * to run. + */ + ahd_search_qinfifo(ahd, target, channel, lun, + SCB_LIST_NULL, ROLE_INITIATOR, + CAM_REQUEUE_REQ, SEARCH_COMPLETE); + ahd_qinfifo_requeue_tail(ahd, scb); + ahd_set_scbptr(ahd, active_scbptr); + ahd_print_path(ahd, scb); + printf("Queuing a BDR SCB\n"); + aic_scb_timer_reset(scb, 2 * 1000000); + break; + } + } + + /* + * Any remaining SCBs were not the "culprit", so remove + * them from the timeout list. The timer for these commands + * will be reset once the recovery SCB completes. + */ + while ((scb = LIST_FIRST(&ahd->timedout_scbs)) != NULL) { + + LIST_REMOVE(scb, timedout_links); + scb->flags &= ~SCB_TIMEDOUT; + } + + ahd_unpause(ahd); + ahd_unlock(ahd, &s); +} + +static void +ahd_other_scb_timeout(struct ahd_softc *ahd, struct scb *scb, + struct scb *other_scb) +{ + u_int newtimeout; + + ahd_print_path(ahd, scb); + printf("Other SCB Timeout%s", + (scb->flags & SCB_OTHERTCL_TIMEOUT) != 0 + ? " again\n" : "\n"); + scb->flags |= SCB_OTHERTCL_TIMEOUT; + newtimeout = MAX(aic_get_timeout(other_scb), + aic_get_timeout(scb)); + aic_scb_timer_reset(scb, newtimeout); +} + /**************************** Flexport Logic **********************************/ /* * Read count 16bit words from 16bit word address start_addr from the @@ -9179,9 +9452,9 @@ ahd_wait_seeprom(struct ahd_softc *ahd) { int cnt; - cnt = 20; + cnt = 5000; while ((ahd_inb(ahd, SEESTAT) & (SEEARBACK|SEEBUSY)) != 0 && --cnt) - ahd_delay(5); + aic_delay(5); if (cnt == 0) return (ETIMEDOUT); @@ -9323,7 +9596,7 @@ ahd_wait_flexport(struct ahd_softc *ahd) AHD_ASSERT_MODES(ahd, AHD_MODE_SCSI_MSK, AHD_MODE_SCSI_MSK); cnt = 1000000 * 2 / 5; while ((ahd_inb(ahd, BRDCTL) & FLXARBACK) == 0 && --cnt) - ahd_delay(5); + aic_delay(5); if (cnt == 0) return (ETIMEDOUT); @@ -9525,13 +9798,9 @@ ahd_handle_en_lun(struct ahd_softc *ahd, struct cam_sim *sim, union ccb *ccb) if ((ahd->features & AHD_MULTI_TID) != 0) { u_int targid_mask; - targid_mask = ahd_inb(ahd, TARGID) - | (ahd_inb(ahd, TARGID + 1) << 8); - + targid_mask = ahd_inw(ahd, TARGID); targid_mask |= target_mask; - ahd_outb(ahd, TARGID, targid_mask); - ahd_outb(ahd, TARGID+1, (targid_mask >> 8)); - + ahd_outw(ahd, TARGID, targid_mask); ahd_update_scsiid(ahd, targid_mask); } else { u_int our_id; @@ -9645,14 +9914,9 @@ ahd_handle_en_lun(struct ahd_softc *ahd, struct cam_sim *sim, union ccb *ccb) if (ahd->features & AHD_MULTI_TID) { u_int targid_mask; - targid_mask = ahd_inb(ahd, TARGID) - | (ahd_inb(ahd, TARGID + 1) - << 8); - + targid_mask = ahd_inw(ahd, TARGID); targid_mask &= ~target_mask; - ahd_outb(ahd, TARGID, targid_mask); - ahd_outb(ahd, TARGID+1, - (targid_mask >> 8)); + ahd_outw(ahd, TARGID, targid_mask); ahd_update_scsiid(ahd, targid_mask); } } diff --git a/sys/dev/aic7xxx/aic79xx.h b/sys/dev/aic7xxx/aic79xx.h index 16706e3..a9b7ae1 100644 --- a/sys/dev/aic7xxx/aic79xx.h +++ b/sys/dev/aic7xxx/aic79xx.h @@ -37,7 +37,7 @@ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * - * $Id: //depot/aic7xxx/aic7xxx/aic79xx.h#94 $ + * $Id: //depot/aic7xxx/aic7xxx/aic79xx.h#101 $ * * $FreeBSD$ */ @@ -74,9 +74,9 @@ struct scb_platform_data; #define ALL_TARGETS_MASK 0xFFFF #define INITIATOR_WILDCARD (~0) #define SCB_LIST_NULL 0xFF00 -#define SCB_LIST_NULL_LE (ahd_htole16(SCB_LIST_NULL)) +#define SCB_LIST_NULL_LE (aic_htole16(SCB_LIST_NULL)) #define QOUTFIFO_ENTRY_VALID 0x8000 -#define QOUTFIFO_ENTRY_VALID_LE (ahd_htole16(0x8000)) +#define QOUTFIFO_ENTRY_VALID_LE (aic_htole16(0x8000)) #define SCBID_IS_NULL(scbid) (((scbid) & 0xFF00 ) == SCB_LIST_NULL) #define SCSIID_TARGET(ahd, scsiid) \ @@ -118,7 +118,7 @@ struct scb_platform_data; ((lun) | ((target) << 8)) #define SCB_GET_TAG(scb) \ - ahd_le16toh(scb->hscb->tag) + aic_le16toh(scb->hscb->tag) #ifndef AHD_TARGET_MODE #undef AHD_TMODE_ENABLE @@ -229,6 +229,7 @@ typedef enum { AHD_RTI = 0x04000,/* Retained Training Support */ AHD_NEW_IOCELL_OPTS = 0x08000,/* More Signal knobs in the IOCELL */ AHD_NEW_DFCNTRL_OPTS = 0x10000,/* SCSIENWRDIS bit */ + AHD_FAST_CDB_DELIVERY = 0x20000,/* CDB acks released to Output Sync */ AHD_REMOVABLE = 0x00000,/* Hot-Swap supported - None so far*/ AHD_AIC7901_FE = AHD_FENONE, AHD_AIC7901A_FE = AHD_FENONE, @@ -374,7 +375,8 @@ typedef enum { AHD_RESET_POLL_ACTIVE = 0x200000, AHD_UPDATE_PEND_CMDS = 0x400000, AHD_RUNNING_QOUTFIFO = 0x800000, - AHD_HAD_FIRST_SEL = 0x1000000 + AHD_HAD_FIRST_SEL = 0x1000000, + AHD_SHUTDOWN_RECOVERY = 0x2000000 /* Terminate recovery thread. */ } ahd_flag; /************************* Hardware SCB Definition ***************************/ @@ -548,7 +550,7 @@ struct ahd_dma64_seg { struct map_node { bus_dmamap_t dmamap; - bus_addr_t physaddr; + bus_addr_t busaddr; uint8_t *vaddr; SLIST_ENTRY(map_node) links; }; @@ -590,12 +592,16 @@ typedef enum { SCB_PKT_SENSE = 0x02000, SCB_CMDPHASE_ABORT = 0x04000, SCB_ON_COL_LIST = 0x08000, - SCB_SILENT = 0x10000 /* + SCB_SILENT = 0x10000,/* * Be quiet about transmission type * errors. They are expected and we * don't want to upset the user. This * flag is typically used during DV. */ + SCB_TIMEDOUT = 0x20000/* + * SCB has timed out and is on the + * timedout list. + */ } scb_flag; struct scb { @@ -612,8 +618,9 @@ struct scb { } links2; #define pending_links links2.le #define collision_links links2.le + LIST_ENTRY(scb) timedout_links; struct scb *col_scb; - ahd_io_ctx_t io_ctx; + aic_io_ctx_t io_ctx; struct ahd_softc *ahd_softc; scb_flag flags; #ifndef __linux__ @@ -1061,6 +1068,7 @@ struct ahd_softc { struct scb_data scb_data; struct hardware_scb *next_queued_hscb; + struct map_node *next_queued_hscb_map; /* * SCBs that have been sent to the controller @@ -1068,6 +1076,11 @@ struct ahd_softc { LIST_HEAD(, scb) pending_scbs; /* + * SCBs whose timeout routine has been called. + */ + LIST_HEAD(, scb) timedout_scbs; + + /* * Current register window mode information. */ ahd_mode dst_mode; @@ -1088,7 +1101,7 @@ struct ahd_softc { /* * Platform specific device information. */ - ahd_dev_softc_t dev_softc; + aic_dev_softc_t dev_softc; /* * Bus specific device information. @@ -1118,8 +1131,8 @@ struct ahd_softc { /* * Timer handles for timer driven callbacks. */ - ahd_timer_t reset_timer; - ahd_timer_t stat_timer; + aic_timer_t reset_timer; + aic_timer_t stat_timer; /* * Statistics. @@ -1196,8 +1209,7 @@ struct ahd_softc { */ bus_dma_tag_t parent_dmat; bus_dma_tag_t shared_data_dmat; - bus_dmamap_t shared_data_dmamap; - bus_addr_t shared_data_busaddr; + struct map_node shared_data_map; /* Information saved through suspend/resume cycles */ struct ahd_suspend_state suspend_state; @@ -1340,7 +1352,7 @@ ahd_unbusy_tcl(struct ahd_softc *ahd, u_int tcl) } /***************************** PCI Front End *********************************/ -struct ahd_pci_identity *ahd_find_pci_device(ahd_dev_softc_t); +struct ahd_pci_identity *ahd_find_pci_device(aic_dev_softc_t); int ahd_pci_config(struct ahd_softc *, struct ahd_pci_identity *); int ahd_pci_test_register_access(struct ahd_softc *); @@ -1432,6 +1444,8 @@ void ahd_handle_scsi_status(struct ahd_softc *ahd, struct scb *scb); void ahd_calc_residual(struct ahd_softc *ahd, struct scb *scb); +void ahd_timeout(struct scb *scb); +void ahd_recover_commands(struct ahd_softc *ahd); /*************************** Utility Functions ********************************/ struct ahd_phase_table_entry* ahd_lookup_phase_entry(int phase); diff --git a/sys/dev/aic7xxx/aic79xx.seq b/sys/dev/aic7xxx/aic79xx.seq index 4022a74..68c539b 100644 --- a/sys/dev/aic7xxx/aic79xx.seq +++ b/sys/dev/aic7xxx/aic79xx.seq @@ -40,7 +40,7 @@ * $FreeBSD$ */ -VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#96 $" +VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#107 $" PATCH_ARG_LIST = "struct ahd_softc *ahd" PREFIX = "ahd_" @@ -90,6 +90,13 @@ idle_loop_check_nonpackreq: test SSTAT2, NONPACKREQ jz . + 2; call unexpected_nonpkt_phase_find_ctxt; if ((ahd->bugs & AHD_FAINT_LED_BUG) != 0) { + /* + * On Rev A. hardware, the busy LED is only + * turned on automaically during selections + * and re-selections. Make the LED status + * more useful by forcing it to be on so + * long as one of our data FIFOs is active. + */ and A, FIFO0FREE|FIFO1FREE, DFFSTAT; cmp A, FIFO0FREE|FIFO1FREE jne . + 3; and SBLKCTL, ~DIAGLEDEN|DIAGLEDON; @@ -101,9 +108,9 @@ idle_loop_check_nonpackreq: call idle_loop_cchan; jmp idle_loop; -BEGIN_CRITICAL; idle_loop_gsfifo: SET_MODE(M_SCSI, M_SCSI) +BEGIN_CRITICAL; idle_loop_gsfifo_in_scsi_mode: test LQISTAT2, LQIGSAVAIL jz return; /* @@ -152,25 +159,28 @@ END_CRITICAL; idle_loop_service_fifos: SET_MODE(M_DFF0, M_DFF0) +BEGIN_CRITICAL; test LONGJMP_ADDR[1], INVALID_ADDR jnz idle_loop_next_fifo; call longjmp; +END_CRITICAL; idle_loop_next_fifo: SET_MODE(M_DFF1, M_DFF1) +BEGIN_CRITICAL; test LONGJMP_ADDR[1], INVALID_ADDR jz longjmp; +END_CRITICAL; return: ret; idle_loop_cchan: SET_MODE(M_CCHAN, M_CCHAN) test QOFF_CTLSTA, HS_MAILBOX_ACT jz hs_mailbox_empty; - mov LOCAL_HS_MAILBOX, HS_MAILBOX; or QOFF_CTLSTA, HS_MAILBOX_ACT; + mov LOCAL_HS_MAILBOX, HS_MAILBOX; hs_mailbox_empty: BEGIN_CRITICAL; test CCSCBCTL, CCARREN|CCSCBEN jz scbdma_idle; test CCSCBCTL, CCSCBDIR jnz fetch_new_scb_inprog; test CCSCBCTL, CCSCBDONE jz return; -END_CRITICAL; /* FALLTHROUGH */ scbdma_tohost_done: test CCSCBCTL, CCARREN jz fill_qoutfifo_dmadone; @@ -180,26 +190,18 @@ scbdma_tohost_done: * bad SCSI status (currently only for underruns), we * queue the SCB for normal completion. Otherwise, we * wait until any select-out activity has halted, and - * then notify the host so that the transaction can be - * dealt with. + * then queue the completion. */ - test SCB_SCSI_STATUS, 0xff jnz scbdma_notify_host; - and CCSCBCTL, ~(CCARREN|CCSCBEN); - bmov COMPLETE_DMA_SCB_HEAD, SCB_NEXT_COMPLETE, 2; - bmov SCB_NEXT_COMPLETE, COMPLETE_SCB_HEAD, 2; - bmov COMPLETE_SCB_HEAD, SCBPTR, 2 ret; -scbdma_notify_host: + test SCB_SCSI_STATUS, 0xff jz scbdma_queue_completion; SET_MODE(M_SCSI, M_SCSI) test SCSISEQ0, ENSELO jnz return; test SSTAT0, (SELDO|SELINGO) jnz return; SET_MODE(M_CCHAN, M_CCHAN) - /* - * Remove SCB and notify host. - */ +scbdma_queue_completion: and CCSCBCTL, ~(CCARREN|CCSCBEN); bmov COMPLETE_DMA_SCB_HEAD, SCB_NEXT_COMPLETE, 2; - SET_SEQINTCODE(BAD_SCB_STATUS) - ret; + bmov SCB_NEXT_COMPLETE, COMPLETE_SCB_HEAD, 2; + bmov COMPLETE_SCB_HEAD, SCBPTR, 2 ret; fill_qoutfifo_dmadone: and CCSCBCTL, ~(CCARREN|CCSCBEN); call qoutfifo_updated; @@ -208,6 +210,7 @@ fill_qoutfifo_dmadone: test QOFF_CTLSTA, SDSCB_ROLLOVR jz return; bmov QOUTFIFO_NEXT_ADDR, SHARED_DATA_ADDR, 4; xor QOUTFIFO_ENTRY_VALID_TAG, QOUTFIFO_ENTRY_VALID_TOGGLE ret; +END_CRITICAL; qoutfifo_updated: /* @@ -490,14 +493,30 @@ allocate_fifo1: SET_SRC_MODE M_SCSI; SET_DST_MODE M_SCSI; select_in: + if ((ahd->bugs & AHD_FAINT_LED_BUG) != 0) { + /* + * On Rev A. hardware, the busy LED is only + * turned on automaically during selections + * and re-selections. Make the LED status + * more useful by forcing it to be on from + * the point of selection until our idle + * loop determines that neither of our FIFOs + * are busy. This handles the non-packetized + * case nicely as we will not return to the + * idle loop until the busfree at the end of + * each transaction. + */ + or SBLKCTL, DIAGLEDEN|DIAGLEDON; + } if ((ahd->bugs & AHD_BUSFREEREV_BUG) != 0) { /* - * This exposes a window whereby a - * busfree just after a selection will - * be missed, but there is no other safe - * way to enable busfree detection if - * the busfreerev function is broken. + * Test to ensure that the bus has not + * already gone free prior to clearing + * any stale busfree status. This avoids + * a window whereby a busfree just after + * a selection could be missed. */ + test SCSISIGI, BSYI jz . + 2; mvi CLRSINT1,CLRBUSFREE; or SIMODE1, ENBUSFREE; } @@ -527,6 +546,21 @@ SET_SRC_MODE M_SCSI; SET_DST_MODE M_SCSI; select_out: BEGIN_CRITICAL; + if ((ahd->bugs & AHD_FAINT_LED_BUG) != 0) { + /* + * On Rev A. hardware, the busy LED is only + * turned on automaically during selections + * and re-selections. Make the LED status + * more useful by forcing it to be on from + * the point of re-selection until our idle + * loop determines that neither of our FIFOs + * are busy. This handles the non-packetized + * case nicely as we will not return to the + * idle loop until the busfree at the end of + * each transaction. + */ + or SBLKCTL, DIAGLEDEN|DIAGLEDON; + } /* Clear out all SCBs that have been successfully sent. */ if ((ahd->bugs & AHD_SENT_SCB_UPDATE_BUG) != 0) { /* @@ -648,12 +682,13 @@ select_out_non_packetized: and SCSISEQ0, ~ENSELO; if ((ahd->bugs & AHD_BUSFREEREV_BUG) != 0) { /* - * This exposes a window whereby a - * busfree just after a selection will - * be missed, but there is no other safe - * way to enable busfree detection if - * the busfreerev function is broken. + * Test to ensure that the bus has not + * already gone free prior to clearing + * any stale busfree status. This avoids + * a window whereby a busfree just after + * a selection could be missed. */ + test SCSISIGI, BSYI jz . + 2; mvi CLRSINT1,CLRBUSFREE; or SIMODE1, ENBUSFREE; } @@ -726,13 +761,38 @@ p_command_embedded: mvi DFCNTRL, SCSIEN; p_command_xfer: and SEQ_FLAGS, ~NO_CDB_SENT; - test DFCNTRL, SCSIEN jnz .; + if ((ahd->features & AHD_FAST_CDB_DELIVERY) != 0) { + /* + * To speed up CDB delivery in Rev B, all CDB acks + * are "released" to the output sync as soon as the + * command phase starts. There is only one problem + * with this approach. If the target changes phase + * before all data are sent, we have left over acks + * that can go out on the bus in a data phase. Due + * to other chip contraints, this only happens if + * the target goes to data-in, but if the acks go + * out before we can test SDONE, we'll think that + * the transfer has completed successfully. Work + * around this by taking advantage of the 400ns or + * 800ns dead time between command phase and the REQ + * of the new phase. If the transfer has completed + * successfully, SCSIEN should fall *long* before we + * see a phase change. We thus treat any phasemiss + * that occurs before SCSIEN falls as an incomplete + * transfer. + */ + test SSTAT1, PHASEMIS jnz p_command_xfer_failed; + test DFCNTRL, SCSIEN jnz . - 1; + } else { + test DFCNTRL, SCSIEN jnz .; + } /* * DMA Channel automatically disabled. * Don't allow a data phase if the command * was not fully transferred. */ test SSTAT2, SDONE jnz ITloop; +p_command_xfer_failed: or SEQ_FLAGS, NO_CDB_SENT; jmp ITloop; @@ -1058,8 +1118,10 @@ queue_scb_completion: test SCB_SGPTR, SG_FULL_RESID jnz upload_scb;/* Never xfered */ test SCB_RESIDUAL_SGPTR, SG_LIST_NULL jz upload_scb; complete: +BEGIN_CRITICAL; bmov SCB_NEXT_COMPLETE, COMPLETE_SCB_HEAD, 2; bmov COMPLETE_SCB_HEAD, SCBPTR, 2 ret; +END_CRITICAL; bad_status: cmp SCB_SCSI_STATUS, STATUS_PKT_SENSE je upload_scb; call freeze_queue; @@ -1070,9 +1132,11 @@ upload_scb: * it on the host. */ bmov SCB_TAG, SCBPTR, 2; +BEGIN_CRITICAL; bmov SCB_NEXT_COMPLETE, COMPLETE_DMA_SCB_HEAD, 2; bmov COMPLETE_DMA_SCB_HEAD, SCBPTR, 2; or SCB_SGPTR, SG_STATUS_VALID ret; +END_CRITICAL; /* * Is it a disconnect message? Set a flag in the SCB to remind us @@ -1119,8 +1183,18 @@ SET_DST_MODE M_DFF1; await_busfree_clrchn: mvi DFFSXFRCTL, CLRCHN; await_busfree_not_m_dff: - call clear_target_state; + /* clear target specific flags */ + mvi SEQ_FLAGS, NOT_IDENTIFIED|NO_CDB_SENT; test SSTAT1,REQINIT|BUSFREE jz .; + /* + * We only set BUSFREE status once either a new + * phase has been detected or we are really + * BUSFREE. This allows the driver to know + * that we are active on the bus even though + * no identified transaction exists should a + * timeout occur while awaiting busfree. + */ + mvi LASTPHASE, P_BUSFREE; test SSTAT1, BUSFREE jnz idle_loop; SET_SEQINTCODE(MISSED_BUSFREE) @@ -1175,11 +1249,6 @@ msgin_rdptrs_get_fifo: call allocate_fifo; jmp mesgin_done; -clear_target_state: - mvi LASTPHASE, P_BUSFREE; - /* clear target specific flags */ - mvi SEQ_FLAGS, NOT_IDENTIFIED|NO_CDB_SENT ret; - phase_lock: if ((ahd->bugs & AHD_EARLY_REQ_BUG) != 0) { /* @@ -1631,7 +1700,7 @@ export seq_isr: * savepointer in the current FIFO. We do this so that * a pending CTXTDONE or SAVEPTR is visible in the active * FIFO. This status is the only way we can detect if we - * have lost the race (e.g. host paused us) and our attepts + * have lost the race (e.g. host paused us) and our attempts * to disable the channel occurred after all REQs were * already seen and acked (REQINIT never comes true). */ @@ -1640,7 +1709,7 @@ export seq_isr: test DFCNTRL, DIRECTION jz interrupt_return; and DFCNTRL, ~SCSIEN; snapshot_wait_data_valid: - test SEQINTSRC, (CTXTDONE|SAVEPTRS) jnz snapshot_data_valid; + test SEQINTSRC, (CTXTDONE|SAVEPTRS) jnz interrupt_return; test SSTAT1, REQINIT jz snapshot_wait_data_valid; snapshot_data_valid: or DFCNTRL, SCSIEN; @@ -1807,7 +1876,6 @@ pkt_saveptrs_check_status: dec SCB_FIFO_USE_COUNT; test SCB_CONTROL, STATUS_RCVD jnz pkt_complete_scb_if_fifos_idle; mvi DFFSXFRCTL, CLRCHN ret; -END_CRITICAL; /* * LAST_SEG_DONE status has been seen in the current FIFO. @@ -1816,7 +1884,6 @@ END_CRITICAL; * Check for overrun and see if we can complete this command. */ pkt_last_seg_done: -BEGIN_CRITICAL; /* * Mark transfer as completed. */ diff --git a/sys/dev/aic7xxx/aic79xx_inline.h b/sys/dev/aic7xxx/aic79xx_inline.h index 440212a..fabda5ba 100644 --- a/sys/dev/aic7xxx/aic79xx_inline.h +++ b/sys/dev/aic7xxx/aic79xx_inline.h @@ -37,7 +37,7 @@ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * - * $Id: //depot/aic7xxx/aic7xxx/aic79xx_inline.h#51 $ + * $Id: //depot/aic7xxx/aic7xxx/aic79xx_inline.h#55 $ * * $FreeBSD$ */ @@ -250,15 +250,15 @@ ahd_sg_setup(struct ahd_softc *ahd, struct scb *scb, struct ahd_dma64_seg *sg; sg = (struct ahd_dma64_seg *)sgptr; - sg->addr = ahd_htole64(addr); - sg->len = ahd_htole32(len | (last ? AHD_DMA_LAST_SEG : 0)); + sg->addr = aic_htole64(addr); + sg->len = aic_htole32(len | (last ? AHD_DMA_LAST_SEG : 0)); return (sg + 1); } else { struct ahd_dma_seg *sg; sg = (struct ahd_dma_seg *)sgptr; - sg->addr = ahd_htole32(addr & 0xFFFFFFFF); - sg->len = ahd_htole32(len | ((addr >> 8) & 0x7F000000) + sg->addr = aic_htole32(addr & 0xFFFFFFFF); + sg->len = aic_htole32(len | ((addr >> 8) & 0x7F000000) | (last ? AHD_DMA_LAST_SEG : 0)); return (sg + 1); } @@ -273,7 +273,7 @@ ahd_setup_scb_common(struct ahd_softc *ahd, struct scb *scb) /* XXX what about ACA?? It is type 4, but TAG_TYPE == 0x3. */ scb->hscb->task_attribute = scb->hscb->control & SCB_TAG_TYPE; } else { - if (ahd_get_transfer_length(scb) & 0x01) + if (aic_get_transfer_length(scb) & 0x01) scb->hscb->task_attribute = SCB_XFERLEN_ODD; else scb->hscb->task_attribute = 0; @@ -282,7 +282,7 @@ ahd_setup_scb_common(struct ahd_softc *ahd, struct scb *scb) if (scb->hscb->cdb_len <= MAX_CDB_LEN_WITH_SENSE_ADDR || (scb->hscb->cdb_len & SCB_CDB_LEN_PTR) != 0) scb->hscb->shared_data.idata.cdb_plus_saddr.sense_addr = - ahd_htole32(scb->sense_busaddr); + aic_htole32(scb->sense_busaddr); } static __inline void @@ -308,8 +308,8 @@ ahd_setup_data_scb(struct ahd_softc *ahd, struct scb *scb) if ((ahd->flags & AHD_39BIT_ADDRESSING) != 0) { uint64_t high_addr; - high_addr = ahd_le32toh(sg->len) & 0x7F000000; - scb->hscb->dataptr |= ahd_htole64(high_addr << 8); + high_addr = aic_le32toh(sg->len) & 0x7F000000; + scb->hscb->dataptr |= aic_htole64(high_addr << 8); } scb->hscb->datacnt = sg->len; } @@ -319,13 +319,13 @@ ahd_setup_data_scb(struct ahd_softc *ahd, struct scb *scb) * sequencer will clear as soon as a data transfer * occurs. */ - scb->hscb->sgptr = ahd_htole32(scb->sg_list_busaddr|SG_FULL_RESID); + scb->hscb->sgptr = aic_htole32(scb->sg_list_busaddr|SG_FULL_RESID); } static __inline void ahd_setup_noxfer_scb(struct ahd_softc *ahd, struct scb *scb) { - scb->hscb->sgptr = ahd_htole32(SG_LIST_NULL); + scb->hscb->sgptr = aic_htole32(SG_LIST_NULL); scb->hscb->dataptr = 0; scb->hscb->datacnt = 0; } @@ -383,7 +383,7 @@ ahd_sg_virt_to_bus(struct ahd_softc *ahd, struct scb *scb, void *sg) static __inline void ahd_sync_scb(struct ahd_softc *ahd, struct scb *scb, int op) { - ahd_dmamap_sync(ahd, ahd->scb_data.hscb_dmat, + aic_dmamap_sync(ahd, ahd->scb_data.hscb_dmat, scb->hscb_map->dmamap, /*offset*/(uint8_t*)scb->hscb - scb->hscb_map->vaddr, /*len*/sizeof(*scb->hscb), op); @@ -395,7 +395,7 @@ ahd_sync_sglist(struct ahd_softc *ahd, struct scb *scb, int op) if (scb->sg_count == 0) return; - ahd_dmamap_sync(ahd, ahd->scb_data.sg_dmat, + aic_dmamap_sync(ahd, ahd->scb_data.sg_dmat, scb->sg_map->dmamap, /*offset*/scb->sg_list_busaddr - ahd_sg_size(ahd), /*len*/ahd_sg_size(ahd) * scb->sg_count, op); @@ -404,7 +404,7 @@ ahd_sync_sglist(struct ahd_softc *ahd, struct scb *scb, int op) static __inline void ahd_sync_sense(struct ahd_softc *ahd, struct scb *scb, int op) { - ahd_dmamap_sync(ahd, ahd->scb_data.sense_dmat, + aic_dmamap_sync(ahd, ahd->scb_data.sense_dmat, scb->sense_map->dmamap, /*offset*/scb->sense_busaddr, /*len*/AHD_SENSE_BUFSIZE, op); @@ -472,7 +472,7 @@ ahd_complete_scb(struct ahd_softc *ahd, struct scb *scb) { uint32_t sgptr; - sgptr = ahd_le32toh(scb->hscb->sgptr); + sgptr = aic_le32toh(scb->hscb->sgptr); if ((sgptr & SG_STATUS_VALID) != 0) ahd_handle_scb_status(ahd, scb); else @@ -488,7 +488,7 @@ ahd_update_residual(struct ahd_softc *ahd, struct scb *scb) { uint32_t sgptr; - sgptr = ahd_le32toh(scb->hscb->sgptr); + sgptr = aic_le32toh(scb->hscb->sgptr); if ((sgptr & SG_STATUS_VALID) != 0) ahd_calc_residual(ahd, scb); } @@ -522,12 +522,21 @@ do { \ static __inline uint16_t ahd_inw(struct ahd_softc *ahd, u_int port) { + /* + * Read high byte first as some registers increment + * or have other side effects when the low byte is + * read. + */ return ((ahd_inb(ahd, port+1) << 8) | ahd_inb(ahd, port)); } static __inline void ahd_outw(struct ahd_softc *ahd, u_int port, u_int value) { + /* + * Write low byte first to accomodate registers + * such as PRGMCNT where the order maters. + */ ahd_outb(ahd, port, value & 0xFF); ahd_outb(ahd, port+1, (value >> 8) & 0xFF); } @@ -727,7 +736,8 @@ ahd_lookup_scb(struct ahd_softc *ahd, u_int tag) static __inline void ahd_swap_with_next_hscb(struct ahd_softc *ahd, struct scb *scb) { - struct hardware_scb *q_hscb; + struct hardware_scb *q_hscb; + struct map_node *q_hscb_map; uint32_t saved_hscb_busaddr; /* @@ -743,6 +753,7 @@ ahd_swap_with_next_hscb(struct ahd_softc *ahd, struct scb *scb) * locate the correct SCB by SCB_TAG. */ q_hscb = ahd->next_queued_hscb; + q_hscb_map = ahd->next_queued_hscb_map; saved_hscb_busaddr = q_hscb->hscb_busaddr; memcpy(q_hscb, scb->hscb, sizeof(*scb->hscb)); q_hscb->hscb_busaddr = saved_hscb_busaddr; @@ -750,7 +761,9 @@ ahd_swap_with_next_hscb(struct ahd_softc *ahd, struct scb *scb) /* Now swap HSCB pointers. */ ahd->next_queued_hscb = scb->hscb; + ahd->next_queued_hscb_map = scb->hscb_map; scb->hscb = q_hscb; + scb->hscb_map = q_hscb_map; /* Now define the mapping from tag to SCB in the scbindex */ ahd->scb_data.scbindex[SCB_GET_TAG(scb)] = scb; @@ -790,13 +803,13 @@ ahd_queue_scb(struct ahd_softc *ahd, struct scb *scb) if ((ahd_debug & AHD_SHOW_QUEUE) != 0) { uint64_t host_dataptr; - host_dataptr = ahd_le64toh(scb->hscb->dataptr); + host_dataptr = aic_le64toh(scb->hscb->dataptr); printf("%s: Queueing SCB 0x%x bus addr 0x%x - 0x%x%x/0x%x\n", ahd_name(ahd), - SCB_GET_TAG(scb), ahd_le32toh(scb->hscb->hscb_busaddr), + SCB_GET_TAG(scb), aic_le32toh(scb->hscb->hscb_busaddr), (u_int)((host_dataptr >> 32) & 0xFFFFFFFF), (u_int)(host_dataptr & 0xFFFFFFFF), - ahd_le32toh(scb->hscb->datacnt)); + aic_le32toh(scb->hscb->datacnt)); } #endif /* Tell the adapter about the newly queued SCB */ @@ -824,8 +837,8 @@ static __inline int ahd_intr(struct ahd_softc *ahd); static __inline void ahd_sync_qoutfifo(struct ahd_softc *ahd, int op) { - ahd_dmamap_sync(ahd, ahd->shared_data_dmat, ahd->shared_data_dmamap, - /*offset*/0, /*len*/AHC_SCB_MAX * sizeof(uint16_t), op); + aic_dmamap_sync(ahd, ahd->shared_data_dmat, ahd->shared_data_map.dmamap, + /*offset*/0, /*len*/AHD_SCB_MAX * sizeof(uint16_t), op); } static __inline void @@ -833,8 +846,8 @@ ahd_sync_tqinfifo(struct ahd_softc *ahd, int op) { #ifdef AHD_TARGET_MODE if ((ahd->flags & AHD_TARGETROLE) != 0) { - ahd_dmamap_sync(ahd, ahd->shared_data_dmat, - ahd->shared_data_dmamap, + aic_dmamap_sync(ahd, ahd->shared_data_dmat, + ahd->shared_data_map.dmamap, ahd_targetcmd_offset(ahd, 0), sizeof(struct target_cmd) * AHD_TMODE_CMDS, op); @@ -854,7 +867,7 @@ ahd_check_cmdcmpltqueues(struct ahd_softc *ahd) u_int retval; retval = 0; - ahd_dmamap_sync(ahd, ahd->shared_data_dmat, ahd->shared_data_dmamap, + aic_dmamap_sync(ahd, ahd->shared_data_dmat, ahd->shared_data_map.dmamap, /*offset*/ahd->qoutfifonext, /*len*/2, BUS_DMASYNC_POSTREAD); if ((ahd->qoutfifo[ahd->qoutfifonext] @@ -863,8 +876,8 @@ ahd_check_cmdcmpltqueues(struct ahd_softc *ahd) #ifdef AHD_TARGET_MODE if ((ahd->flags & AHD_TARGETROLE) != 0 && (ahd->flags & AHD_TQINFIFO_BLOCKED) == 0) { - ahd_dmamap_sync(ahd, ahd->shared_data_dmat, - ahd->shared_data_dmamap, + aic_dmamap_sync(ahd, ahd->shared_data_dmat, + ahd->shared_data_map.dmamap, ahd_targetcmd_offset(ahd, ahd->tqinfifofnext), /*len*/sizeof(struct target_cmd), BUS_DMASYNC_POSTREAD); diff --git a/sys/dev/aic7xxx/aic79xx_osm.c b/sys/dev/aic7xxx/aic79xx_osm.c index a20ad95..bbe07f6 100644 --- a/sys/dev/aic7xxx/aic79xx_osm.c +++ b/sys/dev/aic7xxx/aic79xx_osm.c @@ -1,5 +1,5 @@ /* - * Bus independent FreeBSD shim for the aic7xxx based adaptec SCSI controllers + * Bus independent FreeBSD shim for the aic79xx based Adaptec SCSI controllers * * Copyright (c) 1994-2002 Justin T. Gibbs. * Copyright (c) 2001-2002 Adaptec Inc. @@ -29,7 +29,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: //depot/aic7xxx/freebsd/dev/aic7xxx/aic79xx_osm.c#27 $ + * $Id: //depot/aic7xxx/freebsd/dev/aic7xxx/aic79xx_osm.c#35 $ */ #include <sys/cdefs.h> @@ -38,6 +38,8 @@ __FBSDID("$FreeBSD$"); #include <dev/aic7xxx/aic79xx_osm.h> #include <dev/aic7xxx/aic79xx_inline.h> +#include <sys/kthread.h> + #include "opt_ddb.h" #ifdef DDB #include <ddb/ddb.h> @@ -47,6 +49,8 @@ __FBSDID("$FreeBSD$"); #define AHD_TMODE_ENABLE 0 #endif +#include <dev/aic7xxx/aic_osm_lib.c> + #define ccb_scb_ptr spriv_ptr0 #if UNUSED @@ -73,21 +77,13 @@ static int ahd_create_path(struct ahd_softc *ahd, char channel, u_int target, u_int lun, struct cam_path **path); -#if NOT_YET -static void ahd_set_recoveryscb(struct ahd_softc *ahd, struct scb *scb); -#endif - static int ahd_create_path(struct ahd_softc *ahd, char channel, u_int target, u_int lun, struct cam_path **path) { path_id_t path_id; - if (channel == 'B') - path_id = cam_sim_path(ahd->platform_data->sim_b); - else - path_id = cam_sim_path(ahd->platform_data->sim); - + path_id = cam_sim_path(ahd->platform_data->sim); return (xpt_create_path(path, /*periph*/NULL, path_id, target, lun)); } @@ -122,8 +118,15 @@ ahd_attach(struct ahd_softc *ahd) int count; count = 0; + devq = NULL; sim = NULL; + /* + * Create a thread to perform all recovery. + */ + if (ahd_spawn_recovery_thread(ahd) != 0) + goto fail; + ahd_controller_info(ahd, ahd_info); printf("%s\n", ahd_info); ahd_lock(ahd, &s); @@ -212,8 +215,10 @@ ahd_done(struct ahd_softc *ahd, struct scb *scb) ccb = scb->io_ctx; LIST_REMOVE(scb, pending_links); + if ((scb->flags & SCB_TIMEDOUT) != 0) + LIST_REMOVE(scb, timedout_links); - untimeout(ahd_timeout, (caddr_t)scb, ccb->ccb_h.timeout_ch); + untimeout(ahd_platform_timeout, (caddr_t)scb, ccb->ccb_h.timeout_ch); if ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) { bus_dmasync_op_t op; @@ -249,7 +254,7 @@ ahd_done(struct ahd_softc *ahd, struct scb *scb) } } - if (ahd_get_transaction_status(scb) == CAM_REQ_INPROG) + if (aic_get_transaction_status(scb) == CAM_REQ_INPROG) ccb->ccb_h.status |= CAM_REQ_CMP; ccb->ccb_h.status &= ~CAM_SIM_QUEUED; ahd_free_scb(ahd, scb); @@ -282,19 +287,20 @@ ahd_done(struct ahd_softc *ahd, struct scb *scb) time *= hz; time /= 1000; ccb->ccb_h.timeout_ch = - timeout(ahd_timeout, list_scb, time); + timeout(ahd_platform_timeout, list_scb, time); } - if (ahd_get_transaction_status(scb) == CAM_BDR_SENT - || ahd_get_transaction_status(scb) == CAM_REQ_ABORTED) - ahd_set_transaction_status(scb, CAM_CMD_TIMEOUT); + if (aic_get_transaction_status(scb) == CAM_BDR_SENT + || aic_get_transaction_status(scb) == CAM_REQ_ABORTED) + aic_set_transaction_status(scb, CAM_CMD_TIMEOUT); + ahd_print_path(ahd, scb); printf("no longer in timeout, status = %x\n", ccb->ccb_h.status); } /* Don't clobber any existing error state */ - if (ahd_get_transaction_status(scb) == CAM_REQ_INPROG) { + if (aic_get_transaction_status(scb) == CAM_REQ_INPROG) { ccb->ccb_h.status |= CAM_REQ_CMP; } else if ((scb->flags & SCB_SENSE) != 0) { /* @@ -551,10 +557,7 @@ ahd_action(struct cam_sim *sim, union ccb *ccb) } case XPT_CALC_GEOMETRY: { - int extended; - - extended = ahd->flags & AHD_EXTENDED_TRANS_A; - cam_calc_geometry(&ccb->ccg, extended); + aic_calc_geometry(&ccb->ccg, ahd->flags & AHD_EXTENDED_TRANS_A); xpt_done(ccb); break; } @@ -1027,9 +1030,9 @@ ahd_execute_scb(void *arg, bus_dma_segment_t *dm_segs, int nsegments, if (error != 0) { if (error == EFBIG) - ahd_set_transaction_status(scb, CAM_REQ_TOO_BIG); + aic_set_transaction_status(scb, CAM_REQ_TOO_BIG); else - ahd_set_transaction_status(scb, CAM_REQ_CMP_ERR); + aic_set_transaction_status(scb, CAM_REQ_CMP_ERR); if (nsegments != 0) bus_dmamap_unload(ahd->buffer_dmat, scb->dmamap); ahd_lock(ahd, &s); @@ -1078,7 +1081,7 @@ ahd_execute_scb(void *arg, bus_dma_segment_t *dm_segs, int nsegments, * Last time we need to check if this SCB needs to * be aborted. */ - if (ahd_get_transaction_status(scb) != CAM_REQ_INPROG) { + if (aic_get_transaction_status(scb) != CAM_REQ_INPROG) { if (nsegments != 0) bus_dmamap_unload(ahd->buffer_dmat, scb->dmamap); @@ -1130,7 +1133,7 @@ ahd_execute_scb(void *arg, bus_dma_segment_t *dm_segs, int nsegments, time *= hz; time /= 1000; ccb->ccb_h.timeout_ch = - timeout(ahd_timeout, (caddr_t)scb, time); + timeout(ahd_platform_timeout, (caddr_t)scb, time); } if ((scb->flags & SCB_TARGET_IMMEDIATE) != 0) { @@ -1178,7 +1181,7 @@ ahd_setup_data(struct ahd_softc *ahd, struct cam_sim *sim, * greater than 16 bytes, we could use * the sense buffer to store the CDB. */ - ahd_set_transaction_status(scb, + aic_set_transaction_status(scb, CAM_REQ_INVALID); ahd_lock(ahd, &s); ahd_free_scb(ahd, scb); @@ -1188,7 +1191,7 @@ ahd_setup_data(struct ahd_softc *ahd, struct cam_sim *sim, } if ((ccb_h->flags & CAM_CDB_PHYS) != 0) { hscb->shared_data.idata.cdb_from_host.cdbptr = - ahd_htole64((uintptr_t)csio->cdb_io.cdb_ptr); + aic_htole64((uintptr_t)csio->cdb_io.cdb_ptr); hscb->shared_data.idata.cdb_from_host.cdblen = csio->cdb_len; hscb->cdb_len |= SCB_CDB_LEN_PTR; @@ -1201,7 +1204,7 @@ ahd_setup_data(struct ahd_softc *ahd, struct cam_sim *sim, if (hscb->cdb_len > MAX_CDB_LEN) { u_long s; - ahd_set_transaction_status(scb, + aic_set_transaction_status(scb, CAM_REQ_INVALID); ahd_lock(ahd, &s); ahd_free_scb(ahd, scb); @@ -1275,299 +1278,6 @@ ahd_setup_data(struct ahd_softc *ahd, struct cam_sim *sim, } } -#if NOT_YET -static void -ahd_set_recoveryscb(struct ahd_softc *ahd, struct scb *scb) { - - if ((scb->flags & SCB_RECOVERY_SCB) == 0) { - struct scb *list_scb; - - scb->flags |= SCB_RECOVERY_SCB; - - /* - * Take all queued, but not sent SCBs out of the equation. - * Also ensure that no new CCBs are queued to us while we - * try to fix this problem. - */ - if ((scb->io_ctx->ccb_h.status & CAM_RELEASE_SIMQ) == 0) { - xpt_freeze_simq(SCB_GET_SIM(ahd, scb), /*count*/1); - scb->io_ctx->ccb_h.status |= CAM_RELEASE_SIMQ; - } - - /* - * Go through all of our pending SCBs and remove - * any scheduled timeouts for them. We will reschedule - * them after we've successfully fixed this problem. - */ - LIST_FOREACH(list_scb, &ahd->pending_scbs, pending_links) { - union ccb *ccb; - - ccb = list_scb->io_ctx; - untimeout(ahd_timeout, list_scb, ccb->ccb_h.timeout_ch); - } - } -} -#endif - -void -ahd_timeout(void *arg) -{ - struct scb *scb; - struct ahd_softc *ahd; - ahd_mode_state saved_modes; - long s; - int target; - int lun; - char channel; - -#if NOT_YET - int i; - int found; - u_int last_phase; -#endif - - scb = (struct scb *)arg; - ahd = (struct ahd_softc *)scb->ahd_softc; - - ahd_lock(ahd, &s); - - ahd_pause_and_flushwork(ahd); - - saved_modes = ahd_save_modes(ahd); -#if 0 - ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); - ahd_outb(ahd, SCSISIGO, ACKO); - printf("set ACK\n"); - ahd_outb(ahd, SCSISIGO, 0); - printf("clearing Ack\n"); - ahd_restore_modes(ahd, saved_modes); -#endif - if ((scb->flags & SCB_ACTIVE) == 0) { - /* Previous timeout took care of me already */ - printf("%s: Timedout SCB already complete. " - "Interrupts may not be functioning.\n", ahd_name(ahd)); - ahd_unpause(ahd); - ahd_unlock(ahd, &s); - return; - } - - target = SCB_GET_TARGET(ahd, scb); - channel = SCB_GET_CHANNEL(ahd, scb); - lun = SCB_GET_LUN(scb); - - ahd_print_path(ahd, scb); - printf("SCB 0x%x - timed out\n", SCB_GET_TAG(scb)); - ahd_dump_card_state(ahd); - ahd_reset_channel(ahd, SIM_CHANNEL(ahd, sim), - /*initiate reset*/TRUE); - ahd_unlock(ahd, &s); - return; -#if NOT_YET - last_phase = ahd_inb(ahd, LASTPHASE); - if (scb->sg_count > 0) { - for (i = 0; i < scb->sg_count; i++) { - printf("sg[%d] - Addr 0x%x : Length %d\n", - i, - ((struct ahd_dma_seg *)scb->sg_list)[i].addr, - ((struct ahd_dma_seg *)scb->sg_list)[i].len - & AHD_SG_LEN_MASK); - } - } - if (scb->flags & (SCB_DEVICE_RESET|SCB_ABORT)) { - /* - * Been down this road before. - * Do a full bus reset. - */ -bus_reset: - ahd_set_transaction_status(scb, CAM_CMD_TIMEOUT); - found = ahd_reset_channel(ahd, channel, /*Initiate Reset*/TRUE); - printf("%s: Issued Channel %c Bus Reset. " - "%d SCBs aborted\n", ahd_name(ahd), channel, found); - } else { - /* - * If we are a target, transition to bus free and report - * the timeout. - * - * The target/initiator that is holding up the bus may not - * be the same as the one that triggered this timeout - * (different commands have different timeout lengths). - * If the bus is idle and we are actiing as the initiator - * for this request, queue a BDR message to the timed out - * target. Otherwise, if the timed out transaction is - * active: - * Initiator transaction: - * Stuff the message buffer with a BDR message and assert - * ATN in the hopes that the target will let go of the bus - * and go to the mesgout phase. If this fails, we'll - * get another timeout 2 seconds later which will attempt - * a bus reset. - * - * Target transaction: - * Transition to BUS FREE and report the error. - * It's good to be the target! - */ - u_int active_scb_index; - u_int saved_scbptr; - - saved_scbptr = ahd_get_scbptr(ahd); - active_scb_index = saved_scbptr; - - if (last_phase != P_BUSFREE - && (ahd_inb(ahd, SEQ_FLAGS) & NOT_IDENTIFIED) == 0 - && (active_scb_index < ahd->scb_data.numscbs)) { - struct scb *active_scb; - - /* - * If the active SCB is not us, assume that - * the active SCB has a longer timeout than - * the timedout SCB, and wait for the active - * SCB to timeout. - */ - active_scb = ahd_lookup_scb(ahd, active_scb_index); - if (active_scb != scb) { - struct ccb_hdr *ccbh; - uint64_t newtimeout; - - ahd_print_path(ahd, scb); - printf("Other SCB Timeout%s", - (scb->flags & SCB_OTHERTCL_TIMEOUT) != 0 - ? " again\n" : "\n"); - scb->flags |= SCB_OTHERTCL_TIMEOUT; - newtimeout = - MAX(active_scb->io_ctx->ccb_h.timeout, - scb->io_ctx->ccb_h.timeout); - newtimeout *= hz; - newtimeout /= 1000; - ccbh = &scb->io_ctx->ccb_h; - scb->io_ctx->ccb_h.timeout_ch = - timeout(ahd_timeout, scb, newtimeout); - ahd_unpause(ahd); - ahd_unlock(ahd, &s); - return; - } - - /* It's us */ - if ((scb->hscb->control & TARGET_SCB) != 0) { - - /* - * Send back any queued up transactions - * and properly record the error condition. - */ - ahd_abort_scbs(ahd, SCB_GET_TARGET(ahd, scb), - SCB_GET_CHANNEL(ahd, scb), - SCB_GET_LUN(scb), - SCB_GET_TAG(scb), - ROLE_TARGET, - CAM_CMD_TIMEOUT); - - /* Will clear us from the bus */ - ahd_restart(ahd); - ahd_unlock(ahd, &s); - return; - } - - ahd_set_recoveryscb(ahd, active_scb); - ahd_outb(ahd, MSG_OUT, HOST_MSG); - ahd_outb(ahd, SCSISIGO, last_phase|ATNO); - ahd_print_path(ahd, active_scb); - printf("BDR message in message buffer\n"); - active_scb->flags |= SCB_DEVICE_RESET; - active_scb->io_ctx->ccb_h.timeout_ch = - timeout(ahd_timeout, (caddr_t)active_scb, 2 * hz); - ahd_unpause(ahd); - } else { - int disconnected; - - /* XXX Shouldn't panic. Just punt instead? */ - if ((scb->hscb->control & TARGET_SCB) != 0) - panic("Timed-out target SCB but bus idle"); - - if (last_phase != P_BUSFREE - && (ahd_inb(ahd, SSTAT0) & TARGET) != 0) { - /* XXX What happened to the SCB? */ - /* Hung target selection. Goto busfree */ - printf("%s: Hung target selection\n", - ahd_name(ahd)); - ahd_restart(ahd); - ahd_unlock(ahd, &s); - return; - } - - if (ahd_search_qinfifo(ahd, target, channel, lun, - SCB_GET_TAG(scb), ROLE_INITIATOR, - /*status*/0, SEARCH_COUNT) > 0) { - disconnected = FALSE; - } else { - disconnected = TRUE; - } - - if (disconnected) { - - ahd_set_recoveryscb(ahd, scb); - /* - * Actually re-queue this SCB in an attempt - * to select the device before it reconnects. - * In either case (selection or reselection), - * we will now issue a target reset to the - * timed-out device. - * - * Set the MK_MESSAGE control bit indicating - * that we desire to send a message. We - * also set the disconnected flag since - * in the paging case there is no guarantee - * that our SCB control byte matches the - * version on the card. We don't want the - * sequencer to abort the command thinking - * an unsolicited reselection occurred. - */ - scb->hscb->control |= MK_MESSAGE|DISCONNECTED; - scb->flags |= SCB_DEVICE_RESET; - - /* - * The sequencer will never re-reference the - * in-core SCB. To make sure we are notified - * during reslection, set the MK_MESSAGE flag - * in the card's copy of the SCB. - */ - ahd_set_scbptr(ahd, SCB_GET_TAG(scb)); - ahd_outb(ahd, SCB_CONTROL, - ahd_inb(ahd, SCB_CONTROL)|MK_MESSAGE); - - /* - * Clear out any entries in the QINFIFO first - * so we are the next SCB for this target - * to run. - */ - ahd_search_qinfifo(ahd, - SCB_GET_TARGET(ahd, scb), - channel, SCB_GET_LUN(scb), - SCB_LIST_NULL, - ROLE_INITIATOR, - CAM_REQUEUE_REQ, - SEARCH_COMPLETE); - ahd_print_path(ahd, scb); - printf("Queuing a BDR SCB\n"); - ahd_qinfifo_requeue_tail(ahd, scb); - ahd_set_scbptr(ahd, saved_scbptr); - scb->io_ctx->ccb_h.timeout_ch = - timeout(ahd_timeout, (caddr_t)scb, 2 * hz); - ahd_unpause(ahd); - } else { - /* Go "immediatly" to the bus reset */ - /* This shouldn't happen */ - ahd_set_recoveryscb(ahd, scb); - ahd_print_path(ahd, scb); - printf("SCB %d: Immediate reset. " - "Flags = 0x%x\n", SCB_GET_TAG(scb), - scb->flags); - goto bus_reset; - } - } - } - ahd_unlock(ahd, &s); -#endif -} - static void ahd_abort_ccb(struct ahd_softc *ahd, struct cam_sim *sim, union ccb *ccb) { @@ -1753,12 +1463,6 @@ ahd_platform_free(struct ahd_softc *ahd) pdata->irq_res_type, 0, pdata->irq); - if (pdata->sim_b != NULL) { - xpt_async(AC_LOST_DEVICE, pdata->path_b, NULL); - xpt_free_path(pdata->path_b); - xpt_bus_deregister(cam_sim_path(pdata->sim_b)); - cam_sim_free(pdata->sim_b, /*free_devq*/TRUE); - } if (pdata->sim != NULL) { xpt_async(AC_LOST_DEVICE, pdata->path, NULL); xpt_free_path(pdata->path); @@ -1794,12 +1498,13 @@ ahd_detach(device_t dev) ahd_list_unlock(&l); return (ENOENT); } + TAILQ_REMOVE(&ahd_tailq, ahd, links); + ahd_list_unlock(&l); ahd_lock(ahd, &s); ahd_intr_enable(ahd, FALSE); bus_teardown_intr(dev, ahd->platform_data->irq, ahd->platform_data->ih); ahd_unlock(ahd, &s); ahd_free(ahd); - ahd_list_unlock(&l); return (0); } diff --git a/sys/dev/aic7xxx/aic79xx_osm.h b/sys/dev/aic7xxx/aic79xx_osm.h index 80a0b8c..4299ec8 100644 --- a/sys/dev/aic7xxx/aic79xx_osm.h +++ b/sys/dev/aic7xxx/aic79xx_osm.h @@ -30,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: aic79xx_osm.h,v 1.11 2003/07/01 15:51:52 scottl Exp $ + * $Id: //depot/aic7xxx/freebsd/dev/aic7xxx/aic79xx_osm.h#23 $ * * $FreeBSD$ */ @@ -51,7 +51,7 @@ #include <sys/malloc.h> #include <sys/queue.h> -#define AHD_PCI_CONFIG 1 +#define AIC_PCI_CONFIG 1 #include <machine/bus_memio.h> #include <machine/bus_pio.h> #include <machine/bus.h> @@ -102,45 +102,6 @@ #ifndef offsetof #define offsetof(type, member) ((size_t)(&((type *)0)->member)) #endif -/************************* Forward Declarations *******************************/ -typedef device_t ahd_dev_softc_t; -typedef union ccb *ahd_io_ctx_t; - -/***************************** Bus Space/DMA **********************************/ -#define ahd_dma_tag_create(ahd, parent_tag, alignment, boundary, \ - lowaddr, highaddr, filter, filterarg, \ - maxsize, nsegments, maxsegsz, flags, \ - dma_tagp) \ - bus_dma_tag_create(parent_tag, alignment, boundary, \ - lowaddr, highaddr, filter, filterarg, \ - maxsize, nsegments, maxsegsz, flags, \ - busdma_lock_mutex, &Giant, dma_tagp) - -#define ahd_dma_tag_destroy(ahd, tag) \ - bus_dma_tag_destroy(tag) - -#define ahd_dmamem_alloc(ahd, dmat, vaddr, flags, mapp) \ - bus_dmamem_alloc(dmat, vaddr, flags, mapp) - -#define ahd_dmamem_free(ahd, dmat, vaddr, map) \ - bus_dmamem_free(dmat, vaddr, map) - -#define ahd_dmamap_create(ahd, tag, flags, mapp) \ - bus_dmamap_create(tag, flags, mapp) - -#define ahd_dmamap_destroy(ahd, tag, map) \ - bus_dmamap_destroy(tag, map) - -#define ahd_dmamap_load(ahd, dmat, map, addr, buflen, callback, \ - callback_arg, flags) \ - bus_dmamap_load(dmat, map, addr, buflen, callback, callback_arg, flags) - -#define ahd_dmamap_unload(ahd, tag, map) \ - bus_dmamap_unload(tag, map) - -/* XXX Need to update Bus DMA for partial map syncs */ -#define ahd_dmamap_sync(ahd, dma_tag, dmamap, offset, len, op) \ - bus_dmamap_sync(dma_tag, dmamap, op) /************************ Tunable Driver Parameters **************************/ /* @@ -168,9 +129,7 @@ struct ahd_platform_data { * Hooks into the XPT. */ struct cam_sim *sim; - struct cam_sim *sim_b; struct cam_path *path; - struct cam_path *path_b; int regs_res_type[2]; int regs_res_id[2]; @@ -179,75 +138,22 @@ struct ahd_platform_data { struct resource *irq; void *ih; eventhandler_tag eh; + struct proc *recovery_thread; }; struct scb_platform_data { }; -/********************************* Byte Order *********************************/ -#if __FreeBSD_version >= 500000 -#define ahd_htobe16(x) htobe16(x) -#define ahd_htobe32(x) htobe32(x) -#define ahd_htobe64(x) htobe64(x) -#define ahd_htole16(x) htole16(x) -#define ahd_htole32(x) htole32(x) -#define ahd_htole64(x) htole64(x) - -#define ahd_be16toh(x) be16toh(x) -#define ahd_be32toh(x) be32toh(x) -#define ahd_be64toh(x) be64toh(x) -#define ahd_le16toh(x) le16toh(x) -#define ahd_le32toh(x) le32toh(x) -#define ahd_le64toh(x) le64toh(x) -#else -#define ahd_htobe16(x) (x) -#define ahd_htobe32(x) (x) -#define ahd_htobe64(x) (x) -#define ahd_htole16(x) (x) -#define ahd_htole32(x) (x) -#define ahd_htole64(x) (x) - -#define ahd_be16toh(x) (x) -#define ahd_be32toh(x) (x) -#define ahd_be64toh(x) (x) -#define ahd_le16toh(x) (x) -#define ahd_le32toh(x) (x) -#define ahd_le64toh(x) (x) -#endif - -/************************** Timer DataStructures ******************************/ -typedef struct callout ahd_timer_t; - /***************************** Core Includes **********************************/ #if AHD_REG_PRETTY_PRINT #define AIC_DEBUG_REGISTERS 1 #else #define AIC_DEBUG_REGISTERS 0 #endif -#include <dev/aic7xxx/aic79xx.h> - -/***************************** Timer Facilities *******************************/ -timeout_t ahd_timeout; -#if __FreeBSD_version >= 500000 -#define ahd_timer_init(timer) callout_init(timer, /*mpsafe*/0) -#else -#define ahd_timer_init callout_init -#endif -#define ahd_timer_stop callout_stop - -static __inline void -ahd_timer_reset(ahd_timer_t *timer, u_int usec, ahd_callback_t *func, void *arg) -{ - callout_reset(timer, (usec * hz)/1000000, func, arg); -} - -static __inline void -ahd_scb_timer_reset(struct scb *scb, u_int usec) -{ - untimeout(ahd_timeout, (caddr_t)scb, scb->io_ctx->ccb_h.timeout_ch); - scb->io_ctx->ccb_h.timeout_ch = - timeout(ahd_timeout, scb, (usec * hz)/1000000); -} +#define AIC_CORE_INCLUDE <dev/aic7xxx/aic79xx.h> +#define AIC_LIB_PREFIX ahd +#define AIC_CONST_PREFIX AHD +#include <dev/aic7xxx/aic_osm_lib.h> /*************************** Device Access ************************************/ #define ahd_inb(ahd, port) \ @@ -259,13 +165,13 @@ ahd_scb_timer_reset(struct scb *scb, u_int usec) (ahd)->bshs[(port) >> 8], (port) & 0xFF, value) #define ahd_inw_atomic(ahd, port) \ - ahd_le16toh(bus_space_read_2((ahd)->tags[(port) >> 8], \ + aic_le16toh(bus_space_read_2((ahd)->tags[(port) >> 8], \ (ahd)->bshs[(port) >> 8], (port) & 0xFF)) #define ahd_outw_atomic(ahd, port, value) \ bus_space_write_2((ahd)->tags[(port) >> 8], \ (ahd)->bshs[(port) >> 8], \ - (port & 0xFF), ahd_htole16(value)) + (port & 0xFF), aic_htole16(value)) #define ahd_outsb(ahd, port, valp, count) \ bus_space_write_multi_1((ahd)->tags[(port) >> 8], \ @@ -350,222 +256,26 @@ static __inline void ahd_list_unlock(unsigned long *flags) { } -/****************************** OS Primitives *********************************/ -#define ahd_delay DELAY -/************************** Transaction Operations ****************************/ -static __inline void ahd_set_transaction_status(struct scb *, uint32_t); -static __inline void ahd_set_scsi_status(struct scb *, uint32_t); -static __inline uint32_t ahd_get_transaction_status(struct scb *); -static __inline uint32_t ahd_get_scsi_status(struct scb *); -static __inline void ahd_set_transaction_tag(struct scb *, int, u_int); -static __inline u_long ahd_get_transfer_length(struct scb *); -static __inline int ahd_get_transfer_dir(struct scb *); -static __inline void ahd_set_residual(struct scb *, u_long); -static __inline void ahd_set_sense_residual(struct scb *, u_long); -static __inline u_long ahd_get_residual(struct scb *); -static __inline int ahd_perform_autosense(struct scb *); -static __inline uint32_t ahd_get_sense_bufsize(struct ahd_softc*, struct scb*); -static __inline void ahd_freeze_simq(struct ahd_softc *); -static __inline void ahd_release_simq(struct ahd_softc *); -static __inline void ahd_freeze_ccb(union ccb *ccb); -static __inline void ahd_freeze_scb(struct scb *scb); -static __inline void ahd_platform_freeze_devq(struct ahd_softc *, struct scb *); -static __inline int ahd_platform_abort_scbs(struct ahd_softc *ahd, int target, - char channel, int lun, u_int tag, - role_t role, uint32_t status); - -static __inline -void ahd_set_transaction_status(struct scb *scb, uint32_t status) -{ - scb->io_ctx->ccb_h.status &= ~CAM_STATUS_MASK; - scb->io_ctx->ccb_h.status |= status; -} - -static __inline -void ahd_set_scsi_status(struct scb *scb, uint32_t status) -{ - scb->io_ctx->csio.scsi_status = status; -} - -static __inline -uint32_t ahd_get_transaction_status(struct scb *scb) -{ - return (scb->io_ctx->ccb_h.status & CAM_STATUS_MASK); -} - -static __inline -uint32_t ahd_get_scsi_status(struct scb *scb) -{ - return (scb->io_ctx->csio.scsi_status); -} - -static __inline -void ahd_set_transaction_tag(struct scb *scb, int enabled, u_int type) -{ - scb->io_ctx->csio.tag_action = type; - if (enabled) - scb->io_ctx->ccb_h.flags |= CAM_TAG_ACTION_VALID; - else - scb->io_ctx->ccb_h.flags &= ~CAM_TAG_ACTION_VALID; -} - -static __inline -u_long ahd_get_transfer_length(struct scb *scb) -{ - return (scb->io_ctx->csio.dxfer_len); -} - -static __inline -int ahd_get_transfer_dir(struct scb *scb) -{ - return (scb->io_ctx->ccb_h.flags & CAM_DIR_MASK); -} - -static __inline -void ahd_set_residual(struct scb *scb, u_long resid) -{ - scb->io_ctx->csio.resid = resid; -} - -static __inline -void ahd_set_sense_residual(struct scb *scb, u_long resid) -{ - scb->io_ctx->csio.sense_resid = resid; -} - -static __inline -u_long ahd_get_residual(struct scb *scb) -{ - return (scb->io_ctx->csio.resid); -} - -static __inline -int ahd_perform_autosense(struct scb *scb) -{ - return (!(scb->io_ctx->ccb_h.flags & CAM_DIS_AUTOSENSE)); -} - -static __inline uint32_t -ahd_get_sense_bufsize(struct ahd_softc *ahd, struct scb *scb) -{ - return (sizeof(struct scsi_sense_data)); -} - -static __inline void -ahd_freeze_simq(struct ahd_softc *ahd) -{ - xpt_freeze_simq(ahd->platform_data->sim, /*count*/1); -} - -static __inline void -ahd_release_simq(struct ahd_softc *ahd) -{ - xpt_release_simq(ahd->platform_data->sim, /*run queue*/TRUE); -} - -static __inline void -ahd_freeze_ccb(union ccb *ccb) -{ - if ((ccb->ccb_h.status & CAM_DEV_QFRZN) == 0) { - ccb->ccb_h.status |= CAM_DEV_QFRZN; - xpt_freeze_devq(ccb->ccb_h.path, /*count*/1); - } -} - -static __inline void -ahd_freeze_scb(struct scb *scb) -{ - ahd_freeze_ccb(scb->io_ctx); -} - -static __inline void -ahd_platform_freeze_devq(struct ahd_softc *ahd, struct scb *scb) -{ - /* Nothing to do here for FreeBSD */ -} +/********************************** PCI ***************************************/ +int ahd_pci_map_registers(struct ahd_softc *ahd); +int ahd_pci_map_int(struct ahd_softc *ahd); -static __inline int -ahd_platform_abort_scbs(struct ahd_softc *ahd, int target, - char channel, int lun, u_int tag, - role_t role, uint32_t status) -{ - /* Nothing to do here for FreeBSD */ - return (0); -} +/************************** Transaction Operations ****************************/ +static __inline void aic_freeze_simq(struct aic_softc*); +static __inline void aic_release_simq(struct aic_softc*); static __inline void -ahd_platform_scb_free(struct ahd_softc *ahd, struct scb *scb) -{ - /* What do we do to generically handle driver resource shortages??? */ - if ((ahd->flags & AHD_RESOURCE_SHORTAGE) != 0 - && scb->io_ctx != NULL - && (scb->io_ctx->ccb_h.status & CAM_RELEASE_SIMQ) == 0) { - scb->io_ctx->ccb_h.status |= CAM_RELEASE_SIMQ; - ahd->flags &= ~AHD_RESOURCE_SHORTAGE; - } - scb->io_ctx = NULL; -} - -/********************************** PCI ***************************************/ -#ifdef AHD_PCI_CONFIG -static __inline uint32_t ahd_pci_read_config(ahd_dev_softc_t pci, - int reg, int width); -static __inline void ahd_pci_write_config(ahd_dev_softc_t pci, - int reg, uint32_t value, - int width); -static __inline int ahd_get_pci_function(ahd_dev_softc_t); -static __inline int ahd_get_pci_slot(ahd_dev_softc_t); -static __inline int ahd_get_pci_bus(ahd_dev_softc_t); - -int ahd_pci_map_registers(struct ahd_softc *ahd); -int ahd_pci_map_int(struct ahd_softc *ahd); - -static __inline uint32_t -ahd_pci_read_config(ahd_dev_softc_t pci, int reg, int width) +aic_freeze_simq(struct aic_softc *aic) { - return (pci_read_config(pci, reg, width)); + xpt_freeze_simq(aic->platform_data->sim, /*count*/1); } static __inline void -ahd_pci_write_config(ahd_dev_softc_t pci, int reg, uint32_t value, int width) +aic_release_simq(struct aic_softc *aic) { - pci_write_config(pci, reg, value, width); + xpt_release_simq(aic->platform_data->sim, /*run queue*/TRUE); } - -static __inline int -ahd_get_pci_function(ahd_dev_softc_t pci) -{ - return (pci_get_function(pci)); -} - -static __inline int -ahd_get_pci_slot(ahd_dev_softc_t pci) -{ - return (pci_get_slot(pci)); -} - -static __inline int -ahd_get_pci_bus(ahd_dev_softc_t pci) -{ - return (pci_get_bus(pci)); -} - -typedef enum -{ - AHD_POWER_STATE_D0, - AHD_POWER_STATE_D1, - AHD_POWER_STATE_D2, - AHD_POWER_STATE_D3 -} ahd_power_state; - -void ahd_power_state_change(struct ahd_softc *ahd, - ahd_power_state new_state); -#endif -/******************************** VL/EISA *************************************/ -int aic7770_map_registers(struct ahd_softc *ahd); -int aic7770_map_int(struct ahd_softc *ahd, int irq); - /********************************* Debug **************************************/ static __inline void ahd_print_path(struct ahd_softc *, struct scb *); static __inline void ahd_platform_dump_card_state(struct ahd_softc *ahd); diff --git a/sys/dev/aic7xxx/aic79xx_pci.c b/sys/dev/aic7xxx/aic79xx_pci.c index 0523ed6..004e163 100644 --- a/sys/dev/aic7xxx/aic79xx_pci.c +++ b/sys/dev/aic7xxx/aic79xx_pci.c @@ -38,16 +38,15 @@ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * - * $Id: //depot/aic7xxx/aic7xxx/aic79xx_pci.c#80 $ + * $Id: //depot/aic7xxx/aic7xxx/aic79xx_pci.c#84 $ */ -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - #ifdef __linux__ #include "aic79xx_osm.h" #include "aic79xx_inline.h" #else +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); #include <dev/aic7xxx/aic79xx_osm.h> #include <dev/aic7xxx/aic79xx_inline.h> #endif @@ -76,13 +75,13 @@ ahd_compose_id(u_int device, u_int vendor, u_int subdevice, u_int subvendor) #define ID_AHA_29320ALP 0x8017900500449005ull #define ID_AIC7901A 0x801E9005FFFF9005ull -#define ID_AHA_29320 0x8012900500429005ull -#define ID_AHA_29320B 0x8013900500439005ull #define ID_AHA_29320LP 0x8014900500449005ull #define ID_AIC7902 0x801F9005FFFF9005ull #define ID_AIC7902_B 0x801D9005FFFF9005ull #define ID_AHA_39320 0x8010900500409005ull +#define ID_AHA_29320 0x8012900500429005ull +#define ID_AHA_29320B 0x8013900500439005ull #define ID_AHA_39320_B 0x8015900500409005ull #define ID_AHA_39320A 0x8016900500409005ull #define ID_AHA_39320D 0x8011900500419005ull @@ -137,24 +136,24 @@ struct ahd_pci_identity ahd_pci_ident_table [] = }, /* aic7901A based controllers */ { - ID_AHA_29320, + ID_AHA_29320LP, ID_ALL_MASK, - "Adaptec 29320 Ultra320 SCSI adapter", + "Adaptec 29320LP Ultra320 SCSI adapter", ahd_aic7901A_setup }, + /* aic7902 based controllers */ { - ID_AHA_29320B, + ID_AHA_29320, ID_ALL_MASK, - "Adaptec 29320B Ultra320 SCSI adapter", - ahd_aic7901A_setup + "Adaptec 29320 Ultra320 SCSI adapter", + ahd_aic7902_setup }, { - ID_AHA_29320LP, + ID_AHA_29320B, ID_ALL_MASK, - "Adaptec 29320LP Ultra320 SCSI adapter", - ahd_aic7901A_setup + "Adaptec 29320B Ultra320 SCSI adapter", + ahd_aic7902_setup }, - /* aic7902 based controllers */ { ID_AHA_39320, ID_ALL_MASK, @@ -197,18 +196,6 @@ struct ahd_pci_identity ahd_pci_ident_table [] = "Adaptec (HP OEM) 39320D Ultra320 SCSI adapter", ahd_aic7902_setup }, - { - ID_AHA_29320, - ID_ALL_MASK, - "Adaptec 29320 Ultra320 SCSI adapter", - ahd_aic7902_setup - }, - { - ID_AHA_29320B, - ID_ALL_MASK, - "Adaptec 29320B Ultra320 SCSI adapter", - ahd_aic7902_setup - }, /* Generic chip probes for devices we don't know 'exactly' */ { ID_AIC7901 & ID_DEV_VENDOR_MASK, @@ -276,7 +263,7 @@ static void ahd_configure_termination(struct ahd_softc *ahd, static void ahd_pci_split_intr(struct ahd_softc *ahd, u_int intstat); struct ahd_pci_identity * -ahd_find_pci_device(ahd_dev_softc_t pci) +ahd_find_pci_device(aic_dev_softc_t pci) { uint64_t full_id; uint16_t device; @@ -286,10 +273,10 @@ ahd_find_pci_device(ahd_dev_softc_t pci) struct ahd_pci_identity *entry; u_int i; - vendor = ahd_pci_read_config(pci, PCIR_DEVVENDOR, /*bytes*/2); - device = ahd_pci_read_config(pci, PCIR_DEVICE, /*bytes*/2); - subvendor = ahd_pci_read_config(pci, PCIR_SUBVEND_0, /*bytes*/2); - subdevice = ahd_pci_read_config(pci, PCIR_SUBDEV_0, /*bytes*/2); + vendor = aic_pci_read_config(pci, PCIR_DEVVENDOR, /*bytes*/2); + device = aic_pci_read_config(pci, PCIR_DEVICE, /*bytes*/2); + subvendor = aic_pci_read_config(pci, PCIR_SUBVEND_0, /*bytes*/2); + subdevice = aic_pci_read_config(pci, PCIR_SUBDEV_0, /*bytes*/2); full_id = ahd_compose_id(device, vendor, subdevice, @@ -322,7 +309,7 @@ ahd_pci_config(struct ahd_softc *ahd, struct ahd_pci_identity *entry) /* * Record if this is an HP board. */ - subvendor = ahd_pci_read_config(ahd->dev_softc, + subvendor = aic_pci_read_config(ahd->dev_softc, PCIR_SUBVEND_0, /*bytes*/2); if (subvendor == SUBID_HP) ahd->flags |= AHD_HP_BOARD; @@ -331,7 +318,7 @@ ahd_pci_config(struct ahd_softc *ahd, struct ahd_pci_identity *entry) if (error != 0) return (error); - devconfig = ahd_pci_read_config(ahd->dev_softc, DEVCONFIG, /*bytes*/4); + devconfig = aic_pci_read_config(ahd->dev_softc, DEVCONFIG, /*bytes*/4); if ((devconfig & PCIXINITPAT) == PCIXINIT_PCI33_66) { ahd->chip |= AHD_PCI; /* Disable PCIX workarounds when running in PCI mode. */ @@ -341,7 +328,7 @@ ahd_pci_config(struct ahd_softc *ahd, struct ahd_pci_identity *entry) } ahd->bus_description = pci_bus_modes[PCI_BUS_MODES_INDEX(devconfig)]; - ahd_power_state_change(ahd, AHD_POWER_STATE_D0); + aic_power_state_change(ahd, AIC_POWER_STATE_D0); error = ahd_pci_map_registers(ahd); if (error != 0) @@ -359,17 +346,17 @@ ahd_pci_config(struct ahd_softc *ahd, struct ahd_pci_identity *entry) if (bootverbose) printf("%s: Enabling 39Bit Addressing\n", ahd_name(ahd)); - devconfig = ahd_pci_read_config(ahd->dev_softc, + devconfig = aic_pci_read_config(ahd->dev_softc, DEVCONFIG, /*bytes*/4); devconfig |= DACEN; - ahd_pci_write_config(ahd->dev_softc, DEVCONFIG, + aic_pci_write_config(ahd->dev_softc, DEVCONFIG, devconfig, /*bytes*/4); } /* Ensure busmastering is enabled */ - command = ahd_pci_read_config(ahd->dev_softc, PCIR_COMMAND, /*bytes*/2); + command = aic_pci_read_config(ahd->dev_softc, PCIR_COMMAND, /*bytes*/2); command |= PCIM_CMD_BUSMASTEREN; - ahd_pci_write_config(ahd->dev_softc, PCIR_COMMAND, command, /*bytes*/2); + aic_pci_write_config(ahd->dev_softc, PCIR_COMMAND, command, /*bytes*/2); error = ahd_softc_init(ahd); if (error != 0) @@ -382,7 +369,7 @@ ahd_pci_config(struct ahd_softc *ahd, struct ahd_pci_identity *entry) return (ENXIO); ahd->pci_cachesize = - ahd_pci_read_config(ahd->dev_softc, CSIZE_LATTIME, + aic_pci_read_config(ahd->dev_softc, CSIZE_LATTIME, /*bytes*/1) & CACHESIZE; ahd->pci_cachesize *= 4; @@ -432,8 +419,8 @@ ahd_pci_test_register_access(struct ahd_softc *ahd) * Enable PCI error interrupt status, but suppress NMIs * generated by SERR raised due to target aborts. */ - cmd = ahd_pci_read_config(ahd->dev_softc, PCIR_COMMAND, /*bytes*/2); - ahd_pci_write_config(ahd->dev_softc, PCIR_COMMAND, + cmd = aic_pci_read_config(ahd->dev_softc, PCIR_COMMAND, /*bytes*/2); + aic_pci_write_config(ahd->dev_softc, PCIR_COMMAND, cmd & ~PCIM_CMD_SERRESPEN, /*bytes*/2); /* @@ -465,9 +452,9 @@ ahd_pci_test_register_access(struct ahd_softc *ahd) ahd_set_modes(ahd, AHD_MODE_CFG, AHD_MODE_CFG); targpcistat = ahd_inb(ahd, TARGPCISTAT); ahd_outb(ahd, TARGPCISTAT, targpcistat); - pci_status1 = ahd_pci_read_config(ahd->dev_softc, + pci_status1 = aic_pci_read_config(ahd->dev_softc, PCIR_STATUS + 1, /*bytes*/1); - ahd_pci_write_config(ahd->dev_softc, PCIR_STATUS + 1, + aic_pci_write_config(ahd->dev_softc, PCIR_STATUS + 1, pci_status1, /*bytes*/1); ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); ahd_outb(ahd, CLRINT, CLRPCIINT); @@ -496,14 +483,14 @@ fail: /* Silently clear any latched errors. */ ahd_outb(ahd, TARGPCISTAT, targpcistat); - pci_status1 = ahd_pci_read_config(ahd->dev_softc, + pci_status1 = aic_pci_read_config(ahd->dev_softc, PCIR_STATUS + 1, /*bytes*/1); - ahd_pci_write_config(ahd->dev_softc, PCIR_STATUS + 1, + aic_pci_write_config(ahd->dev_softc, PCIR_STATUS + 1, pci_status1, /*bytes*/1); ahd_outb(ahd, CLRINT, CLRPCIINT); } ahd_outb(ahd, SEQCTL0, PERRORDIS|FAILDIS); - ahd_pci_write_config(ahd->dev_softc, PCIR_COMMAND, cmd, /*bytes*/2); + aic_pci_write_config(ahd->dev_softc, PCIR_COMMAND, cmd, /*bytes*/2); return (error); } @@ -652,14 +639,14 @@ ahd_configure_termination(struct ahd_softc *ahd, u_int adapter_control) uint8_t termctl; uint32_t devconfig; - devconfig = ahd_pci_read_config(ahd->dev_softc, DEVCONFIG, /*bytes*/4); + devconfig = aic_pci_read_config(ahd->dev_softc, DEVCONFIG, /*bytes*/4); devconfig &= ~STPWLEVEL; if ((ahd->flags & AHD_STPWLEVEL_A) != 0) devconfig |= STPWLEVEL; if (bootverbose) printf("%s: STPWLEVEL is %s\n", ahd_name(ahd), (devconfig & STPWLEVEL) ? "on" : "off"); - ahd_pci_write_config(ahd->dev_softc, DEVCONFIG, devconfig, /*bytes*/4); + aic_pci_write_config(ahd->dev_softc, DEVCONFIG, devconfig, /*bytes*/4); /* Make sure current sensing is off. */ if ((ahd->flags & AHD_CURRENT_SENSING) != 0) { @@ -704,6 +691,7 @@ ahd_configure_termination(struct ahd_softc *ahd, u_int adapter_control) * Now set the termination based on what we found. */ sxfrctl1 = ahd_inb(ahd, SXFRCTL1) & ~STPWEN; + ahd->flags &= ~AHD_TERM_ENB_A; if ((termctl & FLX_TERMCTL_ENPRILOW) != 0) { ahd->flags |= AHD_TERM_ENB_A; sxfrctl1 |= STPWEN; @@ -836,9 +824,9 @@ ahd_pci_intr(struct ahd_softc *ahd) } } } - pci_status1 = ahd_pci_read_config(ahd->dev_softc, + pci_status1 = aic_pci_read_config(ahd->dev_softc, PCIR_STATUS + 1, /*bytes*/1); - ahd_pci_write_config(ahd->dev_softc, PCIR_STATUS + 1, + aic_pci_write_config(ahd->dev_softc, PCIR_STATUS + 1, pci_status1, /*bytes*/1); ahd_restore_modes(ahd, saved_modes); ahd_outb(ahd, CLRINT, CLRPCIINT); @@ -860,7 +848,7 @@ ahd_pci_split_intr(struct ahd_softc *ahd, u_int intstat) * Check for splits in all modes. Modes 0 and 1 * additionally have SG engine splits to look at. */ - pcix_status = ahd_pci_read_config(ahd->dev_softc, PCIXR_STATUS, + pcix_status = aic_pci_read_config(ahd->dev_softc, PCIXR_STATUS, /*bytes*/2); printf("%s: PCI Split Interrupt - PCI-X status = 0x%x\n", ahd_name(ahd), pcix_status); @@ -909,7 +897,7 @@ ahd_pci_split_intr(struct ahd_softc *ahd, u_int intstat) /* * Clear PCI-X status bits. */ - ahd_pci_write_config(ahd->dev_softc, PCIXR_STATUS, + aic_pci_write_config(ahd->dev_softc, PCIXR_STATUS, pcix_status, /*bytes*/2); ahd_outb(ahd, CLRINT, CLRSPLTINT); ahd_restore_modes(ahd, saved_modes); @@ -944,18 +932,18 @@ ahd_aic7902_setup(struct ahd_softc *ahd) static int ahd_aic790X_setup(struct ahd_softc *ahd) { - ahd_dev_softc_t pci; + aic_dev_softc_t pci; u_int rev; pci = ahd->dev_softc; - rev = ahd_pci_read_config(pci, PCIR_REVID, /*bytes*/1); + rev = aic_pci_read_config(pci, PCIR_REVID, /*bytes*/1); if (rev < ID_AIC7902_PCI_REV_A4) { printf("%s: Unable to attach to unsupported chip revision %d\n", ahd_name(ahd), rev); - ahd_pci_write_config(pci, PCIR_COMMAND, 0, /*bytes*/2); + aic_pci_write_config(pci, PCIR_COMMAND, 0, /*bytes*/2); return (ENXIO); } - ahd->channel = ahd_get_pci_function(pci) + 'A'; + ahd->channel = aic_get_pci_function(pci) + 'A'; if (rev < ID_AIC7902_PCI_REV_B0) { /* * Enable A series workarounds. @@ -983,7 +971,7 @@ ahd_aic790X_setup(struct ahd_softc *ahd) u_int devconfig1; ahd->features |= AHD_RTI|AHD_NEW_IOCELL_OPTS - | AHD_NEW_DFCNTRL_OPTS; + | AHD_NEW_DFCNTRL_OPTS|AHD_FAST_CDB_DELIVERY; ahd->bugs |= AHD_LQOOVERRUN_BUG|AHD_EARLY_REQ_BUG; /* @@ -1005,10 +993,10 @@ ahd_aic790X_setup(struct ahd_softc *ahd) * XXX - Find out exactly what this does from the hardware * folks! */ - devconfig1 = ahd_pci_read_config(pci, DEVCONFIG1, /*bytes*/1); - ahd_pci_write_config(pci, DEVCONFIG1, + devconfig1 = aic_pci_read_config(pci, DEVCONFIG1, /*bytes*/1); + aic_pci_write_config(pci, DEVCONFIG1, devconfig1|PREQDIS, /*bytes*/1); - devconfig1 = ahd_pci_read_config(pci, DEVCONFIG1, /*bytes*/1); + devconfig1 = aic_pci_read_config(pci, DEVCONFIG1, /*bytes*/1); } return (0); diff --git a/sys/dev/aic7xxx/aic7xxx.c b/sys/dev/aic7xxx/aic7xxx.c index 0030f8e..dfc3509 100644 --- a/sys/dev/aic7xxx/aic7xxx.c +++ b/sys/dev/aic7xxx/aic7xxx.c @@ -37,17 +37,16 @@ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * - * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.c#134 $ + * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.c#146 $ */ -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - #ifdef __linux__ #include "aic7xxx_osm.h" #include "aic7xxx_inline.h" #include "aicasm/aicasm_insformat.h" #else +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); #include <dev/aic7xxx/aic7xxx_osm.h> #include <dev/aic7xxx/aic7xxx_inline.h> #include <dev/aic7xxx/aicasm/aicasm_insformat.h> @@ -321,7 +320,7 @@ ahc_run_qoutfifo(struct ahc_softc *ahc) */ modnext = ahc->qoutfifonext & ~0x3; *((uint32_t *)(&ahc->qoutfifo[modnext])) = 0xFFFFFFFFUL; - ahc_dmamap_sync(ahc, ahc->shared_data_dmat, + aic_dmamap_sync(ahc, ahc->shared_data_dmat, ahc->shared_data_dmamap, /*offset*/modnext, /*len*/4, BUS_DMASYNC_PREREAD); @@ -459,14 +458,14 @@ ahc_handle_seqint(struct ahc_softc *ahc, u_int intstat) * complete. */ scb->flags &= ~SCB_SENSE; - ahc_set_transaction_status(scb, CAM_AUTOSENSE_FAIL); + aic_set_transaction_status(scb, CAM_AUTOSENSE_FAIL); break; } - ahc_set_transaction_status(scb, CAM_SCSI_STATUS_ERROR); + aic_set_transaction_status(scb, CAM_SCSI_STATUS_ERROR); /* Freeze the queue until the client sees the error. */ ahc_freeze_devq(ahc, scb); - ahc_freeze_scb(scb); - ahc_set_scsi_status(scb, hscb->shared_data.status.scsi_status); + aic_freeze_scb(scb); + aic_set_scsi_status(scb, hscb->shared_data.status.scsi_status); switch (hscb->shared_data.status.scsi_status) { case SCSI_STATUS_OK: printf("%s: Interrupted for staus of 0???\n", @@ -488,7 +487,7 @@ ahc_handle_seqint(struct ahc_softc *ahc, u_int intstat) } #endif - if (ahc_perform_autosense(scb) == 0) + if (aic_perform_autosense(scb) == 0) break; targ_info = ahc_fetch_transinfo(ahc, @@ -510,12 +509,12 @@ ahc_handle_seqint(struct ahc_softc *ahc, u_int intstat) } #endif sg->addr = ahc_get_sense_bufaddr(ahc, scb); - sg->len = ahc_get_sense_bufsize(ahc, scb); + sg->len = aic_get_sense_bufsize(ahc, scb); sg->len |= AHC_DMA_LAST_SEG; /* Fixup byte order */ - sg->addr = ahc_htole32(sg->addr); - sg->len = ahc_htole32(sg->len); + sg->addr = aic_htole32(sg->addr); + sg->len = aic_htole32(sg->len); sc->opcode = REQUEST_SENSE; sc->byte2 = 0; @@ -544,8 +543,8 @@ ahc_handle_seqint(struct ahc_softc *ahc, u_int intstat) * errors will be reported before any data * phases occur. */ - if (ahc_get_residual(scb) - == ahc_get_transfer_length(scb)) { + if (aic_get_residual(scb) + == aic_get_transfer_length(scb)) { ahc_update_neg_request(ahc, &devinfo, tstate, targ_info, AHC_NEG_IF_NON_ASYNC); @@ -559,7 +558,7 @@ ahc_handle_seqint(struct ahc_softc *ahc, u_int intstat) hscb->dataptr = sg->addr; hscb->datacnt = sg->len; hscb->sgptr = scb->sg_list_phys | SG_FULL_RESID; - hscb->sgptr = ahc_htole32(hscb->sgptr); + hscb->sgptr = aic_htole32(hscb->sgptr); scb->sg_count = 1; scb->flags |= SCB_SENSE; ahc_qinfifo_requeue_tail(ahc, scb); @@ -568,7 +567,7 @@ ahc_handle_seqint(struct ahc_softc *ahc, u_int intstat) * Ensure we have enough time to actually * retrieve the sense. */ - ahc_scb_timer_reset(scb, 5 * 1000000); + aic_scb_timer_reset(scb, 5 * 1000000); break; } default: @@ -769,7 +768,7 @@ ahc_handle_seqint(struct ahc_softc *ahc, u_int intstat) if ((ahc_inb(ahc, SCSISIGI) & (CDI|MSGI)) != 0) break; - ahc_delay(100); + aic_delay(100); } ahc_outb(ahc, SXFRCTL1, ahc_inb(ahc, SXFRCTL1) & ~BITBUCKET); @@ -783,7 +782,7 @@ ahc_handle_seqint(struct ahc_softc *ahc, u_int intstat) scb_index = ahc_inb(ahc, SCB_TAG); scb = ahc_lookup_scb(ahc, scb_index); if (scb != NULL) - ahc_set_transaction_status(scb, + aic_set_transaction_status(scb, CAM_UNCOR_PARITY); ahc_reset_channel(ahc, devinfo.channel, /*init reset*/TRUE); @@ -821,16 +820,16 @@ ahc_handle_seqint(struct ahc_softc *ahc, u_int intstat) ahc_print_path(ahc, scb); printf("%s seen Data Phase. Length = %ld. NumSGs = %d.\n", ahc_inb(ahc, SEQ_FLAGS) & DPHASE ? "Have" : "Haven't", - ahc_get_transfer_length(scb), scb->sg_count); + aic_get_transfer_length(scb), scb->sg_count); if (scb->sg_count > 0) { for (i = 0; i < scb->sg_count; i++) { printf("sg[%d] - Addr 0x%x%x : Length %d\n", i, - (ahc_le32toh(scb->sg_list[i].len) >> 24 + (aic_le32toh(scb->sg_list[i].len) >> 24 & SG_HIGH_ADDR_BITS), - ahc_le32toh(scb->sg_list[i].addr), - ahc_le32toh(scb->sg_list[i].len) + aic_le32toh(scb->sg_list[i].addr), + aic_le32toh(scb->sg_list[i].len) & AHC_SG_LEN_MASK); } } @@ -840,12 +839,12 @@ ahc_handle_seqint(struct ahc_softc *ahc, u_int intstat) */ ahc_freeze_devq(ahc, scb); if ((scb->flags & SCB_SENSE) == 0) { - ahc_set_transaction_status(scb, CAM_DATA_RUN_ERR); + aic_set_transaction_status(scb, CAM_DATA_RUN_ERR); } else { scb->flags &= ~SCB_SENSE; - ahc_set_transaction_status(scb, CAM_AUTOSENSE_FAIL); + aic_set_transaction_status(scb, CAM_AUTOSENSE_FAIL); } - ahc_freeze_scb(scb); + aic_freeze_scb(scb); if ((ahc->features & AHC_ULTRA2) != 0) { /* @@ -1189,7 +1188,7 @@ ahc_handle_scsiint(struct ahc_softc *ahc, u_int intstat) */ ahc_scb_devinfo(ahc, &devinfo, scb); ahc_force_renegotiation(ahc, &devinfo); - ahc_set_transaction_status(scb, CAM_SEL_TIMEOUT); + aic_set_transaction_status(scb, CAM_SEL_TIMEOUT); ahc_freeze_devq(ahc, scb); } ahc_outb(ahc, CLRINT, CLRSCSIINT); @@ -1271,7 +1270,7 @@ ahc_handle_scsiint(struct ahc_softc *ahc, u_int intstat) CAM_LUN_WILDCARD, SCB_LIST_NULL, ROLE_INITIATOR)) { - ahc_set_transaction_status(scb, CAM_REQ_CMP); + aic_set_transaction_status(scb, CAM_REQ_CMP); } #endif ahc_compile_devinfo(&devinfo, @@ -1483,7 +1482,7 @@ ahc_clear_critical_section(struct ahc_softc *ahc) } ahc_outb(ahc, HCNTRL, ahc->unpause); while (!ahc_is_paused(ahc)) - ahc_delay(200); + aic_delay(200); } if (stepping) { ahc_outb(ahc, SIMODE0, simode0); @@ -1531,18 +1530,18 @@ ahc_print_scb(struct scb *scb) for (i = 0; i < sizeof(hscb->shared_data.cdb); i++) printf("%#02x", hscb->shared_data.cdb[i]); printf(" dataptr:%#x datacnt:%#x sgptr:%#x tag:%#x\n", - ahc_le32toh(hscb->dataptr), - ahc_le32toh(hscb->datacnt), - ahc_le32toh(hscb->sgptr), + aic_le32toh(hscb->dataptr), + aic_le32toh(hscb->datacnt), + aic_le32toh(hscb->sgptr), hscb->tag); if (scb->sg_count > 0) { for (i = 0; i < scb->sg_count; i++) { printf("sg[%d] - Addr 0x%x%x : Length %d\n", i, - (ahc_le32toh(scb->sg_list[i].len) >> 24 + (aic_le32toh(scb->sg_list[i].len) >> 24 & SG_HIGH_ADDR_BITS), - ahc_le32toh(scb->sg_list[i].addr), - ahc_le32toh(scb->sg_list[i].len)); + aic_le32toh(scb->sg_list[i].addr), + aic_le32toh(scb->sg_list[i].len)); } } } @@ -2576,7 +2575,7 @@ ahc_handle_proto_violation(struct ahc_softc *ahc) printf("No SCB found during protocol violation\n"); goto proto_violation_reset; } else { - ahc_set_transaction_status(scb, CAM_SEQUENCE_FAIL); + aic_set_transaction_status(scb, CAM_SEQUENCE_FAIL); if ((seq_flags & NO_CDB_SENT) != 0) { ahc_print_path(ahc, scb); printf("No or incomplete CDB sent to device.\n"); @@ -3514,7 +3513,7 @@ ahc_handle_msg_reject(struct ahc_softc *ahc, struct ahc_devinfo *devinfo) ahc_outb(ahc, SCB_CONTROL, ahc_inb(ahc, SCB_CONTROL) & mask); scb->hscb->control &= mask; - ahc_set_transaction_tag(scb, /*enabled*/FALSE, + aic_set_transaction_tag(scb, /*enabled*/FALSE, /*type*/MSG_SIMPLE_TASK); ahc_outb(ahc, MSG_OUT, MSG_IDENTIFYFLAG); ahc_assert_atn(ahc); @@ -3571,7 +3570,7 @@ ahc_handle_ign_wide_residue(struct ahc_softc *ahc, struct ahc_devinfo *devinfo) * Perhaps add datadir to some spare bits in the hscb? */ if ((ahc_inb(ahc, SEQ_FLAGS) & DPHASE) == 0 - || ahc_get_transfer_dir(scb) != CAM_DIR_IN) { + || aic_get_transfer_dir(scb) != CAM_DIR_IN) { /* * Ignore the message if we haven't * seen an appropriate data phase yet. @@ -3627,18 +3626,18 @@ ahc_handle_ign_wide_residue(struct ahc_softc *ahc, struct ahc_devinfo *devinfo) * to load so we must go back one. */ sg--; - sglen = ahc_le32toh(sg->len) & AHC_SG_LEN_MASK; + sglen = aic_le32toh(sg->len) & AHC_SG_LEN_MASK; if (sg != scb->sg_list && sglen < (data_cnt & AHC_SG_LEN_MASK)) { sg--; - sglen = ahc_le32toh(sg->len); + sglen = aic_le32toh(sg->len); /* * Preserve High Address and SG_LIST bits * while setting the count to 1. */ data_cnt = 1 | (sglen & (~AHC_SG_LEN_MASK)); - data_addr = ahc_le32toh(sg->addr) + data_addr = aic_le32toh(sg->addr) + (sglen & AHC_SG_LEN_MASK) - 1; /* @@ -3694,8 +3693,8 @@ ahc_reinitialize_dataptrs(struct ahc_softc *ahc) | (ahc_inb(ahc, SCB_RESIDUAL_DATACNT + 1) << 8) | ahc_inb(ahc, SCB_RESIDUAL_DATACNT); - dataptr = ahc_le32toh(sg->addr) - + (ahc_le32toh(sg->len) & AHC_SG_LEN_MASK) + dataptr = aic_le32toh(sg->addr) + + (aic_le32toh(sg->len) & AHC_SG_LEN_MASK) - resid; if ((ahc->flags & AHC_39BIT_ADDRESSING) != 0) { u_int dscommand1; @@ -3703,7 +3702,7 @@ ahc_reinitialize_dataptrs(struct ahc_softc *ahc) dscommand1 = ahc_inb(ahc, DSCOMMAND1); ahc_outb(ahc, DSCOMMAND1, dscommand1 | HADDLDSEL0); ahc_outb(ahc, HADDR, - (ahc_le32toh(sg->len) >> 24) & SG_HIGH_ADDR_BITS); + (aic_le32toh(sg->len) >> 24) & SG_HIGH_ADDR_BITS); ahc_outb(ahc, DSCOMMAND1, dscommand1); } ahc_outb(ahc, HADDR + 3, dataptr >> 24); @@ -3884,7 +3883,7 @@ ahc_softc_insert(struct ahc_softc *ahc) { struct ahc_softc *list_ahc; -#if AHC_PCI_CONFIG > 0 +#if AIC_PCI_CONFIG > 0 /* * Second Function PCI devices need to inherit some * settings from function 0. @@ -3892,17 +3891,17 @@ ahc_softc_insert(struct ahc_softc *ahc) if ((ahc->chip & AHC_BUS_MASK) == AHC_PCI && (ahc->features & AHC_MULTI_FUNC) != 0) { TAILQ_FOREACH(list_ahc, &ahc_tailq, links) { - ahc_dev_softc_t list_pci; - ahc_dev_softc_t pci; + aic_dev_softc_t list_pci; + aic_dev_softc_t pci; list_pci = list_ahc->dev_softc; pci = ahc->dev_softc; - if (ahc_get_pci_slot(list_pci) == ahc_get_pci_slot(pci) - && ahc_get_pci_bus(list_pci) == ahc_get_pci_bus(pci)) { + if (aic_get_pci_slot(list_pci) == aic_get_pci_slot(pci) + && aic_get_pci_bus(list_pci) == aic_get_pci_bus(pci)) { struct ahc_softc *master; struct ahc_softc *slave; - if (ahc_get_pci_function(list_pci) == 0) { + if (aic_get_pci_function(list_pci) == 0) { master = list_ahc; slave = ahc; } else { @@ -3970,27 +3969,27 @@ ahc_free(struct ahc_softc *ahc) { int i; + ahc_terminate_recovery_thread(ahc); switch (ahc->init_level) { default: case 5: ahc_shutdown(ahc); - TAILQ_REMOVE(&ahc_tailq, ahc, links); /* FALLTHROUGH */ case 4: - ahc_dmamap_unload(ahc, ahc->shared_data_dmat, + aic_dmamap_unload(ahc, ahc->shared_data_dmat, ahc->shared_data_dmamap); /* FALLTHROUGH */ case 3: - ahc_dmamem_free(ahc, ahc->shared_data_dmat, ahc->qoutfifo, + aic_dmamem_free(ahc, ahc->shared_data_dmat, ahc->qoutfifo, ahc->shared_data_dmamap); - ahc_dmamap_destroy(ahc, ahc->shared_data_dmat, + aic_dmamap_destroy(ahc, ahc->shared_data_dmat, ahc->shared_data_dmamap); /* FALLTHROUGH */ case 2: - ahc_dma_tag_destroy(ahc, ahc->shared_data_dmat); + aic_dma_tag_destroy(ahc, ahc->shared_data_dmat); case 1: #ifndef __linux__ - ahc_dma_tag_destroy(ahc, ahc->buffer_dmat); + aic_dma_tag_destroy(ahc, ahc->buffer_dmat); #endif break; case 0: @@ -3998,7 +3997,7 @@ ahc_free(struct ahc_softc *ahc) } #ifndef __linux__ - ahc_dma_tag_destroy(ahc, ahc->parent_dmat); + aic_dma_tag_destroy(ahc, ahc->parent_dmat); #endif ahc_platform_free(ahc); ahc_fini_scbdata(ahc); @@ -4047,6 +4046,9 @@ ahc_shutdown(void *arg) ahc = (struct ahc_softc *)arg; + /* Kill off our recovery thread. */ + ahc_terminate_recovery_thread(ahc); + /* This will reset most registers to 0, but not all */ ahc_reset(ahc, /*reinit*/FALSE); ahc_outb(ahc, SCSISEQ, 0); @@ -4080,14 +4082,6 @@ ahc_reset(struct ahc_softc *ahc, int reinit) * to disturb the integrity of the bus. */ ahc_pause(ahc); - if ((ahc_inb(ahc, HCNTRL) & CHIPRST) != 0) { - /* - * The chip has not been initialized since - * PCI/EISA/VLB bus reset. Don't trust - * "left over BIOS data". - */ - ahc->flags |= AHC_NO_BIOS_INIT; - } sxfrctl1_b = 0; if ((ahc->chip & AHC_CHIPID_MASK) == AHC_AIC7770) { u_int sblkctl; @@ -4113,7 +4107,7 @@ ahc_reset(struct ahc_softc *ahc, int reinit) */ wait = 1000; do { - ahc_delay(1000); + aic_delay(1000); } while (--wait && !(ahc_inb(ahc, HCNTRL) & CHIPRSTACK)); if (wait == 0) { @@ -4293,7 +4287,7 @@ ahc_init_scbdata(struct ahc_softc *ahc) */ /* DMA tag for our hardware scb structures */ - if (ahc_dma_tag_create(ahc, ahc->parent_dmat, /*alignment*/1, + if (aic_dma_tag_create(ahc, ahc->parent_dmat, /*alignment*/1, /*boundary*/BUS_SPACE_MAXADDR_32BIT + 1, /*lowaddr*/BUS_SPACE_MAXADDR_32BIT, /*highaddr*/BUS_SPACE_MAXADDR, @@ -4308,7 +4302,7 @@ ahc_init_scbdata(struct ahc_softc *ahc) scb_data->init_level++; /* Allocation for our hscbs */ - if (ahc_dmamem_alloc(ahc, scb_data->hscb_dmat, + if (aic_dmamem_alloc(ahc, scb_data->hscb_dmat, (void **)&scb_data->hscbs, BUS_DMA_NOWAIT, &scb_data->hscb_dmamap) != 0) { goto error_exit; @@ -4317,7 +4311,7 @@ ahc_init_scbdata(struct ahc_softc *ahc) scb_data->init_level++; /* And permanently map them */ - ahc_dmamap_load(ahc, scb_data->hscb_dmat, scb_data->hscb_dmamap, + aic_dmamap_load(ahc, scb_data->hscb_dmat, scb_data->hscb_dmamap, scb_data->hscbs, AHC_SCB_MAX_ALLOC * sizeof(struct hardware_scb), ahc_dmamap_cb, &scb_data->hscb_busaddr, /*flags*/0); @@ -4325,7 +4319,7 @@ ahc_init_scbdata(struct ahc_softc *ahc) scb_data->init_level++; /* DMA tag for our sense buffers */ - if (ahc_dma_tag_create(ahc, ahc->parent_dmat, /*alignment*/1, + if (aic_dma_tag_create(ahc, ahc->parent_dmat, /*alignment*/1, /*boundary*/BUS_SPACE_MAXADDR_32BIT + 1, /*lowaddr*/BUS_SPACE_MAXADDR_32BIT, /*highaddr*/BUS_SPACE_MAXADDR, @@ -4340,7 +4334,7 @@ ahc_init_scbdata(struct ahc_softc *ahc) scb_data->init_level++; /* Allocate them */ - if (ahc_dmamem_alloc(ahc, scb_data->sense_dmat, + if (aic_dmamem_alloc(ahc, scb_data->sense_dmat, (void **)&scb_data->sense, BUS_DMA_NOWAIT, &scb_data->sense_dmamap) != 0) { goto error_exit; @@ -4349,7 +4343,7 @@ ahc_init_scbdata(struct ahc_softc *ahc) scb_data->init_level++; /* And permanently map them */ - ahc_dmamap_load(ahc, scb_data->sense_dmat, scb_data->sense_dmamap, + aic_dmamap_load(ahc, scb_data->sense_dmat, scb_data->sense_dmamap, scb_data->sense, AHC_SCB_MAX_ALLOC * sizeof(struct scsi_sense_data), ahc_dmamap_cb, &scb_data->sense_busaddr, /*flags*/0); @@ -4357,7 +4351,7 @@ ahc_init_scbdata(struct ahc_softc *ahc) scb_data->init_level++; /* DMA tag for our S/G structures. We allocate in page sized chunks */ - if (ahc_dma_tag_create(ahc, ahc->parent_dmat, /*alignment*/8, + if (aic_dma_tag_create(ahc, ahc->parent_dmat, /*alignment*/8, /*boundary*/BUS_SPACE_MAXADDR_32BIT + 1, /*lowaddr*/BUS_SPACE_MAXADDR_32BIT, /*highaddr*/BUS_SPACE_MAXADDR, @@ -4414,35 +4408,35 @@ ahc_fini_scbdata(struct ahc_softc *ahc) while ((sg_map = SLIST_FIRST(&scb_data->sg_maps))!= NULL) { SLIST_REMOVE_HEAD(&scb_data->sg_maps, links); - ahc_dmamap_unload(ahc, scb_data->sg_dmat, + aic_dmamap_unload(ahc, scb_data->sg_dmat, sg_map->sg_dmamap); - ahc_dmamem_free(ahc, scb_data->sg_dmat, + aic_dmamem_free(ahc, scb_data->sg_dmat, sg_map->sg_vaddr, sg_map->sg_dmamap); free(sg_map, M_DEVBUF); } - ahc_dma_tag_destroy(ahc, scb_data->sg_dmat); + aic_dma_tag_destroy(ahc, scb_data->sg_dmat); } case 6: - ahc_dmamap_unload(ahc, scb_data->sense_dmat, + aic_dmamap_unload(ahc, scb_data->sense_dmat, scb_data->sense_dmamap); case 5: - ahc_dmamem_free(ahc, scb_data->sense_dmat, scb_data->sense, + aic_dmamem_free(ahc, scb_data->sense_dmat, scb_data->sense, scb_data->sense_dmamap); - ahc_dmamap_destroy(ahc, scb_data->sense_dmat, + aic_dmamap_destroy(ahc, scb_data->sense_dmat, scb_data->sense_dmamap); case 4: - ahc_dma_tag_destroy(ahc, scb_data->sense_dmat); + aic_dma_tag_destroy(ahc, scb_data->sense_dmat); case 3: - ahc_dmamap_unload(ahc, scb_data->hscb_dmat, + aic_dmamap_unload(ahc, scb_data->hscb_dmat, scb_data->hscb_dmamap); case 2: - ahc_dmamem_free(ahc, scb_data->hscb_dmat, scb_data->hscbs, + aic_dmamem_free(ahc, scb_data->hscb_dmat, scb_data->hscbs, scb_data->hscb_dmamap); - ahc_dmamap_destroy(ahc, scb_data->hscb_dmat, + aic_dmamap_destroy(ahc, scb_data->hscb_dmat, scb_data->hscb_dmamap); case 1: - ahc_dma_tag_destroy(ahc, scb_data->hscb_dmat); + aic_dma_tag_destroy(ahc, scb_data->hscb_dmat); break; case 0: break; @@ -4475,7 +4469,7 @@ ahc_alloc_scbs(struct ahc_softc *ahc) return; /* Allocate S/G space for the next batch of SCBS */ - if (ahc_dmamem_alloc(ahc, scb_data->sg_dmat, + if (aic_dmamem_alloc(ahc, scb_data->sg_dmat, (void **)&sg_map->sg_vaddr, BUS_DMA_NOWAIT, &sg_map->sg_dmamap) != 0) { free(sg_map, M_DEVBUF); @@ -4484,7 +4478,7 @@ ahc_alloc_scbs(struct ahc_softc *ahc) SLIST_INSERT_HEAD(&scb_data->sg_maps, sg_map, links); - ahc_dmamap_load(ahc, scb_data->sg_dmat, sg_map->sg_dmamap, + aic_dmamap_load(ahc, scb_data->sg_dmat, sg_map->sg_dmamap, sg_map->sg_vaddr, PAGE_SIZE, ahc_dmamap_cb, &sg_map->sg_physaddr, /*flags*/0); @@ -4511,9 +4505,9 @@ ahc_alloc_scbs(struct ahc_softc *ahc) */ next_scb->sg_list_phys = physaddr + sizeof(struct ahc_dma_seg); next_scb->ahc_softc = ahc; - next_scb->flags = SCB_FREE; + next_scb->flags = SCB_FLAG_NONE; #ifndef __linux__ - error = ahc_dmamap_create(ahc, ahc->buffer_dmat, /*flags*/0, + error = aic_dmamap_create(ahc, ahc->buffer_dmat, /*flags*/0, &next_scb->dmamap); if (error != 0) break; @@ -4748,7 +4742,7 @@ ahc_chip_init(struct ahc_softc *ahc) for (wait = 5000; (ahc_inb(ahc, SBLKCTL) & (ENAB40|ENAB20)) == 0 && wait; wait--) - ahc_delay(100); + aic_delay(100); } ahc_restart(ahc); return (0); @@ -4761,6 +4755,7 @@ int ahc_init(struct ahc_softc *ahc) { int max_targ; + int error; u_int i; u_int scsi_conf; u_int ultraenb; @@ -4818,7 +4813,7 @@ ahc_init(struct ahc_softc *ahc) #ifndef __linux__ /* DMA tag for mapping buffers into device visible space. */ - if (ahc_dma_tag_create(ahc, ahc->parent_dmat, /*alignment*/1, + if (aic_dma_tag_create(ahc, ahc->parent_dmat, /*alignment*/1, /*boundary*/BUS_SPACE_MAXADDR_32BIT + 1, /*lowaddr*/ahc->flags & AHC_39BIT_ADDRESSING ? (bus_addr_t)0x7FFFFFFFFFULL @@ -4849,7 +4844,7 @@ ahc_init(struct ahc_softc *ahc) if ((ahc->features & AHC_TARGETMODE) != 0) driver_data_size += AHC_TMODE_CMDS * sizeof(struct target_cmd) + /*DMA WideOdd Bug Buffer*/1; - if (ahc_dma_tag_create(ahc, ahc->parent_dmat, /*alignment*/1, + if (aic_dma_tag_create(ahc, ahc->parent_dmat, /*alignment*/1, /*boundary*/BUS_SPACE_MAXADDR_32BIT + 1, /*lowaddr*/BUS_SPACE_MAXADDR_32BIT, /*highaddr*/BUS_SPACE_MAXADDR, @@ -4864,7 +4859,7 @@ ahc_init(struct ahc_softc *ahc) ahc->init_level++; /* Allocation of driver data */ - if (ahc_dmamem_alloc(ahc, ahc->shared_data_dmat, + if (aic_dmamem_alloc(ahc, ahc->shared_data_dmat, (void **)&ahc->qoutfifo, BUS_DMA_NOWAIT, &ahc->shared_data_dmamap) != 0) { return (ENOMEM); @@ -4873,7 +4868,7 @@ ahc_init(struct ahc_softc *ahc) ahc->init_level++; /* And permanently map it in */ - ahc_dmamap_load(ahc, ahc->shared_data_dmat, ahc->shared_data_dmamap, + aic_dmamap_load(ahc, ahc->shared_data_dmat, ahc->shared_data_dmamap, ahc->qoutfifo, driver_data_size, ahc_dmamap_cb, &ahc->shared_data_busaddr, /*flags*/0); @@ -4916,6 +4911,13 @@ ahc_init(struct ahc_softc *ahc) } } + /* + * Fire up a recovery thread for this controller. + */ + error = ahc_spawn_recovery_thread(ahc); + if (error != 0) + return (error); + if (ahc->scb_data->maxhscbs < AHC_SCB_MAX_ALLOC) { ahc->flags |= AHC_PAGESCBS; } else { @@ -5113,8 +5115,14 @@ ahc_pause_and_flushwork(struct ahc_softc *ahc) ahc->flags |= AHC_ALL_INTERRUPTS; paused = FALSE; do { - if (paused) + if (paused) { ahc_unpause(ahc); + /* + * Give the sequencer some time to service + * any active selections. + */ + aic_delay(200); + } ahc_intr(ahc); ahc_pause(ahc); paused = TRUE; @@ -5400,12 +5408,12 @@ ahc_search_qinfifo(struct ahc_softc *ahc, int target, char channel, cam_status ostat; cam_status cstat; - ostat = ahc_get_transaction_status(scb); + ostat = aic_get_transaction_status(scb); if (ostat == CAM_REQ_INPROG) - ahc_set_transaction_status(scb, status); - cstat = ahc_get_transaction_status(scb); + aic_set_transaction_status(scb, status); + cstat = aic_get_transaction_status(scb); if (cstat != CAM_REQ_CMP) - ahc_freeze_scb(scb); + aic_freeze_scb(scb); if ((scb->flags & SCB_ACTIVE) == 0) printf("Inactive SCB in qinfifo\n"); ahc_done(ahc, scb); @@ -5512,13 +5520,13 @@ ahc_search_qinfifo(struct ahc_softc *ahc, int target, char channel, cam_status ostat; cam_status cstat; - ostat = ahc_get_transaction_status(scb); + ostat = aic_get_transaction_status(scb); if (ostat == CAM_REQ_INPROG) - ahc_set_transaction_status(scb, + aic_set_transaction_status(scb, status); - cstat = ahc_get_transaction_status(scb); + cstat = aic_get_transaction_status(scb); if (cstat != CAM_REQ_CMP) - ahc_freeze_scb(scb); + aic_freeze_scb(scb); if ((scb->flags & SCB_ACTIVE) == 0) printf("Inactive SCB in Waiting List\n"); ahc_done(ahc, scb); @@ -5540,7 +5548,7 @@ ahc_search_qinfifo(struct ahc_softc *ahc, int target, char channel, } ahc_outb(ahc, SCBPTR, curscbptr); - found += ahc_search_untagged_queues(ahc, /*ahc_io_ctx_t*/NULL, target, + found += ahc_search_untagged_queues(ahc, /*aic_io_ctx_t*/NULL, target, channel, lun, status, action); if (action == SEARCH_COMPLETE) @@ -5549,7 +5557,7 @@ ahc_search_qinfifo(struct ahc_softc *ahc, int target, char channel, } int -ahc_search_untagged_queues(struct ahc_softc *ahc, ahc_io_ctx_t ctx, +ahc_search_untagged_queues(struct ahc_softc *ahc, aic_io_ctx_t ctx, int target, char channel, int lun, uint32_t status, ahc_search_action action) { @@ -5620,12 +5628,12 @@ ahc_search_untagged_queues(struct ahc_softc *ahc, ahc_io_ctx_t ctx, cam_status ostat; cam_status cstat; - ostat = ahc_get_transaction_status(scb); + ostat = aic_get_transaction_status(scb); if (ostat == CAM_REQ_INPROG) - ahc_set_transaction_status(scb, status); - cstat = ahc_get_transaction_status(scb); + aic_set_transaction_status(scb, status); + cstat = aic_get_transaction_status(scb); if (cstat != CAM_REQ_CMP) - ahc_freeze_scb(scb); + aic_freeze_scb(scb); if ((scb->flags & SCB_ACTIVE) == 0) printf("Inactive SCB in untaggedQ\n"); ahc_done(ahc, scb); @@ -5924,11 +5932,11 @@ ahc_abort_scbs(struct ahc_softc *ahc, int target, char channel, if (ahc_match_scb(ahc, scbp, target, channel, lun, tag, role)) { cam_status ostat; - ostat = ahc_get_transaction_status(scbp); + ostat = aic_get_transaction_status(scbp); if (ostat == CAM_REQ_INPROG) - ahc_set_transaction_status(scbp, status); - if (ahc_get_transaction_status(scbp) != CAM_REQ_CMP) - ahc_freeze_scb(scbp); + aic_set_transaction_status(scbp, status); + if (aic_get_transaction_status(scbp) != CAM_REQ_CMP) + aic_freeze_scb(scbp); if ((scbp->flags & SCB_ACTIVE) == 0) printf("Inactive SCB on pending list\n"); ahc_done(ahc, scbp); @@ -5950,7 +5958,7 @@ ahc_reset_current_bus(struct ahc_softc *ahc) scsiseq = ahc_inb(ahc, SCSISEQ); ahc_outb(ahc, SCSISEQ, scsiseq | SCSIRSTO); ahc_flush_device_writes(ahc); - ahc_delay(AHC_BUSRESET_DELAY); + aic_delay(AHC_BUSRESET_DELAY); /* Turn off the bus reset */ ahc_outb(ahc, SCSISEQ, scsiseq & ~SCSIRSTO); @@ -6157,7 +6165,7 @@ ahc_calc_residual(struct ahc_softc *ahc, struct scb *scb) */ hscb = scb->hscb; - sgptr = ahc_le32toh(hscb->sgptr); + sgptr = aic_le32toh(hscb->sgptr); if ((sgptr & SG_RESID_VALID) == 0) /* Case 1 */ return; @@ -6168,10 +6176,10 @@ ahc_calc_residual(struct ahc_softc *ahc, struct scb *scb) return; spkt = &hscb->shared_data.status; - resid_sgptr = ahc_le32toh(spkt->residual_sg_ptr); + resid_sgptr = aic_le32toh(spkt->residual_sg_ptr); if ((sgptr & SG_FULL_RESID) != 0) { /* Case 3 */ - resid = ahc_get_transfer_length(scb); + resid = aic_get_transfer_length(scb); } else if ((resid_sgptr & SG_LIST_NULL) != 0) { /* Case 4 */ return; @@ -6184,7 +6192,7 @@ ahc_calc_residual(struct ahc_softc *ahc, struct scb *scb) * Remainder of the SG where the transfer * stopped. */ - resid = ahc_le32toh(spkt->residual_datacnt) & AHC_SG_LEN_MASK; + resid = aic_le32toh(spkt->residual_datacnt) & AHC_SG_LEN_MASK; sg = ahc_sg_bus_to_virt(scb, resid_sgptr & SG_PTR_MASK); /* The residual sg_ptr always points to the next sg */ @@ -6195,15 +6203,15 @@ ahc_calc_residual(struct ahc_softc *ahc, struct scb *scb) * SG segments that are after the SG where * the transfer stopped. */ - while ((ahc_le32toh(sg->len) & AHC_DMA_LAST_SEG) == 0) { + while ((aic_le32toh(sg->len) & AHC_DMA_LAST_SEG) == 0) { sg++; - resid += ahc_le32toh(sg->len) & AHC_SG_LEN_MASK; + resid += aic_le32toh(sg->len) & AHC_SG_LEN_MASK; } } if ((scb->flags & SCB_SENSE) == 0) - ahc_set_residual(scb, resid); + aic_set_residual(scb, resid); else - ahc_set_sense_residual(scb, resid); + aic_set_sense_residual(scb, resid); #ifdef AHC_DEBUG if ((ahc_debug & AHC_SHOW_MISC) != 0) { @@ -6483,7 +6491,7 @@ ahc_download_instr(struct ahc_softc *ahc, u_int instrptr, uint8_t *dconsts) /* * The firmware is always compiled into a little endian format. */ - instr.integer = ahc_le32toh(*(uint32_t*)&seqprog[instrptr * 4]); + instr.integer = aic_le32toh(*(uint32_t*)&seqprog[instrptr * 4]); fmt1_ins = &instr.format1; fmt3_ins = NULL; @@ -6588,7 +6596,7 @@ ahc_download_instr(struct ahc_softc *ahc, u_int instrptr, uint8_t *dconsts) } } /* The sequencer is a little endian cpu */ - instr.integer = ahc_htole32(instr.integer); + instr.integer = aic_htole32(instr.integer); ahc_outsb(ahc, SEQRAM, instr.bytes, 4); break; default: @@ -6828,6 +6836,324 @@ ahc_dump_card_state(struct ahc_softc *ahc) ahc_unpause(ahc); } +/*************************** Timeout Handling *********************************/ +void +ahc_timeout(struct scb *scb) +{ + struct ahc_softc *ahc; + + ahc = scb->ahc_softc; + if ((scb->flags & SCB_ACTIVE) != 0) { + if ((scb->flags & SCB_TIMEDOUT) == 0) { + LIST_INSERT_HEAD(&ahc->timedout_scbs, scb, + timedout_links); + scb->flags |= SCB_TIMEDOUT; + } + ahc_wakeup_recovery_thread(ahc); + } +} + +/* + * ahc_recover_commands determines if any of the commands that have currently + * timedout are the root cause for this timeout. Innocent commands are given + * a new timeout while we wait for the command executing on the bus to timeout. + * This routine is invoked from a thread context so we are allowed to sleep. + * Our lock is not held on entry. + */ +void +ahc_recover_commands(struct ahc_softc *ahc) +{ + struct scb *scb; + long s; + int found; + int restart_needed; + u_int last_phase; + + ahc_lock(ahc, &s); + + /* + * Pause the controller and manually flush any + * commands that have just completed but that our + * interrupt handler has yet to see. + */ + ahc_pause_and_flushwork(ahc); + + if (LIST_EMPTY(&ahc->timedout_scbs) != 0) { + /* + * The timedout commands have already + * completed. This typically means + * that either the timeout value was on + * the hairy edge of what the device + * requires or - more likely - interrupts + * are not happening. + */ + printf("%s: Timedout SCBs already complete. " + "Interrupts may not be functioning.\n", ahc_name(ahc)); + ahc_unpause(ahc); + ahc_unlock(ahc, &s); + return; + } + + restart_needed = 0; + printf("%s: Recovery Initiated\n", ahc_name(ahc)); + ahc_dump_card_state(ahc); + + last_phase = ahc_inb(ahc, LASTPHASE); + while ((scb = LIST_FIRST(&ahc->timedout_scbs)) != NULL) { + u_int active_scb_index; + u_int saved_scbptr; + int target; + int lun; + int i; + char channel; + + target = SCB_GET_TARGET(ahc, scb); + channel = SCB_GET_CHANNEL(ahc, scb); + lun = SCB_GET_LUN(scb); + + ahc_print_path(ahc, scb); + printf("SCB 0x%x - timed out\n", scb->hscb->tag); + if (scb->sg_count > 0) { + for (i = 0; i < scb->sg_count; i++) { + printf("sg[%d] - Addr 0x%x : Length %d\n", + i, + scb->sg_list[i].addr, + scb->sg_list[i].len & AHC_SG_LEN_MASK); + } + } + if (scb->flags & (SCB_DEVICE_RESET|SCB_ABORT)) { + /* + * Been down this road before. + * Do a full bus reset. + */ + aic_set_transaction_status(scb, CAM_CMD_TIMEOUT); +bus_reset: + found = ahc_reset_channel(ahc, channel, + /*Initiate Reset*/TRUE); + printf("%s: Issued Channel %c Bus Reset. " + "%d SCBs aborted\n", ahc_name(ahc), channel, + found); + continue; + } + + /* + * Remove the command from the timedout list in + * preparation for requeing it. + */ + LIST_REMOVE(scb, timedout_links); + scb->flags &= ~SCB_TIMEDOUT; + + /* + * If we are a target, transition to bus free and report + * the timeout. + * + * The target/initiator that is holding up the bus may not + * be the same as the one that triggered this timeout + * (different commands have different timeout lengths). + * If the bus is idle and we are actiing as the initiator + * for this request, queue a BDR message to the timed out + * target. Otherwise, if the timed out transaction is + * active: + * Initiator transaction: + * Stuff the message buffer with a BDR message and assert + * ATN in the hopes that the target will let go of the bus + * and go to the mesgout phase. If this fails, we'll + * get another timeout 2 seconds later which will attempt + * a bus reset. + * + * Target transaction: + * Transition to BUS FREE and report the error. + * It's good to be the target! + */ + saved_scbptr = ahc_inb(ahc, SCBPTR); + active_scb_index = ahc_inb(ahc, SCB_TAG); + + if ((ahc_inb(ahc, SEQ_FLAGS) & NOT_IDENTIFIED) == 0 + && (active_scb_index < ahc->scb_data->numscbs)) { + struct scb *active_scb; + + /* + * If the active SCB is not us, assume that + * the active SCB has a longer timeout than + * the timedout SCB, and wait for the active + * SCB to timeout. + */ + active_scb = ahc_lookup_scb(ahc, active_scb_index); + if (active_scb != scb) { + u_int newtimeout; + + ahc_print_path(ahc, scb); + printf("Other SCB Timeout%s", + (scb->flags & SCB_OTHERTCL_TIMEOUT) != 0 + ? " again\n" : "\n"); + scb->flags |= SCB_OTHERTCL_TIMEOUT; + newtimeout = + MAX(aic_get_timeout(active_scb), + aic_get_timeout(scb)); + aic_scb_timer_reset(scb, newtimeout); + continue; + } + + /* It's us */ + if ((scb->flags & SCB_TARGET_SCB) != 0) { + + /* + * Send back any queued up transactions + * and properly record the error condition. + */ + ahc_abort_scbs(ahc, SCB_GET_TARGET(ahc, scb), + SCB_GET_CHANNEL(ahc, scb), + SCB_GET_LUN(scb), + scb->hscb->tag, + ROLE_TARGET, + CAM_CMD_TIMEOUT); + + /* Will clear us from the bus */ + restart_needed = 1; + break; + } + + ahc_set_recoveryscb(ahc, active_scb); + ahc_outb(ahc, MSG_OUT, HOST_MSG); + ahc_outb(ahc, SCSISIGO, last_phase|ATNO); + ahc_print_path(ahc, active_scb); + printf("BDR message in message buffer\n"); + active_scb->flags |= SCB_DEVICE_RESET; + aic_scb_timer_reset(scb, 2 * 1000000); + } else if (last_phase != P_BUSFREE + && (ahc_inb(ahc, SSTAT1) & REQINIT) == 0) { + /* + * SCB is not identified, there + * is no pending REQ, and the sequencer + * has not seen a busfree. Looks like + * a stuck connection waiting to + * go busfree. Reset the bus. + */ + printf("%s: Connection stuck awaiting busfree or " + "Identify Msg.\n", ahc_name(ahc)); + goto bus_reset; + } else { + int disconnected; + + if (last_phase != P_BUSFREE + && (ahc_inb(ahc, SSTAT0) & TARGET) != 0) { + /* Hung target selection. Goto busfree */ + printf("%s: Hung target selection\n", + ahc_name(ahc)); + restart_needed = 1; + break; + } + + /* XXX Shouldn't panic. Just punt instead? */ + if ((scb->flags & SCB_TARGET_SCB) != 0) + panic("Timed-out target SCB but bus idle"); + + if (ahc_search_qinfifo(ahc, target, channel, lun, + scb->hscb->tag, ROLE_INITIATOR, + /*status*/0, SEARCH_COUNT) > 0) { + disconnected = FALSE; + } else { + disconnected = TRUE; + } + + if (disconnected) { + + ahc_set_recoveryscb(ahc, scb); + /* + * Actually re-queue this SCB in an attempt + * to select the device before it reconnects. + * In either case (selection or reselection), + * we will now issue a target reset to the + * timed-out device. + * + * Set the MK_MESSAGE control bit indicating + * that we desire to send a message. We + * also set the disconnected flag since + * in the paging case there is no guarantee + * that our SCB control byte matches the + * version on the card. We don't want the + * sequencer to abort the command thinking + * an unsolicited reselection occurred. + */ + scb->hscb->control |= MK_MESSAGE|DISCONNECTED; + scb->flags |= SCB_DEVICE_RESET; + + /* + * Remove any cached copy of this SCB in the + * disconnected list in preparation for the + * queuing of our abort SCB. We use the + * same element in the SCB, SCB_NEXT, for + * both the qinfifo and the disconnected list. + */ + ahc_search_disc_list(ahc, target, channel, + lun, scb->hscb->tag, + /*stop_on_first*/TRUE, + /*remove*/TRUE, + /*save_state*/FALSE); + + /* + * In the non-paging case, the sequencer will + * never re-reference the in-core SCB. + * To make sure we are notified during + * reslection, set the MK_MESSAGE flag in + * the card's copy of the SCB. + */ + if ((ahc->flags & AHC_PAGESCBS) == 0) { + ahc_outb(ahc, SCBPTR, scb->hscb->tag); + ahc_outb(ahc, SCB_CONTROL, + ahc_inb(ahc, SCB_CONTROL) + | MK_MESSAGE); + } + + /* + * Clear out any entries in the QINFIFO first + * so we are the next SCB for this target + * to run. + */ + ahc_search_qinfifo(ahc, + SCB_GET_TARGET(ahc, scb), + channel, SCB_GET_LUN(scb), + SCB_LIST_NULL, + ROLE_INITIATOR, + CAM_REQUEUE_REQ, + SEARCH_COMPLETE); + ahc_print_path(ahc, scb); + printf("Queuing a BDR SCB\n"); + ahc_qinfifo_requeue_tail(ahc, scb); + ahc_outb(ahc, SCBPTR, saved_scbptr); + aic_scb_timer_reset(scb, 2 * 1000000); + } else { + /* Go "immediatly" to the bus reset */ + /* This shouldn't happen */ + ahc_set_recoveryscb(ahc, scb); + ahc_print_path(ahc, scb); + printf("SCB %d: Immediate reset. " + "Flags = 0x%x\n", scb->hscb->tag, + scb->flags); + goto bus_reset; + } + } + break; + } + + /* + * Any remaining SCBs were not the "culprit", so remove + * them from the timeout list. The timer for these commands + * will be reset once the recovery SCB completes. + */ + while ((scb = LIST_FIRST(&ahc->timedout_scbs)) != NULL) { + + LIST_REMOVE(scb, timedout_links); + scb->flags &= ~SCB_TIMEDOUT; + } + + if (restart_needed) + ahc_restart(ahc); + else + ahc_unpause(ahc); + ahc_unlock(ahc, &s); +} + /************************* Target Mode ****************************************/ #ifdef AHC_TARGET_MODE cam_status @@ -7306,7 +7632,7 @@ ahc_run_tqinfifo(struct ahc_softc *ahc, int paused) break; cmd->cmd_valid = 0; - ahc_dmamap_sync(ahc, ahc->shared_data_dmat, + aic_dmamap_sync(ahc, ahc->shared_data_dmat, ahc->shared_data_dmamap, ahc_targetcmd_offset(ahc, ahc->tqinfifonext), sizeof(struct target_cmd), @@ -7443,7 +7769,7 @@ ahc_handle_target_cmd(struct ahc_softc *ahc, struct target_cmd *cmd) initiator, target, lun, ahc->pending_device); #endif ahc->pending_device = lstate; - ahc_freeze_ccb((union ccb *)atio); + aic_freeze_ccb((union ccb *)atio); atio->ccb_h.flags |= CAM_DIS_DISCONNECT; } xpt_done((union ccb*)atio); diff --git a/sys/dev/aic7xxx/aic7xxx.h b/sys/dev/aic7xxx/aic7xxx.h index ef1214c..7458ebc 100644 --- a/sys/dev/aic7xxx/aic7xxx.h +++ b/sys/dev/aic7xxx/aic7xxx.h @@ -37,7 +37,7 @@ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * - * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.h#79 $ + * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.h#85 $ * * $FreeBSD$ */ @@ -243,7 +243,7 @@ typedef enum { */ AHC_AIC7850_FE = AHC_SPIOCAP|AHC_AUTOPAUSE|AHC_TARGETMODE|AHC_ULTRA, AHC_AIC7860_FE = AHC_AIC7850_FE, - AHC_AIC7870_FE = AHC_TARGETMODE, + AHC_AIC7870_FE = AHC_TARGETMODE|AHC_AUTOPAUSE, AHC_AIC7880_FE = AHC_AIC7870_FE|AHC_ULTRA, /* * Although we have space for both the initiator and @@ -366,7 +366,8 @@ typedef enum { AHC_SCB_CONFIG_USED = 0x4000000, /* No SEEPROM but SCB2 had info. */ AHC_NO_BIOS_INIT = 0x8000000, /* No BIOS left over settings. */ AHC_DISABLE_PCI_PERR = 0x10000000, - AHC_HAS_TERM_LOGIC = 0x20000000 + AHC_HAS_TERM_LOGIC = 0x20000000, + AHC_SHUTDOWN_RECOVERY = 0x40000000 /* Terminate recovery thread. */ } ahc_flag; /************************* Hardware SCB Definition ***************************/ @@ -411,6 +412,7 @@ struct target_data { uint8_t initiator_tag; /* Initiator's transaction tag */ }; +#define MAX_CDB_LEN 16 struct hardware_scb { /*0*/ union { /* @@ -530,7 +532,7 @@ struct sg_map_node { * The current state of this SCB. */ typedef enum { - SCB_FREE = 0x0000, + SCB_FLAG_NONE = 0x0000, SCB_OTHERTCL_TIMEOUT = 0x0002,/* * Another device was active * during the first timeout for @@ -560,12 +562,16 @@ typedef enum { * to report the error. */ SCB_TARGET_SCB = 0x2000, - SCB_SILENT = 0x4000 /* + SCB_SILENT = 0x4000,/* * Be quiet about transmission type * errors. They are expected and we * don't want to upset the user. This * flag is typically used during DV. */ + SCB_TIMEDOUT = 0x8000 /* + * SCB has timed out and is on the + * timedout list. + */ } scb_flag; struct scb { @@ -575,7 +581,8 @@ struct scb { TAILQ_ENTRY(scb) tqe; } links; LIST_ENTRY(scb) pending_links; - ahc_io_ctx_t io_ctx; + LIST_ENTRY(scb) timedout_links; + aic_io_ctx_t io_ctx; struct ahc_softc *ahc_softc; scb_flag flags; #ifndef __linux__ @@ -929,6 +936,11 @@ struct ahc_softc { LIST_HEAD(, scb) pending_scbs; /* + * SCBs whose timeout routine has been called. + */ + LIST_HEAD(, scb) timedout_scbs; + + /* * Counting lock for deferring the release of additional * untagged transactions from the untagged_queues. When * the lock is decremented to 0, all queues in the @@ -958,7 +970,7 @@ struct ahc_softc { /* * Platform specific device information. */ - ahc_dev_softc_t dev_softc; + aic_dev_softc_t dev_softc; /* * Bus specific device information. @@ -1135,6 +1147,9 @@ struct ahc_devinfo { }; /****************************** PCI Structures ********************************/ +#define AHC_PCI_IOADDR PCIR_BAR(0) /* I/O Address */ +#define AHC_PCI_MEMADDR PCIR_BAR(1) /* Mem I/O Address */ + typedef int (ahc_device_setup_t)(struct ahc_softc *); struct ahc_pci_identity { @@ -1167,7 +1182,7 @@ void ahc_busy_tcl(struct ahc_softc *ahc, u_int tcl, u_int busyid); /***************************** PCI Front End *********************************/ -struct ahc_pci_identity *ahc_find_pci_device(ahc_dev_softc_t); +struct ahc_pci_identity *ahc_find_pci_device(aic_dev_softc_t); int ahc_pci_config(struct ahc_softc *, struct ahc_pci_identity *); int ahc_pci_test_register_access(struct ahc_softc *); @@ -1231,7 +1246,7 @@ int ahc_search_qinfifo(struct ahc_softc *ahc, int target, role_t role, uint32_t status, ahc_search_action action); int ahc_search_untagged_queues(struct ahc_softc *ahc, - ahc_io_ctx_t ctx, + aic_io_ctx_t ctx, int target, char channel, int lun, uint32_t status, ahc_search_action action); @@ -1248,6 +1263,8 @@ int ahc_abort_scbs(struct ahc_softc *ahc, int target, void ahc_restart(struct ahc_softc *ahc); void ahc_calc_residual(struct ahc_softc *ahc, struct scb *scb); +void ahc_timeout(struct scb *scb); +void ahc_recover_commands(struct ahc_softc *ahc); /*************************** Utility Functions ********************************/ struct ahc_phase_table_entry* ahc_lookup_phase_entry(int phase); diff --git a/sys/dev/aic7xxx/aic7xxx.reg b/sys/dev/aic7xxx/aic7xxx.reg index 810ec70..e196d83 100644 --- a/sys/dev/aic7xxx/aic7xxx.reg +++ b/sys/dev/aic7xxx/aic7xxx.reg @@ -39,7 +39,7 @@ * * $FreeBSD$ */ -VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic7xxx.reg#39 $" +VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic7xxx.reg#40 $" /* * This file is processed by the aic7xxx_asm utility for use in assembling @@ -1306,7 +1306,6 @@ scratch_ram { */ MWI_RESIDUAL { size 1 - alias TARG_IMMEDIATE_SCB } /* * SCBID of the next SCB to be started by the controller. @@ -1461,6 +1460,7 @@ scratch_ram { */ LAST_MSG { size 1 + alias TARG_IMMEDIATE_SCB } /* diff --git a/sys/dev/aic7xxx/aic7xxx.seq b/sys/dev/aic7xxx/aic7xxx.seq index d84b741..1519639 100644 --- a/sys/dev/aic7xxx/aic7xxx.seq +++ b/sys/dev/aic7xxx/aic7xxx.seq @@ -40,7 +40,7 @@ * $FreeBSD$ */ -VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic7xxx.seq#56 $" +VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic7xxx.seq#58 $" PATCH_ARG_LIST = "struct ahc_softc *ahc" PREFIX = "ahc_" @@ -679,6 +679,7 @@ await_busfree: clr SCSIBUSL; /* Prevent bit leakage durint SELTO */ } and SXFRCTL0, ~SPIOEN; + mvi SEQ_FLAGS, NOT_IDENTIFIED|NO_CDB_SENT; test SSTAT1,REQINIT|BUSFREE jz .; test SSTAT1, BUSFREE jnz poll_for_work; mvi MISSED_BUSFREE call set_seqint; @@ -1097,7 +1098,7 @@ ultra2_dmahalt: test SCB_RESIDUAL_DATACNT[3], SG_LAST_SEG jz dma_mid_sg; if ((ahc->flags & AHC_TARGETROLE) != 0) { test SSTAT0, TARGET jz dma_last_sg; - if ((ahc->flags & AHC_TMODE_WIDEODD_BUG) != 0) { + if ((ahc->bugs & AHC_TMODE_WIDEODD_BUG) != 0) { test DMAPARAMS, DIRECTION jz dma_mid_sg; } } diff --git a/sys/dev/aic7xxx/aic7xxx_93cx6.c b/sys/dev/aic7xxx/aic7xxx_93cx6.c index ba01829..6d08d25 100644 --- a/sys/dev/aic7xxx/aic7xxx_93cx6.c +++ b/sys/dev/aic7xxx/aic7xxx_93cx6.c @@ -28,12 +28,9 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: //depot/aic7xxx/aic7xxx/aic7xxx_93cx6.c#17 $ + * $Id: //depot/aic7xxx/aic7xxx/aic7xxx_93cx6.c#19 $ */ -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - /* * The instruction set of the 93C66/56/46/26/06 chips are as follows: * @@ -72,6 +69,8 @@ __FBSDID("$FreeBSD$"); #include "aic7xxx_inline.h" #include "aic7xxx_93cx6.h" #else +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); #include <dev/aic7xxx/aic7xxx_osm.h> #include <dev/aic7xxx/aic7xxx_inline.h> #include <dev/aic7xxx/aic7xxx_93cx6.h> @@ -81,14 +80,22 @@ __FBSDID("$FreeBSD$"); * Right now, we only have to read the SEEPROM. But we make it easier to * add other 93Cx6 functions. */ -static struct seeprom_cmd { +struct seeprom_cmd { uint8_t len; - uint8_t bits[9]; -} seeprom_read = {3, {1, 1, 0}}; + uint8_t bits[11]; +}; +/* Short opcodes for the c46 */ static struct seeprom_cmd seeprom_ewen = {9, {1, 0, 0, 1, 1, 0, 0, 0, 0}}; static struct seeprom_cmd seeprom_ewds = {9, {1, 0, 0, 0, 0, 0, 0, 0, 0}}; + +/* Long opcodes for the C56/C66 */ +static struct seeprom_cmd seeprom_long_ewen = {11, {1, 0, 0, 1, 1, 0, 0, 0, 0}}; +static struct seeprom_cmd seeprom_long_ewds = {11, {1, 0, 0, 0, 0, 0, 0, 0, 0}}; + +/* Common opcodes */ static struct seeprom_cmd seeprom_write = {3, {1, 0, 1}}; +static struct seeprom_cmd seeprom_read = {3, {1, 1, 0}}; /* * Wait for the SEERDY to go high; about 800 ns. @@ -222,12 +229,25 @@ int ahc_write_seeprom(struct seeprom_descriptor *sd, uint16_t *buf, u_int start_addr, u_int count) { + struct seeprom_cmd *ewen, *ewds; uint16_t v; uint8_t temp; int i, k; /* Place the chip into write-enable mode */ - send_seeprom_cmd(sd, &seeprom_ewen); + if (sd->sd_chip == C46) { + ewen = &seeprom_ewen; + ewds = &seeprom_ewds; + } else if (sd->sd_chip == C56_66) { + ewen = &seeprom_long_ewen; + ewds = &seeprom_long_ewds; + } else { + printf("ahc_write_seeprom: unsupported seeprom type %d\n", + sd->sd_chip); + return (0); + } + + send_seeprom_cmd(sd, ewen); reset_seeprom(sd); /* Write all requested data out to the seeprom. */ @@ -277,7 +297,7 @@ ahc_write_seeprom(struct seeprom_descriptor *sd, uint16_t *buf, } /* Put the chip back into write-protect mode */ - send_seeprom_cmd(sd, &seeprom_ewds); + send_seeprom_cmd(sd, ewds); reset_seeprom(sd); return (1); diff --git a/sys/dev/aic7xxx/aic7xxx_inline.h b/sys/dev/aic7xxx/aic7xxx_inline.h index 2cc8a17..e25e104 100644 --- a/sys/dev/aic7xxx/aic7xxx_inline.h +++ b/sys/dev/aic7xxx/aic7xxx_inline.h @@ -37,7 +37,7 @@ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * - * $Id: //depot/aic7xxx/aic7xxx/aic7xxx_inline.h#43 $ + * $Id: //depot/aic7xxx/aic7xxx/aic7xxx_inline.h#47 $ * * $FreeBSD$ */ @@ -196,7 +196,7 @@ ahc_hscb_busaddr(struct ahc_softc *ahc, u_int index) static __inline void ahc_sync_scb(struct ahc_softc *ahc, struct scb *scb, int op) { - ahc_dmamap_sync(ahc, ahc->scb_data->hscb_dmat, + aic_dmamap_sync(ahc, ahc->scb_data->hscb_dmat, ahc->scb_data->hscb_dmamap, /*offset*/(scb->hscb - ahc->hscbs) * sizeof(*scb->hscb), /*len*/sizeof(*scb->hscb), op); @@ -208,7 +208,7 @@ ahc_sync_sglist(struct ahc_softc *ahc, struct scb *scb, int op) if (scb->sg_count == 0) return; - ahc_dmamap_sync(ahc, ahc->scb_data->sg_dmat, scb->sg_map->sg_dmamap, + aic_dmamap_sync(ahc, ahc->scb_data->sg_dmat, scb->sg_map->sg_dmamap, /*offset*/(scb->sg_list - scb->sg_map->sg_vaddr) * sizeof(struct ahc_dma_seg), /*len*/sizeof(struct ahc_dma_seg) * scb->sg_count, op); @@ -272,7 +272,7 @@ ahc_update_residual(struct ahc_softc *ahc, struct scb *scb) { uint32_t sgptr; - sgptr = ahc_le32toh(scb->hscb->sgptr); + sgptr = aic_le32toh(scb->hscb->sgptr); if ((sgptr & SG_RESID_VALID) != 0) ahc_calc_residual(ahc, scb); } @@ -383,13 +383,13 @@ ahc_free_scb(struct ahc_softc *ahc, struct scb *scb) hscb = scb->hscb; /* Clean up for the next user */ ahc->scb_data->scbindex[hscb->tag] = NULL; - scb->flags = SCB_FREE; + scb->flags = SCB_FLAG_NONE; hscb->control = 0; SLIST_INSERT_HEAD(&ahc->scb_data->free_scbs, scb, links.sle); /* Notify the OSM that a resource is now available. */ - ahc_platform_scb_free(ahc, scb); + aic_platform_scb_free(ahc, scb); } static __inline struct scb * @@ -427,7 +427,7 @@ ahc_swap_with_next_hscb(struct ahc_softc *ahc, struct scb *scb) memcpy(q_hscb, scb->hscb, sizeof(*scb->hscb)); if ((scb->flags & SCB_CDB32_PTR) != 0) { q_hscb->shared_data.cdb_ptr = - ahc_htole32(ahc_hscb_busaddr(ahc, q_hscb->tag) + aic_htole32(ahc_hscb_busaddr(ahc, q_hscb->tag) + offsetof(struct hardware_scb, cdb32)); } q_hscb->tag = saved_tag; @@ -458,7 +458,7 @@ ahc_queue_scb(struct ahc_softc *ahc, struct scb *scb) * Setup data "oddness". */ scb->hscb->lun &= LID; - if (ahc_get_transfer_length(scb) & 0x1) + if (aic_get_transfer_length(scb) & 0x1) scb->hscb->lun |= SCB_XFERLEN_ODD; /* @@ -512,7 +512,7 @@ static __inline int ahc_intr(struct ahc_softc *ahc); static __inline void ahc_sync_qoutfifo(struct ahc_softc *ahc, int op) { - ahc_dmamap_sync(ahc, ahc->shared_data_dmat, ahc->shared_data_dmamap, + aic_dmamap_sync(ahc, ahc->shared_data_dmat, ahc->shared_data_dmamap, /*offset*/0, /*len*/256, op); } @@ -521,7 +521,7 @@ ahc_sync_tqinfifo(struct ahc_softc *ahc, int op) { #ifdef AHC_TARGET_MODE if ((ahc->flags & AHC_TARGETROLE) != 0) { - ahc_dmamap_sync(ahc, ahc->shared_data_dmat, + aic_dmamap_sync(ahc, ahc->shared_data_dmat, ahc->shared_data_dmamap, ahc_targetcmd_offset(ahc, 0), sizeof(struct target_cmd) * AHC_TMODE_CMDS, @@ -542,7 +542,7 @@ ahc_check_cmdcmpltqueues(struct ahc_softc *ahc) u_int retval; retval = 0; - ahc_dmamap_sync(ahc, ahc->shared_data_dmat, ahc->shared_data_dmamap, + aic_dmamap_sync(ahc, ahc->shared_data_dmat, ahc->shared_data_dmamap, /*offset*/ahc->qoutfifonext, /*len*/1, BUS_DMASYNC_POSTREAD); if (ahc->qoutfifo[ahc->qoutfifonext] != SCB_LIST_NULL) @@ -550,7 +550,7 @@ ahc_check_cmdcmpltqueues(struct ahc_softc *ahc) #ifdef AHC_TARGET_MODE if ((ahc->flags & AHC_TARGETROLE) != 0 && (ahc->flags & AHC_TQINFIFO_BLOCKED) == 0) { - ahc_dmamap_sync(ahc, ahc->shared_data_dmat, + aic_dmamap_sync(ahc, ahc->shared_data_dmat, ahc->shared_data_dmamap, ahc_targetcmd_offset(ahc, ahc->tqinfifofnext), /*len*/sizeof(struct target_cmd), @@ -593,7 +593,7 @@ ahc_intr(struct ahc_softc *ahc) } if ((intstat & INT_PEND) == 0) { -#if AHC_PCI_CONFIG > 0 +#if AIC_PCI_CONFIG > 0 if (ahc->unsolicited_ints > 500) { ahc->unsolicited_ints = 0; if ((ahc->chip & AHC_PCI) != 0 diff --git a/sys/dev/aic7xxx/aic7xxx_osm.c b/sys/dev/aic7xxx/aic7xxx_osm.c index 2675448..3034f9b 100644 --- a/sys/dev/aic7xxx/aic7xxx_osm.c +++ b/sys/dev/aic7xxx/aic7xxx_osm.c @@ -1,5 +1,5 @@ /* - * Bus independent FreeBSD shim for the aic7xxx based adaptec SCSI controllers + * Bus independent FreeBSD shim for the aic7xxx based Adaptec SCSI controllers * * Copyright (c) 1994-2001 Justin T. Gibbs. * All rights reserved. @@ -28,7 +28,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: //depot/aic7xxx/freebsd/dev/aic7xxx/aic7xxx_osm.c#13 $ + * $Id: //depot/aic7xxx/freebsd/dev/aic7xxx/aic7xxx_osm.c#20 $ */ #include <sys/cdefs.h> @@ -37,10 +37,14 @@ __FBSDID("$FreeBSD$"); #include <dev/aic7xxx/aic7xxx_osm.h> #include <dev/aic7xxx/aic7xxx_inline.h> +#include <sys/kthread.h> + #ifndef AHC_TMODE_ENABLE #define AHC_TMODE_ENABLE 0 #endif +#include <dev/aic7xxx/aic_osm_lib.c> + #define ccb_scb_ptr spriv_ptr0 devclass_t ahc_devclass; @@ -66,7 +70,6 @@ static int ahc_create_path(struct ahc_softc *ahc, char channel, u_int target, u_int lun, struct cam_path **path); -static void ahc_set_recoveryscb(struct ahc_softc *ahc, struct scb *scb); static int ahc_create_path(struct ahc_softc *ahc, char channel, u_int target, @@ -121,9 +124,16 @@ ahc_attach(struct ahc_softc *ahc) sim = NULL; sim2 = NULL; + /* + * Create a thread to perform all recovery. + */ + if (ahc_spawn_recovery_thread(ahc) != 0) + goto fail; + ahc_controller_info(ahc, ahc_info); printf("%s\n", ahc_info); ahc_lock(ahc, &s); + /* * Attach secondary channel first if the user has * declared it the primary channel. @@ -271,6 +281,8 @@ ahc_done(struct ahc_softc *ahc, struct scb *scb) ccb = scb->io_ctx; LIST_REMOVE(scb, pending_links); + if ((scb->flags & SCB_TIMEDOUT) != 0) + LIST_REMOVE(scb, timedout_links); if ((scb->flags & SCB_UNTAGGEDQ) != 0) { struct scb_tailq *untagged_q; int target_offset; @@ -282,7 +294,7 @@ ahc_done(struct ahc_softc *ahc, struct scb *scb) ahc_run_untagged_queue(ahc, untagged_q); } - untimeout(ahc_timeout, (caddr_t)scb, ccb->ccb_h.timeout_ch); + untimeout(ahc_platform_timeout, (caddr_t)scb, ccb->ccb_h.timeout_ch); if ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) { bus_dmasync_op_t op; @@ -315,11 +327,11 @@ ahc_done(struct ahc_softc *ahc, struct scb *scb) xpt_print_path(ccb->ccb_h.path); printf("Still connected\n"); } - ahc_freeze_ccb(ccb); + aic_freeze_ccb(ccb); } } - if (ahc_get_transaction_status(scb) == CAM_REQ_INPROG) + if (aic_get_transaction_status(scb) == CAM_REQ_INPROG) ccb->ccb_h.status |= CAM_REQ_CMP; ccb->ccb_h.status &= ~CAM_SIM_QUEUED; ahc_free_scb(ahc, scb); @@ -336,34 +348,24 @@ ahc_done(struct ahc_softc *ahc, struct scb *scb) /* * We were able to complete the command successfully, - * so reinstate the timeouts for all other pending + * so renew the timeouts for all other pending * commands. */ LIST_FOREACH(list_scb, &ahc->pending_scbs, pending_links) { - union ccb *ccb; - uint64_t time; - - ccb = list_scb->io_ctx; - if (ccb->ccb_h.timeout == CAM_TIME_INFINITY) - continue; - - time = ccb->ccb_h.timeout; - time *= hz; - time /= 1000; - ccb->ccb_h.timeout_ch = - timeout(ahc_timeout, list_scb, time); + + aic_scb_timer_reset(scb, aic_get_timeout(scb)); } - if (ahc_get_transaction_status(scb) == CAM_BDR_SENT - || ahc_get_transaction_status(scb) == CAM_REQ_ABORTED) - ahc_set_transaction_status(scb, CAM_CMD_TIMEOUT); + if (aic_get_transaction_status(scb) == CAM_BDR_SENT + || aic_get_transaction_status(scb) == CAM_REQ_ABORTED) + aic_set_transaction_status(scb, CAM_CMD_TIMEOUT); ahc_print_path(ahc, scb); printf("no longer in timeout, status = %x\n", ccb->ccb_h.status); } /* Don't clobber any existing error state */ - if (ahc_get_transaction_status(scb) == CAM_REQ_INPROG) { + if (aic_get_transaction_status(scb) == CAM_REQ_INPROG) { ccb->ccb_h.status |= CAM_REQ_CMP; } else if ((scb->flags & SCB_SENSE) != 0) { /* @@ -379,7 +381,7 @@ ahc_done(struct ahc_softc *ahc, struct scb *scb) memset(&ccb->csio.sense_data, 0, sizeof(ccb->csio.sense_data)); memcpy(&ccb->csio.sense_data, ahc_get_sense_buf(ahc, scb), - (ahc_le32toh(scb->sg_list->len) & AHC_SG_LEN_MASK) + (aic_le32toh(scb->sg_list->len) & AHC_SG_LEN_MASK) - ccb->csio.sense_resid); scb->io_ctx->ccb_h.status |= CAM_AUTOSNS_VALID; } @@ -820,12 +822,12 @@ ahc_action(struct cam_sim *sim, union ccb *ccb) } case XPT_CALC_GEOMETRY: { - int extended; + int extended; extended = SIM_IS_SCSIBUS_B(ahc, sim) - ? ahc->flags & AHC_EXTENDED_TRANS_B - : ahc->flags & AHC_EXTENDED_TRANS_A; - cam_calc_geometry(&ccb->ccg, extended); + ? ahc->flags & AHC_EXTENDED_TRANS_B + : ahc->flags & AHC_EXTENDED_TRANS_A; + aic_calc_geometry(&ccb->ccg, extended); xpt_done(ccb); break; } @@ -1078,9 +1080,9 @@ ahc_execute_scb(void *arg, bus_dma_segment_t *dm_segs, int nsegments, if (error != 0) { if (error == EFBIG) - ahc_set_transaction_status(scb, CAM_REQ_TOO_BIG); + aic_set_transaction_status(scb, CAM_REQ_TOO_BIG); else - ahc_set_transaction_status(scb, CAM_REQ_CMP_ERR); + aic_set_transaction_status(scb, CAM_REQ_CMP_ERR); if (nsegments != 0) bus_dmamap_unload(ahc->buffer_dmat, scb->dmamap); ahc_lock(ahc, &s); @@ -1101,10 +1103,10 @@ ahc_execute_scb(void *arg, bus_dma_segment_t *dm_segs, int nsegments, while (dm_segs < end_seg) { uint32_t len; - sg->addr = ahc_htole32(dm_segs->ds_addr); + sg->addr = aic_htole32(dm_segs->ds_addr); len = dm_segs->ds_len | ((dm_segs->ds_addr >> 8) & 0x7F000000); - sg->len = ahc_htole32(len); + sg->len = aic_htole32(len); sg++; dm_segs++; } @@ -1115,7 +1117,7 @@ ahc_execute_scb(void *arg, bus_dma_segment_t *dm_segs, int nsegments, * sequencer will clear as soon as a data transfer * occurs. */ - scb->hscb->sgptr = ahc_htole32(scb->sg_list_phys|SG_FULL_RESID); + scb->hscb->sgptr = aic_htole32(scb->sg_list_phys|SG_FULL_RESID); if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) op = BUS_DMASYNC_PREREAD; @@ -1129,6 +1131,9 @@ ahc_execute_scb(void *arg, bus_dma_segment_t *dm_segs, int nsegments, tdata = &scb->hscb->shared_data.tdata; tdata->target_phases |= DPHASE_PENDING; + /* + * CAM data direction is relative to the initiator. + */ if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_OUT) tdata->data_phase = P_DATAOUT; else @@ -1146,12 +1151,12 @@ ahc_execute_scb(void *arg, bus_dma_segment_t *dm_segs, int nsegments, */ if ((ahc->bugs & AHC_TMODE_WIDEODD_BUG) != 0 && (ccb->csio.dxfer_len & 0x1) != 0 - && (ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) { + && (ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_OUT) { nsegments++; if (nsegments > AHC_NSEG) { - ahc_set_transaction_status(scb, + aic_set_transaction_status(scb, CAM_REQ_TOO_BIG); bus_dmamap_unload(ahc->buffer_dmat, scb->dmamap); @@ -1161,19 +1166,19 @@ ahc_execute_scb(void *arg, bus_dma_segment_t *dm_segs, int nsegments, xpt_done(ccb); return; } - sg->addr = ahc_htole32(ahc->dma_bug_buf); - sg->len = ahc_htole32(1); + sg->addr = aic_htole32(ahc->dma_bug_buf); + sg->len = aic_htole32(1); sg++; } } sg--; - sg->len |= ahc_htole32(AHC_DMA_LAST_SEG); + sg->len |= aic_htole32(AHC_DMA_LAST_SEG); /* Copy the first SG into the "current" data pointer area */ scb->hscb->dataptr = scb->sg_list->addr; scb->hscb->datacnt = scb->sg_list->len; } else { - scb->hscb->sgptr = ahc_htole32(SG_LIST_NULL); + scb->hscb->sgptr = aic_htole32(SG_LIST_NULL); scb->hscb->dataptr = 0; scb->hscb->datacnt = 0; } @@ -1186,7 +1191,7 @@ ahc_execute_scb(void *arg, bus_dma_segment_t *dm_segs, int nsegments, * Last time we need to check if this SCB needs to * be aborted. */ - if (ahc_get_transaction_status(scb) != CAM_REQ_INPROG) { + if (aic_get_transaction_status(scb) != CAM_REQ_INPROG) { if (nsegments != 0) bus_dmamap_unload(ahc->buffer_dmat, scb->dmamap); ahc_free_scb(ahc, scb); @@ -1235,7 +1240,7 @@ ahc_execute_scb(void *arg, bus_dma_segment_t *dm_segs, int nsegments, time *= hz; time /= 1000; ccb->ccb_h.timeout_ch = - timeout(ahc_timeout, (caddr_t)scb, time); + timeout(ahc_platform_timeout, (caddr_t)scb, time); } /* @@ -1304,7 +1309,7 @@ ahc_setup_data(struct ahc_softc *ahc, struct cam_sim *sim, || (ccb_h->flags & CAM_CDB_PHYS) != 0) { u_long s; - ahc_set_transaction_status(scb, + aic_set_transaction_status(scb, CAM_REQ_INVALID); ahc_lock(ahc, &s); ahc_free_scb(ahc, scb); @@ -1397,293 +1402,6 @@ ahc_setup_data(struct ahc_softc *ahc, struct cam_sim *sim, } static void -ahc_set_recoveryscb(struct ahc_softc *ahc, struct scb *scb) { - - if ((scb->flags & SCB_RECOVERY_SCB) == 0) { - struct scb *list_scb; - - scb->flags |= SCB_RECOVERY_SCB; - - /* - * Take all queued, but not sent SCBs out of the equation. - * Also ensure that no new CCBs are queued to us while we - * try to fix this problem. - */ - if ((scb->io_ctx->ccb_h.status & CAM_RELEASE_SIMQ) == 0) { - xpt_freeze_simq(SCB_GET_SIM(ahc, scb), /*count*/1); - scb->io_ctx->ccb_h.status |= CAM_RELEASE_SIMQ; - } - - /* - * Go through all of our pending SCBs and remove - * any scheduled timeouts for them. We will reschedule - * them after we've successfully fixed this problem. - */ - LIST_FOREACH(list_scb, &ahc->pending_scbs, pending_links) { - union ccb *ccb; - - ccb = list_scb->io_ctx; - untimeout(ahc_timeout, list_scb, ccb->ccb_h.timeout_ch); - } - } -} - -void -ahc_timeout(void *arg) -{ - struct scb *scb; - struct ahc_softc *ahc; - long s; - int found; - u_int last_phase; - int target; - int lun; - int i; - char channel; - - scb = (struct scb *)arg; - ahc = (struct ahc_softc *)scb->ahc_softc; - - ahc_lock(ahc, &s); - - ahc_pause_and_flushwork(ahc); - - if ((scb->flags & SCB_ACTIVE) == 0) { - /* Previous timeout took care of me already */ - printf("%s: Timedout SCB already complete. " - "Interrupts may not be functioning.\n", ahc_name(ahc)); - ahc_unpause(ahc); - ahc_unlock(ahc, &s); - return; - } - - target = SCB_GET_TARGET(ahc, scb); - channel = SCB_GET_CHANNEL(ahc, scb); - lun = SCB_GET_LUN(scb); - - ahc_print_path(ahc, scb); - printf("SCB 0x%x - timed out\n", scb->hscb->tag); - ahc_dump_card_state(ahc); - last_phase = ahc_inb(ahc, LASTPHASE); - if (scb->sg_count > 0) { - for (i = 0; i < scb->sg_count; i++) { - printf("sg[%d] - Addr 0x%x : Length %d\n", - i, - scb->sg_list[i].addr, - scb->sg_list[i].len & AHC_SG_LEN_MASK); - } - } - if (scb->flags & (SCB_DEVICE_RESET|SCB_ABORT)) { - /* - * Been down this road before. - * Do a full bus reset. - */ -bus_reset: - ahc_set_transaction_status(scb, CAM_CMD_TIMEOUT); - found = ahc_reset_channel(ahc, channel, /*Initiate Reset*/TRUE); - printf("%s: Issued Channel %c Bus Reset. " - "%d SCBs aborted\n", ahc_name(ahc), channel, found); - } else { - /* - * If we are a target, transition to bus free and report - * the timeout. - * - * The target/initiator that is holding up the bus may not - * be the same as the one that triggered this timeout - * (different commands have different timeout lengths). - * If the bus is idle and we are actiing as the initiator - * for this request, queue a BDR message to the timed out - * target. Otherwise, if the timed out transaction is - * active: - * Initiator transaction: - * Stuff the message buffer with a BDR message and assert - * ATN in the hopes that the target will let go of the bus - * and go to the mesgout phase. If this fails, we'll - * get another timeout 2 seconds later which will attempt - * a bus reset. - * - * Target transaction: - * Transition to BUS FREE and report the error. - * It's good to be the target! - */ - u_int active_scb_index; - u_int saved_scbptr; - - saved_scbptr = ahc_inb(ahc, SCBPTR); - active_scb_index = ahc_inb(ahc, SCB_TAG); - - if ((ahc_inb(ahc, SEQ_FLAGS) & NOT_IDENTIFIED) == 0 - && (active_scb_index < ahc->scb_data->numscbs)) { - struct scb *active_scb; - - /* - * If the active SCB is not us, assume that - * the active SCB has a longer timeout than - * the timedout SCB, and wait for the active - * SCB to timeout. - */ - active_scb = ahc_lookup_scb(ahc, active_scb_index); - if (active_scb != scb) { - struct ccb_hdr *ccbh; - uint64_t newtimeout; - - ahc_print_path(ahc, scb); - printf("Other SCB Timeout%s", - (scb->flags & SCB_OTHERTCL_TIMEOUT) != 0 - ? " again\n" : "\n"); - scb->flags |= SCB_OTHERTCL_TIMEOUT; - newtimeout = - MAX(active_scb->io_ctx->ccb_h.timeout, - scb->io_ctx->ccb_h.timeout); - newtimeout *= hz; - newtimeout /= 1000; - ccbh = &scb->io_ctx->ccb_h; - scb->io_ctx->ccb_h.timeout_ch = - timeout(ahc_timeout, scb, newtimeout); - ahc_unpause(ahc); - ahc_unlock(ahc, &s); - return; - } - - /* It's us */ - if ((scb->flags & SCB_TARGET_SCB) != 0) { - - /* - * Send back any queued up transactions - * and properly record the error condition. - */ - ahc_abort_scbs(ahc, SCB_GET_TARGET(ahc, scb), - SCB_GET_CHANNEL(ahc, scb), - SCB_GET_LUN(scb), - scb->hscb->tag, - ROLE_TARGET, - CAM_CMD_TIMEOUT); - - /* Will clear us from the bus */ - ahc_restart(ahc); - ahc_unlock(ahc, &s); - return; - } - - ahc_set_recoveryscb(ahc, active_scb); - ahc_outb(ahc, MSG_OUT, HOST_MSG); - ahc_outb(ahc, SCSISIGO, last_phase|ATNO); - ahc_print_path(ahc, active_scb); - printf("BDR message in message buffer\n"); - active_scb->flags |= SCB_DEVICE_RESET; - active_scb->io_ctx->ccb_h.timeout_ch = - timeout(ahc_timeout, (caddr_t)active_scb, 2 * hz); - ahc_unpause(ahc); - } else { - int disconnected; - - /* XXX Shouldn't panic. Just punt instead? */ - if ((scb->flags & SCB_TARGET_SCB) != 0) - panic("Timed-out target SCB but bus idle"); - - if (last_phase != P_BUSFREE - && (ahc_inb(ahc, SSTAT0) & TARGET) != 0) { - /* XXX What happened to the SCB? */ - /* Hung target selection. Goto busfree */ - printf("%s: Hung target selection\n", - ahc_name(ahc)); - ahc_restart(ahc); - ahc_unlock(ahc, &s); - return; - } - - if (ahc_search_qinfifo(ahc, target, channel, lun, - scb->hscb->tag, ROLE_INITIATOR, - /*status*/0, SEARCH_COUNT) > 0) { - disconnected = FALSE; - } else { - disconnected = TRUE; - } - - if (disconnected) { - - ahc_set_recoveryscb(ahc, scb); - /* - * Actually re-queue this SCB in an attempt - * to select the device before it reconnects. - * In either case (selection or reselection), - * we will now issue a target reset to the - * timed-out device. - * - * Set the MK_MESSAGE control bit indicating - * that we desire to send a message. We - * also set the disconnected flag since - * in the paging case there is no guarantee - * that our SCB control byte matches the - * version on the card. We don't want the - * sequencer to abort the command thinking - * an unsolicited reselection occurred. - */ - scb->hscb->control |= MK_MESSAGE|DISCONNECTED; - scb->flags |= SCB_DEVICE_RESET; - - /* - * Remove any cached copy of this SCB in the - * disconnected list in preparation for the - * queuing of our abort SCB. We use the - * same element in the SCB, SCB_NEXT, for - * both the qinfifo and the disconnected list. - */ - ahc_search_disc_list(ahc, target, channel, - lun, scb->hscb->tag, - /*stop_on_first*/TRUE, - /*remove*/TRUE, - /*save_state*/FALSE); - - /* - * In the non-paging case, the sequencer will - * never re-reference the in-core SCB. - * To make sure we are notified during - * reslection, set the MK_MESSAGE flag in - * the card's copy of the SCB. - */ - if ((ahc->flags & AHC_PAGESCBS) == 0) { - ahc_outb(ahc, SCBPTR, scb->hscb->tag); - ahc_outb(ahc, SCB_CONTROL, - ahc_inb(ahc, SCB_CONTROL) - | MK_MESSAGE); - } - - /* - * Clear out any entries in the QINFIFO first - * so we are the next SCB for this target - * to run. - */ - ahc_search_qinfifo(ahc, - SCB_GET_TARGET(ahc, scb), - channel, SCB_GET_LUN(scb), - SCB_LIST_NULL, - ROLE_INITIATOR, - CAM_REQUEUE_REQ, - SEARCH_COMPLETE); - ahc_print_path(ahc, scb); - printf("Queuing a BDR SCB\n"); - ahc_qinfifo_requeue_tail(ahc, scb); - ahc_outb(ahc, SCBPTR, saved_scbptr); - scb->io_ctx->ccb_h.timeout_ch = - timeout(ahc_timeout, (caddr_t)scb, 2 * hz); - ahc_unpause(ahc); - } else { - /* Go "immediatly" to the bus reset */ - /* This shouldn't happen */ - ahc_set_recoveryscb(ahc, scb); - ahc_print_path(ahc, scb); - printf("SCB %d: Immediate reset. " - "Flags = 0x%x\n", scb->hscb->tag, - scb->flags); - goto bus_reset; - } - } - } - ahc_unlock(ahc, &s); -} - -static void ahc_abort_ccb(struct ahc_softc *ahc, struct cam_sim *sim, union ccb *ccb) { union ccb *abort_ccb; @@ -1903,12 +1621,13 @@ ahc_detach(device_t dev) ahc_list_unlock(&l); return (ENOENT); } + TAILQ_REMOVE(&ahc_tailq, ahc, links); + ahc_list_unlock(&l); ahc_lock(ahc, &s); ahc_intr_enable(ahc, FALSE); bus_teardown_intr(dev, ahc->platform_data->irq, ahc->platform_data->ih); ahc_unlock(ahc, &s); ahc_free(ahc); - ahc_list_unlock(&l); return (0); } diff --git a/sys/dev/aic7xxx/aic7xxx_osm.h b/sys/dev/aic7xxx/aic7xxx_osm.h index 9fbb905..e47498f 100644 --- a/sys/dev/aic7xxx/aic7xxx_osm.h +++ b/sys/dev/aic7xxx/aic7xxx_osm.h @@ -29,7 +29,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: aic7xxx_osm.h,v 1.23 2003/07/01 15:51:52 scottl Exp $ + * $Id: //depot/aic7xxx/freebsd/dev/aic7xxx/aic7xxx_osm.h#18 $ * * $FreeBSD$ */ @@ -57,7 +57,7 @@ #endif #if NPCI > 0 -#define AHC_PCI_CONFIG 1 +#define AIC_PCI_CONFIG 1 #include <machine/bus_memio.h> #endif #include <machine/bus_pio.h> @@ -69,12 +69,12 @@ #include <sys/rman.h> #if NPCI > 0 -#if __FreeBSD_version < 500000 -#include <pci/pcireg.h> -#include <pci/pcivar.h> -#else +#if __FreeBSD_version >= 500000 #include <dev/pci/pcireg.h> #include <dev/pci/pcivar.h> +#else +#include <pci/pcireg.h> +#include <pci/pcivar.h> #endif #endif @@ -115,45 +115,6 @@ extern devclass_t ahc_devclass; #ifndef offsetof #define offsetof(type, member) ((size_t)(&((type *)0)->member)) #endif -/************************* Forward Declarations *******************************/ -typedef device_t ahc_dev_softc_t; -typedef union ccb *ahc_io_ctx_t; - -/***************************** Bus Space/DMA **********************************/ -#define ahc_dma_tag_create(ahc, parent_tag, alignment, boundary, \ - lowaddr, highaddr, filter, filterarg, \ - maxsize, nsegments, maxsegsz, flags, \ - dma_tagp) \ - bus_dma_tag_create(parent_tag, alignment, boundary, \ - lowaddr, highaddr, filter, filterarg, \ - maxsize, nsegments, maxsegsz, flags, \ - busdma_lock_mutex, &Giant, dma_tagp) - -#define ahc_dma_tag_destroy(ahc, tag) \ - bus_dma_tag_destroy(tag) - -#define ahc_dmamem_alloc(ahc, dmat, vaddr, flags, mapp) \ - bus_dmamem_alloc(dmat, vaddr, flags, mapp) - -#define ahc_dmamem_free(ahc, dmat, vaddr, map) \ - bus_dmamem_free(dmat, vaddr, map) - -#define ahc_dmamap_create(ahc, tag, flags, mapp) \ - bus_dmamap_create(tag, flags, mapp) - -#define ahc_dmamap_destroy(ahc, tag, map) \ - bus_dmamap_destroy(tag, map) - -#define ahc_dmamap_load(ahc, dmat, map, addr, buflen, callback, \ - callback_arg, flags) \ - bus_dmamap_load(dmat, map, addr, buflen, callback, callback_arg, flags) - -#define ahc_dmamap_unload(ahc, tag, map) \ - bus_dmamap_unload(tag, map) - -/* XXX Need to update Bus DMA for partial map syncs */ -#define ahc_dmamap_sync(ahc, dma_tag, dmamap, offset, len, op) \ - bus_dmamap_sync(dma_tag, dmamap, op) /************************ Tunable Driver Parameters **************************/ /* @@ -190,76 +151,22 @@ struct ahc_platform_data { struct resource *irq; void *ih; eventhandler_tag eh; + struct proc *recovery_thread; }; struct scb_platform_data { }; -/********************************* Byte Order *********************************/ -#if __FreeBSD_version >= 500000 -#define ahc_htobe16(x) htobe16(x) -#define ahc_htobe32(x) htobe32(x) -#define ahc_htobe64(x) htobe64(x) -#define ahc_htole16(x) htole16(x) -#define ahc_htole32(x) htole32(x) -#define ahc_htole64(x) htole64(x) - -#define ahc_be16toh(x) be16toh(x) -#define ahc_be32toh(x) be32toh(x) -#define ahc_be64toh(x) be64toh(x) -#define ahc_le16toh(x) le16toh(x) -#define ahc_le32toh(x) le32toh(x) -#define ahc_le64toh(x) le64toh(x) -#else -#define ahc_htobe16(x) (x) -#define ahc_htobe32(x) (x) -#define ahc_htobe64(x) (x) -#define ahc_htole16(x) (x) -#define ahc_htole32(x) (x) -#define ahc_htole64(x) (x) - -#define ahc_be16toh(x) (x) -#define ahc_be32toh(x) (x) -#define ahc_be64toh(x) (x) -#define ahc_le16toh(x) (x) -#define ahc_le32toh(x) (x) -#define ahc_le64toh(x) (x) -#endif - -/************************** Timer DataStructures ******************************/ -typedef struct callout ahc_timer_t; - /***************************** Core Includes **********************************/ #if AHC_REG_PRETTY_PRINT #define AIC_DEBUG_REGISTERS 1 #else #define AIC_DEBUG_REGISTERS 0 #endif -#include <dev/aic7xxx/aic7xxx.h> - -/***************************** Timer Facilities *******************************/ -timeout_t ahc_timeout; - -#if __FreeBSD_version >= 500000 -#define ahc_timer_init(timer) callout_init(timer, /*mpsafe*/0) -#else -#define ahc_timer_init callout_init -#endif -#define ahc_timer_stop callout_stop - -static __inline void -ahc_timer_reset(ahc_timer_t *timer, u_int usec, ahc_callback_t *func, void *arg) -{ - callout_reset(timer, (usec * hz)/1000000, func, arg); -} - -static __inline void -ahc_scb_timer_reset(struct scb *scb, u_int usec) -{ - untimeout(ahc_timeout, (caddr_t)scb, scb->io_ctx->ccb_h.timeout_ch); - scb->io_ctx->ccb_h.timeout_ch = - timeout(ahc_timeout, scb, (usec * hz)/1000000); -} +#define AIC_CORE_INCLUDE <dev/aic7xxx/aic7xxx.h> +#define AIC_LIB_PREFIX ahc +#define AIC_CONST_PREFIX AHC +#include <dev/aic7xxx/aic_osm_lib.h> /*************************** Device Access ************************************/ #define ahc_inb(ahc, port) \ @@ -347,204 +254,13 @@ static __inline void ahc_list_unlock(unsigned long *flags) { } -/****************************** OS Primitives *********************************/ -#define ahc_delay DELAY - -/************************** Transaction Operations ****************************/ -static __inline void ahc_set_transaction_status(struct scb *, uint32_t); -static __inline void ahc_set_scsi_status(struct scb *, uint32_t); -static __inline uint32_t ahc_get_transaction_status(struct scb *); -static __inline uint32_t ahc_get_scsi_status(struct scb *); -static __inline void ahc_set_transaction_tag(struct scb *, int, u_int); -static __inline u_long ahc_get_transfer_length(struct scb *); -static __inline int ahc_get_transfer_dir(struct scb *); -static __inline void ahc_set_residual(struct scb *, u_long); -static __inline void ahc_set_sense_residual(struct scb *, u_long); -static __inline u_long ahc_get_residual(struct scb *); -static __inline int ahc_perform_autosense(struct scb *); -static __inline uint32_t ahc_get_sense_bufsize(struct ahc_softc*, struct scb*); -static __inline void ahc_freeze_ccb(union ccb *ccb); -static __inline void ahc_freeze_scb(struct scb *scb); -static __inline void ahc_platform_freeze_devq(struct ahc_softc *, struct scb *); -static __inline int ahc_platform_abort_scbs(struct ahc_softc *ahc, int target, - char channel, int lun, u_int tag, - role_t role, uint32_t status); - -static __inline -void ahc_set_transaction_status(struct scb *scb, uint32_t status) -{ - scb->io_ctx->ccb_h.status &= ~CAM_STATUS_MASK; - scb->io_ctx->ccb_h.status |= status; -} - -static __inline -void ahc_set_scsi_status(struct scb *scb, uint32_t status) -{ - scb->io_ctx->csio.scsi_status = status; -} - -static __inline -uint32_t ahc_get_transaction_status(struct scb *scb) -{ - return (scb->io_ctx->ccb_h.status & CAM_STATUS_MASK); -} - -static __inline -uint32_t ahc_get_scsi_status(struct scb *scb) -{ - return (scb->io_ctx->csio.scsi_status); -} - -static __inline -void ahc_set_transaction_tag(struct scb *scb, int enabled, u_int type) -{ - scb->io_ctx->csio.tag_action = type; - if (enabled) - scb->io_ctx->ccb_h.flags |= CAM_TAG_ACTION_VALID; - else - scb->io_ctx->ccb_h.flags &= ~CAM_TAG_ACTION_VALID; -} - -static __inline -u_long ahc_get_transfer_length(struct scb *scb) -{ - return (scb->io_ctx->csio.dxfer_len); -} - -static __inline -int ahc_get_transfer_dir(struct scb *scb) -{ - return (scb->io_ctx->ccb_h.flags & CAM_DIR_MASK); -} - -static __inline -void ahc_set_residual(struct scb *scb, u_long resid) -{ - scb->io_ctx->csio.resid = resid; -} - -static __inline -void ahc_set_sense_residual(struct scb *scb, u_long resid) -{ - scb->io_ctx->csio.sense_resid = resid; -} - -static __inline -u_long ahc_get_residual(struct scb *scb) -{ - return (scb->io_ctx->csio.resid); -} - -static __inline -int ahc_perform_autosense(struct scb *scb) -{ - return (!(scb->io_ctx->ccb_h.flags & CAM_DIS_AUTOSENSE)); -} - -static __inline uint32_t -ahc_get_sense_bufsize(struct ahc_softc *ahc, struct scb *scb) -{ - return (sizeof(struct scsi_sense_data)); -} - -static __inline void -ahc_freeze_ccb(union ccb *ccb) -{ - if ((ccb->ccb_h.status & CAM_DEV_QFRZN) == 0) { - ccb->ccb_h.status |= CAM_DEV_QFRZN; - xpt_freeze_devq(ccb->ccb_h.path, /*count*/1); - } -} - -static __inline void -ahc_freeze_scb(struct scb *scb) -{ - ahc_freeze_ccb(scb->io_ctx); -} - -static __inline void -ahc_platform_freeze_devq(struct ahc_softc *ahc, struct scb *scb) -{ - /* Nothing to do here for FreeBSD */ -} - -static __inline int -ahc_platform_abort_scbs(struct ahc_softc *ahc, int target, - char channel, int lun, u_int tag, - role_t role, uint32_t status) -{ - /* Nothing to do here for FreeBSD */ - return (0); -} - -static __inline void -ahc_platform_scb_free(struct ahc_softc *ahc, struct scb *scb) -{ - /* What do we do to generically handle driver resource shortages??? */ - if ((ahc->flags & AHC_RESOURCE_SHORTAGE) != 0 - && scb->io_ctx != NULL - && (scb->io_ctx->ccb_h.status & CAM_RELEASE_SIMQ) == 0) { - scb->io_ctx->ccb_h.status |= CAM_RELEASE_SIMQ; - ahc->flags &= ~AHC_RESOURCE_SHORTAGE; - } - scb->io_ctx = NULL; -} /********************************** PCI ***************************************/ -#ifdef AHC_PCI_CONFIG -static __inline uint32_t ahc_pci_read_config(ahc_dev_softc_t pci, - int reg, int width); -static __inline void ahc_pci_write_config(ahc_dev_softc_t pci, - int reg, uint32_t value, - int width); -static __inline int ahc_get_pci_function(ahc_dev_softc_t); -static __inline int ahc_get_pci_slot(ahc_dev_softc_t); -static __inline int ahc_get_pci_bus(ahc_dev_softc_t); - -int ahc_pci_map_registers(struct ahc_softc *ahc); -int ahc_pci_map_int(struct ahc_softc *ahc); - -static __inline uint32_t -ahc_pci_read_config(ahc_dev_softc_t pci, int reg, int width) -{ - return (pci_read_config(pci, reg, width)); -} +#ifdef AIC_PCI_CONFIG +int ahc_pci_map_registers(struct ahc_softc *ahc); +int ahc_pci_map_int(struct ahc_softc *ahc); +#endif /*AIC_PCI_CONFIG*/ -static __inline void -ahc_pci_write_config(ahc_dev_softc_t pci, int reg, uint32_t value, int width) -{ - pci_write_config(pci, reg, value, width); -} - -static __inline int -ahc_get_pci_function(ahc_dev_softc_t pci) -{ - return (pci_get_function(pci)); -} - -static __inline int -ahc_get_pci_slot(ahc_dev_softc_t pci) -{ - return (pci_get_slot(pci)); -} - -static __inline int -ahc_get_pci_bus(ahc_dev_softc_t pci) -{ - return (pci_get_bus(pci)); -} - -typedef enum -{ - AHC_POWER_STATE_D0, - AHC_POWER_STATE_D1, - AHC_POWER_STATE_D2, - AHC_POWER_STATE_D3 -} ahc_power_state; - -void ahc_power_state_change(struct ahc_softc *ahc, - ahc_power_state new_state); -#endif /******************************** VL/EISA *************************************/ int aic7770_map_registers(struct ahc_softc *ahc, u_int port); int aic7770_map_int(struct ahc_softc *ahc, int irq); diff --git a/sys/dev/aic7xxx/aic7xxx_pci.c b/sys/dev/aic7xxx/aic7xxx_pci.c index 49ba1f2..868b693 100644 --- a/sys/dev/aic7xxx/aic7xxx_pci.c +++ b/sys/dev/aic7xxx/aic7xxx_pci.c @@ -39,25 +39,21 @@ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * - * $Id: //depot/aic7xxx/aic7xxx/aic7xxx_pci.c#72 $ + * $Id: //depot/aic7xxx/aic7xxx/aic7xxx_pci.c#78 $ */ -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - #ifdef __linux__ #include "aic7xxx_osm.h" #include "aic7xxx_inline.h" #include "aic7xxx_93cx6.h" #else +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); #include <dev/aic7xxx/aic7xxx_osm.h> #include <dev/aic7xxx/aic7xxx_inline.h> #include <dev/aic7xxx/aic7xxx_93cx6.h> #endif -#define AHC_PCI_IOADDR PCIR_BAR(0) /* I/O Address */ -#define AHC_PCI_MEMADDR PCIR_BAR(1) /* Mem I/O Address */ - static __inline uint64_t ahc_compose_id(u_int device, u_int vendor, u_int subdevice, u_int subvendor) { @@ -134,6 +130,7 @@ ahc_compose_id(u_int device, u_int vendor, u_int subdevice, u_int subvendor) #define ID_AHA_29160C 0x0080900562209005ull #define ID_AHA_29160B 0x00809005E2209005ull #define ID_AHA_19160B 0x0081900562A19005ull +#define ID_AHA_2915_30LP 0x0082900502109005ull #define ID_AIC7896 0x005F9005FFFF9005ull #define ID_AIC7896_ARO 0x00539005FFFF9005ull @@ -471,6 +468,12 @@ struct ahc_pci_identity ahc_pci_ident_table [] = "Adaptec aic7892 Ultra160 SCSI adapter (ARO)", ahc_aic7892_setup }, + { + ID_AHA_2915_30LP, + ID_ALL_MASK, + "Adaptec 2915/30LP Ultra160 SCSI adapter", + ahc_aic7892_setup + }, /* aic7895 based controllers */ { ID_AHA_2940U_DUAL, @@ -739,7 +742,7 @@ ahc_9005_subdevinfo_valid(uint16_t device, uint16_t vendor, } struct ahc_pci_identity * -ahc_find_pci_device(ahc_dev_softc_t pci) +ahc_find_pci_device(aic_dev_softc_t pci) { uint64_t full_id; uint16_t device; @@ -749,10 +752,10 @@ ahc_find_pci_device(ahc_dev_softc_t pci) struct ahc_pci_identity *entry; u_int i; - vendor = ahc_pci_read_config(pci, PCIR_DEVVENDOR, /*bytes*/2); - device = ahc_pci_read_config(pci, PCIR_DEVICE, /*bytes*/2); - subvendor = ahc_pci_read_config(pci, PCIR_SUBVEND_0, /*bytes*/2); - subdevice = ahc_pci_read_config(pci, PCIR_SUBDEV_0, /*bytes*/2); + vendor = aic_pci_read_config(pci, PCIR_DEVVENDOR, /*bytes*/2); + device = aic_pci_read_config(pci, PCIR_DEVICE, /*bytes*/2); + subvendor = aic_pci_read_config(pci, PCIR_SUBVEND_0, /*bytes*/2); + subdevice = aic_pci_read_config(pci, PCIR_SUBDEV_0, /*bytes*/2); full_id = ahc_compose_id(device, vendor, subdevice, subvendor); /* @@ -762,7 +765,7 @@ ahc_find_pci_device(ahc_dev_softc_t pci) * to sanity check it prior to accepting the subdevice * ID as valid. */ - if (ahc_get_pci_function(pci) > 0 + if (aic_get_pci_function(pci) > 0 && ahc_9005_subdevinfo_valid(vendor, device, subvendor, subdevice) && SUBID_9005_MFUNCENB(subdevice) == 0) return (NULL); @@ -799,7 +802,7 @@ ahc_pci_config(struct ahc_softc *ahc, struct ahc_pci_identity *entry) ahc->chip |= AHC_PCI; ahc->description = entry->name; - ahc_power_state_change(ahc, AHC_POWER_STATE_D0); + aic_power_state_change(ahc, AIC_POWER_STATE_D0); error = ahc_pci_map_registers(ahc); if (error != 0) @@ -813,7 +816,7 @@ ahc_pci_config(struct ahc_softc *ahc, struct ahc_pci_identity *entry) */ ahc_intr_enable(ahc, FALSE); - devconfig = ahc_pci_read_config(ahc->dev_softc, DEVCONFIG, /*bytes*/4); + devconfig = aic_pci_read_config(ahc->dev_softc, DEVCONFIG, /*bytes*/4); /* * If we need to support high memory, enable dual @@ -832,13 +835,13 @@ ahc_pci_config(struct ahc_softc *ahc, struct ahc_pci_identity *entry) /* Ensure that pci error generation, a test feature, is disabled. */ devconfig |= PCIERRGENDIS; - ahc_pci_write_config(ahc->dev_softc, DEVCONFIG, devconfig, /*bytes*/4); + aic_pci_write_config(ahc->dev_softc, DEVCONFIG, devconfig, /*bytes*/4); /* Ensure busmastering is enabled */ - command = ahc_pci_read_config(ahc->dev_softc, PCIR_COMMAND, /*bytes*/2); + command = aic_pci_read_config(ahc->dev_softc, PCIR_COMMAND, /*bytes*/2); command |= PCIM_CMD_BUSMASTEREN; - ahc_pci_write_config(ahc->dev_softc, PCIR_COMMAND, command, /*bytes*/2); + aic_pci_write_config(ahc->dev_softc, PCIR_COMMAND, command, /*bytes*/2); /* On all PCI adapters, we allow SCB paging */ ahc->flags |= AHC_PAGESCBS; @@ -921,14 +924,14 @@ ahc_pci_config(struct ahc_softc *ahc, struct ahc_pci_identity *entry) ahc_outb(ahc, DSCOMMAND0, dscommand0); ahc->pci_cachesize = - ahc_pci_read_config(ahc->dev_softc, CSIZE_LATTIME, + aic_pci_read_config(ahc->dev_softc, CSIZE_LATTIME, /*bytes*/1) & CACHESIZE; ahc->pci_cachesize *= 4; if ((ahc->bugs & AHC_PCI_2_1_RETRY_BUG) != 0 && ahc->pci_cachesize == 4) { - ahc_pci_write_config(ahc->dev_softc, CSIZE_LATTIME, + aic_pci_write_config(ahc->dev_softc, CSIZE_LATTIME, 0, /*bytes*/1); ahc->pci_cachesize = 0; } @@ -940,7 +943,7 @@ ahc_pci_config(struct ahc_softc *ahc, struct ahc_pci_identity *entry) if ((ahc->features & AHC_ULTRA) != 0) { uint32_t devconfig; - devconfig = ahc_pci_read_config(ahc->dev_softc, + devconfig = aic_pci_read_config(ahc->dev_softc, DEVCONFIG, /*bytes*/4); if ((devconfig & REXTVALID) == 0) ahc->features &= ~AHC_ULTRA; @@ -1006,11 +1009,11 @@ ahc_pci_config(struct ahc_softc *ahc, struct ahc_pci_identity *entry) * that occur during runtime and resume events. */ ahc->bus_softc.pci_softc.devconfig = - ahc_pci_read_config(ahc->dev_softc, DEVCONFIG, /*bytes*/4); + aic_pci_read_config(ahc->dev_softc, DEVCONFIG, /*bytes*/4); ahc->bus_softc.pci_softc.command = - ahc_pci_read_config(ahc->dev_softc, PCIR_COMMAND, /*bytes*/1); + aic_pci_read_config(ahc->dev_softc, PCIR_COMMAND, /*bytes*/1); ahc->bus_softc.pci_softc.csize_lattime = - ahc_pci_read_config(ahc->dev_softc, CSIZE_LATTIME, /*bytes*/1); + aic_pci_read_config(ahc->dev_softc, CSIZE_LATTIME, /*bytes*/1); ahc->bus_softc.pci_softc.dscommand0 = ahc_inb(ahc, DSCOMMAND0); ahc->bus_softc.pci_softc.dspcistatus = ahc_inb(ahc, DSPCISTATUS); if ((ahc->features & AHC_DT) != 0) { @@ -1064,7 +1067,7 @@ ahc_ext_scbram_present(struct ahc_softc *ahc) uint32_t devconfig; chip = ahc->chip & AHC_CHIPID_MASK; - devconfig = ahc_pci_read_config(ahc->dev_softc, + devconfig = aic_pci_read_config(ahc->dev_softc, DEVCONFIG, /*bytes*/4); single_user = (devconfig & MPORTMODE) != 0; @@ -1102,13 +1105,13 @@ ahc_scbram_config(struct ahc_softc *ahc, int enable, int pcheck, * Set the SCB Base addr (highest address bit) * depending on which channel we are. */ - ahc_outb(ahc, SCBBADDR, ahc_get_pci_function(ahc->dev_softc)); + ahc_outb(ahc, SCBBADDR, aic_get_pci_function(ahc->dev_softc)); } ahc->flags &= ~AHC_LSCBS_ENABLED; if (large) ahc->flags |= AHC_LSCBS_ENABLED; - devconfig = ahc_pci_read_config(ahc->dev_softc, DEVCONFIG, /*bytes*/4); + devconfig = aic_pci_read_config(ahc->dev_softc, DEVCONFIG, /*bytes*/4); if ((ahc->features & AHC_ULTRA2) != 0) { u_int dscommand0; @@ -1141,7 +1144,7 @@ ahc_scbram_config(struct ahc_softc *ahc, int enable, int pcheck, else devconfig &= ~EXTSCBPEN; - ahc_pci_write_config(ahc->dev_softc, DEVCONFIG, devconfig, /*bytes*/4); + aic_pci_write_config(ahc->dev_softc, DEVCONFIG, devconfig, /*bytes*/4); } /* @@ -1264,8 +1267,8 @@ ahc_pci_test_register_access(struct ahc_softc *ahc) * Enable PCI error interrupt status, but suppress NMIs * generated by SERR raised due to target aborts. */ - cmd = ahc_pci_read_config(ahc->dev_softc, PCIR_COMMAND, /*bytes*/2); - ahc_pci_write_config(ahc->dev_softc, PCIR_COMMAND, + cmd = aic_pci_read_config(ahc->dev_softc, PCIR_COMMAND, /*bytes*/2); + aic_pci_write_config(ahc->dev_softc, PCIR_COMMAND, cmd & ~PCIM_CMD_SERRESPEN, /*bytes*/2); /* @@ -1277,9 +1280,19 @@ ahc_pci_test_register_access(struct ahc_softc *ahc) * use for this test. */ hcntrl = ahc_inb(ahc, HCNTRL); + if (hcntrl == 0xFF) goto fail; + if ((hcntrl & CHIPRST) != 0) { + /* + * The chip has not been initialized since + * PCI/EISA/VLB bus reset. Don't trust + * "left over BIOS data". + */ + ahc->flags |= AHC_NO_BIOS_INIT; + } + /* * Next create a situation where write combining * or read prefetching could be initiated by the @@ -1294,9 +1307,9 @@ ahc_pci_test_register_access(struct ahc_softc *ahc) ; /* Clear any PCI errors that occurred before our driver attached. */ - status1 = ahc_pci_read_config(ahc->dev_softc, + status1 = aic_pci_read_config(ahc->dev_softc, PCIR_STATUS + 1, /*bytes*/1); - ahc_pci_write_config(ahc->dev_softc, PCIR_STATUS + 1, + aic_pci_write_config(ahc->dev_softc, PCIR_STATUS + 1, status1, /*bytes*/1); ahc_outb(ahc, CLRINT, CLRPARERR); @@ -1306,7 +1319,7 @@ ahc_pci_test_register_access(struct ahc_softc *ahc) if (ahc_inl(ahc, SCB_BASE) != 0x5aa555aa) goto fail; - status1 = ahc_pci_read_config(ahc->dev_softc, + status1 = aic_pci_read_config(ahc->dev_softc, PCIR_STATUS + 1, /*bytes*/1); if ((status1 & STA) != 0) goto fail; @@ -1315,13 +1328,13 @@ ahc_pci_test_register_access(struct ahc_softc *ahc) fail: /* Silently clear any latched errors. */ - status1 = ahc_pci_read_config(ahc->dev_softc, + status1 = aic_pci_read_config(ahc->dev_softc, PCIR_STATUS + 1, /*bytes*/1); - ahc_pci_write_config(ahc->dev_softc, PCIR_STATUS + 1, + aic_pci_write_config(ahc->dev_softc, PCIR_STATUS + 1, status1, /*bytes*/1); ahc_outb(ahc, CLRINT, CLRPARERR); ahc_outb(ahc, SEQCTL, PERRORDIS|FAILDIS); - ahc_pci_write_config(ahc->dev_softc, PCIR_COMMAND, cmd, /*bytes*/2); + aic_pci_write_config(ahc->dev_softc, PCIR_COMMAND, cmd, /*bytes*/2); return (error); } @@ -1391,6 +1404,10 @@ check_extport(struct ahc_softc *ahc, u_int *sxfrctl1) sd.sd_chip = C56_66; } ahc_release_seeprom(&sd); + + /* Remember the SEEPROM type for later */ + if (sd.sd_chip == C56_66) + ahc->flags |= AHC_LARGE_SEEPROM; } if (!have_seeprom) { @@ -1576,12 +1593,12 @@ ahc_parse_pci_eeprom(struct ahc_softc *ahc, struct seeprom_config *sc) uint32_t devconfig; /* Honor the STPWLEVEL settings */ - devconfig = ahc_pci_read_config(ahc->dev_softc, + devconfig = aic_pci_read_config(ahc->dev_softc, DEVCONFIG, /*bytes*/4); devconfig &= ~STPWLEVEL; if ((sc->bios_control & CFSTPWLEVEL) != 0) devconfig |= STPWLEVEL; - ahc_pci_write_config(ahc->dev_softc, DEVCONFIG, + aic_pci_write_config(ahc->dev_softc, DEVCONFIG, devconfig, /*bytes*/4); } /* Set SCSICONF info */ @@ -1894,10 +1911,10 @@ aic785X_cable_detect(struct ahc_softc *ahc, int *internal50_present, ahc_outb(ahc, SPIOCAP, spiocap); ahc_outb(ahc, BRDCTL, BRDRW|BRDCS); ahc_flush_device_writes(ahc); - ahc_delay(500); + aic_delay(500); ahc_outb(ahc, BRDCTL, 0); ahc_flush_device_writes(ahc); - ahc_delay(500); + aic_delay(500); brdctl = ahc_inb(ahc, BRDCTL); *internal50_present = (brdctl & BRDDAT5) ? 0 : 1; *externalcable_present = (brdctl & BRDDAT6) ? 0 : 1; @@ -1923,7 +1940,7 @@ ahc_acquire_seeprom(struct ahc_softc *ahc, struct seeprom_descriptor *sd) SEEPROM_OUTB(sd, sd->sd_MS); wait = 1000; /* 1 second timeout in msec */ while (--wait && ((SEEPROM_STATUS_INB(sd) & sd->sd_RDY) == 0)) { - ahc_delay(1000); /* delay 1 msec */ + aic_delay(1000); /* delay 1 msec */ } if ((SEEPROM_STATUS_INB(sd) & sd->sd_RDY) == 0) { SEEPROM_OUTB(sd, 0); @@ -2003,7 +2020,7 @@ ahc_pci_intr(struct ahc_softc *ahc) if ((error & PCIERRSTAT) == 0) return; - status1 = ahc_pci_read_config(ahc->dev_softc, + status1 = aic_pci_read_config(ahc->dev_softc, PCIR_STATUS + 1, /*bytes*/1); printf("%s: PCI error Interrupt at seqaddr = 0x%x\n", @@ -2033,7 +2050,7 @@ ahc_pci_intr(struct ahc_softc *ahc) } /* Clear latched errors. */ - ahc_pci_write_config(ahc->dev_softc, PCIR_STATUS + 1, + aic_pci_write_config(ahc->dev_softc, PCIR_STATUS + 1, status1, /*bytes*/1); if ((status1 & (DPE|SSE|RMA|RTA|STA|DPR)) == 0) { @@ -2094,7 +2111,7 @@ static int ahc_pci_resume(struct ahc_softc *ahc) { - ahc_power_state_change(ahc, AHC_POWER_STATE_D0); + aic_power_state_change(ahc, AIC_POWER_STATE_D0); /* * We assume that the OS has restored our register @@ -2102,11 +2119,11 @@ ahc_pci_resume(struct ahc_softc *ahc) * that the OS doesn't know about and rely on our chip * reset handler to handle the rest. */ - ahc_pci_write_config(ahc->dev_softc, DEVCONFIG, /*bytes*/4, + aic_pci_write_config(ahc->dev_softc, DEVCONFIG, /*bytes*/4, ahc->bus_softc.pci_softc.devconfig); - ahc_pci_write_config(ahc->dev_softc, PCIR_COMMAND, /*bytes*/1, + aic_pci_write_config(ahc->dev_softc, PCIR_COMMAND, /*bytes*/1, ahc->bus_softc.pci_softc.command); - ahc_pci_write_config(ahc->dev_softc, CSIZE_LATTIME, /*bytes*/1, + aic_pci_write_config(ahc->dev_softc, CSIZE_LATTIME, /*bytes*/1, ahc->bus_softc.pci_softc.csize_lattime); if ((ahc->flags & AHC_HAS_TERM_LOGIC) != 0) { struct seeprom_descriptor sd; @@ -2129,7 +2146,7 @@ ahc_pci_resume(struct ahc_softc *ahc) static int ahc_aic785X_setup(struct ahc_softc *ahc) { - ahc_dev_softc_t pci; + aic_dev_softc_t pci; uint8_t rev; pci = ahc->dev_softc; @@ -2137,7 +2154,7 @@ ahc_aic785X_setup(struct ahc_softc *ahc) ahc->chip = AHC_AIC7850; ahc->features = AHC_AIC7850_FE; ahc->bugs |= AHC_TMODE_WIDEODD_BUG|AHC_CACHETHEN_BUG|AHC_PCI_MWI_BUG; - rev = ahc_pci_read_config(pci, PCIR_REVID, /*bytes*/1); + rev = aic_pci_read_config(pci, PCIR_REVID, /*bytes*/1); if (rev >= 1) ahc->bugs |= AHC_PCI_2_1_RETRY_BUG; ahc->instruction_ram_size = 512; @@ -2147,7 +2164,7 @@ ahc_aic785X_setup(struct ahc_softc *ahc) static int ahc_aic7860_setup(struct ahc_softc *ahc) { - ahc_dev_softc_t pci; + aic_dev_softc_t pci; uint8_t rev; pci = ahc->dev_softc; @@ -2155,7 +2172,7 @@ ahc_aic7860_setup(struct ahc_softc *ahc) ahc->chip = AHC_AIC7860; ahc->features = AHC_AIC7860_FE; ahc->bugs |= AHC_TMODE_WIDEODD_BUG|AHC_CACHETHEN_BUG|AHC_PCI_MWI_BUG; - rev = ahc_pci_read_config(pci, PCIR_REVID, /*bytes*/1); + rev = aic_pci_read_config(pci, PCIR_REVID, /*bytes*/1); if (rev >= 1) ahc->bugs |= AHC_PCI_2_1_RETRY_BUG; ahc->instruction_ram_size = 512; @@ -2222,7 +2239,7 @@ ahc_aha494X_setup(struct ahc_softc *ahc) static int ahc_aic7880_setup(struct ahc_softc *ahc) { - ahc_dev_softc_t pci; + aic_dev_softc_t pci; uint8_t rev; pci = ahc->dev_softc; @@ -2230,7 +2247,7 @@ ahc_aic7880_setup(struct ahc_softc *ahc) ahc->chip = AHC_AIC7880; ahc->features = AHC_AIC7880_FE; ahc->bugs |= AHC_TMODE_WIDEODD_BUG; - rev = ahc_pci_read_config(pci, PCIR_REVID, /*bytes*/1); + rev = aic_pci_read_config(pci, PCIR_REVID, /*bytes*/1); if (rev >= 1) { ahc->bugs |= AHC_PCI_2_1_RETRY_BUG; } else { @@ -2273,7 +2290,7 @@ ahc_aha398XU_setup(struct ahc_softc *ahc) static int ahc_aic7890_setup(struct ahc_softc *ahc) { - ahc_dev_softc_t pci; + aic_dev_softc_t pci; uint8_t rev; pci = ahc->dev_softc; @@ -2281,7 +2298,7 @@ ahc_aic7890_setup(struct ahc_softc *ahc) ahc->chip = AHC_AIC7890; ahc->features = AHC_AIC7890_FE; ahc->flags |= AHC_NEWEEPROM_FMT; - rev = ahc_pci_read_config(pci, PCIR_REVID, /*bytes*/1); + rev = aic_pci_read_config(pci, PCIR_REVID, /*bytes*/1); if (rev == 0) ahc->bugs |= AHC_AUTOFLUSH_BUG|AHC_CACHETHEN_BUG; ahc->instruction_ram_size = 768; @@ -2304,15 +2321,15 @@ ahc_aic7892_setup(struct ahc_softc *ahc) static int ahc_aic7895_setup(struct ahc_softc *ahc) { - ahc_dev_softc_t pci; + aic_dev_softc_t pci; uint8_t rev; pci = ahc->dev_softc; - ahc->channel = ahc_get_pci_function(pci) == 1 ? 'B' : 'A'; + ahc->channel = aic_get_pci_function(pci) == 1 ? 'B' : 'A'; /* * The 'C' revision of the aic7895 has a few additional features. */ - rev = ahc_pci_read_config(pci, PCIR_REVID, /*bytes*/1); + rev = aic_pci_read_config(pci, PCIR_REVID, /*bytes*/1); if (rev >= 4) { ahc->chip = AHC_AIC7895C; ahc->features = AHC_AIC7895C_FE; @@ -2328,9 +2345,9 @@ ahc_aic7895_setup(struct ahc_softc *ahc) * we have. Disabling MWI reduces performance, so * turn it on again. */ - command = ahc_pci_read_config(pci, PCIR_COMMAND, /*bytes*/1); + command = aic_pci_read_config(pci, PCIR_COMMAND, /*bytes*/1); command |= PCIM_CMD_MWRICEN; - ahc_pci_write_config(pci, PCIR_COMMAND, command, /*bytes*/1); + aic_pci_write_config(pci, PCIR_COMMAND, command, /*bytes*/1); ahc->bugs |= AHC_PCI_MWI_BUG; } /* @@ -2347,10 +2364,10 @@ ahc_aic7895_setup(struct ahc_softc *ahc) * Cachesize must also be zero due to stray DAC * problem when sitting behind some bridges. */ - ahc_pci_write_config(pci, CSIZE_LATTIME, 0, /*bytes*/1); - devconfig = ahc_pci_read_config(pci, DEVCONFIG, /*bytes*/1); + aic_pci_write_config(pci, CSIZE_LATTIME, 0, /*bytes*/1); + devconfig = aic_pci_read_config(pci, DEVCONFIG, /*bytes*/1); devconfig |= MRDCEN; - ahc_pci_write_config(pci, DEVCONFIG, devconfig, /*bytes*/1); + aic_pci_write_config(pci, DEVCONFIG, devconfig, /*bytes*/1); #endif ahc->flags |= AHC_NEWEEPROM_FMT; ahc->instruction_ram_size = 512; @@ -2360,10 +2377,10 @@ ahc_aic7895_setup(struct ahc_softc *ahc) static int ahc_aic7896_setup(struct ahc_softc *ahc) { - ahc_dev_softc_t pci; + aic_dev_softc_t pci; pci = ahc->dev_softc; - ahc->channel = ahc_get_pci_function(pci) == 1 ? 'B' : 'A'; + ahc->channel = aic_get_pci_function(pci) == 1 ? 'B' : 'A'; ahc->chip = AHC_AIC7896; ahc->features = AHC_AIC7896_FE; ahc->flags |= AHC_NEWEEPROM_FMT; @@ -2375,10 +2392,10 @@ ahc_aic7896_setup(struct ahc_softc *ahc) static int ahc_aic7899_setup(struct ahc_softc *ahc) { - ahc_dev_softc_t pci; + aic_dev_softc_t pci; pci = ahc->dev_softc; - ahc->channel = ahc_get_pci_function(pci) == 1 ? 'B' : 'A'; + ahc->channel = aic_get_pci_function(pci) == 1 ? 'B' : 'A'; ahc->chip = AHC_AIC7899; ahc->features = AHC_AIC7899_FE; ahc->flags |= AHC_NEWEEPROM_FMT; @@ -2409,10 +2426,10 @@ ahc_raid_setup(struct ahc_softc *ahc) static int ahc_aha394XX_setup(struct ahc_softc *ahc) { - ahc_dev_softc_t pci; + aic_dev_softc_t pci; pci = ahc->dev_softc; - switch (ahc_get_pci_slot(pci)) { + switch (aic_get_pci_slot(pci)) { case AHC_394X_SLOT_CHANNEL_A: ahc->channel = 'A'; break; @@ -2422,7 +2439,7 @@ ahc_aha394XX_setup(struct ahc_softc *ahc) default: printf("adapter at unexpected slot %d\n" "unable to map to a channel\n", - ahc_get_pci_slot(pci)); + aic_get_pci_slot(pci)); ahc->channel = 'A'; } return (0); @@ -2431,10 +2448,10 @@ ahc_aha394XX_setup(struct ahc_softc *ahc) static int ahc_aha398XX_setup(struct ahc_softc *ahc) { - ahc_dev_softc_t pci; + aic_dev_softc_t pci; pci = ahc->dev_softc; - switch (ahc_get_pci_slot(pci)) { + switch (aic_get_pci_slot(pci)) { case AHC_398X_SLOT_CHANNEL_A: ahc->channel = 'A'; break; @@ -2447,7 +2464,7 @@ ahc_aha398XX_setup(struct ahc_softc *ahc) default: printf("adapter at unexpected slot %d\n" "unable to map to a channel\n", - ahc_get_pci_slot(pci)); + aic_get_pci_slot(pci)); ahc->channel = 'A'; break; } @@ -2458,10 +2475,10 @@ ahc_aha398XX_setup(struct ahc_softc *ahc) static int ahc_aha494XX_setup(struct ahc_softc *ahc) { - ahc_dev_softc_t pci; + aic_dev_softc_t pci; pci = ahc->dev_softc; - switch (ahc_get_pci_slot(pci)) { + switch (aic_get_pci_slot(pci)) { case AHC_494X_SLOT_CHANNEL_A: ahc->channel = 'A'; break; @@ -2477,7 +2494,7 @@ ahc_aha494XX_setup(struct ahc_softc *ahc) default: printf("adapter at unexpected slot %d\n" "unable to map to a channel\n", - ahc_get_pci_slot(pci)); + aic_get_pci_slot(pci)); ahc->channel = 'A'; } ahc->flags |= AHC_LARGE_SEEPROM; diff --git a/sys/dev/aic7xxx/aic_osm_lib.c b/sys/dev/aic7xxx/aic_osm_lib.c new file mode 100644 index 0000000..409cfce --- /dev/null +++ b/sys/dev/aic7xxx/aic_osm_lib.c @@ -0,0 +1,169 @@ +/* + * FreeBSD OSM Library for the aic7xxx aic79xx based Adaptec SCSI controllers + * + * Copyright (c) 1994-2002 Justin T. Gibbs. + * Copyright (c) 2001-2003 Adaptec Inc. + * 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, + * without modification. + * 2. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU Public License ("GPL"). + * + * 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. + * + * $Id: //depot/aic7xxx/freebsd/dev/aic7xxx/aic_osm_lib.c#4 $ + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +static void aic_recovery_thread(void *arg); + +void +aic_set_recoveryscb(struct aic_softc *aic, struct scb *scb) +{ + + if ((scb->flags & SCB_RECOVERY_SCB) == 0) { + struct scb *list_scb; + + scb->flags |= SCB_RECOVERY_SCB; + + /* + * Take all queued, but not sent SCBs out of the equation. + * Also ensure that no new CCBs are queued to us while we + * try to fix this problem. + */ + if ((scb->io_ctx->ccb_h.status & CAM_RELEASE_SIMQ) == 0) { + xpt_freeze_simq(SCB_GET_SIM(aic, scb), /*count*/1); + scb->io_ctx->ccb_h.status |= CAM_RELEASE_SIMQ; + } + + /* + * Go through all of our pending SCBs and remove + * any scheduled timeouts for them. We will reschedule + * them after we've successfully fixed this problem. + */ + LIST_FOREACH(list_scb, &aic->pending_scbs, pending_links) { + union ccb *ccb; + + ccb = list_scb->io_ctx; + untimeout(aic_platform_timeout, list_scb, + ccb->ccb_h.timeout_ch); + } + } +} + +void +aic_platform_timeout(void *arg) +{ + struct scb *scb; + u_long s; + + scb = (struct scb *)arg; + aic_lock(scb->aic_softc, &s); + aic_timeout(scb); + aic_unlock(scb->aic_softc, &s); +} + +int +aic_spawn_recovery_thread(struct aic_softc *aic) +{ + int error; + + error = aic_kthread_create(aic_recovery_thread, aic, + &aic->platform_data->recovery_thread, + /*flags*/0, /*altstack*/0, "aic_recovery%d", + aic->unit); + return (error); +} + +/* + * Lock is not held on entry. + */ +void +aic_terminate_recovery_thread(struct aic_softc *aic) +{ + u_long s; + + aic_lock(aic, &s); + if (aic->platform_data->recovery_thread == NULL) { + aic_unlock(aic, &s); + return; + } + aic->flags |= AIC_SHUTDOWN_RECOVERY; + wakeup(aic); + /* + * Sleep on a slightly different location + * for this interlock just for added safety. + */ + tsleep(aic->platform_data, PUSER, "thtrm", 0); + aic_unlock(aic, &s); +} + +void +aic_calc_geometry(struct ccb_calc_geometry *ccg, int extended) +{ +#if __FreeBSD_version >= 500000 + cam_calc_geometry(ccg, extended); +#else + uint32_t size_mb; + uint32_t secs_per_cylinder; + + size_mb = ccg->volume_size / ((1024L * 1024L) / ccg->block_size); + if (size_mb > 1024 && extended) { + ccg->heads = 255; + ccg->secs_per_track = 63; + } else { + ccg->heads = 64; + ccg->secs_per_track = 32; + } + secs_per_cylinder = ccg->heads * ccg->secs_per_track; + ccg->cylinders = ccg->volume_size / secs_per_cylinder; + ccg->ccb_h.status = CAM_REQ_CMP; +#endif +} + +static void +aic_recovery_thread(void *arg) +{ + struct aic_softc *aic; + u_long s; + +#if __FreeBSD_version >= 500000 + mtx_lock(&Giant); +#endif + aic = (struct aic_softc *)arg; + aic_lock(aic, &s); + while ((aic->flags & AIC_SHUTDOWN_RECOVERY) == 0) { + + while (LIST_EMPTY(&aic->timedout_scbs) != 0) + tsleep(aic, PUSER, "idle", 0); + aic_unlock(aic, &s); + aic_recover_commands(aic); + aic_lock(aic, &s); + } + wakeup(aic->platform_data); + aic_unlock(aic, &s); +#if __FreeBSD_version >= 500000 + mtx_unlock(&Giant); +#endif + kthread_exit(0); +} diff --git a/sys/dev/aic7xxx/aic_osm_lib.h b/sys/dev/aic7xxx/aic_osm_lib.h new file mode 100644 index 0000000..b12ac35 --- /dev/null +++ b/sys/dev/aic7xxx/aic_osm_lib.h @@ -0,0 +1,426 @@ +/* + * FreeBSD platform specific, shared driver option settings, data structures, + * function declarations and includes. + * + * Copyright (c) 1994-2001 Justin T. Gibbs. + * Copyright (c) 2001-2003 Adaptec Inc. + * 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, + * without modification. + * 2. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU Public License ("GPL"). + * + * 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. + * + * $Id: //depot/aic7xxx/freebsd/dev/aic7xxx/aic_osm_lib.h#4 $ + * + * $FreeBSD$ + */ + +/******************************** OS Includes *********************************/ +#if __FreeBSD_version >= 500000 +#include <sys/mutex.h> +#endif + +/*************************** Library Symbol Mapping ***************************/ +#define AIC_LIB_ENTRY_CONCAT(x, prefix) prefix ## x +#define AIC_LIB_ENTRY_EXPAND(x, prefix) AIC_LIB_ENTRY_CONCAT(x, prefix) +#define AIC_LIB_ENTRY(x) AIC_LIB_ENTRY_EXPAND(x, AIC_LIB_PREFIX) +#define AIC_CONST_ENTRY(x) AIC_LIB_ENTRY_EXPAND(x,AIC_CONST_PREFIX) + +#define aic_softc AIC_LIB_ENTRY(_softc) +#define aic_tailq AIC_LIB_ENTRY(_tailq) +#define aic_transinfo AIC_LIB_ENTRY(_transinfo) +#define aic_platform_data AIC_LIB_ENTRY(_platform_data) +#define aic_devinfo AIC_LIB_ENTRY(_devinfo) +#define aic_lock AIC_LIB_ENTRY(_lock) +#define aic_unlock AIC_LIB_ENTRY(_unlock) +#define aic_callback_t AIC_LIB_ENTRY(_callback_t) +#define aic_platform_freeze_devq AIC_LIB_ENTRY(_platform_freeze_devq) +#define aic_platform_abort_scbs AIC_LIB_ENTRY(_platform_abort_scbs) +#define aic_platform_timeout AIC_LIB_ENTRY(_platform_timeout) +#define aic_timeout AIC_LIB_ENTRY(_timeout) +#define aic_set_recoveryscb AIC_LIB_ENTRY(_set_recoveryscb) +#define aic_spawn_recovery_thread AIC_LIB_ENTRY(_spawn_recovery_thread) +#define aic_wakeup_recovery_thread AIC_LIB_ENTRY(_wakeup_recovery_thread) +#define aic_terminate_recovery_thread \ + AIC_LIB_ENTRY(_terminate_recovery_thread) +#define aic_recovery_thread AIC_LIB_ENTRY(_recovery_thread) +#define aic_recover_commands AIC_LIB_ENTRY(_recover_commands) +#define aic_calc_geometry AIC_LIB_ENTRY(_calc_geometry) + +#define AIC_RESOURCE_SHORTAGE AIC_CONST_ENTRY(_RESOURCE_SHORTAGE) +#define AIC_SHUTDOWN_RECOVERY AIC_CONST_ENTRY(_SHUTDOWN_RECOVERY) + +/********************************* Byte Order *********************************/ +#if __FreeBSD_version >= 500000 +#define aic_htobe16(x) htobe16(x) +#define aic_htobe32(x) htobe32(x) +#define aic_htobe64(x) htobe64(x) +#define aic_htole16(x) htole16(x) +#define aic_htole32(x) htole32(x) +#define aic_htole64(x) htole64(x) + +#define aic_be16toh(x) be16toh(x) +#define aic_be32toh(x) be32toh(x) +#define aic_be64toh(x) be64toh(x) +#define aic_le16toh(x) le16toh(x) +#define aic_le32toh(x) le32toh(x) +#define aic_le64toh(x) le64toh(x) +#else +#define aic_htobe16(x) (x) +#define aic_htobe32(x) (x) +#define aic_htobe64(x) (x) +#define aic_htole16(x) (x) +#define aic_htole32(x) (x) +#define aic_htole64(x) (x) + +#define aic_be16toh(x) (x) +#define aic_be32toh(x) (x) +#define aic_be64toh(x) (x) +#define aic_le16toh(x) (x) +#define aic_le32toh(x) (x) +#define aic_le64toh(x) (x) +#endif + +/************************* Forward Declarations *******************************/ +typedef device_t aic_dev_softc_t; +typedef union ccb *aic_io_ctx_t; +struct aic_softc; +struct scb; + +/*************************** Timer DataStructures *****************************/ +typedef struct callout aic_timer_t; + +/****************************** Error Recovery ********************************/ +void aic_set_recoveryscb(struct aic_softc *aic, struct scb *scb); +timeout_t aic_platform_timeout; +int aic_spawn_recovery_thread(struct aic_softc *aic); +void aic_terminate_recovery_thread(struct aic_softc *aic); + +static __inline void aic_wakeup_recovery_thread(struct aic_softc *aic); + +static __inline void +aic_wakeup_recovery_thread(struct aic_softc *aic) +{ + wakeup(aic); +} + +/****************************** Kernel Threads ********************************/ +#if __FreeBSD_version > 500005 +#define aic_kthread_create(func, farg, proc_ptr, flags, stackpgs, fmtstr, arg) \ + kthread_create(func, farg, proc_ptr, flags, stackpgs, fmtstr, arg) +#else +#define aic_kthread_create(func, farg, proc_ptr, flags, stackpgs, fmtstr, arg) \ + kthread_create(func, farg, proc_ptr, fmtstr, arg) +#endif + +/******************************* Bus Space/DMA ********************************/ + +#if __FreeBSD_version >= 501102 +#define aic_dma_tag_create(aic, parent_tag, alignment, boundary, \ + lowaddr, highaddr, filter, filterarg, \ + maxsize, nsegments, maxsegsz, flags, \ + dma_tagp) \ + bus_dma_tag_create(parent_tag, alignment, boundary, \ + lowaddr, highaddr, filter, filterarg, \ + maxsize, nsegments, maxsegsz, flags, \ + busdma_lock_mutex, &Giant, \ + dma_tagp) +#else +#define aic_dma_tag_create(aic, parent_tag, alignment, boundary, \ + lowaddr, highaddr, filter, filterarg, \ + maxsize, nsegments, maxsegsz, flags, \ + dma_tagp) \ + bus_dma_tag_create(parent_tag, alignment, boundary, \ + lowaddr, highaddr, filter, filterarg, \ + maxsize, nsegments, maxsegsz, flags, \ + dma_tagp) +#endif + +#define aic_dma_tag_destroy(aic, tag) \ + bus_dma_tag_destroy(tag) + +#define aic_dmamem_alloc(aic, dmat, vaddr, flags, mapp) \ + bus_dmamem_alloc(dmat, vaddr, flags, mapp) + +#define aic_dmamem_free(aic, dmat, vaddr, map) \ + bus_dmamem_free(dmat, vaddr, map) + +#define aic_dmamap_create(aic, tag, flags, mapp) \ + bus_dmamap_create(tag, flags, mapp) + +#define aic_dmamap_destroy(aic, tag, map) \ + bus_dmamap_destroy(tag, map) + +#define aic_dmamap_load(aic, dmat, map, addr, buflen, callback, \ + callback_arg, flags) \ + bus_dmamap_load(dmat, map, addr, buflen, callback, callback_arg, flags) + +#define aic_dmamap_unload(aic, tag, map) \ + bus_dmamap_unload(tag, map) + +/* XXX Need to update Bus DMA for partial map syncs */ +#define aic_dmamap_sync(aic, dma_tag, dmamap, offset, len, op) \ + bus_dmamap_sync(dma_tag, dmamap, op) + +/***************************** Core Includes **********************************/ +#include AIC_CORE_INCLUDE + +/***************************** Timer Facilities *******************************/ +#if __FreeBSD_version >= 500000 +#define aic_timer_init(timer) callout_init(timer, /*mpsafe*/0) +#else +#define aic_timer_init callout_init +#endif +#define aic_timer_stop callout_stop + +static __inline void aic_timer_reset(aic_timer_t *, u_int, + aic_callback_t *, void *); +static __inline u_int aic_get_timeout(struct scb *); +static __inline void aic_scb_timer_reset(struct scb *, u_int); + +static __inline void +aic_timer_reset(aic_timer_t *timer, u_int usec, aic_callback_t *func, void *arg) +{ + callout_reset(timer, (usec * hz)/1000000, func, arg); +} + +static __inline u_int +aic_get_timeout(struct scb *scb) +{ + return (scb->io_ctx->ccb_h.timeout); +} + +static __inline void +aic_scb_timer_reset(struct scb *scb, u_int usec) +{ + untimeout(aic_platform_timeout, (caddr_t)scb, + scb->io_ctx->ccb_h.timeout_ch); + scb->io_ctx->ccb_h.timeout_ch = + timeout(aic_platform_timeout, scb, (usec * hz)/1000000); +} + +/************************** Transaction Operations ****************************/ +static __inline void aic_set_transaction_status(struct scb *, uint32_t); +static __inline void aic_set_scsi_status(struct scb *, uint32_t); +static __inline uint32_t aic_get_transaction_status(struct scb *); +static __inline uint32_t aic_get_scsi_status(struct scb *); +static __inline void aic_set_transaction_tag(struct scb *, int, u_int); +static __inline u_long aic_get_transfer_length(struct scb *); +static __inline int aic_get_transfer_dir(struct scb *); +static __inline void aic_set_residual(struct scb *, u_long); +static __inline void aic_set_sense_residual(struct scb *, u_long); +static __inline u_long aic_get_residual(struct scb *); +static __inline int aic_perform_autosense(struct scb *); +static __inline uint32_t aic_get_sense_bufsize(struct aic_softc*, struct scb*); +static __inline void aic_freeze_ccb(union ccb *ccb); +static __inline void aic_freeze_scb(struct scb *scb); +static __inline void aic_platform_freeze_devq(struct aic_softc *, struct scb *); +static __inline int aic_platform_abort_scbs(struct aic_softc *aic, int target, + char channel, int lun, u_int tag, + role_t role, uint32_t status); + +static __inline +void aic_set_transaction_status(struct scb *scb, uint32_t status) +{ + scb->io_ctx->ccb_h.status &= ~CAM_STATUS_MASK; + scb->io_ctx->ccb_h.status |= status; +} + +static __inline +void aic_set_scsi_status(struct scb *scb, uint32_t status) +{ + scb->io_ctx->csio.scsi_status = status; +} + +static __inline +uint32_t aic_get_transaction_status(struct scb *scb) +{ + return (scb->io_ctx->ccb_h.status & CAM_STATUS_MASK); +} + +static __inline +uint32_t aic_get_scsi_status(struct scb *scb) +{ + return (scb->io_ctx->csio.scsi_status); +} + +static __inline +void aic_set_transaction_tag(struct scb *scb, int enabled, u_int type) +{ + scb->io_ctx->csio.tag_action = type; + if (enabled) + scb->io_ctx->ccb_h.flags |= CAM_TAG_ACTION_VALID; + else + scb->io_ctx->ccb_h.flags &= ~CAM_TAG_ACTION_VALID; +} + +static __inline +u_long aic_get_transfer_length(struct scb *scb) +{ + return (scb->io_ctx->csio.dxfer_len); +} + +static __inline +int aic_get_transfer_dir(struct scb *scb) +{ + return (scb->io_ctx->ccb_h.flags & CAM_DIR_MASK); +} + +static __inline +void aic_set_residual(struct scb *scb, u_long resid) +{ + scb->io_ctx->csio.resid = resid; +} + +static __inline +void aic_set_sense_residual(struct scb *scb, u_long resid) +{ + scb->io_ctx->csio.sense_resid = resid; +} + +static __inline +u_long aic_get_residual(struct scb *scb) +{ + return (scb->io_ctx->csio.resid); +} + +static __inline +int aic_perform_autosense(struct scb *scb) +{ + return (!(scb->io_ctx->ccb_h.flags & CAM_DIS_AUTOSENSE)); +} + +static __inline uint32_t +aic_get_sense_bufsize(struct aic_softc *aic, struct scb *scb) +{ + return (sizeof(struct scsi_sense_data)); +} + +static __inline void +aic_freeze_ccb(union ccb *ccb) +{ + if ((ccb->ccb_h.status & CAM_DEV_QFRZN) == 0) { + ccb->ccb_h.status |= CAM_DEV_QFRZN; + xpt_freeze_devq(ccb->ccb_h.path, /*count*/1); + } +} + +static __inline void +aic_freeze_scb(struct scb *scb) +{ + aic_freeze_ccb(scb->io_ctx); +} + +static __inline void +aic_platform_freeze_devq(struct aic_softc *aic, struct scb *scb) +{ + /* Nothing to do here for FreeBSD */ +} + +static __inline int +aic_platform_abort_scbs(struct aic_softc *aic, int target, + char channel, int lun, u_int tag, + role_t role, uint32_t status) +{ + /* Nothing to do here for FreeBSD */ + return (0); +} + +static __inline void +aic_platform_scb_free(struct aic_softc *aic, struct scb *scb) +{ + /* What do we do to generically handle driver resource shortages??? */ + if ((aic->flags & AIC_RESOURCE_SHORTAGE) != 0 + && scb->io_ctx != NULL + && (scb->io_ctx->ccb_h.status & CAM_RELEASE_SIMQ) == 0) { + scb->io_ctx->ccb_h.status |= CAM_RELEASE_SIMQ; + aic->flags &= ~AIC_RESOURCE_SHORTAGE; + } + scb->io_ctx = NULL; +} + +/*************************** CAM CCB Operations *******************************/ +void aic_calc_geometry(struct ccb_calc_geometry *ccg, int extended); + +/****************************** OS Primitives *********************************/ +#define aic_delay DELAY + +/********************************** PCI ***************************************/ +#ifdef AIC_PCI_CONFIG +static __inline uint32_t aic_pci_read_config(aic_dev_softc_t pci, + int reg, int width); +static __inline void aic_pci_write_config(aic_dev_softc_t pci, + int reg, uint32_t value, + int width); +static __inline int aic_get_pci_function(aic_dev_softc_t); +static __inline int aic_get_pci_slot(aic_dev_softc_t); +static __inline int aic_get_pci_bus(aic_dev_softc_t); + + +static __inline uint32_t +aic_pci_read_config(aic_dev_softc_t pci, int reg, int width) +{ + return (pci_read_config(pci, reg, width)); +} + +static __inline void +aic_pci_write_config(aic_dev_softc_t pci, int reg, uint32_t value, int width) +{ + pci_write_config(pci, reg, value, width); +} + +static __inline int +aic_get_pci_function(aic_dev_softc_t pci) +{ + return (pci_get_function(pci)); +} + +static __inline int +aic_get_pci_slot(aic_dev_softc_t pci) +{ + return (pci_get_slot(pci)); +} + +static __inline int +aic_get_pci_bus(aic_dev_softc_t pci) +{ + return (pci_get_bus(pci)); +} + +typedef enum +{ + AIC_POWER_STATE_D0 = PCI_POWERSTATE_D0, + AIC_POWER_STATE_D1 = PCI_POWERSTATE_D1, + AIC_POWER_STATE_D2 = PCI_POWERSTATE_D2, + AIC_POWER_STATE_D3 = PCI_POWERSTATE_D3 +} aic_power_state; + +static __inline int aic_power_state_change(struct aic_softc *aic, + aic_power_state new_state); + +static __inline int +aic_power_state_change(struct aic_softc *aic, aic_power_state new_state) +{ + return (pci_set_powerstate(aic->dev_softc, new_state)); +} +#endif |