summaryrefslogtreecommitdiffstats
path: root/sys/dev/aic7xxx
diff options
context:
space:
mode:
authorgibbs <gibbs@FreeBSD.org>2003-12-17 00:02:10 +0000
committergibbs <gibbs@FreeBSD.org>2003-12-17 00:02:10 +0000
commitdf180be1a1cbeaebbc37fd8ccf96c25e4841c15b (patch)
tree4790640cfba22d98a6759549fdae47323b03710a /sys/dev/aic7xxx
parentcc1cc974aee6c9c450e01ac55c122becb6cf0a68 (diff)
downloadFreeBSD-src-df180be1a1cbeaebbc37fd8ccf96c25e4841c15b.zip
FreeBSD-src-df180be1a1cbeaebbc37fd8ccf96c25e4841c15b.tar.gz
ahc_eisa.c:
ahc_pci.c: ahd_pci.c: aic7xxx.c: aic79xx.c: aic_osm_lib.c: aic_osm_lib.h: Use common OSM routines from aic_osm_lib for bus dma operations, delay routines, accessing CCBs, byte swapping, etc. aic7xxx_pci.c: Provide a better description for the 2915/30LP on attach. aic7xxx.c: aic79xx.c: aic7770.c: aic79xx_pci.c: aic7xxx_pci.c: aic7xxx_93cx6.c: Move FBSDID behind an ifdef so that these core files will still compile under other OSes. aic79xx.h: aic79xx_pci.c: aic79xx.seq: To speed up non-packetized 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. aic79xx.h: Add the AHD_FAST_CDB_DELIVERY feature. aic79xx_pci.c: Set AHD_FAST_CDB_DELIVERY for all Rev. B parts. aic79xx.seq: Test for PHASEMIS in the command phase for all AHD_FAST_CDB_DELIVERY controlelrs. ahd_pci.c: ahc_pci.c: aic7xxx.h: aic79xx.h: Move definition of controller BAR offsets to core header files. aic7xxx.c: aic79xx.c: In the softc free routine, leave removal of a softc from the global list of softcs to the OSM (the caller of this routine). This allows us to avoid holding the softc list_lock during device destruction where we may have to sleep waiting for our recovery thread to halt. ahc_pci.c: Use ahc_pci_test_register access to validate I/O mapped in addition to the tests already performed for memory mapped access. Remove unused ahc_power_state_change() function. The PCI layer in both 4.X and 5.X now offer this functionality. ahd_pci.c: Remove reduntant definition of controller BAR offsets. These are also defined in aic79xx.h. Remove unused ahd_power_state_change() function. The PCI layer in both 4.X and 5.X now offer this functionality. aic7xxx.c: aic79xx.c: aic79xx.h: aic7xxx.h: aic7xxx_osm.c: aic79xx_osm.c: Move timeout handling to the driver cores. In the case of the aic79xx driver, the algorithm has been enhanced to try target resets before performing a bus reset. For the aic7xxx driver, the algorithm is unchanged. Although the drivers do not currently sleep during recovery (recovery is timeout driven), the cores do expect all processing to be performed via a recovery thread. Our timeout handlers are now little stubs that wakeup the recovery thread. aic79xx.c: aic79xx.h: aic79xx_inline.h: Change shared_data allocation to use a map_node so that the sentinel hscb can use this map node in ahd_swap_with_next_hscb. This routine now swaps the hscb_map pointer in additon to the hscb contents so that any sync operations occur on the correct map. physaddr -> busaddr Pointed out by: Jason Thorpe <thorpej@wasabisystems.com> aic79xx.c: Make more use of the in/out/w/l/q macros for accessing byte registers in the chip. Correct some issues in the ahd_flush_qoutfifo() routine. o Run the qoutfifo only once the command channel DMA engine has been halted. This closes a window where we might have missed some entries. o Change ahd_run_data_fifo() to not loop to completion. If we happen to start on the wrong FIFO and the other FIFO has a snapshot savepointers, we might deadlock. This required our delay between FIFO tests to be moved to the ahd_flush_qoutfifo() routine. o Update/add comments. o Remove spurious test for COMPLETE_DMA list being empty when completing transactions from the GSFIFO with residuals. The SCB must be put on the COMPLETE_DMA scb list unconditionally. o When halting command channel DMA activity, we must disable the DMA channel in all cases but an update of the QOUTFIFO. The latter case is required so that the sequencer will update its position in the QOUTFIFO. Previously, we left the channel enabled for all "push" DMAs. This left us vulnerable to the sequencer handling an SCB push long after that SCB was already processed manually by this routine. o Correct the polarity of tests involving ahd_scb_active_in_fifo(). This routine returns non-zero for true. Return to processing bad status completions through the qoutfifo. This reduces the time that the sequencer is kept paused when handling transactions with bad status or underruns. When waiting for the controller to quiece selections, add a delay to our loop. Otherwise we may fail to wait long enough for the sequencer to comply. On H2A4 hardware, use the slow slewrate for non-paced transfers. This mirrors what the Adaptec Windows drivers do. On the Rev B. only slow down the CRC timing for older U160 devices that might need the slower timing. We define "older" as devices that do not support packetized protocol. Wait up to 5000 * 5us for the SEEPROM to become unbusy. Write ops seem to take much longer than read ops. aic79xx.seq: For controllers with the FAINT_LED bug, turn the diagnostic led feature on during selection and reselection. This covers the non-packetized case. The LED will be disabled for non-packetized transfers once we return to the top level idle loop. Add more comments about the busy LED workaround. Extend a critical section around the entire command channel idle loop process. Previously the portion of this handler that directly manipulated the linked list of completed SCBs was not protected. This is the likely cause of the recent reports of commands being completed twice by the driver. Extend critical sections across the test for, and the longjump to, longjump routines. This prevents the firmware from trying to jump to a longjmp handler that was just cleared by the host. Improve the locations of several critical section begin and end points. Typically these changes remove instructions that did not need to be inside a critical section. Close the "busfree after selection, but before busfree interrupts can be enabled" race to just a single sequencer instruction. We now test the BSY line explicitly before clearing the busfree status and enabling the busfree interrupt. Close a race condition in the processing of HS_MAILBOX updates. We now clear the "updated" status before the copy. This ensures that we don't accidentally clear the status incorrectly when the host sneaks in an update just after our last copy, but before we clear the status. This race has never been observed. Don't re-enable SCSIEN if we lose the race to disable SCSIEN in our interrupt handler's workaround for the RevA data-valid too early issue. aic79xx_inline.h: Add comments indicating that the order in which bytes are read or written in ahd_inw and ahd_outw is important. This allows us to use these inlines when accessing registers with side-effects. aic79xx_pci.c: The 29320 and the 29320B are 7902 not 7901 based products. Correct the driver banner. aic7xxx.h: Enable the use of the auto-access pause feature on the aic7870 and aic7880. It was disabled due to an oversight. aic7xxx.reg: Move TARG_IMMEDIATE_SCB to alias LAST_MSG to avoid leaving garbage in MWI_RESIDUAL. This prevents spurious overflows whn operating target mode on controllers that require the MWI_RESIDUAL work-around. aic7xxx.seq: AHC_TMODE_WIDEODD_BUG is a bug, not a softc flag. Reference the correct softc field when testing for its presence. Set the NOT_IDENTIFIED and NO_CDB_SENT bits in SEQ_FLAGS to indicate that the nexus is invalid in await busfree. aic7xxx_93cx6.c: Add support for the C56/C66 versions of the EWEN and EWDS commands. aic7xxx.c: aic7xxx_pci.c: Move test for the validity of left over BIOS data to ahc_test_register_access(). This guarantees that any left over CHIPRST value is not clobbered by our register access test and lost to the test that was in ahc_reset.
Diffstat (limited to 'sys/dev/aic7xxx')
-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