patch-1.3.64 linux/drivers/scsi/aic7xxx.c
Next file: linux/drivers/scsi/aic7xxx.seq
Previous file: linux/drivers/net/arcnet.c
Back to the patch index
Back to the overall index
- Lines: 3246
- Date:
Thu Feb 15 06:57:02 1996
- Orig file:
v1.3.63/linux/drivers/scsi/aic7xxx.c
- Orig date:
Thu Dec 21 08:53:33 1995
diff -u --recursive --new-file v1.3.63/linux/drivers/scsi/aic7xxx.c linux/drivers/scsi/aic7xxx.c
@@ -1,5 +1,5 @@
/*+M*************************************************************************
- * Adaptec 274x/284x/294x device driver for Linux.
+ * Adaptec AIC7xxx device driver for Linux.
*
* Copyright (c) 1994 John Aycock
* The University of Calgary Department of Computer Science.
@@ -41,7 +41,7 @@
*
* -- Daniel M. Eischen, deischen@iworks.InterWorks.org, 04/03/95
*
- * $Id: aic7xxx.c,v 2.15 1995/12/17 19:43:20 deang Exp $
+ * $Id: aic7xxx.c,v 2.22 1996/02/10 09:22:50 deang Exp deang $
*-M*************************************************************************/
#ifdef MODULE
@@ -64,6 +64,7 @@
#include "scsi.h"
#include "hosts.h"
#include "aic7xxx.h"
+#include "aic7xxx_reg.h"
#include <linux/stat.h>
#include <linux/config.h> /* for CONFIG_PCI */
@@ -73,7 +74,7 @@
S_IFDIR | S_IRUGO | S_IXUGO, 2
};
-#define AIC7XXX_C_VERSION "$Revision: 2.15 $"
+#define AIC7XXX_C_VERSION "$Revision: 2.22 $"
#define NUMBER(arr) (sizeof(arr) / sizeof(arr[0]))
#define MIN(a,b) ((a < b) ? a : b)
@@ -92,10 +93,9 @@
*
* o PCI bus support - this has been implemented and working since
* the December 1, 1994 release of this driver. If you don't have
- * a PCI bus and do not wish to configure your kernel with PCI
- * support, then make sure this define is set to the cprrect
- * define for PCI support (CONFIG_PCI) and configure your kernel
- * without PCI support (make config).
+ * a PCI bus, then you can configure your kernel without PCI
+ * support because all PCI dependent code is bracketed with
+ * "#ifdef CONFIG_PCI ... #endif CONFIG_PCI".
*
* o Twin bus support - this has been tested and does work.
*
@@ -130,7 +130,17 @@
* 1 SCB for each device and ensure that there will always be
* a free SCB for up to 4 devices active at the same time.
*
- * Daniel M. Eischen, deischen@iworks.InterWorks.org, 03/11/95
+ * o 3985 support - The 3985 adapter is much like the 3940, but
+ * has three 7870 controllers as opposed to two for the 3940.
+ * It will get probed and recognized as three different adapters,
+ * but all three controllers share the same bank of 255 SCBs
+ * instead of each controller having their own bank (like the
+ * controllers on the 3940). For this reason, it is important
+ * that all devices be resident on just one channel of the 3985.
+ * In the near future, we'll modify the driver to reserve 1/3
+ * of the SCBs for each controller.
+ *
+ * Daniel M. Eischen, deischen@iworks.InterWorks.org, 01/11/96
*/
/* Uncomment this for testing twin bus support. */
@@ -211,8 +221,7 @@
typedef enum {
LIST_HEAD,
- LIST_SECOND,
- LIST_TAIL
+ LIST_SECOND
} insert_type;
typedef enum {
@@ -268,523 +277,52 @@
/*
* Standard EISA Host ID regs (Offset from slot base)
*/
-#define HID0(x) ((x) + 0xC80) /* 0,1: msb of ID2, 2-7: ID1 */
-#define HID1(x) ((x) + 0xC81) /* 0-4: ID3, 5-7: LSB ID2 */
-#define HID2(x) ((x) + 0xC82) /* product */
-#define HID3(x) ((x) + 0xC83) /* firmware revision */
+#define HID0 0x80 /* 0,1: msb of ID2, 2-7: ID1 */
+#define HID1 0x81 /* 0-4: ID3, 5-7: LSB ID2 */
+#define HID2 0x82 /* product */
+#define HID3 0x83 /* firmware revision */
/*
* AIC-7770 I/O range to reserve for a card
*/
-#define MINREG(x) ((x) + 0xC00ul)
-#define MAXREG(x) ((x) + 0xCBFul)
-
-/* -------------------- AIC-7770 offset definitions ----------------------- */
-
-/*
- * SCSI Sequence Control (p. 3-11).
- * Each bit, when set starts a specific SCSI sequence on the bus
- */
-#define SCSISEQ(x) ((x) + 0xC00ul)
-#define TEMODEO 0x80
-#define ENSELO 0x40
-#define ENSELI 0x20
-#define ENRSELI 0x10
-#define ENAUTOATNO 0x08
-#define ENAUTOATNI 0x04
-#define ENAUTOATNP 0x02
-#define SCSIRSTO 0x01
-
-
-/*
- * SCSI Transfer Control 0 Register (pp. 3-13).
- * Controls the SCSI module data path.
- */
-#define SXFRCTL0(x) ((x) + 0xC01ul)
-#define DFON 0x80
-#define DFPEXP 0x40
-#define ULTRAEN 0x20
-#define CLRSTCNT 0x10
-#define SPIOEN 0x08
-#define SCAMEN 0x04
-#define CLRCHN 0x02
-/* UNUSED 0x01 */
-
-/*
- * SCSI Transfer Control 1 Register (pp. 3-14,15).
- * Controls the SCSI module data path.
- */
-#define SXFRCTL1(x) ((x) + 0xC02ul)
-#define BITBUCKET 0x80
-#define SWRAPEN 0x40
-#define ENSPCHK 0x20
-#define STIMESEL 0x18
-#define ENSTIMER 0x04
-#define ACTNEGEN 0x02
-#define STPWEN 0x01 /* Powered Termination */
-
-/*
- * SCSI Control Signal Read Register (p. 3-15).
- * Reads the actual state of the SCSI bus pins
- */
-#define SCSISIGI(x) ((x) + 0xC03ul)
-#define CDI 0x80
-#define IOI 0x40
-#define MSGI 0x20
-#define ATNI 0x10
-#define SELI 0x08
-#define BSYI 0x04
-#define REQI 0x02
-#define ACKI 0x01
-
-/*
- * SCSI Contol Signal Write Register (p. 3-16).
- * Writing to this register modifies the control signals on the bus. Only
- * those signals that are allowed in the current mode (Initiator/Target) are
- * asserted.
- */
-#define SCSISIGO(x) ((x) + 0xC03ul)
-#define CDO 0x80
-#define IOO 0x40
-#define MSGO 0x20
-#define ATNO 0x10
-#define SELO 0x08
-#define BSYO 0x04
-#define REQO 0x02
-#define ACKO 0x01
-
-/*
- * SCSI Rate
- */
-#define SCSIRATE(x) ((x) + 0xC04ul)
-#define WIDEXFER 0x80 /* Wide transfer control */
-#define SXFR 0x70 /* Sync transfer rate */
-#define SOFS 0x0F /* Sync offset */
-
-/*
- * SCSI ID (p. 3-18).
- * Contains the ID of the board and the current target on the
- * selected channel
- */
-#define SCSIID(x) ((x) + 0xC05ul)
-#define TID 0xF0 /* Target ID mask */
-#define OID 0x0F /* Our ID mask */
-
-/*
- * SCSI Transfer Count (pp. 3-19,20)
- * These registers count down the number of bytes transfered
- * across the SCSI bus. The counter is decremented only once
- * the data has been safely transfered. SDONE in SSTAT0 is
- * set when STCNT goes to 0
- */
-#define STCNT(x) ((x) + 0xC08ul)
-
-/*
- * SCSI Status 0 (p. 3-21)
- * Contains one set of SCSI Interrupt codes
- * These are most likely of interest to the sequencer
- */
-#define SSTAT0(x) ((x) + 0xC0Bul)
-#define TARGET 0x80 /* Board is a target */
-#define SELDO 0x40 /* Selection Done */
-#define SELDI 0x20 /* Board has been selected */
-#define SELINGO 0x10 /* Selection In Progress */
-#define SWRAP 0x08 /* 24bit counter wrap */
-#define SDONE 0x04 /* STCNT = 0x000000 */
-#define SPIORDY 0x02 /* SCSI PIO Ready */
-#define DMADONE 0x01 /* DMA transfer completed */
-
-/*
- * Clear SCSI Interrupt 1 (p. 3-23)
- * Writing a 1 to a bit clears the associated SCSI Interrupt in SSTAT1.
- */
-#define CLRSINT1(x) ((x) + 0xC0Cul)
-#define CLRSELTIMEO 0x80
-#define CLRATNO 0x40
-#define CLRSCSIRSTI 0x20
-/* UNUSED 0x10 */
-#define CLRBUSFREE 0x08
-#define CLRSCSIPERR 0x04
-#define CLRPHASECHG 0x02
-#define CLRREQINIT 0x01
-
-/*
- * SCSI Status 1 (p. 3-24)
- * These interrupt bits are of interest to the kernel driver
- */
-#define SSTAT1(x) ((x) + 0xC0Cul)
-#define SELTO 0x80
-#define ATNTARG 0x40
-#define SCSIRSTI 0x20
-#define PHASEMIS 0x10
-#define BUSFREE 0x08
-#define SCSIPERR 0x04
-#define PHASECHG 0x02
-#define REQINIT 0x01
-
-/*
- * SCSI Interrrupt Mode 1 (pp. 3-28,29).
- * Set bits in this register enable the corresponding
- * interrupt source.
- */
-#define SIMODE1(x) ((x) + 0xC11ul)
-#define ENSELTIMO 0x80
-#define ENATNTARG 0x40
-#define ENSCSIRST 0x20
-#define ENPHASEMIS 0x10
-#define ENBUSFREE 0x08
-#define ENSCSIPERR 0x04
-#define ENPHASECHG 0x02
-#define ENREQINIT 0x01
-
-/*
- * SCSI/Host Address (p. 3-30)
- * These registers hold the host address for the byte about to be
- * transfered on the SCSI bus. They are counted up in the same
- * manner as STCNT is counted down. SHADDR should always be used
- * to determine the address of the last byte transfered since HADDR
- * can be squewed by write ahead.
- */
-#define SHADDR(x) ((x) + 0xC14ul)
-
-/*
- * Selection/Reselection ID (p. 3-31)
- * Upper four bits are the device id. The ONEBIT is set when the re/selecting
- * device did not set its own ID.
- */
-#define SELID(x) ((x) + 0xC19ul)
-#define SELID_MASK 0xF0
-#define ONEBIT 0x08
-/* UNUSED 0x07 */
-
-/*
- * SCSI Block Control (p. 3-32)
- * Controls Bus type and channel selection. In a twin channel configuration
- * addresses 0x00-0x1E are gated to the appropriate channel based on this
- * register. SELWIDE allows for the coexistence of 8bit and 16bit devices
- * on a wide bus.
- */
-#define SBLKCTL(x) ((x) + 0xC1Ful)
-/* UNUSED 0xC0 */
-#define DIAGLEDEN 0x80
-#define DIAGLEDON 0x40
-#define AUTOFLUSHDIS 0x20 /* used for Rev C check */
-/* UNUSED 0x10 */
-#define SELBUS_MASK 0x0F
-#define SELBUSB 0x08
-/* UNUSED 0x04 */
-#define SELWIDE 0x02
-/* UNUSED 0x01 */
-#define SELSINGLE 0x00
-
-/*
- * Sequencer Control (p. 3-33)
- * Error detection mode and speed configuration
- */
-#define SEQCTL(x) ((x) + 0xC60ul)
-#define PERRORDIS 0x80
-#define PAUSEDIS 0x40
-#define FAILDIS 0x20
-#define FASTMODE 0x10
-#define BRKADRINTEN 0x08
-#define STEP 0x04
-#define SEQRESET 0x02
-#define LOADRAM 0x01
-
-/*
- * Sequencer RAM Data (p. 3-34)
- * Single byte window into the Scratch Ram area starting at the address
- * specified by SEQADDR0 and SEQADDR1. To write a full word, simply write
- * four bytes in sucessesion. The SEQADDRs will increment after the most
- * significant byte is written
- */
-#define SEQRAM(x) ((x) + 0xC61ul)
-
-/*
- * Sequencer Address Registers (p. 3-35)
- * Only the first bit of SEQADDR1 holds addressing information
- */
-#define SEQADDR0(x) ((x) + 0xC62ul)
-#define SEQADDR1(x) ((x) + 0xC63ul)
-
-#define ACCUM(x) ((x) + 0xC64ul) /* accumulator */
-#define SINDEX(x) ((x) + 0xC65ul)
-
-/*
- * Board Control (p. 3-43)
- */
-#define BCTL(x) ((x) + 0xC84ul)
-/* RSVD 0xF0 */
-#define ACE 0x08 /* Support for external processors */
-/* RSVD 0x06 */
-#define ENABLE 0x01
-
-/*
- * Bus On/Off Time (p. 3-44)
- */
-#define BUSTIME(x) ((x) + 0xC85ul)
-#define BOFF 0xF0
-#define BON 0x0F
-
-/*
- * Bus Speed (p. 3-45)
- */
-#define BUSSPD(x) ((x) + 0xC86ul)
-#define DFTHRSH 0xC0
-#define STBOFF 0x38
-#define STBON 0x07
+#define MINREG 0xC00
+#define MAXREG 0xCBF
-/*
- * Host Control (p. 3-47) R/W
- * Overal host control of the device.
- */
-#define HCNTRL(x) ((x) + 0xC87ul)
-/* UNUSED 0x80 */
-#define POWRDN 0x40
-/* UNUSED 0x20 */
-#define SWINT 0x10
-#define IRQMS 0x08
-#define PAUSE 0x04
-#define INTEN 0x02
-#define CHIPRST 0x01
-#define REQ_PAUSE IRQMS | INTEN | PAUSE
-#define UNPAUSE_274X IRQMS | INTEN
-#define UNPAUSE_284X INTEN
-#define UNPAUSE_294X IRQMS | INTEN
+#define INTDEF 0x5C /* Interrupt Definition Register */
/*
- * Host Address (p. 3-48)
- * This register contains the address of the byte about
- * to be transfered across the host bus.
+ * Some defines for the HCNTRL register.
*/
-#define HADDR(x) ((x) + 0xC88ul)
-
-/*
- * SCB Pointer (p. 3-49)
- * Gate one of the four SCBs into the SCBARRAY window.
- */
-#define SCBPTR(x) ((x) + 0xC90ul)
-
-/*
- * Interrupt Status (p. 3-50)
- * Status for system interrupts
- */
-#define INTSTAT(x) ((x) + 0xC91ul)
-#define SEQINT_MASK 0xF0 /* SEQINT Status Codes */
-#define BAD_PHASE 0x00
-#define SEND_REJECT 0x10
-#define NO_IDENT 0x20
-#define NO_MATCH 0x30
-#define MSG_SDTR 0x40
-#define MSG_WDTR 0x50
-#define MSG_REJECT 0x60
-#define BAD_STATUS 0x70
-#define RESIDUAL 0x80
-#define ABORT_TAG 0x90
-#define AWAITING_MSG 0xA0
-#define IMMEDDONE 0xB0
-#define BRKADRINT 0x08
-#define SCSIINT 0x04
-#define CMDCMPLT 0x02
-#define SEQINT 0x01
-#define INT_PEND (BRKADRINT | SEQINT | SCSIINT | CMDCMPLT)
-
-/*
- * Hard Error (p. 3-53)
- * Reporting of catastrophic errors. You usually cannot recover from
- * these without a full board reset.
- */
-#define ERROR(x) ((x) + 0xC92ul)
-/* UNUSED 0xF0 */
-#define PARERR 0x08
-#define ILLOPCODE 0x04
-#define ILLSADDR 0x02
-#define ILLHADDR 0x01
-
-/*
- * Clear Interrupt Status (p. 3-52)
- */
-#define CLRINT(x) ((x) + 0xC92ul)
-#define CLRBRKADRINT 0x08
-#define CLRSCSIINT 0x04
-#define CLRCMDINT 0x02
-#define CLRSEQINT 0x01
-
-/*
- * SCB Auto Increment (p. 3-59)
- * Byte offset into the SCB Array and an optional bit to allow auto
- * incrementing of the address during download and upload operations
- */
-#define SCBCNT(x) ((x) + 0xC9Aul)
-#define SCBAUTO 0x80
-#define SCBCNT_MASK 0x1F
-
-/*
- * Queue In FIFO (p. 3-60)
- * Input queue for queued SCBs (commands that the seqencer has yet to start)
- */
-#define QINFIFO(x) ((x) + 0xC9Bul)
-
-/*
- * Queue In Count (p. 3-60)
- * Number of queued SCBs
- */
-#define QINCNT(x) ((x) + 0xC9Cul)
-
-/*
- * Queue Out FIFO (p. 3-61)
- * Queue of SCBs that have completed and await the host
- */
-#define QOUTFIFO(x) ((x) + 0xC9Dul)
-
-/*
- * Queue Out Count (p. 3-61)
- * Number of queued SCBs in the Out FIFO
- */
-#define QOUTCNT(x) ((x) + 0xC9Eul)
-
-#define SCBARRAY(x) ((x) + 0xCA0ul)
-
-/* ---------------- END AIC-7770 Register Definitions ----------------- */
-
-/* --------------------- AHA-2840-only definitions -------------------- */
-
-#define SEECTL_2840(x) ((x) + 0xCC0ul)
-/* UNUSED 0xF8 */
-#define CS_2840 0x04
-#define CK_2840 0x02
-#define DO_2840 0x01
-
-#define STATUS_2840(x) ((x) + 0xCC1ul)
-#define EEPROM_TF 0x80
-#define BIOS_SEL 0x60
-#define ADSEL 0x1E
-#define DI_2840 0x01
-
-/* --------------------- AIC-7870-only definitions -------------------- */
-
-#define DSPCISTATUS(x) ((x) + 0xC86ul)
-#define DFTHRESH 0xC0
-
-/*
- * Serial EEPROM Control (p. 4-92 in 7870 Databook)
- * Controls the reading and writing of an external serial 1-bit
- * EEPROM Device. In order to access the serial EEPROM, you must
- * first set the SEEMS bit that generates a request to the memory
- * port for access to the serial EEPROM device. When the memory
- * port is not busy servicing another request, it reconfigures
- * to allow access to the serial EEPROM. When this happens, SEERDY
- * gets set high to verify that the memory port access has been
- * granted. See aic7xxx_read_eprom for detailed information on
- * the protocol necessary to read the serial EEPROM.
- */
-#define SEECTL(x) ((x) + 0xC1Eul)
-#define EXTARBACK 0x80
-#define EXTARBREQ 0x40
-#define SEEMS 0x20
-#define SEERDY 0x10
-#define SEECS 0x08
-#define SEECK 0x04
-#define SEEDO 0x02
-#define SEEDI 0x01
-
-#define DEVREVID 0x08ul
-
-#define DEVSTATUS 0x40ul
-#define MPORTMODE 0x04 /* aic7870 only */
-#define RAMPSM 0x02 /* aic7870 only */
-#define VOLSENSE 0x01
-
-#define DEVCONFIG 0x41ul
-#define SCBRAMSEL 0x80
-#define MRDCEN 0x40
-#define EXTSCBTIME 0x20 /* aic7870 only */
-#define EXTSCBPEN 0x10 /* aic7870 only */
-#define BERREN 0x08
-#define DACEN 0x04
-#define STPWLEVEL 0x02
-#define DIFACTNEGEN 0x01 /* aic7870 only */
-
-/* Scratch RAM offset definitions */
-
-/* ---------------------- Scratch RAM Offsets ------------------------- */
-/* These offsets are either to values that are initialized by the board's
- * BIOS or are specified by the Linux sequencer code. If I can figure out
- * how to read the EISA configuration info at probe time, the cards could
- * be run without BIOS support installed
- */
-
-/*
- * 1 byte per target starting at this address for configuration values
- */
-#define HA_TARG_SCRATCH(x) ((x) + 0xC20ul)
-
-/*
- * The sequencer will stick the first byte of any rejected message here so
- * we can see what is getting thrown away.
- */
-#define HA_REJBYTE(x) ((x) + 0xC31ul)
-
-/*
- * Bit vector of targets that have disconnection disabled.
- */
-#define HA_DISC_DSB(x) ((x) + 0xC32ul)
-
-/*
- * Length of pending message
- */
-#define HA_MSG_LEN(x) ((x) + 0xC34ul)
-
-/*
- * Outgoing Message Body
- */
-#define HA_MSG_START(x) ((x) + 0xC35ul)
-
-/*
- * These are offsets into the card's scratch ram. Some of the values are
- * specified in the AHA2742 technical reference manual and are initialized
- * by the BIOS at boot time.
- */
-#define HA_ARG_1(x) ((x) + 0xC4Aul) /* sdtr <-> rate parameters */
-#define HA_RETURN_1(x) ((x) + 0xC4Aul)
-#define SEND_SENSE 0x80
-#define SEND_SDTR 0x80
-#define SEND_WDTR 0x80
-#define SEND_REJ 0x40
-
-#define SG_COUNT(x) ((x) + 0xC4Dul)
-#define SG_NEXT(x) ((x) + 0xC4Eul)
-#define HA_SIGSTATE(x) ((x) + 0xC4Bul) /* value in SCSISIGO */
-#define HA_SCBCOUNT(x) ((x) + 0xC52ul) /* number of hardware SCBs */
-
-#define HA_FLAGS(x) ((x) + 0xC53ul) /* TWIN and WIDE bus flags */
-#define SINGLE_BUS 0x00
-#define TWIN_BUS 0x01
-#define WIDE_BUS 0x02
-#define ACTIVE_MSG 0x20
-#define IDENTIFY_SEEN 0x40
-#define RESELECTING 0x80
-
-#define HA_ACTIVE0(x) ((x) + 0xC54ul) /* Active bits; targets 0-7 */
-#define HA_ACTIVE1(x) ((x) + 0xC55ul) /* Active bits; targets 8-15 */
-#define SAVED_TCL(x) ((x) + 0xC56ul) /* Saved target, channel, LUN */
-#define WAITING_SCBH(x) ((x) + 0xC57ul) /* Head of disconnected targets list. */
-#define WAITING_SCBT(x) ((x) + 0xC58ul) /* Tail of disconnected targets list. */
-
-#define HA_SCSICONF(x) ((x) + 0xC5Aul) /* SCSI config register */
-#define HA_INTDEF(x) ((x) + 0xC5Cul) /* interrupt def'n register */
-#define HA_HOSTCONF(x) ((x) + 0xC5Dul) /* host config def'n register */
-
-#define HA_274_BIOSCTRL(x) ((x) + 0xC5Ful) /* BIOS enabled for 274x */
-#define BIOSMODE 0x30
-#define BIOSDISABLED 0x30
-
-#define MSG_ABORT 0x06
-#define MSG_BUS_DEVICE_RESET 0x0C
-#define BUS_8_BIT 0x00
-#define BUS_16_BIT 0x01
-#define BUS_32_BIT 0x02
-
+#define REQ_PAUSE IRQMS | INTEN | PAUSE
+#define UNPAUSE_274X IRQMS | INTEN
+#define UNPAUSE_284X INTEN
+#define UNPAUSE_294X IRQMS | INTEN
+
+/*
+ * AIC-78X0 PCI registers
+ */
+#define CLASS_PROGIF_REVID 0x08
+#define DEVREVID 0x000000FFul
+#define PROGINFC 0x0000FF00ul
+#define SUBCLASS 0x00FF0000ul
+#define BASECLASS 0xFF000000ul
+
+#define CSIZE_LATTIME 0x0C
+#define CACHESIZE 0x0000003Ful /* only 5 bits */
+#define LATTIME 0x0000FF00ul
+
+#define DEVCONFIG 0x40
+#define MPORTMODE 0x00000400ul /* aic7870 only */
+#define RAMPSM 0x00000200ul /* aic7870 only */
+#define VOLSENSE 0x00000100ul
+#define SCBRAMSEL 0x00000080ul
+#define MRDCEN 0x00000040ul
+#define EXTSCBTIME 0x00000020ul /* aic7870 only */
+#define EXTSCBPEN 0x00000010ul /* aic7870 only */
+#define BERREN 0x00000008ul
+#define DACEN 0x00000004ul
+#define STPWLEVEL 0x00000002ul
+#define DIFACTNEGEN 0x00000001ul /* aic7870 only */
/*
*
@@ -853,7 +391,6 @@
unsigned short res_1[11]; /* words 20-30 */
unsigned short checksum; /* word 31 */
-
};
/*
@@ -862,8 +399,8 @@
* sections.
*/
#define PAUSE_SEQUENCER(p) \
- outb(p->pause, HCNTRL(p->base)); \
- while ((inb(HCNTRL(p->base)) & PAUSE) == 0) \
+ outb(p->pause, HCNTRL + p->base); \
+ while ((inb(HCNTRL + p->base) & PAUSE) == 0) \
; \
/*
@@ -871,16 +408,16 @@
* warrant an easy way to do it.
*/
#define UNPAUSE_SEQUENCER(p) \
- outb(p->unpause, HCNTRL(p->base))
+ outb(p->unpause, HCNTRL + p->base)
/*
* Restart the sequencer program from address zero
*/
#define RESTART_SEQUENCER(p) \
do { \
- outb(SEQRESET | FASTMODE, SEQCTL(p->base)); \
- } while (inb(SEQADDR0(p->base)) != 0 && \
- inb(SEQADDR1(p->base)) != 0); \
+ outb(SEQRESET | FASTMODE, SEQCTL + p->base); \
+ } while (inb(SEQADDR0 + p->base) != 0 && \
+ inb(SEQADDR1 + p->base) != 0); \
UNPAUSE_SEQUENCER(p);
/*
@@ -958,48 +495,31 @@
/*
* The driver keeps up to four scb structures per card in memory. Only the
- * first 26 bytes of the structure are valid for the hardware, the rest used
- * for driver level bookeeping.
+ * first 25 bytes of the structure are valid for the hardware, the rest used
+ * for driver level bookkeeping.
*/
-#define SCB_DOWNLOAD_SIZE 26 /* amount to actually download */
-#define SCB_UPLOAD_SIZE 26 /* amount to actually upload */
struct aic7xxx_scb {
/* ------------ Begin hardware supported fields ---------------- */
-/*1 */ unsigned char control;
-#define SCB_NEEDWDTR 0x80 /* Initiate Wide Negotiation */
-#define SCB_DISCENB 0x40 /* Disconnection Enable */
-#define SCB_TE 0x20 /* Tag enable */
-#define SCB_NEEDSDTR 0x10 /* Initiate Sync Negotiation */
-#define SCB_NEEDDMA 0x08 /* Refresh SCB from host ram */
-#define SCB_DIS 0x04
-#define SCB_TAG_TYPE 0x03
-#define SIMPLE_QUEUE 0x00
-#define HEAD_QUEUE 0x01
-#define OR_QUEUE 0x02
-/* ILLEGAL 0x03 */
-/*2 */ unsigned char target_channel_lun; /* 4/1/3 bits */
-/*3 */ unsigned char SG_segment_count;
-/*7 */ unsigned char SG_list_pointer[4] __attribute__ ((packed));
-/*11*/ unsigned char SCSI_cmd_pointer[4] __attribute__ ((packed));
-/*12*/ unsigned char SCSI_cmd_length;
-/*14*/ unsigned char RESERVED[2]; /* must be zero */
-/*15*/ unsigned char target_status;
-/*18*/ unsigned char residual_data_count[3];
-/*19*/ unsigned char residual_SG_segment_count;
-/*23*/ unsigned char data_pointer[4] __attribute__ ((packed));
-/*26*/ unsigned char data_count[3];
-/*30*/ unsigned char host_scb[4] __attribute__ ((packed));
-/*31*/ u_char next_waiting; /* Used to thread SCBs awaiting selection. */
-#define SCB_LIST_NULL 0xFF /* SCB list equivelent to NULL */
-#if 0
- /*
- * No real point in transferring this to the
- * SCB registers.
- */
- unsigned char RESERVED[1];
-#endif
-
+/* 0*/ unsigned char control;
+/* 1*/ unsigned char target_channel_lun; /* 4/1/3 bits */
+/* 2*/ unsigned char target_status;
+/* 3*/ unsigned char SG_segment_count;
+/* 4*/ unsigned char SG_list_pointer[4] __attribute__ ((packed));
+/* 8*/ unsigned char residual_SG_segment_count;
+/* 9*/ unsigned char residual_data_count[3];
+/*12*/ unsigned char data_pointer[4] __attribute__ ((packed));
+/*16*/ unsigned long data_count;
+/*20*/ unsigned char SCSI_cmd_pointer[4] __attribute__ ((packed));
+/*24*/ unsigned char SCSI_cmd_length;
+#define SCB_PIO_TRANSFER_SIZE 25 /*
+ * amount we need to upload/download
+ * via rep in/outsb to perform
+ * a request sense. The second
+ * RESERVED byte is initialized to
+ * 0 in getscb().
+ */
+/*25*/ u_char next_waiting; /* Used to thread SCBs awaiting selection. */
/*-----------------end of hardware supported fields----------------*/
struct aic7xxx_scb *next; /* next ptr when in free list */
Scsi_Cmnd *cmd; /* Scsi_Cmnd for this scb */
@@ -1016,8 +536,6 @@
unsigned char sense_cmd[6]; /* Allocate 6 characters for sense command */
};
-typedef void (*timeout_fn)(unsigned long);
-
static struct {
unsigned char errno;
const char *errmesg;
@@ -1142,10 +660,11 @@
static int num_aic7xxx_syncrates =
sizeof(aic7xxx_syncrates) / sizeof(aic7xxx_syncrates[0]);
+#ifdef CONFIG_PCI
static int number_of_39xxs = 0;
+#endif CONFIG_PCI
#ifdef AIC7XXX_DEBUG
-
static void
debug(const char *fmt, ...)
{
@@ -1169,8 +688,8 @@
static int SST[] = { 256, 128, 64, 32 };
static const char *BUSW[] = { "", "-TWIN", "-WIDE" };
- host_conf = inb(HA_HOSTCONF(p->base));
- scsi_conf = inb(HA_SCSICONF(p->base));
+ host_conf = inb(HOSTCONF + p->base);
+ scsi_conf = inb(SCSICONF + p->base);
/*
* The 7870 gets the bus release time and data FIFO threshold
@@ -1282,13 +801,11 @@
scb->SCSI_cmd_length);
printk("reserved 0x%x, target status 0x%x, resid SG count %d, resid data count %d\n",
(scb->RESERVED[1] << 8) | scb->RESERVED[0], scb->target_status,
- scb->residual_SG_segment_count, (scb->residual_data_count[2] << 16) |
- (scb->residual_data_count[1] << 8) | scb->residual_data_count[0]);
- printk("data ptr 0x%x, data count %d, host scb 0x%x, next waiting %d\n",
+ scb->residual_SG_segment_count, scb->residual_data_count);
+ printk("data ptr 0x%x, data count %d, next waiting %d\n",
(scb->data_pointer[3] << 24) | (scb->data_pointer[2] << 16) |
(scb->data_pointer[1] << 8) | scb->data_pointer[0],
- (scb->data_count[2] << 16) | (scb->data_count[1] << 8) | scb->data_count[0],
- (unsigned int) scb->host_scb, scb->next_waiting);
+ scb->data_count, scb->next_waiting);
printk("next ptr 0x%lx, Scsi Cmnd 0x%lx, state 0x%x, position %d\n",
(unsigned long) scb->next, (unsigned long) scb->cmd, scb->state,
scb->position);
@@ -1385,14 +902,9 @@
* sequencer RAM parity error detection while loading, and
* make sure the LOADRAM bit is enabled for loading.
*/
- outb(PERRORDIS | SEQRESET | LOADRAM, SEQCTL(base));
+ outb(PERRORDIS | SEQRESET | LOADRAM, SEQCTL + base);
- asm volatile("cld\n\t"
- "rep\n\t"
- "outsb"
- : /* no output */
- :"S" (seqprog), "c" (sizeof(seqprog)), "d" (SEQRAM(base))
- :"si", "cx", "dx");
+ outsb(SEQRAM + base, seqprog, sizeof(seqprog));
/*
* WARNING! This is a magic sequence! After extensive
@@ -1410,8 +922,8 @@
* the address shows up as
* zero just to be safe..
*/
- outb(SEQRESET | FASTMODE, SEQCTL(base));
- } while ((inb(SEQADDR0(base)) != 0) && (inb(SEQADDR1(base)) != 0));
+ outb(SEQRESET | FASTMODE, SEQCTL + base);
+ } while ((inb(SEQADDR0 + base) != 0) && (inb(SEQADDR1 + base) != 0));
}
/*+F*************************************************************************
@@ -1551,7 +1063,7 @@
*-F*************************************************************************/
static void
aic7xxx_scsirate(struct aic7xxx_host *p, unsigned char *scsirate,
- unsigned char period, unsigned char offset,
+ short period, unsigned char offset,
int target, char channel)
{
int i;
@@ -1568,8 +1080,8 @@
{
if (!(aic7xxx_syncrates[i].rate & ULTRA_SXFR))
{
- printk ("aic7xxx: Target %d, channel %c, requests %sMB/s transfers, "
- "but adapter in Ultra mode can only sync at 10MB/s or "
+ printk ("aic7xxx: Target %d, channel %c, requests %sMHz transfers, "
+ "but adapter in Ultra mode can only sync at 10MHz or "
"above.\n", target, channel, aic7xxx_syncrates[i].english);
break; /* Use asynchronous transfers. */
}
@@ -1591,7 +1103,7 @@
}
}
*scsirate = (aic7xxx_syncrates[i].rate) | (offset & 0x0F);
- printk("aic7xxx: Target %d, channel %c, now synchronous at %sMB/s, "
+ printk("aic7xxx: Target %d, channel %c, now synchronous at %sMHz, "
"offset(0x%x).\n",
target, channel, aic7xxx_syncrates[i].english, offset);
return;
@@ -1613,43 +1125,35 @@
* Description:
* Transfer a SCB to the controller.
*-F*************************************************************************/
-static void
-aic7xxx_putscb(int base, struct aic7xxx_scb *scb)
+static inline void
+aic7xxx_putscb(struct aic7xxx_host *p, struct aic7xxx_scb *scb)
{
- /*
- * All we need to do, is to output the position
- * of the SCB in the SCBARRAY to the QINFIFO
- * of the host adapter.
- */
- outb(scb->position, QINFIFO(base));
-}
+ unsigned char curscb;
+ int base = p->base;
+
+ curscb = inb(SCBPTR + base);
+ outb(scb->position, SCBPTR + base);
+ outb(SCBAUTO, SCBCNT + base);
-/*+F*************************************************************************
- * Function:
- * aic7xxx_putscb_dma
- *
- * Description:
- * DMA a SCB to the controller.
- *-F*************************************************************************/
-static void
-aic7xxx_putscb_dma(int base, struct aic7xxx_scb *scb)
-{
/*
* By turning on the SCB auto increment, any reference
* to the SCB I/O space postincrements the SCB address
* we're looking at. So turn this on and dump the relevant
* portion of the SCB to the card.
+ *
+ * We can do 16bit transfers on all but 284x.
*/
- outb(SCBAUTO, SCBCNT(base));
-
- asm volatile("cld\n\t"
- "rep\n\t"
- "outsb"
- : /* no output */
- :"S" (scb), "c" (31), "d" (SCBARRAY(base))
- :"si", "cx", "dx");
+ if (p->type == AIC_284x)
+ {
+ outsb(SCBARRAY + base, scb, SCB_PIO_TRANSFER_SIZE);
+ }
+ else
+ {
+ outsl(SCBARRAY + base, scb, (SCB_PIO_TRANSFER_SIZE + 3) / 4);
+ }
- outb(0, SCBCNT(base));
+ outb(0, SCBCNT + base);
+ outb(curscb, SCBPTR + base);
}
/*+F*************************************************************************
@@ -1659,22 +1163,17 @@
* Description:
* Get a SCB from the controller.
*-F*************************************************************************/
-static void
-aic7xxx_getscb(int base, struct aic7xxx_scb *scb)
+static inline void
+aic7xxx_getscb(struct aic7xxx_host *p, struct aic7xxx_scb *scb)
{
+ int base = p->base;
+
/*
* This is almost identical to aic7xxx_putscb().
*/
- outb(SCBAUTO, SCBCNT(base));
-
- asm volatile("cld\n\t"
- "rep\n\t"
- "insb"
- : /* no output */
- :"D" (scb), "c" (SCB_UPLOAD_SIZE), "d" (SCBARRAY(base))
- :"di", "cx", "dx");
-
- outb(0, SCBCNT(base));
+ outb(SCBAUTO, SCBCNT + base);
+ insb(SCBARRAY + base, scb, SCB_PIO_TRANSFER_SIZE);
+ outb(0, SCBCNT + base);
}
/*+F*************************************************************************
@@ -1709,6 +1208,32 @@
/*+F*************************************************************************
* Function:
+ * aic7xxx_busy_target
+ *
+ * Description:
+ * Set the specified target active.
+ *-F*************************************************************************/
+static void
+aic7xxx_busy_target(unsigned char target, char channel, int base)
+{
+ unsigned char active;
+ unsigned long active_port = ACTIVE_A + base;
+
+ if ((target > 0x07) || (channel == 'B'))
+ {
+ /*
+ * targets on the Second channel or above id 7 store info in byte two
+ * of ACTIVE
+ */
+ active_port++;
+ }
+ active = inb(active_port);
+ active |= (0x01 << (target & 0x07));
+ outb(active, active_port);
+}
+
+/*+F*************************************************************************
+ * Function:
* aic7xxx_unbusy_target
*
* Description:
@@ -1718,9 +1243,9 @@
aic7xxx_unbusy_target(unsigned char target, char channel, int base)
{
unsigned char active;
- unsigned long active_port = HA_ACTIVE0(base);
+ unsigned long active_port = ACTIVE_A + base;
-#ifdef AIC7XXX_DEBUG_ABORT
+#ifdef 0
printk ("aic7xxx: (unbusy_target) target/channel %d/%c\n",
target, channel);
#endif
@@ -1728,13 +1253,13 @@
{
/*
* targets on the Second channel or above id 7 store info in byte two
- * of HA_ACTIVE
+ * of ACTIVE
*/
active_port++;
}
active = inb(active_port);
active &= ~(0x01 << (target & 0x07));
- outb(active_port, active);
+ outb(active, active_port);
}
/*+F*************************************************************************
@@ -1767,7 +1292,7 @@
*/
scb->state = SCB_FREE;
scb->next = p->free_scb;
- p->free_scb = &(p->scb_array[scb->position]);
+ p->free_scb = scb;
scb->cmd = NULL;
restore_flags(flags);
@@ -1787,63 +1312,40 @@
struct aic7xxx_scb *scb,
insert_type where)
{
- unsigned char head, tail;
+ unsigned char head;
unsigned char curscb;
- curscb = inb(SCBPTR(base));
- head = inb(WAITING_SCBH(base));
- tail = inb(WAITING_SCBT(base));
+ curscb = inb(SCBPTR + base);
+ head = inb(WAITING_SCBH + base);
if (head == SCB_LIST_NULL)
{
/*
* List was empty
*/
head = scb->position;
- tail = SCB_LIST_NULL;
}
else
{
if (where == LIST_HEAD)
{
- outb(scb->position, SCBPTR(base));
- outb(head, SCBARRAY(base) + 30);
+ outb(scb->position, SCBPTR + base);
+ outb(head, SCB_NEXT_WAITING + base);
head = scb->position;
}
else
{
- if (tail == SCB_LIST_NULL)
- {
- /*
- * List had one element
- */
- tail = scb->position;
- outb(head, SCBPTR(base));
- outb(tail, SCBARRAY(base) + 30);
- }
- else
- {
- if (where == LIST_SECOND)
- {
- unsigned char third_scb;
+ /* where == LIST_SECOND */
+ unsigned char third_scb;
- outb(head, SCBPTR(base));
- third_scb = inb(SCBARRAY(base) + 30);
- outb(scb->position, SCBARRAY(base) + 30);
- outb(scb->position, SCBPTR(base));
- outb(third_scb, SCBARRAY(base) + 30);
- }
- else
- {
- outb(tail, SCBPTR(base));
- tail = scb->position;
- outb(tail, SCBARRAY(base) + 30);
- }
- }
+ outb(head, SCBPTR + base);
+ third_scb = inb(SCB_NEXT_WAITING + base);
+ outb(scb->position, SCB_NEXT_WAITING + base);
+ outb(scb->position, SCBPTR + base);
+ outb(third_scb, SCB_NEXT_WAITING + base);
}
}
- outb(head, WAITING_SCBH(base));
- outb(tail, WAITING_SCBT(base));
- outb(curscb, SCBPTR(base));
+ outb(head, WAITING_SCBH + base);
+ outb(curscb, SCBPTR + base);
}
/*+F*************************************************************************
@@ -1867,15 +1369,15 @@
* Select the SCB we want to abort and
* pull the next pointer out of it.
*/
- curscb = inb(SCBPTR(base));
- outb(scb->position, SCBPTR(base));
- next = inb(SCBARRAY(base) + 30);
+ curscb = inb(SCBPTR + base);
+ outb(scb->position, SCBPTR + base);
+ next = inb(SCB_NEXT_WAITING + base);
/*
* Clear the necessary fields
*/
- outb(SCB_NEEDDMA, SCBARRAY(base));
- outb(SCB_LIST_NULL, SCBARRAY(base) + 30);
+ outb(0, SCBARRAY + base);
+ outb(SCB_LIST_NULL, SCB_NEXT_WAITING + base);
aic7xxx_unbusy_target(target, channel, base);
/*
@@ -1886,22 +1388,22 @@
/*
* First in the list
*/
- outb(next, WAITING_SCBH(base));
+ outb(next, WAITING_SCBH + base);
}
else
{
/*
* Select the scb that pointed to us and update its next pointer.
*/
- outb(prev, SCBPTR(base));
- outb(next, SCBARRAY(base) + 30);
+ outb(prev, SCBPTR + base);
+ outb(next, SCB_NEXT_WAITING + base);
}
/*
- * Update the tale pointer
+ * Update the tail pointer
*/
- if (inb(WAITING_SCBT(base)) == scb->position)
+ if (inb(WAITING_SCBT + base) == scb->position)
{
- outb(prev, WAITING_SCBT(base));
+ outb(prev, WAITING_SCBT + base);
}
/*
@@ -1909,7 +1411,7 @@
* and inform the SCSI system that the command
* has been aborted.
*/
- outb(curscb, SCBPTR(base));
+ outb(curscb, SCBPTR + base);
scb->state |= SCB_ABORTED;
scb->cmd->result = (DID_RESET << 16);
aic7xxx_done(p, scb);
@@ -1942,7 +1444,7 @@
/*
* Restore this when we're done
*/
- active_scb = inb(SCBPTR(base));
+ active_scb = inb(SCBPTR + base);
#ifdef AIC7XXX_DEBUG_ABORT
printk ("aic7xxx: (reset_device) target/channel %d/%c, to_scb %d, "
@@ -1953,11 +1455,11 @@
*/
{
int saved_queue[AIC7XXX_MAXSCB];
- int queued = inb(QINCNT(base));
+ int queued = inb(QINCNT + base);
for (i = 0; i < (queued - found); i++)
{
- saved_queue[i] = inb(QINFIFO(base));
+ saved_queue[i] = inb(QINFIFO + base);
scb = &(p->scb_array[saved_queue[i]]);
if (aic7xxx_match_scb(scb, target, channel))
{
@@ -1967,8 +1469,8 @@
scb->state |= SCB_ABORTED;
scb->cmd->result = (DID_RESET << 16);
aic7xxx_done(p, scb);
- outb(scb->position, SCBPTR(base));
- outb(SCB_NEEDDMA, SCBARRAY(base));
+ outb(scb->position, SCBPTR + base);
+ outb(0, SCBARRAY + base);
i--;
found++;
}
@@ -1978,7 +1480,7 @@
*/
for (queued = 0; queued < i; queued++)
{
- outb(saved_queue[queued], QINFIFO(base));
+ outb(saved_queue[queued], QINFIFO + base);
}
}
@@ -1988,7 +1490,7 @@
{
unsigned char next, prev;
- next = inb(WAITING_SCBH(base)); /* Start at head of list. */
+ next = inb(WAITING_SCBH + base); /* Start at head of list. */
prev = SCB_LIST_NULL;
while (next != SCB_LIST_NULL)
@@ -2004,9 +1506,9 @@
}
else
{
- outb(scb->position, SCBPTR(base));
+ outb(scb->position, SCBPTR + base);
prev = next;
- next = inb(SCBARRAY(base) + 30);
+ next = inb(SCB_NEXT_WAITING + base);
}
}
}
@@ -2026,8 +1528,8 @@
* Ensure the target is "free"
*/
aic7xxx_unbusy_target(target, channel, base);
- outb(scb->position, SCBPTR(base));
- outb(SCB_NEEDDMA, SCBARRAY(base));
+ outb(scb->position, SCBPTR + base);
+ outb(0, SCBARRAY + base);
scb->state |= SCB_ABORTED;
scb->cmd->result = (DID_RESET << 16);
aic7xxx_done(p, scb);
@@ -2035,7 +1537,7 @@
}
}
- outb(active_scb, SCBPTR(base));
+ outb(active_scb, SCBPTR + base);
return (found);
}
@@ -2052,9 +1554,9 @@
#ifdef AIC7XXX_DEBUG_ABORT
printk ("aic7xxx: (reset_current_bus)\n");
#endif
- outb(SCSIRSTO, SCSISEQ(base));
+ outb(SCSIRSTO, SCSISEQ + base);
udelay(1000);
- outb(0, SCSISEQ(base));
+ outb(0, SCSISEQ + base);
}
/*+F*************************************************************************
@@ -2088,9 +1590,9 @@
{
p->needsdtr |= (p->needsdtr_copy & 0xFF00);
p->sdtr_pending &= 0x00FF;
- outb(0, HA_ACTIVE1(base));
- offset = HA_TARG_SCRATCH(base) + 8;
- offset_max = HA_TARG_SCRATCH(base) + 16;
+ outb(0, ACTIVE_B + base);
+ offset = TARG_SCRATCH + base + 8;
+ offset_max = TARG_SCRATCH + base + 16;
}
else
{
@@ -2098,20 +1600,20 @@
{
p->needsdtr = p->needsdtr_copy;
p->needwdtr = p->needwdtr_copy;
- p->sdtr_pending = 0;
- p->wdtr_pending = 0;
- outb(0, HA_ACTIVE0(base));
- outb(0, HA_ACTIVE1(base));
- offset = HA_TARG_SCRATCH(base);
- offset_max = HA_TARG_SCRATCH(base) + 16;
+ p->sdtr_pending = 0x0;
+ p->wdtr_pending = 0x0;
+ outb(0, ACTIVE_A + base);
+ outb(0, ACTIVE_B + base);
+ offset = TARG_SCRATCH + base;
+ offset_max = TARG_SCRATCH + base + 16;
}
else
{
p->needsdtr |= (p->needsdtr_copy & 0x00FF);
p->sdtr_pending &= 0xFF00;
- outb(0, HA_ACTIVE0(base));
- offset = HA_TARG_SCRATCH(base);
- offset_max = HA_TARG_SCRATCH(base) + 8;
+ outb(0, ACTIVE_A + base);
+ offset = TARG_SCRATCH + base;
+ offset_max = TARG_SCRATCH + base + 8;
}
}
while (offset < offset_max)
@@ -2134,7 +1636,7 @@
/*
* Case 1: Command for another bus is active
*/
- sblkctl = inb(SBLKCTL(base));
+ sblkctl = inb(SBLKCTL + base);
cur_channel = (sblkctl & SELBUSB) ? 'B' : 'A';
if (cur_channel != channel)
{
@@ -2145,9 +1647,9 @@
/*
* Stealthily reset the other bus without upsetting the current bus
*/
- outb(sblkctl ^ SELBUSB, SBLKCTL(base));
+ outb(sblkctl ^ SELBUSB, SBLKCTL + base);
aic7xxx_reset_current_bus(base);
- outb(sblkctl, SBLKCTL(base));
+ outb(sblkctl, SBLKCTL + base);
UNPAUSE_SEQUENCER(p);
}
@@ -2183,11 +1685,12 @@
int base, intstat;
struct aic7xxx_host *p;
struct aic7xxx_scb *scb;
- unsigned char ha_flags, transfer;
+ unsigned char ha_flags;
+ short transfer;
unsigned char scsi_id, bus_width;
unsigned char offset, rate, scratch, scratch_offset;
unsigned char max_offset, rej_byte;
- unsigned short target_mask, active;
+ unsigned short target_mask;
char channel;
void *addr;
int actual;
@@ -2200,7 +1703,7 @@
* Search for the host with a pending interrupt. If we can't find
* one, then we've encountered a spurious interrupt.
*/
- while ((p != NULL) && !(inb(INTSTAT(p->base)) & INT_PEND))
+ while ((p != NULL) && !(inb(INTSTAT + p->base) & INT_PEND))
{
if (p->next == NULL)
{
@@ -2235,7 +1738,7 @@
*/
p->isr_count++;
- if ((p->a_scanned == 0) && (p->isr_count == 1))
+ if (!p->a_scanned && (p->isr_count == 1))
{
/*
* We must only have one card at this IRQ and it must have been
@@ -2252,12 +1755,12 @@
* Handle all the interrupt sources - especially for SCSI
* interrupts, we won't get a second chance at them.
*/
- intstat = inb(INTSTAT(base));
+ intstat = inb(INTSTAT + base);
if (intstat & BRKADRINT)
{
int i;
- unsigned char errno = inb(ERROR(base));
+ unsigned char errno = inb(ERROR + base);
printk("aic7xxx: (aic7xxx_isr) BRKADRINT error(0x%x):\n", errno);
for (i = 0; i < NUMBER(hard_error); i++)
@@ -2269,7 +1772,7 @@
}
panic("aic7xxx: (aic7xxx_isr) BRKADRINT, error(0x%x) seqaddr(0x%x).\n",
- inb(ERROR(base)), (inb(SEQADDR1(base)) << 8) | inb(SEQADDR0(base)));
+ inb(ERROR + base), (inb(SEQADDR1 + base) << 8) | inb(SEQADDR0 + base));
}
if (intstat & SEQINT)
@@ -2281,10 +1784,10 @@
*/
PAUSE_SEQUENCER(p);
- scsi_id = (inb(SCSIID(base)) >> 4) & 0x0F;
+ scsi_id = (inb(SCSIID + base) >> 4) & 0x0F;
scratch_offset = scsi_id;
channel = 'A';
- if (inb(SBLKCTL(base)) & SELBUSB)
+ if (inb(SBLKCTL + base) & SELBUSB)
{
channel = 'B';
scratch_offset += 8;
@@ -2298,50 +1801,50 @@
break;
case SEND_REJECT:
- rej_byte = inb(HA_REJBYTE(base));
- if (rej_byte != 0x20)
- {
- debug("aic7xxx: Warning - Issuing message reject, 1st byte(0x%x)\n",
- rej_byte);
- }
- else
+ rej_byte = inb(REJBYTE + base);
+ if ((rej_byte & 0xF0) == 0x20)
{
- scb_index = inb(SCBPTR(base));
+ scb_index = inb(SCBPTR + base);
scb = &(p->scb_array[scb_index]);
- printk("aic7xxx: Warning - Tagged message rejected for target %d,"
- " channel %c.\n", scsi_id, channel);
+ printk("aic7xxx: Warning - Tagged message received without identify."
+ "Disabling tagged commands for target %d channel %c.\n",
+ scsi_id, channel);
scb->cmd->device->tagged_supported = 0;
scb->cmd->device->tagged_queue = 0;
}
+ else
+ {
+ debug("aic7xxx: Warning - Rejecting unknown message (0x%x) received "
+ "from target %d channel %c.\n", rej_byte, scsi_id, channel);
+ }
break;
case NO_IDENT:
panic("aic7xxx: Target %d, channel %c, did not send an IDENTIFY "
"message. SAVED_TCL(0x%x).\n",
- scsi_id, channel, inb(SAVED_TCL(base)));
+ scsi_id, channel, inb(SAVED_TCL + base));
break;
case NO_MATCH:
printk("aic7xxx: No active SCB for reconnecting target %d, "
"channel %c - Issuing ABORT. SAVED_TCL(0x%x).\n",
- scsi_id, channel, inb(SAVED_TCL(base)));
+ scsi_id, channel, inb(SAVED_TCL + base));
aic7xxx_unbusy_target(scsi_id, channel, base);
- outb(SCB_NEEDDMA, SCBARRAY(base));
-
- outb(CLRSELTIMEO, CLRSINT1(base));
+ outb(0, SCBARRAY + base);
+ outb(CLRSELTIMEO, CLRSINT1 + base);
RESTART_SEQUENCER(p);
break;
- case MSG_SDTR:
+ case SDTR_MSG:
/*
* Help the sequencer to translate the negotiated
* transfer rate. Transfer is 1/4 the period
* in ns as is returned by the sync negotiation
* message. So, we must multiply by four.
*/
- transfer = (inb(HA_ARG_1(base)) << 2);
- offset = inb(ACCUM(base));
- scratch = inb(HA_TARG_SCRATCH(base) + scratch_offset);
+ transfer = (inb(ARG_1 + base) << 2);
+ offset = inb(ACCUM + base);
+ scratch = inb(TARG_SCRATCH + base + scratch_offset);
/*
* The maximum offset for a wide device is 0x08; for a
* 8-bit bus device the maximum offset is 0x0F.
@@ -2354,13 +1857,14 @@
{
max_offset = 0x0F;
}
- aic7xxx_scsirate(p, &rate, transfer, MIN(offset, max_offset), scsi_id, channel);
+ aic7xxx_scsirate(p, &rate, transfer, MIN(offset, max_offset),
+ scsi_id, channel);
/*
* Preserve the wide transfer flag.
*/
scratch = rate | (scratch & WIDEXFER);
- outb(scratch, HA_TARG_SCRATCH(base) + scratch_offset);
- outb(scratch, SCSIRATE(base));
+ outb(scratch, TARG_SCRATCH + base + scratch_offset);
+ outb(scratch, SCSIRATE + base);
if ((scratch & 0x0F) == 0)
{ /*
* The requested rate was so low that asynchronous transfers
@@ -2368,7 +1872,7 @@
* them), so we issue a reject to ensure we go to asynchronous
* transfers.
*/
- outb(SEND_REJ, HA_RETURN_1(base));
+ outb(SEND_REJ, RETURN_1 + base);
}
else
{
@@ -2380,7 +1884,7 @@
/*
* Don't send an SDTR back to the target.
*/
- outb(0, HA_RETURN_1(base));
+ outb(0, RETURN_1 + base);
}
else
{
@@ -2388,7 +1892,7 @@
* Send our own SDTR in reply.
*/
printk("aic7xxx: Sending SDTR!!\n");
- outb(SEND_SDTR, HA_RETURN_1(base));
+ outb(SEND_SDTR, RETURN_1 + base);
}
}
/*
@@ -2396,27 +1900,21 @@
*/
p->needsdtr &= ~target_mask;
p->sdtr_pending &= ~target_mask;
-#if 0
- scb_index = inb(SCBPTR(base));
- scb = &(p->scb_array[scb_index]);
- debug_scb(scb);
-#endif
-
break;
- case MSG_WDTR:
+ case WDTR_MSG:
{
- bus_width = inb(ACCUM(base));
+ bus_width = inb(ARG_1 + base);
printk("aic7xxx: Received MSG_WDTR, Target %d, channel %c "
"needwdtr(0x%x).\n", scsi_id, channel, p->needwdtr);
- scratch = inb(HA_TARG_SCRATCH(base) + scratch_offset);
+ scratch = inb(TARG_SCRATCH + base + scratch_offset);
if (p->wdtr_pending & target_mask)
{
/*
* Don't send an WDTR back to the target, since we asked first.
*/
- outb(0, HA_RETURN_1(base));
+ outb(0, RETURN_1 + base);
switch (bus_width)
{
case BUS_8_BIT:
@@ -2428,6 +1926,12 @@
"transfers.\n", scsi_id, channel);
scratch |= 0x80;
break;
+
+ case BUS_32_BIT:
+ outb(SEND_REJ, RETURN_1 + base);
+ printk("aic7xxx: Target %d, channel %c, requesting 32 bit "
+ "transfers, rejecting...\n", scsi_id, channel);
+ break;
}
}
else
@@ -2455,16 +1959,16 @@
scratch |= 0x80;
break;
}
- outb(bus_width | SEND_WDTR, HA_RETURN_1(base));
+ outb(bus_width | SEND_WDTR, RETURN_1 + base);
}
p->needwdtr &= ~target_mask;
p->wdtr_pending &= ~target_mask;
- outb(scratch, HA_TARG_SCRATCH(base) + scratch_offset);
- outb(scratch, SCSIRATE(base));
+ outb(scratch, TARG_SCRATCH + base + scratch_offset);
+ outb(scratch, SCSIRATE + base);
break;
}
- case MSG_REJECT:
+ case REJECT_MSG:
{
/*
* What we care about here is if we had an
@@ -2473,7 +1977,7 @@
* the target is refusing negotiation.
*/
- scratch = inb(HA_TARG_SCRATCH(base) + scratch_offset);
+ scratch = inb(TARG_SCRATCH + base + scratch_offset);
if (p->wdtr_pending & target_mask)
{
@@ -2483,7 +1987,6 @@
scratch &= 0x7F;
p->needwdtr &= ~target_mask;
p->wdtr_pending &= ~target_mask;
- outb(scratch, HA_TARG_SCRATCH(base) + scratch_offset);
printk("aic7xxx: Target %d, channel %c, refusing WIDE negotiation. "
"Using 8 bit transfers.\n", scsi_id, channel);
}
@@ -2497,7 +2000,6 @@
scratch &= 0xF0;
p->needsdtr &= ~target_mask;
p->sdtr_pending &= ~target_mask;
- outb(scratch, HA_TARG_SCRATCH(base) + scratch_offset);
printk("aic7xxx: Target %d, channel %c, refusing synchronous "
"negotiation. Using asynchronous transfers.\n",
scsi_id, channel);
@@ -2506,16 +2008,16 @@
* Otherwise, we ignore it.
*/
}
- outb(scratch, HA_TARG_SCRATCH(base) + scratch_offset);
- outb(scratch, SCSIRATE(base));
+ outb(scratch, TARG_SCRATCH + base + scratch_offset);
+ outb(scratch, SCSIRATE + base);
break;
}
case BAD_STATUS:
- scb_index = inb(SCBPTR(base));
+ scb_index = inb(SCBPTR + base);
scb = &(p->scb_array[scb_index]);
- outb(0, HA_RETURN_1(base)); /* CHECK_CONDITION may change this */
- if ((scb->state != SCB_ACTIVE) || (scb->cmd == NULL))
+ outb(0, RETURN_1 + base); /* CHECK_CONDITION may change this */
+ if (!(scb->state & SCB_ACTIVE) || (scb->cmd == NULL))
{
printk("aic7xxx: Referenced SCB not valid during SEQINT(0x%x) "
"scb(%d) state(0x%x) cmd(0x%x).\n",
@@ -2524,7 +2026,7 @@
else
{
cmd = scb->cmd;
- aic7xxx_getscb(base, scb);
+ aic7xxx_getscb(p, scb);
aic7xxx_status(cmd) = scb->target_status;
cmd->result |= scb->target_status;
@@ -2543,6 +2045,7 @@
void *req_buf;
tcl = scb->target_channel_lun;
+
/*
* Send a sense command to the requesting target.
*/
@@ -2558,8 +2061,9 @@
req_buf = &scb->sense_sg;
cmd->cmd_len = COMMAND_SIZE(cmd->cmnd[0]);
control = scb->control;
- memset(scb, 0, SCB_DOWNLOAD_SIZE);
- scb->control = control & SCB_DISCENB;
+
+ memset(scb, 0, SCB_PIO_TRANSFER_SIZE);
+ scb->control = control & DISCENB;
scb->target_channel_lun = tcl;
addr = scb->sense_cmd;
scb->SCSI_cmd_length = COMMAND_SIZE(scb->sense_cmd[0]);
@@ -2568,41 +2072,26 @@
scb->SG_segment_count = 1;
memcpy(scb->SG_list_pointer, &req_buf,
sizeof(scb->SG_list_pointer));
- scb->data_count[0] = scb->sense_sg.length & 0xFF;
- scb->data_count[1] = (scb->sense_sg.length >> 8) & 0xFF;
- scb->data_count[2] = (scb->sense_sg.length >> 16) & 0xFF;
+ scb->data_count = scb->sense_sg.length;
memcpy(scb->data_pointer, &(scb->sense_sg.address), 4);
- outb(SCBAUTO, SCBCNT(base));
- asm volatile("cld\n\t"
- "rep\n\t"
- "outsb"
- : /* no output */
- :"S" (scb), "c" (SCB_DOWNLOAD_SIZE), "d" (SCBARRAY(base))
- :"si", "cx", "dx");
- outb(0, SCBCNT(base));
- outb(SCB_LIST_NULL, (SCBARRAY(base) + 30));
+ aic7xxx_putscb(p, scb);
+ outb(SCB_LIST_NULL, SCB_NEXT_WAITING + base);
/*
* Ensure that the target is "BUSY" so we don't get overlapping
* commands if we happen to be doing tagged I/O.
*/
- active = inb(HA_ACTIVE0(base)) | (inb(HA_ACTIVE1(base)) << 8);
- active |= target_mask;
- outb(active & 0xFF, HA_ACTIVE0(base));
- outb((active >> 8) & 0xFF, HA_ACTIVE1(base));
+ aic7xxx_busy_target(scsi_id, channel, base);
aic7xxx_add_waiting_scb(base, scb, LIST_HEAD);
- outb(SEND_SENSE, HA_RETURN_1(base));
+ outb(SEND_SENSE, RETURN_1 + base);
} /* first time sense, no errors */
- else
- {
- /*
- * Indicate that we asked for sense, have the sequencer do
- * a normal command complete, and have the scsi driver handle
- * this condition.
- */
- cmd->flags |= ASKED_FOR_SENSE;
- }
+
+ cmd->flags &= ~ASKED_FOR_SENSE;
+ if (aic7xxx_error(cmd) == 0)
+ {
+ aic7xxx_error(cmd) = DID_RETRY_COMMAND;
+ }
break;
case BUSY:
@@ -2634,9 +2123,9 @@
break;
case RESIDUAL:
- scb_index = inb(SCBPTR(base));
+ scb_index = inb(SCBPTR + base);
scb = &(p->scb_array[scb_index]);
- if ((scb->state != SCB_ACTIVE) || (scb->cmd == NULL))
+ if (!(scb->state & SCB_ACTIVE) || (scb->cmd == NULL))
{
printk("aic7xxx: Referenced SCB not valid during SEQINT(0x%x) "
"scb(%d) state(0x%x) cmd(0x%x).\n",
@@ -2659,16 +2148,16 @@
*/
actual = aic7xxx_length(cmd, scb->residual_SG_segment_count);
- actual -= ((inb(SCBARRAY(base + 17)) << 16) |
- (inb(SCBARRAY(base + 16)) << 8) |
- inb(SCBARRAY(base + 15)));
+ actual -= (inb(SCB_RESID_DCNT2 + base) << 16) |
+ (inb(SCB_RESID_DCNT1 + base) << 8) |
+ inb(SCB_RESID_DCNT0 + base);
if (actual < cmd->underflow)
{
printk("aic7xxx: Target %d underflow - "
"Wanted (at least) (%u) got(%u) count(%d).\n",
cmd->target, cmd->underflow, actual,
- inb(SCBARRAY(base + 18)));
+ inb(SCB_RESID_SGCNT + base));
aic7xxx_error(cmd) = DID_RETRY_COMMAND;
aic7xxx_status(cmd) = scb->target_status;
}
@@ -2677,9 +2166,9 @@
break;
case ABORT_TAG:
- scb_index = inb(SCBPTR(base));
+ scb_index = inb(SCBPTR + base);
scb = &(p->scb_array[scb_index]);
- if ((scb->state != SCB_ACTIVE) || (scb->cmd == NULL))
+ if (!(scb->state & SCB_ACTIVE) || (scb->cmd == NULL))
{
printk("aic7xxx: Referenced SCB not valid during SEQINT(0x%x) "
"scb(%d) state(0x%x) cmd(0x%x)\n",
@@ -2702,9 +2191,9 @@
break;
case AWAITING_MSG:
- scb_index = inb(SCBPTR(base));
+ scb_index = inb(SCBPTR + base);
scb = &(p->scb_array[scb_index]);
- if ((scb->state != SCB_ACTIVE) || (scb->cmd == NULL))
+ if (!(scb->state & SCB_ACTIVE) || (scb->cmd == NULL))
{
printk("aic7xxx: Referenced SCB not valid during SEQINT(0x%x) "
"scb(%d) state(0x%x) cmd(0x%x).\n",
@@ -2723,8 +2212,8 @@
printk ("aic7xxx: (isr) sending bus device reset to target %d\n",
scsi_id);
#endif
- outb(MSG_BUS_DEVICE_RESET, HA_MSG_START(base));
- outb(1, HA_MSG_LEN(base));
+ outb(MSG_BUS_DEVICE_RESET, MSG0 + base);
+ outb(1, MSG_LEN + base);
}
else
{
@@ -2735,7 +2224,7 @@
break;
case IMMEDDONE:
- scb_index = inb(SCBPTR(base));
+ scb_index = inb(SCBPTR + base);
scb = &(p->scb_array[scb_index]);
#ifdef AIC7XXX_DEBUG_ABORT
printk ("aic7xxx: (isr) received IMMEDDONE for target %d, scb %d, state %d\n",
@@ -2753,9 +2242,9 @@
p->needwdtr |= (p->needwdtr_copy & target_mask);
p->sdtr_pending &= ~target_mask;
p->wdtr_pending &= ~target_mask;
- scratch = inb(HA_TARG_SCRATCH(base) + scratch_offset);
+ scratch = inb(TARG_SCRATCH + base + scratch_offset);
scratch &= SXFR;
- outb(scratch, HA_TARG_SCRATCH(base));
+ outb(scratch, TARG_SCRATCH + base + scratch_offset);
found = aic7xxx_reset_device(p, (int) scsi_id, channel, SCB_LIST_NULL);
}
else
@@ -2764,22 +2253,112 @@
}
break;
+#if AIC7XXX_NOT_YET
+ /* XXX Fill these in later */
+ case MESG_BUFFER_BUSY:
+ break;
+ case MSGIN_PHASEMIS:
+ break;
+#endif
+
+ case PARITY_ERROR:
+ {
+ scb_index = inb(SCBPTR + base);
+ scb = &(p->scb_array[scb_index]);
+ if (!(scb->state & SCB_ACTIVE) || (scb->cmd == NULL))
+ {
+ printk("aic7xxx: Referenced SCB not valid during SEQINT(0x%x) "
+ "scb(%d) state(0x%x) cmd(0x%x).\n",
+ intstat, scb_index, scb->state, (unsigned int) scb->cmd);
+ }
+ else
+ {
+ char *phase;
+ unsigned char mesg_out = MSG_NOP;
+ unsigned char lastphase = inb(LASTPHASE + base);
+
+ cmd = scb->cmd;
+ switch (lastphase)
+ {
+ case P_DATAOUT:
+ phase = "Data-Out";
+ break;
+ case P_DATAIN:
+ phase = "Data-In";
+ mesg_out = MSG_INITIATOR_DET_ERROR;
+ break;
+ case P_COMMAND:
+ phase = "Command";
+ break;
+ case P_MESGOUT:
+ phase = "Message-Out";
+ break;
+ case P_STATUS:
+ phase = "Status";
+ mesg_out = MSG_INITIATOR_DET_ERROR;
+ break;
+ case P_MESGIN:
+ phase = "Message-In";
+ mesg_out = MSG_MSG_PARITY_ERROR;
+ break;
+ default:
+ phase = "unknown";
+ break;
+ }
+
+ /*
+ * A parity error has occurred during a data
+ * transfer phase. Flag it and continue.
+ */
+ printk("aic7xxx: Parity error during phase %s on target %d, "
+ "channel %d, lun %d.\n", phase,
+ cmd->target, cmd->channel & 0x01, cmd->lun & 0x07);
+
+ /*
+ * We've set the hardware to assert ATN if we get a parity
+ * error on "in" phases, so all we need to do is stuff the
+ * message buffer with the appropriate message. In phases
+ * have set mesg_out to something other than MSG_NOP.
+ */
+ if (mesg_out != MSG_NOP)
+ {
+ outb(mesg_out, MSG0 + base);
+ outb(1, MSG_LEN + base);
+ aic7xxx_error(cmd) = DID_PARITY;
+ }
+ else
+ {
+ /*
+ * Should we allow the target to make this decision for us?
+ */
+ aic7xxx_error(cmd) = DID_RETRY_COMMAND;
+ }
+ }
+ break;
+ }
default: /* unknown */
debug("aic7xxx: SEQINT, INTSTAT(0x%x) SCSISIGI(0x%x).\n",
- intstat, inb(SCSISIGI(base)));
+ intstat, inb(SCSISIGI + base));
break;
}
- outb(CLRSEQINT, CLRINT(base));
+
+ outb(CLRSEQINT, CLRINT + base);
UNPAUSE_SEQUENCER(p);
}
if (intstat & SCSIINT)
{
- int status = inb(SSTAT1(base));
+ int status = inb(SSTAT1 + base);
+ scsi_id = (inb(SCSIID + base) >> 4) & 0x0F;
+ channel = 'A';
+ if (inb(SBLKCTL + base) & SELBUSB)
+ {
+ channel = 'B';
+ }
- scb_index = inb(SCBPTR(base));
+ scb_index = inb(SCBPTR + base);
scb = &(p->scb_array[scb_index]);
- if ((scb->state != SCB_ACTIVE) || (scb->cmd == NULL))
+ if (!(scb->state & SCB_ACTIVE) || (scb->cmd == NULL))
{
printk("aic7xxx: No command for SCB (SCSIINT).\n");
/*
@@ -2787,10 +2366,9 @@
* to zero, so that it falls through the
* reset of the SCSIINT code.
*/
- outb(status, CLRSINT1(base));
+ outb(status, CLRSINT1 + base);
UNPAUSE_SEQUENCER(p);
- outb(CLRSCSIINT, CLRINT(base));
- status = 0;
+ outb(CLRSCSIINT, CLRINT + base);
scb = NULL;
}
else
@@ -2806,36 +2384,23 @@
*/
if (status & SELTO)
{
- unsigned char target_mask = (1 << (cmd->target & 0x07));
unsigned char waiting;
/*
* Hardware selection timer has expired. Turn
* off SCSI selection sequence.
*/
- outb(ENRSELI, SCSISEQ(base));
+ outb(ENRSELI, SCSISEQ + base);
cmd->result = (DID_TIME_OUT << 16);
/*
* Clear an pending messages for the timed out
* target and mark the target as free.
*/
- ha_flags = inb(HA_FLAGS(base));
- outb(ha_flags & ~ACTIVE_MSG, HA_FLAGS(base));
-
- if (scb->target_channel_lun & 0x88)
- {
- active = inb(HA_ACTIVE1(base));
- active = active & ~(target_mask);
- outb(active, HA_ACTIVE1(base));
- }
- else
- {
- active = inb(HA_ACTIVE0(base));
- active &= ~(target_mask);
- outb(active, HA_ACTIVE0(base));
- }
+ ha_flags = inb(FLAGS + base);
+ outb(0, MSG_LEN + base);
+ aic7xxx_unbusy_target(scsi_id, channel, base);
- outb(SCB_NEEDDMA, SCBARRAY(base));
+ outb(0, SCBARRAY + base);
/*
* Shut off the offending interrupt sources, reset
@@ -2852,17 +2417,17 @@
* with an Illegal Host Address status, so the
* sequencer has to be restarted first.
*/
- outb(CLRSELTIMEO, CLRSINT1(base));
+ outb(CLRSELTIMEO, CLRSINT1 + base);
- outb(CLRSCSIINT, CLRINT(base));
+ outb(CLRSCSIINT, CLRINT + base);
/*
* Shift the waiting for selection queue forward
*/
- waiting = inb(WAITING_SCBH(base));
- outb(waiting, SCBPTR(base));
- waiting = inb(SCBARRAY(base) + 30);
- outb(waiting, WAITING_SCBH(base));
+ waiting = inb(WAITING_SCBH + base);
+ outb(waiting, SCBPTR + base);
+ waiting = inb(SCB_NEXT_WAITING + base);
+ outb(waiting, WAITING_SCBH + base);
RESTART_SEQUENCER(p);
aic7xxx_done(p, scb);
@@ -2873,40 +2438,17 @@
}
else
{
- if (status & SCSIPERR)
- {
- /*
- * A parity error has occurred during a data
- * transfer phase. Flag it and continue.
- */
- printk("aic7xxx: Parity error on target %d, channel %d, lun %d.\n",
- cmd->target, cmd->channel & 0x01, cmd->lun & 0x07);
- aic7xxx_error(cmd) = DID_PARITY;
-
- /*
- * Clear interrupt and resume as above.
- */
- outb(CLRSCSIPERR, CLRSINT1(base));
- UNPAUSE_SEQUENCER(p);
-
- outb(CLRSCSIINT, CLRINT(base));
- scb = NULL;
- }
- else
- {
- if (!(status & BUSFREE))
- {
- /*
- * We don't know what's going on. Turn off the
- * interrupt source and try to continue.
- */
- printk("aic7xxx: SSTAT1(0x%x).\n", status);
- outb(status, CLRSINT1(base));
- UNPAUSE_SEQUENCER(p);
- outb(CLRSCSIINT, CLRINT(base));
- scb = NULL;
- }
- }
+ if (!(status & BUSFREE))
+ {
+ /*
+ * We don't know what's going on. Turn off the
+ * interrupt source and try to continue.
+ */
+ printk("aic7xxx: SSTAT1(0x%x).\n", status);
+ outb(status, CLRSINT1 + base);
+ UNPAUSE_SEQUENCER(p);
+ outb(CLRSCSIINT, CLRINT + base);
+ }
}
} /* else */
}
@@ -2921,21 +2463,20 @@
* finished, so loop until we've processed them all.
*/
do {
- complete = inb(QOUTFIFO(base));
+ complete = inb(QOUTFIFO + base);
scb = &(p->scb_array[complete]);
- if ((scb->state != SCB_ACTIVE) || (scb->cmd == NULL))
+ if (!(scb->state & SCB_ACTIVE) || (scb->cmd == NULL))
{
printk("aic7xxx: Warning - No command for SCB %d (CMDCMPLT).\n"
" QOUTCNT(%d) SCB state(0x%x) cmd(0x%x) pos(%d).\n",
- complete, inb(QOUTFIFO(base)),
+ complete, inb(QOUTFIFO + base),
scb->state, (unsigned int) scb->cmd, scb->position);
- outb(CLRCMDINT, CLRINT(base));
+ outb(CLRCMDINT, CLRINT + base);
continue;
}
cmd = scb->cmd;
- cmd->result = (aic7xxx_error(cmd) << 16) | aic7xxx_status(cmd);
if ((cmd->flags & WAS_SENSE) && !(cmd->flags & ASKED_FOR_SENSE))
{
/*
@@ -2957,7 +2498,7 @@
* command being complete never made it back
* up to the kernel.
*/
- outb(CLRCMDINT, CLRINT(base));
+ outb(CLRCMDINT, CLRINT + base);
aic7xxx_done(p, scb);
#if 0
if (scb != &p->scb_array[scb->position])
@@ -2974,7 +2515,7 @@
* XXX: for each command, but apparently that's too difficult.
*/
actual = aic7xxx_length(cmd, 0);
- if (((cmd->flags & WAS_SENSE) == 0) && (actual > 0))
+ if (!(cmd->flags & WAS_SENSE) && (actual > 0))
{
struct aic7xxx_xferstats *sp;
long *ptr;
@@ -3010,7 +2551,7 @@
}
#endif /* AIC7XXX_PROC_STATS */
- } while (inb(QOUTCNT(base)));
+ } while (inb(QOUTCNT + base));
}
}
@@ -3118,11 +2659,11 @@
struct seeprom_cmd seeprom_read = {3, {1, 1, 0}};
#define CLOCK_PULSE(p) \
- while ((inb(STATUS_2840(base)) & EEPROM_TF) == 0) \
+ while ((inb(STATUS_2840 + base) & EEPROM_TF) == 0) \
{ \
; /* Do nothing */ \
} \
- (void) inb(SEECTL_2840(base));
+ (void) inb(SEECTL_2840 + base);
/*
* Read the first 32 registers of the seeprom. For the 2840,
@@ -3135,7 +2676,7 @@
/*
* Send chip select for one clock cycle.
*/
- outb(CK_2840 | CS_2840, SEECTL_2840(base));
+ outb(CK_2840 | CS_2840, SEECTL_2840 + base);
CLOCK_PULSE(base);
/*
@@ -3145,10 +2686,10 @@
for (i = 0; i < seeprom_read.len; i++)
{
temp = CS_2840 | seeprom_read.bits[i];
- outb(temp, SEECTL_2840(base));
+ outb(temp, SEECTL_2840 + base);
CLOCK_PULSE(base);
temp = temp ^ CK_2840;
- outb(temp, SEECTL_2840(base));
+ outb(temp, SEECTL_2840 + base);
CLOCK_PULSE(base);
}
/*
@@ -3159,10 +2700,10 @@
temp = k;
temp = (temp >> i) & 1; /* Mask out all but lower bit. */
temp = CS_2840 | temp;
- outb(temp, SEECTL_2840(base));
+ outb(temp, SEECTL_2840 + base);
CLOCK_PULSE(base);
temp = temp ^ CK_2840;
- outb(temp, SEECTL_2840(base));
+ outb(temp, SEECTL_2840 + base);
CLOCK_PULSE(base);
}
@@ -3175,11 +2716,11 @@
for (i = 0; i <= 16; i++)
{
temp = CS_2840;
- outb(temp, SEECTL_2840(base));
+ outb(temp, SEECTL_2840 + base);
CLOCK_PULSE(base);
temp = temp ^ CK_2840;
- seeprom[k] = (seeprom[k] << 1) | (inb(STATUS_2840(base)) & DI_2840);
- outb(temp, SEECTL_2840(base));
+ seeprom[k] = (seeprom[k] << 1) | (inb(STATUS_2840 + base) & DI_2840);
+ outb(temp, SEECTL_2840 + base);
CLOCK_PULSE(base);
}
/*
@@ -3196,11 +2737,11 @@
/*
* Reset the chip select for the next command cycle.
*/
- outb(0, SEECTL_2840(base));
+ outb(0, SEECTL_2840 + base);
CLOCK_PULSE(base);
- outb(CK_2840, SEECTL_2840(base));
+ outb(CK_2840, SEECTL_2840 + base);
CLOCK_PULSE(base);
- outb(0, SEECTL_2840(base));
+ outb(0, SEECTL_2840 + base);
CLOCK_PULSE(base);
}
@@ -3292,7 +2833,7 @@
struct seeprom_cmd seeprom_read = {3, {1, 1, 0}};
#define CLOCK_PULSE(p) \
- while ((inb(SEECTL(base)) & SEERDY) == 0) \
+ while ((inb(SEECTL + base) & SEERDY) == 0) \
{ \
; /* Do nothing */ \
}
@@ -3304,15 +2845,15 @@
* is needed. Reason: after the 7870 chip reset, there
* should be no contention.
*/
- outb(SEEMS, SEECTL(base));
+ outb(SEEMS, SEECTL + base);
timeout = jiffies + 100; /* 1 second timeout */
- while ((jiffies < timeout) && ((inb(SEECTL(base)) & SEERDY) == 0))
+ while ((jiffies < timeout) && ((inb(SEECTL + base) & SEERDY) == 0))
{
; /* Do nothing! Wait for access to be granted. */
}
- if ((inb(SEECTL(base)) & SEERDY) == 0)
+ if ((inb(SEECTL + base) & SEERDY) == 0)
{
- outb(0, SEECTL(base));
+ outb(0, SEECTL + base);
return (0);
}
@@ -3327,7 +2868,7 @@
/*
* Send chip select for one clock cycle.
*/
- outb(SEEMS | SEECK | SEECS, SEECTL(base));
+ outb(SEEMS | SEECK | SEECS, SEECTL + base);
CLOCK_PULSE(base);
/*
@@ -3337,10 +2878,10 @@
for (i = 0; i < seeprom_read.len; i++)
{
temp = SEEMS | SEECS | (seeprom_read.bits[i] << 1);
- outb(temp, SEECTL(base));
+ outb(temp, SEECTL + base);
CLOCK_PULSE(base);
temp = temp ^ SEECK;
- outb(temp, SEECTL(base));
+ outb(temp, SEECTL + base);
CLOCK_PULSE(base);
}
/*
@@ -3351,10 +2892,10 @@
temp = k + offset;
temp = (temp >> i) & 1; /* Mask out all but lower bit. */
temp = SEEMS | SEECS | (temp << 1);
- outb(temp, SEECTL(base));
+ outb(temp, SEECTL + base);
CLOCK_PULSE(base);
temp = temp ^ SEECK;
- outb(temp, SEECTL(base));
+ outb(temp, SEECTL + base);
CLOCK_PULSE(base);
}
@@ -3367,11 +2908,11 @@
for (i = 0; i <= 16; i++)
{
temp = SEEMS | SEECS;
- outb(temp, SEECTL(base));
+ outb(temp, SEECTL + base);
CLOCK_PULSE(base);
temp = temp ^ SEECK;
- seeprom[k] = (seeprom[k] << 1) | (inb(SEECTL(base)) & SEEDI);
- outb(temp, SEECTL(base));
+ seeprom[k] = (seeprom[k] << 1) | (inb(SEECTL + base) & SEEDI);
+ outb(temp, SEECTL + base);
CLOCK_PULSE(base);
}
@@ -3389,18 +2930,18 @@
/*
* Reset the chip select for the next command cycle.
*/
- outb(SEEMS, SEECTL(base));
+ outb(SEEMS, SEECTL + base);
CLOCK_PULSE(base);
- outb(SEEMS | SEECK, SEECTL(base));
+ outb(SEEMS | SEECK, SEECTL + base);
CLOCK_PULSE(base);
- outb(SEEMS, SEECTL(base));
+ outb(SEEMS, SEECTL + base);
CLOCK_PULSE(base);
}
/*
* Release access to the memory port and the serial EEPROM.
*/
- outb(0, SEECTL(base));
+ outb(0, SEECTL + base);
#if 0
printk("Computed checksum 0x%x, checksum read 0x%x\n", checksum, sc->checksum);
@@ -3451,22 +2992,22 @@
* we limit them, along with the Rev C chips, to 4 SCBs.
*
* The Rev E boards have a read/write autoflush bit in the
- * SBLKCTL registor, while in the Rev C boards it is read only.
+ * SBLKCTL register, while in the Rev C boards it is read only.
*/
- sblkctl_reg = inb(SBLKCTL(base)) ^ AUTOFLUSHDIS;
- outb(sblkctl_reg, SBLKCTL(base));
- if (inb(SBLKCTL(base)) == sblkctl_reg)
+ sblkctl_reg = inb(SBLKCTL + base) ^ AUTOFLUSHDIS;
+ outb(sblkctl_reg, SBLKCTL + base);
+ if (inb(SBLKCTL + base) == sblkctl_reg)
{
/*
* We detected a Rev E board.
*/
- printk("aic7770: Rev E and subsequent; using 4 SCB's.\n");
- outb(sblkctl_reg ^ AUTOFLUSHDIS, SBLKCTL(base));
+ printk("aic7xxx: %s Rev E and subsequent.\n", board_names[type]);
+ outb(sblkctl_reg ^ AUTOFLUSHDIS, SBLKCTL + base);
maxscb = 4;
}
else
{
- printk("aic7770: Rev C and previous; using 4 SCB's.\n");
+ printk("aic7xxx: %s Rev C and previous.\n", board_names[type]);
maxscb = 4;
}
break;
@@ -3501,6 +3042,7 @@
*/
break;
}
+
if (walk_scbs)
{
/*
@@ -3510,16 +3052,22 @@
i = 0;
while (i < AIC7XXX_MAXSCB)
{
- outb(i, SCBPTR(base));
- scb_byte = ~(inb(SCBARRAY(base))); /* complement the byte */
- outb(scb_byte, SCBARRAY(base)); /* write it back out */
- if (inb(SCBARRAY(base)) != scb_byte)
+ outb(i, SCBPTR + base);
+ scb_byte = ~(inb(SCBARRAY + base)); /* complement the byte */
+ outb(scb_byte, SCBARRAY + base); /* write it back out */
+ if (inb(SCBARRAY + base) != scb_byte)
{
break;
}
i++;
}
maxscb = i;
+
+ printk("aic7xxx: Using %d SCB's after checking for SCB memory.\n", maxscb);
+ }
+ else
+ {
+ printk("aic7xxx: Using %d SCB's; No SCB memory check.\n", maxscb);
}
return (maxscb);
@@ -3540,10 +3088,10 @@
unsigned char sblkctl;
int max_targets;
int found = 1, base;
- int bios_disabled = 0;
+ int bios_disabled = FALSE;
unsigned char target_settings;
unsigned char scsi_conf, host_conf;
- int have_seeprom = 0;
+ int have_seeprom = FALSE;
struct Scsi_Host *host;
struct aic7xxx_host *p;
struct seeprom_config sc;
@@ -3553,7 +3101,7 @@
/*
* Lock out other contenders for our i/o space.
*/
- request_region(MINREG(base), MAXREG(base) - MINREG(base), "aic7xxx");
+ request_region(MINREG + base, MAXREG - MINREG, "aic7xxx");
switch (config->type)
{
@@ -3569,33 +3117,33 @@
* trigger type (level or edge) and use this value
* for pausing and unpausing the sequencer.
*/
- config->unpause = (inb(HCNTRL(base)) & IRQMS) | INTEN;
+ config->unpause = (inb(HCNTRL + base) & IRQMS) | INTEN;
config->pause = config->unpause | PAUSE;
config->extended = aic7xxx_extended;
- outb(config->pause | CHIPRST, HCNTRL(base));
+ outb(config->pause | CHIPRST, HCNTRL + base);
aic7xxx_delay(1);
- if (inb(HCNTRL(base)) & CHIPRST)
+ if (inb(HCNTRL + base) & CHIPRST)
{
printk("aic7xxx: Chip reset not cleared; clearing manually.\n");
}
- outb(config->pause, HCNTRL(base));
+ outb(config->pause, HCNTRL + base);
/*
* Just to be on the safe side with the 274x, we will re-read the irq
- * since there was some issue about reseting the board.
+ * since there was some issue about resetting the board.
*/
- config->irq = inb(HA_INTDEF(base)) & 0x0F;
- if ((inb(HA_274_BIOSCTRL(base)) & BIOSMODE) == BIOSDISABLED)
+ config->irq = inb(INTDEF + base) & 0x0F;
+ if ((inb(HA_274_BIOSCTRL + base) & BIOSMODE) == BIOSDISABLED)
{
- bios_disabled = 1;
+ bios_disabled = TRUE;
}
- host_conf = inb(HA_HOSTCONF(base));
+ host_conf = inb(HOSTCONF + base);
config->busrtime = host_conf & 0x3C;
/* XXX Is this valid for motherboard based controllers? */
/* Setup the FIFO threshold and the bus off time */
- outb(host_conf & DFTHRSH, BUSSPD(base));
- outb((host_conf << 2) & BOFF, BUSTIME(base));
+ outb(host_conf & DFTHRSH, BUSSPD + base);
+ outb((host_conf << 2) & BOFF, BUSTIME + base);
/*
* A reminder until this can be detected automatically.
@@ -3605,19 +3153,19 @@
break;
case AIC_284x:
- outb(CHIPRST, HCNTRL(base));
+ outb(CHIPRST, HCNTRL + base);
config->unpause = UNPAUSE_284X;
config->pause = REQ_PAUSE; /* DWG would like to be like the rest */
aic7xxx_delay(1);
- outb(config->pause, HCNTRL(base));
+ outb(config->pause, HCNTRL + base);
config->extended = aic7xxx_extended;
- config->irq = inb(HA_INTDEF(base)) & 0x0F;
- if ((inb(HA_274_BIOSCTRL(base)) & BIOSMODE) == BIOSDISABLED)
+ config->irq = inb(INTDEF + base) & 0x0F;
+ if ((inb(HA_274_BIOSCTRL + base) & BIOSMODE) == BIOSDISABLED)
{
- bios_disabled = 1;
+ bios_disabled = TRUE;
}
- host_conf = inb(HA_HOSTCONF(base));
+ host_conf = inb(HOSTCONF + base);
printk("aic7xxx: Reading SEEPROM...");
have_seeprom = read_2840_seeprom(base, &sc);
@@ -3647,8 +3195,8 @@
}
/* XXX Is this valid for motherboard based controllers? */
/* Setup the FIFO threshold and the bus off time */
- outb(host_conf & DFTHRSH, BUSSPD(base));
- outb((host_conf << 2) & BOFF, BUSTIME(base));
+ outb(host_conf & DFTHRSH, BUSSPD + base);
+ outb((host_conf << 2) & BOFF, BUSTIME + base);
printk("aic7xxx: Extended translation %sabled.\n",
config->extended ? "en" : "dis");
@@ -3665,11 +3213,11 @@
case AIC_7882:
case AIC_7883:
case AIC_7884:
- outb(CHIPRST, HCNTRL(base));
+ outb(CHIPRST, HCNTRL + base);
config->unpause = UNPAUSE_294X;
config->pause = config->unpause | PAUSE;
aic7xxx_delay(1);
- outb(config->pause, HCNTRL(base));
+ outb(config->pause, HCNTRL + base);
config->extended = aic7xxx_extended;
config->scsi_id = 7;
@@ -3704,14 +3252,17 @@
/*
* XXX - force data fifo threshold to 100%. Why does this
* need to be done?
+ *
+ * We don't know where this is set in the SEEPROM or by the BIOS,
+ * so we default it to 100%.
*/
- outb(inb(DSPCISTATUS(base)) | DFTHRESH, DSPCISTATUS(base));
- outb(config->scsi_id | DFTHRESH, HA_SCSICONF(base));
+ outb(config->scsi_id | DFTHRSH_100, SCSICONF + base);
+ outb(DFTHRSH_100, DSPCISTATUS + base);
/*
* In case we are a wide card, place scsi ID in second conf byte.
*/
- outb(config->scsi_id, (HA_SCSICONF(base) + 1));
+ outb(config->scsi_id, (SCSICONF + base + 1));
printk("aic7xxx: Extended translation %sabled.\n",
config->extended ? "en" : "dis");
@@ -3739,43 +3290,43 @@
* Read the bus type from the SBLKCTL register. Set the FLAGS
* register in the sequencer for twin and wide bus cards.
*/
- sblkctl = inb(SBLKCTL(base));
+ sblkctl = inb(SBLKCTL + base);
switch (sblkctl & SELBUS_MASK)
{
- case SELSINGLE: /* narrow/normal bus */
- config->scsi_id = inb(HA_SCSICONF(base)) & 0x07;
+ case SELNARROW: /* narrow/normal bus */
+ config->scsi_id = inb(SCSICONF + base) & 0x07;
config->bus_type = AIC_SINGLE;
- outb(SINGLE_BUS, HA_FLAGS(base));
+ outb(SINGLE_BUS, FLAGS + base);
break;
case SELWIDE: /* Wide bus */
- config->scsi_id = inb(HA_SCSICONF(base) + 1) & 0x0F;
+ config->scsi_id = inb(SCSICONF + base + 1) & 0x0F;
config->bus_type = AIC_WIDE;
printk("aic7xxx: Enabling wide channel of %s-Wide.\n",
board_names[config->type]);
- outb(WIDE_BUS, HA_FLAGS(base));
+ outb(WIDE_BUS, FLAGS + base);
break;
case SELBUSB: /* Twin bus */
- config->scsi_id = inb(HA_SCSICONF(base)) & 0x07;
+ config->scsi_id = inb(SCSICONF + base) & 0x07;
#ifdef AIC7XXX_TWIN_SUPPORT
- config->scsi_id_b = inb(HA_SCSICONF(base) + 1) & 0x07;
+ config->scsi_id_b = inb(SCSICONF + base + 1) & 0x07;
config->bus_type = AIC_TWIN;
printk("aic7xxx: Enabled channel B of %s-Twin.\n",
board_names[config->type]);
- outb(TWIN_BUS, HA_FLAGS(base));
+ outb(TWIN_BUS, FLAGS + base);
#else
config->bus_type = AIC_SINGLE;
printk("aic7xxx: Channel B of %s-Twin will be ignored.\n",
board_names[config->type]);
- outb(0, HA_FLAGS(base));
+ outb(0, FLAGS + base);
#endif
break;
default:
printk("aic7xxx: Unsupported type 0x%x, please "
- "mail deang@ims.com\n", inb(SBLKCTL(base)));
- outb(0, HA_FLAGS(base));
+ "mail deang@ims.com\n", inb(SBLKCTL + base));
+ outb(0, FLAGS + base);
return (0);
}
@@ -3784,7 +3335,7 @@
* take the card out of diagnostic mode and make the host adatper
* LED follow bus activity (will not always be on).
*/
- outb(sblkctl & ~(DIAGLEDEN | DIAGLEDON), SBLKCTL(base));
+ outb(sblkctl & ~(DIAGLEDEN | DIAGLEDON), SBLKCTL + base);
/*
* The IRQ level in i/o port 4 maps directly onto the real
@@ -3878,8 +3429,8 @@
}
p->isr_count = 0;
- p->a_scanned = 0;
- p->b_scanned = 0;
+ p->a_scanned = FALSE;
+ p->b_scanned = FALSE;
p->base = base;
p->maxscb = config->maxscb;
p->numscb = 0;
@@ -3942,11 +3493,11 @@
/*
* Set Fast Mode and Enable the board
*/
- outb(FASTMODE, SEQCTL(base));
+ outb(FASTMODE, SEQCTL + base);
if (p->chip_type == AIC_777x)
{
- outb(ENABLE, BCTL(base));
+ outb(ENABLE, BCTL + base);
}
printk("done.\n");
@@ -3959,29 +3510,37 @@
/*
* Select Channel B.
*/
- outb((sblkctl & ~SELBUS_MASK) | SELBUSB, SBLKCTL(base));
+ outb((sblkctl & ~SELBUS_MASK) | SELBUSB, SBLKCTL + base);
- outb(config->scsi_id_b, SCSIID(base));
- scsi_conf = inb(HA_SCSICONF(base) + 1) & (ENSPCHK | STIMESEL);
- outb(scsi_conf | ENSTIMER | ACTNEGEN | STPWEN, SXFRCTL1(base));
- outb(ENSELTIMO | ENSCSIPERR, SIMODE1(base));
+ outb(config->scsi_id_b, SCSIID + base);
+ scsi_conf = inb(SCSICONF + base + 1) & (ENSPCHK | STIMESEL);
+ outb(scsi_conf | ENSTIMER | ACTNEGEN | STPWEN, SXFRCTL1 + base);
+ outb(ENSELTIMO , SIMODE1 + base);
if (p->ultra_enabled)
{
- outb(ULTRAEN, SXFRCTL0(base));
+ outb(DFON | SPIOEN | ULTRAEN, SXFRCTL0 + base);
+ }
+ else
+ {
+ outb(DFON | SPIOEN, SXFRCTL0 + base);
}
/*
* Select Channel A
*/
- outb((sblkctl & ~SELBUS_MASK) | SELSINGLE, SBLKCTL(base));
+ outb((sblkctl & ~SELBUS_MASK) | SELNARROW, SBLKCTL + base);
}
- outb(config->scsi_id, SCSIID(base));
- scsi_conf = inb(HA_SCSICONF(base)) & (ENSPCHK | STIMESEL);
- outb(scsi_conf | ENSTIMER | ACTNEGEN | STPWEN, SXFRCTL1(base));
- outb(ENSELTIMO | ENSCSIPERR, SIMODE1(base));
+ outb(config->scsi_id, SCSIID + base);
+ scsi_conf = inb(SCSICONF + base) & (ENSPCHK | STIMESEL);
+ outb(scsi_conf | ENSTIMER | ACTNEGEN | STPWEN, SXFRCTL1 + base);
+ outb(ENSELTIMO , SIMODE1 + base);
if (p->ultra_enabled)
{
- outb(ULTRAEN, SXFRCTL0(base));
+ outb(DFON | SPIOEN | ULTRAEN, SXFRCTL0 + base);
+ }
+ else
+ {
+ outb(DFON | SPIOEN, SXFRCTL0 + base);
}
/*
@@ -3992,10 +3551,10 @@
* BIOS has decided to disable synchronous negotiation to that
* target so we don't activate the needsdtr flag.
*/
- p->needsdtr_copy = 0;
- p->sdtr_pending = 0;
- p->needwdtr_copy = 0;
- p->wdtr_pending = 0;
+ p->needsdtr_copy = 0x0;
+ p->sdtr_pending = 0x0;
+ p->needwdtr_copy = 0x0;
+ p->wdtr_pending = 0x0;
if (p->bus_type == AIC_SINGLE)
{
max_targets = 8;
@@ -4010,7 +3569,7 @@
*/
if (have_seeprom)
{
- p->discenable = 0;
+ p->discenable = 0x0;
}
else
{
@@ -4022,8 +3581,8 @@
}
else
{
- p->discenable = ~((inb(HA_DISC_DSB(base) + 1) << 8) |
- inb(HA_DISC_DSB(base)));
+ p->discenable = ~((inb(DISC_DSB + base + 1) << 8) |
+ inb(DISC_DSB + base));
}
}
@@ -4036,7 +3595,7 @@
{
p->needsdtr_copy |= (0x01 << i);
}
- if ((sc.device_flags[i] & CFWIDEB) && (p->bus_type == AIC_WIDE))
+ if (sc.device_flags[i] & CFWIDEB)
{
p->needwdtr_copy |= (0x01 << i);
}
@@ -4047,29 +3606,42 @@
}
else
{
- target_settings = inb(HA_TARG_SCRATCH(base) + i);
- if (target_settings & 0x0F)
+ if (bios_disabled)
{
- p->needsdtr_copy |= (0x01 << i);
- /*
- * Default to asynchronous transfers (0 offset)
- */
- target_settings &= 0xF0;
+ target_settings = 0; /* 10 MHz */
+ p->needsdtr_copy |= (0x01 << i);
+ p->needwdtr_copy |= (0x01 << i);
}
- /*
- * If we are not wide, forget WDTR. This makes the driver
- * work on some cards that don't leave these fields cleared
- * when BIOS is not installed.
- */
- if ((target_settings & 0x80) && (p->bus_type == AIC_WIDE))
+ else
{
- p->needwdtr_copy |= (0x01 << i);
- target_settings &= 0x7F;
+ target_settings = inb(TARG_SCRATCH + base + i);
+ if (target_settings & 0x0F)
+ {
+ p->needsdtr_copy |= (0x01 << i);
+ /*
+ * Default to asynchronous transfers (0 offset)
+ */
+ target_settings &= 0xF0;
+ }
+ if (target_settings & 0x80)
+ {
+ p->needwdtr_copy |= (0x01 << i);
+ target_settings &= 0x7F;
+ }
}
}
- outb(target_settings, (HA_TARG_SCRATCH(base) + i));
+ outb(target_settings, (TARG_SCRATCH + base + i));
}
+ /*
+ * If we are not wide, forget WDTR. This makes the driver
+ * work on some cards that don't leave these fields cleared
+ * when BIOS is not installed.
+ */
+ if (p->bus_type != AIC_WIDE)
+ {
+ p->needwdtr = 0;
+ }
p->needsdtr = p->needsdtr_copy;
p->needwdtr = p->needwdtr_copy;
#if 0
@@ -4083,27 +3655,33 @@
*/
for (i = 0; i < config->maxscb; i++)
{
- outb(i, SCBPTR(base));
- outb(0, SCBARRAY(base));
+ outb(i, SCBPTR + base);
+ outb(0, SCBARRAY + base);
}
/*
* For reconnecting targets, the sequencer code needs to
* know how many SCBs it has to search through.
*/
- outb(config->maxscb, HA_SCBCOUNT(base));
+ outb(config->maxscb, SCBCOUNT + base);
+
+ /*
+ * 2s compliment of SCBCOUNT
+ */
+ i = p->maxscb;
+ outb(-i & 0xff, COMP_SCBCOUNT + base);
/*
* Clear the active flags - no targets are busy.
*/
- outb(0, HA_ACTIVE0(base));
- outb(0, HA_ACTIVE1(base));
+ outb(0, ACTIVE_A + base);
+ outb(0, ACTIVE_B + base);
/*
* We don't have any waiting selections
*/
- outb(SCB_LIST_NULL, WAITING_SCBH(base));
- outb(SCB_LIST_NULL, WAITING_SCBT(base));
+ outb(SCB_LIST_NULL, WAITING_SCBH + base);
+ outb(SCB_LIST_NULL, WAITING_SCBT + base);
/*
* Reset the SCSI bus. Is this necessary?
@@ -4126,21 +3704,21 @@
/*
* Select Channel B.
*/
- outb((sblkctl & ~SELBUS_MASK) | SELBUSB, SBLKCTL(base));
+ outb((sblkctl & ~SELBUS_MASK) | SELBUSB, SBLKCTL + base);
- outb(SCSIRSTO, SCSISEQ(base));
+ outb(SCSIRSTO, SCSISEQ + base);
udelay(1000);
- outb(0, SCSISEQ(base));
+ outb(0, SCSISEQ + base);
/*
* Select Channel A.
*/
- outb((sblkctl & ~SELBUS_MASK) | SELSINGLE, SBLKCTL(base));
+ outb((sblkctl & ~SELBUS_MASK) | SELNARROW, SBLKCTL + base);
}
- outb(SCSIRSTO, SCSISEQ(base));
+ outb(SCSIRSTO, SCSISEQ + base);
udelay(1000);
- outb(0, SCSISEQ(base));
+ outb(0, SCSISEQ + base);
aic7xxx_delay(AIC7XXX_RESET_DELAY);
@@ -4196,9 +3774,9 @@
*/
for (slot = MINSLOT; slot <= MAXSLOT; slot++)
{
- base = SLOTBASE(slot);
+ base = SLOTBASE(slot) + MINREG;
- if (check_region(MINREG(base), MAXREG(base) - MINREG(base)))
+ if (check_region(MINREG + base, MAXREG - MINREG))
{
/*
* Some other driver has staked a
@@ -4207,7 +3785,7 @@
continue;
}
- config.type = aic7xxx_probe(slot, HID0(base));
+ config.type = aic7xxx_probe(slot, HID0 + base);
if (config.type != AIC_NONE)
{
/*
@@ -4269,7 +3847,9 @@
unsigned int io_port;
unsigned short index = 0;
unsigned char pci_bus, pci_device_fn;
- unsigned char devrevid, devconfig, devstatus;
+ unsigned int csize_lattime;
+ unsigned int class_revid;
+ unsigned int devconfig;
char rev_id[] = {'B', 'C', 'D'};
for (i = 0; i < NUMBER(aic7xxx_pci_devices); i++)
@@ -4287,10 +3867,13 @@
{
config.type = aic7xxx_pci_devices[i].card_type;
config.chip_type = aic7xxx_pci_devices[i].chip_type;
+ config.chan_num = 0;
+ config.walk_scbs = FALSE;
switch (config.type)
{
case AIC_7872: /* 3940 */
case AIC_7882: /* 3940-Ultra */
+ config.walk_scbs = TRUE;
config.chan_num = number_of_39xxs & 0x1; /* Has 2 controllers */
number_of_39xxs++;
if (number_of_39xxs == 2)
@@ -4313,69 +3896,67 @@
break;
}
- /*
- * Read esundry information from PCI BIOS.
- */
- error = pcibios_read_config_dword(pci_bus, pci_device_fn,
- PCI_BASE_ADDRESS_0, &io_port);
- if (error)
- {
- panic("aic7xxx: (aic7xxx_detect) Error %d reading I/O port.\n",
- error);
- }
-
- error = pcibios_read_config_byte(pci_bus, pci_device_fn,
- PCI_INTERRUPT_LINE, &irq);
- if (error)
- {
- panic("aic7xxx: (aic7xxx_detect) Error %d reading IRQ.\n",
- error);
- }
-
- error = pcibios_read_config_byte(pci_bus, pci_device_fn,
- DEVREVID, &devrevid);
- if (error)
- {
- panic("aic7xxx: (aic7xxx_detect) Error %d reading device "
- "revision ID.\n", error);
- }
-
- if (devrevid < 3)
- {
- printk("aic7xxx: %s Rev %c.\n", board_names[config.type],
- rev_id[devrevid]);
- }
+ /*
+ * Read esundry information from PCI BIOS.
+ */
+ error = pcibios_read_config_dword(pci_bus, pci_device_fn,
+ PCI_BASE_ADDRESS_0, &io_port);
+ error += pcibios_read_config_byte(pci_bus, pci_device_fn,
+ PCI_INTERRUPT_LINE, &irq);
- error = pcibios_read_config_byte(pci_bus, pci_device_fn,
- DEVCONFIG, &devconfig);
- if (error)
- {
- panic("aic7xxx: (aic7xxx_detect) Error %d reading device "
- "configuration.\n", error);
- }
+ /*
+ * Ensure that we are using good values for the PCI burst size
+ * and latency timer.
+ */
+ error += pcibios_read_config_dword(pci_bus, pci_device_fn,
+ CSIZE_LATTIME, &csize_lattime);
+ if ((csize_lattime & CACHESIZE) == 0)
+ {
+ /* Default to 8DWDs - what's the PCI define for this? */
+ csize_lattime |= 8;
+ }
+ if((csize_lattime & LATTIME) == 0)
+ {
+ /* Default to 64 PCLKS (is this a good value?) */
+ /* This may also be availble in the SEEPROM?? */
+ csize_lattime |= (64 << 8);
+ }
+ pcibios_write_config_dword(pci_bus, pci_device_fn,
+ CSIZE_LATTIME, csize_lattime);
+ printk("aic7xxx: BurstLen = %d DWDs, Latency Timer = %d PCLKS\n",
+ (int) (csize_lattime & CACHESIZE),
+ (csize_lattime >> 8) & 0x000000ff);
+
+ error += pcibios_read_config_dword(pci_bus, pci_device_fn,
+ CLASS_PROGIF_REVID, &class_revid);
+ if ((class_revid & DEVREVID) < 3)
+ {
+ printk("aic7xxx: %s Rev %c.\n", board_names[config.type],
+ rev_id[class_revid & DEVREVID]);
+ }
- error = pcibios_read_config_byte(pci_bus, pci_device_fn,
- DEVSTATUS, &devstatus);
- if (error)
- {
- panic("aic7xxx: (aic7xxx_detect) Error %d reading device status.\n",
+ error += pcibios_read_config_dword(pci_bus, pci_device_fn,
+ DEVCONFIG, &devconfig);
+ if (error)
+ {
+ panic("aic7xxx: (aic7xxx_detect) Error %d reading PCI registers.\n",
error);
- }
+ }
- printk("aic7xxx: devconfig(0x%x) devstatus(0x%x).\n",
- devconfig, devstatus);
+ printk("aic7xxx: devconfig = 0x%x.\n", devconfig);
- /*
- * Make the base I/O register look like EISA and VL-bus.
- */
- base = io_port - 0xC01;
+ /*
+ * The first bit of PCI_BASE_ADDRESS_0 is always set, so
+ * we mask it off.
+ */
+ base = io_port & 0xfffffffe;
- /*
- * I don't think we need to bother with allowing
- * spurious interrupts for the 787x/7850, but what
- * the hey.
- */
- aic7xxx_spurious_count = 1;
+ /*
+ * I don't think we need to bother with allowing
+ * spurious interrupts for the 787x/7850, but what
+ * the hey.
+ */
+ aic7xxx_spurious_count = 1;
config.base = base;
config.irq = irq;
@@ -4383,20 +3964,39 @@
config.low_term = AIC_UNKNOWN;
config.high_term = AIC_UNKNOWN;
config.busrtime = 0;
- config.walk_scbs = FALSE;
config.ultra_enabled = FALSE;
- if ((devstatus & RAMPSM) || (devconfig & SCBRAMSEL))
- {
+ if (devconfig & RAMPSM)
+ {
+ /*
+ * External SRAM present. Have the probe walk the SCBs to see
+ * how much SRAM we have and set the number of SCBs accordingly.
+ * We have to turn off SCBRAMSEL to access the external SCB
+ * SRAM.
+ *
+ * It seems that early versions of the aic7870 didn't use these
+ * bits, hence the hack for the 3940 above. I would guess that
+ * recent 3940s using later aic7870 or aic7880 chips do actually
+ * set RAMPSM.
+ *
+ * The documentation isn't clear, but it sounds like the value
+ * written to devconfig must not have RAMPSM set. The second
+ * sixteen bits of the register are R/O anyway, so it shouldn't
+ * affect RAMPSM either way.
+ */
+ printk ("aic7xxx: External RAM detected. Enabling RAM access.\n");
+ devconfig &= ~(RAMPSM | SCBRAMSEL);
+ pcibios_write_config_dword(pci_bus, pci_device_fn,
+ DEVCONFIG, devconfig);
config.walk_scbs = TRUE;
- }
- found += aic7xxx_register(template, &config);
+ }
+ found += aic7xxx_register(template, &config);
- /*
- * Disable spurious interrupts.
- */
- aic7xxx_spurious_count = 0;
+ /*
+ * Disable spurious interrupts.
+ */
+ aic7xxx_spurious_count = 0;
- index++;
+ index++;
} /* Found an Adaptec PCI device. */
}
}
@@ -4440,18 +4040,18 @@
}
cmd->tag = cmd->device->current_tag;
cmd->device->current_tag++;
- scb->control |= SCB_TE;
+ scb->control |= TAG_ENB;
}
#endif
mask = (0x01 << (cmd->target | (cmd->channel << 3)));
if (p->discenable & mask)
{
- scb->control |= SCB_DISCENB;
+ scb->control |= DISCENB;
}
if ((p->needwdtr & mask) && !(p->wdtr_pending & mask))
{
p->wdtr_pending |= mask;
- scb->control |= SCB_NEEDWDTR;
+ scb->control |= NEEDWDTR;
#if 0
printk("aic7xxx: Sending WDTR request to target %d.\n", cmd->target);
#endif
@@ -4461,7 +4061,7 @@
if ((p->needsdtr & mask) && !(p->sdtr_pending & mask))
{
p->sdtr_pending |= mask;
- scb->control |= SCB_NEEDSDTR;
+ scb->control |= NEEDSDTR;
#if 0
printk("aic7xxx: Sending SDTR request to target %d.\n", cmd->target);
#endif
@@ -4493,18 +4093,16 @@
if (cmd->use_sg)
{
-#if 0
- debug("aic7xxx: (build_scb) SG used, %d segments, length(%u).\n",
- cmd->use_sg, length);
-#endif
scb->SG_segment_count = cmd->use_sg;
memcpy(scb->SG_list_pointer, &cmd->request_buffer,
sizeof(scb->SG_list_pointer));
memcpy(&sg, &cmd->request_buffer, sizeof(sg));
memcpy(scb->data_pointer, &(sg[0].address), sizeof(scb->data_pointer));
- scb->data_count[0] = sg[0].length & 0xFF;
- scb->data_count[1] = (sg[0].length >> 8) & 0xFF;
- scb->data_count[2] = (sg[0].length >> 16) & 0xFF;
+ scb->data_count = sg[0].length;
+#if 0
+ debug("aic7xxx: (build_scb) SG segs(%d), length(%u), sg[0].length(%d).\n",
+ cmd->use_sg, aic7xxx_length(cmd, 0), scb->data_count);
+#endif
}
else
{
@@ -4522,7 +4120,7 @@
scb->SG_segment_count = 0;
memset(scb->SG_list_pointer, 0, sizeof(scb->SG_list_pointer));
memset(scb->data_pointer, 0, sizeof(scb->data_pointer));
- memset(scb->data_count, 0, sizeof(scb->data_count));
+ scb->data_count = 0;
}
else
{
@@ -4531,9 +4129,7 @@
scb->sg.length = cmd->request_bufflen;
addr = &scb->sg;
memcpy(scb->SG_list_pointer, &addr, sizeof(scb->SG_list_pointer));
- scb->data_count[0] = scb->sg.length & 0xFF;
- scb->data_count[1] = (scb->sg.length >> 8) & 0xFF;
- scb->data_count[2] = (scb->sg.length >> 16) & 0xFF;
+ scb->data_count = scb->sg.length;
memcpy(scb->data_pointer, &cmd->request_buffer, sizeof(scb->data_pointer));
}
}
@@ -4552,7 +4148,6 @@
long flags;
struct aic7xxx_host *p;
struct aic7xxx_scb *scb;
- unsigned char curscb;
p = (struct aic7xxx_host *) cmd->host->hostdata;
@@ -4562,19 +4157,19 @@
if (!p->a_scanned && (cmd->channel == 0))
{
printk("aic7xxx: Scanning channel A for devices.\n");
- p->a_scanned = 1;
+ p->a_scanned = TRUE;
}
else
{
if (!p->b_scanned && (cmd->channel == 1))
{
printk("aic7xxx: Scanning channel B for devices.\n");
- p->b_scanned = 1;
+ p->b_scanned = TRUE;
}
}
#if 0
- debug("aic7xxx_queue: cmd(0x%x) size(%u), target %d, channel %d, lun %d.\n",
+ debug("aic7xxx: (queue) cmd(0x%x) size(%u), target %d, channel %d, lun %d.\n",
cmd->cmnd[0], cmd->cmd_len, cmd->target, cmd->channel,
cmd->lun & 0x07);
#endif
@@ -4632,16 +4227,6 @@
scb->position = p->numscb;
p->numscb++;
scb->state = SCB_ACTIVE;
- scb->next_waiting = SCB_LIST_NULL;
- memcpy(scb->host_scb, &scb, sizeof(scb));
- scb->control = SCB_NEEDDMA;
- PAUSE_SEQUENCER(p);
- curscb = inb(SCBPTR(p->base));
- outb(scb->position, SCBPTR(p->base));
- aic7xxx_putscb_dma(p->base, scb);
- outb(curscb, SCBPTR(p->base));
- UNPAUSE_SEQUENCER(p);
- scb->control = 0;
}
}
@@ -4681,7 +4266,8 @@
* the SCB, then write its pointer into the queue in FIFO
* and restore the saved SCB pointer.
*/
- aic7xxx_putscb(p->base, scb);
+ aic7xxx_putscb(p, scb);
+ outb(scb->position, QINFIFO + p->base);
/*
* Make sure the Scsi_Cmnd pointer is saved, the struct it
@@ -4720,7 +4306,7 @@
unsigned char errcode)
{
int base = p->base;
- int found = 0;
+ int found = FALSE;
aha_abort_reset_type scb_status = ABORT_RESET_SUCCESS;
char channel = scb->target_channel_lun & SELBUSB ? 'B': 'A';
@@ -4730,7 +4316,7 @@
*/
PAUSE_SEQUENCER(p);
-#ifdef AIC7XXX_DEBUG_ABORT
+#ifdef AIC7XXX_DEBUG_ABORT
printk ("aic7xxx: (abort_scb) scb %d, scb_aborted 0x%x\n",
scb->position, (scb->state & SCB_ABORTED));
#endif
@@ -4765,15 +4351,15 @@
* may also be that we're timing out on a command that just takes
* too much time, so we try the bus device reset there first.
*/
- active_scb = inb(SCBPTR(base));
+ active_scb = inb(SCBPTR + base);
active_scbp = &(p->scb_array[active_scb]);
- control = inb(SCBARRAY(base));
+ control = inb(SCBARRAY + base);
/*
* Test to see if scbp is disconnected
*/
- outb(scb->position, SCBPTR(base));
- if (inb(SCBARRAY(base)) & SCB_DIS)
+ outb(scb->position, SCBPTR + base);
+ if (inb(SCBARRAY + base) & DISCONNECTED)
{
#ifdef AIC7XXX_DEBUG_ABORT
printk ("aic7xxx: (abort_scb) scb %d is disconnected.\n", scb->position);
@@ -4782,15 +4368,8 @@
scb->SG_segment_count = 0;
memset(scb->SG_list_pointer, 0, sizeof(scb->SG_list_pointer));
memset(scb->data_pointer, 0, sizeof(scb->data_pointer));
- memset(scb->data_count, 0, sizeof(scb->data_count));
- outb(SCBAUTO, SCBCNT(base));
- asm volatile("cld\n\t"
- "rep\n\t"
- "outsb"
- : /* no output */
- :"S" (scb), "c" (SCB_DOWNLOAD_SIZE), "d" (SCBARRAY(base))
- :"si", "cx", "dx");
- outb(0, SCBCNT(base));
+ scb->data_count = 0;
+ aic7xxx_putscb(p, scb);
aic7xxx_error(scb->cmd) = errcode;
scb_status = ABORT_RESET_PENDING;
aic7xxx_add_waiting_scb(base, scb, LIST_SECOND);
@@ -4801,14 +4380,14 @@
/*
* Is the active SCB really active?
*/
- if ((active_scbp->state & SCB_ACTIVE) && (control & SCB_NEEDDMA))
+ if (active_scbp->state & SCB_ACTIVE)
{
- unsigned char flags = inb(HA_FLAGS(base));
- if (flags & ACTIVE_MSG)
+ unsigned char msg_len = inb(MSG_LEN + base);
+ if (msg_len != 0)
{
#ifdef AIC7XXX_DEBUG_ABORT
printk ("aic7xxx: (abort_scb) scb is active, needs DMA, "
- "ha_flags active.\n");
+ "msg_len is non-zero.\n");
#endif
/*
* If we're in a message phase, tacking on another message
@@ -4822,15 +4401,14 @@
{
#ifdef AIC7XXX_DEBUG_ABORT
printk ("aic7xxx: (abort_scb) scb is active, needs DMA, "
- "ha_flags inactive.\n");
+ "msg_len is zero.\n");
#endif
/*
* Load the message buffer and assert attention.
*/
active_scbp->state |= (SCB_DEVICE_RESET | SCB_ABORTED);
- outb(flags | ACTIVE_MSG, HA_FLAGS(base));
- outb(1, HA_MSG_LEN(base));
- outb(MSG_BUS_DEVICE_RESET, HA_MSG_START(base));
+ outb(1, MSG_LEN + base);
+ outb(MSG_BUS_DEVICE_RESET, MSG0 + base);
if (active_scbp->target_channel_lun != scb->target_channel_lun)
{
/*
@@ -4897,7 +4475,7 @@
*/
/* cmd->retries = 0; */
aic7xxx_error(cmd) = errcode;
- aic7xxx_done (p, scb);
+ aic7xxx_done(p, scb);
}
else
{
@@ -5060,3 +4638,4 @@
* tab-width: 8
* End:
*/
+
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov
with Sam's (original) version of this