patch-2.0.34 linux/drivers/scsi/ncr53c8xx.c
Next file: linux/drivers/scsi/ncr53c8xx.h
Previous file: linux/drivers/scsi/in2000.readme
Back to the patch index
Back to the overall index
- Lines: 1845
- Date:
Wed Jun 3 15:17:49 1998
- Orig file:
v2.0.33/linux/drivers/scsi/ncr53c8xx.c
- Orig date:
Thu Aug 21 15:13:05 1997
diff -u --recursive --new-file v2.0.33/linux/drivers/scsi/ncr53c8xx.c linux/drivers/scsi/ncr53c8xx.c
@@ -60,11 +60,14 @@
** May 19 1997 by Richard Waltham <dormouse@farsrobt.demon.co.uk>:
** Support for NvRAM detection and reading.
**
+** August 18 1997 by Cort <cort@cs.nmt.edu>:
+** Support for Power/PC (Big Endian).
+**
*******************************************************************************
*/
/*
-** 21 August 1997, version 2.4a
+** 30 January 1998, version 2.5f.1
**
** Supported SCSI-II features:
** Synchronous negotiation
@@ -306,6 +309,7 @@
** architecture.
*/
+#ifndef NCR_IOMAPPED
__initfunc(
static vm_offset_t remap_pci_mem(u_long base, u_long size)
)
@@ -332,6 +336,7 @@
vfree((void *) (vaddr & PAGE_MASK));
#endif
}
+#endif /* !NCR_IOMAPPED */
#else /* linux-1.2.13 */
@@ -452,9 +457,9 @@
/*
** Head of list of NCR boards
**
-** Host is retrieved by its irq level.
-** If interrupts are shared, the internal host control block
-** address (struct ncb) is used as device id.
+** For kernel version < 1.3.70, host is retrieved by its irq level.
+** For later kernels, the internal host control block address
+** (struct ncb) is used as device id parameter of the irq stuff.
*/
static struct Scsi_Host *first_host = NULL;
@@ -499,7 +504,7 @@
unsigned master_parity : 1;
unsigned scsi_parity : 1;
unsigned disconnection : 1;
- unsigned special_features : 1;
+ unsigned special_features : 2;
unsigned ultra_scsi : 2;
unsigned force_sync_nego: 1;
unsigned reverse_probe: 1;
@@ -515,6 +520,7 @@
u_char settle_delay;
u_char diff_support;
u_char irqm;
+ u_char bus_check;
};
static struct ncr_driver_setup
@@ -523,6 +529,9 @@
#ifdef SCSI_NCR_BOOT_COMMAND_LINE_SUPPORT
static struct ncr_driver_setup
driver_safe_setup __initdata = SCSI_NCR_DRIVER_SAFE_SETUP;
+#ifdef MODULE
+char *ncr53c8xx = 0; /* command line passed by insmod */
+#endif
#endif
/*
@@ -570,7 +579,8 @@
u_short flags1;
#define SYMBIOS_SCAN_HI_LO (1)
u_short word10; /* 0x00 */
- u_short word12; /* 0x00 */
+ u_short flags3; /* 0x00 */
+#define SYMBIOS_REMOVABLE_FLAGS (3) /* 0=none, 1=bootable, 2=all */
u_char host_id;
u_char byte15; /* 0x04 */
u_short word16; /* 0x0410 */
@@ -657,6 +667,7 @@
int bus;
u_char device_fn;
u_int base;
+ u_int base_2;
u_int io_port;
int irq;
/* port and reg fields to use INB, OUTB macros */
@@ -684,7 +695,7 @@
ncr_slot slot;
ncr_chip chip;
ncr_nvram *nvram;
- int attached;
+ int attach_done;
} ncr_device;
/*==========================================================
@@ -743,79 +754,156 @@
/*==========================================================
**
-** Access to the controller chip.
-**
-** If NCR_IOMAPPED is defined, only IO are used by the driver.
+** Big/Little endian support.
**
**==========================================================
*/
/*
-** IO mapped only input / ouput
+** If the NCR uses big endian addressing mode over the
+** PCI, actual io register addresses for byte and word
+** accesses must be changed according to lane routing.
+** Btw, ncr_offb() and ncr_offw() macros only apply to
+** constants and so donnot generate bloated code.
*/
-#define IOM_INB(r) inb (np->port + offsetof(struct ncr_reg, r))
-#define IOM_INB_OFF(o) inb (np->port + (o))
-#define IOM_INW(r) inw (np->port + offsetof(struct ncr_reg, r))
-#define IOM_INL(r) inl (np->port + offsetof(struct ncr_reg, r))
-#define IOM_INL_OFF(o) inl (np->port + (o))
-
-#define IOM_OUTB(r, val) outb ((val), np->port+offsetof(struct ncr_reg,r))
-#define IOM_OUTW(r, val) outw ((val), np->port+offsetof(struct ncr_reg,r))
-#define IOM_OUTL(r, val) outl ((val), np->port+offsetof(struct ncr_reg,r))
-#define IOM_OUTL_OFF(o, val) outl ((val), np->port + (o))
+#if defined(SCSI_NCR_BIG_ENDIAN)
+
+#define ncr_offb(o) (((o)&~3)+((~((o)&3))&3))
+#define ncr_offw(o) (((o)&~3)+((~((o)&3))&2))
+
+#else
+
+#define ncr_offb(o) (o)
+#define ncr_offw(o) (o)
+
+#endif
/*
-** MEMORY mapped IO input / output
+** If the CPU and the NCR use same endian-ness adressing,
+** no byte reordering is needed for script patching.
+** Macro cpu_to_scr() is to be used for script patching.
+** Macro scr_to_cpu() is to be used for getting a DWORD
+** from the script.
*/
-#define MMIO_INB(r) readb(&np->reg->r)
-#define MMIO_INB_OFF(o) readb((char *)np->reg + (o))
-#define MMIO_INW(r) readw(&np->reg->r)
-#define MMIO_INL(r) readl(&np->reg->r)
-#define MMIO_INL_OFF(o) readl((char *)np->reg + (o))
-
-#define MMIO_OUTB(r, val) writeb((val), &np->reg->r)
-#define MMIO_OUTW(r, val) writew((val), &np->reg->r)
-#define MMIO_OUTL(r, val) writel((val), &np->reg->r)
-#define MMIO_OUTL_OFF(o, val) writel((val), (char *)np->reg + (o))
+#if defined(__BIG_ENDIAN) && !defined(SCSI_NCR_BIG_ENDIAN)
+
+#define cpu_to_scr(dw) cpu_to_le32(dw)
+#define scr_to_cpu(dw) le32_to_cpu(dw)
+
+#elif defined(__LITTLE_ENDIAN) && defined(SCSI_NCR_BIG_ENDIAN)
+
+#define cpu_to_scr(dw) cpu_to_be32(dw)
+#define scr_to_cpu(dw) be32_to_cpu(dw)
+
+#else
+
+#define cpu_to_scr(dw) (dw)
+#define scr_to_cpu(dw) (dw)
+
+#endif
+
+/*==========================================================
+**
+** Access to the controller chip.
+**
+** If NCR_IOMAPPED is defined, only IO are used by the driver.
+**
+**==========================================================
+*/
/*
-** IO mapped input / output
+** If the CPU and the NCR use same endian-ness adressing,
+** no byte reordering is needed for accessing chip io
+** registers. Functions suffixed by '_raw' are assumed
+** to access the chip over the PCI without doing byte
+** reordering. Functions suffixed by '_l2b' are
+** assumed to perform little-endian to big-endian byte
+** reordering, those suffixed by '_b2l' blah, blah,
+** blah, ...
*/
#if defined(NCR_IOMAPPED)
-#define INB(r) IOM_INB(r)
-#define INB_OFF(o) IOM_INB_OFF(o)
-#define INW(r) IOM_INW(r)
-#define INL(r) IOM_INL(r)
-#define INL_OFF(o) IOM_INL_OFF(o)
-
-#define OUTB(r, val) IOM_OUTB(r, val)
-#define OUTW(r, val) IOM_OUTW(r, val)
-#define OUTL(r, val) IOM_OUTL(r, val)
-#define OUTL_OFF(o, val) IOM_OUTL_OFF(o, val)
+/*
+** IO mapped only input / ouput
+*/
+
+#define INB_OFF(o) inb (np->port + ncr_offb(o))
+#define OUTB_OFF(o, val) outb ((val), np->port + ncr_offb(o))
+
+#if defined(__BIG_ENDIAN) && !defined(SCSI_NCR_BIG_ENDIAN)
+
+#define INW_OFF(o) inw_l2b (np->port + ncr_offw(o))
+#define INL_OFF(o) inl_l2b (np->port + (o))
+
+#define OUTW_OFF(o, val) outw_b2l ((val), np->port + ncr_offw(o))
+#define OUTL_OFF(o, val) outl_b2l ((val), np->port + (o))
+
+#elif defined(__LITTLE_ENDIAN) && defined(SCSI_NCR_BIG_ENDIAN)
+
+#define INW_OFF(o) inw_b2l (np->port + ncr_offw(o))
+#define INL_OFF(o) inl_b2l (np->port + (o))
+
+#define OUTW_OFF(o, val) outw_l2b ((val), np->port + ncr_offw(o))
+#define OUTL_OFF(o, val) outl_l2b ((val), np->port + (o))
+
+#else
+
+#define INW_OFF(o) inw_raw (np->port + ncr_offw(o))
+#define INL_OFF(o) inl_raw (np->port + (o))
+
+#define OUTW_OFF(o, val) outw_raw ((val), np->port + ncr_offw(o))
+#define OUTL_OFF(o, val) outl_raw ((val), np->port + (o))
+
+#endif /* ENDIANs */
+
+#else /* defined NCR_IOMAPPED */
/*
-** MEMORY mapped only input / output
+** MEMORY mapped IO input / output
*/
+#define INB_OFF(o) readb((char *)np->reg + ncr_offb(o))
+#define OUTB_OFF(o, val) writeb((val), (char *)np->reg + ncr_offb(o))
+
+#if defined(__BIG_ENDIAN) && !defined(SCSI_NCR_BIG_ENDIAN)
+
+#define INW_OFF(o) readw_l2b((char *)np->reg + ncr_offw(o))
+#define INL_OFF(o) readl_l2b((char *)np->reg + (o))
+
+#define OUTW_OFF(o, val) writew_b2l((val), (char *)np->reg + ncr_offw(o))
+#define OUTL_OFF(o, val) writel_b2l((val), (char *)np->reg + (o))
+
+#elif defined(__LITTLE_ENDIAN) && defined(SCSI_NCR_BIG_ENDIAN)
+
+#define INW_OFF(o) readw_b2l((char *)np->reg + ncr_offw(o))
+#define INL_OFF(o) readl_b2l((char *)np->reg + (o))
+
+#define OUTW_OFF(o, val) writew_l2b((val), (char *)np->reg + ncr_offw(o))
+#define OUTL_OFF(o, val) writel_l2b((val), (char *)np->reg + (o))
+
#else
-#define INB(r) MMIO_INB(r)
-#define INB_OFF(o) MMIO_INB_OFF(o)
-#define INW(r) MMIO_INW(r)
-#define INL(r) MMIO_INL(r)
-#define INL_OFF(o) MMIO_INL_OFF(o)
-
-#define OUTB(r, val) MMIO_OUTB(r, val)
-#define OUTW(r, val) MMIO_OUTW(r, val)
-#define OUTL(r, val) MMIO_OUTL(r, val)
-#define OUTL_OFF(o, val) MMIO_OUTL_OFF(o, val)
+#define INW_OFF(o) readw_raw((char *)np->reg + ncr_offw(o))
+#define INL_OFF(o) readl_raw((char *)np->reg + (o))
+
+#define OUTW_OFF(o, val) writew_raw((val), (char *)np->reg + ncr_offw(o))
+#define OUTL_OFF(o, val) writel_raw((val), (char *)np->reg + (o))
#endif
+#endif /* defined NCR_IOMAPPED */
+
+#define INB(r) INB_OFF (offsetof(struct ncr_reg,r))
+#define INW(r) INW_OFF (offsetof(struct ncr_reg,r))
+#define INL(r) INL_OFF (offsetof(struct ncr_reg,r))
+
+#define OUTB(r, val) OUTB_OFF (offsetof(struct ncr_reg,r), (val))
+#define OUTW(r, val) OUTW_OFF (offsetof(struct ncr_reg,r), (val))
+#define OUTL(r, val) OUTL_OFF (offsetof(struct ncr_reg,r), (val))
+
/*
** Set bit field ON, OFF
*/
@@ -827,6 +915,7 @@
#define OUTONL(r, m) OUTL(r, INL(r) | (m))
#define OUTOFFL(r, m) OUTL(r, INL(r) & ~(m))
+
/*==========================================================
**
** Command control block states.
@@ -1264,27 +1353,36 @@
** status fields.
*/
- u_char status[8];
+ u_char scr_st[4]; /* script status */
+ u_char status[4]; /* host status. Must be the last */
+ /* DWORD of the CCB header */
};
/*
** The status bytes are used by the host and the script processor.
**
-** The first four byte are copied to the scratchb register
+** The byte corresponding to the host_status must be stored in the
+** last DWORD of the CCB header since it is used for command
+** completion (ncr_wakeup()). Doing so, we are sure that the header
+** has been entirely copied back to the CCB when the host_status is
+** seen complete by the CPU.
+**
+** The last four bytes (status[4]) are copied to the scratchb register
** (declared as scr0..scr3 in ncr_reg.h) just after the select/reselect,
** and copied back just after disconnecting.
** Inside the script the XX_REG are used.
**
-** The last four bytes are used inside the script by "COPY" commands.
+** The first four bytes (scr_st[4]) are used inside the script by
+** "COPY" commands.
** Because source and destination must have the same alignment
-** in a longword, the fields HAVE to be at the choosen offsets.
-** xerr_st (4) 0 (0x34) scratcha
-** sync_st (5) 1 (0x05) sxfer
-** wide_st (7) 3 (0x03) scntl3
+** in a DWORD, the fields HAVE to be at the choosen offsets.
+** xerr_st 0 (0x34) scratcha
+** sync_st 1 (0x05) sxfer
+** wide_st 3 (0x03) scntl3
*/
/*
-** First four bytes (script)
+** Last four bytes (script)
*/
#define QU_REG scr0
#define HS_REG scr1
@@ -1293,7 +1391,7 @@
#define PS_REG scr3
/*
-** First four bytes (host)
+** Last four bytes (host)
*/
#define actualquirks phys.header.status[0]
#define host_status phys.header.status[1]
@@ -1301,15 +1399,15 @@
#define parity_status phys.header.status[3]
/*
-** Last four bytes (script)
+** First four bytes (script)
*/
-#define xerr_st header.status[4] /* MUST be ==0 mod 4 */
-#define sync_st header.status[5] /* MUST be ==1 mod 4 */
-#define nego_st header.status[6]
-#define wide_st header.status[7] /* MUST be ==3 mod 4 */
+#define xerr_st header.scr_st[0]
+#define sync_st header.scr_st[1]
+#define nego_st header.scr_st[2]
+#define wide_st header.scr_st[3]
/*
-** Last four bytes (host)
+** First four bytes (host)
*/
#define xerr_status phys.xerr_st
#define sync_status phys.sync_st
@@ -1677,9 +1775,11 @@
/*
** Timeout handler
*/
+#if 0
u_long heartbeat;
u_short ticks;
u_short latetime;
+#endif
u_long lasttime;
/*-----------------------------------------------
@@ -1771,7 +1871,7 @@
** of 825A, 875 and 895 chips.
*/
struct script {
- ncrcmd start [ 7];
+ ncrcmd start [ 4];
ncrcmd start0 [ 2];
ncrcmd start1 [ 3];
ncrcmd startpos [ 1];
@@ -1785,7 +1885,7 @@
ncrcmd prepare2 [ 24];
ncrcmd setmsg [ 5];
ncrcmd clrack [ 2];
- ncrcmd dispatch [ 33];
+ ncrcmd dispatch [ 38];
ncrcmd no_data [ 17];
ncrcmd checkatn [ 10];
ncrcmd command [ 15];
@@ -1859,7 +1959,7 @@
static void ncr_getclock (ncb_p np, int mult);
static void ncr_selectclock (ncb_p np, u_char scntl3);
static ccb_p ncr_get_ccb (ncb_p np, u_long t,u_long l);
-static void ncr_init (ncb_p np, char * msg, u_long code);
+static void ncr_init (ncb_p np, int reset, char * msg, u_long code);
static int ncr_int_sbmc (ncb_p np);
static int ncr_int_par (ncb_p np);
static void ncr_int_ma (ncb_p np);
@@ -1887,6 +1987,7 @@
static void ncr_timeout (ncb_p np);
static void ncr_wakeup (ncb_p np, u_long code);
static void ncr_start_reset (ncb_p np, int settle_delay);
+static int ncr_reset_scsi_bus (ncb_p np, int enab_int, int settle_delay);
#ifdef SCSI_NCR_USER_COMMAND_SUPPORT
static void ncr_usercmd (ncb_p np);
@@ -1917,16 +2018,6 @@
**==========================================================
*/
-#if 0
-static char ident[] =
- "\n$Id: ncr.c,v 1.67 1996/03/11 19:36:07 se Exp $\n";
-static u_long ncr_version = NCR_VERSION * 11
- + (u_long) sizeof (struct ncb) * 7
- + (u_long) sizeof (struct ccb) * 5
- + (u_long) sizeof (struct lcb) * 3
- + (u_long) sizeof (struct tcb) * 2;
-#endif
-
#ifdef SCSI_NCR_DEBUG_INFO_SUPPORT
static int ncr_debug = SCSI_NCR_DEBUG_FLAGS;
#endif
@@ -1984,13 +2075,14 @@
static struct script script0 __initdata = {
/*--------------------------< START >-----------------------*/ {
+#if 0
/*
** Claim to be still alive ...
*/
SCR_COPY (sizeof (((struct ncb *)0)->heartbeat)),
KVAR(SCRIPT_KVAR_JIFFIES),
NADDR (heartbeat),
-
+#endif
/*
** Make data structure address invalid.
** clear SIGP.
@@ -2291,8 +2383,21 @@
0,
SCR_RETURN ^ IFTRUE (WHEN (SCR_DATA_OUT)),
0,
- SCR_RETURN ^ IFTRUE (IF (SCR_DATA_IN)),
+ /*
+ ** DEL 397 - 53C875 Rev 3 - Part Number 609-0392410 - ITEM 4.
+ ** Possible data corruption during Memory Write and Invalidate.
+ ** This work-around resets the addressing logic prior to the
+ ** start of the first MOVE of a DATA IN phase.
+ ** (See README.ncr53c8xx for more information)
+ */
+ SCR_JUMPR ^ IFFALSE (IF (SCR_DATA_IN)),
+ 20,
+ SCR_COPY (4),
+ RADDR (scratcha),
+ RADDR (scratcha),
+ SCR_RETURN,
0,
+
SCR_JUMP ^ IFTRUE (IF (SCR_MSG_OUT)),
PADDR (msg_out),
SCR_JUMP ^ IFTRUE (IF (SCR_MSG_IN)),
@@ -3603,7 +3708,8 @@
while (src < end) {
- *dst++ = opcode = *src++;
+ opcode = *src++;
+ *dst++ = cpu_to_scr(opcode);
/*
** If we forget to change the length
@@ -3648,7 +3754,7 @@
** the NO FLUSH bit if present.
*/
if ((opcode & SCR_NO_FLUSH) && !(np->features & FE_PFEN)) {
- dst[-1] = (opcode & ~SCR_NO_FLUSH);
+ dst[-1] = cpu_to_scr(opcode & ~SCR_NO_FLUSH);
++opchanged;
}
break;
@@ -3721,10 +3827,10 @@
break;
}
- *dst++ = new;
+ *dst++ = cpu_to_scr(new);
}
} else
- *dst++ = *src++;
+ *dst++ = cpu_to_scr(*src++);
};
if (bootverbose > 1 && opchanged)
@@ -3984,15 +4090,6 @@
np->maxsync = period > 2540 ? 254 : period / 10;
/*
- ** Get on-board RAM bus address when supported
- */
- if (np->features & FE_RAM) {
- OUTONB(nc_ctest2, 0x8);
- np->paddr2 = INL(nc_scr0);
- OUTOFFB(nc_ctest2, 0x8);
- }
-
- /*
** Prepare initial value of other IO registers
*/
#if defined SCSI_NCR_TRUST_BIOS_SETTING
@@ -4348,7 +4445,8 @@
** virtual and physical memory.
*/
- np->paddr = device->slot.base;
+ np->paddr = device->slot.base;
+ np->paddr2 = (np->features & FE_RAM)? device->slot.base_2 : 0;
#ifndef NCR_IOMAPPED
np->vaddr = remap_pci_mem((u_long) np->paddr, (u_long) 128);
@@ -4456,17 +4554,20 @@
*/
if (np->features & FE_LED0) {
- np->script0->reselect[0] = SCR_REG_REG(gpreg, SCR_OR, 0x01);
- np->script0->reselect1[0] = SCR_REG_REG(gpreg, SCR_AND, 0xfe);
- np->script0->reselect2[0] = SCR_REG_REG(gpreg, SCR_AND, 0xfe);
+ np->script0->reselect[0] =
+ cpu_to_scr(SCR_REG_REG(gpreg, SCR_OR, 0x01));
+ np->script0->reselect1[0] =
+ cpu_to_scr(SCR_REG_REG(gpreg, SCR_AND, 0xfe));
+ np->script0->reselect2[0] =
+ cpu_to_scr(SCR_REG_REG(gpreg, SCR_AND, 0xfe));
}
/*
** init data structure
*/
- np->jump_tcb.l_cmd = SCR_JUMP;
- np->jump_tcb.l_paddr = NCB_SCRIPTH_PHYS (np, abort);
+ np->jump_tcb.l_cmd = cpu_to_scr(SCR_JUMP);
+ np->jump_tcb.l_paddr = cpu_to_scr(NCB_SCRIPTH_PHYS (np, abort));
/*
** Reset chip.
@@ -4497,7 +4598,7 @@
SA_INTERRUPT|SA_SHIRQ, "ncr53c8xx", np)) {
#else
if (request_irq(device->slot.irq, ncr53c8xx_intr,
- SA_INTERRUPT, "ncr53c8xx", NULL)) {
+ SA_INTERRUPT, "ncr53c8xx", np)) {
#endif
#else
if (request_irq(device->slot.irq, ncr53c8xx_intr,
@@ -4517,7 +4618,11 @@
** Then enable disconnects.
*/
save_flags(flags); cli();
- ncr_start_reset(np, driver_setup.settle_delay);
+ if (ncr_reset_scsi_bus(np, 0, driver_setup.settle_delay) != 0) {
+ printf("%s: FATAL ERROR: CHECK SCSI BUS - CABLES, TERMINATION, DEVICE POWER etc.!\n", ncr_name(np));
+ restore_flags(flags);
+ goto attach_error;
+ }
ncr_exception (np);
restore_flags(flags);
@@ -4585,6 +4690,16 @@
#endif
release_region(np->port, 128);
}
+ if (np->irq) {
+#ifdef DEBUG_NCR53C8XX
+ printf("%s: freeing irq %d\n", ncr_name(np), np->irq);
+#endif
+#if LINUX_VERSION_CODE >= LinuxVersionCode(1,3,70)
+ free_irq(np->irq, np);
+#else
+ free_irq(np->irq);
+#endif
+ }
scsi_unregister(instance);
return -1;
@@ -4654,7 +4769,9 @@
/*---------------------------------------------------
**
- ** Assign a ccb / bind cmd
+ ** Assign a ccb / bind cmd.
+ ** If resetting, shorten settle_time if necessary
+ ** in order to avoid spurious timeouts.
** If resetting or no free ccb,
** insert cmd into the waiting list.
**
@@ -4662,6 +4779,11 @@
*/
save_flags(flags); cli();
+ if (np->settle_time && cmd->timeout_per_command >= HZ &&
+ np->settle_time > jiffies + cmd->timeout_per_command - HZ) {
+ np->settle_time = jiffies + cmd->timeout_per_command - HZ;
+ }
+
if (np->settle_time || !(cp=ncr_get_ccb (np, cmd->target, cmd->lun))) {
insert_into_waiting_list(np, cmd);
restore_flags(flags);
@@ -4933,21 +5055,23 @@
u_long endp;
default:
case XferBoth:
- cp->phys.header.savep = NCB_SCRIPT_PHYS (np, data_io);
+ cp->phys.header.savep =
+ cpu_to_scr(NCB_SCRIPT_PHYS (np, data_io));
cp->phys.header.goalp = cp->phys.header.savep;
break;
case XferIn:
endp = NCB_SCRIPT_PHYS (np, data_in) + MAX_SCATTER*16;
- cp->phys.header.goalp = endp + 8;
- cp->phys.header.savep = endp - segments*16;
+ cp->phys.header.goalp = cpu_to_scr(endp + 8);
+ cp->phys.header.savep = cpu_to_scr(endp - segments*16);
break;
case XferOut:
endp = NCB_SCRIPTH_PHYS (np, data_out) + MAX_SCATTER*16;
- cp->phys.header.goalp = endp + 8;
- cp->phys.header.savep = endp - segments*16;
+ cp->phys.header.goalp = cpu_to_scr(endp + 8);
+ cp->phys.header.savep = cpu_to_scr(endp - segments*16);
break;
case XferNone:
- cp->phys.header.savep = NCB_SCRIPT_PHYS (np, no_data);
+ cp->phys.header.savep =
+ cpu_to_scr(NCB_SCRIPT_PHYS (np, no_data));
cp->phys.header.goalp = cp->phys.header.savep;
break;
}
@@ -4968,8 +5092,9 @@
/*
** Startqueue
*/
- cp->phys.header.launch.l_paddr = NCB_SCRIPT_PHYS (np, select);
- cp->phys.header.launch.l_cmd = SCR_JUMP;
+ cp->phys.header.launch.l_paddr =
+ cpu_to_scr(NCB_SCRIPT_PHYS (np, select));
+ cp->phys.header.launch.l_cmd = cpu_to_scr(SCR_JUMP);
/*
** select
*/
@@ -4979,21 +5104,21 @@
/*
** message
*/
- cp->phys.smsg.addr = CCB_PHYS (cp, scsi_smsg);
- cp->phys.smsg.size = msglen;
+ cp->phys.smsg.addr = cpu_to_scr(CCB_PHYS (cp, scsi_smsg));
+ cp->phys.smsg.size = cpu_to_scr(msglen);
- cp->phys.smsg2.addr = CCB_PHYS (cp, scsi_smsg2);
- cp->phys.smsg2.size = msglen2;
+ cp->phys.smsg2.addr = cpu_to_scr(CCB_PHYS (cp, scsi_smsg2));
+ cp->phys.smsg2.size = cpu_to_scr(msglen2);
/*
** command
*/
- cp->phys.cmd.addr = vtophys (&cmd->cmnd[0]);
- cp->phys.cmd.size = cmd->cmd_len;
+ cp->phys.cmd.addr = cpu_to_scr(vtophys (&cmd->cmnd[0]));
+ cp->phys.cmd.size = cpu_to_scr(cmd->cmd_len);
/*
** sense command
*/
- cp->phys.scmd.addr = CCB_PHYS (cp, sensecmd);
- cp->phys.scmd.size = 6;
+ cp->phys.scmd.addr = cpu_to_scr(CCB_PHYS (cp, sensecmd));
+ cp->phys.scmd.size = cpu_to_scr(6);
/*
** patch requested size into sense command
*/
@@ -5003,8 +5128,9 @@
/*
** sense data
*/
- cp->phys.sense.addr = vtophys (&cmd->sense_buffer[0]);
- cp->phys.sense.size = sizeof(cmd->sense_buffer);
+ cp->phys.sense.addr =
+ cpu_to_scr(vtophys (&cmd->sense_buffer[0]));
+ cp->phys.sense.size = cpu_to_scr(sizeof(cmd->sense_buffer));
/*
** status
*/
@@ -5029,8 +5155,10 @@
** reselect pattern and activate this job.
*/
- cp->jump_ccb.l_cmd = (SCR_JUMP ^ IFFALSE (DATA (cp->tag)));
- /* Compute a time limit bigger than the middle-level driver one */
+ cp->jump_ccb.l_cmd =
+ cpu_to_scr((SCR_JUMP ^ IFFALSE (DATA (cp->tag))));
+
+ /* Compute a time limit greater than the middle-level driver one */
if (cmd->timeout_per_command > 0)
cp->tlimit = jiffies + cmd->timeout_per_command + NCR_TIMEOUT_INCREASE;
else
@@ -5043,14 +5171,14 @@
qidx = np->squeueput + 1;
if (qidx >= MAX_START) qidx=0;
- np->squeue [qidx ] = NCB_SCRIPT_PHYS (np, idle);
- np->squeue [np->squeueput] = CCB_PHYS (cp, phys);
+ np->squeue [qidx ] = cpu_to_scr(NCB_SCRIPT_PHYS (np, idle));
+ np->squeue [np->squeueput] = cpu_to_scr(CCB_PHYS (cp, phys));
np->squeueput = qidx;
if(DEBUG_FLAGS & DEBUG_QUEUE)
printf ("%s: queuepos=%d tryoffset=%d.\n", ncr_name (np),
np->squeueput,
- (unsigned)(np->script->startpos[0]-
+ (unsigned)(scr_to_cpu(np->script->startpos[0]) -
(NCB_SCRIPTH_PHYS (np, tryloop))));
/*
@@ -5093,21 +5221,70 @@
save_flags(flags); cli();
if (!np->settle_time) {
- if (bootverbose > 1)
- printf("%s: resetting, command processing suspended for %d seconds\n",
- ncr_name(np), settle_delay);
- np->settle_time = jiffies + settle_delay * HZ;
- OUTB (nc_istat, SRST);
- DELAY (1000);
- OUTB (nc_istat, 0);
- OUTW (nc_sien, RST);
- OUTB (nc_scntl1, CRST);
- DELAY (100);
+ (void) ncr_reset_scsi_bus(np, 1, settle_delay);
}
-
restore_flags(flags);
}
+static int ncr_reset_scsi_bus(ncb_p np, int enab_int, int settle_delay)
+{
+ u_int32 term;
+ int retv = 0;
+
+ np->settle_time = jiffies + settle_delay * HZ;
+
+ if (bootverbose > 1)
+ printf("%s: resetting, "
+ "command processing suspended for %d seconds\n",
+ ncr_name(np), settle_delay);
+
+ OUTB (nc_istat, SRST);
+ DELAY (1000);
+ OUTB (nc_istat, 0);
+ if (enab_int)
+ OUTW (nc_sien, RST);
+ /*
+ ** Enable Tolerant, reset IRQD if present and
+ ** properly set IRQ mode, prior to resetting the bus.
+ */
+ OUTB (nc_stest3, TE);
+ OUTB (nc_dcntl, (np->rv_dcntl & IRQM));
+ OUTB (nc_scntl1, CRST);
+ DELAY (100);
+
+ if (!driver_setup.bus_check)
+ goto out;
+ /*
+ ** Check for no terminators or SCSI bus shorts to ground.
+ ** Read SCSI data bus, data parity bits and control signals.
+ ** We are expecting RESET to be TRUE and other signals to be
+ ** FALSE.
+ */
+ term = INB(nc_sstat0); /* rst, sdp0 */
+ term = ((term & 2) << 7) + ((term & 1) << 16);
+ term |= ((INB(nc_sstat2) & 0x01) << 25) | /* sdp1 */
+ (INW(nc_sbdl) << 9) | /* d15-0 */
+ INB(nc_sbcl); /* req, ack, bsy, sel, atn, msg, cd, io */
+
+ if (!(np->features & FE_WIDE))
+ term &= 0x3ffff;
+
+ if (term != (2<<7)) {
+ printf("%s: suspicious SCSI data while resetting the BUS.\n",
+ ncr_name(np));
+ printf("%s: %sdp0,d7-0,rst,req,ack,bsy,sel,atn,msg,c/d,i/o = "
+ "0x%lx, expecting 0x%lx\n",
+ ncr_name(np),
+ (np->features & FE_WIDE) ? "dp1,d15-8," : "",
+ (u_long)term, (u_long)(2<<7));
+ if (driver_setup.bus_check == 1)
+ retv = 1;
+ }
+out:
+ OUTB (nc_scntl1, 0);
+ return retv;
+}
+
/*==========================================================
**
**
@@ -5146,7 +5323,7 @@
* Commands will now be queued in the waiting list until a settle
* delay of 2 seconds will be completed.
*/
- ncr_start_reset(np, 2);
+ ncr_start_reset(np, driver_setup.settle_delay);
/*
* First, look in the wakeup list
*/
@@ -5256,10 +5433,12 @@
** this condition in order to complete the canceled command
** after the script skipped the ccb, if necessary.
*/
- cp->jump_ccb.l_cmd = (SCR_JUMP);
- if (cp->phys.header.launch.l_paddr == NCB_SCRIPT_PHYS (np, select)) {
+ cp->jump_ccb.l_cmd = cpu_to_scr(SCR_JUMP);
+ if (cp->phys.header.launch.l_paddr ==
+ cpu_to_scr(NCB_SCRIPT_PHYS (np, select))) {
printf ("%s: abort ccb=%p (skip)\n", ncr_name (np), cp);
- cp->phys.header.launch.l_paddr = NCB_SCRIPT_PHYS (np, skip);
+ cp->phys.header.launch.l_paddr =
+ cpu_to_scr(NCB_SCRIPT_PHYS (np, skip));
}
cp->tlimit = 0;
@@ -5292,7 +5471,7 @@
*/
#ifdef MODULE
-static int ncr_detach(ncb_p np, int irq)
+static int ncr_detach(ncb_p np)
{
ccb_p cp;
tcb_p tp;
@@ -5331,16 +5510,12 @@
*/
#ifdef DEBUG_NCR53C8XX
- printf("%s: freeing irq %d\n", ncr_name(np), irq);
+ printf("%s: freeing irq %d\n", ncr_name(np), np->irq);
#endif
#if LINUX_VERSION_CODE >= LinuxVersionCode(1,3,70)
-# ifdef SCSI_NCR_SHARE_IRQ
- free_irq(irq, np);
-# else
- free_irq(irq, NULL);
-# endif
+ free_irq(np->irq, np);
#else
- free_irq(irq);
+ free_irq(np->irq);
#endif
/*
@@ -5450,12 +5625,12 @@
/*
** No Reselect anymore.
*/
- cp->jump_ccb.l_cmd = (SCR_JUMP);
+ cp->jump_ccb.l_cmd = cpu_to_scr(SCR_JUMP);
/*
** No starting.
*/
- cp->phys.header.launch.l_paddr= NCB_SCRIPT_PHYS (np, idle);
+ cp->phys.header.launch.l_paddr = cpu_to_scr(NCB_SCRIPT_PHYS (np, idle));
/*
** timestamp
@@ -5522,10 +5697,12 @@
** Check the status.
*/
if ( (cp->host_status == HS_COMPLETE)
- && (cp->scsi_status == S_GOOD)) {
-
+ && (cp->scsi_status == S_GOOD ||
+ cp->scsi_status == S_COND_MET)) {
/*
- ** All went well.
+ ** All went well (GOOD status).
+ ** CONDITION MET status is returned on
+ ** `Pre-Fetch' or `Search data' success.
*/
cmd->result = ScsiResult(DID_OK, cp->scsi_status);
@@ -5620,7 +5797,8 @@
}
} else if ((cp->host_status == HS_COMPLETE)
- && (cp->scsi_status == S_BUSY)) {
+ && (cp->scsi_status == S_BUSY ||
+ cp->scsi_status == S_CONFLICT)) {
/*
** Target is busy.
@@ -5786,16 +5964,21 @@
**==========================================================
*/
-void ncr_init (ncb_p np, char * msg, u_long code)
+void ncr_init (ncb_p np, int reset, char * msg, u_long code)
{
int i;
/*
- ** Reset chip.
+ ** Reset chip if asked, otherwise just clear fifos.
*/
-
- OUTB (nc_istat, SRST);
- DELAY (10000);
+ if (reset) {
+ OUTB (nc_istat, SRST);
+ DELAY (10000);
+ }
+ else {
+ OUTB (nc_stest3, TE|CSF);
+ OUTONB (nc_ctest3, CLF);
+ }
/*
** Message.
@@ -5807,14 +5990,14 @@
** Clear Start Queue
*/
for (i=0;i<MAX_START;i++)
- np -> squeue [i] = NCB_SCRIPT_PHYS (np, idle);
+ np -> squeue [i] = cpu_to_scr(NCB_SCRIPT_PHYS (np, idle));
/*
** Start at first entry.
*/
np->squeueput = 0;
- np->script0->startpos[0] = NCB_SCRIPTH_PHYS (np, tryloop);
- np->script0->start0 [0] = SCR_INT ^ IFFALSE (0);
+ np->script0->startpos[0] = cpu_to_scr(NCB_SCRIPTH_PHYS (np, tryloop));
+ np->script0->start0 [0] = cpu_to_scr(SCR_INT ^ IFFALSE (0));
/*
** Wakeup all pending jobs.
@@ -5866,7 +6049,11 @@
if (np->vaddr2) {
if (bootverbose)
printf ("%s: copying script fragments into the on-board RAM ...\n", ncr_name(np));
- bcopy(np->script0, np->script, sizeof(struct script));
+#if LINUX_VERSION_CODE >= LinuxVersionCode(2,0,0)
+ memcpy_toio(np->script, np->script0, sizeof(struct script));
+#else
+ memcpy(np->script, np->script0, sizeof(struct script));
+#endif
}
/*
@@ -6150,7 +6337,7 @@
if (tp->period < 500) scsi = "FAST-40";
else if (tp->period < 1000) scsi = "FAST-20";
else if (tp->period < 2000) scsi = "FAST-10";
- else scsi = "SLOW";
+ else scsi = "FAST-5";
printf ("%s %sSCSI %d.%d MB/s (%d ns, offset %d)\n", scsi,
tp->widedone > 1 ? "WIDE " : "",
@@ -6487,7 +6674,6 @@
{
u_long thistime = jiffies;
u_long count = 0;
- long signed t;
ccb_p cp;
u_long flags;
@@ -6561,10 +6747,12 @@
**
**----------------------------------------------------
*/
-
- t = (thistime - np->heartbeat) / HZ;
-
- if (t<2) np->latetime=0; else np->latetime++;
+#if 0
+ if (thistime < np->heartbeat + HZ + HZ)
+ np->latetime = 0;
+ else
+ np->latetime++;
+#endif
/*----------------------------------------------------
**
@@ -6607,7 +6795,7 @@
** still in start queue ?
*/
if (cp->phys.header.launch.l_paddr ==
- NCB_SCRIPT_PHYS (np, skip))
+ cpu_to_scr(NCB_SCRIPT_PHYS (np, skip)))
continue;
/* fall through */
@@ -6691,14 +6879,20 @@
script_base = (u_char *) np->script;
script_name = "script";
}
- else {
+ else if (np->p_scripth < dsp &&
+ dsp <= np->p_scripth + sizeof(struct scripth)) {
script_ofs = dsp - np->p_scripth;
script_size = sizeof(struct scripth);
script_base = (u_char *) np->scripth;
script_name = "scripth";
+ } else {
+ script_ofs = dsp;
+ script_size = 0;
+ script_base = 0;
+ script_name = "mem";
}
- printf ("%s:%d: ERROR (%x:%x) (%x-%x-%x) (%x/%x) @ %s (%x:%08x).\n",
+ printf ("%s:%d: ERROR (%x:%x) (%x-%x-%x) (%x/%x) @ (%s %x:%08x).\n",
ncr_name (np), (unsigned)INB (nc_ctest0)&0x0f, dstat, sist,
(unsigned)INB (nc_socl), (unsigned)INB (nc_sbcl), (unsigned)INB (nc_sbdl),
(unsigned)INB (nc_sxfer),(unsigned)INB (nc_scntl3), script_name, script_ofs,
@@ -6756,15 +6950,18 @@
/*
** interrupt on the fly ?
- */
- while ((istat = INB (nc_istat)) & INTF) {
+ ** Since the global header may be copied back to a CCB
+ ** using a posted PCI memory write, the last operation on
+ ** the istat register is a READ in order to flush posted
+ ** PCI commands (Btw, the 'do' loop is probably useless).
+ */
+ istat = INB (nc_istat);
+ if (istat & INTF) {
+ do {
+ OUTB (nc_istat, (istat & SIGP) | INTF);
+ istat = INB (nc_istat);
+ } while (istat & INTF);
if (DEBUG_FLAGS & DEBUG_TINY) printf ("F ");
-#ifdef SCSI_NCR_DEBUG_ERROR_RECOVERY_SUPPORT
- if (np->stalling)
- OUTB (nc_istat, INTF);
- else
-#endif
- OUTB (nc_istat, (istat & SIGP) | INTF);
np->profile.num_fly++;
ncr_wakeup (np, 0);
};
@@ -6819,9 +7016,16 @@
ncr_int_sir (np);
return;
}
- if (!(sist & (SBMC|PAR)) && !(dstat & SSI))
- printf("%s: unknown interrupt(s) ignored sist=%x dstat=%x\n",
- ncr_name(np), sist, dstat);
+ /*
+ ** DEL 397 - 53C875 Rev 3 - Part Number 609-0392410 - ITEM 2.
+ */
+ if (!(sist & (SBMC|PAR)) && !(dstat & SSI)) {
+ printf( "%s: unknown interrupt(s) ignored, "
+ "ISTAT=%x DSTAT=%x SIST=%x\n",
+ ncr_name(np), istat, dstat, sist);
+ return;
+ }
+
OUTONB (nc_dcntl, (STD|NOCOM));
return;
};
@@ -6842,12 +7046,17 @@
*/
if (sist & RST) {
- ncr_init (np, bootverbose ? "scsi reset" : NULL, HS_RESET);
+ ncr_init (np, 1, bootverbose ? "scsi reset" : NULL, HS_RESET);
return;
};
if ((sist & STO) &&
!(dstat & (MDPE|BF|ABRT))) {
+ /*
+ ** DEL 397 - 53C875 Rev 3 - Part Number 609-0392410 - ITEM 1.
+ */
+ OUTONB (nc_ctest3, CLF);
+
ncr_int_sto (np);
return;
};
@@ -6880,13 +7089,13 @@
if ((sist & (SGE)) ||
(dstat & (MDPE|BF|ABORT|IID))) {
- ncr_start_reset(np, 2);
+ ncr_start_reset(np, driver_setup.settle_delay);
return;
};
if (sist & HTH) {
printf ("%s: handshake timeout\n", ncr_name(np));
- ncr_start_reset(np, 2);
+ ncr_start_reset(np, driver_setup.settle_delay);
return;
};
@@ -6896,7 +7105,7 @@
OUTB (nc_scr1, HS_UNEXPECTED);
OUTL (nc_dsp, NCB_SCRIPT_PHYS (np, cleanup));
};
- ncr_start_reset(np, 2);
+ ncr_start_reset(np, driver_setup.settle_delay);
return;
};
@@ -6954,11 +7163,11 @@
/* assert ((diff <= MAX_START * 20) && !(diff % 20));*/
if ((diff <= MAX_START * 20) && !(diff % 20)) {
- np->script->startpos[0] = scratcha;
+ np->script->startpos[0] = cpu_to_scr(scratcha);
OUTL (nc_dsp, NCB_SCRIPT_PHYS (np, start));
return;
};
- ncr_init (np, "selection timeout", HS_FAIL);
+ ncr_init (np, 1, "selection timeout", HS_FAIL);
np->disc = 1;
}
@@ -6983,11 +7192,17 @@
{
u_char scsi_mode = INB (nc_stest4) & SMODE;
- printf("%s: SCSI bus mode change from %x to %x, resetting ...\n",
+ printf("%s: SCSI bus mode change from %x to %x.\n",
ncr_name(np), np->scsi_mode, scsi_mode);
np->scsi_mode = scsi_mode;
- ncr_start_reset(np, 2);
+
+ /*
+ ** Suspend command processing for 1 second and
+ ** reinitialize all except the chip.
+ */
+ np->settle_time = jiffies + HZ;
+ ncr_init (np, 0, bootverbose ? "scsi mode change" : NULL, HS_RESET);
return 1;
}
@@ -7146,20 +7361,20 @@
** get old startaddress and old length.
*/
- oadr = vdsp[1];
+ oadr = scr_to_cpu(vdsp[1]);
if (cmd & 0x10) { /* Table indirect */
tblp = (u_int32 *) ((char*) &cp->phys + oadr);
- olen = tblp[0];
- oadr = tblp[1];
+ olen = scr_to_cpu(tblp[0]);
+ oadr = scr_to_cpu(tblp[1]);
} else {
tblp = (u_int32 *) 0;
- olen = vdsp[0] & 0xffffff;
+ olen = scr_to_cpu(vdsp[0]) & 0xffffff;
};
if (DEBUG_FLAGS & DEBUG_PHASE) {
printf ("OCMD=%x\nTBLP=%p OLEN=%x OADR=%x\n",
- (unsigned) (vdsp[0] >> 24),
+ (unsigned) (scr_to_cpu(vdsp[0]) >> 24),
tblp,
(unsigned) olen,
(unsigned) oadr);
@@ -7169,10 +7384,10 @@
** check cmd against assumed interrupted script command.
*/
- if (cmd != (vdsp[0] >> 24)) {
+ if (cmd != (scr_to_cpu(vdsp[0]) >> 24)) {
PRINT_ADDR(cp->cmd);
printf ("internal error: cmd=%02x != %02x=(vdsp[0] >> 24)\n",
- (unsigned)cmd, (unsigned)vdsp[0] >> 24);
+ (unsigned)cmd, (unsigned)scr_to_cpu(vdsp[0]) >> 24);
return;
}
@@ -7204,25 +7419,25 @@
*/
newcmd = cp->patch;
- if (cp->phys.header.savep == vtophys (newcmd)) newcmd+=4;
+ if (cp->phys.header.savep == cpu_to_scr(vtophys (newcmd))) newcmd+=4;
/*
** fillin the commands
*/
- newcmd[0] = ((cmd & 0x0f) << 24) | rest;
- newcmd[1] = oadr + olen - rest;
- newcmd[2] = SCR_JUMP;
- newcmd[3] = nxtdsp;
+ newcmd[0] = cpu_to_scr(((cmd & 0x0f) << 24) | rest);
+ newcmd[1] = cpu_to_scr(oadr + olen - rest);
+ newcmd[2] = cpu_to_scr(SCR_JUMP);
+ newcmd[3] = cpu_to_scr(nxtdsp);
if (DEBUG_FLAGS & DEBUG_PHASE) {
PRINT_ADDR(cp->cmd);
printf ("newcmd[%d] %x %x %x %x.\n",
(int) (newcmd - cp->patch),
- (unsigned)newcmd[0],
- (unsigned)newcmd[1],
- (unsigned)newcmd[2],
- (unsigned)newcmd[3]);
+ (unsigned)scr_to_cpu(newcmd[0]),
+ (unsigned)scr_to_cpu(newcmd[1]),
+ (unsigned)scr_to_cpu(newcmd[2]),
+ (unsigned)scr_to_cpu(newcmd[3]));
}
/*
** fake the return address (to the patch).
@@ -7309,20 +7524,23 @@
*/
if (num == SIR_DATA_IO_IS_OUT) {
endp = NCB_SCRIPTH_PHYS (np, data_out) + MAX_SCATTER*16;
- cp->phys.header.goalp = endp + 8;
- cp->phys.header.savep = endp - cp->segments*16;
+ cp->phys.header.goalp = cpu_to_scr(endp + 8);
+ cp->phys.header.savep =
+ cpu_to_scr(endp - cp->segments*16);
} else {
endp = NCB_SCRIPT_PHYS (np, data_in) + MAX_SCATTER*16;
- cp->phys.header.goalp = endp + 8;
- cp->phys.header.savep = endp - cp->segments*16;
+ cp->phys.header.goalp = cpu_to_scr(endp + 8);
+ cp->phys.header.savep =
+ cpu_to_scr(endp - cp->segments*16);
}
cp->phys.header.lastp = cp->phys.header.savep;
np->header.savep = cp->phys.header.savep;
np->header.goalp = cp->phys.header.goalp;
np->header.lastp = cp->phys.header.lastp;
- OUTL (nc_temp, np->header.savep);
- OUTL (nc_dsp, np->header.savep);
+
+ OUTL (nc_temp, scr_to_cpu(np->header.savep));
+ OUTL (nc_dsp, scr_to_cpu(np->header.savep));
return;
/* break; */
@@ -7369,7 +7587,7 @@
** no job, resume normal processing
*/
if (DEBUG_FLAGS & DEBUG_RESTART) printf (" -- remove trap\n");
- np->script->start0[0] = SCR_INT ^ IFFALSE (0);
+ np->script->start0[0] = cpu_to_scr(SCR_INT ^ IFFALSE (0));
break;
case SIR_SENSE_FAILED:
@@ -7395,7 +7613,7 @@
/*
** And patch code to restart it.
*/
- np->script->start0[0] = SCR_INT;
+ np->script->start0[0] = cpu_to_scr(SCR_INT);
break;
/*-----------------------------------------------------------------------------
@@ -7752,7 +7970,7 @@
PRINT_ADDR(cp->cmd);
printf ("M_REJECT received (%x:%x).\n",
- (unsigned)np->lastmsg, np->msgout[0]);
+ (unsigned)scr_to_cpu(np->lastmsg), np->msgout[0]);
break;
case SIR_REJECT_SENT:
@@ -7802,8 +8020,8 @@
printf ("M_DISCONNECT received, but datapointer not saved: "
"data=%x save=%x goal=%x.\n",
(unsigned) INL (nc_temp),
- (unsigned) np->header.savep,
- (unsigned) np->header.goalp);
+ (unsigned) scr_to_cpu(np->header.savep),
+ (unsigned) scr_to_cpu(np->header.goalp));
break;
#if 0 /* This stuff does not work */
@@ -7834,7 +8052,7 @@
PRINT_ADDR(cp->cmd);
printf ("queue full.\n");
- np->script->start1[0] = SCR_INT;
+ np->script->start1[0] = cpu_to_scr(SCR_INT);
/*
** Try to disable tagged transfers.
@@ -7882,7 +8100,7 @@
*/
printf ("%s: queue empty.\n", ncr_name (np));
- np->script->start1[0] = SCR_INT ^ IFFALSE (0);
+ np->script->start1[0] = cpu_to_scr(SCR_INT ^ IFFALSE (0));
break;
#endif /* This stuff does not work */
};
@@ -8021,33 +8239,37 @@
tp=&np->target[target];
if (!tp->jump_tcb.l_cmd) {
-
/*
** initialize it.
*/
- tp->jump_tcb.l_cmd = (SCR_JUMP^IFFALSE (DATA (0x80 + target)));
+ tp->jump_tcb.l_cmd =
+ cpu_to_scr((SCR_JUMP^IFFALSE (DATA (0x80 + target))));
tp->jump_tcb.l_paddr = np->jump_tcb.l_paddr;
- tp->getscr[0] =
- (np->features & FE_PFEN)? SCR_COPY(1) : SCR_COPY_F(1);
- tp->getscr[1] = vtophys (&tp->sval);
- tp->getscr[2] = np->paddr + offsetof (struct ncr_reg, nc_sxfer);
- tp->getscr[3] =
- (np->features & FE_PFEN)? SCR_COPY(1) : SCR_COPY_F(1);
- tp->getscr[4] = vtophys (&tp->wval);
- tp->getscr[5] = np->paddr + offsetof (struct ncr_reg, nc_scntl3);
+ tp->getscr[0] = (np->features & FE_PFEN) ?
+ cpu_to_scr(SCR_COPY(1)):cpu_to_scr(SCR_COPY_F(1));
+ tp->getscr[1] = cpu_to_scr(vtophys (&tp->sval));
+ tp->getscr[2] =
+ cpu_to_scr(np->paddr + offsetof (struct ncr_reg, nc_sxfer));
+
+ tp->getscr[3] = (np->features & FE_PFEN) ?
+ cpu_to_scr(SCR_COPY(1)):cpu_to_scr(SCR_COPY_F(1));
+ tp->getscr[4] = cpu_to_scr(vtophys (&tp->wval));
+ tp->getscr[5] =
+ cpu_to_scr(np->paddr + offsetof (struct ncr_reg, nc_scntl3));
assert (( (offsetof(struct ncr_reg, nc_sxfer) ^
offsetof(struct tcb , sval )) &3) == 0);
assert (( (offsetof(struct ncr_reg, nc_scntl3) ^
offsetof(struct tcb , wval )) &3) == 0);
- tp->call_lun.l_cmd = (SCR_CALL);
- tp->call_lun.l_paddr = NCB_SCRIPT_PHYS (np, resel_lun);
-
- tp->jump_lcb.l_cmd = (SCR_JUMP);
- tp->jump_lcb.l_paddr = NCB_SCRIPTH_PHYS (np, abort);
- np->jump_tcb.l_paddr = vtophys (&tp->jump_tcb);
+ tp->call_lun.l_cmd = cpu_to_scr(SCR_CALL);
+ tp->call_lun.l_paddr =
+ cpu_to_scr(NCB_SCRIPT_PHYS (np, resel_lun));
+
+ tp->jump_lcb.l_cmd = cpu_to_scr(SCR_JUMP);
+ tp->jump_lcb.l_paddr = cpu_to_scr(NCB_SCRIPTH_PHYS (np, abort));
+ np->jump_tcb.l_paddr = cpu_to_scr(vtophys (&tp->jump_tcb));
}
/*
@@ -8070,14 +8292,17 @@
** Initialize it
*/
bzero (lp, sizeof (*lp));
- lp->jump_lcb.l_cmd = (SCR_JUMP ^ IFFALSE (DATA (lun)));
+ lp->jump_lcb.l_cmd =
+ cpu_to_scr(SCR_JUMP ^ IFFALSE (DATA (lun)));
lp->jump_lcb.l_paddr = tp->jump_lcb.l_paddr;
- lp->call_tag.l_cmd = (SCR_CALL);
- lp->call_tag.l_paddr = NCB_SCRIPT_PHYS (np, resel_tag);
-
- lp->jump_ccb.l_cmd = (SCR_JUMP);
- lp->jump_ccb.l_paddr = NCB_SCRIPTH_PHYS (np, aborttag);
+ lp->call_tag.l_cmd = cpu_to_scr(SCR_CALL);
+ lp->call_tag.l_paddr =
+ cpu_to_scr(NCB_SCRIPT_PHYS (np, resel_tag));
+
+ lp->jump_ccb.l_cmd = cpu_to_scr(SCR_JUMP);
+ lp->jump_ccb.l_paddr =
+ cpu_to_scr(NCB_SCRIPTH_PHYS (np, aborttag));
lp->actlink = 1;
@@ -8086,7 +8311,7 @@
/*
** Chain into LUN list
*/
- tp->jump_lcb.l_paddr = vtophys (&lp->jump_lcb);
+ tp->jump_lcb.l_paddr = cpu_to_scr(vtophys (&lp->jump_lcb));
tp->lp[lun] = lp;
ncr_setmaxtags (np, tp, driver_setup.default_tags);
@@ -8138,11 +8363,11 @@
/*
** Chain into reselect list
*/
- cp->jump_ccb.l_cmd = SCR_JUMP;
+ cp->jump_ccb.l_cmd = cpu_to_scr(SCR_JUMP);
cp->jump_ccb.l_paddr = lp->jump_ccb.l_paddr;
- lp->jump_ccb.l_paddr = CCB_PHYS (cp, jump_ccb);
- cp->call_tmp.l_cmd = SCR_CALL;
- cp->call_tmp.l_paddr = NCB_SCRIPT_PHYS (np, resel_tmp);
+ lp->jump_ccb.l_paddr = cpu_to_scr(CCB_PHYS (cp, jump_ccb));
+ cp->call_tmp.l_cmd = cpu_to_scr(SCR_CALL);
+ cp->call_tmp.l_paddr = cpu_to_scr(NCB_SCRIPT_PHYS (np, resel_tmp));
/*
** Chain into wakeup list
@@ -8255,9 +8480,9 @@
if (!use_sg) {
if (cmd->request_bufflen) {
data = &data[MAX_SCATTER - 1];
- data[0].addr = vtophys(cmd->request_buffer);
- data[0].size = cmd->request_bufflen;
- cp->data_len = data[0].size;
+ data[0].addr = cpu_to_scr(vtophys(cmd->request_buffer));
+ data[0].size = cpu_to_scr(cmd->request_bufflen);
+ cp->data_len = cmd->request_bufflen;
segment = 1;
}
}
@@ -8266,9 +8491,11 @@
data = &data[MAX_SCATTER - use_sg];
while (segment < use_sg) {
- data[segment].addr = vtophys(scatter[segment].address);
- data[segment].size = scatter[segment].length;
- cp->data_len += data[segment].size;
+ data[segment].addr =
+ cpu_to_scr(vtophys(scatter[segment].address));
+ data[segment].size =
+ cpu_to_scr(scatter[segment].length);
+ cp->data_len += scatter[segment].length;
++segment;
}
}
@@ -8338,7 +8565,7 @@
/*
** Set memory and register.
*/
- np->ncr_cache = host_wr;
+ np->ncr_cache = cpu_to_scr(host_wr);
OUTL (nc_temp, ncr_wr);
/*
** Start script (exchange values)
@@ -8357,7 +8584,7 @@
/*
** Read memory and register.
*/
- host_rd = np->ncr_cache;
+ host_rd = scr_to_cpu(np->ncr_cache);
ncr_rd = INL (nc_scratcha);
ncr_bk = INL (nc_temp);
/*
@@ -8575,7 +8802,7 @@
OUTB(nc_stest3, HSC); /* Halt the scsi clock */
OUTB(nc_scntl3, scntl3);
OUTB(nc_stest1, (DBLEN|DBLSEL));/* Select clock multiplier */
- OUTB(nc_stest3, 0x00); /* Restart scsi clock */
+ OUTB(nc_stest3, 0x00|TE); /* Restart scsi clock */
}
@@ -8793,6 +9020,8 @@
driver_setup.irqm = val;
else if (!strncmp(cur, "pcifix:", 7))
driver_setup.pci_fix_up = val;
+ else if (!strncmp(cur, "buschk:", 7))
+ driver_setup.bus_check = val;
#ifdef SCSI_NCR_NVRAM_SUPPORT
else if (!strncmp(cur, "nvram:", 6))
driver_setup.use_nvram = val;
@@ -8803,7 +9032,11 @@
else
printf("ncr53c8xx_setup: unexpected boot option '%.*s' ignored\n", (int)(pc-cur+1), cur);
+#ifdef MODULE
+ if ((cur = strchr(cur, ' ')) != NULL)
+#else
if ((cur = strchr(cur, ',')) != NULL)
+#endif
++cur;
}
#endif /* SCSI_NCR_BOOT_COMMAND_LINE_SUPPORT */
@@ -8832,9 +9065,9 @@
)
{
#define YesNo(y) y ? 'y' : 'n'
- printk("ncr53c8xx: setup=disc:%c,specf:%c,ultra:%c,tags:%d,sync:%d,burst:%d,wide:%c,diff:%d\n",
+ printk("ncr53c8xx: setup=disc:%c,specf:%d,ultra:%c,tags:%d,sync:%d,burst:%d,wide:%c,diff:%d\n",
YesNo(driver_setup.disconnection),
- YesNo(driver_setup.special_features),
+ driver_setup.special_features,
YesNo(driver_setup.ultra_scsi),
driver_setup.default_tags,
driver_setup.default_sync,
@@ -8933,10 +9166,10 @@
h->device_id == devp->chip.device_id)
break;
}
- if (j < count && !devp->attached &&
- !ncr_attach (tpnt, attach_count, devp)) {
- attach_count++;
- devp->attached = 1;
+ if (j < count && !devp->attach_done) {
+ if (!ncr_attach (tpnt, attach_count, devp))
+ attach_count++;
+ devp->attach_done = 1;
}
}
@@ -8979,6 +9212,11 @@
# endif
#endif
+#if defined(SCSI_NCR_BOOT_COMMAND_LINE_SUPPORT) && defined(MODULE)
+if (ncr53c8xx)
+ ncr53c8xx_setup(ncr53c8xx, (int *) 0);
+#endif
+
/*
** Detect all 53c8xx hosts and then attach them.
**
@@ -9040,8 +9278,6 @@
#endif
printf(KERN_INFO "ncr53c8xx: 53c%s detected %s\n",
device[count].chip.name, msg);
-
- device[count].attached = 0;
++count;
}
}
@@ -9054,9 +9290,9 @@
** so try to attach them here.
*/
for (i= 0; i < count; i++) {
- if ((!device[i].attached) && (!ncr_attach (tpnt, attach_count, &device[i]))) {
+ if (!device[i].attach_done &&
+ !ncr_attach (tpnt, attach_count, &device[i])) {
attach_count++;
- device[i].attached = 1;
}
}
@@ -9078,11 +9314,11 @@
uchar cache_line_size, latency_timer;
uchar irq, revision;
#if LINUX_VERSION_CODE >= LinuxVersionCode(1,3,0)
- uint base, io_port;
+ uint base, base_2, io_port;
#else
- ulong base, io_port;
+ ulong base, base_2;
#endif
- int i, error;
+ int i;
#ifdef SCSI_NCR_NVRAM_SUPPORT
ncr_nvram *nvram = device->nvram;
@@ -9092,20 +9328,32 @@
printk(KERN_INFO "ncr53c8xx: at PCI bus %d, device %d, function %d\n",
bus, (int) (device_fn & 0xf8) >> 3, (int) device_fn & 7);
/*
- * Read info from the PCI config space
+ * Read info from the PCI config space.
+ * pcibios_read_config_xxx() functions are assumed to be used for
+ * successfully detected PCI devices.
+ * Expecting error conditions from them is just paranoia,
+ * thus void cast.
*/
- if (
- (error=pcibios_read_config_word(bus, device_fn, PCI_VENDOR_ID, &vendor_id)) ||
- (error=pcibios_read_config_word(bus, device_fn, PCI_DEVICE_ID, &device_id)) ||
- (error=pcibios_read_config_word( bus, device_fn, PCI_COMMAND, &command)) ||
- (error=pcibios_read_config_dword(bus, device_fn, PCI_BASE_ADDRESS_0,&io_port)) ||
- (error=pcibios_read_config_dword(bus, device_fn, PCI_BASE_ADDRESS_1, &base)) ||
- (error=pcibios_read_config_byte(bus, device_fn, PCI_CLASS_REVISION,&revision)) ||
- (error=pcibios_read_config_byte(bus, device_fn, PCI_INTERRUPT_LINE, &irq)) ||
- (error=pcibios_read_config_byte(bus, device_fn, PCI_CACHE_LINE_SIZE, &cache_line_size)) ||
- (error=pcibios_read_config_byte(bus, device_fn, PCI_LATENCY_TIMER, &latency_timer))
- )
- goto err_pcibios;
+ (void) pcibios_read_config_word(bus, device_fn,
+ PCI_VENDOR_ID, &vendor_id);
+ (void) pcibios_read_config_word(bus, device_fn,
+ PCI_DEVICE_ID, &device_id);
+ (void) pcibios_read_config_word(bus, device_fn,
+ PCI_COMMAND, &command);
+ (void) pcibios_read_config_dword(bus, device_fn,
+ PCI_BASE_ADDRESS_0, &io_port);
+ (void) pcibios_read_config_dword(bus, device_fn,
+ PCI_BASE_ADDRESS_1, &base);
+ (void) pcibios_read_config_dword(bus, device_fn,
+ PCI_BASE_ADDRESS_2, &base_2);
+ (void) pcibios_read_config_byte(bus, device_fn,
+ PCI_CLASS_REVISION,&revision);
+ (void) pcibios_read_config_byte(bus, device_fn,
+ PCI_INTERRUPT_LINE, &irq);
+ (void) pcibios_read_config_byte(bus, device_fn,
+ PCI_CACHE_LINE_SIZE, &cache_line_size);
+ (void) pcibios_read_config_byte(bus, device_fn,
+ PCI_LATENCY_TIMER, &latency_timer);
/*
* Check if the chip is supported
@@ -9126,6 +9374,28 @@
return -1;
}
+#ifdef __powerpc__
+ /*
+ * Severall fix-up for power/pc.
+ * Should not be performed by the driver.
+ */
+ if ((command &
+ (PCI_COMMAND_MASTER|PCI_COMMAND_IO|PCI_COMMAND_MEMORY)) !=
+ (PCI_COMMAND_MASTER|PCI_COMMAND_IO|PCI_COMMAND_MEMORY)) {
+ printk("ncr53c8xx : setting PCI master/io/command bit\n");
+ command |= PCI_COMMAND_MASTER|PCI_COMMAND_IO|PCI_COMMAND_MEMORY;
+ pcibios_write_config_word(bus, device_fn, PCI_COMMAND, command);
+ }
+ if (io_port >= 0x10000000) {
+ io_port = (io_port & 0x00FFFFFF) | 0x01000000;
+ pcibios_write_config_dword(bus, device_fn, PCI_BASE_ADDRESS_0, io_port);
+ }
+ if (base >= 0x10000000) {
+ base = (base & 0x00FFFFFF) | 0x01000000;
+ pcibios_write_config_dword(bus, device_fn, PCI_BASE_ADDRESS_1, base);
+ }
+#endif
+
/*
* Check availability of IO space, memory space and master capability.
*/
@@ -9158,6 +9428,8 @@
return -1;
}
+ base_2 &= PCI_BASE_ADDRESS_MEM_MASK;
+
if (io_port && check_region (io_port, 128)) {
printk("ncr53c8xx: IO region 0x%x to 0x%x is in use\n",
(int) io_port, (int) (io_port + 127));
@@ -9172,8 +9444,12 @@
/*
* Fix some features according to driver setup.
*/
- if (!driver_setup.special_features)
+ if (!(driver_setup.special_features & 1))
chip->features &= ~FE_SPECIAL_SET;
+ else {
+ if (driver_setup.special_features & 2)
+ chip->features &= ~FE_WRIE;
+ }
if (driver_setup.ultra_scsi < 2 && (chip->features & FE_ULTRA2)) {
chip->features |= FE_ULTRA;
chip->features &= ~FE_ULTRA2;
@@ -9192,15 +9468,18 @@
#if defined(__i386) && !defined(MODULE)
if ((driver_setup.pci_fix_up & 1) &&
(chip->features & FE_CLSE) && cache_line_size == 0) {
+#if LINUX_VERSION_CODE < LinuxVersionCode(2,1,75)
extern char x86;
switch(x86) {
+#else
+ switch(boot_cpu_data.x86) {
+#endif
case 4: cache_line_size = 4; break;
case 5: cache_line_size = 8; break;
}
if (cache_line_size)
- error = pcibios_write_config_byte(bus, device_fn, PCI_CACHE_LINE_SIZE, cache_line_size);
- if (error)
- goto err_pcibios;
+ (void) pcibios_write_config_byte(bus, device_fn,
+ PCI_CACHE_LINE_SIZE, cache_line_size);
if (initverbose)
printk("ncr53c8xx: setting PCI_CACHE_LINE_SIZE to %d (fix-up).\n", cache_line_size);
}
@@ -9208,9 +9487,8 @@
if ((driver_setup.pci_fix_up & 2) && cache_line_size &&
(chip->features & FE_WRIE) && !(command & PCI_COMMAND_INVALIDATE)) {
command |= PCI_COMMAND_INVALIDATE;
- error=pcibios_write_config_word(bus, device_fn, PCI_COMMAND, command);
- if (error)
- goto err_pcibios;
+ (void) pcibios_write_config_word(bus, device_fn,
+ PCI_COMMAND, command);
if (initverbose)
printk("ncr53c8xx: setting PCI_COMMAND_INVALIDATE bit (fix-up).\n");
}
@@ -9252,10 +9530,8 @@
latency_timer = lt;
if (initverbose)
printk("ncr53c8xx: setting PCI_LATENCY_TIMER to %d bus clocks (fix-up).\n", latency_timer);
- error = pcibios_write_config_byte(bus, device_fn,
+ (void) pcibios_write_config_byte(bus, device_fn,
PCI_LATENCY_TIMER, latency_timer);
- if (error)
- goto err_pcibios;
}
}
@@ -9281,9 +9557,10 @@
device->slot.bus = bus;
device->slot.device_fn = device_fn;
device->slot.base = base;
+ device->slot.base_2 = base_2;
device->slot.io_port = io_port;
device->slot.irq = irq;
- device->attached = 0;
+ device->attach_done = 0;
#ifdef SCSI_NCR_NVRAM_SUPPORT
if (!nvram)
goto out;
@@ -9331,11 +9608,6 @@
#endif /* SCSI_NCR_NVRAM_SUPPORT */
return 0;
-
-err_pcibios:
- printk("ncr53c8xx: error %s reading configuration space\n",
- pcibios_strerror(error));
- return -1;
}
#if LINUX_VERSION_CODE >= LinuxVersionCode(2,0,0)
@@ -9394,47 +9666,41 @@
}
/*
-** Linux entry point of the interrupt handler
+** Linux entry point of the interrupt handler.
+** Fort linux versions > 1.3.70, we trust the kernel for
+** passing the internal host descriptor as 'dev_id'.
+** Otherwise, we scan the host list and call the interrupt
+** routine for each host that uses this IRQ.
*/
#if LINUX_VERSION_CODE >= LinuxVersionCode(1,3,70)
static void ncr53c8xx_intr(int irq, void *dev_id, struct pt_regs * regs)
+{
+#ifdef DEBUG_NCR53C8XX
+ printk("ncr53c8xx : interrupt received\n");
+#endif
+
+ if (DEBUG_FLAGS & DEBUG_TINY) printf ("[");
+ ncr_exception((ncb_p) dev_id);
+ if (DEBUG_FLAGS & DEBUG_TINY) printf ("]\n");
+}
+
#else
static void ncr53c8xx_intr(int irq, struct pt_regs * regs)
-#endif
{
struct Scsi_Host *host;
struct host_data *host_data;
-#if 0
- u_long flags;
-
- save_flags(flags); cli();
-#endif
-
-#ifdef DEBUG_NCR53C8XX
-printk("ncr53c8xx : interrupt received\n");
-#endif
for (host = first_host; host; host = host->next) {
if (host->hostt == the_template && host->irq == irq) {
host_data = (struct host_data *) host->hostdata;
-#if LINUX_VERSION_CODE >= LinuxVersionCode(1,3,70)
-# ifdef SCSI_NCR_SHARE_IRQ
- if (dev_id == host_data->ncb) {
-#else
- if (1) {
-# endif
-#endif
- if (DEBUG_FLAGS & DEBUG_TINY) printf ("[");
- ncr_exception(host_data->ncb);
- if (DEBUG_FLAGS & DEBUG_TINY) printf ("]\n");
- }
+ if (DEBUG_FLAGS & DEBUG_TINY) printf ("[");
+ ncr_exception(host_data->ncb);
+ if (DEBUG_FLAGS & DEBUG_TINY) printf ("]\n");
}
}
-#if 0
- restore_flags(flags);
-#endif
}
+#endif
/*
** Linux entry point of the timer handler
@@ -9540,17 +9806,10 @@
#ifdef MODULE
int ncr53c8xx_release(struct Scsi_Host *host)
{
- struct host_data *host_data;
#ifdef DEBUG_NCR53C8XX
printk("ncr53c8xx : release\n");
#endif
-
- for (host = first_host; host; host = host->next) {
- if (host->hostt == the_template) {
- host_data = (struct host_data *) host->hostdata;
- ncr_detach(host_data->ncb, host->irq);
- }
- }
+ ncr_detach(((struct host_data *) host->hostdata)->ncb);
return 1;
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov