summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/dev/aic7xxx/ahc_eisa.c6
-rw-r--r--sys/dev/aic7xxx/ahc_pci.c72
-rw-r--r--sys/dev/aic7xxx/ahd_pci.c59
-rw-r--r--sys/dev/aic7xxx/aic7770.c9
-rw-r--r--sys/dev/aic7xxx/aic79xx.c1092
-rw-r--r--sys/dev/aic7xxx/aic79xx.h42
-rw-r--r--sys/dev/aic7xxx/aic79xx.seq143
-rw-r--r--sys/dev/aic7xxx/aic79xx_inline.h67
-rw-r--r--sys/dev/aic7xxx/aic79xx_osm.c363
-rw-r--r--sys/dev/aic7xxx/aic79xx_osm.h328
-rw-r--r--sys/dev/aic7xxx/aic79xx_pci.c110
-rw-r--r--sys/dev/aic7xxx/aic7xxx.c576
-rw-r--r--sys/dev/aic7xxx/aic7xxx.h35
-rw-r--r--sys/dev/aic7xxx/aic7xxx.reg4
-rw-r--r--sys/dev/aic7xxx/aic7xxx.seq5
-rw-r--r--sys/dev/aic7xxx/aic7xxx_93cx6.c38
-rw-r--r--sys/dev/aic7xxx/aic7xxx_inline.h26
-rw-r--r--sys/dev/aic7xxx/aic7xxx_osm.c379
-rw-r--r--sys/dev/aic7xxx/aic7xxx_osm.h314
-rw-r--r--sys/dev/aic7xxx/aic7xxx_pci.c169
-rw-r--r--sys/dev/aic7xxx/aic_osm_lib.c169
-rw-r--r--sys/dev/aic7xxx/aic_osm_lib.h426
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
OpenPOWER on IntegriCloud