diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2000-06-19 22:45:37 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2000-06-19 22:45:37 +0000 |
commit | 6d403070f28cd44860fdb3a53be5da0275c65cf4 (patch) | |
tree | 0d0e7fe7b5fb7568d19e11d7d862b77a866ce081 /drivers/scsi | |
parent | ecf1bf5f6c2e668d03b0a9fb026db7aa41e292e1 (diff) |
Merge with 2.4.0-test1-ac21 + pile of MIPS cleanups to make merging
possible. Chainsawed RM200 kernel to compile again. Jazz machine
status unknown.
Diffstat (limited to 'drivers/scsi')
45 files changed, 3385 insertions, 1946 deletions
diff --git a/drivers/scsi/3w-xxxx.c b/drivers/scsi/3w-xxxx.c index 31adb57fa..b3b8d17fb 100644 --- a/drivers/scsi/3w-xxxx.c +++ b/drivers/scsi/3w-xxxx.c @@ -565,6 +565,8 @@ int tw_findcards(Scsi_Host_Template *tw_host) dprintk(KERN_NOTICE "3w-xxxx: tw_findcards()\n"); while ((tw_pci_dev = pci_find_device(TW_VENDOR_ID, TW_DEVICE_ID, tw_pci_dev))) { + if (pci_enable_device(tw_pci_dev)) + continue; /* Prepare temporary device extension */ tw_dev=(TW_Device_Extension *)kmalloc(sizeof(TW_Device_Extension), GFP_ATOMIC); if (tw_dev == NULL) { @@ -582,11 +584,11 @@ int tw_findcards(Scsi_Host_Template *tw_host) } /* Calculate the cards register addresses */ - tw_dev->registers.base_addr = tw_pci_dev->resource[0].start; - tw_dev->registers.control_reg_addr = (tw_pci_dev->resource[0].start & ~15); - tw_dev->registers.status_reg_addr = ((tw_pci_dev->resource[0].start & ~15) + 0x4); - tw_dev->registers.command_que_addr = ((tw_pci_dev->resource[0].start & ~15) + 0x8); - tw_dev->registers.response_que_addr = ((tw_pci_dev->resource[0].start & ~15) + 0xC); + tw_dev->registers.base_addr = pci_resource_start(tw_pci_dev, 0); + tw_dev->registers.control_reg_addr = pci_resource_start(tw_pci_dev, 0); + tw_dev->registers.status_reg_addr = pci_resource_start(tw_pci_dev, 0) + 0x4; + tw_dev->registers.command_que_addr = pci_resource_start(tw_pci_dev, 0) + 0x8; + tw_dev->registers.response_que_addr = pci_resource_start(tw_pci_dev, 0) + 0xC; /* Save pci_dev struct to device extension */ tw_dev->tw_pci_dev = tw_pci_dev; diff --git a/drivers/scsi/53c7,8xx.c b/drivers/scsi/53c7,8xx.c index 30ad34200..7a3e28f7a 100644 --- a/drivers/scsi/53c7,8xx.c +++ b/drivers/scsi/53c7,8xx.c @@ -1412,8 +1412,10 @@ ncr_pci_init (Scsi_Host_Template *tpnt, int board, int chip, " perhaps you specified an incorrect PCI bus, device, or function.\n", error); return -1; } - io_port = pdev->resource[0].start; - base = pdev->resource[1].start; + if (pci_enable_device(pdev)) + return -1; + io_port = pci_resource_start(pdev, 0); + base = pci_resource_start(pdev, 1); irq = pdev->irq; /* If any one ever clones the NCR chips, this will have to change */ diff --git a/drivers/scsi/AM53C974.c b/drivers/scsi/AM53C974.c index 74b63bd37..7abe05e6c 100644 --- a/drivers/scsi/AM53C974.c +++ b/drivers/scsi/AM53C974.c @@ -616,27 +616,23 @@ void AM53C974_setup(char *str, int *ints) * * Returns : number of host adapters detected **************************************************************************/ -static __inline__ int AM53C974_pci_detect(Scsi_Host_Template * tpnt) +static inline int AM53C974_pci_detect(Scsi_Host_Template * tpnt) { int count = 0; /* number of boards detected */ struct pci_dev *pdev = NULL; unsigned short command; while ((pdev = pci_find_device(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_SCSI, pdev))) { + if (pci_enable_device(pdev)) + continue; pci_read_config_word(pdev, PCI_COMMAND, &command); /* check whether device is I/O mapped -- should be */ if (!(command & PCI_COMMAND_IO)) continue; - /* PCI Spec 2.1 states that it is either the driver's or the PCI card's responsibility - to set the PCI Master Enable Bit if needed. - (from Mark Stockton <marks@schooner.sys.hou.compaq.com>) */ - if (!(command & PCI_COMMAND_MASTER)) { - command |= PCI_COMMAND_MASTER; - printk("PCI Master Bit has not been set. Setting...\n"); - pci_write_config_word(pdev, PCI_COMMAND, command); - } + pci_set_master (pdev); + /* everything seems OK now, so initialize */ if (AM53C974_init(tpnt, pdev)) count++; @@ -696,7 +692,7 @@ static int __init AM53C974_init(Scsi_Host_Template * tpnt, struct pci_dev *pdev instance = scsi_register(tpnt, sizeof(struct AM53C974_hostdata)); hostdata = (struct AM53C974_hostdata *) instance->hostdata; instance->base = 0; - instance->io_port = pdev->resource[0].start; + instance->io_port = pci_resource_start(pdev, 0); instance->irq = pdev->irq; instance->dma_channel = -1; AM53C974_setio(instance); diff --git a/drivers/scsi/BusLogic.c b/drivers/scsi/BusLogic.c index aa61a55f8..c648fed02 100644 --- a/drivers/scsi/BusLogic.c +++ b/drivers/scsi/BusLogic.c @@ -771,12 +771,15 @@ static int BusLogic_InitializeMultiMasterProbeInfo(BusLogic_HostAdapter_T unsigned char Bus = PCI_Device->bus->number; unsigned char Device = PCI_Device->devfn >> 3; unsigned int IRQ_Channel = PCI_Device->irq; - unsigned long BaseAddress0 = PCI_Device->resource[0].start; - unsigned long BaseAddress1 = PCI_Device->resource[1].start; + unsigned long BaseAddress0 = pci_resource_start(PCI_Device, 0); + unsigned long BaseAddress1 = pci_resource_start(PCI_Device, 1); BusLogic_IO_Address_T IO_Address = BaseAddress0; BusLogic_PCI_Address_T PCI_Address = BaseAddress1; + + if (pci_enable_device(PCI_Device)) + continue; - if (!(PCI_Device->resource[0].flags & PCI_BASE_ADDRESS_SPACE_IO)) + if (pci_resource_flags(PCI_Device, 0) & IORESOURCE_MEM) { BusLogic_Error("BusLogic: Base Address0 0x%X not I/O for " "MultiMaster Host Adapter\n", NULL, BaseAddress0); @@ -784,7 +787,7 @@ static int BusLogic_InitializeMultiMasterProbeInfo(BusLogic_HostAdapter_T NULL, Bus, Device, IO_Address); continue; } - if (PCI_Device->resource[1].flags & PCI_BASE_ADDRESS_SPACE_IO) + if (pci_resource_flags(PCI_Device,1) & IORESOURCE_IO) { BusLogic_Error("BusLogic: Base Address1 0x%X not Memory for " "MultiMaster Host Adapter\n", NULL, BaseAddress1); @@ -973,7 +976,10 @@ static int BusLogic_InitializeMultiMasterProbeInfo(BusLogic_HostAdapter_T unsigned char Bus = PCI_Device->bus->number; unsigned char Device = PCI_Device->devfn >> 3; unsigned int IRQ_Channel = PCI_Device->irq; - BusLogic_IO_Address_T IO_Address = PCI_Device->resource[0].start; + BusLogic_IO_Address_T IO_Address = pci_resource_start(PCI_Device, 0); + + if (pci_enable_device(PCI_Device)) + continue; if (IO_Address == 0 || IRQ_Channel == 0) continue; for (i = 0; i < BusLogic_ProbeInfoCount; i++) @@ -1017,12 +1023,16 @@ static int BusLogic_InitializeFlashPointProbeInfo(BusLogic_HostAdapter_T unsigned char Bus = PCI_Device->bus->number; unsigned char Device = PCI_Device->devfn >> 3; unsigned int IRQ_Channel = PCI_Device->irq; - unsigned long BaseAddress0 = PCI_Device->resource[0].start; - unsigned long BaseAddress1 = PCI_Device->resource[1].start; + unsigned long BaseAddress0 = pci_resource_start(PCI_Device, 0); + unsigned long BaseAddress1 = pci_resource_start(PCI_Device, 1); BusLogic_IO_Address_T IO_Address = BaseAddress0; BusLogic_PCI_Address_T PCI_Address = BaseAddress1; + + if (pci_enable_device(PCI_Device)) + continue; + #ifndef CONFIG_SCSI_OMIT_FLASHPOINT - if (!(PCI_Device->resource[0].flags & PCI_BASE_ADDRESS_SPACE_IO)) + if (pci_resource_flags(PCI_Device, 0) & IORESOURCE_MEM) { BusLogic_Error("BusLogic: Base Address0 0x%X not I/O for " "FlashPoint Host Adapter\n", NULL, BaseAddress0); @@ -1030,7 +1040,7 @@ static int BusLogic_InitializeFlashPointProbeInfo(BusLogic_HostAdapter_T NULL, Bus, Device, IO_Address); continue; } - if (PCI_Device->resource[1].flags & PCI_BASE_ADDRESS_SPACE_IO) + if (pci_resource_flags(PCI_Device, 1) & IORESOURCE_IO) { BusLogic_Error("BusLogic: Base Address1 0x%X not Memory for " "FlashPoint Host Adapter\n", NULL, BaseAddress1); diff --git a/drivers/scsi/ChangeLog.ips b/drivers/scsi/ChangeLog.ips index 38848f751..52c273673 100644 --- a/drivers/scsi/ChangeLog.ips +++ b/drivers/scsi/ChangeLog.ips @@ -1,25 +1,53 @@ -Change Log -~~~~~~~~~~ +IBM ServeRAID driver Change Log +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + 4.00.06 - Fix timeout with initial FFDC command + + 4.00.05 - Remove wish_block from init routine + - Use linux/spinlock.h instead of asm/spinlock.h for kernels + 2.3.18 and later + - Sync with other changes from the 2.3 kernels - 1.00.00 - Initial Public Release - - Functionally equivalent to 0.99.05 + 4.00.04 - Rename structures/constants to be prefixed with IPS_ + + 4.00.03 - Add alternative passthru interface + - Add ability to flash ServeRAID BIOS + + 4.00.02 - Fix problem with PT DCDB with no buffer + + 4.00.01 - Add support for First Failure Data Capture + + 4.00.00 - Add support for ServeRAID 4 + + 3.60.02 - Make DCDB direction based on lookup table. + - Only allow one DCDB command to a SCSI ID at a time. + + 3.60.01 - Remove bogus error check in passthru routine. + + 3.60.00 - Bump max commands to 128 for use with ServeRAID + firmware 3.60. + - Change version to 3.60 to coincide with ServeRAID release + numbering. + + 1.00.00 - Initial Public Release + - Functionally equivalent to 0.99.05 0.99.05 - Fix an oops on certain passthru commands - 0.99.04 - Fix race condition in the passthru mechanism + 0.99.04 - Fix race condition in the passthru mechanism -- this required the interface to the utilities to change - - Fix error recovery code + - Fix error recovery code - 0.99.03 - Make interrupt routine handle all completed request on the - adapter not just the first one - - Make sure passthru commands get woken up if we run out of - SCBs - - Send all of the commands on the queue at once rather than - one at a time since the card will support it. + 0.99.03 - Make interrupt routine handle all completed request on the + adapter not just the first one + - Make sure passthru commands get woken up if we run out of + SCBs + - Send all of the commands on the queue at once rather than + one at a time since the card will support it. - 0.99.02 - Added some additional debug statements to print out + 0.99.02 - Added some additional debug statements to print out errors if an error occurs while trying to read/write to a logical drive (IPS_DEBUG). - Fixed read/write errors when the adapter is using an + - Fixed read/write errors when the adapter is using an 8K stripe size. + diff --git a/drivers/scsi/ChangeLog.ncr53c8xx b/drivers/scsi/ChangeLog.ncr53c8xx index 80a28c9f4..bce816f9e 100644 --- a/drivers/scsi/ChangeLog.ncr53c8xx +++ b/drivers/scsi/ChangeLog.ncr53c8xx @@ -1,3 +1,6 @@ +Thu May 11 12:30 2000 Pam Delaney (pam.delaney@lsil.com) + * revision 3.3b + Mon Apr 24 12:00 2000 Gerard Roudier (groudier@club-internet.fr) * revision 3.2i - Return value 1 (instead of 0) from the driver setup routine. @@ -14,6 +17,11 @@ Sat Apr 1 12:00 2000 Gerard Roudier (groudier@club-internet.fr) that supply SCSI_DATA_NONE direction (this avoids some BUG() statement in the PCI code when a data buffer is also supplied). +Thu Mar 16 9:30 2000 Pam Delaney (pam.delaney@lsil.com) + * revision 3.3b-3 + - Added exclusion for the 53C1010 and 53C1010_66 chips + to the driver (change to sym53c8xx_comm.h). + Mon March 6 23:15 2000 Gerard Roudier (groudier@club-internet.fr) * revision 3.2g - Add the file sym53c8xx_comm.h that collects code that should @@ -31,6 +39,40 @@ Mon March 6 23:15 2000 Gerard Roudier (groudier@club-internet.fr) - Get data transfer direction from the scsi command structure (Scsi_Cmnd) when this information is available. +Mon March 6 23:15 2000 Gerard Roudier (groudier@club-internet.fr) + * revision 3.2g + - Add the file sym53c8xx_comm.h that collects code that should + be shared by sym53c8xx and ncr53c8xx drivers. For now, it is + a header file that is only included by the ncr53c8xx driver, + but things will be cleaned up later. This code addresses + notably: + * Chip detection and PCI related initialisations + * NVRAM detection and reading + * DMA mapping + * Boot setup command + * And some other ... + - Add support for the new dynamic dma mapping kernel interface. + Requires Linux-2.3.47 (tested with pre-2.3.47-6). + - Get data transfer direction from the scsi command structure + (Scsi_Cmnd) when this information is available. + +Fri Jan 14 14:00 2000 Pam Delaney (pam.delaney@lsil.com) + * revision pre-3.3b-1 + - Merge parallel driver series 3.31 and 3.2e + +Tue Jan 11 14:00 2000 Pam Delaney (pam.delaney@lsil.com) + * revision 3.31 + - Added support for mounting disks on wide-narrow-wide + scsi configurations. + - Built off of version 3.30 + +Mon Jan 10 13:30 2000 Pam Delaney (pam.delaney@lsil.com) + * revision 3.30 + - Added capability to use the integrity checking code + in the kernel (optional). + - Disabled support for the 53C1010. + - Built off of version 3.2c + Sat Jan 8 22:00 2000 Gerard Roudier (groudier@club-internet.fr) * revision 3.2e - Add year 2000 copyright. @@ -94,7 +136,7 @@ Thu Mar 11 23:00 1999 Gerard Roudier (groudier@club-internet.fr) * revision 3.2 (8xx-896 driver bundle) - Only define the host template in ncr53c8xx.h and include the sym53c8xx_defs.h file. - - Declare static all symbols that donnot need to be visible from + - Declare static all symbols that do not need to be visible from outside the driver code. - Add 'excl' boot command option that allows to pass to the driver io address of devices not to attach. diff --git a/drivers/scsi/ChangeLog.sym53c8xx b/drivers/scsi/ChangeLog.sym53c8xx index ced86ef14..f17cc7466 100644 --- a/drivers/scsi/ChangeLog.sym53c8xx +++ b/drivers/scsi/ChangeLog.sym53c8xx @@ -1,9 +1,20 @@ +Thu May 11 12:40 2000 Pam Delaney (pam.delaney@lsil.com) + * version sym53c8xx-1.6b + - Merged version. + Mon Apr 24 12:00 2000 Gerard Roudier (groudier@club-internet.fr) * version sym53c8xx-1.5m - Return value 1 (instead of 0) from the driver setup routine. - - Donnot enable PCI DAC cycles. This just broke support for + - Do not enable PCI DAC cycles. This just broke support for SYM534C896 on sparc64. Problem fixed by David S. Miller. +Fri Apr 14 9:00 2000 Pam Delaney (pam.delaney@lsil.com) + * version sym53c8xx-1.6b-9 + - Added 53C1010_66 support. + - Small fix to integrity checking code. + - Removed requirement for integrity checking if want to run + at ultra 3. + Sat Apr 1 12:00 2000 Gerard Roudier (groudier@club-internet.fr) * version sym53c8xx-1.5l - Tiny change for __sparc__ appeared in 2.3.99-pre4.1 that @@ -12,6 +23,16 @@ Sat Apr 1 12:00 2000 Gerard Roudier (groudier@club-internet.fr) that supply SCSI_DATA_NONE direction (this avoids some BUG() statement in the PCI code when a data buffer is also supplied). +Sat Mar 11 12:00 2000 Gerard Roudier (groudier@club-internet.fr) + * version sym53c8xx-1.6b-5 + - Test against expected data transfer direction from SCRIPTS. + - Add support for the new dynamic dma mapping kernel interface. + Requires Linux-2.3.47 (tested with pre-2.3.47-6). + Many thanks to David S. Miller for his preliminary changes + that have been useful guidelines. + - Get data transfer direction from the scsi command structure + (Scsi_Cmnd) with kernels that provide this information. + Mon Mar 6 23:30 2000 Gerard Roudier (groudier@club-internet.fr) * version sym53c8xx-1.5k - Test against expected data transfer direction from SCRIPTS. @@ -21,6 +42,16 @@ Mon Mar 6 23:30 2000 Gerard Roudier (groudier@club-internet.fr) - Miscellaneous (minor) fixes in the code added in driver version 1.5j. +Mon Feb 14 4:00 2000 Pam Delaney (pam.delaney@lsil.com) + * version sym53c8xx-pre-1.6b-2. + - Updated the SCRIPTS error handling of the SWIDE + condition - to remove any reads of the sbdl + register. Changes needed because the 896 and 1010 + chips will check parity in some special circumstances. + This will cause a parity error interrupt if not in + data phase. Changes based on those made in the + FreeBSD driver version 1.3.2. + Sun Feb 20 11:00 2000 Gerard Roudier (groudier@club-internet.fr) * version sym53c8xx-1.5j - Add support for the new dynamic dma mapping kernel interface. @@ -35,6 +66,26 @@ Sun Feb 20 11:00 2000 Gerard Roudier (groudier@club-internet.fr) - Fix an old bug that only affected 896 rev. 1 when driver profile support option was set in kernel configuration. +Fri Jan 14 14:00 2000 Pam Delaney (pam.delaney@lsil.com) + * version sym53c8xx-pre-1.6b-1. + - Merge parallel driver series 1.61 and 1.5e + +Tue Jan 11 14:00 2000 Pam Delaney (pam.delaney@lsil.com) + * version sym53c8xx-1.61 + - Added support for mounting disks on wide-narrow-wide + scsi configurations. + - Modified offset to be a maximum of 31 in ST mode, + 62 in DT mode. + - Based off of 1.60 + +Mon Jan 10 10:00 2000 Pam Delaney (pam.delaney@lsil.com) + * version sym53c8xx-1.60 + - Added capability to use the integrity checking code + in the kernel (optional). + - Added PPR negotiation. + - Added support for 53C1010 Ultra 3 part. + - Based off of 1.5f + Sat Jan 8 22:00 2000 Gerard Roudier (groudier@club-internet.fr) * version sym53c8xx-1.5h - Add year 2000 copyright. @@ -118,7 +169,7 @@ Sat Sep 11 11:00 1999 Gerard Roudier (groudier@club-internet.fr) Sat Jun 5 11:00 1999 Gerard Roudier (groudier@club-internet.fr) * version sym53c8xx-1.5c - - Donnot negotiate on auto-sense if we are currently using 8 bit + - Do not negotiate on auto-sense if we are currently using 8 bit async transfer for the target. - Only check for SISL/RAID on i386 platforms. (A problem has been reported on PPC with that code). @@ -179,7 +230,7 @@ Sun May 9 11:00 1999 Gerard Roudier (groudier@club-internet.fr) - Do some work in SCRIPTS after the SELECT instruction and prior to testing for a PHASE. SYMBIOS say this feature is working fine. (Btw, only problems with Toshiba 3401B had been reported). - - Measure the PCI clock speed and donnot attach controllers if + - Measure the PCI clock speed and do not attach controllers if result is greater than 37 MHz. Since the precision of the algorithm (from Stefan Esser) is better than 2%, this should be fine. @@ -353,7 +404,7 @@ Thu Nov 19 23:00 1998 Gerard Roudier (groudier@club-internet.fr) transactions since those early chip revisions may use such on LOAD/STORE instructions (work-around). - Remove some useless and bloat code from the pci init stuff. - - Donnot use the readX()/writeX() kernel functions for __i386__, + - Do not use the readX()/writeX() kernel functions for __i386__, since they perform useless masking operations in order to deal with broken driver in 2.1.X kernel. @@ -379,7 +430,7 @@ Wed Oct 30 22H00 1998 Gerard Roudier (groudier@club-internet.fr) * version pre-sym53c8xx-0.12 - Damned! I just broke the driver for Alpha by leaving a stale instruction in the source code. Hopefully fixed. - - Donnot set PFEN when it is useless. Doing so we are sure that BOF + - Do not set PFEN when it is useless. Doing so we are sure that BOF will be active, since the manual appears to be very unclear on what feature is actually used by the chip when both PFEN and BOF are set. diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile index e5531e006..1292c50f6 100644 --- a/drivers/scsi/Makefile +++ b/drivers/scsi/Makefile @@ -1,19 +1,18 @@ +# # Makefile for linux/drivers/scsi # -# Note! Dependencies are done automagically by 'make dep', which also -# removes any old dependencies. DON'T put your own dependencies here -# unless it's something special (ie not a .c file). +# 30 May 2000, Christoph Hellwig <chhellwig@gmx.net> +# Rewritten to use lists instead of if-statements. # -L_TARGET := scsi.a -L_OBJS := -M_OBJS := -MX_OBJS := -MIX_OBJS := +O_TARGET := scsidrv.o MOD_LIST_NAME := SCSI_MODULES -SCSI_SRCS = $(wildcard $(L_OBJS:%.o=%.c)) -ALL_SUB_DIRS := pcmcia +SUB_DIRS := +MOD_SUB_DIRS := +MOD_IN_SUBDIRS := +ALL_SUB_DIRS := $(SUB_DIRS) pcmcia + ifeq ($(CONFIG_PCMCIA),y) SUB_DIRS += pcmcia MOD_IN_SUB_DIRS += pcmcia @@ -23,697 +22,146 @@ else endif endif +export-objs := scsi_syms.o +list-multi := scsi_mod.o sr_mod.o initio.o a100u2w.o + CFLAGS_aha152x.o = -DAHA152X_STAT -DAUTOCONF CFLAGS_gdth.o = # -DDEBUG_GDTH=2 -D__SERIAL__ -D__COM2__ -DGDTH_STATISTICS CFLAGS_seagate.o = -DARBITRATE -DPARITY -DSEAGATE_USE_ASM -.SUFFIXES: -.SUFFIXES: .c .o .h .a .S - -ifeq (${CFLAGS},) -CFLAGS = -D__KERNEL__=1 \ - -DMODULE -Wall -Wstrict-prototypes -I. -I../../include \ - -O2 -fomit-frame-pointer - -include ../../.config - -TOPDIR = ../.. - -endif - -ifeq ($(CONFIG_SCSI),y) - # We must attach scsi_syms.o to scsi.o, as otherwise there is nothing to - # pull the object file from the archive. - O_TARGET := scsi_n_syms.o - O_OBJS := scsi.o - ifeq ($(CONFIG_MODULES),y) - OX_OBJS := scsi_syms.o - endif - L_OBJS += scsi_n_syms.o hosts.o scsi_ioctl.o constants.o scsicam.o - L_OBJS += scsi_error.o scsi_obsolete.o scsi_queue.o scsi_lib.o - L_OBJS += scsi_merge.o scsi_proc.o scsi_dma.o scsi_scan.o -else - ifeq ($(CONFIG_SCSI),m) - MIX_OBJS += scsi_syms.o - M_OBJS += scsi_mod.o - endif -endif - -ifeq ($(CONFIG_CHR_DEV_ST),y) -L_OBJS += st.o -else - ifeq ($(CONFIG_CHR_DEV_ST),m) - M_OBJS += st.o - endif -endif - -ifeq ($(CONFIG_BLK_DEV_SD),y) -L_OBJS += sd.o -else - ifeq ($(CONFIG_BLK_DEV_SD),m) - M_OBJS += sd_mod.o - endif -endif - -ifeq ($(CONFIG_BLK_DEV_SR),y) -L_OBJS += sr.o sr_ioctl.o sr_vendor.o -else - ifeq ($(CONFIG_BLK_DEV_SR),m) - M_OBJS += sr_mod.o - endif -endif - -ifeq ($(CONFIG_CHR_DEV_SG),y) -L_OBJS += sg.o -else - ifeq ($(CONFIG_CHR_DEV_SG),m) - M_OBJS += sg.o - endif -endif - -ifeq ($(CONFIG_SCSI_ADVANSYS),y) -L_OBJS += advansys.o -else - ifeq ($(CONFIG_SCSI_ADVANSYS),m) - M_OBJS += advansys.o - endif -endif - -ifeq ($(CONFIG_SCSI_PCI2000),y) -L_OBJS += pci2000.o -else - ifeq ($(CONFIG_SCSI_PCI2000),m) - M_OBJS += pci2000.o - endif -endif - -ifeq ($(CONFIG_SCSI_PCI2220I),y) -L_OBJS += pci2220i.o -else - ifeq ($(CONFIG_SCSI_PCI2220I),m) - M_OBJS += pci2220i.o - endif -endif - -ifeq ($(CONFIG_SCSI_PSI240I),y) -L_OBJS += psi240i.o -else - ifeq ($(CONFIG_SCSI_PSI240I),m) - M_OBJS += psi240i.o - endif -endif - -ifeq ($(CONFIG_MVME16x_SCSI),y) -L_OBJS += mvme16x.o 53c7xx.o -else - ifeq ($(CONFIG_MVME16x_SCSI),m) - M_OBJS += mvme16x.o 53c7xx.o - endif -endif - -ifeq ($(CONFIG_BVME6000_SCSI),y) -L_OBJS += bvme6000.o 53c7xx.o -else - ifeq ($(CONFIG_BVME6000_SCSI),m) - M_OBJS += bvme6000.o 53c7xx.o - endif -endif - -ifeq ($(CONFIG_SCSI_SIM710),y) -L_OBJS += sim710.o -else - ifeq ($(CONFIG_SCSI_SIM710),m) - M_OBJS += sim710.o - endif -endif - -ifeq ($(CONFIG_A4000T_SCSI),y) -L_OBJS += amiga7xx.o 53c7xx.o -else - ifeq ($(CONFIG_A4000T_SCSI),m) - M_OBJS += amiga7xx.o 53c7xx.o - endif -endif - -ifeq ($(CONFIG_A4091_SCSI),y) -L_OBJS += amiga7xx.o 53c7xx.o -else - ifeq ($(CONFIG_A4091_SCSI),m) - M_OBJS += amiga7xx.o 53c7xx.o - endif -endif - -ifeq ($(CONFIG_BLZ603EPLUS_SCSI),y) -L_OBJS += amiga7xx.o 53c7xx.o -else - ifeq ($(CONFIG_BLZ603EPLUS_SCSI),m) - M_OBJS += amiga7xx.o 53c7xx.o - endif -endif - -ifeq ($(CONFIG_WARPENGINE_SCSI),y) -L_OBJS += amiga7xx.o 53c7xx.o -else - ifeq ($(CONFIG_WARPENGINE_SCSI),m) - M_OBJS += amiga7xx.o 53c7xx.o - endif -endif - -ifeq ($(CONFIG_A3000_SCSI),y) -L_OBJS += a3000.o wd33c93.o -else - ifeq ($(CONFIG_A3000_SCSI),m) - M_OBJS += a3000.o wd33c93.o - endif -endif - -ifeq ($(CONFIG_A2091_SCSI),y) -L_OBJS += a2091.o wd33c93.o -else - ifeq ($(CONFIG_A2091_SCSI),m) - M_OBJS += a2091.o wd33c93.o - endif -endif - -ifeq ($(CONFIG_GVP11_SCSI),y) -L_OBJS += gvp11.o wd33c93.o -else - ifeq ($(CONFIG_GVP11_SCSI),m) - M_OBJS += gvp11.o wd33c93.o - endif -endif - -ifeq ($(CONFIG_SCSI_SGIWD93),y) -L_OBJS += sgiwd93.o wd33c93.o -else - ifeq ($(CONFIG_SCSI_SGIWD93),m) - M_OBJS += sgiwd93.o wd33c93.o - endif -endif - -ifeq ($(CONFIG_SCSI_MCA_53C9X),y) -L_OBJS += NCR53C9x.o mca_53c9x.o -else - ifeq ($(CONFIG_SCSI_MCA_53C9X),m) - M_OBJS += NCR53C9x.o mca_53c9x.o - endif -endif - -ifeq ($(CONFIG_CYBERSTORM_SCSI),y) -L_OBJS += NCR53C9x.o cyberstorm.o -else - ifeq ($(CONFIG_CYBERSTORM_SCSI),m) - M_OBJS += NCR53C9x.o cyberstorm.o - endif -endif - -ifeq ($(CONFIG_CYBERSTORMII_SCSI),y) -L_OBJS += NCR53C9x.o cyberstormII.o -else - ifeq ($(CONFIG_CYBERSTORMII_SCSI),m) - M_OBJS += NCR53C9x.o cyberstormII.o - endif -endif - -ifeq ($(CONFIG_BLZ2060_SCSI),y) -L_OBJS += NCR53C9x.o blz2060.o -else - ifeq ($(CONFIG_BLZ2060_SCSI),m) - M_OBJS += NCR53C9x.o blz2060.o - endif -endif - -ifeq ($(CONFIG_BLZ1230_SCSI),y) -L_OBJS += NCR53C9x.o blz1230.o -else - ifeq ($(CONFIG_BLZ1230_SCSI),m) - M_OBJS += NCR53C9x.o blz1230.o - endif -endif - -ifeq ($(CONFIG_FASTLANE_SCSI),y) -L_OBJS += NCR53C9x.o fastlane.o -else - ifeq ($(CONFIG_FASTLANE_SCSI),m) - M_OBJS += NCR53C9x.o fastlane.o - endif -endif - -ifeq ($(CONFIG_OKTAGON_SCSI),y) -L_OBJS += NCR53C9x.o oktagon_esp.o oktagon_io.o -else - ifeq ($(CONFIG_OKTAGON_SCSI),m) - M_OBJS += NCR53C9x.o oktagon_esp.o oktagon_io.o - endif -endif - -ifeq ($(CONFIG_ATARI_SCSI),y) -L_OBJS += atari_scsi.o -else - ifeq ($(CONFIG_ATARI_SCSI),m) - M_OBJS += atari_scsi.o - endif -endif - -ifeq ($(CONFIG_MAC_SCSI),y) -L_OBJS += mac_scsi.o -else - ifeq ($(CONFIG_MAC_SCSI),m) - M_OBJS += mac_scsi.o - endif -endif - -ifeq ($(CONFIG_SUN3_SCSI),y) -L_OBJS += sun3_scsi.o -else - ifeq ($(CONFIG_SUN3_SCSI),m) - M_OBJS += sun3_scsi.o - endif -endif - -ifeq ($(CONFIG_SCSI_MAC_ESP),y) -L_OBJS += mac_esp.o NCR53C9x.o -else - ifeq ($(CONFIG_SCSI_MAC_ESP),m) - M_OBJS += mac_esp.o NCR53C9x.o - endif -endif - -ifeq ($(CONFIG_SCSI_PPA),y) -L_OBJS += ppa.o -else - ifeq ($(CONFIG_SCSI_PPA),m) - M_OBJS += ppa.o - endif -endif - -ifeq ($(CONFIG_SCSI_IMM),y) -L_OBJS += imm.o -else - ifeq ($(CONFIG_SCSI_IMM),m) - M_OBJS += imm.o - endif -endif - -ifeq ($(CONFIG_SCSI_QLOGIC_FAS),y) -L_OBJS += qlogicfas.o -else - ifeq ($(CONFIG_SCSI_QLOGIC_FAS),m) - M_OBJS += qlogicfas.o - endif -endif - - -ifeq ($(CONFIG_SCSI_QLOGIC_ISP),y) -L_OBJS += qlogicisp.o -else - ifeq ($(CONFIG_SCSI_QLOGIC_ISP),m) - M_OBJS += qlogicisp.o - endif -endif - -ifeq ($(CONFIG_SCSI_QLOGIC_1280),y) -L_OBJS += qla1280.o -else - ifeq ($(CONFIG_SCSI_QLOGIC_1280),m) - M_OBJS += qla1280.o - endif -endif - -ifeq ($(CONFIG_SCSI_ACARD),y) -L_OBJS += atp870u.o -else - ifeq ($(CONFIG_SCSI_ACARD),m) - M_OBJS += atp870u.o - endif -endif - -ifeq ($(CONFIG_SCSI_INITIO),y) -L_OBJS += initio.o -else - ifeq ($(CONFIG_SCSI_INITIO),m) - M_OBJS += initio.o - endif -endif - -ifeq ($(CONFIG_SCSI_INIA100),y) -L_OBJS += a100u2w.o -else - ifeq ($(CONFIG_SCSI_INIA100),m) - M_OBJS += a100u2w.o - endif -endif - -ifeq ($(CONFIG_SCSI_QLOGIC_FC),y) -L_OBJS += qlogicfc.o -else - ifeq ($(CONFIG_SCSI_QLOGIC_FC),m) - M_OBJS += qlogicfc.o - endif -endif - -ifeq ($(CONFIG_SCSI_AHA152X),y) -L_OBJS += aha152x.o -else - ifeq ($(CONFIG_SCSI_AHA152X),m) - M_OBJS += aha152x.o - endif -endif - -ifeq ($(CONFIG_SCSI_AHA1542),y) -L_OBJS += aha1542.o -else - ifeq ($(CONFIG_SCSI_AHA1542),m) - M_OBJS += aha1542.o - endif -endif - -ifeq ($(CONFIG_SCSI_AHA1740),y) -L_OBJS += aha1740.o -else - ifeq ($(CONFIG_SCSI_AHA1740),m) - M_OBJS += aha1740.o - endif -endif - -ifeq ($(CONFIG_SCSI_AIC7XXX),y) -L_OBJS += aic7xxx.o -else - ifeq ($(CONFIG_SCSI_AIC7XXX),m) - M_OBJS += aic7xxx.o - endif -endif - -ifeq ($(CONFIG_SCSI_IPS),y) -L_OBJS += ips.o -else - ifeq ($(CONFIG_SCSI_IPS),m) - M_OBJS += ips.o - endif -endif - -ifeq ($(CONFIG_SCSI_DC390T),y) -L_OBJS += tmscsim.o -else - ifeq ($(CONFIG_SCSI_DC390T),m) - M_OBJS += tmscsim.o - endif -endif - -ifeq ($(CONFIG_SCSI_AM53C974),y) -L_OBJS += AM53C974.o -else - ifeq ($(CONFIG_SCSI_AM53C974),m) - M_OBJS += AM53C974.o - endif -endif - -ifeq ($(CONFIG_SCSI_BUSLOGIC),y) -L_OBJS += BusLogic.o -else - ifeq ($(CONFIG_SCSI_BUSLOGIC),m) - M_OBJS += BusLogic.o - endif -endif - -ifeq ($(CONFIG_SCSI_EATA_DMA),y) -L_OBJS += eata_dma.o -else - ifeq ($(CONFIG_SCSI_EATA_DMA),m) - M_OBJS += eata_dma.o - endif -endif - -ifeq ($(CONFIG_SCSI_EATA_PIO),y) -L_OBJS += eata_pio.o -else - ifeq ($(CONFIG_SCSI_EATA_PIO),m) - M_OBJS += eata_pio.o - endif -endif - -ifeq ($(CONFIG_SCSI_U14_34F),y) -L_OBJS += u14-34f.o -else - ifeq ($(CONFIG_SCSI_U14_34F),m) - M_OBJS += u14-34f.o - endif -endif - -ifeq ($(CONFIG_SCSI_SUNESP),y) -L_OBJS += esp.o -else - ifeq ($(CONFIG_SCSI_SUNESP),m) - M_OBJS += esp.o - endif -endif - -ifeq ($(CONFIG_SCSI_QLOGICPTI),y) -L_OBJS += qlogicpti.o -else - ifeq ($(CONFIG_SCSI_QLOGICPTI),m) - M_OBJS += qlogicpti.o - endif -endif - -ifeq ($(CONFIG_SCSI_MESH),y) -L_OBJS += mesh.o -else - ifeq ($(CONFIG_SCSI_MESH),m) - M_OBJS += mesh.o - endif -endif - -ifeq ($(CONFIG_SCSI_MAC53C94),y) -L_OBJS += mac53c94.o -else - ifeq ($(CONFIG_SCSI_MAC53C94),m) - M_OBJS += mac53c94.o - endif -endif - -ifeq ($(CONFIG_SCSI_GDTH),y) -L_OBJS += gdth.o -else - ifeq ($(CONFIG_SCSI_GDTH),m) - M_OBJS += gdth.o - endif -endif +obj-$(CONFIG_SCSI) += scsi_mod.o +obj-$(CONFIG_CHR_DEV_ST) += st.o +obj-$(CONFIG_BLK_DEV_SD) += sd.o +obj-$(CONFIG_BLK_DEV_SR) += sr_mod.o +obj-$(CONFIG_CHR_DEV_SG) += sg.o + +obj-$(CONFIG_SCSI_ADVANSYS) += advansys.o +obj-$(CONFIG_SCSI_PCI2000) += pci2000.o +obj-$(CONFIG_SCSI_PCI2220I) += pci2220i.o +obj-$(CONFIG_SCSI_PSI240I) += psi240i.o +obj-$(CONFIG_MVME16x_SCSI) += mvme16x.o 53c7xx.o +obj-$(CONFIG_BVME6000_SCSI) += bvme6000.o 53c7xx.o +obj-$(CONFIG_SCSI_SIM710) += sim710.o +obj-$(CONFIG_A4000T_SCSI) += amiga7xx.o 53c7xx.o +obj-$(CONFIG_A4091_SCSI) += amiga7xx.o 53c7xx.o +obj-$(CONFIG_BLZ603EPLUS_SCSI) += amiga7xx.o 53c7xx.o +obj-$(CONFIG_WARPENGINE_SCSI) += amiga7xx.o 53c7xx.o +obj-$(CONFIG_A3000_SCSI) += a3000.o wd33c93.o +obj-$(CONFIG_A2091_SCSI) += a2091.o wd33c93.o +obj-$(CONFIG_GVP11_SCSI) += gvp11.o wd33c93.o +obj-$(CONFIG_SCSI_SGIWD93) += sgiwd93.o wd33c93.o +obj-$(CONFIG_SCSI_MCA_53C9X) += NCR53C9x.o mca_53c9x.o +obj-$(CONFIG_CYBERSTORM_SCSI) += NCR53C9x.o cyberstorm.o +obj-$(CONFIG_CYBERSTORMII_SCSI) += NCR53C9x.o cyberstormII.o +obj-$(CONFIG_BLZ2060_SCSI) += NCR53C9x.o blz2060.o +obj-$(CONFIG_BLZ1230_SCSI) += NCR53C9x.o blz1230.o +obj-$(CONFIG_FASTLANE_SCSI) += NCR53C9x.o fastlane.o +obj-$(CONFIG_OKTAGON_SCSI) += NCR53C9x.o oktagon_esp.o oktagon_io.o +obj-$(CONFIG_ATARI_SCSI) += atari_scsi.o +obj-$(CONFIG_MAC_SCSI) += mac_scsi.o +obj-$(CONFIG_SUN3_SCSI) += sun3_scsi.o +obj-$(CONFIG_SCSI_MAC_ESP) += mac_esp.o NCR53C9x.o +obj-$(CONFIG_SCSI_PPA) += ppa.o +obj-$(CONFIG_SCSI_IMM) += imm.o +obj-$(CONFIG_SCSI_QLOGIC_FAS) += qlogicfas.o +obj-$(CONFIG_SCSI_QLOGIC_ISP) += qlogicisp.o +obj-$(CONFIG_SCSI_QLOGIC_1280) += qla1280.o +obj-$(CONFIG_SCSI_ACARD) += atp870u.o +obj-$(CONFIG_SCSI_INITIO) += initio.o +obj-$(CONFIG_SCSI_INIA100) += a100u2w.o +obj-$(CONFIG_SCSI_QLOGIC_FC) += qlogicfc.o +obj-$(CONFIG_SCSI_AHA152X) += aha152x.o +obj-$(CONFIG_SCSI_AHA1542) += aha1542.o +obj-$(CONFIG_SCSI_AHA1740) += aha1740.o +obj-$(CONFIG_SCSI_AIC7XXX) += aic7xxx.o +obj-$(CONFIG_SCSI_IPS) += ips.o +obj-$(CONFIG_SCSI_DC390T) += tmscsim.o +obj-$(CONFIG_SCSI_AM53C974) += AM53C974.o +obj-$(CONFIG_SCSI_BUSLOGIC) += BusLogic.o +obj-$(CONFIG_SCSI_EATA_DMA) += eata_dma.o +obj-$(CONFIG_SCSI_EATA_PIO) += eata_pio.o +obj-$(CONFIG_SCSI_U14_34F) += u14-34f.o +obj-$(CONFIG_SCSI_SUNESP) += esp.o +obj-$(CONFIG_SCSI_QLOGICPTI) += qlogicpti.o +obj-$(CONFIG_SCSI_MESH) += mesh.o +obj-$(CONFIG_SCSI_MAC53C94) += mac53c94.o +obj-$(CONFIG_SCSI_GDTH) += gdth.o + +obj-$(CONFIG_SCSI_DEBUG) += scsi_debug.o + +obj-$(CONFIG_SCSI_FUTURE_DOMAIN)+= fdomain.o +obj-$(CONFIG_SCSI_IN2000) += in2000.o +obj-$(CONFIG_SCSI_GENERIC_NCR5380) += g_NCR5380.o +obj-$(CONFIG_SCSI_NCR53C7xx) += 53c7,8xx.o +obj-$(CONFIG_SCSI_NCR53C8XX) += ncr53c8xx.o +obj-$(CONFIG_SCSI_SYM53C8XX) += sym53c8xx.o +obj-$(CONFIG_SCSI_PAS16) += pas16.o +obj-$(CONFIG_SCSI_SEAGATE) += seagate.o +obj-$(CONFIG_SCSI_FD_8xx) += seagate.o +obj-$(CONFIG_SCSI_7000FASST) += wd7000.o +obj-$(CONFIG_SCSI_IBMMCA) += ibmmca.o +obj-$(CONFIG_SCSI_FD_MCS) += fd_mcs.o +obj-$(CONFIG_SCSI_T128) += t128.o +obj-$(CONFIG_SCSI_DMX3191D) += dmx3191d.o +obj-$(CONFIG_SCSI_DTC3280) += dtc.o +obj-$(CONFIG_SCSI_ULTRASTOR) += ultrastor.o +obj-$(CONFIG_SCSI_PLUTO) += pluto.o +obj-$(CONFIG_SCSI_FCAL) += fcal.o +obj-$(CONFIG_SCSI_EATA) += eata.o +obj-$(CONFIG_SCSI_NCR53C406A) += NCR53c406a.o +obj-$(CONFIG_SCSI_MEGARAID) += megaraid.o +obj-$(CONFIG_SCSI_SYM53C416) += sym53c416.o +obj-$(CONFIG_BLK_DEV_IDESCSI) += ide-scsi.o +obj-$(CONFIG_JAZZ_ESP) += NCR53C9x.o jazz_esp.o +obj-$(CONFIG_SCSI_DECNCR) += NCR53C9x.o dec_esp.o +obj-$(CONFIG_SUN3X_ESP) += NCR53C9x.o sun3x_esp.o +obj-$(CONFIG_BLK_DEV_3W_XXXX_RAID) += 3w-xxxx.o + +scsi_mod-objs := hosts.o scsi.o scsi_ioctl.o constants.o \ + scsicam.o scsi_proc.o scsi_error.o \ + scsi_obsolete.o scsi_queue.o scsi_lib.o \ + scsi_merge.o scsi_dma.o scsi_scan.o \ + scsi_syms.o +sr_mod-objs := sr.o sr_ioctl.o sr_vendor.o +initio-objs := ini9100u.o i91uscsi.o +a100u2w-objs := inia100.o i60uscsi.o + +# Extract lists of the multi-part drivers. +# The 'int-*' lists are the intermediate files used to build the multi's. +multi-y := $(filter $(list-multi), $(obj-y)) +multi-m := $(filter $(list-multi), $(obj-m)) +int-y := $(sort $(foreach m, $(multi-y), $($(basename $(m))-objs))) +int-m := $(sort $(foreach m, $(multi-m), $($(basename $(m))-objs))) + +# Files that are both resident and modular: remove from modular. +obj-m := $(filter-out $(obj-y), $(obj-m)) +int-m := $(filter-out $(int-y), $(int-m)) + +# Take multi-part drivers out of obj-y and put components in. +obj-y := $(filter-out $(list-multi), $(obj-y)) $(int-y) + +O_OBJS := $(filter-out $(export-objs), $(obj-y)) +OX_OBJS := $(filter $(export-objs), $(obj-y)) +M_OBJS := $(sort $(filter-out $(export-objs), $(obj-m))) +MX_OBJS := $(sort $(filter $(export-objs), $(obj-m))) +MI_OBJS := $(sort $(filter-out $(export-objs), $(int-m))) +MIX_OBJS := $(sort $(filter $(export-objs), $(int-m))) -ifeq ($(CONFIG_SCSI_DEBUG),y) -L_OBJS += scsi_debug.o -else - ifeq ($(CONFIG_SCSI_DEBUG),m) - M_OBJS += scsi_debug.o - endif -endif - -ifeq ($(CONFIG_SCSI_FUTURE_DOMAIN),y) -L_OBJS += fdomain.o -else - ifeq ($(CONFIG_SCSI_FUTURE_DOMAIN),m) - M_OBJS += fdomain.o - endif -endif - -ifeq ($(CONFIG_SCSI_IN2000),y) -L_OBJS += in2000.o -else - ifeq ($(CONFIG_SCSI_IN2000),m) - M_OBJS += in2000.o - endif -endif - -ifeq ($(CONFIG_SCSI_GENERIC_NCR5380),y) -L_OBJS += g_NCR5380.o -else - ifeq ($(CONFIG_SCSI_GENERIC_NCR5380),m) - M_OBJS += g_NCR5380.o - endif -endif - -ifeq ($(CONFIG_SCSI_NCR53C7xx),y) -L_OBJS += 53c7,8xx.o -else - ifeq ($(CONFIG_SCSI_NCR53C7xx),m) - M_OBJS += 53c7,8xx.o - endif -endif - -ifeq ($(CONFIG_SCSI_NCR53C8XX),y) -L_OBJS += ncr53c8xx.o -else - ifeq ($(CONFIG_SCSI_NCR53C8XX),m) - M_OBJS += ncr53c8xx.o - endif -endif - -ifeq ($(CONFIG_SCSI_SYM53C8XX),y) -L_OBJS += sym53c8xx.o -else - ifeq ($(CONFIG_SCSI_SYM53C8XX),m) - M_OBJS += sym53c8xx.o - endif -endif - -ifeq ($(CONFIG_SCSI_PAS16),y) -L_OBJS += pas16.o -else - ifeq ($(CONFIG_SCSI_PAS16),m) - M_OBJS += pas16.o - endif -endif - -ifeq ($(CONFIG_SCSI_SEAGATE),y) -L_OBJS += seagate.o -else - ifeq ($(CONFIG_SCSI_SEAGATE),m) - M_OBJS += seagate.o - endif -endif -ifndef CONFIG_SCSI_SEAGATE - ifeq ($(CONFIG_SCSI_FD_8xx),y) - L_OBJS += seagate.o - else - ifeq ($(CONFIG_SCSI_FD_8xx),m) - M_OBJS += seagate.o - endif - endif -endif - -ifeq ($(CONFIG_SCSI_7000FASST),y) -L_OBJS += wd7000.o -else - ifeq ($(CONFIG_SCSI_7000FASST),m) - M_OBJS += wd7000.o - endif -endif - -ifeq ($(CONFIG_SCSI_IBMMCA),y) -L_OBJS += ibmmca.o -else - ifeq ($(CONFIG_SCSI_IBMMCA),m) - M_OBJS += ibmmca.o - endif -endif - -ifeq ($(CONFIG_SCSI_FD_MCS),y) -L_OBJS += fd_mcs.o -else - ifeq ($(CONFIG_SCSI_FD_MCS),m) - M_OBJS += fd_mcs.o - endif -endif - -ifeq ($(CONFIG_SCSI_T128),y) -L_OBJS += t128.o -else - ifeq ($(CONFIG_SCSI_T128),m) - M_OBJS += t128.o - endif -endif - -ifeq ($(CONFIG_SCSI_DMX3191D),y) -L_OBJS += dmx3191d.o -else - ifeq ($(CONFIG_SCSI_DMX3191D),m) - M_OBJS += dmx3191d.o - endif -endif - -ifeq ($(CONFIG_SCSI_DTC3280),y) -L_OBJS += dtc.o -else - ifeq ($(CONFIG_SCSI_DTC3280),m) - M_OBJS += dtc.o - endif -endif - -ifeq ($(CONFIG_SCSI_ULTRASTOR),y) -L_OBJS += ultrastor.o -else - ifeq ($(CONFIG_SCSI_ULTRASTOR),m) - M_OBJS += ultrastor.o - endif -endif - -ifeq ($(CONFIG_SCSI_PLUTO),y) -L_OBJS += pluto.o -else - ifeq ($(CONFIG_SCSI_PLUTO),m) - M_OBJS += pluto.o - endif -endif - -ifeq ($(CONFIG_SCSI_FCAL),y) -L_OBJS += fcal.o -else - ifeq ($(CONFIG_SCSI_FCAL),m) - M_OBJS += fcal.o - endif -endif - -ifeq ($(CONFIG_SCSI_EATA),y) -L_OBJS += eata.o -else - ifeq ($(CONFIG_SCSI_EATA),m) - M_OBJS += eata.o - endif -endif - -ifeq ($(CONFIG_SCSI_NCR53C406A),y) -L_OBJS += NCR53c406a.o -else - ifeq ($(CONFIG_SCSI_NCR53C406A),m) - M_OBJS += NCR53c406a.o - endif -endif - -ifeq ($(CONFIG_SCSI_MEGARAID),y) -L_OBJS += megaraid.o -else - ifeq ($(CONFIG_SCSI_MEGARAID),m) - M_OBJS += megaraid.o - endif -endif - -ifeq ($(CONFIG_SCSI_SYM53C416),y) -L_OBJS += sym53c416.o -else - ifeq ($(CONFIG_SCSI_SYM53C416),m) - M_OBJS += sym53c416.o - endif -endif +include $(TOPDIR)/Rules.make -ifeq ($(CONFIG_BLK_DEV_IDESCSI),y) -L_OBJS += ide-scsi.o -else - ifeq ($(CONFIG_BLK_DEV_IDESCSI),m) - M_OBJS += ide-scsi.o - endif -endif -ifeq ($(CONFIG_JAZZ_ESP),y) -L_OBJS += NCR53C9x.o jazz_esp.o -endif +scsi_mod.o: $(scsi_mod-objs) + $(LD) -r -o $@ $(scsi_mod-objs) -ifeq ($(CONFIG_SCSI_DECNCR),y) -L_OBJS += NCR53C9x.o dec_esp.o -endif +sr_mod.o: $(sr_mod-objs) + $(LD) -r -o $@ $(sr_mod-objs) -ifeq ($(CONFIG_SUN3X_ESP),y) -L_OBJS += NCR53C9x.o sun3x_esp.o -endif +initio.o: $(initio-objs) + $(LD) -r -o $@ $(initio-objs) -ifeq ($(CONFIG_BLK_DEV_3W_XXXX_RAID),y) -L_OBJS += 3w-xxxx.o -else - ifeq ($(CONFIG_BLK_DEV_3W_XXXX_RAID),m) - M_OBJS += 3w-xxxx.o - endif -endif +a100u2w.o: $(a100u2w-objs) + $(LD) -r -o $@ $(a100u2w-objs) -include $(TOPDIR)/Rules.make 53c8xx_d.h: 53c7,8xx.scr script_asm.pl ln -sf 53c7,8xx.scr fake8.c @@ -745,23 +193,3 @@ sim710_d.h: sim710.scr script_asm.pl sim710_u.h: sim710_d.h sim710.o : sim710_d.h - -initio.o: ini9100u.o i91uscsi.o - $(LD) -r -o initio.o ini9100u.o i91uscsi.o - -a100u2w.o: inia100.o i60uscsi.o - $(LD) -r -o a100u2w.o inia100.o i60uscsi.o - -scsi_mod.o: $(MIX_OBJS) hosts.o scsi.o scsi_ioctl.o constants.o \ - scsicam.o scsi_proc.o scsi_error.o scsi_obsolete.o \ - scsi_queue.o scsi_lib.o scsi_merge.o scsi_dma.o scsi_scan.o - $(LD) $(LD_RFLAG) -r -o $@ $(MIX_OBJS) hosts.o scsi.o scsi_ioctl.o \ - constants.o scsicam.o scsi_proc.o scsi_merge.o \ - scsi_error.o scsi_obsolete.o scsi_queue.o scsi_lib.o \ - scsi_dma.o scsi_scan.o - -sr_mod.o: sr.o sr_ioctl.o sr_vendor.o - $(LD) $(LD_RFLAG) -r -o $@ sr.o sr_ioctl.o sr_vendor.o - -sd_mod.o: sd.o - $(LD) $(LD_RFLAG) -r -o $@ sd.o diff --git a/drivers/scsi/NCR53C9x.c b/drivers/scsi/NCR53C9x.c index 4c17f6fd0..0340ab5c4 100644 --- a/drivers/scsi/NCR53C9x.c +++ b/drivers/scsi/NCR53C9x.c @@ -412,7 +412,7 @@ static void esp_reset_esp(struct NCR_ESP *esp, struct ESP_regs *eregs) else if(family_code == 0x00) { if ((version & 7) == 2) esp->erev = fas100a; /* NCR53C9X */ - else + else esp->erev = espunknown; } else if(family_code == 0x14) { if ((version & 7) == 2) @@ -463,18 +463,18 @@ static void esp_reset_esp(struct NCR_ESP *esp, struct ESP_regs *eregs) panic("esp: FAS366 support not present, please notify " "jongk@cs.utwente.nl"); break; - case fas216: + case fas216: case fas236: case fsc: /* Fast ESP variants */ esp_write(eregs->esp_cfg2, esp->config2); for(i=0; i<8; i++) - esp->config3[i] |= ESP_CONFIG3_FCLK; + esp->config3[i] |= ESP_CONFIG3_FCLK; esp->prev_cfg3 = esp->config3[0]; esp_write(eregs->esp_cfg3, esp->prev_cfg3); - if(esp->diff) - esp->radelay = 0; - else + if(esp->diff) + esp->radelay = 0; + else esp->radelay = 16; /* Different timeout constant for these chips */ esp->neg_defp = @@ -692,7 +692,7 @@ void esp_initialize(struct NCR_ESP *esp) esp->erev = esp100a; } else { int target; - + for(target=0; target<8; target++) esp->config3[target] = 0; esp->prev_cfg3 = 0; @@ -707,12 +707,12 @@ void esp_initialize(struct NCR_ESP *esp) } } } - + /* Initialize the command queues */ esp->current_SC = 0; esp->disconnected_SC = 0; esp->issue_SC = 0; - + /* Clear the state machines. */ esp->targets_present = 0; esp->resetting_bus = 0; @@ -733,7 +733,7 @@ void esp_initialize(struct NCR_ESP *esp) /* Reset the thing before we try anything... */ esp_bootup_reset(esp, eregs); - + #ifdef MODULE MOD_INC_USE_COUNT; #endif @@ -1117,12 +1117,12 @@ do_sync_known: * Macintosh. Well, maybe later when we figured out how to * do DMA on the machines that support it ... */ - SDptr->disconnect = 1; - SDptr->sync_max_offset = 0; - SDptr->sync_min_period = 0; - SDptr->sync = 1; - esp->snip = 0; - goto do_sync_known; + SDptr->disconnect = 1; + SDptr->sync_max_offset = 0; + SDptr->sync_min_period = 0; + SDptr->sync = 1; + esp->snip = 0; + goto do_sync_known; #endif /* We've talked to this guy before, * but never negotiated. Let's try @@ -1228,14 +1228,14 @@ do_sync_known: /* Tell ESP to "go". */ esp_cmd(esp, eregs, the_esp_command); } else { - /* Set up the ESP counters */ + /* Set up the ESP counters */ esp_write(eregs->esp_tclow, i); esp_write(eregs->esp_tcmed, 0); - esp->dma_init_write(esp, esp->esp_command_dvma, i); + esp->dma_init_write(esp, esp->esp_command_dvma, i); - /* Tell ESP to "go". */ - esp_cmd(esp, eregs, the_esp_command); - } + /* Tell ESP to "go". */ + esp_cmd(esp, eregs, the_esp_command); + } } /* Queue a SCSI command delivered from the mid-level Linux SCSI code. */ @@ -1301,7 +1301,7 @@ static void esp_dump_cmd(Scsi_Cmnd *SCptr) } static void esp_dump_state(struct NCR_ESP *esp, - struct ESP_regs *eregs) + struct ESP_regs *eregs) { Scsi_Cmnd *SCptr = esp->current_SC; #ifdef DEBUG_ESP_CMDS @@ -1656,13 +1656,13 @@ static inline int reconnect_target(struct NCR_ESP *esp, struct ESP_regs *eregs) if(2 != fcount(esp, eregs)) return -1; it = esp_read(eregs->esp_fdata); - if(!(it & me)) - return -1; - it &= ~me; - if(it & (it - 1)) - return -1; - while(!(it & 1)) - targ++, it >>= 1; + if(!(it & me)) + return -1; + it &= ~me; + if(it & (it - 1)) + return -1; + while(!(it & 1)) + targ++, it >>= 1; return targ; } @@ -1733,7 +1733,7 @@ static inline void esp_reconnect(struct NCR_ESP *esp, Scsi_Cmnd *sp) /* Begin message in phase. */ static int esp_do_msgin(struct NCR_ESP *esp, struct ESP_regs *eregs) { - esp_cmd(esp, eregs, ESP_CMD_FLUSH); + esp_cmd(esp, eregs, ESP_CMD_FLUSH); esp_maybe_nop(esp, eregs); esp_cmd(esp, eregs, ESP_CMD_TI); esp->msgin_len = 1; @@ -1747,10 +1747,10 @@ static inline void advance_sg(struct NCR_ESP *esp, Scsi_Cmnd *sp) ++sp->SCp.buffer; --sp->SCp.buffers_residual; sp->SCp.this_residual = sp->SCp.buffer->length; - if (esp->dma_advance_sg) - esp->dma_advance_sg (sp); - else - sp->SCp.ptr = (char *)virt_to_phys(sp->SCp.buffer->address); + if (esp->dma_advance_sg) + esp->dma_advance_sg (sp); + else + sp->SCp.ptr = (char *)virt_to_phys(sp->SCp.buffer->address); } /* Please note that the way I've coded these routines is that I _always_ @@ -1790,8 +1790,8 @@ static int esp_do_data(struct NCR_ESP *esp, struct ESP_regs *eregs) /* * DMA */ - ESPDATA(("hmuch<%d> ", hmuch)); - esp->current_transfer_size = hmuch; + ESPDATA(("hmuch<%d> ", hmuch)); + esp->current_transfer_size = hmuch; esp_setcount(eregs, (esp->fas_premature_intr_workaround ? (hmuch + 0x40) : hmuch)); esp->dma_setup(esp, (__u32)((unsigned long)SCptr->SCp.ptr), @@ -1860,7 +1860,7 @@ static int esp_do_data(struct NCR_ESP *esp, struct ESP_regs *eregs) if (!fifocnt) fifo_stuck++; - else + else fifo_stuck = 0; ESPDATA(("\rgot %d st %x ph %x", fifocnt, esp->sreg, newphase)); @@ -1880,7 +1880,7 @@ static int esp_do_data(struct NCR_ESP *esp, struct ESP_regs *eregs) esp->ireg = esp_read(eregs->esp_intrpt); break; } - } else { + } else { #define MAX_FIFO 8 /* how much will fit ? */ int this_count = MAX_FIFO - fifocnt; @@ -1979,7 +1979,7 @@ static int esp_do_data(struct NCR_ESP *esp, struct ESP_regs *eregs) /* See how successful the data transfer was. */ static int esp_do_data_finale(struct NCR_ESP *esp, - struct ESP_regs *eregs) + struct ESP_regs *eregs) { Scsi_Cmnd *SCptr = esp->current_SC; int bogus_data = 0, bytes_sent = 0, fifocnt, ecount = 0; @@ -2017,25 +2017,25 @@ static int esp_do_data_finale(struct NCR_ESP *esp, /* Check for partial transfers and other horrible events. */ fifocnt = (esp_read(eregs->esp_fflags) & ESP_FF_FBYTES); - ecount = esp_getcount(eregs); + ecount = esp_getcount(eregs); if(esp->fas_premature_intr_workaround) ecount -= 0x40; bytes_sent = esp->current_transfer_size; ESPDATA(("trans_sz=%d, ", bytes_sent)); - if(!(esp->sreg & ESP_STAT_TCNT)) - bytes_sent -= ecount; - if(SCptr->SCp.phase == in_dataout) - bytes_sent -= fifocnt; + if(!(esp->sreg & ESP_STAT_TCNT)) + bytes_sent -= ecount; + if(SCptr->SCp.phase == in_dataout) + bytes_sent -= fifocnt; ESPDATA(("bytes_sent=%d (ecount=%d, fifocnt=%d), ", bytes_sent, ecount, fifocnt)); /* If we were in synchronous mode, check for peculiarities. */ - if(SCptr->device->sync_max_offset) - bogus_data = esp100_sync_hwbug(esp, eregs, SCptr, fifocnt); - else - esp_cmd(esp, eregs, ESP_CMD_FLUSH); + if(SCptr->device->sync_max_offset) + bogus_data = esp100_sync_hwbug(esp, eregs, SCptr, fifocnt); + else + esp_cmd(esp, eregs, ESP_CMD_FLUSH); /* Until we are sure of what has happened, we are certainly * in the dark. @@ -2134,7 +2134,7 @@ static int esp_do_data_finale(struct NCR_ESP *esp, if(sreg_datainp(esp->sreg) || sreg_dataoutp(esp->sreg)) { ESPDATA(("to more data\n")); } else { - ESPDATA(("to new phase\n")); + ESPDATA(("to new phase\n")); } #endif return esp_do_phase_determine(esp, eregs); @@ -2259,33 +2259,33 @@ static int esp_do_freebus(struct NCR_ESP *esp, struct ESP_regs *eregs) */ static int esp_bad_reconnect(struct NCR_ESP *esp) { - Scsi_Cmnd *sp; + Scsi_Cmnd *sp; - ESPLOG(("esp%d: Eieeee, reconnecting unknown command!\n", - esp->esp_id)); - ESPLOG(("QUEUE DUMP\n")); - sp = esp->issue_SC; - ESPLOG(("esp%d: issue_SC[", esp->esp_id)); - while(sp) { - ESPLOG(("<%02x,%02x>", sp->target, sp->lun)); - sp = (Scsi_Cmnd *) sp->host_scribble; - } - ESPLOG(("]\n")); - sp = esp->current_SC; - ESPLOG(("esp%d: current_SC[", esp->esp_id)); - while(sp) { - ESPLOG(("<%02x,%02x>", sp->target, sp->lun)); - sp = (Scsi_Cmnd *) sp->host_scribble; - } - ESPLOG(("]\n")); - sp = esp->disconnected_SC; - ESPLOG(("esp%d: disconnected_SC[", esp->esp_id)); - while(sp) { - ESPLOG(("<%02x,%02x>", sp->target, sp->lun)); - sp = (Scsi_Cmnd *) sp->host_scribble; - } - ESPLOG(("]\n")); - return do_reset_bus; + ESPLOG(("esp%d: Eieeee, reconnecting unknown command!\n", + esp->esp_id)); + ESPLOG(("QUEUE DUMP\n")); + sp = esp->issue_SC; + ESPLOG(("esp%d: issue_SC[", esp->esp_id)); + while(sp) { + ESPLOG(("<%02x,%02x>", sp->target, sp->lun)); + sp = (Scsi_Cmnd *) sp->host_scribble; + } + ESPLOG(("]\n")); + sp = esp->current_SC; + ESPLOG(("esp%d: current_SC[", esp->esp_id)); + while(sp) { + ESPLOG(("<%02x,%02x>", sp->target, sp->lun)); + sp = (Scsi_Cmnd *) sp->host_scribble; + } + ESPLOG(("]\n")); + sp = esp->disconnected_SC; + ESPLOG(("esp%d: disconnected_SC[", esp->esp_id)); + while(sp) { + ESPLOG(("<%02x,%02x>", sp->target, sp->lun)); + sp = (Scsi_Cmnd *) sp->host_scribble; + } + ESPLOG(("]\n")); + return do_reset_bus; } /* Do the needy when a target tries to reconnect to us. */ @@ -2447,11 +2447,11 @@ static int esp_do_status(struct NCR_ESP *esp, struct ESP_regs *eregs) } static int esp_enter_status(struct NCR_ESP *esp, - struct ESP_regs *eregs) + struct ESP_regs *eregs) { unchar thecmd = ESP_CMD_ICCSEQ; - esp_cmd(esp, eregs, ESP_CMD_FLUSH); + esp_cmd(esp, eregs, ESP_CMD_FLUSH); if(esp->do_pio_cmds) { esp_advance_phase(esp->current_SC, in_status); @@ -2464,11 +2464,11 @@ static int esp_enter_status(struct NCR_ESP *esp, esp->esp_command[0] = esp->esp_command[1] = 0xff; esp_write(eregs->esp_tclow, 2); esp_write(eregs->esp_tcmed, 0); - esp->dma_init_read(esp, esp->esp_command_dvma, 2); + esp->dma_init_read(esp, esp->esp_command_dvma, 2); thecmd |= ESP_CMD_DMA; esp_cmd(esp, eregs, thecmd); esp_advance_phase(esp->current_SC, in_status); - } + } return esp_do_status(esp, eregs); } @@ -2479,43 +2479,43 @@ static int esp_disconnect_amidst_phases(struct NCR_ESP *esp, Scsi_Cmnd *sp = esp->current_SC; Scsi_Device *dp = sp->device; - /* This means real problems if we see this - * here. Unless we were actually trying - * to force the device to abort/reset. - */ + /* This means real problems if we see this + * here. Unless we were actually trying + * to force the device to abort/reset. + */ ESPLOG(("esp%d: Disconnect amidst phases, ", esp->esp_id)); - ESPLOG(("pphase<%s> cphase<%s>, ", + ESPLOG(("pphase<%s> cphase<%s>, ", phase_string(sp->SCp.phase), phase_string(sp->SCp.sent_command))); if(esp->disconnected_SC) - esp_cmd(esp, eregs, ESP_CMD_ESEL); + esp_cmd(esp, eregs, ESP_CMD_ESEL); - switch(esp->cur_msgout[0]) { - default: - /* We didn't expect this to happen at all. */ - ESPLOG(("device is bolixed\n")); + switch(esp->cur_msgout[0]) { + default: + /* We didn't expect this to happen at all. */ + ESPLOG(("device is bolixed\n")); esp_advance_phase(sp, in_tgterror); - esp_done(esp, (DID_ERROR << 16)); - break; + esp_done(esp, (DID_ERROR << 16)); + break; - case BUS_DEVICE_RESET: - ESPLOG(("device reset successful\n")); - dp->sync_max_offset = 0; - dp->sync_min_period = 0; - dp->sync = 0; + case BUS_DEVICE_RESET: + ESPLOG(("device reset successful\n")); + dp->sync_max_offset = 0; + dp->sync_min_period = 0; + dp->sync = 0; esp_advance_phase(sp, in_resetdev); - esp_done(esp, (DID_RESET << 16)); - break; + esp_done(esp, (DID_RESET << 16)); + break; - case ABORT: - ESPLOG(("device abort successful\n")); + case ABORT: + ESPLOG(("device abort successful\n")); esp_advance_phase(sp, in_abortone); - esp_done(esp, (DID_ABORT << 16)); - break; + esp_done(esp, (DID_ABORT << 16)); + break; - }; - return do_intr_end; + }; + return do_intr_end; } static int esp_enter_msgout(struct NCR_ESP *esp, @@ -2687,7 +2687,7 @@ static int esp_select_complete(struct NCR_ESP *esp, struct ESP_regs *eregs) if(SCptr->SCp.phase == in_slct_norm) cmd_bytes_sent -= 1; }; - esp_cmd(esp, eregs, ESP_CMD_NULL); + esp_cmd(esp, eregs, ESP_CMD_NULL); /* Be careful, we could really get fucked during synchronous * data transfers if we try to flush the fifo now. @@ -2851,7 +2851,7 @@ static int esp_do_msgincont(struct NCR_ESP *esp, struct ESP_regs *eregs) } static int check_singlebyte_msg(struct NCR_ESP *esp, - struct ESP_regs *eregs) + struct ESP_regs *eregs) { esp->prevmsgin = esp->cur_msgin[0]; if(esp->cur_msgin[0] & 0x80) { @@ -2929,8 +2929,8 @@ static int check_singlebyte_msg(struct NCR_ESP *esp, * this because so many initiators cannot cope with this occuring. */ static int target_with_ants_in_pants(struct NCR_ESP *esp, - Scsi_Cmnd *SCptr, - Scsi_Device *SDptr) + Scsi_Cmnd *SCptr, + Scsi_Device *SDptr) { if(SDptr->sync || SDptr->borken) { /* sorry, no can do */ @@ -2982,7 +2982,7 @@ static void sync_report(struct NCR_ESP *esp) } static int check_multibyte_msg(struct NCR_ESP *esp, - struct ESP_regs *eregs) + struct ESP_regs *eregs) { Scsi_Cmnd *SCptr = esp->current_SC; Scsi_Device *SDptr = SCptr->device; @@ -3111,7 +3111,7 @@ static int check_multibyte_msg(struct NCR_ESP *esp, return 0; } else if(esp->cur_msgin[2] == EXTENDED_WDTR) { ESPLOG(("esp%d: AIEEE wide msg received\n", esp->esp_id)); - message_out = MESSAGE_REJECT; + message_out = MESSAGE_REJECT; } else if(esp->cur_msgin[2] == EXTENDED_MODIFY_DATA_POINTER) { ESPLOG(("esp%d: rejecting modify data ptr msg\n", esp->esp_id)); message_out = MESSAGE_REJECT; @@ -3142,7 +3142,7 @@ static int esp_do_msgindone(struct NCR_ESP *esp, struct ESP_regs *eregs) esp_advance_phase(SCptr, in_msgincont); } else { /* it is ok and we want it */ - it = esp->cur_msgin[esp->msgin_ctr] = + it = esp->cur_msgin[esp->msgin_ctr] = esp_read(eregs->esp_fdata); esp->msgin_ctr++; } @@ -3200,17 +3200,17 @@ static int esp_do_cmdbegin(struct NCR_ESP *esp, struct ESP_regs *eregs) Scsi_Cmnd *SCptr = esp->current_SC; esp_advance_phase(SCptr, in_cmdend); - esp_cmd(esp, eregs, ESP_CMD_FLUSH); + esp_cmd(esp, eregs, ESP_CMD_FLUSH); tmp = *esp->esp_scmdp++; - esp->esp_scmdleft--; + esp->esp_scmdleft--; esp_write(eregs->esp_fdata, tmp); - esp_cmd(esp, eregs, ESP_CMD_TI); + esp_cmd(esp, eregs, ESP_CMD_TI); return do_intr_end; } static int esp_do_cmddone(struct NCR_ESP *esp, struct ESP_regs *eregs) { - esp_cmd(esp, eregs, ESP_CMD_NULL); + esp_cmd(esp, eregs, ESP_CMD_NULL); if(esp->ireg & ESP_INTR_BSERV) { esp_advance_phase(esp->current_SC, in_the_dark); return esp_do_phase_determine(esp, eregs); @@ -3237,10 +3237,10 @@ static int esp_do_msgout(struct NCR_ESP *esp, struct ESP_regs *eregs) } else { esp->esp_command[0] = esp->cur_msgout[0]; esp->esp_command[1] = esp->cur_msgout[1]; - esp->dma_setup(esp, esp->esp_command_dvma, 2, 0); + esp->dma_setup(esp, esp->esp_command_dvma, 2, 0); esp_setcount(eregs, 2); - esp_cmd(esp, eregs, ESP_CMD_DMA | ESP_CMD_TI); - } + esp_cmd(esp, eregs, ESP_CMD_DMA | ESP_CMD_TI); + } break; case 4: @@ -3256,10 +3256,10 @@ static int esp_do_msgout(struct NCR_ESP *esp, struct ESP_regs *eregs) esp->esp_command[1] = esp->cur_msgout[1]; esp->esp_command[2] = esp->cur_msgout[2]; esp->esp_command[3] = esp->cur_msgout[3]; - esp->dma_setup(esp, esp->esp_command_dvma, 4, 0); + esp->dma_setup(esp, esp->esp_command_dvma, 4, 0); esp_setcount(eregs, 4); - esp_cmd(esp, eregs, ESP_CMD_DMA | ESP_CMD_TI); - } + esp_cmd(esp, eregs, ESP_CMD_DMA | ESP_CMD_TI); + } break; case 5: @@ -3270,17 +3270,17 @@ static int esp_do_msgout(struct NCR_ESP *esp, struct ESP_regs *eregs) esp_write(eregs->esp_fdata, esp->cur_msgout[2]); esp_write(eregs->esp_fdata, esp->cur_msgout[3]); esp_write(eregs->esp_fdata, esp->cur_msgout[4]); - esp_cmd(esp, eregs, ESP_CMD_TI); - } else { + esp_cmd(esp, eregs, ESP_CMD_TI); + } else { esp->esp_command[0] = esp->cur_msgout[0]; esp->esp_command[1] = esp->cur_msgout[1]; esp->esp_command[2] = esp->cur_msgout[2]; esp->esp_command[3] = esp->cur_msgout[3]; esp->esp_command[4] = esp->cur_msgout[4]; - esp->dma_setup(esp, esp->esp_command_dvma, 5, 0); + esp->dma_setup(esp, esp->esp_command_dvma, 5, 0); esp_setcount(eregs, 5); - esp_cmd(esp, eregs, ESP_CMD_DMA | ESP_CMD_TI); - } + esp_cmd(esp, eregs, ESP_CMD_DMA | ESP_CMD_TI); + } break; default: @@ -3297,13 +3297,13 @@ static int esp_do_msgout(struct NCR_ESP *esp, struct ESP_regs *eregs) } static int esp_do_msgoutdone(struct NCR_ESP *esp, - struct ESP_regs *eregs) + struct ESP_regs *eregs) { if((esp->msgout_len > 1) && esp->dma_barrier) esp->dma_barrier(esp); if(!(esp->ireg & ESP_INTR_DC)) { - esp_cmd(esp, eregs, ESP_CMD_NULL); + esp_cmd(esp, eregs, ESP_CMD_NULL); switch(esp->sreg & ESP_STAT_PMASK) { case ESP_MOP: /* whoops, parity error */ @@ -3532,10 +3532,10 @@ state_machine: what_next < do_intr_end) what_next = isvc_vector[what_next](esp, eregs); else { - /* state is completely lost ;-( */ - ESPLOG(("esp%d: interrupt engine loses state, resetting bus\n", - esp->esp_id)); - what_next = do_reset_bus; + /* state is completely lost ;-( */ + ESPLOG(("esp%d: interrupt engine loses state, resetting bus\n", + esp->esp_id)); + what_next = do_reset_bus; } } if(esp->dma_irq_exit) @@ -3578,7 +3578,7 @@ repeat: } #else /* For SMP we only service one ESP on the list list at our IRQ level! */ -static void esp_intr(int irq, void *dev_id, struct pt_regs *pregs) +void esp_intr(int irq, void *dev_id, struct pt_regs *pregs) { struct NCR_ESP *esp; unsigned long flags; diff --git a/drivers/scsi/README.ncr53c8xx b/drivers/scsi/README.ncr53c8xx index 858673c33..e1d965b1a 100644 --- a/drivers/scsi/README.ncr53c8xx +++ b/drivers/scsi/README.ncr53c8xx @@ -168,6 +168,12 @@ Chip SDMS BIOS Wide SCSI std. Max. sync driver driver 895 Y Y FAST40 80 MB/s Y Y 895A Y Y FAST40 80 MB/s Y Y 896 Y Y FAST40 80 MB/s Y Y +897 Y Y FAST40 80 MB/s Y Y +1510D Y Y FAST40 80 MB/s Y Y +1010 Y Y FAST80 160 MB/s N Y +1010_66* Y Y FAST80 160 MB/s N Y + +* Chip supports 33MHz and 66MHz PCI buses. Summary of other supported features: @@ -686,11 +692,12 @@ port address 0x1400. Invalidate. 10.2.5 Ultra SCSI support - Only apply to 860, 875 and 895 controllers. + Only apply to 860, 875, 895, 895a, 896, 1010 and 1010_66 controllers. Have no effect with other ones. + ultra:n All ultra speeds enabled ultra:2 Ultra2 enabled ultra:1 Ultra enabled - ultra:n disabled + ultra:0 Ultra speeds disabled 10.2.6 Default number of tagged commands tags:0 (or tags:1 ) tagged command queuing disabled @@ -822,6 +829,7 @@ port address 0x1400. 0x0: No check. 0x1: Check and donnot attach the controller on error. 0x2: Check and just warn on error. + 0x4: Disable SCSI bus integrity checking. 10.2.20 Exclude a host from being attached excl=<io_address> diff --git a/drivers/scsi/advansys.c b/drivers/scsi/advansys.c index eb3c22cf0..02315dc57 100644 --- a/drivers/scsi/advansys.c +++ b/drivers/scsi/advansys.c @@ -4699,7 +4699,8 @@ advansys_detect(Scsi_Host_Template *tpnt) NULL) { pci_device_id_cnt++; } else { - pci_devicep[pci_card_cnt_max++] = pci_devp; + if (pci_enable_device(pci_devp) == 0) + pci_devicep[pci_card_cnt_max++] = pci_devp; } } @@ -4739,7 +4740,7 @@ advansys_detect(Scsi_Host_Template *tpnt) #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,3,13) iop = pci_devp->base_address[0] & PCI_IOADDRESS_MASK; #else /* version >= v2.3.13 */ - iop = pci_devp->resource[0].start & PCI_IOADDRESS_MASK; + iop = pci_resource_start(pci_devp, 0); #endif /* version >= v2.3.13 */ ASC_DBG2(1, "advansys_detect: vendorID %X, deviceID %X\n", @@ -4900,7 +4901,7 @@ advansys_detect(Scsi_Host_Template *tpnt) #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,3,13) pci_memory_address = pci_devp->base_address[1]; #else /* version >= v2.3.13 */ - pci_memory_address = pci_devp->resource[1].start; + pci_memory_address = pci_resource_start(pci_devp, 1); #endif /* version >= v2.3.13 */ ASC_DBG1(1, "advansys_detect: pci_memory_address: %x\n", pci_memory_address); diff --git a/drivers/scsi/aha152x.c b/drivers/scsi/aha152x.c index 240041cf0..3f17ad86f 100644 --- a/drivers/scsi/aha152x.c +++ b/drivers/scsi/aha152x.c @@ -1301,10 +1301,11 @@ int aha152x_detect(Scsi_Host_Template * tpnt) printk(KERN_ERR "aha152x%d: IRQ %d possibly wrong. Please verify.\n", HOSTNO, shpnt->irq); - scsi_unregister(shpnt); registered_count--; release_region(shpnt->io_port, IO_RANGE); - shpnt = aha152x_host[shpnt->irq - IRQ_MIN] = 0; + aha152x_host[shpnt->irq - IRQ_MIN] = 0; + scsi_unregister(shpnt); + shpnt=NULL; continue; } printk("ok.\n"); diff --git a/drivers/scsi/aic7xxx.c b/drivers/scsi/aic7xxx.c index 8d041639b..67648bc75 100644 --- a/drivers/scsi/aic7xxx.c +++ b/drivers/scsi/aic7xxx.c @@ -9551,14 +9551,15 @@ aic7xxx_detect(Scsi_Host_Template *template) pdev = NULL; while ((pdev = pci_find_device(aic_pdevs[i].vendor_id, aic_pdevs[i].device_id, - pdev))) + pdev))) { + if (pci_enable_device(pdev)) + continue; #else index = 0; while (!(pcibios_find_device(aic_pdevs[i].vendor_id, aic_pdevs[i].device_id, - index++, &pci_bus, &pci_devfn)) ) + index++, &pci_bus, &pci_devfn)) ) { #endif - { if ( i == 0 ) /* We found one, but it's the 7810 RAID cont. */ { if (aic7xxx_verbose & (VERBOSE_PROBE|VERBOSE_PROBE2)) @@ -9587,8 +9588,8 @@ aic7xxx_detect(Scsi_Host_Template *template) temp_p->pdev = pdev; temp_p->pci_bus = pdev->bus->number; temp_p->pci_device_fn = pdev->devfn; - temp_p->base = pdev->resource[0].start; - temp_p->mbase = pdev->resource[1].start; + temp_p->base = pci_resource_start(pdev, 0); + temp_p->mbase = pci_resource_start(pdev, 1); current_p = list_p; while(current_p && temp_p) { diff --git a/drivers/scsi/atp870u.c b/drivers/scsi/atp870u.c index 6c92531fc..3eb3021f2 100644 --- a/drivers/scsi/atp870u.c +++ b/drivers/scsi/atp870u.c @@ -1,11 +1,15 @@ /* $Id: atp870u.c,v 1.0 1997/05/07 15:22:00 root Exp root $ * linux/kernel/atp870u.c * - * Copyright (C) 1997 Wu Ching Chen + * Copyright (C) 1997 Wu Ching Chen * 2.1.x update (C) 1998 Krzysztof G. Baranowski - * - * Marcelo Tosatti <marcelo@conectiva.com.br> : SMP fixes - * + * + * Marcelo Tosatti <marcelo@conectiva.com.br> : SMP fixes + * + * Wu Ching Chen : NULL pointer fixes 2000/06/02 + * support atp876 chip + * enable 32 bit fifo transfer + * support cdrom & remove device run ultra speed */ #include <linux/module.h> @@ -100,19 +104,19 @@ irq_numok: dev->in_int = 1; workportu = dev->ioport; tmport = workportu; - - if (dev->working != 0) + + if (dev->working != 0) { tmport += 0x1f; j = inb(tmport); - if((j&0x80)==0) + if ((j & 0x80) == 0) { - dev->in_int=0; + dev->in_int = 0; return; } tmpcip = dev->pciport; - if ((inb(tmpcip) & 0x08) != 0) + if ((inb(tmpcip) & 0x08) != 0) { tmpcip += 0x2; for (k=0; k < 1000; k++) @@ -124,7 +128,7 @@ irq_numok: if ((inb(tmpcip) & 0x01) == 0) { goto stop_dma; - } + } } } stop_dma: @@ -133,9 +137,9 @@ stop_dma: tmport -= 0x08; i = inb(tmport); - if ((j & 0x40) == 0) + if ((j & 0x40) == 0) { - if ((dev->last_cmd & 0x40) == 0) + if ((dev->last_cmd & 0x40) == 0) { dev->last_cmd = 0xff; } @@ -149,30 +153,32 @@ stop_dma: /* * Remap wide devices onto id numbers */ - + if ((target_id & 0x40) != 0) { target_id = (target_id & 0x07) | 0x08; } else { target_id &= 0x07; } - - if (i == 0x85) + + if (i == 0x85) { /* * Flip wide */ - if (dev->wide_idu != 0) + if (dev->wide_idu != 0) { tmport = workportu + 0x1b; - j = inb(tmport) & 0x0e; - j |= 0x01; - outb(j, tmport); + outb(0x01,tmport); + while ((inb(tmport) & 0x01) != 0x01) + { + outb(0x01,tmport); + } } /* * Issue more commands */ if (((dev->quhdu != dev->quendu) || (dev->last_cmd != 0xff)) && - (dev->in_snd == 0)) + (dev->in_snd == 0)) { send_s870(h); } @@ -182,7 +188,7 @@ stop_dma: dev->in_int = 0; return; } - if (i == 0x21) + if (i == 0x21) { tmport -= 0x05; adrcntu = 0; @@ -200,7 +206,7 @@ stop_dma: dev->in_int = 0; return; } - if ((i == 0x80) || (i == 0x8f)) + if ((i == 0x80) || (i == 0x8f)) { lun = 0; tmport -= 0x07; @@ -209,7 +215,7 @@ stop_dma: tmport += 0x0d; lun = inb(tmport) & 0x07; } else { - if (j == 0x41) + if (j == 0x41) { tmport += 0x02; adrcntu = 0; @@ -225,7 +231,7 @@ stop_dma: dev->in_int = 0; return; } - else + else { outb(0x46, tmport); dev->id[target_id].dirctu = 0x00; @@ -246,7 +252,7 @@ stop_dma: /* * Remap wide identifiers */ - if ((target_id & 0x10) != 0) + if ((target_id & 0x10) != 0) { target_id = (target_id & 0x07) | 0x08; } else { @@ -271,8 +277,21 @@ stop_dma: j |= dev->id[target_id].dirctu; outb(j, tmport++); outb(0x80, tmport); + + /* enable 32 bit fifo transfer */ + tmport = workportu + 0x3a; + if ((dev->ata_cdbu[0] == 0x08) || (dev->ata_cdbu[0] == 0x28) || + (dev->ata_cdbu[0] == 0x0a) || (dev->ata_cdbu[0] == 0x2a)) + { + outb((unsigned char)((inb(tmport) & 0xf3) | 0x08),tmport); + } + else + { + outb((unsigned char)(inb(tmport) & 0xf3),tmport); + } + tmport = workportu + 0x1b; - j = inb(tmport) & 0x0e; + j = 0; id = 1; id = id << target_id; /* @@ -282,7 +301,11 @@ stop_dma: j |= 0x01; } outb(j, tmport); - + while ((inb(tmport) & 0x01) != j) + { + outb(j,tmport); + } + if (dev->id[target_id].last_lenu == 0) { tmport = workportu + 0x18; outb(0x08, tmport); @@ -290,7 +313,7 @@ stop_dma: return; } prd = dev->id[target_id].prd_posu; - while (adrcntu != 0) + while (adrcntu != 0) { id = ((unsigned short int *) (prd))[2]; if (id == 0) { @@ -334,19 +357,19 @@ stop_dma: dev->in_int = 0; return; } - + /* * Current scsi request on this target */ - + workrequ = dev->id[target_id].curr_req; - + if (i == 0x42) { errstus = 0x02; workrequ->result = errstus; goto go_42; } - if (i == 0x16) + if (i == 0x16) { errstus = 0; tmport -= 0x08; @@ -370,15 +393,17 @@ go_42: */ if (dev->wide_idu != 0) { tmport = workportu + 0x1b; - j = inb(tmport) & 0x0e; - j |= 0x01; - outb(j, tmport); + outb(0x01,tmport); + while ((inb(tmport) & 0x01) != 0x01) + { + outb(0x01,tmport); + } } /* * If there is stuff to send and nothing going then send it */ if (((dev->last_cmd != 0xff) || (dev->quhdu != dev->quendu)) && - (dev->in_snd == 0)) + (dev->in_snd == 0)) { send_s870(h); } @@ -439,9 +464,9 @@ go_42: dev->in_int = 0; return; } else { - tmport = workportu + 0x17; - inb(tmport); - dev->working = 0; +// tmport = workportu + 0x17; +// inb(tmport); +// dev->working = 0; dev->in_int = 0; return; } @@ -474,7 +499,7 @@ host_ok: /* * Fake a timeout for missing targets */ - + if ((m & dev->active_idu) == 0) { req_p->result = 0x00040000; done(req_p); @@ -550,7 +575,17 @@ void send_s870(unsigned char h) if ((dev->last_cmd != 0xff) && ((dev->last_cmd & 0x40) != 0)) { dev->last_cmd &= 0x0f; workrequ = dev->id[dev->last_cmd].curr_req; - goto cmd_subp; + if (workrequ != NULL) /* check NULL pointer */ + { + goto cmd_subp; + } + dev->last_cmd = 0xff; + if (dev->quhdu == dev->quendu) + { + dev->in_snd = 0; + restore_flags(flags); + return ; + } } dev->working++; j = dev->quhdu; @@ -591,6 +626,9 @@ oktosend: workrequ->request_bufflen = 0x08; } } + if (dev->ata_cdbu[0] == 0x00) { + workrequ->request_bufflen = 0; + } /* * Why limit this ???? */ @@ -600,11 +638,11 @@ oktosend: dev->ata_cdbu[4] = 0x24; } } - + tmport = workportu + 0x1b; - j = inb(tmport) & 0x0e; + j = 0; target_id = workrequ->target; - + /* * Wide ? */ @@ -612,13 +650,17 @@ oktosend: w = w << target_id; if ((w & dev->wide_idu) != 0) { j |= 0x01; - } + } outb(j, tmport); - + while ((inb(tmport) & 0x01) != j) + { + outb(j,tmport); + } + /* * Write the command */ - + tmport = workportu; outb(workrequ->cmd_len, tmport++); outb(0x2c, tmport++); @@ -633,17 +675,17 @@ oktosend: * Write the target */ outb(dev->id[target_id].devspu, tmport++); - + /* * Figure out the transfer size */ - if (workrequ->use_sg) + if (workrequ->use_sg) { l = 0; sgpnt = (struct scatterlist *) workrequ->request_buffer; - for (i = 0; i < workrequ->use_sg; i++) + for (i = 0; i < workrequ->use_sg; i++) { - if (sgpnt[i].length == 0 || workrequ->use_sg > ATP870U_SCATTER) + if (sgpnt[i].length == 0 || workrequ->use_sg > ATP870U_SCATTER) { panic("Foooooooood fight!"); } @@ -694,13 +736,13 @@ oktosend: tmpcip = dev->pciport; prd = dev->id[target_id].prd_tableu; dev->id[target_id].prd_posu = prd; - + /* * Now write the request list. Either as scatter/gather or as * a linear chain. */ - - if (workrequ->use_sg) + + if (workrequ->use_sg) { sgpnt = (struct scatterlist *) workrequ->request_buffer; i = 0; @@ -737,8 +779,21 @@ oktosend: outb(0x06, tmpcip); outb(0x00, tmpcip); tmpcip = tmpcip - 2; + + tmport = workportu + 0x3a; + if ((dev->ata_cdbu[0] == 0x08) || (dev->ata_cdbu[0] == 0x28) || + (dev->ata_cdbu[0] == 0x0a) || (dev->ata_cdbu[0] == 0x2a)) + { + outb((unsigned char)((inb(tmport) & 0xf3) | 0x08),tmport); + } + else + { + outb((unsigned char)(inb(tmport) & 0xf3),tmport); + } + tmport = workportu + 0x1c; + if ((dev->ata_cdbu[0] == WRITE_6) || (dev->ata_cdbu[0] == WRITE_10) || - (dev->ata_cdbu[0] == WRITE_12) || (dev->ata_cdbu[0] == MODE_SELECT)) + (dev->ata_cdbu[0] == WRITE_12) || (dev->ata_cdbu[0] == MODE_SELECT)) { dev->id[target_id].dirctu = 0x20; if (inb(tmport) == 0) { @@ -752,7 +807,7 @@ oktosend: restore_flags(flags); return; } - if (inb(tmport) == 0) + if (inb(tmport) == 0) { tmport = workportu + 0x18; outb(0x08, tmport); @@ -798,20 +853,20 @@ FUN_D7: goto FUN_D7; } } - *val |= 0x4000; /* assert DB6 */ + *val |= 0x4000; /* assert DB6 */ outw(*val, tmport); - *val &= 0xdfff; /* assert DB5 */ + *val &= 0xdfff; /* assert DB5 */ outw(*val, tmport); FUN_D5: for (i = 0; i < 10; i++) { /* stable >= bus settle delay(400 ns) */ - if ((inw(tmport) & 0x2000) != 0) { /* DB5 all release? */ + if ((inw(tmport) & 0x2000) != 0) { /* DB5 all release? */ goto FUN_D5; } } - *val |= 0x8000; /* no DB4-0, assert DB7 */ + *val |= 0x8000; /* no DB4-0, assert DB7 */ *val &= 0xe0ff; outw(*val, tmport); - *val &= 0xbfff; /* release DB6 */ + *val &= 0xbfff; /* release DB6 */ outw(*val, tmport); FUN_D6: for (i = 0; i < 10; i++) { /* stable >= bus settle delay(400 ns) */ @@ -887,9 +942,9 @@ void tscam(unsigned char host) outb(k, tmport++); tmport = dev->ioport + 0x1b; if (dev->chip_veru == 4) { - outb((unsigned char) ((inb(tmport) & 0x0e) | 0x01), tmport); + outb(0x01, tmport); } else { - outb((unsigned char) (inb(tmport) & 0x0e), tmport); + outb(0x00, tmport); } wait_rdyok: tmport = dev->ioport + 0x18; @@ -917,17 +972,17 @@ wait_rdyok: outb(0, 0x80); - val = 0x0080; /* bsy */ + val = 0x0080; /* bsy */ tmport = dev->ioport + 0x1c; outw(val, tmport); - val |= 0x0040; /* sel */ + val |= 0x0040; /* sel */ outw(val, tmport); - val |= 0x0004; /* msg */ + val |= 0x0004; /* msg */ outw(val, tmport); inb(0x80); /* 2 deskew delay(45ns*2=90ns) */ val &= 0x007f; /* no bsy */ outw(val, tmport); - mydlyu(0xffff); /* recommanded SCAM selection response time */ + mydlyu(0xffff); /* recommanded SCAM selection response time */ mydlyu(0xffff); val &= 0x00fb; /* after 1ms no msg */ outw(val, tmport); @@ -977,7 +1032,7 @@ TCM_SYNC: val |= 0x3f00; fun_scam(dev, &val); outb(3, 0x80); - val &= 0x00ff; /* isolation */ + val &= 0x00ff; /* isolation */ val |= 0x2000; fun_scam(dev, &val); outb(4, 0x80); @@ -1012,10 +1067,10 @@ TCM_5: /* isolation complete.. */ printk(" \n%x %x %x %s\n ",assignid_map,mbuf[0],mbuf[1],&mbuf[2]); */ i = 15; j = mbuf[0]; - if ((j & 0x20) != 0) { /* bit5=1:ID upto 7 */ + if ((j & 0x20) != 0) { /* bit5=1:ID upto 7 */ i = 7; } - if ((j & 0x06) == 0) { /* IDvalid? */ + if ((j & 0x06) == 0) { /* IDvalid? */ goto G2Q5; } k = mbuf[1]; @@ -1030,7 +1085,7 @@ small_id: goto small_id; } G2Q5: /* srch from max acceptable ID# */ - k = i; /* max acceptable ID# */ + k = i; /* max acceptable ID# */ G2Q_LP: m = 1; m <<= k; @@ -1041,12 +1096,12 @@ G2Q_LP: k--; goto G2Q_LP; } -G2Q_QUIN: /* k=binID#, */ +G2Q_QUIN: /* k=binID#, */ assignid_map |= m; if (k < 8) { quintet[0] = 0x38; /* 1st dft ID<8 */ } else { - quintet[0] = 0x31; /* 1st ID>=8 */ + quintet[0] = 0x31; /* 1st ID>=8 */ } k &= 0x07; quintet[1] = g2q_tab[k]; @@ -1067,15 +1122,15 @@ G2Q_QUIN: /* k=binID#, */ void is870(unsigned long host, unsigned int wkport) { unsigned int tmport; - unsigned char i, j, k, rmb; + unsigned char i, j, k, rmb, n; unsigned short int m; static unsigned char mbuf[512]; - static unsigned char satn[9] = {0, 0, 0, 0, 0, 0, 0, 6, 6}; + static unsigned char satn[9] = {0, 0, 0, 0, 0, 0, 0, 6, 6}; static unsigned char inqd[9] = {0x12, 0, 0, 0, 0x24, 0, 0, 0x24, 6}; - static unsigned char synn[6] = {0x80, 1, 3, 1, 0x19, 0x0e}; + static unsigned char synn[6] = {0x80, 1, 3, 1, 0x19, 0x0e}; static unsigned char synu[6] = {0x80, 1, 3, 1, 0x0c, 0x0e}; static unsigned char synw[6] = {0x80, 1, 3, 1, 0x0c, 0x07}; - static unsigned char wide[6] = {0x80, 1, 2, 3, 1, 0}; + static unsigned char wide[6] = {0x80, 1, 2, 3, 1, 0}; struct atp_unit *dev = &atp_unit[host]; sync_idu = 0; @@ -1095,10 +1150,13 @@ void is870(unsigned long host, unsigned int wkport) printk(KERN_INFO " ID: %2d Host Adapter\n", dev->host_idu); continue; } + tmport = wkport + 0x1b; if (dev->chip_veru == 4) { - tmport = wkport + 0x1b; - j = (inb(tmport) & 0x0e) | 0x01; - outb(j, tmport); + outb(0x01, tmport); + } + else + { + outb(0x00, tmport); } tmport = wkport + 1; outb(0x08, tmport++); @@ -1174,10 +1232,9 @@ sel_ok: continue; } while (inb(tmport) != 0x8e); + tmport = wkport + 0x1b; if (dev->chip_veru == 4) { - tmport = wkport + 0x1b; - j = inb(tmport) & 0x0e; - outb(j, tmport); + outb(0x00, tmport); } tmport = wkport + 0x18; outb(0x08, tmport); @@ -1218,6 +1275,7 @@ inq_ok: printk(KERN_INFO " ID: %2d %s\n", i, &mbuf[8]); dev->id[i].devtypeu = mbuf[0]; rmb = mbuf[1]; + n = mbuf[7]; if (dev->chip_veru != 4) { goto not_wide; } @@ -1228,8 +1286,7 @@ inq_ok: goto not_wide; } tmport = wkport + 0x1b; - j = (inb(tmport) & 0x0e) | 0x01; - outb(j, tmport); + outb(0x01, tmport); tmport = wkport + 3; outb(satn[0], tmport++); outb(satn[1], tmport++); @@ -1368,13 +1425,15 @@ widep_cmd: m = m << i; dev->wide_idu |= m; not_wide: - if ((dev->id[i].devtypeu == 0x00) || (dev->id[i].devtypeu == 0x07)) { + if ((dev->id[i].devtypeu == 0x00) || (dev->id[i].devtypeu == 0x07) || + ((dev->id[i].devtypeu == 0x05) && ((n & 0x10) != 0))) + { goto set_sync; } continue; set_sync: tmport = wkport + 0x1b; - j = inb(tmport) & 0x0e; + j = 0; if ((m & dev->wide_idu) != 0) { j |= 0x01; } @@ -1414,17 +1473,13 @@ try_sync: while ((inb(tmport) & 0x80) == 0) { if ((inb(tmport) & 0x01) != 0) { tmport -= 0x06; - if (rmb != 0) { - outb(synn[j++], tmport); + if ((m & dev->wide_idu) != 0) { + outb(synw[j++], tmport); } else { - if ((m & dev->wide_idu) != 0) { - outb(synw[j++], tmport); + if ((m & dev->ultra_map) != 0) { + outb(synu[j++], tmport); } else { - if ((m & dev->ultra_map) != 0) { - outb(synu[j++], tmport); - } else { - outb(synn[j++], tmport); - } + outb(synn[j++], tmport); } } tmport += 0x06; @@ -1573,9 +1628,9 @@ int atp870u_detect(Scsi_Host_Template * tpnt) int tmpcnt = 0; int count = 0; int result; - - static unsigned short devid[7] = { - 0x8002, 0x8010, 0x8020, 0x8030, 0x8040, 0x8050, 0 + + static unsigned short devid[8] = { + 0x8002, 0x8010, 0x8020, 0x8030, 0x8040, 0x8050, 0x8060, 0 }; printk(KERN_INFO "aec671x_detect: \n"); @@ -1615,7 +1670,7 @@ int atp870u_detect(Scsi_Host_Template * tpnt) h = 0; while (devid[h] != 0) { pdev[2] = pci_find_device(0x1191, devid[h], pdev[2]); - if (pdev[2] == NULL) { + if (pdev[2] == NULL || pci_enable_device(pdev[2])) { h++; index = 0; continue; @@ -1650,7 +1705,7 @@ int atp870u_detect(Scsi_Host_Template * tpnt) } /* Found an atp870u/w. */ - base_io = pdev[h]->resource[0].start; + base_io = pci_resource_start(pdev[h], 0); irq = pdev[h]->irq; error = pci_read_config_byte(pdev[h],0x49,&host_id); @@ -1687,6 +1742,13 @@ int atp870u_detect(Scsi_Host_Template * tpnt) printk(KERN_ERR "Unable to allocate IRQ for Acard controller.\n"); goto unregister; } + + if (chip_ver[h] > 0x07) /* check if atp876 chip */ + { /* then enable terminator */ + tmport = base_io + 0x3e; + outb(0x30, tmport); + } + tmport = base_io + 0x3a; k = (inb(tmport) & 0xf3) | 0x10; outb(k, tmport); @@ -1725,7 +1787,7 @@ int atp870u_detect(Scsi_Host_Template * tpnt) shpnt->n_io_port = 0x40; /* Number of bytes of I/O space used */ shpnt->irq = irq; restore_flags(flags); - request_region(base_io, 0x40, "atp870u"); /* Register the IO ports that we use */ + request_region(base_io, 0x40, "atp870u"); /* Register the IO ports that we use */ count++; index++; continue; @@ -1788,7 +1850,7 @@ int atp870u_reset(Scsi_Cmnd * SCpnt, unsigned int reset_flags) } panic("Reset bus host not found !"); find_host: -/* SCpnt->result = 0x00080000; +/* SCpnt->result = 0x00080000; SCpnt->scsi_done(SCpnt); dev->working=0; dev->quhdu=0; @@ -1801,14 +1863,14 @@ const char *atp870u_info(struct Scsi_Host *notused) { static char buffer[128]; - strcpy(buffer, "ACARD AEC-6710/6712 PCI Ultra/W SCSI-3 Adapter Driver V2.0+ac "); + strcpy(buffer, "ACARD AEC-6710/6712 PCI Ultra/W SCSI-3 Adapter Driver V2.1+ac "); return buffer; } int atp870u_set_info(char *buffer, int length, struct Scsi_Host *HBAptr) { - return -ENOSYS; /* Currently this is a no-op */ + return -ENOSYS; /* Currently this is a no-op */ } #define BLS buffer + len + size @@ -1846,7 +1908,7 @@ int atp870u_proc_info(char *buffer, char **start, off_t offset, int length, if (offset == 0) { memset(buff, 0, sizeof(buff)); } - size += sprintf(BLS, "ACARD AEC-671X Driver Version: 2.0+ac\n"); + size += sprintf(BLS, "ACARD AEC-671X Driver Version: 2.1+ac\n"); len += size; pos = begin + len; size = 0; @@ -1894,7 +1956,7 @@ int atp870u_biosparam(Scsi_Disk * disk, kdev_t dev, int *ip) int atp870u_release (struct Scsi_Host *pshost) { int h; - for (h = 0; h <= admaxu; h++) + for (h = 0; h <= admaxu; h++) { if (pshost == atp_host[h]) { int k; @@ -1907,7 +1969,7 @@ int atp870u_release (struct Scsi_Host *pshost) } } panic("atp870u: bad scsi host passed.\n"); - + } #ifdef MODULE diff --git a/drivers/scsi/dmx3191d.c b/drivers/scsi/dmx3191d.c index 2bc31ea28..4d1eecef4 100644 --- a/drivers/scsi/dmx3191d.c +++ b/drivers/scsi/dmx3191d.c @@ -68,11 +68,10 @@ int __init dmx3191d_detect(Scsi_Host_Template *tmpl) { while ((pdev = pci_find_device(PCI_VENDOR_ID_DOMEX, PCI_DEVICE_ID_DOMEX_DMX3191D, pdev))) { -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,13) - unsigned long port = pdev->base_address[0] & PCI_IOADDRESS_MASK; -#else - unsigned long port = pdev->resource[0].start; -#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2,3,13) */ + unsigned long port = pci_resource_start (pdev, 0); + + if (pci_enable_device(pdev)) + continue; if (check_region(port, DMX3191D_REGION)) { dmx3191d_printk("region 0x%lx-0x%lx already reserved\n", diff --git a/drivers/scsi/eata.c b/drivers/scsi/eata.c index c1939a817..4f3c09d6c 100644 --- a/drivers/scsi/eata.c +++ b/drivers/scsi/eata.c @@ -829,7 +829,9 @@ static inline void tune_pci_port(unsigned long port_base) { if (!(dev = pci_find_class(PCI_CLASS_STORAGE_SCSI << 8, dev))) break; - if (pci_read_config_dword(dev, PCI_BASE_ADDRESS_0, &addr)) continue; + addr = pci_resource_start (dev, 0); + + pci_enable_device (dev); /* XXX handle error */ #if defined(DEBUG_PCI_DETECT) printk("%s: tune_pci_port, bus %d, devfn 0x%x, addr 0x%x.\n", diff --git a/drivers/scsi/eata_dma.c b/drivers/scsi/eata_dma.c index 0f072c46e..ca3b48110 100644 --- a/drivers/scsi/eata_dma.c +++ b/drivers/scsi/eata_dma.c @@ -1388,20 +1388,22 @@ void find_PCI(struct get_conf *buf, Scsi_Host_Template * tpnt) #ifndef CONFIG_PCI printk("eata_dma: kernel PCI support not enabled. Skipping scan for PCI HBAs.\n"); #else - struct pci_dev *dev; + struct pci_dev *dev = NULL; u32 base, x; u8 pal1, pal2, pal3; - for(dev=NULL; dev = pci_find_device(PCI_VENDOR_ID_DPT, PCI_DEVICE_ID_DPT, dev);) { + while ((dev = pci_find_device(PCI_VENDOR_ID_DPT, PCI_DEVICE_ID_DPT, dev)) != NULL) { DBG(DBG_PROBE && DBG_PCI, printk("eata_dma: find_PCI, HBA at %s\n", dev->name)); + if (pci_enable_device(dev)) + continue; pci_set_master(dev); - base = dev->resource[0].flags; - if (!(base & PCI_BASE_ADDRESS_SPACE_IO)) { + base = pci_resource_flags(dev, 0); + if (base & IORESOURCE_MEM) { printk("eata_dma: invalid base address of device %s\n", dev->name); continue; } - base = dev->resource[0].start; + base = pci_resource_start(dev, 0); /* EISA tag there ? */ pal1 = inb(base); pal2 = inb(base + 1); diff --git a/drivers/scsi/eata_pio.c b/drivers/scsi/eata_pio.c index dca7ca765..b276f8629 100644 --- a/drivers/scsi/eata_pio.c +++ b/drivers/scsi/eata_pio.c @@ -878,19 +878,21 @@ void find_pio_PCI(struct get_conf *buf, Scsi_Host_Template * tpnt) #ifndef CONFIG_PCI printk("eata_dma: kernel PCI support not enabled. Skipping scan for PCI HBAs.\n"); #else - struct pci_dev *dev; + struct pci_dev *dev = NULL; u32 base, x; - for(dev=NULL; dev = pci_find_device(PCI_VENDOR_ID_DPT, PCI_DEVICE_ID_DPT, dev);) { + while ((dev = pci_find_device(PCI_VENDOR_ID_DPT, PCI_DEVICE_ID_DPT, dev)) != NULL) { DBG(DBG_PROBE && DBG_PCI, printk("eata_pio: find_PCI, HBA at %s\n", dev->name)); + if (pci_enable_device(dev)) + continue; pci_set_master(dev); - base = dev->resource[0].flags; - if (!(base & PCI_BASE_ADDRESS_SPACE_IO)) { + base = pci_resource_flags(dev, 0); + if (base & IORESOURCE_MEM) { printk("eata_pio: invalid base address of device %s\n", dev->name); continue; } - base = dev->resource[0].start; + base = pci_resource_start(dev, 0); /* EISA tag there ? */ if ((inb(base) == 0x12) && (inb(base + 1) == 0x14)) continue; /* Jep, it's forced, so move on */ diff --git a/drivers/scsi/fdomain.c b/drivers/scsi/fdomain.c index 59d9f2415..71cd7337a 100644 --- a/drivers/scsi/fdomain.c +++ b/drivers/scsi/fdomain.c @@ -828,6 +828,7 @@ static int fdomain_pci_bios_detect( int *irq, int *iobase ) PCI_DEVICE_ID_FD_36C70, pdev)) == NULL) return 0; + if (pci_enable_device(pdev)) return 0; #if DEBUG_DETECT printk( "scsi: <fdomain> TMC-3260 detect:" @@ -840,7 +841,7 @@ static int fdomain_pci_bios_detect( int *irq, int *iobase ) /* We now have the appropriate device function for the FD board so we just read the PCI config info from the registers. */ - pci_base = pdev->resource[0].start; + pci_base = pci_resource_start(pdev, 0); pci_irq = pdev->irq; /* Now we have the I/O base address and interrupt from the PCI diff --git a/drivers/scsi/gdth.c b/drivers/scsi/gdth.c index cb42f6b7a..d04270af9 100644 --- a/drivers/scsi/gdth.c +++ b/drivers/scsi/gdth.c @@ -533,6 +533,8 @@ static int __init gdth_search_pci(gdth_pci_str *pcistr) pdev = NULL; while ((pdev = pci_find_device(PCI_VENDOR_ID_VORTEX,device_id,pdev)) != NULL) { + if (pci_enable_device(pdev)) + continue; if (cnt >= MAXHA) return cnt; /* GDT PCI controller found, resources are already in pdev */ diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c index 56c441a62..fd1a3ba72 100644 --- a/drivers/scsi/hosts.c +++ b/drivers/scsi/hosts.c @@ -349,6 +349,14 @@ #include "../acorn/scsi/powertec.h" #endif +#ifdef CONFIG_SCSI_ARXESCSI +#include "../acorn/scsi/arxescsi.h" +#endif + +#ifdef CONFIG_I2O_SCSI +#include "../i2o/i2o_scsi.h" +#endif + #ifdef CONFIG_JAZZ_ESP #include "jazz_esp.h" #endif @@ -640,6 +648,9 @@ static Scsi_Host_Template builtin_scsi_hosts[] = #ifdef CONFIG_SCSI_CUMANA_2 CUMANA_FAS216, #endif +#ifdef CONFIG_SCSI_ARXESCSI + ARXEScsi, +#endif #ifdef CONFIG_SCSI_ECOSCSI ECOSCSI_NCR5380, #endif @@ -659,6 +670,10 @@ static Scsi_Host_Template builtin_scsi_hosts[] = #ifdef CONFIG_BLK_DEV_3W_XXXX_RAID TWXXXX, #endif +/* Put I2O last so that host specific controllers always win */ +#ifdef CONFIG_I2O_SCSI + I2OSCSI +#endif /* "Removable host adapters" below this line (Parallel Port/USB/other) */ #ifdef CONFIG_SCSI_PPA PPA, @@ -742,38 +757,41 @@ scsi_unregister(struct Scsi_Host * sh){ */ struct Scsi_Host * scsi_register(Scsi_Host_Template * tpnt, int j){ - struct Scsi_Host * retval, *shpnt; + struct Scsi_Host * retval, *shpnt, *o_shp; Scsi_Host_Name *shn, *shn2; - int new = 1; + int flag_new = 1; + const char * hname; + size_t hname_len; retval = (struct Scsi_Host *)kmalloc(sizeof(struct Scsi_Host) + j, - (tpnt->unchecked_isa_dma && j ? GFP_DMA : 0) | GFP_ATOMIC); + (tpnt->unchecked_isa_dma && j ? + GFP_DMA : 0) | GFP_ATOMIC); memset(retval, 0, sizeof(struct Scsi_Host) + j); /* trying to find a reserved entry (host_no) */ - for (shn = scsi_host_no_list;shn;shn = shn->next) - if (!(shn->host_registered) && shn->loaded_as_module && tpnt->proc_dir && - tpnt->proc_dir->name && !strncmp(tpnt->proc_dir->name, shn->name, strlen(tpnt->proc_dir->name))) { - new = 0; + hname = (tpnt->proc_name) ? tpnt->proc_name : ""; + hname_len = strlen(hname); + for (shn = scsi_host_no_list;shn;shn = shn->next) { + if (!(shn->host_registered) && shn->loaded_as_module && + (hname_len > 0) && (0 == strncmp(hname, shn->name, hname_len))) { + flag_new = 0; retval->host_no = shn->host_no; shn->host_registered = 1; shn->loaded_as_module = scsi_loadable_module_flag; break; } + } atomic_set(&retval->host_active,0); retval->host_busy = 0; retval->host_failed = 0; if(j > 0xffff) panic("Too many extra bytes requested\n"); retval->extra_bytes = j; retval->loaded_as_module = scsi_loadable_module_flag; - if (new) { - int len = 0; + if (flag_new) { shn = (Scsi_Host_Name *) kmalloc(sizeof(Scsi_Host_Name), GFP_ATOMIC); - if (tpnt->proc_dir) - len = strlen(tpnt->proc_dir->name); - shn->name = kmalloc(len+1, GFP_ATOMIC); - if (tpnt->proc_dir) - strncpy(shn->name, tpnt->proc_dir->name, len); - shn->name[len] = 0; + shn->name = kmalloc(hname_len + 1, GFP_ATOMIC); + if (hname_len > 0) + strncpy(shn->name, hname, hname_len); + shn->name[hname_len] = 0; shn->host_no = max_scsi_hosts++; shn->host_registered = 1; shn->loaded_as_module = scsi_loadable_module_flag; @@ -837,11 +855,26 @@ struct Scsi_Host * scsi_register(Scsi_Host_Template * tpnt, int j){ if(!scsi_hostlist) scsi_hostlist = retval; - else - { + else { shpnt = scsi_hostlist; - while(shpnt->next) shpnt = shpnt->next; - shpnt->next = retval; + if (retval->host_no < shpnt->host_no) { + retval->next = shpnt; + wmb(); /* want all to see these writes in this order */ + scsi_hostlist = retval; + } + else { + for (o_shp = shpnt, shpnt = shpnt->next; shpnt; + o_shp = shpnt, shpnt = shpnt->next) { + if (retval->host_no < shpnt->host_no) { + retval->next = shpnt; + wmb(); + o_shp->next = retval; + break; + } + } + if (! shpnt) + o_shp->next = retval; + } } return retval; diff --git a/drivers/scsi/in2000.h b/drivers/scsi/in2000.h index 63bfa6d65..2b7121a9b 100644 --- a/drivers/scsi/in2000.h +++ b/drivers/scsi/in2000.h @@ -34,8 +34,10 @@ #define DEBUGGING_ON /* enable command-line debugging bitmask */ #define DEBUG_DEFAULTS 0 /* default bitmask - change from command-line */ +#ifdef __i386__ #define FAST_READ_IO /* No problems with these on my machine */ #define FAST_WRITE_IO +#endif #ifdef DEBUGGING_ON #define DB(f,a) if (hostdata->args & (f)) a; @@ -52,6 +54,7 @@ #define write1_io(b,a) (outb((b),hostdata->io_base+(a))) #define write2_io(w,a) (outw((w),hostdata->io_base+(a))) +#ifdef __i386__ /* These inline assembly defines are derived from a patch * sent to me by Bill Earnest. He's done a lot of very * valuable thinking, testing, and coding during his effort @@ -90,6 +93,7 @@ int __dummy_1,__dummy_2; \ : "2" (f), "0" (sp), "1" (i) /* input */ \ ); /* trashed */ \ }) +#endif /* IN2000 io_port offsets */ #define IO_WD_ASR 0x00 /* R - 3393 auxstat reg */ diff --git a/drivers/scsi/ini9100u.c b/drivers/scsi/ini9100u.c index e44bc7929..4b903ea98 100644 --- a/drivers/scsi/ini9100u.c +++ b/drivers/scsi/ini9100u.c @@ -290,6 +290,8 @@ int tul_NewReturnNumberOfAdapters(void) for (i = 0; i < TULSZ(i91u_pci_devices); i++) { while ((pDev = pci_find_device(i91u_pci_devices[i].vendor_id, i91u_pci_devices[i].device_id, pDev)) != NULL) { + if (pci_enable_device(pDev)) + continue; pci_read_config_dword(pDev, 0x44, (u32 *) & dRegValue); wBIOS = (UWORD) (dRegValue & 0xFF); if (((dRegValue & 0xFF00) >> 8) == 0xFF) @@ -377,8 +379,6 @@ int i91u_detect(Scsi_Host_Template * tpnt) pHCB->pSRB_head = NULL; /* Initial SRB save queue */ pHCB->pSRB_tail = NULL; /* Initial SRB save queue */ pHCB->pSRB_lock = SPIN_LOCK_UNLOCKED; /* SRB save queue lock */ - request_region(pHCB->HCS_Base, 0x100, "i91u"); /* Register */ - get_tulipPCIConfig(pHCB, i); dBiosAdr = pHCB->HCS_BIOS; @@ -387,6 +387,8 @@ int i91u_detect(Scsi_Host_Template * tpnt) pbBiosAdr = phys_to_virt(dBiosAdr); init_tulip(pHCB, tul_scb + (i * tul_num_scb), tul_num_scb, pbBiosAdr, 10); + request_region(pHCB->HCS_Base, 256, "i91u"); /* Register */ + pHCB->HCS_Index = i; /* 7/29/98 */ hreg = scsi_register(tpnt, sizeof(HCS)); hreg->io_port = pHCB->HCS_Base; @@ -813,3 +815,13 @@ static void i91u_panic(char *msg) printk("\ni91u_panic: %s\n", msg); panic("i91u panic"); } + +/* + * Release ressources + */ +int i91u_release(struct Scsi_Host *hreg) +{ + free_irq(hreg->irq, hreg); + release_region(hreg->io_port, 256); + return 0; +} diff --git a/drivers/scsi/ini9100u.h b/drivers/scsi/ini9100u.h index a7bef8790..7f7b039a7 100644 --- a/drivers/scsi/ini9100u.h +++ b/drivers/scsi/ini9100u.h @@ -78,6 +78,7 @@ #include "sd.h" extern int i91u_detect(Scsi_Host_Template *); +extern int i91u_release(struct Scsi_Host *); extern int i91u_command(Scsi_Cmnd *); extern int i91u_queue(Scsi_Cmnd *, void (*done) (Scsi_Cmnd *)); extern int i91u_abort(Scsi_Cmnd *); @@ -93,7 +94,7 @@ extern int i91u_biosparam(Scsi_Disk *, kdev_t, int *); /*for linux v2.0 */ proc_info: NULL, \ name: i91u_REVID, \ detect: i91u_detect, \ - release: NULL, \ + release: i91u_release, \ info: NULL, \ command: i91u_command, \ queuecommand: i91u_queue, \ diff --git a/drivers/scsi/inia100.c b/drivers/scsi/inia100.c index 7dfc22fc1..6ca6ca7f9 100644 --- a/drivers/scsi/inia100.c +++ b/drivers/scsi/inia100.c @@ -247,6 +247,8 @@ int orc_ReturnNumberOfAdapters(void) inia100_pci_devices[i].device_id, pdev))) { + if (pci_enable_device(pdev)) + continue; if (iAdapters >= MAX_SUPPORTED_ADAPTERS) break; /* Never greater than maximum */ @@ -261,24 +263,23 @@ int orc_ReturnNumberOfAdapters(void) */ bPCIBusNum = pdev->bus->number; bPCIDeviceNum = pdev->devfn; - dRegValue = pdev->resource[0].start; + dRegValue = pci_resource_start(pdev, 0); if (dRegValue == -1) { /* Check return code */ printk("\n\rinia100: orchid read configuration error.\n"); return (0); /* Read configuration space error */ } + /* <02> read from base address + 0x50 offset to get the wBIOS balue. */ wBASE = (WORD) dRegValue; - /* Now read the interrupt line */ + /* Now read the interrupt line value */ dRegValue = pdev->irq; - bInterrupt = dRegValue & 0xFF; /* Assign interrupt line */ - pci_read_config_word(pdev, PCI_COMMAND, &command); - pci_write_config_word(pdev, PCI_COMMAND, - command | PCI_COMMAND_MASTER | PCI_COMMAND_IO); + bInterrupt = dRegValue; /* Assign interrupt line */ - wBASE &= PCI_BASE_ADDRESS_IO_MASK; wBIOS = ORC_RDWORD(wBASE, 0x50); + pci_set_master(pdev); + #ifdef MMAPIO base = wBASE & PAGE_MASK; page_offset = wBASE - base; @@ -370,7 +371,6 @@ int inia100_detect(Scsi_Host_Template * tpnt) memset((unsigned char *) pHCB->HCS_virEscbArray, 0, sz); pHCB->HCS_physEscbArray = (U32) VIRT_TO_BUS(pHCB->HCS_virEscbArray); - request_region(pHCB->HCS_Base, 0x100, "inia100"); /* Register */ get_orcPCIConfig(pHCB, i); dBiosAdr = pHCB->HCS_BIOS; @@ -382,6 +382,8 @@ int inia100_detect(Scsi_Host_Template * tpnt) printk("inia100: initial orchid fail!!\n"); return (0); } + request_region(pHCB->HCS_Base, 256, "inia100"); /* Register */ + hreg = scsi_register(tpnt, sizeof(ORC_HCS)); if (hreg == NULL) { printk("Invalid scsi_register pointer.\n"); @@ -411,28 +413,28 @@ int inia100_detect(Scsi_Host_Template * tpnt) /* Initial orc chip */ switch (i) { case 0: - ok = request_irq(pHCB->HCS_Intr, inia100_intr0, SA_INTERRUPT | SA_SHIRQ, "inia100", NULL); + ok = request_irq(pHCB->HCS_Intr, inia100_intr0, SA_INTERRUPT | SA_SHIRQ, "inia100", hreg); break; case 1: - ok = request_irq(pHCB->HCS_Intr, inia100_intr1, SA_INTERRUPT | SA_SHIRQ, "inia100", NULL); + ok = request_irq(pHCB->HCS_Intr, inia100_intr1, SA_INTERRUPT | SA_SHIRQ, "inia100", hreg); break; case 2: - ok = request_irq(pHCB->HCS_Intr, inia100_intr2, SA_INTERRUPT | SA_SHIRQ, "inia100", NULL); + ok = request_irq(pHCB->HCS_Intr, inia100_intr2, SA_INTERRUPT | SA_SHIRQ, "inia100", hreg); break; case 3: - ok = request_irq(pHCB->HCS_Intr, inia100_intr3, SA_INTERRUPT | SA_SHIRQ, "inia100", NULL); + ok = request_irq(pHCB->HCS_Intr, inia100_intr3, SA_INTERRUPT | SA_SHIRQ, "inia100", hreg); break; case 4: - ok = request_irq(pHCB->HCS_Intr, inia100_intr4, SA_INTERRUPT | SA_SHIRQ, "inia100", NULL); + ok = request_irq(pHCB->HCS_Intr, inia100_intr4, SA_INTERRUPT | SA_SHIRQ, "inia100", hreg); break; case 5: - ok = request_irq(pHCB->HCS_Intr, inia100_intr5, SA_INTERRUPT | SA_SHIRQ, "inia100", NULL); + ok = request_irq(pHCB->HCS_Intr, inia100_intr5, SA_INTERRUPT | SA_SHIRQ, "inia100", hreg); break; case 6: - ok = request_irq(pHCB->HCS_Intr, inia100_intr6, SA_INTERRUPT | SA_SHIRQ, "inia100", NULL); + ok = request_irq(pHCB->HCS_Intr, inia100_intr6, SA_INTERRUPT | SA_SHIRQ, "inia100", hreg); break; case 7: - ok = request_irq(pHCB->HCS_Intr, inia100_intr7, SA_INTERRUPT | SA_SHIRQ, "inia100", NULL); + ok = request_irq(pHCB->HCS_Intr, inia100_intr7, SA_INTERRUPT | SA_SHIRQ, "inia100", hreg); break; default: inia100_panic("inia100: Too many host adapters\n"); @@ -785,4 +787,14 @@ static void inia100_panic(char *msg) panic("inia100 panic"); } +/* + * Release ressources + */ +int inia100_release(struct Scsi_Host *hreg) +{ + free_irq(hreg->irq, hreg); + release_region(hreg->io_port, 256); + return 0; +} + /*#include "inia100scsi.c" */ diff --git a/drivers/scsi/inia100.h b/drivers/scsi/inia100.h index 509a42b5e..cc38bca81 100644 --- a/drivers/scsi/inia100.h +++ b/drivers/scsi/inia100.h @@ -71,6 +71,7 @@ #include "sd.h" extern int inia100_detect(Scsi_Host_Template *); +extern int inia100_release(struct Scsi_Host *); extern int inia100_command(Scsi_Cmnd *); extern int inia100_queue(Scsi_Cmnd *, void (*done) (Scsi_Cmnd *)); extern int inia100_abort(Scsi_Cmnd *); @@ -87,7 +88,7 @@ extern int inia100_biosparam(Scsi_Disk *, kdev_t, int *); /*for linux v2.0 */ proc_info: NULL, \ name: inia100_REVID, \ detect: inia100_detect, \ - release: NULL, \ + release: inia100_release, \ info: NULL, \ command: inia100_command, \ queuecommand: inia100_queue, \ diff --git a/drivers/scsi/ips.c b/drivers/scsi/ips.c index 22f98b60d..e5c5ca10f 100644 --- a/drivers/scsi/ips.c +++ b/drivers/scsi/ips.c @@ -325,12 +325,13 @@ ips_detect(Scsi_Host_Template *SHT) { if (!(dev = pci_find_device(IPS_VENDORID, IPS_DEVICEID, dev))) break; - + if (pci_enable_device(dev)) + break; /* stuff that we get in dev */ irq = dev->irq; bus = dev->bus->number; func = dev->devfn; - io_addr = dev->resource[0].start; + io_addr = pci_resource_start(dev, 0); /* get planer status */ if (pci_read_config_word(dev, 0x04, &planer)) { @@ -341,7 +342,7 @@ ips_detect(Scsi_Host_Template *SHT) { } /* check I/O address */ - if ((dev->resource[0].flags & PCI_BASE_ADDRESS_SPACE) != PCI_BASE_ADDRESS_SPACE_IO) + if (pci_resource_flags(dev, 0) & IORESOURCE_MEM) continue; /* check to see if an onboard planer controller is disabled */ diff --git a/drivers/scsi/mac_esp.c b/drivers/scsi/mac_esp.c index 99cfa7e8c..1bd2cdfcf 100644 --- a/drivers/scsi/mac_esp.c +++ b/drivers/scsi/mac_esp.c @@ -148,7 +148,7 @@ void fake_drq(int irq, void *dev_id, struct pt_regs *pregs) #define DRIVER_SETUP /* - * Function : mac_scsi_setup(char *str, int *ints) + * Function : mac_esp_setup(char *str, int *ints) * * Purpose : booter command line initialization of the overrides array, * @@ -160,7 +160,7 @@ void fake_drq(int irq, void *dev_id, struct pt_regs *pregs) * */ -void mac_esp_setup(char *str, int *ints) { +static int __init mac_esp_setup(char *str, int *ints) { #ifdef DRIVER_SETUP /* Format of mac53c9x parameter is: * mac53c9x=<num_esps>,<disconnect>,<nosync>,<can_queue>,<cmd_per_lun>,<sg_tablesize>,<hostid>,<use_tags> @@ -186,7 +186,7 @@ void mac_esp_setup(char *str, int *ints) { if (ints[0] < 1) { printk( "mac_esp_setup: no arguments!\n" ); - return; + return 0; } if (ints[0] >= 1) { @@ -237,6 +237,7 @@ void mac_esp_setup(char *str, int *ints) { } #endif #endif + return 1; } __setup("mac53c9x=", mac_esp_setup); diff --git a/drivers/scsi/mac_scsi.c b/drivers/scsi/mac_scsi.c index 11a58c478..62f7bd3c1 100644 --- a/drivers/scsi/mac_scsi.c +++ b/drivers/scsi/mac_scsi.c @@ -133,7 +133,7 @@ static volatile unsigned char *mac_scsi_nodrq = NULL; * */ -void mac_scsi_setup(char *str, int *ints) { +static int __init mac_scsi_setup(char *str, int *ints) { #ifdef DRIVER_SETUP /* Format of mac5380 parameter is: * mac5380=<can_queue>,<cmd_per_lun>,<sg_tablesize>,<hostid>,<use_tags> @@ -159,7 +159,7 @@ void mac_scsi_setup(char *str, int *ints) { if (ints[0] < 1) { printk( "mac_scsi_setup: no arguments!\n" ); - return; + return 0; } if (ints[0] >= 1) { @@ -193,6 +193,7 @@ void mac_scsi_setup(char *str, int *ints) { } #endif #endif + return 1; } __setup("mac5380=", mac_scsi_setup); diff --git a/drivers/scsi/megaraid.c b/drivers/scsi/megaraid.c index f051d391a..03e6d62ab 100644 --- a/drivers/scsi/megaraid.c +++ b/drivers/scsi/megaraid.c @@ -1478,6 +1478,8 @@ int mega_findCard (Scsi_Host_Template * pHostTmpl, struct pci_dev *pdev = NULL; while ((pdev = pci_find_device (pciVendor, pciDev, pdev))) { + if (pci_enable_device(pdev)) + continue; if ((flag & BOARD_QUARTZ) && (skip_id == -1)) { u16 magic; pci_read_config_word(pdev, PCI_CONF_AMISIG, &magic); @@ -1505,18 +1507,13 @@ int mega_findCard (Scsi_Host_Template * pHostTmpl, } /* Read the base port and IRQ from PCI */ - megaBase = pdev->resource[0].start; + megaBase = pci_resource_start (pdev, 0); megaIrq = pdev->irq; - if (flag & BOARD_QUARTZ) { - - megaBase &= PCI_BASE_ADDRESS_MEM_MASK; + if (flag & BOARD_QUARTZ) megaBase = (long) ioremap (megaBase, 128); - } - else { - megaBase &= PCI_BASE_ADDRESS_IO_MASK; + else megaBase += 0x10; - } /* Initialize SCSI Host structure */ host = scsi_register (pHostTmpl, sizeof (mega_host_config)); @@ -1589,7 +1586,7 @@ int mega_findCard (Scsi_Host_Template * pHostTmpl, "megaraid: to protect your data, please upgrade your firmware to version\n" "megaraid: 3.10 or later, available from the Dell Technical Support web\n" "megaraid: site at\n" -"http://support.dell.com/us/en/filelib/download/index.asp?fileid=2489\n"); +"http://support.dell.com/us/en/filelib/download/index.asp?fileid=2940\n"); megaraid_release (host); #ifdef MODULE continue; diff --git a/drivers/scsi/ncr53c8xx.c b/drivers/scsi/ncr53c8xx.c index aecbd4cf0..72f4ce11d 100644 --- a/drivers/scsi/ncr53c8xx.c +++ b/drivers/scsi/ncr53c8xx.c @@ -73,7 +73,7 @@ */ /* -** April 24 2000, version 3.2i +** May 11 2000, version 3.3b ** ** Supported SCSI-II features: ** Synchronous negotiation @@ -93,6 +93,7 @@ ** 53C895 (Wide, Fast 40, on board rom BIOS) ** 53C895A (Wide, Fast 40, on board rom BIOS) ** 53C896 (Wide, Fast 40, on board rom BIOS) +** 53C897 (Wide, Fast 40, on board rom BIOS) ** 53C1510D (Wide, Fast 40, on board rom BIOS) ** ** Other features: @@ -104,7 +105,7 @@ /* ** Name and version of the driver */ -#define SCSI_NCR_DRIVER_NAME "ncr53c8xx - version 3.2i" +#define SCSI_NCR_DRIVER_NAME "ncr53c8xx - version 3.3b" #define SCSI_NCR_DEBUG_FLAGS (0) @@ -187,6 +188,14 @@ typedef u64 u_int64; typedef u_long vm_offset_t; #include "ncr53c8xx.h" +/* +** Donnot compile integrity checking code for Linux-2.3.0 +** and above since SCSI data structures are not ready yet. +*/ +#if LINUX_VERSION_CODE < LinuxVersionCode(2,3,0) +#define SCSI_NCR_INTEGRITY_CHECKING +#endif + #define NAME53C "ncr53c" #define NAME53C8XX "ncr53c8xx" #define DRIVER_SMP_LOCK ncr53c8xx_lock @@ -472,8 +481,10 @@ static u_char Tekram_sync[16] __initdata = **========================================================== */ +#define NS_NOCHANGE (0) #define NS_SYNC (1) #define NS_WIDE (2) +#define NS_PPR (4) /*========================================================== ** @@ -666,6 +677,13 @@ struct tcb { /*2*/ u_char widedone; /*3*/ u_char wval; +#ifdef SCSI_NCR_INTEGRITY_CHECKING + u_char ic_min_sync; + u_char ic_max_width; + u_char ic_maximums_set; + u_char ic_done; +#endif + /*---------------------------------------------------------------- ** User settable limits and options. ** These limits are read from the NVRAM if present. @@ -1204,6 +1222,17 @@ struct ncb { struct ccb *ccb; /* Global CCB */ struct usrcmd user; /* Command from user */ u_char release_stage; /* Synchronisation stage on release */ + +#ifdef SCSI_NCR_INTEGRITY_CHECKING + /*---------------------------------------------------------------- + ** Fields that are used for integrity check + **---------------------------------------------------------------- + */ + unsigned char check_integrity; /* Enable midlayer integ.check on + * bus scan. */ + unsigned char check_integ_par; /* Set if par or Init. Det. error + * used only during integ check */ +#endif }; #define NCB_SCRIPT_PHYS(np,lbl) (np->p_script + offsetof (struct script, lbl)) @@ -1382,6 +1411,10 @@ static void ncr_int_sir (ncb_p np); static void ncr_int_sto (ncb_p np); static u_long ncr_lookup (char* id); static void ncr_negotiate (struct ncb* np, struct tcb* tp); +static int ncr_prepare_nego(ncb_p np, ccb_p cp, u_char *msgptr); +#ifdef SCSI_NCR_INTEGRITY_CHECKING +static int ncr_ic_nego(ncb_p np, ccb_p cp, Scsi_Cmnd *cmd, u_char *msgptr); +#endif #ifdef SCSI_NCR_PROFILE_SUPPORT static void ncb_profile (ncb_p np, ccb_p cp); @@ -1396,6 +1429,7 @@ static void ncr_setsync (ncb_p np, ccb_p cp, u_char scntl3, u_char sxfer); static void ncr_setup_tags (ncb_p np, u_char tn, u_char ln); static void ncr_setwide (ncb_p np, ccb_p cp, u_char wide, u_char ack); static int ncr_show_msg (u_char * msg); +static void ncr_print_msg (ccb_p cp, char *label, u_char *msg); static int ncr_snooptest (ncb_p np); static void ncr_timeout (ncb_p np); static void ncr_wakeup (ncb_p np, u_long code); @@ -3792,6 +3826,17 @@ ncr_attach (Scsi_Host_Template *tpnt, int unit, ncr_device *device) instance->can_queue = (MAX_START-4); instance->select_queue_depths = ncr53c8xx_select_queue_depths; +#ifdef SCSI_NCR_INTEGRITY_CHECKING + np->check_integrity = 0; + instance->check_integrity = 0; + +#ifdef SCSI_NCR_ENABLE_INTEGRITY_CHECK + if ( !(driver_setup.bus_check & 0x04) ) { + np->check_integrity = 1; + instance->check_integrity = 1; + } +#endif +#endif /* ** Patch script to physical addresses */ @@ -4020,6 +4065,270 @@ static inline void ncr_flush_done_cmds(Scsi_Cmnd *lcmd) } } +/*========================================================== +** +** +** Prepare the next negotiation message for integrity check, +** if needed. +** +** Fill in the part of message buffer that contains the +** negotiation and the nego_status field of the CCB. +** Returns the size of the message in bytes. +** +** +**========================================================== +*/ + +#ifdef SCSI_NCR_INTEGRITY_CHECKING +static int ncr_ic_nego(ncb_p np, ccb_p cp, Scsi_Cmnd *cmd, u_char *msgptr) +{ + tcb_p tp = &np->target[cp->target]; + int msglen = 0; + int nego = 0; + u_char no_increase; + + if (tp->inq_done) { + + if (!tp->ic_maximums_set) { + tp->ic_maximums_set = 1; + + /* check target and host adapter capabilities */ + if ( (tp->inq_byte7 & INQ7_WIDE16) && + np->maxwide && tp->usrwide ) + tp->ic_max_width = 1; + else + tp->ic_max_width = 0; + + if ((tp->inq_byte7 & INQ7_SYNC) && tp->maxoffs) { + tp->ic_min_sync = (tp->minsync < np->minsync) ? + np->minsync : tp->minsync; + } + else + tp->ic_min_sync = 255; + + tp->period = 1; + tp->widedone = 1; + } + + if (DEBUG_FLAGS & DEBUG_IC) { + printk("%s: cmd->ic_nego %d, 1st byte 0x%2X\n", + ncr_name(np), cmd->ic_nego, cmd->cmnd[0]); + } + + /* First command from integrity check routine will request + * a PPR message. Disable. + */ + if ((cmd->ic_nego & NS_PPR) == NS_PPR) + cmd->ic_nego &= ~NS_PPR; + /* Previous command recorded a parity or an initiator + * detected error condition. Force bus to narrow for this + * target. Clear flag. Negotation on request sense. + * Note: kernel forces 2 bus resets :o( but clears itself out. + * Minor bug? in scsi_obsolete.c (ugly) + */ + if (np->check_integ_par) { + printk("%s: Parity Error. Target set to narrow.\n", + ncr_name(np)); + tp->ic_max_width = 0; + tp->widedone = tp->period = 0; + } + + /* In case of a bus reset, ncr_negotiate will reset + * the flags tp->widedone and tp->period to 0, forcing + * a new negotiation. + */ + no_increase = 0; + if (tp->widedone == 0) { + cmd->ic_nego = NS_WIDE; + tp->widedone = 1; + no_increase = 1; + } + else if (tp->period == 0) { + cmd->ic_nego = NS_SYNC; + tp->period = 1; + no_increase = 1; + } + + switch (cmd->ic_nego) { + case NS_WIDE: + /* + ** negotiate wide transfers ? + ** Do NOT negotiate if device only supports + ** narrow. + */ + if (tp->ic_max_width | np->check_integ_par) { + nego = NS_WIDE; + + msgptr[msglen++] = M_EXTENDED; + msgptr[msglen++] = 2; + msgptr[msglen++] = M_X_WIDE_REQ; + msgptr[msglen++] = cmd->ic_nego_width & tp->ic_max_width; + } + else + cmd->ic_nego_width &= tp->ic_max_width; + + break; + + case NS_SYNC: + /* + ** negotiate synchronous transfers? + ** Target must support sync transfers. + ** + ** If period becomes longer than max, reset to async + */ + + if (tp->inq_byte7 & INQ7_SYNC) { + + nego = NS_SYNC; + + msgptr[msglen++] = M_EXTENDED; + msgptr[msglen++] = 3; + msgptr[msglen++] = M_X_SYNC_REQ; + + switch (cmd->ic_nego_sync) { + case 2: /* increase the period */ + if (!no_increase) { + if (tp->ic_min_sync <= 0x0A) + tp->ic_min_sync = 0x0C; + else if (tp->ic_min_sync <= 0x0C) + tp->ic_min_sync = 0x19; + else if (tp->ic_min_sync <= 0x19) + tp->ic_min_sync *= 2; + else { + tp->ic_min_sync = 255; + cmd->ic_nego_sync = 0; + tp->maxoffs = 0; + } + } + msgptr[msglen++] = tp->maxoffs?tp->ic_min_sync:0; + msgptr[msglen++] = tp->maxoffs; + break; + + case 1: /* nego. to maximum */ + msgptr[msglen++] = tp->maxoffs?tp->ic_min_sync:0; + msgptr[msglen++] = tp->maxoffs; + break; + + case 0: /* nego to async */ + default: + msgptr[msglen++] = 0; + msgptr[msglen++] = 0; + break; + }; + } + else + cmd->ic_nego_sync = 0; + break; + + case NS_NOCHANGE: + default: + break; + }; + }; + + cp->nego_status = nego; + np->check_integ_par = 0; + + if (nego) { + tp->nego_cp = cp; + if (DEBUG_FLAGS & DEBUG_NEGO) { + ncr_print_msg(cp, nego == NS_WIDE ? + "wide/narrow msgout": "sync/async msgout", msgptr); + }; + }; + + return msglen; +} +#endif /* SCSI_NCR_INTEGRITY_CHECKING */ + +/*========================================================== +** +** +** Prepare the next negotiation message if needed. +** +** Fill in the part of message buffer that contains the +** negotiation and the nego_status field of the CCB. +** Returns the size of the message in bytes. +** +** +**========================================================== +*/ + + +static int ncr_prepare_nego(ncb_p np, ccb_p cp, u_char *msgptr) +{ + tcb_p tp = &np->target[cp->target]; + int msglen = 0; + int nego = 0; + + if (tp->inq_done) { + + /* + ** negotiate wide transfers ? + */ + + if (!tp->widedone) { + if (tp->inq_byte7 & INQ7_WIDE16) { + nego = NS_WIDE; +#ifdef SCSI_NCR_INTEGRITY_CHECKING + if (tp->ic_done) + tp->usrwide &= tp->ic_max_width; +#endif + } else + tp->widedone=1; + + }; + + /* + ** negotiate synchronous transfers? + */ + + if (!nego && !tp->period) { + if (tp->inq_byte7 & INQ7_SYNC) { + nego = NS_SYNC; +#ifdef SCSI_NCR_INTEGRITY_CHECKING + if ((tp->ic_done) && + (tp->minsync < tp->ic_min_sync)) + tp->minsync = tp->ic_min_sync; +#endif + } else { + tp->period =0xffff; + PRINT_TARGET(np, cp->target); + printk ("target did not report SYNC.\n"); + }; + }; + }; + + switch (nego) { + case NS_SYNC: + msgptr[msglen++] = M_EXTENDED; + msgptr[msglen++] = 3; + msgptr[msglen++] = M_X_SYNC_REQ; + msgptr[msglen++] = tp->maxoffs ? tp->minsync : 0; + msgptr[msglen++] = tp->maxoffs; + break; + case NS_WIDE: + msgptr[msglen++] = M_EXTENDED; + msgptr[msglen++] = 2; + msgptr[msglen++] = M_X_WIDE_REQ; + msgptr[msglen++] = tp->usrwide; + break; + }; + + cp->nego_status = nego; + + if (nego) { + tp->nego_cp = cp; + if (DEBUG_FLAGS & DEBUG_NEGO) { + ncr_print_msg(cp, nego == NS_WIDE ? + "wide msgout":"sync_msgout", msgptr); + }; + }; + + return msglen; +} + + /*========================================================== ** @@ -4038,7 +4347,7 @@ static int ncr_queue_command (ncb_p np, Scsi_Cmnd *cmd) ccb_p cp; int segments; - u_char nego, idmsg, *msgptr; + u_char idmsg, *msgptr; u_int msglen; int direction; u_int32 lastp, goalp; @@ -4120,51 +4429,6 @@ static int ncr_queue_command (ncb_p np, Scsi_Cmnd *cmd) cp->phys.header.stamp.start = jiffies; #endif - /*--------------------------------------------------- - ** - ** negotiation required? - ** - **--------------------------------------------------- - */ - - nego = 0; - - if ((!tp->widedone || !tp->period) && !tp->nego_cp && tp->inq_done && lp) { - - /* - ** negotiate wide transfers ? - */ - - if (!tp->widedone) { - if (tp->inq_byte7 & INQ7_WIDE16) { - nego = NS_WIDE; - } else - tp->widedone=1; - }; - - /* - ** negotiate synchronous transfers? - */ - - if (!nego && !tp->period) { - if (tp->inq_byte7 & INQ7_SYNC) { - nego = NS_SYNC; - } else { - tp->period =0xffff; - PRINT_TARGET(np, cmd->target); - printk ("device did not report SYNC.\n"); - }; - }; - - /* - ** remember nego is pending for the target. - ** Avoid to start a nego for all queued commands - ** when tagged command queuing is enabled. - */ - - if (nego) - tp->nego_cp = cp; - }; /*---------------------------------------------------- ** @@ -4225,34 +4489,6 @@ static int ncr_queue_command (ncb_p np, Scsi_Cmnd *cmd) msgptr[msglen++] = (cp->tag << 1) + 1; } - switch (nego) { - case NS_SYNC: - msgptr[msglen++] = M_EXTENDED; - msgptr[msglen++] = 3; - msgptr[msglen++] = M_X_SYNC_REQ; - msgptr[msglen++] = tp->maxoffs ? tp->minsync : 0; - msgptr[msglen++] = tp->maxoffs; - if (DEBUG_FLAGS & DEBUG_NEGO) { - PRINT_ADDR(cp->cmd); - printk ("sync msgout: "); - ncr_show_msg (&cp->scsi_smsg [msglen-5]); - printk (".\n"); - }; - break; - case NS_WIDE: - msgptr[msglen++] = M_EXTENDED; - msgptr[msglen++] = 2; - msgptr[msglen++] = M_X_WIDE_REQ; - msgptr[msglen++] = tp->usrwide; - if (DEBUG_FLAGS & DEBUG_NEGO) { - PRINT_ADDR(cp->cmd); - printk ("wide msgout: "); - ncr_show_msg (&cp->scsi_smsg [msglen-4]); - printk (".\n"); - }; - break; - }; - /*---------------------------------------------------- ** ** Build the data descriptors @@ -4273,6 +4509,84 @@ static int ncr_queue_command (ncb_p np, Scsi_Cmnd *cmd) segments = 0; } + /*--------------------------------------------------- + ** + ** negotiation required? + ** + ** (nego_status is filled by ncr_prepare_nego()) + ** + **--------------------------------------------------- + */ + + cp->nego_status = 0; + +#ifdef SCSI_NCR_INTEGRITY_CHECKING + if ((np->check_integrity && tp->ic_done) || !np->check_integrity) { + if ((!tp->widedone || !tp->period) && !tp->nego_cp && lp) { + msglen += ncr_prepare_nego (np, cp, msgptr + msglen); + } + } + else if (np->check_integrity && (cmd->ic_in_progress)) { + msglen += ncr_ic_nego (np, cp, cmd, msgptr + msglen); + } + else if (np->check_integrity && cmd->ic_complete) { + /* + * Midlayer signal to the driver that all of the scsi commands + * for the integrity check have completed. Save the negotiated + * parameters (extracted from sval and wval). + */ + + { + u_char idiv; + idiv = (tp->wval>>4) & 0x07; + if ((tp->sval&0x1f) && idiv ) + tp->period = (((tp->sval>>5)+4) + *div_10M[idiv-1])/np->clock_khz; + else + tp->period = 0xffff; + } + /* + * tp->period contains 10 times the transfer period, + * which itself is 4 * the requested negotiation rate. + */ + if (tp->period <= 250) tp->ic_min_sync = 10; + else if (tp->period <= 303) tp->ic_min_sync = 11; + else if (tp->period <= 500) tp->ic_min_sync = 12; + else + tp->ic_min_sync = (tp->period + 40 - 1) / 40; + + + /* + * Negotiation for this target it complete. + */ + tp->ic_max_width = (tp->wval & EWS) ? 1: 0; + tp->ic_done = 1; + tp->widedone = 1; + + printk("%s: Integrity Check Complete: \n", ncr_name(np)); + + printk("%s: %s %s SCSI", ncr_name(np), + (tp->sval&0x1f)?"SYNC":"ASYNC", + tp->ic_max_width?"WIDE":"NARROW"); + + if (tp->sval&0x1f) { + u_long mbs = 10000 * (tp->ic_max_width + 1); + + printk(" %d.%d MB/s", + (int) (mbs / tp->period), (int) (mbs % tp->period)); + + printk(" (%d ns, %d offset)\n", + tp->period/10, tp->sval&0x1f); + } + else + printk(" %d MB/s. \n ", (tp->ic_max_width+1)*5); + } +#else + if ((!tp->widedone || !tp->period) && !tp->nego_cp && lp) { + msglen += ncr_prepare_nego (np, cp, msgptr + msglen); + } +#endif /* SCSI_NCR_INTEGRITY_CHECKING */ + /*---------------------------------------------------- ** ** Determine xfer direction. @@ -4376,12 +4690,11 @@ static int ncr_queue_command (ncb_p np, Scsi_Cmnd *cmd) ** status */ cp->actualquirks = tp->quirks; - cp->host_status = nego ? HS_NEGOTIATE : HS_BUSY; + cp->host_status = cp->nego_status ? HS_NEGOTIATE : HS_BUSY; cp->scsi_status = S_ILLEGAL; cp->parity_status = 0; cp->xerr_status = XE_OK; - cp->nego_status = nego; #if 0 cp->sync_status = tp->sval; cp->wide_status = tp->wval; @@ -5041,7 +5354,13 @@ void ncr_complete (ncb_p np, ccb_p cp) for (i=0; i<14; i++) printk (" %x", *p++); printk (".\n"); } - + } else if ((cp->host_status == HS_COMPLETE) + && (cp->scsi_status == S_CONFLICT)) { + /* + ** Reservation Conflict condition code + */ + cmd->result = ScsiResult(DID_OK, S_CONFLICT); + } else if ((cp->host_status == HS_COMPLETE) && (cp->scsi_status == S_BUSY || cp->scsi_status == S_QUEUE_FULL)) { @@ -6398,6 +6717,14 @@ static int ncr_int_par (ncb_p np) else msg = M_ID_ERROR; +#ifdef SCSI_NCR_INTEGRITY_CHECKING + /* + ** Save error message. For integrity check use only. + */ + if (np->check_integrity) + np->check_integ_par = msg; +#endif + /* * If the NCR stopped on a MOVE ^ DATA_IN, we jump to a * script that will ignore all data in bytes until phase @@ -6908,6 +7235,16 @@ static int ncr_show_msg (u_char * msg) return (1); } +static void ncr_print_msg ( ccb_p cp, char *label, u_char *msg) +{ + if (cp) + PRINT_ADDR(cp->cmd); + if (label) + printk("%s: ", label); + + (void) ncr_show_msg (msg); + printk(".\n"); +} void ncr_int_sir (ncb_p np) { @@ -8275,6 +8612,7 @@ static void ncr_selectclock(ncb_p np, u_char scntl3) static unsigned __init ncrgetfreq (ncb_p np, int gen) { unsigned ms = 0; + char count = 0; /* * Measure GEN timer delay in order @@ -8299,8 +8637,10 @@ static unsigned __init ncrgetfreq (ncb_p np, int gen) OUTB (nc_scntl3, 4); /* set pre-scaler to divide by 3 */ OUTB (nc_stime1, 0); /* disable general purpose timer */ OUTB (nc_stime1, gen); /* set to nominal delay of 1<<gen * 125us */ - while (!(INW(nc_sist) & GEN) && ms++ < 100000) - UDELAY (1000); /* count ms */ + while (!(INW(nc_sist) & GEN) && ms++ < 100000) { + for (count = 0; count < 10; count ++) + UDELAY (100); /* count ms */ + } OUTB (nc_stime1, 0); /* disable general purpose timer */ /* * set prescaler to divide by whatever 0 means diff --git a/drivers/scsi/pci2000.c b/drivers/scsi/pci2000.c index 94007c5a8..2681c520d 100644 --- a/drivers/scsi/pci2000.c +++ b/drivers/scsi/pci2000.c @@ -679,10 +679,12 @@ int Pci2000_Detect (Scsi_Host_Template *tpnt) while ( (pdev = pci_find_device (VENDOR_PSI, DEVICE_ROY_1, pdev)) != NULL ) { + if (pci_enable_device(pdev)) + continue; pshost = scsi_register (tpnt, sizeof(ADAPTER2000)); padapter = HOSTDATA(pshost); - padapter->basePort = pdev->resource[1].start & PCI_BASE_ADDRESS_IO_MASK; + padapter->basePort = pci_resource_start (pdev, 1); DEB (printk ("\nBase Regs = %#04X", padapter->basePort)); // get the base I/O port address padapter->mb0 = padapter->basePort + RTR_MAILBOX; // get the 32 bit mail boxes padapter->mb1 = padapter->basePort + RTR_MAILBOX + 4; diff --git a/drivers/scsi/pci2220i.c b/drivers/scsi/pci2220i.c index ca5c57981..8a59351aa 100644 --- a/drivers/scsi/pci2220i.c +++ b/drivers/scsi/pci2220i.c @@ -2386,8 +2386,8 @@ static USHORT GetRegs (struct Scsi_Host *pshost, BOOL bigd, struct pci_dev *pcid memset (&DaleSetup, 0, sizeof (DaleSetup)); memset (DiskMirror, 0, sizeof (DiskMirror)); - zr = pcidev->resource[1].start & PCI_BASE_ADDRESS_IO_MASK; - zl = pcidev->resource[2].start & PCI_BASE_ADDRESS_IO_MASK; + zr = pci_resource_start (pcidev, 1); + zl = pci_resource_start (pcidev, 2); padapter->basePort = zr; padapter->regRemap = zr + RTR_LOCAL_REMAP; // 32 bit local space remap @@ -2542,6 +2542,8 @@ int Pci2220i_Detect (Scsi_Host_Template *tpnt) while ( (pcidev = pci_find_device (VENDOR_PSI, DEVICE_DALE_1, pcidev)) != NULL ) { + if (pci_enable_device(pcidev)) + continue; pshost = scsi_register (tpnt, sizeof(ADAPTER2220I)); padapter = HOSTDATA(pshost); diff --git a/drivers/scsi/qla1280.c b/drivers/scsi/qla1280.c index 42f208062..f3d059df8 100644 --- a/drivers/scsi/qla1280.c +++ b/drivers/scsi/qla1280.c @@ -801,13 +801,13 @@ qla1280_detect(Scsi_Host_Template *template) for( i=0; bdp->device_id != 0 && i < NUM_OF_ISP_DEVICES; i++, bdp++ ) { #if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,95) while ((pdev = pci_find_device(QLA1280_VENDOR_ID, - bdp->device_id, pdev ) )) + bdp->device_id, pdev ) )) { + if (pci_enable_device(pdev)) continue; #else while (!(pcibios_find_device(QLA1280_VENDOR_ID, bdp->device_id, - index++, &pci_bus, &pci_devfn)) ) + index++, &pci_bus, &pci_devfn)) ) { #endif - { /* found a adapter */ host = scsi_register(template, sizeof(scsi_qla_host_t)); ha = (scsi_qla_host_t *) host->hostdata; @@ -817,9 +817,7 @@ qla1280_detect(Scsi_Host_Template *template) /* Sanitize the information from PCI BIOS. */ #if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,95) host->irq = pdev->irq; -/* this depends on release 2.3.18 */ - host->io_port = pdev->resource[0].start; -/* MRS host->io_port = (unsigned int) pdev->base_address[0]; */ + host->io_port = pci_resource_start(pdev, 0); ha->pci_bus = pdev->bus->number; ha->pci_device_fn = pdev->devfn; ha->pdev = pdev; @@ -828,14 +826,13 @@ qla1280_detect(Scsi_Host_Template *template) pcibios_read_config_dword(pci_bus, pci_devfn, OFFSET(cfgp->base_port), &piobase); host->irq = pci_irq; host->io_port = (unsigned int) piobase; + host->io_port &= PCI_BASE_ADDRESS_IO_MASK; ha->pci_bus = pci_bus; ha->pci_device_fn = pci_devfn; #endif ha->device_id = bdp->device_id; - host->io_port &= PCI_BASE_ADDRESS_IO_MASK; ha->devnum = i; - host->io_port &= PCI_BASE_ADDRESS_IO_MASK; if( qla1280_mem_alloc(ha) ) { printk(KERN_INFO "qla1280: Failed to allocate memory for adapter\n"); } diff --git a/drivers/scsi/qlogicfc.c b/drivers/scsi/qlogicfc.c index b8e739387..6200afafc 100644 --- a/drivers/scsi/qlogicfc.c +++ b/drivers/scsi/qlogicfc.c @@ -752,6 +752,8 @@ int isp2x00_detect(Scsi_Host_Template * tmpt) for (i=0; i<2; i++){ while ((pdev = pci_find_device(PCI_VENDOR_ID_QLOGIC, device_ids[i], pdev))) { + if (pci_enable_device(pdev)) + continue; host = scsi_register(tmpt, sizeof(struct isp2x00_hostdata)); host->max_id = QLOGICFC_MAX_ID + 1; @@ -2010,7 +2012,7 @@ static int isp2x00_init(struct Scsi_Host *sh) printk("qlogicfc%d : error reading PCI configuration\n", hostdata->host_id); return 1; } - io_base = pdev->resource[0].start; + io_base = pci_resource_start(pdev, 0); irq = pdev->irq; diff --git a/drivers/scsi/qlogicisp.c b/drivers/scsi/qlogicisp.c index b5da20220..b48a87326 100644 --- a/drivers/scsi/qlogicisp.c +++ b/drivers/scsi/qlogicisp.c @@ -678,6 +678,9 @@ int isp1020_detect(Scsi_Host_Template *tmpt) while ((pdev = pci_find_device(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP1020, pdev))) { + if (pci_enable_device(pdev)) + continue; + host = scsi_register(tmpt, sizeof(struct isp1020_hostdata)); hostdata = (struct isp1020_hostdata *) host->hostdata; @@ -1371,10 +1374,10 @@ static int isp1020_init(struct Scsi_Host *sh) return 1; } - io_base = pdev->resource[0].start; - mem_base = pdev->resource[1].start; - io_flags = pdev->resource[0].flags; - mem_flags = pdev->resource[1].flags; + io_base = pci_resource_start(pdev, 0); + mem_base = pci_resource_start(pdev, 1); + io_flags = pci_resource_flags(pdev, 0); + mem_flags = pci_resource_flags(pdev, 1); irq = pdev->irq; if (pdev->vendor != PCI_VENDOR_ID_QLOGIC) { diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index 7f67db94c..56ef67cb2 100644 --- a/drivers/scsi/scsi_scan.c +++ b/drivers/scsi/scsi_scan.c @@ -38,7 +38,6 @@ #define BLIST_MAX5LUN 0x080 #define BLIST_ISDISK 0x100 #define BLIST_ISROM 0x200 -#define BLIST_GHOST 0x400 static void print_inquiry(unsigned char *data); static int scan_scsis_single(int channel, int dev, int lun, int *max_scsi_dev, @@ -137,13 +136,7 @@ static struct dev_info device_list[] = {"NEC", "PD-1 ODX654P", "*", BLIST_FORCELUN | BLIST_SINGLELUN}, {"MATSHITA", "PD-1", "*", BLIST_FORCELUN | BLIST_SINGLELUN}, {"iomega", "jaz 1GB", "J.86", BLIST_NOTQ | BLIST_NOLUN}, - {"CREATIVE","DVD-RAM RAM","*", BLIST_GHOST}, - {"MATSHITA","PD-2 LF-D100","*", BLIST_GHOST}, - {"AOpen", "PD-2 DVD-520S", "*", BLIST_GHOST}, - {"HITACHI", "GF-1050","*", BLIST_GHOST}, /* Hitachi SCSI DVD-RAM */ {"TOSHIBA","CDROM","*", BLIST_ISROM}, - {"TOSHIBA","DVD-RAM SD-W1101","*", BLIST_GHOST}, - {"TOSHIBA","DVD-RAM SD-W1111","*", BLIST_GHOST}, {"MegaRAID", "LD", "*", BLIST_FORCELUN}, /* @@ -468,8 +461,6 @@ static int scan_scsis_single(int channel, int dev, int lun, int *max_dev_lun, Scsi_Device *SDtail, *SDpnt = *SDpnt2; Scsi_Request * SRpnt; int bflags, type = -1; - static int ghost_channel=-1, ghost_dev=-1; - int org_lun = lun; extern devfs_handle_t scsi_devfs_handle; SDpnt->host = shpnt; @@ -480,13 +471,6 @@ static int scan_scsis_single(int channel, int dev, int lun, int *max_dev_lun, scsi_build_commandblocks(SDpnt); - if ((channel == ghost_channel) && (dev == ghost_dev) && (lun == 1)) { - SDpnt->lun = 0; - } else { - ghost_channel = ghost_dev = -1; - } - - /* Some low level driver could use device->type (DB) */ SDpnt->type = -1; @@ -499,39 +483,14 @@ static int scan_scsis_single(int channel, int dev, int lun, int *max_dev_lun, SDpnt->expecting_cc_ua = 0; SDpnt->starved = 0; - scsi_cmd[0] = TEST_UNIT_READY; - scsi_cmd[1] = lun << 5; - scsi_cmd[2] = scsi_cmd[3] = scsi_cmd[4] = scsi_cmd[5] = 0; - SRpnt = scsi_allocate_request(SDpnt); - SRpnt->sr_data_direction = SCSI_DATA_NONE; - - scsi_wait_req (SRpnt, (void *) scsi_cmd, - (void *) NULL, - 0, SCSI_TIMEOUT + 4 * HZ, 5); - - SCSI_LOG_SCAN_BUS(3, printk("scsi: scan_scsis_single id %d lun %d. Return code 0x%08x\n", - dev, lun, SRpnt->sr_result)); - SCSI_LOG_SCAN_BUS(3, print_driverbyte(SRpnt->sr_result)); - SCSI_LOG_SCAN_BUS(3, print_hostbyte(SRpnt->sr_result)); - SCSI_LOG_SCAN_BUS(3, printk("\n")); + /* + * We used to do a TEST_UNIT_READY before the INQUIRY but that was + * not really necessary. Spec recommends using INQUIRY to scan for + * devices (and TEST_UNIT_READY to poll for media change). - Paul G. + */ - if (SRpnt->sr_result) { - if (((driver_byte(SRpnt->sr_result) & DRIVER_SENSE) || - (status_byte(SRpnt->sr_result) & CHECK_CONDITION)) && - ((SRpnt->sr_sense_buffer[0] & 0x70) >> 4) == 7) { - if (((SRpnt->sr_sense_buffer[2] & 0xf) != NOT_READY) && - ((SRpnt->sr_sense_buffer[2] & 0xf) != UNIT_ATTENTION) && - ((SRpnt->sr_sense_buffer[2] & 0xf) != ILLEGAL_REQUEST || lun > 0)) { - scsi_release_request(SRpnt); - return 1; - } - } else { - scsi_release_request(SRpnt); - return 0; - } - } SCSI_LOG_SCAN_BUS(3, printk("scsi: performing INQUIRY\n")); /* * Build an INQUIRY command block. @@ -547,7 +506,7 @@ static int scan_scsis_single(int channel, int dev, int lun, int *max_dev_lun, scsi_wait_req (SRpnt, (void *) scsi_cmd, (void *) scsi_result, - 256, SCSI_TIMEOUT, 3); + 256, SCSI_TIMEOUT+4*HZ, 3); SCSI_LOG_SCAN_BUS(3, printk("scsi: INQUIRY %s with code 0x%x\n", SRpnt->sr_result ? "failed" : "successful", SRpnt->sr_result)); @@ -588,18 +547,6 @@ static int scan_scsis_single(int channel, int dev, int lun, int *max_dev_lun, scsi_result[1] |= 0x80; /* removable */ } - if (bflags & BLIST_GHOST) { - if ((ghost_channel == channel) && (ghost_dev == dev) && (org_lun == 1)) { - lun=1; - } else { - ghost_channel = channel; - ghost_dev = dev; - scsi_result[0] = TYPE_MOD; - scsi_result[1] |= 0x80; /* removable */ - } - } - - memcpy(SDpnt->vendor, scsi_result + 8, 8); memcpy(SDpnt->model, scsi_result + 16, 16); memcpy(SDpnt->rev, scsi_result + 32, 4); @@ -808,19 +755,9 @@ static int scan_scsis_single(int channel, int dev, int lun, int *max_dev_lun, } /* - * If this device is Ghosted, scan upto two luns. (It physically only - * has one). -- REW - */ - if (bflags & BLIST_GHOST) { - *max_dev_lun = 2; - return 1; - } - - - /* - * We assume the device can't handle lun!=0 if: - it reports scsi-0 (ANSI - * SCSI Revision 0) (old drives like MAXTOR XT-3280) or - it reports scsi-1 - * (ANSI SCSI Revision 1) and Response Data Format 0 + * We assume the device can't handle lun!=0 if: - it reports scsi-0 + * (ANSI SCSI Revision 0) (old drives like MAXTOR XT-3280) or - it + * reports scsi-1 (ANSI SCSI Revision 1) and Response Data Format 0 */ if (((scsi_result[2] & 0x07) == 0) || diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 280cda345..bcdc4aab3 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -338,6 +338,15 @@ static int sd_init_command(Scsi_Cmnd * SCpnt) this_count = this_count >> 2; } } + if (dpnt->device->sector_size == 4096) { + if ((block & 7) || (SCpnt->request.nr_sectors & 7)) { + printk("sd.c:Bad block number requested"); + return 0; + } else { + block = block >> 3; + this_count = this_count >> 3; + } + } switch (SCpnt->request.cmd) { case WRITE: if (!dpnt->device->writeable) { @@ -588,6 +597,11 @@ static void rw_intr(Scsi_Cmnd * SCpnt) if (block_sectors < 4) block_sectors = 4; break; + case 4096: + error_sector <<=3; + if (block_sectors < 8) + block_sectors = 8; + break; case 256: error_sector >>= 1; break; @@ -889,7 +903,7 @@ static int sd_init_onedisk(int i) */ rscsi_disks[i].capacity = 0; } - if (sector_size == 2048) { + if (sector_size > 1024) { int m; /* @@ -899,7 +913,7 @@ static int sd_init_onedisk(int i) * of partial sectors. */ for (m = i << 4; m < ((i + 1) << 4); m++) { - sd_blocksizes[m] = 2048; + sd_blocksizes[m] = sector_size; } } { /* diff --git a/drivers/scsi/seagate.c b/drivers/scsi/seagate.c index c8c5dd54d..ff68dca96 100644 --- a/drivers/scsi/seagate.c +++ b/drivers/scsi/seagate.c @@ -311,6 +311,8 @@ static const Signature __initdata signatures[] = {"FUTURE DOMAIN CORP. (C) 1992 V8.00.004/02/92", 5, 44, FD}, {"IBM F1 BIOS V1.1004/30/92", 5, 25, FD}, {"FUTURE DOMAIN TMC-950", 5, 21, FD}, + /* Added for 2.2.16 by Matthias_Heidbrink@b.maus.de */ + {"IBM F1 V1.2009/22/93", 5, 25, FD}, }; #define NUM_SIGNATURES (sizeof(signatures) / sizeof(Signature)) diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index 4fca4d14d..71b93e379 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c @@ -17,8 +17,8 @@ * any later version. * */ - static char * sg_version_str = "Version: 3.1.13 (20000323)"; - static int sg_version_num = 30113; /* 2 digits for each component */ + static char * sg_version_str = "Version: 3.1.15 (20000528)"; + static int sg_version_num = 30115; /* 2 digits for each component */ /* * D. P. Gilbert (dgilbert@interlog.com, dougg@triode.net.au), notes: * - scsi logging is available via SCSI_LOG_TIMEOUT macros. First @@ -113,7 +113,8 @@ static void sg_detach(Scsi_Device *); static Scsi_Cmnd * dummy_cmdp = 0; /* only used for sizeof */ -static rwlock_t sg_dev_arr_lock = RW_LOCK_UNLOCKED; +static rwlock_t sg_dev_arr_lock = RW_LOCK_UNLOCKED; /* Also used to lock + file descriptor list for device */ struct Scsi_Device_Template sg_template = { @@ -155,7 +156,7 @@ typedef struct sg_request /* SG_MAX_QUEUE requests outstanding per file */ char res_used; /* 1 -> using reserve buffer, 0 -> not ... */ char orphan; /* 1 -> drop on sight, 0 -> normal */ char sg_io_owned; /* 1 -> packet belongs to SG_IO */ - char done; /* 1 -> bh handler done, 0 -> prior to bh */ + char done; /* 0->before bh, 1->before read, 2->read */ } Sg_request; /* 168 bytes long on i386 */ typedef struct sg_fd /* holds the state of a file descriptor */ @@ -163,6 +164,7 @@ typedef struct sg_fd /* holds the state of a file descriptor */ struct sg_fd * nextfp; /* NULL when last opened fd on this device */ struct sg_device * parentdp; /* owning device */ wait_queue_head_t read_wait; /* queue read until command done */ + rwlock_t rq_list_lock; /* protect access to list in req_arr */ int timeout; /* defaults to SG_DEFAULT_TIMEOUT */ Sg_scatter_hold reserve; /* buffer held for this file descriptor */ unsigned save_scat_len; /* original length of trunc. scat. element */ @@ -176,7 +178,7 @@ typedef struct sg_fd /* holds the state of a file descriptor */ char cmd_q; /* 1 -> allow command queuing, 0 -> don't */ char next_cmd_len; /* 0 -> automatic (def), >0 -> use on next write() */ char keep_orphan; /* 0 -> drop orphan (def), 1 -> keep for read() */ -} Sg_fd; /* 2760 bytes long on i386 */ +} Sg_fd; /* 2768 bytes long on i386 */ typedef struct sg_device /* holds the state of each scsi generic device */ { @@ -189,7 +191,7 @@ typedef struct sg_device /* holds the state of each scsi generic device */ char exclude; /* opened for exclusive access */ char sgdebug; /* 0->off, 1->sense, 9->dump dev, 10-> all devs */ char detached; /* 0->attached, 1->detached pending removal */ -} Sg_device; /* 40 bytes long on i386 */ +} Sg_device; /* 44 bytes long on i386 */ static int sg_fasync(int fd, struct file * filp, int mode); @@ -222,11 +224,11 @@ static char * sg_low_malloc(int rqSz, int lowDma, int mem_src, static void sg_low_free(char * buff, int size, int mem_src); static Sg_fd * sg_add_sfp(Sg_device * sdp, int dev); static int sg_remove_sfp(Sg_device * sdp, Sg_fd * sfp); -static Sg_request * sg_get_request(const Sg_fd * sfp, int pack_id); +static Sg_request * sg_get_rq_mark(Sg_fd * sfp, int pack_id); static Sg_request * sg_add_request(Sg_fd * sfp); static int sg_remove_request(Sg_fd * sfp, Sg_request * srp); -static int sg_res_in_use(const Sg_fd * sfp); -static int sg_dio_in_use(const Sg_fd * sfp); +static int sg_res_in_use(Sg_fd * sfp); +static int sg_dio_in_use(Sg_fd * sfp); static void sg_clr_scpnt(Scsi_Cmnd * SCpnt); static void sg_shorten_timeout(Scsi_Cmnd * scpnt); static int sg_ms_to_jif(unsigned int msecs); @@ -364,7 +366,7 @@ static ssize_t sg_read(struct file * filp, char * buf, else req_pack_id = old_hdr.pack_id; } - srp = sg_get_request(sfp, req_pack_id); + srp = sg_get_rq_mark(sfp, req_pack_id); if (! srp) { /* now wait on packet to arrive */ if (filp->f_flags & O_NONBLOCK) return -EAGAIN; @@ -372,7 +374,7 @@ static ssize_t sg_read(struct file * filp, char * buf, int dio = sg_dio_in_use(sfp); res = 0; /* following is a macro that beats race condition */ __wait_event_interruptible(sfp->read_wait, - (srp = sg_get_request(sfp, req_pack_id)), + (srp = sg_get_rq_mark(sfp, req_pack_id)), res); if (0 == res) break; @@ -550,7 +552,7 @@ static ssize_t sg_write(struct file * filp, const char * buf, hp->cmd_len = (unsigned char)cmd_size; hp->iovec_count = 0; hp->mx_sb_len = 0; -#if 1 +#if 0 hp->dxfer_direction = SG_DXFER_UNKNOWN; #else if (input_size > 0) @@ -686,7 +688,7 @@ static int sg_common_write(Sg_fd * sfp, Sg_request * srp, srp->data.sglist_len = 0; srp->data.bufflen = 0; srp->data.buffer = NULL; - hp->duration = jiffies; + hp->duration = jiffies; /* unit jiffies now, millisecs after done */ /* Now send everything of to mid-level. The next time we hear about this packet is when sg_cmd_done_bh() is called (i.e. a callback). */ scsi_do_cmd(SCpnt, (void *)cmnd, @@ -703,6 +705,7 @@ static int sg_ioctl(struct inode * inode, struct file * filp, Sg_device * sdp; Sg_fd * sfp; Sg_request * srp; + unsigned long iflags; if ((! (sfp = (Sg_fd *)filp->private_data)) || (! (sdp = sfp->parentdp))) return -ENXIO; @@ -740,6 +743,7 @@ static int sg_ioctl(struct inode * inode, struct file * filp, return result; /* -ERESTARTSYS because signal hit process */ } } + srp->done = 2; result = sg_new_read(sfp, (char *)arg, size_sg_io_hdr, srp); return (result < 0) ? result : 0; } @@ -794,24 +798,24 @@ static int sg_ioctl(struct inode * inode, struct file * filp, case SG_GET_PACK_ID: result = verify_area(VERIFY_WRITE, (void *) arg, sizeof(int)); if (result) return result; - srp = sfp->headrp; - while (srp) { - if (srp->done && (! srp->sg_io_owned)) { + read_lock_irqsave(&sfp->rq_list_lock, iflags); + for (srp = sfp->headrp; srp; srp = srp->nextrp) { + if ((1 == srp->done) && (! srp->sg_io_owned)) { + read_unlock_irqrestore(&sfp->rq_list_lock, iflags); __put_user(srp->header.pack_id, (int *)arg); return 0; } - srp = srp->nextrp; } + read_unlock_irqrestore(&sfp->rq_list_lock, iflags); __put_user(-1, (int *)arg); return 0; case SG_GET_NUM_WAITING: - srp = sfp->headrp; - val = 0; - while (srp) { - if (srp->done && (! srp->sg_io_owned)) + read_lock_irqsave(&sfp->rq_list_lock, iflags); + for (val = 0, srp = sfp->headrp; srp; srp = srp->nextrp) { + if ((1 == srp->done) && (! srp->sg_io_owned)) ++val; - srp = srp->nextrp; } + read_unlock_irqrestore(&sfp->rq_list_lock, iflags); return put_user(val, (int *)arg); case SG_GET_SG_TABLESIZE: return put_user(sdp->sg_tablesize, (int *)arg); @@ -855,16 +859,17 @@ static int sg_ioctl(struct inode * inode, struct file * filp, if (result) return result; else { sg_req_info_t rinfo[SG_MAX_QUEUE]; - Sg_request * srp = sfp->headrp; - for (val = 0; val < SG_MAX_QUEUE; + Sg_request * srp; + read_lock_irqsave(&sfp->rq_list_lock, iflags); + for (srp = sfp->headrp, val = 0; val < SG_MAX_QUEUE; ++val, srp = srp ? srp->nextrp : srp) { memset(&rinfo[val], 0, size_sg_req_info); if (srp) { - rinfo[val].req_state = srp->done ? 2 : 1; + rinfo[val].req_state = srp->done + 1; rinfo[val].problem = srp->header.masked_status & srp->header.host_status & srp->header.driver_status; rinfo[val].duration = srp->done ? - sg_jif_to_ms(srp->header.duration) : + srp->header.duration : sg_jif_to_ms(jiffies - srp->header.duration); rinfo[val].orphan = srp->orphan; rinfo[val].sg_io_owned = srp->sg_io_owned; @@ -872,6 +877,7 @@ static int sg_ioctl(struct inode * inode, struct file * filp, rinfo[val].usr_ptr = srp->header.usr_ptr; } } + read_unlock_irqrestore(&sfp->rq_list_lock, iflags); __copy_to_user((void *)arg, rinfo, size_sg_req_info * SG_MAX_QUEUE); return 0; } @@ -882,8 +888,29 @@ static int sg_ioctl(struct inode * inode, struct file * filp, return -EBUSY; result = get_user(val, (int *)arg); if (result) return result; - /* Don't do anything till scsi mid level visibility */ - return 0; + if (SG_SCSI_RESET_NOTHING == val) + return 0; +#ifdef SCSI_TRY_RESET_DEVICE + switch (val) + { + case SG_SCSI_RESET_DEVICE: + val = SCSI_TRY_RESET_DEVICE; + break; + case SG_SCSI_RESET_BUS: + val = SCSI_TRY_RESET_BUS; + break; + case SG_SCSI_RESET_HOST: + val = SCSI_TRY_RESET_HOST; + break; + default: + return -EINVAL; + } + if(! capable(CAP_SYS_ADMIN)) return -EACCES; + return (scsi_reset_provider(sdp->device, val) == SUCCESS) ? 0 : -EIO; +#else + SCSI_LOG_TIMEOUT(1, printk("sg_ioctl: SG_RESET_SCSI not supported\n")); + result = -EINVAL; +#endif case SCSI_IOCTL_SEND_COMMAND: if (read_only) { unsigned char opcode = WRITE_6; @@ -918,17 +945,19 @@ static unsigned int sg_poll(struct file * filp, poll_table * wait) Sg_fd * sfp; Sg_request * srp; int count = 0; + unsigned long iflags; if ((! (sfp = (Sg_fd *)filp->private_data)) || (! (sdp = sfp->parentdp))) return POLLERR; poll_wait(filp, &sfp->read_wait, wait); - srp = sfp->headrp; - while (srp) { /* if any read waiting, flag it */ - if ((0 == res) && srp->done && (! srp->sg_io_owned)) + read_lock_irqsave(&sfp->rq_list_lock, iflags); + for (srp = sfp->headrp; srp; srp = srp->nextrp) { + /* if any read waiting, flag it */ + if ((0 == res) && (1 == srp->done) && (! srp->sg_io_owned)) res = POLLIN | POLLRDNORM; ++count; - srp = srp->nextrp; } + read_unlock_irqrestore(&sfp->rq_list_lock, iflags); if (! sfp->cmd_q) { if (0 == count) res |= POLLOUT | POLLWRNORM; @@ -960,11 +989,17 @@ static int sg_fasync(int fd, struct file * filp, int mode) static void sg_cmd_done_bh(Scsi_Cmnd * SCpnt) { int dev = MINOR(SCpnt->request.rq_dev); - Sg_device * sdp; + Sg_device * sdp = NULL; Sg_fd * sfp; Sg_request * srp = NULL; - if (NULL == (sdp = sg_get_dev(dev))) { + read_lock(&sg_dev_arr_lock); + if (sg_dev_arr && (dev >= 0)) { + if (dev < sg_template.dev_max) + sdp = sg_dev_arr[dev]; + } + if (NULL == sdp) { + read_unlock(&sg_dev_arr_lock); SCSI_LOG_TIMEOUT(1, printk("sg...bh: bad args dev=%d\n", dev)); scsi_release_command(SCpnt); SCpnt = NULL; @@ -972,16 +1007,17 @@ static void sg_cmd_done_bh(Scsi_Cmnd * SCpnt) } sfp = sdp->headfp; while (sfp) { - srp = sfp->headrp; - while (srp) { + read_lock(&sfp->rq_list_lock); + for (srp = sfp->headrp; srp; srp = srp->nextrp) { if (SCpnt == srp->my_cmdp) break; - srp = srp->nextrp; } + read_unlock(&sfp->rq_list_lock); if (srp) break; sfp = sfp->nextfp; } + read_unlock(&sg_dev_arr_lock); if (! srp) { SCSI_LOG_TIMEOUT(1, printk("sg...bh: req missing, dev=%d\n", dev)); scsi_release_command(SCpnt); @@ -1001,6 +1037,7 @@ static void sg_cmd_done_bh(Scsi_Cmnd * SCpnt) dev, srp->header.pack_id, (int)SCpnt->result)); srp->header.resid = SCpnt->resid; /* sg_unmap_and(&srp->data, 0); */ /* unmap locked pages a.s.a.p. */ + /* N.B. unit of duration changes here from jiffies to millisecs */ srp->header.duration = sg_jif_to_ms(jiffies - (int)srp->header.duration); if (0 != SCpnt->result) { memcpy(srp->sense_b, SCpnt->sense_buffer, sizeof(srp->sense_b)); @@ -1052,8 +1089,7 @@ static void sg_cmd_done_bh(Scsi_Cmnd * SCpnt) if (sfp && srp) { /* Now wake up any sg_read() that is waiting for this packet. */ wake_up_interruptible(&sfp->read_wait); - if (sfp->async_qp) - kill_fasync(sfp->async_qp, SIGPOLL, POLL_IN); + kill_fasync(&sfp->async_qp, SIGPOLL, POLL_IN); } } @@ -1091,18 +1127,18 @@ static int sg_detect(Scsi_Device * scsidp) static int sg_init() { static int sg_registered = 0; - unsigned long flags = 0; + unsigned long iflags; if ((sg_template.dev_noticed == 0) || sg_dev_arr) return 0; - write_lock_irqsave(&sg_dev_arr_lock, flags); + write_lock_irqsave(&sg_dev_arr_lock, iflags); if(!sg_registered) { if (devfs_register_chrdev(SCSI_GENERIC_MAJOR,"sg",&sg_fops)) { printk("Unable to get major %d for generic SCSI device\n", SCSI_GENERIC_MAJOR); - write_unlock_irqrestore(&sg_dev_arr_lock, flags); + write_unlock_irqrestore(&sg_dev_arr_lock, iflags); return 1; } sg_registered++; @@ -1114,11 +1150,11 @@ static int sg_init() sizeof(Sg_device *), GFP_ATOMIC); if (NULL == sg_dev_arr) { printk("sg_init: no space for sg_dev_arr\n"); - write_unlock_irqrestore(&sg_dev_arr_lock, flags); + write_unlock_irqrestore(&sg_dev_arr_lock, iflags); return 1; } memset(sg_dev_arr, 0, sg_template.dev_max * sizeof(Sg_device *)); - write_unlock_irqrestore(&sg_dev_arr_lock, flags); + write_unlock_irqrestore(&sg_dev_arr_lock, iflags); #ifdef CONFIG_PROC_FS sg_proc_init(); #endif /* CONFIG_PROC_FS */ @@ -1149,10 +1185,10 @@ __setup("sg_def_reserved_size=", sg_def_reserved_size_setup); static int sg_attach(Scsi_Device * scsidp) { Sg_device * sdp; - unsigned long flags = 0; + unsigned long iflags; int k; - write_lock_irqsave(&sg_dev_arr_lock, flags); + write_lock_irqsave(&sg_dev_arr_lock, iflags); if (sg_template.nr_dev >= sg_template.dev_max) { /* try to resize */ Sg_device ** tmp_da; int tmp_dev_max = sg_template.nr_dev + SG_DEV_ARR_LUMP; @@ -1161,7 +1197,7 @@ static int sg_attach(Scsi_Device * scsidp) sizeof(Sg_device *), GFP_ATOMIC); if (NULL == tmp_da) { scsidp->attached--; - write_unlock_irqrestore(&sg_dev_arr_lock, flags); + write_unlock_irqrestore(&sg_dev_arr_lock, iflags); printk("sg_attach: device array cannot be resized\n"); return 1; } @@ -1180,7 +1216,7 @@ static int sg_attach(Scsi_Device * scsidp) sdp = NULL; if (NULL == sdp) { scsidp->attached--; - write_unlock_irqrestore(&sg_dev_arr_lock, flags); + write_unlock_irqrestore(&sg_dev_arr_lock, iflags); printk("sg_attach: Sg_device cannot be allocated\n"); return 1; } @@ -1200,7 +1236,7 @@ static int sg_attach(Scsi_Device * scsidp) &sg_fops, NULL); sg_template.nr_dev++; sg_dev_arr[k] = sdp; - write_unlock_irqrestore(&sg_dev_arr_lock, flags); + write_unlock_irqrestore(&sg_dev_arr_lock, iflags); return 0; } @@ -1214,37 +1250,36 @@ static void sg_finish(void) static void sg_detach(Scsi_Device * scsidp) { Sg_device * sdp; - unsigned long flags = 0; + unsigned long iflags; Sg_fd * sfp; Sg_request * srp; int k; if (NULL == sg_dev_arr) return; - write_lock_irqsave(&sg_dev_arr_lock, flags); -/* Need to stop sg_cmd_done_bh() playing with this list during this loop */ + write_lock_irqsave(&sg_dev_arr_lock, iflags); for (k = 0; k < sg_template.dev_max; k++) { sdp = sg_dev_arr[k]; if ((NULL == sdp) || (sdp->device != scsidp)) continue; /* dirty but lowers nesting */ if (sdp->headfp) { - sfp = sdp->headfp; - while (sfp) { - srp = sfp->headrp; - while (srp) { - if (! srp->done) + for (sfp = sdp->headfp; sfp; sfp = sfp->nextfp) { + /* no lock on request list here */ + for (srp = sfp->headrp; srp; srp = srp->nextrp) { + if (! srp->done) { + write_unlock_irqrestore(&sg_dev_arr_lock, iflags); sg_shorten_timeout(srp->my_cmdp); - srp = srp->nextrp; + write_lock_irqsave(&sg_dev_arr_lock, iflags); } - sfp = sfp->nextfp; } - write_unlock_irqrestore(&sg_dev_arr_lock, flags); + } + write_unlock_irqrestore(&sg_dev_arr_lock, iflags); SCSI_LOG_TIMEOUT(3, printk("sg_detach: dev=%d, dirty, sleep(3)\n", k)); scsi_sleep(3); /* sleep 3 jiffies, hoping for timeout to go off */ devfs_unregister (sdp->de); sdp->de = NULL; sdp->detached = 1; - write_lock_irqsave(&sg_dev_arr_lock, flags); + write_lock_irqsave(&sg_dev_arr_lock, iflags); } else { SCSI_LOG_TIMEOUT(3, printk("sg_detach: dev=%d\n", k)); @@ -1259,7 +1294,7 @@ static void sg_detach(Scsi_Device * scsidp) sg_template.dev_noticed--; break; } - write_unlock_irqrestore(&sg_dev_arr_lock, flags); + write_unlock_irqrestore(&sg_dev_arr_lock, iflags); return; } @@ -1277,12 +1312,11 @@ int init_module(void) { void cleanup_module( void) { - scsi_unregister_module(MODULE_SCSI_DEV, &sg_template); - devfs_unregister_chrdev(SCSI_GENERIC_MAJOR, "sg"); - #ifdef CONFIG_PROC_FS sg_proc_cleanup(); #endif /* CONFIG_PROC_FS */ + scsi_unregister_module(MODULE_SCSI_DEV, &sg_template); + devfs_unregister_chrdev(SCSI_GENERIC_MAJOR, "sg"); if(sg_dev_arr != NULL) { /* Really worrying situation of writes still pending and get here */ /* Strategy: shorten timeout on release + wait on detach ... */ @@ -1301,7 +1335,7 @@ extern void scsi_old_times_out (Scsi_Cmnd * SCpnt); /* Can't see clean way to abort a command so shorten timeout to 1 jiffy */ static void sg_shorten_timeout(Scsi_Cmnd * scpnt) -{ /* assumed to be called with sg_dev_arr_lock held */ +{ #if 0 /* scsi_syms.c is very miserly about exported functions */ scsi_delete_timer(scpnt); if (! scpnt) @@ -1313,11 +1347,7 @@ static void sg_shorten_timeout(Scsi_Cmnd * scpnt) scsi_add_timer(scpnt, scpnt->timeout_per_command, scsi_old_times_out); #else - unsigned long flags = 0; - - write_unlock_irqrestore(&sg_dev_arr_lock, flags); scsi_sleep(HZ); /* just sleep 1 second and hope ... */ - write_lock_irqsave(&sg_dev_arr_lock, flags); #endif } @@ -1859,6 +1889,8 @@ static void sg_link_reserve(Sg_fd * sfp, Sg_request * srp, int size) Sg_scatter_hold * rsv_schp = &sfp->reserve; SCSI_LOG_TIMEOUT(4, printk("sg_link_reserve: size=%d\n", size)); + /* round request up to next highest SG_SECTOR_SZ byte boundary */ + size = (size + SG_SECTOR_MSK) & (~SG_SECTOR_MSK); if (rsv_schp->k_use_sg > 0) { int k, num; int rem = size; @@ -1921,17 +1953,35 @@ static void sg_unlink_reserve(Sg_fd * sfp, Sg_request * srp) srp->res_used = 0; } -static Sg_request * sg_get_request(const Sg_fd * sfp, int pack_id) +static Sg_request * sg_get_rq_mark(Sg_fd * sfp, int pack_id) { - Sg_request * resp = NULL; + Sg_request * resp; + unsigned long iflags; - resp = sfp->headrp; - while (resp) { /* look for requests that are ready + not SG_IO owned */ - if (resp->done && (! resp->sg_io_owned) && - ((-1 == pack_id) || (resp->header.pack_id == pack_id))) - return resp; - resp = resp->nextrp; + write_lock_irqsave(&sfp->rq_list_lock, iflags); + for (resp = sfp->headrp; resp; resp = resp->nextrp) { + /* look for requests that are ready + not SG_IO owned */ + if ((1 == resp->done) && (! resp->sg_io_owned) && + ((-1 == pack_id) || (resp->header.pack_id == pack_id))) { + resp->done = 2; /* guard against other readers */ + break; + } } + write_unlock_irqrestore(&sfp->rq_list_lock, iflags); + return resp; +} + +static Sg_request * sg_get_nth_request(Sg_fd * sfp, int nth) +{ + Sg_request * resp; + unsigned long iflags; + int k; + + read_lock_irqsave(&sfp->rq_list_lock, iflags); + for (k = 0, resp = sfp->headrp; resp && (k < nth); + ++k, resp = resp->nextrp) + ; + read_unlock_irqrestore(&sfp->rq_list_lock, iflags); return resp; } @@ -1939,46 +1989,45 @@ static Sg_request * sg_get_request(const Sg_fd * sfp, int pack_id) static Sg_request * sg_add_request(Sg_fd * sfp) { int k; - Sg_request * resp = NULL; - Sg_request * rp; + unsigned long iflags; + Sg_request * resp; + Sg_request * rp = sfp->req_arr; + write_lock_irqsave(&sfp->rq_list_lock, iflags); resp = sfp->headrp; - rp = sfp->req_arr; if (! resp) { - resp = rp; - sfp->headrp = resp; + memset(rp, 0, sizeof(Sg_request)); + rp->parentfp = sfp; + resp = rp; + sfp->headrp = resp; } else { if (0 == sfp->cmd_q) resp = NULL; /* command queuing disallowed */ else { - for (k = 0, rp; k < SG_MAX_QUEUE; ++k, ++rp) { + for (k = 0; k < SG_MAX_QUEUE; ++k, ++rp) { if (! rp->parentfp) break; } if (k < SG_MAX_QUEUE) { - while (resp->nextrp) resp = resp->nextrp; - resp->nextrp = rp; - resp = rp; + memset(rp, 0, sizeof(Sg_request)); + rp->parentfp = sfp; + while (resp->nextrp) + resp = resp->nextrp; + resp->nextrp = rp; + resp = rp; } else resp = NULL; } } if (resp) { - resp->parentfp = sfp; resp->nextrp = NULL; - resp->res_used = 0; - resp->orphan = 0; - resp->sg_io_owned = 0; - resp->done = 0; - memset(&resp->data, 0, sizeof(Sg_scatter_hold)); - memset(&resp->header, 0, size_sg_io_hdr); resp->header.duration = jiffies; resp->my_cmdp = NULL; resp->data.kiobp = NULL; - resp->data.mapped = 0; } + write_unlock_irqrestore(&sfp->rq_list_lock, iflags); return resp; } @@ -1987,29 +2036,51 @@ static int sg_remove_request(Sg_fd * sfp, Sg_request * srp) { Sg_request * prev_rp; Sg_request * rp; + unsigned long iflags; + int res = 0; if ((! sfp) || (! srp) || (! sfp->headrp)) - return 0; + return res; + write_lock_irqsave(&sfp->rq_list_lock, iflags); prev_rp = sfp->headrp; if (srp == prev_rp) { - prev_rp->parentfp = NULL; sfp->headrp = prev_rp->nextrp; - return 1; + prev_rp->parentfp = NULL; + res = 1; } - while ((rp = prev_rp->nextrp)) { - if (srp == rp) { - rp->parentfp = NULL; - prev_rp->nextrp = rp->nextrp; - return 1; - } - prev_rp = rp; + else { + while ((rp = prev_rp->nextrp)) { + if (srp == rp) { + prev_rp->nextrp = rp->nextrp; + rp->parentfp = NULL; + res = 1; + break; + } + prev_rp = rp; + } } - return 0; + write_unlock_irqrestore(&sfp->rq_list_lock, iflags); + return res; +} + +static Sg_fd * sg_get_nth_sfp(Sg_device * sdp, int nth) +{ + Sg_fd * resp; + unsigned long iflags; + int k; + + read_lock_irqsave(&sg_dev_arr_lock, iflags); + for (k = 0, resp = sdp->headfp; resp && (k < nth); + ++k, resp = resp->nextfp) + ; + read_unlock_irqrestore(&sg_dev_arr_lock, iflags); + return resp; } static Sg_fd * sg_add_sfp(Sg_device * sdp, int dev) { Sg_fd * sfp; + unsigned long iflags; sfp = (Sg_fd *)sg_low_malloc(sizeof(Sg_fd), 0, SG_HEAP_KMAL, 0); if (! sfp) @@ -2017,6 +2088,7 @@ static Sg_fd * sg_add_sfp(Sg_device * sdp, int dev) memset(sfp, 0, sizeof(Sg_fd)); sfp->fd_mem_src = SG_HEAP_KMAL; init_waitqueue_head(&sfp->read_wait); + sfp->rq_list_lock = RW_LOCK_UNLOCKED; sfp->timeout = SG_DEFAULT_TIMEOUT; sfp->force_packid = SG_DEF_FORCE_PACK_ID; @@ -2025,14 +2097,16 @@ static Sg_fd * sg_add_sfp(Sg_device * sdp, int dev) sfp->cmd_q = SG_DEF_COMMAND_Q; sfp->keep_orphan = SG_DEF_KEEP_ORPHAN; sfp->parentdp = sdp; + write_lock_irqsave(&sg_dev_arr_lock, iflags); if (! sdp->headfp) sdp->headfp = sfp; else { /* add to tail of existing list */ - Sg_fd * pfp = sdp->headfp; - while (pfp->nextfp) - pfp = pfp->nextfp; - pfp->nextfp = sfp; + Sg_fd * pfp = sdp->headfp; + while (pfp->nextfp) + pfp = pfp->nextfp; + pfp->nextfp = sfp; } + write_unlock_irqrestore(&sg_dev_arr_lock, iflags); SCSI_LOG_TIMEOUT(3, printk("sg_add_sfp: sfp=0x%p, m_s=%d\n", sfp, (int)sfp->fd_mem_src)); sg_build_reserve(sfp, sg_big_buff); @@ -2048,36 +2122,41 @@ static int sg_remove_sfp(Sg_device * sdp, Sg_fd * sfp) int dirty = 0; int res = 0; + /* no lock since not expecting any parallel action on this fd */ srp = sfp->headrp; if (srp) { - while (srp) { - tsrp = srp->nextrp; + while (srp) { + tsrp = srp->nextrp; if (srp->done) sg_finish_rem_req(srp); - else - ++dirty; - srp = tsrp; - } + else + ++dirty; + srp = tsrp; + } } if (0 == dirty) { - Sg_fd * fp; - Sg_fd * prev_fp = sdp->headfp; - - if (sfp == prev_fp) - sdp->headfp = prev_fp->nextfp; - else { - while ((fp = prev_fp->nextfp)) { - if (sfp == fp) { - prev_fp->nextfp = fp->nextfp; - break; - } - prev_fp = fp; - } - } - if (sfp->reserve.bufflen > 0) { + Sg_fd * fp; + Sg_fd * prev_fp; + unsigned long iflags; + + write_lock_irqsave(&sg_dev_arr_lock, iflags); + prev_fp = sdp->headfp; + if (sfp == prev_fp) + sdp->headfp = prev_fp->nextfp; + else { + while ((fp = prev_fp->nextfp)) { + if (sfp == fp) { + prev_fp->nextfp = fp->nextfp; + break; + } + prev_fp = fp; + } + } + write_unlock_irqrestore(&sg_dev_arr_lock, iflags); + if (sfp->reserve.bufflen > 0) { SCSI_LOG_TIMEOUT(6, printk("sg_remove_sfp: bufflen=%d, k_use_sg=%d\n", (int)sfp->reserve.bufflen, (int)sfp->reserve.k_use_sg)); - sg_remove_scat(&sfp->reserve); + sg_remove_scat(&sfp->reserve); } sfp->parentdp = NULL; SCSI_LOG_TIMEOUT(6, printk("sg_remove_sfp: sfp=0x%p\n", sfp)); @@ -2104,28 +2183,28 @@ SCSI_LOG_TIMEOUT(6, printk("sg_remove_sfp: bufflen=%d, k_use_sg=%d\n", return res; } -static int sg_res_in_use(const Sg_fd * sfp) +static int sg_res_in_use(Sg_fd * sfp) { - const Sg_request * srp = sfp->headrp; + const Sg_request * srp; + unsigned long iflags; - while (srp) { - if (srp->res_used) - return 1; - srp = srp->nextrp; - } - return 0; + read_lock_irqsave(&sfp->rq_list_lock, iflags); + for (srp = sfp->headrp; srp; srp = srp->nextrp) + if (srp->res_used) break; + read_unlock_irqrestore(&sfp->rq_list_lock, iflags); + return srp ? 1 : 0; } -static int sg_dio_in_use(const Sg_fd * sfp) +static int sg_dio_in_use(Sg_fd * sfp) { - const Sg_request * srp = sfp->headrp; + const Sg_request * srp; + unsigned long iflags; - while (srp) { - if ((! srp->done) && srp->data.kiobp) - return 1; - srp = srp->nextrp; - } - return 0; + read_lock_irqsave(&sfp->rq_list_lock, iflags); + for (srp = sfp->headrp; srp; srp = srp->nextrp) + if ((! srp->done) && srp->data.kiobp) break; + read_unlock_irqrestore(&sfp->rq_list_lock, iflags); + return srp ? 1 : 0; } /* If retSzp==NULL want exact size or fail */ @@ -2314,7 +2393,8 @@ static unsigned sg_jif_to_ms(int jifs) } static unsigned char allow_ops[] = {TEST_UNIT_READY, INQUIRY, -READ_CAPACITY, READ_BUFFER, READ_6, READ_10, READ_12}; +READ_CAPACITY, READ_BUFFER, READ_6, READ_10, READ_12, +MODE_SENSE, MODE_SENSE_10}; static int sg_allow_access(unsigned char opcode, char dev_type) { @@ -2331,28 +2411,29 @@ static int sg_allow_access(unsigned char opcode, char dev_type) static int sg_last_dev() -{ /* assumed to be called with sg_dev_arr_lock held */ +{ int k; + unsigned long iflags; - for (k = sg_template.dev_max - 1; k >= 0; --k) { - if (sg_dev_arr[k] && sg_dev_arr[k]->device) - return k + 1; - } - return 0; /* origin 1 */ + read_lock_irqsave(&sg_dev_arr_lock, iflags); + for (k = sg_template.dev_max - 1; k >= 0; --k) + if (sg_dev_arr[k] && sg_dev_arr[k]->device) break; + read_unlock_irqrestore(&sg_dev_arr_lock, iflags); + return k + 1; /* origin 1 */ } static Sg_device * sg_get_dev(int dev) { - Sg_device * sdp; + Sg_device * sdp = NULL; + unsigned long iflags; - if ((NULL == sg_dev_arr) || (dev < 0)) - return NULL; - read_lock(&sg_dev_arr_lock); + if (sg_dev_arr && (dev >= 0)) + { + read_lock_irqsave(&sg_dev_arr_lock, iflags); if (dev < sg_template.dev_max) sdp = sg_dev_arr[dev]; - else - sdp = NULL; - read_unlock(&sg_dev_arr_lock); + read_unlock_irqrestore(&sg_dev_arr_lock, iflags); + } return sdp; } @@ -2429,8 +2510,7 @@ static write_proc_t * sg_proc_leaf_writes[] = { *eof = infofp(buffer, &len, &begin, offset, size); \ if (offset >= (begin + len)) \ return 0; \ - *start = buffer + ((begin > offset) ? \ - (begin - offset) : (offset - begin)); \ + *start = buffer + offset - begin; \ return (size < (begin + len - offset)) ? \ size : begin + len - offset; \ } while(0) @@ -2520,7 +2600,6 @@ static int sg_proc_debug_info(char * buffer, int * len, off_t * begin, PRINT_PROC("sg_dev_arr NULL, driver not initialized\n"); return 1; } - read_lock(&sg_dev_arr_lock); max_dev = sg_last_dev(); PRINT_PROC("dev_max(currently)=%d max_active_device=%d (origin 1)\n", sg_template.dev_max, max_dev); @@ -2528,11 +2607,11 @@ static int sg_proc_debug_info(char * buffer, int * len, off_t * begin, "def_reserved_size=%d\n", scsi_dma_free_sectors, sg_pool_secs_avail, sg_big_buff); for (j = 0; j < max_dev; ++j) { - if ((sdp = sg_dev_arr[j])) { + if ((sdp = sg_get_dev(j))) { Sg_fd * fp; Sg_request * srp; struct scsi_device * scsidp; - int dev, k, blen, usg; + int dev, k, m, blen, usg; if (! (scsidp = sdp->device)) { PRINT_PROC("device %d detached ??\n", j); @@ -2540,48 +2619,45 @@ static int sg_proc_debug_info(char * buffer, int * len, off_t * begin, } dev = MINOR(sdp->i_rdev); - if ((fp = sdp->headfp)) { - PRINT_PROC(" >>> device=%d(sg%d) ", dev, dev); + if (sg_get_nth_sfp(sdp, 0)) { + PRINT_PROC(" >>> device=sg%d ", dev); PRINT_PROC("scsi%d chan=%d id=%d lun=%d em=%d sg_tablesize=%d" " excl=%d\n", scsidp->host->host_no, scsidp->channel, scsidp->id, scsidp->lun, scsidp->host->hostt->emulated, sdp->sg_tablesize, sdp->exclude); } - for (k = 1; fp; fp = fp->nextfp, ++k) { - PRINT_PROC(" FD(%d): timeout=%d bufflen=%d " - "(res)sgat=%d low_dma=%d\n", - k, fp->timeout, fp->reserve.bufflen, + for (k = 0; (fp = sg_get_nth_sfp(sdp, k)); ++k) { + PRINT_PROC(" FD(%d): timeout=%dms bufflen=%d " + "(res)sgat=%d low_dma=%d\n", k + 1, + sg_jif_to_ms(fp->timeout), fp->reserve.bufflen, (int)fp->reserve.k_use_sg, (int)fp->low_dma); PRINT_PROC(" cmd_q=%d f_packid=%d k_orphan=%d closed=%d\n", (int)fp->cmd_q, (int)fp->force_packid, (int)fp->keep_orphan, (int)fp->closed); - srp = fp->headrp; - if (NULL == srp) - PRINT_PROC(" No requests active\n"); - while (srp) { + for (m = 0; (srp = sg_get_nth_request(fp, m)); ++m) { hp = &srp->header; /* stop indenting so far ... */ PRINT_PROC(srp->res_used ? " rb>> " : ((SG_INFO_DIRECT_IO_MASK & hp->info) ? " dio>> " : " ")); blen = srp->my_cmdp ? srp->my_cmdp->bufflen : srp->data.bufflen; usg = srp->my_cmdp ? srp->my_cmdp->use_sg : srp->data.k_use_sg; - PRINT_PROC(srp->done ? "rcv: id=%d" : (srp->my_cmdp ? "act: id=%d" : - "prior: id=%d"), srp->header.pack_id); - PRINT_PROC(" blen=%d", blen); + PRINT_PROC(srp->done ? ((1 == srp->done) ? "rcv:" : "fin:") + : (srp->my_cmdp ? "act:" : "prior:")); + PRINT_PROC(" id=%d blen=%d", srp->header.pack_id, blen); if (srp->done) - PRINT_PROC(" dur=%d", sg_jif_to_ms(hp->duration)); + PRINT_PROC(" dur=%d", hp->duration); else PRINT_PROC(" t_o/elap=%d/%d", ((hp->interface_id == '\0') ? sg_jif_to_ms(fp->timeout) : hp->timeout), sg_jif_to_ms(hp->duration ? (jiffies - hp->duration) : 0)); - PRINT_PROC(" sgat=%d op=0x%02x\n", usg, (int)srp->data.cmd_opcode); - srp = srp->nextrp; + PRINT_PROC("ms sgat=%d op=0x%02x\n", usg, (int)srp->data.cmd_opcode); /* reset indenting */ } + if (0 == m) + PRINT_PROC(" No requests active\n"); } } } - read_unlock(&sg_dev_arr_lock); return 1; } @@ -2596,19 +2672,17 @@ static int sg_proc_dev_info(char * buffer, int * len, off_t * begin, int j, max_dev; struct scsi_device * scsidp; - read_lock(&sg_dev_arr_lock); max_dev = sg_last_dev(); for (j = 0; j < max_dev; ++j) { - sdp = sg_dev_arr[j]; + sdp = sg_get_dev(j); if (sdp && (scsidp = sdp->device)) PRINT_PROC("%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\n", scsidp->host->host_no, scsidp->channel, scsidp->id, - scsidp->lun, (int)scsidp->type, (int)scsidp->disconnect, - (int)scsidp->queue_depth, (int)scsidp->tagged_queue); + scsidp->lun, (int)scsidp->type, (int)scsidp->access_count, + (int)scsidp->queue_depth, (int)scsidp->device_busy); else PRINT_PROC("-1\t-1\t-1\t-1\t-1\t-1\t-1\t-1\n"); } - read_unlock(&sg_dev_arr_lock); return 1; } @@ -2619,7 +2693,7 @@ static int sg_proc_devhdr_read(char * buffer, char ** start, off_t offset, static int sg_proc_devhdr_info(char * buffer, int * len, off_t * begin, off_t offset, int size) { - PRINT_PROC("host\tchan\tid\tlun\ttype\tdiscon\tqdepth\ttq\n"); + PRINT_PROC("host\tchan\tid\tlun\ttype\tbopens\tqdepth\tbusy\n"); return 1; } @@ -2634,17 +2708,15 @@ static int sg_proc_devstrs_info(char * buffer, int * len, off_t * begin, int j, max_dev; struct scsi_device * scsidp; - read_lock(&sg_dev_arr_lock); max_dev = sg_last_dev(); for (j = 0; j < max_dev; ++j) { - sdp = sg_dev_arr[j]; + sdp = sg_get_dev(j); if (sdp && (scsidp = sdp->device)) PRINT_PROC("%8.8s\t%16.16s\t%4.4s\n", scsidp->vendor, scsidp->model, scsidp->rev); else PRINT_PROC("<no active device>\n"); } - read_unlock(&sg_dev_arr_lock); return 1; } diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c index dc6712247..e568c6d1b 100644 --- a/drivers/scsi/sr.c +++ b/drivers/scsi/sr.c @@ -25,6 +25,9 @@ * * Modified by Richard Gooch <rgooch@atnf.csiro.au> to support devfs * + * Modified by Jens Axboe <axboe@suse.de> - support DVD-RAM + * transparently and loose the GHOST hack + * */ #include <linux/module.h> @@ -297,9 +300,10 @@ static int sr_init_command(Scsi_Cmnd * SCpnt) else printk("sr: can't switch blocksize: in interrupt\n"); } - if (SCpnt->request.cmd == WRITE) { + + if ((SCpnt->request.cmd == WRITE) && !scsi_CDs[dev].device->writeable) return 0; - } + if (scsi_CDs[dev].device->sector_size == 1024) { if ((block & 1) || (SCpnt->request.nr_sectors & 1)) { printk("sr.c:Bad 1K block number requested (%d %ld)", @@ -322,9 +326,6 @@ static int sr_init_command(Scsi_Cmnd * SCpnt) } switch (SCpnt->request.cmd) { case WRITE: - if (!scsi_CDs[dev].device->writeable) { - return 0; - } SCpnt->cmnd[0] = WRITE_10; SCpnt->sc_data_direction = SCSI_DATA_WRITE; break; @@ -587,10 +588,11 @@ void get_capabilities(int i) scsi_CDs[i].readcd_known = 1; scsi_CDs[i].readcd_cdda = buffer[n + 5] & 0x01; /* print some capability bits */ - printk("sr%i: scsi3-mmc drive: %dx/%dx %s%s%s%s%s\n", i, + printk("sr%i: scsi3-mmc drive: %dx/%dx %s%s%s%s%s%s\n", i, ((buffer[n + 14] << 8) + buffer[n + 15]) / 176, scsi_CDs[i].cdi.speed, buffer[n + 3] & 0x01 ? "writer " : "", /* CD Writer */ + buffer[n + 3] & 0x20 ? "dvd-ram " : "", buffer[n + 2] & 0x02 ? "cd/rw " : "", /* can read rewriteable */ buffer[n + 4] & 0x20 ? "xa/form2 " : "", /* can read xa/from2 */ buffer[n + 5] & 0x01 ? "cdda " : "", /* can read audio data */ @@ -601,9 +603,12 @@ void get_capabilities(int i) if ((buffer[n + 2] & 0x8) == 0) /* not a DVD drive */ scsi_CDs[i].cdi.mask |= CDC_DVD; - if ((buffer[n + 3] & 0x20) == 0) + if ((buffer[n + 3] & 0x20) == 0) { /* can't write DVD-RAM media */ scsi_CDs[i].cdi.mask |= CDC_DVD_RAM; + } else { + scsi_CDs[i].device->writeable = 1; + } if ((buffer[n + 3] & 0x10) == 0) /* can't write DVD-R media */ scsi_CDs[i].cdi.mask |= CDC_DVD_R; @@ -627,7 +632,6 @@ void get_capabilities(int i) /*else I don't think it can close its tray scsi_CDs[i].cdi.mask |= CDC_CLOSE_TRAY; */ - scsi_free(buffer, 512); } diff --git a/drivers/scsi/sym53c8xx.c b/drivers/scsi/sym53c8xx.c index 965543f8d..bec37e4a7 100644 --- a/drivers/scsi/sym53c8xx.c +++ b/drivers/scsi/sym53c8xx.c @@ -55,7 +55,7 @@ */ /* -** April 24 2000, sym53c8xx 1.5m +** May 11 2000, sym53c8xx 1.6b ** ** Supported SCSI features: ** Synchronous data transfers @@ -73,7 +73,10 @@ ** 53C895 (Wide, Fast 40, on-board rom BIOS) ** 53C895A (Wide, Fast 40, on-board rom BIOS) ** 53C896 (Wide, Fast 40 Dual, on-board rom BIOS) +** 53C897 (Wide, Fast 40 Dual, on-board rom BIOS) ** 53C1510D (Wide, Fast 40 Dual, on-board rom BIOS) +** 53C1010 (Wide, Fast 80 Dual, on-board rom BIOS) +** 53C1010_66(Wide, Fast 80 Dual, on-board rom BIOS, 33/66MHz PCI) ** ** Other features: ** Memory mapped IO @@ -84,7 +87,7 @@ /* ** Name and version of the driver */ -#define SCSI_NCR_DRIVER_NAME "sym53c8xx - version 1.5m" +#define SCSI_NCR_DRIVER_NAME "sym53c8xx - version 1.6b" /* #define DEBUG_896R1 */ #define SCSI_NCR_OPTIMIZE_896 @@ -174,6 +177,14 @@ typedef u64 u_int64; #include "sym53c8xx.h" +/* +** Donnot compile integrity checking code for Linux-2.3.0 +** and above since SCSI data structures are not ready yet. +*/ +#if LINUX_VERSION_CODE < LinuxVersionCode(2,3,0) +#define SCSI_NCR_INTEGRITY_CHECKING +#endif + #define MIN(a,b) (((a) < (b)) ? (a) : (b)) #define MAX(a,b) (((a) > (b)) ? (a) : (b)) @@ -606,6 +617,7 @@ pci_get_base_address(pcidev_t dev, int offset, u_long *base) #define DEBUG_TIMING (0x0100) #define DEBUG_NEGO (0x0200) #define DEBUG_TAGS (0x0400) +#define DEBUG_IC (0x0800) /* ** Enable/Disable debug messages. @@ -1654,6 +1666,8 @@ typedef struct { #define XE_EXTRA_DATA (1) /* unexpected data phase */ #define XE_BAD_PHASE (2) /* illegal phase (4/5) */ #define XE_PARITY_ERR (4) /* unrecovered SCSI parity error */ +#define XE_SODL_UNRUN (1<<3) +#define XE_SWIDE_OVRUN (1<<4) /*========================================================== ** @@ -1663,8 +1677,10 @@ typedef struct { **========================================================== */ +#define NS_NOCHANGE (0) #define NS_SYNC (1) #define NS_WIDE (2) +#define NS_PPR (4) /*========================================================== ** @@ -1819,7 +1835,7 @@ struct tcb { /*---------------------------------------------------------------- ** negotiation of wide and synch transfer and device quirks. - ** sval and wval are read from SCRIPTS and so have alignment + ** sval, wval and uval are read from SCRIPTS and so have alignment ** constraints. **---------------------------------------------------------------- */ @@ -1830,6 +1846,15 @@ struct tcb { /*1*/ u_char quirks; /*2*/ u_char widedone; /*3*/ u_char wval; +/*0*/ u_char uval; + +#ifdef SCSI_NCR_INTEGRITY_CHECKING + u_char ic_min_sync; + u_char ic_max_width; + u_char ic_done; +#endif + u_char ic_maximums_set; + u_char ppr_negotiation; /*---------------------------------------------------------------- ** User settable limits and options. @@ -1838,8 +1863,8 @@ struct tcb { */ u_char usrsync; u_char usrwide; - u_char usrflag; u_short usrtags; + u_char usrflag; }; /*======================================================================== @@ -2049,6 +2074,7 @@ struct head { #define HF_AUTO_SENSE (1u<<4) #define HF_DATA_IN (1u<<5) #define HF_PM_TO_C (1u<<6) +#define HF_EXT_ERR (1u<<7) #ifdef SCSI_NCR_IARB_SUPPORT #define HF_HINT_IARB (1u<<7) @@ -2106,6 +2132,7 @@ struct dsb { struct scr_tblmove smsg_ext ; struct scr_tblmove cmd ; struct scr_tblmove sense ; + struct scr_tblmove wresid; struct scr_tblmove data [MAX_SCATTER]; /* @@ -2269,7 +2296,7 @@ struct ncb { **---------------------------------------------------------------- */ u_char sv_scntl0, sv_scntl3, sv_dmode, sv_dcntl, sv_ctest3, sv_ctest4, - sv_ctest5, sv_gpcntl, sv_stest2, sv_stest4, sv_stest1; + sv_ctest5, sv_gpcntl, sv_stest2, sv_stest4, sv_stest1, sv_scntl4; /*---------------------------------------------------------------- ** Actual initial value of IO register bits used by the @@ -2278,7 +2305,7 @@ struct ncb { **---------------------------------------------------------------- */ u_char rv_scntl0, rv_scntl3, rv_dmode, rv_dcntl, rv_ctest3, rv_ctest4, - rv_ctest5, rv_stest2, rv_ccntl0, rv_ccntl1; + rv_ctest5, rv_stest2, rv_ccntl0, rv_ccntl1, rv_scntl4; /*---------------------------------------------------------------- ** Target data. @@ -2393,8 +2420,8 @@ struct ncb { ** written with a script command. **---------------------------------------------------------------- */ - u_char msgout[8]; /* Buffer for MESSAGE OUT */ - u_char msgin [8]; /* Buffer for MESSAGE IN */ + u_char msgout[12]; /* Buffer for MESSAGE OUT */ + u_char msgin [12]; /* Buffer for MESSAGE IN */ u_int32 lastmsg; /* Last SCSI message sent */ u_char scratch; /* Scratch for SCSI receive */ @@ -2466,6 +2493,17 @@ struct ncb { */ struct usrcmd user; /* Command from user */ u_char release_stage; /* Synchronisation stage on release */ + + /*---------------------------------------------------------------- + ** Fields that are used (primarily) for integrity check + **---------------------------------------------------------------- + */ + unsigned char check_integrity; /* Enable midlayer integ. check on + * bus scan. */ +#ifdef SCSI_NCR_INTEGRITY_CHECKING + unsigned char check_integ_par; /* Set if par or Init. Det. error + * used only during integ check */ +#endif }; #define NCB_PHYS(np, lbl) (np->p_ncb + offsetof(struct ncb, lbl)) @@ -2511,20 +2549,20 @@ struct script { ncrcmd select2 [ 2]; #endif ncrcmd command [ 2]; - ncrcmd dispatch [ 28]; + ncrcmd dispatch [ 30]; ncrcmd sel_no_cmd [ 10]; ncrcmd init [ 6]; ncrcmd clrack [ 4]; - ncrcmd disp_msg_in [ 2]; ncrcmd disp_status [ 4]; - ncrcmd datai_done [ 16]; - ncrcmd datao_done [ 10]; + ncrcmd datai_done [ 26]; + ncrcmd datao_done [ 12]; ncrcmd ign_i_w_r_msg [ 4]; #ifdef SCSI_NCR_PROFILE_SUPPORT - ncrcmd dataphase [ 4]; + ncrcmd datai_phase [ 4]; #else - ncrcmd dataphase [ 2]; + ncrcmd datai_phase [ 2]; #endif + ncrcmd datao_phase [ 4]; ncrcmd msg_in [ 2]; ncrcmd msg_in2 [ 10]; #ifdef SCSI_NCR_IARB_SUPPORT @@ -2562,16 +2600,17 @@ struct script { ncrcmd ungetjob [ 4]; #endif ncrcmd reselect [ 4]; - ncrcmd reselected [ 48]; + ncrcmd reselected [ 20]; + ncrcmd resel_scntl4 [ 30]; #if MAX_TASKS*4 > 512 - ncrcmd resel_tag [ 16]; + ncrcmd resel_tag [ 18]; #elif MAX_TASKS*4 > 256 - ncrcmd resel_tag [ 10]; + ncrcmd resel_tag [ 12]; #else - ncrcmd resel_tag [ 6]; + ncrcmd resel_tag [ 8]; #endif ncrcmd resel_go [ 6]; - ncrcmd resel_notag [ 4]; + ncrcmd resel_notag [ 2]; ncrcmd resel_dsa [ 8]; ncrcmd data_in [MAX_SCATTER * SCR_SG_SIZE]; ncrcmd data_in2 [ 4]; @@ -2591,6 +2630,7 @@ struct script { */ struct scripth { ncrcmd start64 [ 2]; + ncrcmd no_data [ 2]; ncrcmd sel_for_abort [ 18]; ncrcmd sel_for_abort_1 [ 2]; ncrcmd select_no_atn [ 8]; @@ -2608,11 +2648,13 @@ struct scripth { ncrcmd send_wdtr [ 4]; ncrcmd sdtr_resp [ 6]; ncrcmd send_sdtr [ 4]; + ncrcmd ppr_resp [ 6]; + ncrcmd send_ppr [ 4]; ncrcmd nego_bad_phase [ 4]; - ncrcmd msg_out_abort [ 12]; - ncrcmd msg_out [ 6]; + ncrcmd msg_out [ 4]; ncrcmd msg_out_done [ 4]; - ncrcmd no_data [ 28]; + ncrcmd data_ovrun [ 18]; + ncrcmd data_ovrun1 [ 20]; ncrcmd abort_resel [ 16]; ncrcmd resend_ident [ 4]; ncrcmd ident_break [ 4]; @@ -2621,7 +2663,7 @@ struct scripth { ncrcmd data_io [ 2]; ncrcmd data_io_com [ 8]; ncrcmd data_io_out [ 12]; - ncrcmd bad_identify [ 12]; + ncrcmd resel_bad_lun [ 4]; ncrcmd bad_i_t_l [ 4]; ncrcmd bad_i_t_l_q [ 4]; ncrcmd bad_status [ 6]; @@ -2632,14 +2674,13 @@ struct scripth { ncrcmd pm0_save [ 14]; ncrcmd pm1_save [ 14]; - /* SWIDE handling */ - ncrcmd swide_ma_32 [ 4]; - ncrcmd swide_ma_64 [ 6]; - ncrcmd swide_scr_64 [ 26]; - ncrcmd swide_scr_64_1 [ 12]; - ncrcmd swide_com_64 [ 6]; - ncrcmd swide_common [ 10]; - ncrcmd swide_fin_32 [ 24]; + /* WSR handling */ +#ifdef SYM_DEBUG_PM_WITH_WSR + ncrcmd pm_wsr_handle [ 44]; +#else + ncrcmd pm_wsr_handle [ 42]; +#endif + ncrcmd wsr_ma_helper [ 4]; /* Data area */ ncrcmd zero [ 1]; @@ -2697,6 +2738,9 @@ static void ncr_int_sto (ncb_p np); static void ncr_int_udc (ncb_p np); static void ncr_negotiate (ncb_p np, tcb_p tp); static int ncr_prepare_nego(ncb_p np, ccb_p cp, u_char *msgptr); +#ifdef SCSI_NCR_INTEGRITY_CHECKING +static int ncr_ic_nego(ncb_p np, ccb_p cp, Scsi_Cmnd *cmd, u_char *msgptr); +#endif #ifdef SCSI_NCR_PROFILE_SUPPORT static void ncb_profile (ncb_p np, ccb_p cp); #endif @@ -2706,9 +2750,12 @@ static void ncr_script_fill (struct script * scr, struct scripth * scripth); static int ncr_scatter_896R1 (ncb_p np, ccb_p cp, Scsi_Cmnd *cmd); static int ncr_scatter (ncb_p np, ccb_p cp, Scsi_Cmnd *cmd); static void ncr_getsync (ncb_p np, u_char sfac, u_char *fakp, u_char *scntl3p); -static void ncr_setsync (ncb_p np, ccb_p cp, u_char scntl3, u_char sxfer); +static void ncr_get_xfer_info(ncb_p np, tcb_p tp, u_char *factor, u_char *offset, u_char *width); +static void ncr_setsync (ncb_p np, ccb_p cp, u_char scntl3, u_char sxfer, u_char scntl4); +static void ncr_set_sync_wide_status (ncb_p np, u_char target); static void ncr_setup_tags (ncb_p np, u_char tn, u_char ln); static void ncr_setwide (ncb_p np, ccb_p cp, u_char wide, u_char ack); +static void ncr_setsyncwide (ncb_p np, ccb_p cp, u_char scntl3, u_char sxfer, u_char scntl4, u_char wide); static int ncr_show_msg (u_char * msg); static void ncr_print_msg (ccb_p cp, char *label, u_char * msg); static int ncr_snooptest (ncb_p np); @@ -2978,9 +3025,9 @@ static struct script script0 __initdata = { SCR_JUMP ^ IFTRUE (WHEN (SCR_MSG_IN)), PADDR (msg_in), SCR_JUMP ^ IFTRUE (IF (SCR_DATA_OUT)), - PADDR (dataphase), + PADDR (datao_phase), SCR_JUMP ^ IFTRUE (IF (SCR_DATA_IN)), - PADDR (dataphase), + PADDR (datai_phase), SCR_JUMP ^ IFTRUE (IF (SCR_STATUS)), PADDR (status), SCR_JUMP ^ IFTRUE (IF (SCR_COMMAND)), @@ -2988,6 +3035,12 @@ static struct script script0 __initdata = { SCR_JUMP ^ IFTRUE (IF (SCR_MSG_OUT)), PADDRH (msg_out), /* + * Set the extended error flag. + */ + SCR_REG_REG (HF_REG, SCR_OR, HF_EXT_ERR), + 0, + + /* ** Discard one illegal phase byte, if required. */ SCR_LOAD_REL (scratcha, 1), @@ -3056,17 +3109,6 @@ static struct script script0 __initdata = { SCR_JUMP, PADDR (dispatch), -}/*-------------------------< DISP_MSG_IN >----------------------*/,{ - /* - ** Anticipate MSG_IN phase then STATUS phase. - ** - ** May spare 2 SCRIPTS instructions when we have - ** completed the OUTPUT of the data and the device - ** goes directly to STATUS phase. - */ - SCR_JUMP ^ IFTRUE (WHEN (SCR_MSG_IN)), - PADDR (msg_in), - }/*-------------------------< DISP_STATUS >----------------------*/,{ /* ** Anticipate STATUS phase. @@ -3081,6 +3123,12 @@ static struct script script0 __initdata = { }/*-------------------------< DATAI_DONE >-------------------*/,{ /* + * If the device wants us to send more data, + * we must count the extra bytes. + */ + SCR_JUMP ^ IFTRUE (WHEN (SCR_DATA_IN)), + PADDRH (data_ovrun), + /* ** If the SWIDE is not full, jump to dispatcher. ** We anticipate a STATUS phase. ** If we get later an IGNORE WIDE RESIDUE, we @@ -3097,36 +3145,56 @@ static struct script script0 __initdata = { SCR_REG_REG (scntl2, SCR_OR, WSR), 0, /* - ** Since the device is required to send any - ** IGNORE WIDE RESIDUE message prior to any - ** other information, we just snoop the SCSI - ** BUS to check for such a message. + * We are expecting an IGNORE RESIDUE message + * from the device, otherwise we are in data + * overrun condition. Check against MSG_IN phase. */ + SCR_INT ^ IFFALSE (WHEN (SCR_MSG_IN)), + SIR_SWIDE_OVERRUN, SCR_JUMP ^ IFFALSE (WHEN (SCR_MSG_IN)), PADDR (disp_status), - SCR_FROM_REG (sbdl), - 0, + /* + * We are in MSG_IN phase, + * Read the first byte of the message. + * If it is not an IGNORE RESIDUE message, + * signal overrun and jump to message + * processing. + */ + SCR_MOVE_ABS (1) ^ SCR_MSG_IN, + NADDR (msgin[0]), + SCR_INT ^ IFFALSE (DATA (M_IGN_RESIDUE)), + SIR_SWIDE_OVERRUN, SCR_JUMP ^ IFFALSE (DATA (M_IGN_RESIDUE)), - PADDR (disp_status), + PADDR (msg_in2), + /* - ** We have been ODD at the end of the transfer, - ** but the device hasn't be so. - ** Signal a DATA OVERRUN condition to the C code. - */ - SCR_INT, - SIR_SWIDE_OVERRUN, + * We got the message we expected. + * Read the 2nd byte, and jump to dispatcher. + */ + SCR_CLR (SCR_ACK), + 0, + SCR_MOVE_ABS (1) ^ SCR_MSG_IN, + NADDR (msgin[1]), + SCR_CLR (SCR_ACK), + 0, SCR_JUMP, - PADDR (dispatch), + PADDR (disp_status), }/*-------------------------< DATAO_DONE >-------------------*/,{ /* + * If the device wants us to send more data, + * we must count the extra bytes. + */ + SCR_JUMP ^ IFTRUE (WHEN (SCR_DATA_OUT)), + PADDRH (data_ovrun), + /* ** If the SODL is not full jump to dispatcher. ** We anticipate a MSG IN phase or a STATUS phase. */ SCR_FROM_REG (scntl2), 0, SCR_JUMP ^ IFFALSE (MASK (WSS, WSS)), - PADDR (disp_msg_in), + PADDR (disp_status), /* ** The SODL is full, clear this condition. */ @@ -3157,13 +3225,25 @@ static struct script script0 __initdata = { SCR_JUMP, PADDR (clrack), -}/*-------------------------< DATAPHASE >------------------*/,{ +}/*-------------------------< DATAI_PHASE >------------------*/,{ #ifdef SCSI_NCR_PROFILE_SUPPORT SCR_REG_REG (QU_REG, SCR_OR, HF_DATA_ST), 0, #endif SCR_RETURN, 0, +}/*-------------------------< DATAO_PHASE >------------------*/,{ + /* + ** Patch for 53c1010_66 only - to allow A0 part + ** to operate properly in a 33MHz PCI bus. + ** + ** SCR_REG_REG(scntl4, SCR_OR, 0x0c), + ** 0, + */ + SCR_NO_OP, + 0, + SCR_RETURN, + 0, }/*-------------------------< MSG_IN >--------------------*/,{ /* ** Get the first byte of the message. @@ -3524,31 +3604,42 @@ static struct script script0 __initdata = { offsetof(struct tcb, wval), SCR_LOAD_REL (sxfer, 1), offsetof(struct tcb, sval), +}/*-------------------------< RESEL_SCNTL4 >------------------*/,{ /* - ** If MESSAGE IN phase as expected, - ** read the data directly from the BUS DATA lines. - ** This helps to support very old SCSI devices that - ** may reselect without sending an IDENTIFY. + ** Write with uval value. Patch if device + ** does not support Ultra3. + ** + ** SCR_LOAD_REL (scntl4, 1), + ** offsetof(struct tcb, uval), */ + + SCR_NO_OP, + 0, + /* + * We expect MESSAGE IN phase. + * If not, get help from the C code. + */ SCR_INT ^ IFFALSE (WHEN (SCR_MSG_IN)), SIR_RESEL_NO_MSG_IN, - SCR_FROM_REG (sbdl), - 0, + SCR_MOVE_ABS (1) ^ SCR_MSG_IN, + NADDR (msgin), + /* - ** If message phase but not an IDENTIFY, - ** get some help from the C code. - ** Old SCSI device may behave so. - */ + * If IDENTIFY LUN #0, use a faster path + * to find the LCB structure. + */ + SCR_JUMPR ^ IFTRUE (MASK (0x80, 0xbf)), + 56, + /* + * If message isn't an IDENTIFY, + * tell the C code about. + */ SCR_INT ^ IFFALSE (MASK (0x80, 0x80)), SIR_RESEL_NO_IDENTIFY, /* - ** It is an IDENTIFY message, - ** Load the LUN control block address. - ** If LUN 0, avoid a PCI BUS ownership by loading - ** directly 'b_lun0' from the TCB. - */ - SCR_JUMPR ^ IFTRUE (MASK (0x0, 0x3f)), - 48, + * It is an IDENTIFY message, + * Load the LUN control block address. + */ SCR_LOAD_REL (dsa, 4), offsetof(struct tcb, b_luntbl), SCR_SFBR_REG (dsa, SCR_SHL, 0), @@ -3578,15 +3669,20 @@ static struct script script0 __initdata = { offsetof(struct lcb, b_tasktbl), SCR_RETURN, 0, - }/*-------------------------< RESEL_TAG >-------------------*/,{ /* + ** ACK the IDENTIFY or TAG previously received + */ + + SCR_CLR (SCR_ACK), + 0, + /* ** Read IDENTIFY + SIMPLE + TAG using a single MOVE. ** Agressive optimization, is'nt it? ** No need to test the SIMPLE TAG message, since the ** driver only supports conformant devices for tags. ;-) */ - SCR_MOVE_ABS (3) ^ SCR_MSG_IN, + SCR_MOVE_ABS (2) ^ SCR_MSG_IN, NADDR (msgin), /* ** Read the TAG from the SIDL. @@ -3627,14 +3723,9 @@ static struct script script0 __initdata = { offsetof(struct ccb, phys.header.go.restart), SCR_RETURN, 0, + /* In normal situations we branch to RESEL_DSA */ }/*-------------------------< RESEL_NOTAG >-------------------*/,{ /* - ** No tag expected. - ** Read an throw away the IDENTIFY. - */ - SCR_MOVE_ABS (1) ^ SCR_MSG_IN, - NADDR (msgin), - /* ** JUMP indirectly to the restart point of the CCB. */ SCR_JUMP, @@ -3681,7 +3772,7 @@ static struct script script0 __initdata = { SCR_CALL, PADDR (datai_done), SCR_JUMP, - PADDRH (no_data), + PADDRH (data_ovrun), }/*-------------------------< DATA_OUT >--------------------*/,{ /* ** Because the size depends on the @@ -3700,7 +3791,7 @@ static struct script script0 __initdata = { SCR_CALL, PADDR (datao_done), SCR_JUMP, - PADDRH (no_data), + PADDRH (data_ovrun), }/*-------------------------< PM0_DATA >--------------------*/,{ /* @@ -3719,7 +3810,7 @@ static struct script script0 __initdata = { ** Check against expected direction. */ SCR_JUMP ^ IFFALSE (MASK (HF_DATA_IN, HF_DATA_IN)), - PADDRH (no_data), + PADDRH (data_ovrun), /* ** Keep track we are moving data from the ** PM0 DATA mini-script. @@ -3739,7 +3830,7 @@ static struct script script0 __initdata = { ** Check against expected direction. */ SCR_JUMP ^ IFTRUE (MASK (HF_DATA_IN, HF_DATA_IN)), - PADDRH (no_data), + PADDRH (data_ovrun), /* ** Keep track we are moving data from the ** PM0 DATA mini-script. @@ -3784,7 +3875,7 @@ static struct script script0 __initdata = { ** Check against expected direction. */ SCR_JUMP ^ IFFALSE (MASK (HF_DATA_IN, HF_DATA_IN)), - PADDRH (no_data), + PADDRH (data_ovrun), /* ** Keep track we are moving data from the ** PM1 DATA mini-script. @@ -3804,7 +3895,7 @@ static struct script script0 __initdata = { ** Check against expected direction. */ SCR_JUMP ^ IFTRUE (MASK (HF_DATA_IN, HF_DATA_IN)), - PADDRH (no_data), + PADDRH (data_ovrun), /* ** Keep track we are moving data from the ** PM1 DATA mini-script. @@ -3835,6 +3926,7 @@ static struct script script0 __initdata = { }/*---------------------------------------------------------*/ }; + static struct scripth scripth0 __initdata = { /*------------------------< START64 >-----------------------*/{ /* @@ -3844,7 +3936,9 @@ static struct scripth scripth0 __initdata = { */ SCR_JUMP, PADDR (init), - +}/*-------------------------< NO_DATA >-------------------*/,{ + SCR_JUMP, + PADDRH (data_ovrun), }/*-----------------------< SEL_FOR_ABORT >------------------*/,{ /* ** We are jumped here by the C code, if we have @@ -4078,33 +4172,31 @@ static struct scripth scripth0 __initdata = { SCR_JUMP, PADDRH (msg_out_done), -}/*-------------------------< NEGO_BAD_PHASE >------------*/,{ - SCR_INT, - SIR_NEGO_PROTO, - SCR_JUMP, - PADDR (dispatch), - -}/*-------------------------< MSG_OUT_ABORT >-------------*/,{ +}/*-------------------------< PPR_RESP >-------------*/,{ /* - ** After ABORT message, - ** - ** expect an immediate disconnect, ... + ** let the target fetch our answer. */ - SCR_REG_REG (scntl2, SCR_AND, 0x7f), - 0, - SCR_CLR (SCR_ACK|SCR_ATN), + SCR_SET (SCR_ATN), 0, - SCR_WAIT_DISC, + SCR_CLR (SCR_ACK), 0, - SCR_INT, - SIR_MSG_OUT_DONE, + SCR_JUMP ^ IFFALSE (WHEN (SCR_MSG_OUT)), + PADDRH (nego_bad_phase), + +}/*-------------------------< SEND_PPR >-------------*/,{ /* - ** ... and set the status to "ABORTED" + ** Send the M_X_PPR_REQ */ - SCR_LOAD_REG (HS_REG, HS_ABORTED), - 0, + SCR_MOVE_ABS (8) ^ SCR_MSG_OUT, + NADDR (msgout), SCR_JUMP, - PADDR (complete2), + PADDRH (msg_out_done), + +}/*-------------------------< NEGO_BAD_PHASE >------------*/,{ + SCR_INT, + SIR_NEGO_PROTO, + SCR_JUMP, + PADDR (dispatch), }/*-------------------------< MSG_OUT >-------------------*/,{ /* @@ -4113,11 +4205,6 @@ static struct scripth scripth0 __initdata = { SCR_MOVE_ABS (1) ^ SCR_MSG_OUT, NADDR (msgout), /* - ** If it was no ABORT message ... - */ - SCR_JUMP ^ IFTRUE (DATA (M_ABORT)), - PADDRH (msg_out_abort), - /* ** ... wait for the next phase ** if it's a message out, send it again, ... */ @@ -4135,34 +4222,56 @@ static struct scripth scripth0 __initdata = { SCR_JUMP, PADDR (dispatch), -}/*-------------------------< NO_DATA >--------------------*/,{ +}/*-------------------------< DATA_OVRUN >--------------------*/,{ /* - ** The target wants to tranfer too much data - ** or in the wrong direction. - ** Remember that in extended error. - */ + * The target may want to transfer too much data. + * + * If phase is DATA OUT write 1 byte and count it. + */ + SCR_JUMPR ^ IFFALSE (WHEN (SCR_DATA_OUT)), + 16, + SCR_CHMOV_ABS (1) ^ SCR_DATA_OUT, + NADDR (scratch), + SCR_JUMP, + PADDRH (data_ovrun1), + /* + * If WSR is set, clear this condition, and + * count this byte. + */ + SCR_FROM_REG (scntl2), + 0, + SCR_JUMPR ^ IFFALSE (MASK (WSR, WSR)), + 16, + SCR_REG_REG (scntl2, SCR_OR, WSR), + 0, + SCR_JUMP, + PADDRH (data_ovrun1), + /* + * Finally check against DATA IN phase. + * Jump to dispatcher if not so. + * Read 1 byte otherwise and count it. + */ + SCR_JUMP ^ IFFALSE (IF (SCR_DATA_IN)), + PADDR (dispatch), + SCR_CHMOV_ABS (1) ^ SCR_DATA_IN, + NADDR (scratch), +}/*-------------------------< DATA_OVRUN1 >--------------------*/,{ + /* + * Set the extended error flag. + */ + SCR_REG_REG (HF_REG, SCR_OR, HF_EXT_ERR), + 0, SCR_LOAD_REL (scratcha, 1), offsetof (struct ccb, xerr_status), - SCR_REG_REG (scratcha, SCR_OR, XE_EXTRA_DATA), + SCR_REG_REG (scratcha, SCR_OR, XE_EXTRA_DATA), 0, SCR_STORE_REL (scratcha, 1), offsetof (struct ccb, xerr_status), /* - ** Discard one data byte, if required. - */ - SCR_JUMPR ^ IFFALSE (WHEN (SCR_DATA_OUT)), - 8, - SCR_MOVE_ABS (1) ^ SCR_DATA_OUT, - NADDR (scratch), - SCR_JUMPR ^ IFFALSE (IF (SCR_DATA_IN)), - 8, - SCR_MOVE_ABS (1) ^ SCR_DATA_IN, - NADDR (scratch), - /* - ** Count this byte. - ** This will allow to return a positive - ** residual to user. - */ + * Count this byte. + * This will allow to return a negative + * residual to user. + */ SCR_LOAD_REL (scratcha, 4), offsetof (struct ccb, phys.extra_bytes), SCR_REG_REG (scratcha, SCR_ADD, 0x01), @@ -4174,12 +4283,10 @@ static struct scripth scripth0 __initdata = { SCR_STORE_REL (scratcha, 4), offsetof (struct ccb, phys.extra_bytes), /* - ** .. and repeat as required. - */ - SCR_CALL, - PADDR (dispatch), + * .. and repeat as required. + */ SCR_JUMP, - PADDRH (no_data), + PADDRH (data_ovrun), }/*-------------------------< ABORT_RESEL >----------------*/,{ SCR_SET (SCR_ATN), @@ -4227,10 +4334,9 @@ static struct scripth scripth0 __initdata = { SCR_CHMOV_TBL ^ SCR_DATA_IN, offsetof (struct dsb, sense), SCR_CALL, - PADDR (dispatch), + PADDR (datai_done), SCR_JUMP, - PADDRH (no_data), - + PADDRH (data_ovrun), }/*-------------------------< DATA_IO >--------------------*/,{ /* ** We jump here if the data direction was unknown at the @@ -4280,29 +4386,14 @@ static struct scripth scripth0 __initdata = { SCR_JUMP, PADDRH(data_io_com), -}/*-------------------------< BAD_IDENTIFY >---------------*/,{ - /* - ** If message phase but not an IDENTIFY, - ** get some help from the C code. - ** Old SCSI device may behave so. - */ - SCR_JUMPR ^ IFTRUE (MASK (0x80, 0x80)), - 16, - SCR_INT, - SIR_RESEL_NO_IDENTIFY, - SCR_JUMP, - PADDRH (abort_resel), +}/*-------------------------< RESEL_BAD_LUN >---------------*/,{ /* ** Message is an IDENTIFY, but lun is unknown. - ** Read the message, since we got it directly - ** from the SCSI BUS data lines. ** Signal problem to C code for logging the event. ** Send a M_ABORT to clear all pending tasks. */ SCR_INT, SIR_RESEL_BAD_LUN, - SCR_MOVE_ABS (1) ^ SCR_MSG_IN, - NADDR (msgin), SCR_JUMP, PADDRH (abort_resel), }/*-------------------------< BAD_I_T_L >------------------*/,{ @@ -4441,7 +4532,7 @@ static struct scripth scripth0 __initdata = { SCR_FROM_REG (scntl2), 0, SCR_CALL ^ IFTRUE (MASK (WSR, WSR)), - PADDRH (swide_scr_64), + PADDRH (pm_wsr_handle), /* ** Save the remaining byte count, the updated ** address and the return address. @@ -4468,7 +4559,7 @@ static struct scripth scripth0 __initdata = { SCR_FROM_REG (scntl2), 0, SCR_CALL ^ IFTRUE (MASK (WSR, WSR)), - PADDRH (swide_scr_64), + PADDRH (pm_wsr_handle), /* ** Save the remaining byte count, the updated ** address and the return address. @@ -4484,101 +4575,32 @@ static struct scripth scripth0 __initdata = { PADDRH (pm1_data_addr), SCR_JUMP, PADDR (dispatch), - -}/*--------------------------< SWIDE_MA_32 >-----------------------*/,{ - /* - ** Handling of the SWIDE for 32 bit chips. - ** - ** We jump here from the C code with SCRATCHA - ** containing the address to write the SWIDE. - ** - Save 32 bit address in <scratch>. - */ - SCR_STORE_ABS (scratcha, 4), - PADDRH (scratch), - SCR_JUMP, - PADDRH (swide_common), -}/*--------------------------< SWIDE_MA_64 >-----------------------*/,{ +}/*--------------------------< PM_WSR_HANDLE >-----------------------*/,{ /* - ** Handling of the SWIDE for 64 bit chips when the - ** hardware handling of phase mismatch is disabled. - ** - ** We jump here from the C code with SCRATCHA - ** containing the address to write the SWIDE and - ** SBR containing bit 32..39 of this address. - ** - Save 32 bit address in <scratch>. - ** - Move address bit 32..39 to SFBR. - */ - SCR_STORE_ABS (scratcha, 4), - PADDRH (scratch), - SCR_FROM_REG (sbr), - 0, - SCR_JUMP, - PADDRH (swide_com_64), -}/*--------------------------< SWIDE_SCR_64 >-----------------------*/,{ - /* - ** Handling of the SWIDE for 64 bit chips when - ** hardware phase mismatch is enabled. - ** We are entered with a SCR_CALL from PMO_SAVE - ** and PM1_SAVE sub-scripts. - ** - ** Snoop the SCSI BUS in case of the device - ** willing to ignore this residue. - ** If it does, we must only increment the RBC, - ** since this register does reflect all bytes - ** received from the SCSI BUS including the SWIDE. - */ - SCR_JUMP ^ IFFALSE (WHEN (SCR_MSG_IN)), - PADDRH (swide_scr_64_1), - SCR_FROM_REG (sbdl), - 0, - SCR_JUMP ^ IFFALSE (DATA (M_IGN_RESIDUE)), - PADDRH (swide_scr_64_1), - SCR_REG_REG (rbc, SCR_ADD, 1), - 0, - SCR_REG_REG (rbc1, SCR_ADDC, 0), - 0, - SCR_REG_REG (rbc2, SCR_ADDC, 0), - 0, - /* - ** Save UA and RBC, since the PM0/1_SAVE - ** sub-scripts haven't moved them to the - ** context yet and the below MOV may just - ** change their value. - */ - SCR_STORE_ABS (ua, 4), - PADDRH (scratch), - SCR_STORE_ABS (rbc, 4), - PADDRH (scratch1), + * Phase mismatch handling from SCRIPT with WSR set. + * Such a condition can occur if the chip wants to + * execute a CHMOV(size > 1) when the WSR bit is + * set and the target changes PHASE. + */ +#ifdef SYM_DEBUG_PM_WITH_WSR /* - ** Throw away the IGNORE WIDE RESIDUE message. - ** since we just did take care of it. - */ - SCR_MOVE_ABS (2) ^ SCR_MSG_IN, - NADDR (scratch), - SCR_CLR (SCR_ACK), - 0, + * Some debugging may still be needed.:) + */ + SCR_INT, + SIR_PM_WITH_WSR, +#endif /* - ** Restore UA and RBC registers and return. - */ - SCR_LOAD_ABS (ua, 4), - PADDRH (scratch), - SCR_LOAD_ABS (rbc, 4), - PADDRH (scratch1), - SCR_RETURN, - 0, -}/*--------------------------< SWIDE_SCR_64_1 >---------------------*/,{ + * We must move the residual byte to memory. + * + * UA contains bit 0..31 of the address to + * move the residual byte. + * Move it to the table indirect. + */ + SCR_STORE_REL (ua, 4), + offsetof (struct ccb, phys.wresid.addr), /* - ** We must grab the SWIDE and move it to - ** memory. - ** - ** - Save UA (32 bit address) in <scratch>. - ** - Move address bit 32..39 to SFBR. - ** - Increment UA (updated address). - */ - SCR_STORE_ABS (ua, 4), - PADDRH (scratch), - SCR_FROM_REG (rbc3), - 0, + * Increment UA (move address to next position). + */ SCR_REG_REG (ua, SCR_ADD, 1), 0, SCR_REG_REG (ua1, SCR_ADDC, 0), @@ -4587,70 +4609,45 @@ static struct scripth scripth0 __initdata = { 0, SCR_REG_REG (ua3, SCR_ADDC, 0), 0, -}/*--------------------------< SWIDE_COM_64 >-----------------------*/,{ /* - ** - Save DRS. - ** - Load DRS with address bit 32..39 of the - ** location to write the SWIDE. - ** SFBR has been loaded with these bits. - ** (Look above). - */ - SCR_STORE_ABS (drs, 4), - PADDRH (saved_drs), - SCR_LOAD_ABS (drs, 4), + * Compute SCRATCHA as: + * - size to transfer = 1 byte. + * - bit 24..31 = high address bit [32...39]. + */ + SCR_LOAD_ABS (scratcha, 4), PADDRH (zero), - SCR_TO_REG (drs), + SCR_REG_REG (scratcha, SCR_OR, 1), 0, -}/*--------------------------< SWIDE_COMMON >-----------------------*/,{ - /* - ** - Save current DSA - ** - Load DSA with bit 0..31 of the memory - ** location to write the SWIDE. - */ - SCR_STORE_ABS (dsa, 4), - PADDRH (saved_dsa), - SCR_LOAD_ABS (dsa, 4), - PADDRH (scratch), - /* - ** Move the SWIDE to memory. - ** Clear the WSR bit. - */ - SCR_STORE_REL (swide, 1), + SCR_FROM_REG (rbc3), 0, - SCR_REG_REG (scntl2, SCR_OR, WSR), + SCR_TO_REG (scratcha3), 0, /* - ** Restore the original DSA. - */ - SCR_LOAD_ABS (dsa, 4), - PADDRH (saved_dsa), -}/*--------------------------< SWIDE_FIN_32 >-----------------------*/,{ - /* - ** For 32 bit chip, the following SCRIPTS - ** instruction is patched with a JUMP to dispatcher. - ** (Look into the C code). - */ - SCR_LOAD_ABS (drs, 4), - PADDRH (saved_drs), - /* - ** 64 bit chip only. - ** If PM handling from SCRIPTS, we are just - ** a helper for the C code, so jump to - ** dispatcher now. - */ - SCR_FROM_REG (ccntl0), + * Move this value to the table indirect. + */ + SCR_STORE_REL (scratcha, 4), + offsetof (struct ccb, phys.wresid.size), + /* + * Wait for a valid phase. + * While testing with bogus QUANTUM drives, the C1010 + * sometimes raised a spurious phase mismatch with + * WSR and the CHMOV(1) triggered another PM. + * Waiting explicitely for the PHASE seemed to avoid + * the nested phase mismatch. Btw, this didn't happen + * using my IBM drives. + */ + SCR_JUMPR ^ IFFALSE (WHEN (SCR_DATA_IN)), 0, - SCR_JUMP ^ IFFALSE (MASK (ENPMJ, ENPMJ)), - PADDR (dispatch), /* - ** 64 bit chip with hardware PM handling enabled. - ** - ** Since we are paranoid:), we donnot want - ** a SWIDE followed by a CHMOV(1) to lead to - ** a CHMOV(0) in our PM context. - ** We check against such a condition. - ** Also does the C code. - */ + * Perform the move of the residual byte. + */ + SCR_CHMOV_TBL ^ SCR_DATA_IN, + offsetof (struct ccb, phys.wresid), + /* + * We can now handle the phase mismatch with UA fixed. + * RBC[0..23]=0 is a special case that does not require + * a PM context. The C code also checks against this. + */ SCR_FROM_REG (rbc), 0, SCR_RETURN ^ IFFALSE (DATA (0)), @@ -4664,19 +4661,29 @@ static struct scripth scripth0 __initdata = { SCR_RETURN ^ IFFALSE (DATA (0)), 0, /* - ** If we are there, RBC(0..23) is zero, - ** and we just have to load the current - ** DATA SCRIPTS address (register TEMP) - ** with the IA and go to dispatch. - ** No PM context is needed. - */ + * RBC[0..23]=0. + * Not only we donnot need a PM context, but this would + * lead to a bogus CHMOV(0). This condition means that + * the residual was the last byte to move from this CHMOV. + * So, we just have to move the current data script pointer + * (i.e. TEMP) to the SCRIPTS address following the + * interrupted CHMOV and jump to dispatcher. + */ SCR_STORE_ABS (ia, 4), PADDRH (scratch), SCR_LOAD_ABS (temp, 4), PADDRH (scratch), SCR_JUMP, PADDR (dispatch), - +}/*--------------------------< WSR_MA_HELPER >-----------------------*/,{ + /* + * Helper for the C code when WSR bit is set. + * Perform the move of the residual byte. + */ + SCR_CHMOV_TBL ^ SCR_DATA_IN, + offsetof (struct ccb, phys.wresid), + SCR_JUMP, + PADDR (dispatch), }/*-------------------------< ZERO >------------------------*/,{ SCR_DATA_ZERO, }/*-------------------------< SCRATCH >---------------------*/,{ @@ -4792,6 +4799,7 @@ void __init ncr_script_fill (struct script * scr, struct scripth * scrh) assert ((u_long)p == (u_long)&scr->data_in + sizeof (scr->data_in)); p = scr->data_out; + for (i=0; i<MAX_SCATTER; i++) { *p++ =SCR_CHMOV_TBL ^ SCR_DATA_OUT; *p++ =offsetof (struct dsb, data[i]); @@ -4963,6 +4971,7 @@ ncr_script_copy_and_bind (ncb_p np,ncrcmd *src,ncrcmd *dst,int len) break; #ifdef RELOC_KVAR case RELOC_KVAR: + new=0; if (((old & ~RELOC_MASK) < SCRIPT_KVAR_FIRST) || ((old & ~RELOC_MASK) > SCRIPT_KVAR_LAST)) panic("ncr KVAR out of range"); @@ -5152,16 +5161,30 @@ ncr_Tekram_setup_target(ncb_p np, int target, Tekram_nvram *nvram) static void __init ncr_save_initial_setting(ncb_p np) { np->sv_scntl0 = INB(nc_scntl0) & 0x0a; - np->sv_scntl3 = INB(nc_scntl3) & 0x07; np->sv_dmode = INB(nc_dmode) & 0xce; np->sv_dcntl = INB(nc_dcntl) & 0xa8; np->sv_ctest3 = INB(nc_ctest3) & 0x01; np->sv_ctest4 = INB(nc_ctest4) & 0x80; - np->sv_ctest5 = INB(nc_ctest5) & 0x24; np->sv_gpcntl = INB(nc_gpcntl); np->sv_stest2 = INB(nc_stest2) & 0x20; np->sv_stest4 = INB(nc_stest4); np->sv_stest1 = INB(nc_stest1); + + np->sv_scntl3 = INB(nc_scntl3) & 0x07; + + if ((np->device_id == PCI_DEVICE_ID_LSI_53C1010) || + (np->device_id == PCI_DEVICE_ID_LSI_53C1010_66) ){ + /* + ** C1010 always uses large fifo, bit 5 rsvd + ** scntl4 used ONLY with C1010 + */ + np->sv_ctest5 = INB(nc_ctest5) & 0x04 ; + np->sv_scntl4 = INB(nc_scntl4); + } + else { + np->sv_ctest5 = INB(nc_ctest5) & 0x24 ; + np->sv_scntl4 = 0; + } } /* @@ -5200,15 +5223,35 @@ static int __init ncr_prepare_setting(ncb_p np, ncr_nvram *nvram) /* * Divisor to be used for async (timer pre-scaler). + * + * Note: For C1010 the async divisor is 2(8) if he + * quadrupler is disabled (enabled). */ - i = np->clock_divn - 1; - while (--i >= 0) { - if (10ul * SCSI_NCR_MIN_ASYNC * np->clock_khz > div_10M[i]) { - ++i; - break; + + if ( (np->device_id == PCI_DEVICE_ID_LSI_53C1010) || + (np->device_id == PCI_DEVICE_ID_LSI_53C1010_66)) { + + np->rv_scntl3 = 0; + } + else + { + i = np->clock_divn - 1; + while (--i >= 0) { + if (10ul * SCSI_NCR_MIN_ASYNC * np->clock_khz + > div_10M[i]) { + ++i; + break; + } } + np->rv_scntl3 = i+1; } - np->rv_scntl3 = i+1; + + + /* + * Save the ultra3 register for the C1010/C1010_66 + */ + + np->rv_scntl4 = np->sv_scntl4; /* * Minimum synchronous period factor supported by the chip. @@ -5222,13 +5265,28 @@ static int __init ncr_prepare_setting(ncb_p np, ncr_nvram *nvram) else np->minsync = (period + 40 - 1) / 40; /* + * Fix up. If sync. factor is 10 (160000Khz clock) and chip + * supports ultra3, then min. sync. period 12.5ns and the factor is 9 + */ + + if ((np->minsync == 10) && (np->features & FE_ULTRA3)) + np->minsync = 9; + + /* * Check against chip SCSI standard support (SCSI-2,ULTRA,ULTRA2). + * + * Transfer period minimums: SCSI-1 200 (50); Fast 100 (25) + * Ultra 50 (12); Ultra2 (6); Ultra3 (3) */ - if (np->minsync < 25 && !(np->features & (FE_ULTRA|FE_ULTRA2))) + if (np->minsync < 25 && !(np->features & (FE_ULTRA|FE_ULTRA2|FE_ULTRA3))) np->minsync = 25; - else if (np->minsync < 12 && !(np->features & FE_ULTRA2)) + else if (np->minsync < 12 && (np->features & FE_ULTRA)) np->minsync = 12; + else if (np->minsync < 10 && (np->features & FE_ULTRA2)) + np->minsync = 10; + else if (np->minsync < 9 && (np->features & FE_ULTRA3)) + np->minsync = 9; /* * Maximum synchronous period factor supported by the chip. @@ -5248,7 +5306,7 @@ static int __init ncr_prepare_setting(ncb_p np, ncr_nvram *nvram) #endif /* - ** Phase mismatch handled by SCRIPTS (53C895A or 53C896) ? + ** Phase mismatch handled by SCRIPTS (53C895A, 53C896 or C1010) ? */ if (np->features & FE_NOPM) np->rv_ccntl0 |= (ENPMJ); @@ -5292,6 +5350,14 @@ static int __init ncr_prepare_setting(ncb_p np, ncr_nvram *nvram) np->features &= ~(FE_WRIE|FE_ERL|FE_ERMP); /* + ** DEL ? - 53C1010 Rev 1 - Part Number 609-0393638 + ** 64-bit Slave Cycles must be disabled. + */ + if ( ((np->device_id == PCI_DEVICE_ID_LSI_53C1010) && (np->revision_id < 0x02) ) + || (np->device_id == PCI_DEVICE_ID_LSI_53C1010_66 ) ) + np->rv_ccntl1 |= 0x10; + + /* ** Select all supported special features. ** If we are using on-board RAM for scripts, prefetch (PFEN) ** does not help, but burst op fetch (BOF) does. @@ -5313,8 +5379,13 @@ static int __init ncr_prepare_setting(ncb_p np, ncr_nvram *nvram) np->rv_dcntl |= CLSE; /* Cache Line Size Enable */ if (np->features & FE_WRIE) np->rv_ctest3 |= WRIE; /* Write and Invalidate */ - if (np->features & FE_DFS) + + + if ( (np->device_id != PCI_DEVICE_ID_LSI_53C1010) && + (np->device_id != PCI_DEVICE_ID_LSI_53C1010_66) && + (np->features & FE_DFS)) np->rv_ctest5 |= DFS; /* Dma Fifo Size */ + /* C1010/C1010_66 always large fifo */ /* ** Select some other @@ -5362,14 +5433,15 @@ static int __init ncr_prepare_setting(ncb_p np, ncr_nvram *nvram) /* ** Set SCSI BUS mode. ** - ** - ULTRA2 chips (895/895A/896) report the current + ** - ULTRA2 chips (895/895A/896) + ** and ULTRA 3 chips (1010) report the current ** BUS mode through the STEST4 IO register. ** - For previous generation chips (825/825A/875), ** user has to tell us how to check against HVD, ** since a 100% safe algorithm is not possible. */ np->scsi_mode = SMODE_SE; - if (np->features & FE_ULTRA2) + if (np->features & (FE_ULTRA2 | FE_ULTRA3)) np->scsi_mode = (np->sv_stest4 & SMODE); else if (np->features & FE_DIFF) { switch(driver_setup.diff_support) { @@ -5471,7 +5543,8 @@ static int __init ncr_prepare_setting(ncb_p np, ncr_nvram *nvram) i == SCSI_NCR_SYMBIOS_NVRAM ? "Symbios format NVRAM, " : (i == SCSI_NCR_TEKRAM_NVRAM ? "Tekram format NVRAM, " : ""), np->myaddr, - np->minsync < 12 ? 40 : (np->minsync < 25 ? 20 : 10), + np->minsync < 10 ? 80 : + (np->minsync < 12 ? 40 : (np->minsync < 25 ? 20 : 10) ), (np->rv_scntl0 & 0xa) ? ", Parity Checking" : ", NO Parity", (np->rv_stest2 & 0x20) ? ", Differential" : ""); @@ -5864,14 +5937,6 @@ ncr_attach (Scsi_Host_Template *tpnt, int unit, ncr_device *device) ncr_script_copy_and_bind (np, (ncrcmd *) &scripth0, (ncrcmd *) np->scripth0, sizeof(struct scripth)); /* - ** If not 64 bit chip, patch some places in SCRIPTS. - */ - if (!(np->features & FE_64BIT)) { - np->scripth0->swide_fin_32[0] = cpu_to_scr(SCR_JUMP); - np->scripth0->swide_fin_32[1] = - cpu_to_scr(NCB_SCRIPT_PHYS(np, dispatch)); - } - /* ** Patch some variables in SCRIPTS */ np->scripth0->pm0_data_addr[0] = @@ -5879,6 +5944,15 @@ ncr_attach (Scsi_Host_Template *tpnt, int unit, ncr_device *device) np->scripth0->pm1_data_addr[0] = cpu_to_scr(NCB_SCRIPT_PHYS(np, pm1_data)); + /* + ** Patch if not Ultra 3 - Do not write to scntl4 + */ + if (np->features & FE_ULTRA3) { + np->script0->resel_scntl4[0] = cpu_to_scr(SCR_LOAD_REL (scntl4, 1)); + np->script0->resel_scntl4[1] = cpu_to_scr(offsetof(struct tcb, uval)); + } + + #ifdef SCSI_NCR_PCI_MEM_NOT_SUPPORTED np->scripth0->script0_ba[0] = cpu_to_scr(vtobus(np->script0)); np->scripth0->script0_ba64[0] = cpu_to_scr(vtobus(np->script0)); @@ -5912,7 +5986,7 @@ ncr_attach (Scsi_Host_Template *tpnt, int unit, ncr_device *device) goto attach_error; assert (offsetof(struct lcb, resel_task) == 0); - np->resel_badlun = cpu_to_scr(NCB_SCRIPTH_PHYS(np, bad_identify)); + np->resel_badlun = cpu_to_scr(NCB_SCRIPTH_PHYS(np, resel_bad_lun)); for (i = 0 ; i < 64 ; i++) np->badluntbl[i] = cpu_to_scr(NCB_PHYS(np, resel_badlun)); @@ -5940,6 +6014,15 @@ ncr_attach (Scsi_Host_Template *tpnt, int unit, ncr_device *device) cpu_to_scr(SCR_REG_REG(gpreg, SCR_AND, 0xfe)); } + /* + ** Patch the script to provide an extra clock cycle on + ** data out phase - 53C1010_66MHz part only. + */ + if (np->device_id == PCI_DEVICE_ID_LSI_53C1010_66){ + np->script0->datao_phase[0] = + cpu_to_scr(SCR_REG_REG(scntl4, SCR_OR, 0x0c)); + } + #ifdef SCSI_NCR_IARB_SUPPORT /* ** If user does not want to use IMMEDIATE ARBITRATION @@ -5968,8 +6051,11 @@ ncr_attach (Scsi_Host_Template *tpnt, int unit, ncr_device *device) #else #define XXX 2 #endif - np->script0->dataphase[XXX] = cpu_to_scr(SCR_JUMP); - np->script0->dataphase[XXX+1] = + np->script0->datai_phase[XXX] = cpu_to_scr(SCR_JUMP); + np->script0->datai_phase[XXX+1] = + cpu_to_scr(NCB_SCRIPTH_PHYS (np, tweak_pmj)); + np->script0->datao_phase[0] = cpu_to_scr(SCR_JUMP); + np->script0->datao_phase[1] = cpu_to_scr(NCB_SCRIPTH_PHYS (np, tweak_pmj)); #undef XXX } @@ -5985,6 +6071,9 @@ ncr_attach (Scsi_Host_Template *tpnt, int unit, ncr_device *device) ** We should use ncr_soft_reset(), but we donnot want to do ** so, since we may not be safe if ABRT interrupt occurs due ** to the BIOS or previous O/S having enable this interrupt. + ** + ** For C1010 need to set ABRT bit prior to SRST if SCRIPTs + ** are running. Not true in this case. */ ncr_chip_reset(np); @@ -6089,6 +6178,19 @@ ncr_attach (Scsi_Host_Template *tpnt, int unit, ncr_device *device) instance->dma_channel = 0; instance->cmd_per_lun = MAX_TAGS; instance->can_queue = (MAX_START-4); + + np->check_integrity = 0; + +#ifdef SCSI_NCR_INTEGRITY_CHECKING + instance->check_integrity = 0; + +#ifdef SCSI_NCR_ENABLE_INTEGRITY_CHECK + if ( !(driver_setup.bus_check & 0x04) ) { + np->check_integrity = 1; + instance->check_integrity = 1; + } +#endif +#endif instance->select_queue_depths = sym53c8xx_select_queue_depths; @@ -6214,6 +6316,299 @@ static inline void ncr_flush_done_cmds(Scsi_Cmnd *lcmd) /*========================================================== ** ** +** Prepare the next negotiation message for integrity check, +** if needed. +** +** Fill in the part of message buffer that contains the +** negotiation and the nego_status field of the CCB. +** Returns the size of the message in bytes. +** +** If tp->ppr_negotiation is 1 and a M_REJECT occurs, then +** we disable ppr_negotiation. If the first ppr_negotiation is +** successful, set this flag to 2. +** +**========================================================== +*/ +#ifdef SCSI_NCR_INTEGRITY_CHECKING +static int ncr_ic_nego(ncb_p np, ccb_p cp, Scsi_Cmnd *cmd, u_char *msgptr) +{ + tcb_p tp = &np->target[cp->target]; + int msglen = 0; + int nego = 0; + u_char new_width, new_offset, new_period; + u_char no_increase; + + if (tp->ppr_negotiation == 1) /* PPR message successful */ + tp->ppr_negotiation = 2; + + if (tp->inq_done) { + + if (!tp->ic_maximums_set) { + tp->ic_maximums_set = 1; + + /* + * Check against target, host and user limits + */ + if ( (tp->inq_byte7 & INQ7_WIDE16) && + np->maxwide && tp->usrwide) + tp->ic_max_width = 1; + else + tp->ic_max_width = 0; + + + if ((tp->inq_byte7 & INQ7_SYNC) && tp->maxoffs) + tp->ic_min_sync = (tp->minsync < np->minsync) ? + np->minsync : tp->minsync; + else + tp->ic_min_sync = 255; + + tp->period = 1; + tp->widedone = 1; + + /* + * Enable PPR negotiation - only if Ultra3 support + * is accessible. + */ + +#if 0 + if (tp->ic_max_width && (tp->ic_min_sync != 255 )) + tp->ppr_negotiation = 1; +#endif + tp->ppr_negotiation = 0; + if (np->features & FE_ULTRA3) { + if (tp->ic_max_width && (tp->ic_min_sync == 0x09)) + tp->ppr_negotiation = 1; + } + + if (!tp->ppr_negotiation) + cmd->ic_nego &= ~NS_PPR; + } + + if (DEBUG_FLAGS & DEBUG_IC) { + printk("%s: cmd->ic_nego %d, 1st byte 0x%2X\n", + ncr_name(np), cmd->ic_nego, cmd->cmnd[0]); + } + + /* Previous command recorded a parity or an initiator + * detected error condition. Force bus to narrow for this + * target. Clear flag. Negotation on request sense. + * Note: kernel forces 2 bus resets :o( but clears itself out. + * Minor bug? in scsi_obsolete.c (ugly) + */ + if (np->check_integ_par) { + printk("%s: Parity Error. Target set to narrow.\n", + ncr_name(np)); + tp->ic_max_width = 0; + tp->widedone = tp->period = 0; + } + + /* Initializing: + * If ic_nego == NS_PPR, we are in the initial test for + * PPR messaging support. If driver flag is clear, then + * either we don't support PPR nego (narrow or async device) + * or this is the second TUR and we have had a M. REJECT + * or unexpected disconnect on the first PPR negotiation. + * Do not negotiate, reset nego flags (in case a reset has + * occurred), clear ic_nego and return. + * General case: Kernel will clear flag on a fallback. + * Do only SDTR or WDTR in the future. + */ + if (!tp->ppr_negotiation && (cmd->ic_nego == NS_PPR )) { + tp->ppr_negotiation = 0; + cmd->ic_nego &= ~NS_PPR; + tp->widedone = tp->period = 1; + return msglen; + } + else if (( tp->ppr_negotiation && !(cmd->ic_nego & NS_PPR )) || + (!tp->ppr_negotiation && (cmd->ic_nego & NS_PPR )) ) { + tp->ppr_negotiation = 0; + cmd->ic_nego &= ~NS_PPR; + } + + /* + * Always check the PPR nego. flag bit if ppr_negotiation + * is set. If the ic_nego PPR bit is clear, + * there must have been a fallback. Do only + * WDTR / SDTR in the future. + */ + if ((tp->ppr_negotiation) && (!(cmd->ic_nego & NS_PPR))) + tp->ppr_negotiation = 0; + + /* In case of a bus reset, ncr_negotiate will reset + * the flags tp->widedone and tp->period to 0, forcing + * a new negotiation. Do WDTR then SDTR. If PPR, do both. + * Do NOT increase the period. It is possible for the Scsi_Cmnd + * flags to be set to increase the period when a bus reset + * occurs - we don't want to change anything. + */ + + no_increase = 0; + + if (tp->ppr_negotiation && (!tp->widedone) && (!tp->period) ) { + cmd->ic_nego = NS_PPR; + tp->widedone = tp->period = 1; + no_increase = 1; + } + else if (!tp->widedone) { + cmd->ic_nego = NS_WIDE; + tp->widedone = 1; + no_increase = 1; + } + else if (!tp->period) { + cmd->ic_nego = NS_SYNC; + tp->period = 1; + no_increase = 1; + } + + new_width = cmd->ic_nego_width & tp->ic_max_width; + + switch (cmd->ic_nego_sync) { + case 2: /* increase the period */ + if (!no_increase) { + if (tp->ic_min_sync <= 0x09) + tp->ic_min_sync = 0x0A; + else if (tp->ic_min_sync <= 0x0A) + tp->ic_min_sync = 0x0C; + else if (tp->ic_min_sync <= 0x0C) + tp->ic_min_sync = 0x19; + else if (tp->ic_min_sync <= 0x19) + tp->ic_min_sync *= 2; + else { + tp->ic_min_sync = 255; + cmd->ic_nego_sync = 0; + tp->maxoffs = 0; + } + } + new_period = tp->maxoffs?tp->ic_min_sync:0; + new_offset = tp->maxoffs; + break; + + case 1: /* nego. to maximum */ + new_period = tp->maxoffs?tp->ic_min_sync:0; + new_offset = tp->maxoffs; + break; + + case 0: /* nego to async */ + default: + new_period = 0; + new_offset = 0; + break; + }; + + + nego = NS_NOCHANGE; + if (tp->ppr_negotiation) { + u_char options_byte = 0; + + /* + ** Must make sure data is consistent. + ** If period is 9 and sync, must be wide and DT bit set. + ** else period must be larger. If the width is 0, + ** reset bus to wide but increase the period to 0x0A. + ** Note: The strange else clause is due to the integrity check. + ** If fails at 0x09, wide, the I.C. code will redo at the same + ** speed but a narrow bus. The driver must take care of slowing + ** the bus speed down. + ** + ** The maximum offset in ST mode is 31, in DT mode 62 (1010/1010_66 only) + */ + if ( (new_period==0x09) && new_offset) { + if (new_width) + options_byte = 0x02; + else { + tp->ic_min_sync = 0x0A; + new_period = 0x0A; + cmd->ic_nego_width = 1; + new_width = 1; + new_offset &= 0x1f; + } + } + else if (new_period > 0x09) + new_offset &= 0x1f; + + nego = NS_PPR; + + msgptr[msglen++] = M_EXTENDED; + msgptr[msglen++] = 6; + msgptr[msglen++] = M_X_PPR_REQ; + msgptr[msglen++] = new_period; + msgptr[msglen++] = 0; + msgptr[msglen++] = new_offset; + msgptr[msglen++] = new_width; + msgptr[msglen++] = options_byte; + + } + else { + switch (cmd->ic_nego & ~NS_PPR) { + case NS_WIDE: + /* + ** WDTR negotiation on if device supports + ** wide or if wide device forced narrow + ** due to a parity error. + */ + + cmd->ic_nego_width &= tp->ic_max_width; + + if (tp->ic_max_width | np->check_integ_par) { + nego = NS_WIDE; + msgptr[msglen++] = M_EXTENDED; + msgptr[msglen++] = 2; + msgptr[msglen++] = M_X_WIDE_REQ; + msgptr[msglen++] = new_width; + } + break; + + case NS_SYNC: + /* + ** negotiate synchronous transfers + ** Target must support sync transfers. + ** Min. period = 0x0A, maximum offset of 31=0x1f. + */ + + if (tp->inq_byte7 & INQ7_SYNC) { + + if (new_offset && (new_period < 0x0A)) { + tp->ic_min_sync = 0x0A; + new_period = 0x0A; + } + nego = NS_SYNC; + msgptr[msglen++] = M_EXTENDED; + msgptr[msglen++] = 3; + msgptr[msglen++] = M_X_SYNC_REQ; + msgptr[msglen++] = new_period; + msgptr[msglen++] = new_offset & 0x1f; + } + else + cmd->ic_nego_sync = 0; + break; + + case NS_NOCHANGE: + break; + } + } + + }; + + cp->nego_status = nego; + np->check_integ_par = 0; + + if (nego) { + tp->nego_cp = cp; + if (DEBUG_FLAGS & DEBUG_NEGO) { + ncr_print_msg(cp, nego == NS_WIDE ? + "wide/narrow msgout": + (nego == NS_SYNC ? "sync/async msgout" : "ppr msgout"), + msgptr); + }; + }; + + return msglen; +} +#endif /* SCSI_NCR_INTEGRITY_CHECKING */ + +/*========================================================== +** +** ** Prepare the next negotiation message if needed. ** ** Fill in the part of message buffer that contains the @@ -6224,13 +6619,42 @@ static inline void ncr_flush_done_cmds(Scsi_Cmnd *lcmd) **========================================================== */ + static int ncr_prepare_nego(ncb_p np, ccb_p cp, u_char *msgptr) { tcb_p tp = &np->target[cp->target]; int msglen = 0; int nego = 0; + u_char width, offset, factor, last_byte; + + if (!np->check_integrity) { + /* If integrity checking disabled, enable PPR messaging + * if device supports wide, sync and ultra 3 + */ + if (tp->ppr_negotiation == 1) /* PPR message successful */ + tp->ppr_negotiation = 2; + + if ((tp->inq_done) && (!tp->ic_maximums_set)) { + tp->ic_maximums_set = 1; + + /* + * Issue PPR only if board is capable + * and set-up for Ultra3 transfers. + */ + tp->ppr_negotiation = 0; + if ( (np->features & FE_ULTRA3) && + (tp->usrwide) && (tp->maxoffs) && + (tp->minsync == 0x09) ) + tp->ppr_negotiation = 1; + } + } if (tp->inq_done) { + /* + * Get the current width, offset and period + */ + ncr_get_xfer_info( np, tp, &factor, + &offset, &width); /* ** negotiate wide transfers ? @@ -6238,19 +6662,50 @@ static int ncr_prepare_nego(ncb_p np, ccb_p cp, u_char *msgptr) if (!tp->widedone) { if (tp->inq_byte7 & INQ7_WIDE16) { - nego = NS_WIDE; + if (tp->ppr_negotiation) + nego = NS_PPR; + else + nego = NS_WIDE; + + width = tp->usrwide; +#ifdef SCSI_NCR_INTEGRITY_CHECKING + if (tp->ic_done) + width &= tp->ic_max_width; +#endif } else tp->widedone=1; + }; /* ** negotiate synchronous transfers? */ - if (!nego && !tp->period) { + if ((nego != NS_WIDE) && !tp->period) { if (tp->inq_byte7 & INQ7_SYNC) { - nego = NS_SYNC; + if (tp->ppr_negotiation) + nego = NS_PPR; + else + nego = NS_SYNC; + + /* Check for async flag */ + if (tp->maxoffs == 0) { + offset = 0; + factor = 0; + } + else { + offset = tp->maxoffs; + factor = tp->minsync; +#ifdef SCSI_NCR_INTEGRITY_CHECKING + if ((tp->ic_done) && + (factor < tp->ic_min_sync)) + factor = tp->ic_min_sync; +#endif + } + } else { + offset = 0; + factor = 0; tp->period =0xffff; PRINT_TARGET(np, cp->target); printk ("target did not report SYNC.\n"); @@ -6259,18 +6714,54 @@ static int ncr_prepare_nego(ncb_p np, ccb_p cp, u_char *msgptr) }; switch (nego) { + case NS_PPR: + /* + ** Must make sure data is consistent. + ** If period is 9 and sync, must be wide and DT bit set + ** else period must be larger. + ** Maximum offset is 31=0x1f is ST mode, 62 if DT mode + */ + last_byte = 0; + if ( (factor==9) && offset) { + if (!width) { + factor = 0x0A; + offset &= 0x1f; + } + else + last_byte = 0x02; + } + else if (factor > 0x09) + offset &= 0x1f; + + msgptr[msglen++] = M_EXTENDED; + msgptr[msglen++] = 6; + msgptr[msglen++] = M_X_PPR_REQ; + msgptr[msglen++] = factor; + msgptr[msglen++] = 0; + msgptr[msglen++] = offset; + msgptr[msglen++] = width; + msgptr[msglen++] = last_byte; + break; case NS_SYNC: + /* + ** Never negotiate faster than Ultra 2 (25ns periods) + */ + if (offset && (factor < 0x0A)) { + factor = 0x0A; + tp->minsync = 0x0A; + } + msgptr[msglen++] = M_EXTENDED; msgptr[msglen++] = 3; msgptr[msglen++] = M_X_SYNC_REQ; - msgptr[msglen++] = tp->maxoffs ? tp->minsync : 0; - msgptr[msglen++] = tp->maxoffs; + msgptr[msglen++] = factor; + msgptr[msglen++] = offset & 0x1f; break; case NS_WIDE: msgptr[msglen++] = M_EXTENDED; msgptr[msglen++] = 2; msgptr[msglen++] = M_X_WIDE_REQ; - msgptr[msglen++] = tp->usrwide; + msgptr[msglen++] = width; break; }; @@ -6280,7 +6771,9 @@ static int ncr_prepare_nego(ncb_p np, ccb_p cp, u_char *msgptr) tp->nego_cp = cp; if (DEBUG_FLAGS & DEBUG_NEGO) { ncr_print_msg(cp, nego == NS_WIDE ? - "wide msgout":"sync_msgout", msgptr); + "wide msgout": + (nego == NS_SYNC ? "sync msgout" : "ppr msgout"), + msgptr); }; }; @@ -6464,6 +6957,73 @@ static int ncr_queue_command (ncb_p np, Scsi_Cmnd *cmd) cp->segments = 0; } + /*--------------------------------------------------- + ** + ** negotiation required? + ** + ** (nego_status is filled by ncr_prepare_nego()) + ** + **--------------------------------------------------- + */ + + cp->nego_status = 0; + +#ifdef SCSI_NCR_INTEGRITY_CHECKING + if ((np->check_integrity && tp->ic_done) || !np->check_integrity) { + if ((!tp->widedone || !tp->period) && !tp->nego_cp && lp) { + msglen += ncr_prepare_nego (np, cp, msgptr + msglen); + } + } + else if (np->check_integrity && (cmd->ic_in_progress)) { + msglen += ncr_ic_nego (np, cp, cmd, msgptr + msglen); + } + else if (np->check_integrity && cmd->ic_complete) { + u_long current_period; + u_char current_offset, current_width, current_factor; + + ncr_get_xfer_info (np, tp, ¤t_factor, + ¤t_offset, ¤t_width); + + tp->ic_max_width = current_width; + tp->ic_min_sync = current_factor; + + if (current_factor == 9) current_period = 125; + else if (current_factor == 10) current_period = 250; + else if (current_factor == 11) current_period = 303; + else if (current_factor == 12) current_period = 500; + else current_period = current_factor * 40; + + /* + * Negotiation for this target is complete. Update flags. + */ + tp->period = current_period; + tp->widedone = 1; + tp->ic_done = 1; + + printk("%s: Integrity Check Complete: \n", ncr_name(np)); + + printk("%s: %s %s SCSI", ncr_name(np), + current_offset?"SYNC":"ASYNC", + tp->ic_max_width?"WIDE":"NARROW"); + if (current_offset) { + u_long mbs = 10000 * (tp->ic_max_width + 1); + + printk(" %d.%d MB/s", + (int) (mbs / current_period), (int) (mbs % current_period)); + + printk(" (%d ns, %d offset)\n", + (int) current_period/10, current_offset); + } + else + printk(" %d MB/s. \n ", (tp->ic_max_width+1)*5); + } +#else + if ((!tp->widedone || !tp->period) && !tp->nego_cp && lp) { + msglen += ncr_prepare_nego (np, cp, msgptr + msglen); + } +#endif /* SCSI_NCR_INTEGRITY_CHECKING */ + + /*---------------------------------------------------- ** ** Determine xfer direction. @@ -6524,19 +7084,6 @@ static int ncr_queue_command (ncb_p np, Scsi_Cmnd *cmd) cp->startp = cp->phys.header.savep; cp->lastp0 = cp->phys.header.lastp; - /*--------------------------------------------------- - ** - ** negotiation required? - ** - ** (nego_status is filled by ncr_prepare_nego()) - ** - **--------------------------------------------------- - */ - - cp->nego_status = 0; - if ((!tp->widedone || !tp->period) && !tp->nego_cp && lp) - msglen += ncr_prepare_nego (np, cp, msgptr + msglen); - /*---------------------------------------------------- ** ** fill in ccb @@ -6559,6 +7106,7 @@ static int ncr_queue_command (ncb_p np, Scsi_Cmnd *cmd) cp->phys.select.sel_id = cp->target; cp->phys.select.sel_scntl3 = tp->wval; cp->phys.select.sel_sxfer = tp->sval; + cp->phys.select.sel_scntl4 = tp->uval; /* ** message */ @@ -7091,6 +7639,14 @@ void ncr_complete (ncb_p np, ccb_p cp) PRINT_ADDR(cmd); printk ("illegal scsi phase (4/5).\n"); } + if (cp->xerr_status & XE_SODL_UNRUN) { + PRINT_ADDR(cmd); + printk ("ODD transfer in DATA OUT phase.\n"); + } + if (cp->xerr_status & XE_SWIDE_OVRUN){ + PRINT_ADDR(cmd); + printk ("ODD transfer in DATA IN phase.\n"); + } if (cp->host_status==HS_COMPLETE) cp->host_status = HS_FAIL; @@ -7167,6 +7723,12 @@ void ncr_complete (ncb_p np, ccb_p cp) PRINT_ADDR(cmd); ncr_printl_hex("sense data:", cmd->sense_buffer, 14); } + } else if ((cp->host_status == HS_COMPLETE) + && (cp->scsi_status == S_CONFLICT)) { + /* + ** Reservation Conflict condition code + */ + SetScsiResult(cmd, DID_OK, S_CONFLICT); } else if ((cp->host_status == HS_COMPLETE) && (cp->scsi_status == S_BUSY || @@ -7418,7 +7980,11 @@ void ncr_init (ncb_p np, int reset, char * msg, u_long code) OUTB (nc_ctest3, np->rv_ctest3); /* Write and invalidate */ OUTB (nc_ctest4, np->rv_ctest4); /* Master parity checking */ - OUTB (nc_stest2, EXT|np->rv_stest2); /* Extended Sreq/Sack filtering */ + if ((np->device_id != PCI_DEVICE_ID_LSI_53C1010) && + (np->device_id != PCI_DEVICE_ID_LSI_53C1010_66)){ + OUTB (nc_stest2, EXT|np->rv_stest2); + /* Extended Sreq/Sack filtering, not supported in C1010/C1010_66 */ + } OUTB (nc_stest3, TE); /* TolerANT enable */ OUTB (nc_stime0, 0x0c); /* HTH disabled STO 0.25 sec */ @@ -7427,14 +7993,24 @@ void ncr_init (ncb_p np, int reset, char * msg, u_long code) ** Disable overlapped arbitration for all dual-function ** devices, regardless revision id. ** We may consider it is a post-chip-design feature. ;-) + ** + ** Errata applies to all 896 and 1010 parts. */ if (np->device_id == PCI_DEVICE_ID_NCR_53C875) OUTB (nc_ctest0, (1<<5)); - else if (np->device_id == PCI_DEVICE_ID_NCR_53C896) + else if (np->device_id == PCI_DEVICE_ID_NCR_53C896 || + np->device_id == PCI_DEVICE_ID_LSI_53C1010 || + np->device_id == PCI_DEVICE_ID_LSI_53C1010_66 ) np->rv_ccntl0 |= DPR; /* - ** If 64 bit (895A/896/1010) write the CCNTL1 register to + ** C1010_66MHz rev 0 part requies AIPCNTL1 bit 3 to be set. + */ + if (np->device_id == PCI_DEVICE_ID_LSI_53C1010_66) + OUTB(nc_aipcntl1, (1<<3)); + + /* + ** If 64 bit (895A/896/1010/1010_66) write the CCNTL1 register to ** enable 40 bit address table indirect addressing for MOVE. ** Also write CCNTL0 if 64 bit chip, since this register seems ** to only be used by 64 bit cores. @@ -7445,8 +8021,8 @@ void ncr_init (ncb_p np, int reset, char * msg, u_long code) } /* - ** If phase mismatch handled by scripts (53C895A or 53C896), - ** set PM jump addresses. + ** If phase mismatch handled by scripts (53C895A or 53C896 + ** or 53C1010 or 53C1010_66), set PM jump addresses. */ if (np->features & FE_NOPM) { @@ -7475,9 +8051,10 @@ void ncr_init (ncb_p np, int reset, char * msg, u_long code) OUTB (nc_dien , MDPE|BF|SSI|SIR|IID); /* - ** For 895/6 enable SBMC interrupt and save current SCSI bus mode. + ** For 895/895A/896/c1010 + ** Enable SBMC interrupt and save current SCSI bus mode. */ - if (np->features & FE_ULTRA2) { + if ( (np->features & FE_ULTRA2) || (np->features & FE_ULTRA3) ) { OUTONW (nc_sien, SBMC); np->scsi_mode = INB (nc_stest4) & SMODE; } @@ -7496,6 +8073,7 @@ void ncr_init (ncb_p np, int reset, char * msg, u_long code) tp->sval = 0; tp->wval = np->rv_scntl3; + tp->uval = np->rv_scntl4; if (tp->usrsync != 255) { if (tp->usrsync <= np->maxsync) { @@ -7626,6 +8204,10 @@ static void ncr_getsync(ncb_p np, u_char sfac, u_char *fakp, u_char *scntl3p) /* ** Compute the synchronous period in tenths of nano-seconds + ** from sfac. + ** + ** Note, if sfac == 9, DT is being used. Double the period of 125 + ** to 250. */ if (sfac <= 10) per = 250; else if (sfac == 11) per = 303; @@ -7673,7 +8255,76 @@ static void ncr_getsync(ncb_p np, u_char sfac, u_char *fakp, u_char *scntl3p) ** Compute and return sync parameters for the ncr */ *fakp = fak - 4; - *scntl3p = ((div+1) << 4) + (sfac < 25 ? 0x80 : 0); + + /* + ** If sfac < 25, and 8xx parts, desire that the chip operate at + ** least at Ultra speeds. Must set bit 7 of scntl3. + ** For C1010, do not set this bit. If operating at Ultra3 speeds, + ** set the U3EN bit instead. + */ + if ((np->device_id == PCI_DEVICE_ID_LSI_53C1010) || + (np->device_id == PCI_DEVICE_ID_LSI_53C1010_66)) { + *scntl3p = (div+1) << 4; + *fakp = 0; + } + else { + *scntl3p = ((div+1) << 4) + (sfac < 25 ? 0x80 : 0); + *fakp = fak - 4; + } +} + +/*========================================================== +** +** Utility routine to return the current bus width +** synchronous period and offset. +** Utilizes target sval, wval and uval +** +**========================================================== +*/ +static void ncr_get_xfer_info(ncb_p np, tcb_p tp, u_char *factor, + u_char *offset, u_char *width) +{ + + u_char idiv; + u_long period; + + *width = (tp->wval & EWS) ? 1 : 0; + + if ((np->device_id == PCI_DEVICE_ID_LSI_53C1010) || + (np->device_id == PCI_DEVICE_ID_LSI_53C1010_66)) + *offset = (tp->sval & 0x3f); + else + *offset = (tp->sval & 0x1f); + + /* + * Midlayer signal to the driver that all of the scsi commands + * for the integrity check have completed. Save the negotiated + * parameters (extracted from sval, wval and uval). + * See ncr_setsync for alg. details. + */ + + idiv = (tp->wval>>4) & 0x07; + + if ( *offset && idiv ) { + if ((np->device_id == PCI_DEVICE_ID_LSI_53C1010) || + (np->device_id == PCI_DEVICE_ID_LSI_53C1010_66)){ + if (tp->uval & 0x80) + period = (2*div_10M[idiv-1])/np->clock_khz; + else + period = (4*div_10M[idiv-1])/np->clock_khz; + } + else + period = (((tp->sval>>5)+4)*div_10M[idiv-1])/np->clock_khz; + } + else + period = 0xffff; + + if (period <= 125) *factor = 9; + else if (period <= 250) *factor = 10; + else if (period <= 303) *factor = 11; + else if (period <= 500) *factor = 12; + else *factor = (period + 40 - 1) / 40; + } @@ -7687,14 +8338,20 @@ static void ncr_getsync(ncb_p np, u_char sfac, u_char *fakp, u_char *scntl3p) static void ncr_set_sync_wide_status (ncb_p np, u_char target) { - ccb_p cp; + ccb_p cp = np->ccbc; tcb_p tp = &np->target[target]; /* ** set actual value and sync_status + ** + ** TEMP register contains current scripts address + ** which is data type/direction/dependent. */ OUTB (nc_sxfer, tp->sval); OUTB (nc_scntl3, tp->wval); + if ((np->device_id == PCI_DEVICE_ID_LSI_53C1010) || + (np->device_id == PCI_DEVICE_ID_LSI_53C1010_66)) + OUTB (nc_scntl4, tp->uval); /* ** patch ALL ccbs of this target. @@ -7706,6 +8363,9 @@ static void ncr_set_sync_wide_status (ncb_p np, u_char target) continue; cp->phys.select.sel_scntl3 = tp->wval; cp->phys.select.sel_sxfer = tp->sval; + if ((np->device_id == PCI_DEVICE_ID_LSI_53C1010) || + (np->device_id == PCI_DEVICE_ID_LSI_53C1010_66)) + cp->phys.select.sel_scntl4 = tp->uval; }; } @@ -7716,11 +8376,13 @@ static void ncr_set_sync_wide_status (ncb_p np, u_char target) **========================================================== */ -static void ncr_setsync (ncb_p np, ccb_p cp, u_char scntl3, u_char sxfer) +static void ncr_setsync (ncb_p np, ccb_p cp, u_char scntl3, u_char sxfer, + u_char scntl4) { tcb_p tp; u_char target = INB (nc_sdid) & 0x0f; u_char idiv; + u_char offset; assert (cp); if (!cp) return; @@ -7729,9 +8391,21 @@ static void ncr_setsync (ncb_p np, ccb_p cp, u_char scntl3, u_char sxfer) tp = &np->target[target]; - if (!scntl3 || !(sxfer & 0x1f)) - scntl3 = np->rv_scntl3; - scntl3 = (scntl3 & 0xf0) | (tp->wval & EWS) | (np->rv_scntl3 & 0x07); + if ((np->device_id == PCI_DEVICE_ID_LSI_53C1010) || + (np->device_id == PCI_DEVICE_ID_LSI_53C1010_66)) { + offset = sxfer & 0x3f; /* bits 5-0 */ + scntl3 = (scntl3 & 0xf0) | (tp->wval & EWS); + scntl4 = (scntl4 & 0x80); + } + else { + offset = sxfer & 0x1f; /* bits 4-0 */ + if (!scntl3 || !offset) + scntl3 = np->rv_scntl3; + + scntl3 = (scntl3 & 0xf0) | (tp->wval & EWS) | + (np->rv_scntl3 & 0x07); + } + /* ** Deduce the value of controller sync period from scntl3. @@ -7739,27 +8413,42 @@ static void ncr_setsync (ncb_p np, ccb_p cp, u_char scntl3, u_char sxfer) */ idiv = ((scntl3 >> 4) & 0x7); - if ((sxfer & 0x1f) && idiv) - tp->period = (((sxfer>>5)+4)*div_10M[idiv-1])/np->clock_khz; + if ( offset && idiv) { + if ((np->device_id == PCI_DEVICE_ID_LSI_53C1010) || + (np->device_id == PCI_DEVICE_ID_LSI_53C1010_66)) { + /* Note: If extra data hold clocks are used, + * the formulas below must be modified. + * When scntl4 == 0, ST mode. + */ + if (scntl4 & 0x80) + tp->period = (2*div_10M[idiv-1])/np->clock_khz; + else + tp->period = (4*div_10M[idiv-1])/np->clock_khz; + } + else + tp->period = (((sxfer>>5)+4)*div_10M[idiv-1])/np->clock_khz; + } else tp->period = 0xffff; + /* ** Stop there if sync parameters are unchanged */ - if (tp->sval == sxfer && tp->wval == scntl3) return; + if (tp->sval == sxfer && tp->wval == scntl3 && tp->uval == scntl4) return; tp->sval = sxfer; tp->wval = scntl3; + tp->uval = scntl4; /* ** Bells and whistles ;-) ** Donnot announce negotiations due to auto-sense, ** unless user really want us to be verbose. :) */ - if (bootverbose < 2 && (cp->host_flags & HF_AUTO_SENSE)) + if ( bootverbose < 2 && (cp->host_flags & HF_AUTO_SENSE)) goto next; PRINT_TARGET(np, target); - if (sxfer & 0x01f) { + if (offset) { unsigned f10 = 100000 << (tp->widedone ? tp->widedone -1 : 0); unsigned mb10 = (f10 + tp->period/2) / tp->period; char *scsi; @@ -7767,19 +8456,23 @@ static void ncr_setsync (ncb_p np, ccb_p cp, u_char scntl3, u_char sxfer) /* ** Disable extended Sreq/Sack filtering */ - if (tp->period <= 2000) OUTOFFB (nc_stest2, EXT); + if ((tp->period <= 2000) && + (np->device_id != PCI_DEVICE_ID_LSI_53C1010) && + (np->device_id != PCI_DEVICE_ID_LSI_53C1010_66)) + OUTOFFB (nc_stest2, EXT); /* ** Bells and whistles ;-) */ - if (tp->period < 500) scsi = "FAST-40"; + if (tp->period < 250) scsi = "FAST-80"; + else 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 = "FAST-5"; printk ("%s %sSCSI %d.%d MB/s (%d ns, offset %d)\n", scsi, tp->widedone > 1 ? "WIDE " : "", - mb10 / 10, mb10 % 10, tp->period / 10, sxfer & 0x1f); + mb10 / 10, mb10 % 10, tp->period / 10, offset); } else printk ("%sasynchronous.\n", tp->widedone > 1 ? "wide " : ""); next: @@ -7790,6 +8483,7 @@ next: ncr_set_sync_wide_status(np, target); } + /*========================================================== ** ** Switch wide mode for current job and it's target @@ -7843,6 +8537,126 @@ static void ncr_setwide (ncb_p np, ccb_p cp, u_char wide, u_char ack) ncr_set_sync_wide_status(np, target); } + +/*========================================================== +** +** Switch sync/wide mode for current job and it's target +** PPR negotiations only +** +**========================================================== +*/ + +static void ncr_setsyncwide (ncb_p np, ccb_p cp, u_char scntl3, u_char sxfer, + u_char scntl4, u_char wide) +{ + tcb_p tp; + u_char target = INB (nc_sdid) & 0x0f; + u_char idiv; + u_char offset; + + assert (cp); + if (!cp) return; + + assert (target == (cp->target & 0xf)); + + tp = &np->target[target]; + tp->widedone = wide+1; + + if ((np->device_id == PCI_DEVICE_ID_LSI_53C1010) || + (np->device_id == PCI_DEVICE_ID_LSI_53C1010_66)) { + offset = sxfer & 0x3f; /* bits 5-0 */ + scntl3 = (scntl3 & 0xf0) | (wide ? EWS : 0); + scntl4 = (scntl4 & 0x80); + } + else { + offset = sxfer & 0x1f; /* bits 4-0 */ + if (!scntl3 || !offset) + scntl3 = np->rv_scntl3; + + scntl3 = (scntl3 & 0xf0) | (wide ? EWS : 0) | + (np->rv_scntl3 & 0x07); + } + + + /* + ** Deduce the value of controller sync period from scntl3. + ** period is in tenths of nano-seconds. + */ + + idiv = ((scntl3 >> 4) & 0x7); + if ( offset && idiv) { + if ((np->device_id == PCI_DEVICE_ID_LSI_53C1010) || + (np->device_id == PCI_DEVICE_ID_LSI_53C1010_66)) { + /* Note: If extra data hold clocks are used, + * the formulas below must be modified. + * When scntl4 == 0, ST mode. + */ + if (scntl4 & 0x80) + tp->period = (2*div_10M[idiv-1])/np->clock_khz; + else + tp->period = (4*div_10M[idiv-1])/np->clock_khz; + } + else + tp->period = (((sxfer>>5)+4)*div_10M[idiv-1])/np->clock_khz; + } + else + tp->period = 0xffff; + + + /* + ** Stop there if sync parameters are unchanged + */ + if (tp->sval == sxfer && tp->wval == scntl3 && tp->uval == scntl4) return; + tp->sval = sxfer; + tp->wval = scntl3; + tp->uval = scntl4; + + /* + ** Bells and whistles ;-) + ** Donnot announce negotiations due to auto-sense, + ** unless user really want us to be verbose. :) + */ + if ( bootverbose < 2 && (cp->host_flags & HF_AUTO_SENSE)) + goto next; + PRINT_TARGET(np, target); + if (offset) { + unsigned f10 = 100000 << (tp->widedone ? tp->widedone -1 : 0); + unsigned mb10 = (f10 + tp->period/2) / tp->period; + char *scsi; + + /* + ** Disable extended Sreq/Sack filtering + */ + if ((tp->period <= 2000) && + (np->device_id != PCI_DEVICE_ID_LSI_53C1010) && + (np->device_id != PCI_DEVICE_ID_LSI_53C1010_66)) + OUTOFFB (nc_stest2, EXT); + + /* + ** Bells and whistles ;-) + */ + if (tp->period < 250) scsi = "FAST-80"; + else 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 = "FAST-5"; + + printk ("%s %sSCSI %d.%d MB/s (%d ns, offset %d)\n", scsi, + tp->widedone > 1 ? "WIDE " : "", + mb10 / 10, mb10 % 10, tp->period / 10, offset); + } else + printk ("%sasynchronous.\n", tp->widedone > 1 ? "wide " : ""); +next: + /* + ** set actual value and sync_status + ** patch ALL ccbs of this target. + */ + ncr_set_sync_wide_status(np, target); +} + + + + /*========================================================== ** ** Switch tagged mode for a target. @@ -8452,6 +9266,28 @@ void ncr_exception (ncb_p np) ncr_log_hard_error(np, sist, dstat); + if ((np->device_id == PCI_DEVICE_ID_LSI_53C1010) || + (np->device_id == PCI_DEVICE_ID_LSI_53C1010_66)) { + u_char ctest4_o, ctest4_m; + u_char shadow; + + /* + * Get shadow register data + * Write 1 to ctest4 + */ + ctest4_o = INB(nc_ctest4); + + OUTB(nc_ctest4, ctest4_o | 0x10); + + ctest4_m = INB(nc_ctest4); + shadow = INW_OFF(0x42); + + OUTB(nc_ctest4, ctest4_o); + + printk("%s: ctest4/sist original 0x%x/0x%X mod: 0x%X/0x%x\n", + ncr_name(np), ctest4_o, sist, ctest4_m, shadow); + } + if ((sist & (GEN|HTH|SGE)) || (dstat & (MDPE|BF|ABRT|IID))) { ncr_start_reset(np); @@ -8577,6 +9413,20 @@ void ncr_int_sto (ncb_p np) */ void ncr_int_udc (ncb_p np) { + u_int32 dsa = INL (nc_dsa); + ccb_p cp = ncr_ccb_from_dsa(np, dsa); + tcb_p tp = &np->target[cp->target]; + + /* + * Fix Up. Some disks respond to a PPR negotation with + * a bus free instead of a message reject. + * Disable ppr negotiation if this is first time + * tried ppr negotiation. + */ + + if (tp->ppr_negotiation == 1) + tp->ppr_negotiation = 0; + printk ("%s: unexpected disconnect\n", ncr_name(np)); ncr_recover_scsi_int(np, HS_UNEXPECTED); } @@ -8688,6 +9538,7 @@ static void ncr_int_par (ncb_p np, u_short sist) /* ** Keep track of the parity error. */ + OUTONB (HF_PRT, HF_EXT_ERR); cp->xerr_status |= XE_PARITY_ERR; /* @@ -8695,14 +9546,22 @@ static void ncr_int_par (ncb_p np, u_short sist) */ np->msgout[0] = (phase == 7) ? M_PARITY : M_ID_ERROR; +#ifdef SCSI_NCR_INTEGRITY_CHECKING /* - ** If the old phase was DATA IN phase, we have to deal with - ** the 3 situations described above. + ** Save error message. For integrity check use only. + */ + if (np->check_integrity) + np->check_integ_par = np->msgout[0]; +#endif + + /* + ** If the old phase was DATA IN or DT DATA IN phase, + ** we have to deal with the 3 situations described above. ** For other input phases (MSG IN and STATUS), the device ** must resend the whole thing that failed parity checking ** or signal error. So, jumping to dispatcher should be OK. */ - if (phase == 1) { + if ((phase == 1) || (phase == 5)) { /* Phase mismatch handled by SCRIPTS */ if (dsp == NCB_SCRIPTH_PHYS (np, pm_handle)) OUTL (nc_dsp, dsp); @@ -8772,45 +9631,64 @@ static void ncr_int_ma (ncb_p np) */ cp = ncr_ccb_from_dsa(np, dsa); + if (DEBUG_FLAGS & DEBUG_PHASE) + printk("CCB = %2x %2x %2x %2x %2x %2x\n", + cp->cmd->cmnd[0], cp->cmd->cmnd[1], cp->cmd->cmnd[2], + cp->cmd->cmnd[3], cp->cmd->cmnd[4], cp->cmd->cmnd[5]); + /* ** Donnot take into account dma fifo and various buffers in ** INPUT phase since the chip flushes everything before ** raising the MA interrupt for interrupted INPUT phases. ** For DATA IN phase, we will check for the SWIDE later. */ - if ((cmd & 7) != 1) { + if ( !(((cmd & 7) == 1) || ((cmd & 7) == 5) ) ) { u_int32 dfifo; u_char ss0, ss2; /* - ** Read DFIFO, CTEST[4-6] using 1 PCI bus ownership. + ** If C1010, DFBC contains number of bytes in DMA fifo. + ** else read DFIFO, CTEST[4-6] using 1 PCI bus ownership. */ - dfifo = INL(nc_dfifo); + if ((np->device_id == PCI_DEVICE_ID_LSI_53C1010) || + (np->device_id == PCI_DEVICE_ID_LSI_53C1010_66)) + delta = INL(nc_dfbc) & 0xffff; + else { + dfifo = INL(nc_dfifo); - /* - ** Calculate remaining bytes in DMA fifo. - ** (CTEST5 = dfifo >> 16) - */ - if (dfifo & (DFS << 16)) - delta = ((((dfifo >> 8) & 0x300) | - (dfifo & 0xff)) - rest) & 0x3ff; - else - delta = ((dfifo & 0xff) - rest) & 0x7f; + /* + ** Calculate remaining bytes in DMA fifo. + ** C1010 - always large fifo, value in dfbc + ** Otherwise, (CTEST5 = dfifo >> 16) + */ + if (dfifo & (DFS << 16)) + delta = ((((dfifo >> 8) & 0x300) | + (dfifo & 0xff)) - rest) & 0x3ff; + else + delta = ((dfifo & 0xff) - rest) & 0x7f; - /* - ** The data in the dma fifo has not been transfered to - ** the target -> add the amount to the rest - ** and clear the data. - ** Check the sstat2 register in case of wide transfer. - */ + /* + ** The data in the dma fifo has not been + ** transferred to the target -> add the amount + ** to the rest and clear the data. + ** Check the sstat2 register in case of wide + ** transfer. + */ + + } + rest += delta; ss0 = INB (nc_sstat0); if (ss0 & OLF) rest++; - if (ss0 & ORF) rest++; + if ((np->device_id != PCI_DEVICE_ID_LSI_53C1010) && + (np->device_id != PCI_DEVICE_ID_LSI_53C1010_66) && (ss0 & ORF)) + rest++; if (cp && (cp->phys.select.sel_scntl3 & EWS)) { ss2 = INB (nc_sstat2); if (ss2 & OLF1) rest++; - if (ss2 & ORF1) rest++; + if ((np->device_id != PCI_DEVICE_ID_LSI_53C1010) && + (np->device_id != PCI_DEVICE_ID_LSI_53C1010_66) && (ss2 & ORF)) + rest++; }; /* @@ -8902,9 +9780,10 @@ static void ncr_int_ma (ncb_p np) /* ** if old phase not dataphase, leave here. + ** C/D line is low if data. */ - if (cmd & 0x06) { + if (cmd & 0x02) { PRINT_ADDR(cp->cmd); printk ("phase change %x-%x %d@%08x resid=%d.\n", cmd&7, INB(nc_sbcl)&7, (unsigned)olen, @@ -8962,45 +9841,42 @@ static void ncr_int_ma (ncb_p np) ** - move current data pointer context by one byte. */ nxtdsp = NCB_SCRIPT_PHYS (np, dispatch); - if ((cmd & 7) == 1 && cp && (cp->phys.select.sel_scntl3 & EWS) && + if ( ((cmd & 7) == 1 || (cmd & 7) == 5) + && cp && (cp->phys.select.sel_scntl3 & EWS) && (INB (nc_scntl2) & WSR)) { + u32 tmp; + +#ifdef SYM_DEBUG_PM_WITH_WSR + PRINT_ADDR(cp); + printf ("MA interrupt with WSR set - " + "pm->sg.addr=%x - pm->sg.size=%d\n", + pm->sg.addr, pm->sg.size); +#endif /* - ** Hmmm... The device may want to also ignore - ** this residue but it must send immediately the - ** appropriate message. We snoop the SCSI BUS - ** and will just throw away this message from - ** SCRIPTS if the SWIDE is to be ignored. - */ - if ((INB (nc_sbcl) & 7) == 7 && - INB (nc_sbdl) == M_IGN_RESIDUE) { - nxtdsp = NCB_SCRIPT_PHYS (np, ign_i_w_r_msg); - } + * Set up the table indirect for the MOVE + * of the residual byte and adjust the data + * pointer context. + */ + tmp = scr_to_cpu(pm->sg.addr); + cp->phys.wresid.addr = cpu_to_scr(tmp); + pm->sg.addr = cpu_to_scr(tmp + 1); + tmp = scr_to_cpu(pm->sg.size); + cp->phys.wresid.size = cpu_to_scr((tmp&0xff000000) | 1); + pm->sg.size = cpu_to_scr(tmp - 1); + /* - ** We must grab the SWIDE. - ** We will use some complex SCRIPTS for that. - */ - else { - OUTL (nc_scratcha, pm->sg.addr); - nxtdsp = NCB_SCRIPTH_PHYS (np, swide_ma_32); - if (np->features & FE_64BIT) { - OUTB (nc_sbr, (pm->sg.size >> 24)); - nxtdsp = NCB_SCRIPTH_PHYS (np, swide_ma_64); - } - /* - ** Adjust our data pointer context. - */ - ++pm->sg.addr; - --pm->sg.size; - /* - ** Hmmm... Could it be possible that a SWIDE that - ** is followed by a 1 byte CHMOV would lead to - ** a CHMOV(0). Anyway, we handle it by just - ** skipping context that would attempt a CHMOV(0). - */ - if (!pm->sg.size) - newcmd = pm->ret; - } - } + * If only the residual byte is to be moved, + * no PM context is needed. + */ + if ((tmp&0xffffff) == 1) + newcmd = pm->ret; + + /* + * Prepare the address of SCRIPTS that will + * move the residual byte to memory. + */ + nxtdsp = NCB_SCRIPTH_PHYS (np, wsr_ma_helper); + } if (DEBUG_FLAGS & DEBUG_PHASE) { PRINT_ADDR(cp->cmd); @@ -9076,7 +9952,8 @@ unexpected_phase: nxtdsp = NCB_SCRIPTH_PHYS (np, ident_break); } else if (dsp == NCB_SCRIPTH_PHYS (np, send_wdtr) || - dsp == NCB_SCRIPTH_PHYS (np, send_sdtr)) { + dsp == NCB_SCRIPTH_PHYS (np, send_sdtr) || + dsp == NCB_SCRIPTH_PHYS (np, send_ppr)) { nxtdsp = NCB_SCRIPTH_PHYS (np, nego_bad_phase); } break; @@ -9277,12 +10154,56 @@ next: ** to be stuck with WIDE and/or SYNC data transfer. ** ** cp->nego_status is filled by ncr_prepare_nego(). + ** + ** Do NOT negotiate if performing integrity check + ** or if integrity check has completed, all check + ** conditions will have been cleared. + */ + +#ifdef SCSI_NCR_INTEGRITY_CHECKING + if (DEBUG_FLAGS & DEBUG_IC) { + printk("%s: ncr_sir_to_redo: ic_done %2X, in_progress %2X\n", + ncr_name(np), tp->ic_done, cp->cmd->ic_in_progress); + } + + /* + ** If parity error during integrity check, + ** set the target width to narrow. Otherwise, + ** do not negotiate on a request sense. */ + if ( np->check_integ_par && np->check_integrity + && cp->cmd->ic_in_progress ) { + cp->nego_status = 0; + msglen += + ncr_ic_nego (np, cp, cmd ,&cp->scsi_smsg2[msglen]); + } + + if (!np->check_integrity || + (np->check_integrity && + (!cp->cmd->ic_in_progress && !tp->ic_done)) ) { + ncr_negotiate(np, tp); + cp->nego_status = 0; + { + u_char sync_offset; + if ((np->device_id == PCI_DEVICE_ID_LSI_53C1010) || + (np->device_id == PCI_DEVICE_ID_LSI_53C1010_66)) + sync_offset = tp->sval & 0x3f; + else + sync_offset = tp->sval & 0x1f; + + if ((tp->wval & EWS) || sync_offset) + msglen += + ncr_prepare_nego (np, cp, &cp->scsi_smsg2[msglen]); + } + + } +#else ncr_negotiate(np, tp); cp->nego_status = 0; if ((tp->wval & EWS) || (tp->sval & 0x1f)) msglen += ncr_prepare_nego (np, cp, &cp->scsi_smsg2[msglen]); +#endif /* SCSI_NCR_INTEGRITY_CHECKING */ /* ** Message table indirect structure. @@ -9489,6 +10410,7 @@ static void ncr_sir_task_recovery(ncb_p np, int num) np->abrt_sel.sel_id = target; np->abrt_sel.sel_scntl3 = tp->wval; np->abrt_sel.sel_sxfer = tp->sval; + np->abrt_sel.sel_scntl4 = tp->uval; OUTL(nc_dsa, np->p_ncb); OUTL (nc_dsp, NCB_SCRIPTH_PHYS (np, sel_for_abort)); return; @@ -9696,6 +10618,7 @@ static void ncr_sir_task_recovery(ncb_p np, int num) if (np->abrt_msg[0] == M_RESET) { tp->sval = 0; tp->wval = np->rv_scntl3; + tp->uval = np->rv_scntl4; ncr_set_sync_wide_status(np, target); ncr_negotiate(np, tp); } @@ -10014,11 +10937,30 @@ out_reject: static int ncr_compute_residual(ncb_p np, ccb_p cp) { - int dp_sg, dp_sgmin, resid, tmp; + int dp_sg, dp_sgmin, tmp; + int resid=0; int dp_ofs = 0; /* - ** Should have been checked by the caller. + * Check for some data lost or just thrown away. + * We are not required to be quite accurate in this + * situation. Btw, if we are odd for output and the + * device claims some more data, it may well happen + * than our residual be zero. :-) + */ + if (cp->xerr_status & (XE_EXTRA_DATA|XE_SODL_UNRUN|XE_SWIDE_OVRUN)) { + if (cp->xerr_status & XE_EXTRA_DATA) + resid -= scr_to_cpu(cp->phys.extra_bytes); + if (cp->xerr_status & XE_SODL_UNRUN) + ++resid; + if (cp->xerr_status & XE_SWIDE_OVRUN) + --resid; + } + + + /* + ** If all data has been transferred, + ** there is no residual. */ if (cp->phys.header.lastp == cp->phys.header.goalp) return 0; @@ -10159,7 +11101,7 @@ static void ncr_print_msg (ccb_p cp, char *label, u_char *msg) */ static void ncr_sync_nego(ncb_p np, tcb_p tp, ccb_p cp) { - u_char scntl3; + u_char scntl3, scntl4; u_char chg, ofs, per, fak; /* @@ -10203,6 +11145,7 @@ static void ncr_sync_nego(ncb_p np, tcb_p tp, ccb_p cp) */ fak = 7; scntl3 = 0; + scntl4 = 0; if (ofs != 0) { ncr_getsync(np, per, &fak, &scntl3); if (fak > 7) { @@ -10214,13 +11157,14 @@ static void ncr_sync_nego(ncb_p np, tcb_p tp, ccb_p cp) fak = 7; per = 0; scntl3 = 0; + scntl4 = 0; tp->minsync = 0; } if (DEBUG_FLAGS & DEBUG_NEGO) { PRINT_ADDR(cp->cmd); - printk ("sync: per=%d scntl3=0x%x ofs=%d fak=%d chg=%d.\n", - per, scntl3, ofs, fak, chg); + printk ("sync: per=%d scntl3=0x%x scntl4=0x%x ofs=%d fak=%d chg=%d.\n", + per, scntl3, scntl4, ofs, fak, chg); } if (INB (HS_PRT) == HS_NEGOTIATE) { @@ -10234,13 +11178,18 @@ static void ncr_sync_nego(ncb_p np, tcb_p tp, ccb_p cp) /* ** Answer wasn't acceptable. */ - ncr_setsync (np, cp, 0, 0xe0); + ncr_setsync (np, cp, 0, 0xe0, 0); OUTL (nc_dsp, NCB_SCRIPTH_PHYS (np, msg_bad)); } else { /* ** Answer is ok. */ - ncr_setsync (np, cp, scntl3, (fak<<5)|ofs); + if ((np->device_id != PCI_DEVICE_ID_LSI_53C1010) && + (np->device_id != PCI_DEVICE_ID_LSI_53C1010_66)) + ncr_setsync (np, cp, scntl3, (fak<<5)|ofs,0); + else + ncr_setsync (np, cp, scntl3, ofs, scntl4); + OUTL (nc_dsp, NCB_SCRIPT_PHYS (np, clrack)); }; return; @@ -10256,7 +11205,11 @@ static void ncr_sync_nego(ncb_p np, tcb_p tp, ccb_p cp) ** prepare an answer message */ - ncr_setsync (np, cp, scntl3, (fak<<5)|ofs); + if ((np->device_id != PCI_DEVICE_ID_LSI_53C1010) && + (np->device_id != PCI_DEVICE_ID_LSI_53C1010_66)) + ncr_setsync (np, cp, scntl3, (fak<<5)|ofs,0); + else + ncr_setsync (np, cp, scntl3, ofs, scntl4); np->msgout[0] = M_EXTENDED; np->msgout[1] = 3; @@ -10350,7 +11303,7 @@ static void ncr_wide_nego(ncb_p np, tcb_p tp, ccb_p cp) return; case NS_SYNC: - ncr_setsync (np, cp, 0, 0xe0); + ncr_setsync (np, cp, 0, 0xe0, 0); break; }; }; @@ -10377,6 +11330,205 @@ static void ncr_wide_nego(ncb_p np, tcb_p tp, ccb_p cp) OUTL (nc_dsp, NCB_SCRIPTH_PHYS (np, wdtr_resp)); } +/*========================================================== +** +** ncr chip handler for PARALLEL PROTOCOL REQUEST +** (PPR) message. +** +**========================================================== +** +** Read comments above. +** +**---------------------------------------------------------- +*/ +static void ncr_ppr_nego(ncb_p np, tcb_p tp, ccb_p cp) +{ + u_char scntl3, scntl4; + u_char chg, ofs, per, fak, wth, dt; + + /* + ** PPR message received. + */ + + if (DEBUG_FLAGS & DEBUG_NEGO) { + ncr_print_msg(cp, "ppr msg in", np->msgin); + }; + + /* + ** get requested values. + */ + + chg = 0; + per = np->msgin[3]; + ofs = np->msgin[5]; + wth = np->msgin[6]; + dt = np->msgin[7]; + if (ofs==0) per=255; + + /* + ** if target sends sync (wide), + ** it CAN transfer synch (wide). + */ + + if (ofs) + tp->inq_byte7 |= INQ7_SYNC; + + if (wth) + tp->inq_byte7 |= INQ7_WIDE16; + + /* + ** check values against driver limits. + */ + + if (wth > tp->usrwide) + {chg = 1; wth = tp->usrwide;} + if (per < np->minsync) + {chg = 1; per = np->minsync;} + if (per < tp->minsync) + {chg = 1; per = tp->minsync;} + if (ofs > tp->maxoffs) + {chg = 1; ofs = tp->maxoffs;} + + /* + ** Check against controller limits. + */ + fak = 7; + scntl3 = 0; + scntl4 = 0; + if (ofs != 0) { + scntl4 = dt ? 0x80 : 0; + ncr_getsync(np, per, &fak, &scntl3); + if (fak > 7) { + chg = 1; + ofs = 0; + } + } + if (ofs == 0) { + fak = 7; + per = 0; + scntl3 = 0; + scntl4 = 0; + tp->minsync = 0; + } + + /* + ** If target responds with Ultra 3 speed + ** but narrow or not DT, reject. + ** If target responds with DT request + ** but not Ultra3 speeds, reject message, + ** reset min sync for target to 0x0A and + ** set flags to re-negotiate. + */ + + if ((per == 0x09) && ofs && (!wth || !dt)) + chg = 1; + else if (( (per > 0x09) && dt) ) + chg = 2; + + + if (DEBUG_FLAGS & DEBUG_NEGO) { + PRINT_ADDR(cp->cmd); + printk ("ppr: wth=%d per=%d scntl3=0x%x scntl4=0x%x ofs=%d fak=%d chg=%d.\n", + wth, per, scntl3, scntl4, ofs, fak, chg); + } + + if (INB (HS_PRT) == HS_NEGOTIATE) { + OUTB (HS_PRT, HS_BUSY); + switch (cp->nego_status) { + case NS_PPR: + /* + ** This was an answer message + */ + if (chg) { + /* + ** Answer wasn't acceptable. + */ + if (chg == 2) { + /* Send message reject and reset flags for + ** host to re-negotiate with min period 0x0A. + */ + tp->minsync = 0x0A; + tp->period = 0; + tp->widedone = 0; + } + ncr_setsyncwide (np, cp, 0, 0xe0, 0, 0); + OUTL (nc_dsp, NCB_SCRIPTH_PHYS (np, msg_bad)); + } else { + /* + ** Answer is ok. + */ + + if ((np->device_id != PCI_DEVICE_ID_LSI_53C1010) && + (np->device_id != PCI_DEVICE_ID_LSI_53C1010_66)) + ncr_setsyncwide (np, cp, scntl3, (fak<<5)|ofs,0, wth); + else + ncr_setsyncwide (np, cp, scntl3, ofs, scntl4, wth); + + OUTL (nc_dsp, NCB_SCRIPT_PHYS (np, clrack)); + + }; + return; + + case NS_SYNC: + ncr_setsync (np, cp, 0, 0xe0, 0); + break; + + case NS_WIDE: + ncr_setwide (np, cp, 0, 0); + break; + }; + }; + + /* + ** It was a request. Set value and + ** prepare an answer message + ** + ** If narrow or not DT and requesting Ultra3 + ** slow the bus down and force ST. If not + ** requesting Ultra3, force ST. + ** Max offset is 31=0x1f if ST mode. + */ + + if ((per == 0x09) && ofs && (!wth || !dt)) { + per = 0x0A; + dt = 0; + ofs &= 0x1f; + } + else if ( (per > 0x09) && dt) { + dt = 0; + ofs &= 0x1f; + } + + if ((np->device_id != PCI_DEVICE_ID_LSI_53C1010) && + (np->device_id != PCI_DEVICE_ID_LSI_53C1010_66)) + ncr_setsyncwide (np, cp, scntl3, (fak<<5)|ofs,0, wth); + else + ncr_setsyncwide (np, cp, scntl3, ofs, scntl4, wth); + + np->msgout[0] = M_EXTENDED; + np->msgout[1] = 6; + np->msgout[2] = M_X_PPR_REQ; + np->msgout[3] = per; + np->msgout[4] = 0; + np->msgout[5] = ofs; + np->msgout[6] = wth; + np->msgout[7] = dt; + + cp->nego_status = NS_PPR; + + if (DEBUG_FLAGS & DEBUG_NEGO) { + ncr_print_msg(cp, "ppr msgout", np->msgout); + } + + np->msgin [0] = M_NOOP; + + if (!ofs) + OUTL (nc_dsp, NCB_SCRIPTH_PHYS (np, msg_bad)); + else + OUTL (nc_dsp, NCB_SCRIPTH_PHYS (np, ppr_resp)); +} + + /* ** Reset SYNC or WIDE to default settings. @@ -10392,13 +11544,45 @@ static void ncr_nego_default(ncb_p np, tcb_p tp, ccb_p cp) switch (cp->nego_status) { case NS_SYNC: - ncr_setsync (np, cp, 0, 0xe0); + ncr_setsync (np, cp, 0, 0xe0, 0); break; case NS_WIDE: ncr_setwide (np, cp, 0, 0); break; + case NS_PPR: + /* + * ppr_negotiation is set to 1 on the first ppr nego command. + * If ppr is successful, it is reset to 2. + * If unsuccessful it is reset to 0. + */ + if (DEBUG_FLAGS & DEBUG_NEGO) { + tcb_p tp=&np->target[cp->target]; + u_char factor, offset, width; + + ncr_get_xfer_info ( np, tp, &factor, &offset, &width); + + printk("Current factor %d offset %d width %d\n", + factor, offset, width); + } + if (tp->ppr_negotiation == 2) + ncr_setsyncwide (np, cp, 0, 0xe0, 0, 0); + else if (tp->ppr_negotiation == 1) { + + /* First ppr command has received a M REJECT. + * Do not change the existing wide/sync parameter + * values (asyn/narrow if this as the first nego; + * may be different if target initiates nego.). + */ + tp->ppr_negotiation = 0; + } + else + { + tp->ppr_negotiation = 0; + ncr_setwide (np, cp, 0, 0); + } + break; }; np->msgin [0] = M_NOOP; np->msgout[0] = M_NOOP; @@ -10410,6 +11594,9 @@ static void ncr_nego_default(ncb_p np, tcb_p tp, ccb_p cp) ** ncr chip handler for MESSAGE REJECT received for ** a WIDE or SYNCHRONOUS negotiation. ** +** clear the PPR negotiation flag, all future nego. +** will be SDTR and WDTR +** **========================================================== ** ** Read comments above. @@ -10451,6 +11638,7 @@ void ncr_int_sir (ncb_p np) case SIR_DUMMY_INTERRUPT: goto out; #endif + /* ** The C code is currently trying to recover from something. ** Typically, user want to abort some command. @@ -10529,8 +11717,11 @@ void ncr_int_sir (ncb_p np) np->msgout[0] = M_NOOP; /* Should we really care of that */ if (np->lastmsg == M_PARITY || np->lastmsg == M_ID_ERROR) { - if (cp) + if (cp) { cp->xerr_status &= ~XE_PARITY_ERR; + if (!cp->xerr_status) + OUTOFFB (HF_PRT, HF_EXT_ERR); + } } goto out; /* @@ -10558,8 +11749,10 @@ void ncr_int_sir (ncb_p np) ** It is a data overrun condition. */ case SIR_SWIDE_OVERRUN: - if (cp) - cp->xerr_status |= XE_EXTRA_DATA; + if (cp) { + OUTONB (HF_PRT, HF_EXT_ERR); + cp->xerr_status |= XE_SWIDE_OVRUN; + } goto out; /* ** We have been ODD at the end of a DATA OUT @@ -10567,8 +11760,10 @@ void ncr_int_sir (ncb_p np) ** It is a data underrun condition. */ case SIR_SODL_UNDERRUN: - if (cp) - cp->xerr_status |= XE_EXTRA_DATA; + if (cp) { + OUTONB (HF_PRT, HF_EXT_ERR); + cp->xerr_status |= XE_SODL_UNRUN; + } goto out; /* ** We received a message. @@ -10597,6 +11792,9 @@ void ncr_int_sir (ncb_p np) case M_X_WIDE_REQ: ncr_wide_nego(np, tp, cp); return; + case M_X_PPR_REQ: + ncr_ppr_nego(np, tp, cp); + return; default: goto out_reject; } @@ -10910,6 +12108,11 @@ static void ncr_init_tcb (ncb_p np, u_char tn) offsetof(struct tcb , sval )) &3) == 0); assert (( (offsetof(struct ncr_reg, nc_scntl3) ^ offsetof(struct tcb , wval )) &3) == 0); + if ((np->device_id == PCI_DEVICE_ID_LSI_53C1010) || + (np->device_id == PCI_DEVICE_ID_LSI_53C1010_66)){ + assert (( (offsetof(struct ncr_reg, nc_scntl4) ^ + offsetof(struct tcb , uval )) &3) == 0); + } } /*------------------------------------------------------------------------ @@ -11446,7 +12649,8 @@ static void ncb_profile (ncb_p np, ccb_p cp) ** do not have a clock doubler and so are provided with a ** 80 MHz clock. All other fast20 boards incorporate a doubler ** and so should be delivered with a 40 MHz clock. -** The recent fast40 chips (895/896/895A) use a 40 Mhz base clock +** The recent fast40 chips (895/896/895A) and the +** fast80 chip (C1010) use a 40 Mhz base clock ** and provide a clock quadrupler (160 Mhz). The code below ** tries to deal as cleverly as possible with all this stuff. ** @@ -11467,14 +12671,20 @@ static void ncr_selectclock(ncb_p np, u_char scntl3) printk ("%s: enabling clock multiplier\n", ncr_name(np)); OUTB(nc_stest1, DBLEN); /* Enable clock multiplier */ - if (np->multiplier > 2) { /* Poll bit 5 of stest4 for quadrupler */ - int i = 20; + + if ( (np->device_id != PCI_DEVICE_ID_LSI_53C1010) && + (np->device_id != PCI_DEVICE_ID_LSI_53C1010_66) && + (np->multiplier > 2)) { + int i = 20; /* Poll bit 5 of stest4 for quadrupler */ while (!(INB(nc_stest4) & LCKFRQ) && --i > 0) UDELAY (20); if (!i) - printk("%s: the chip cannot lock the frequency\n", ncr_name(np)); - } else /* Wait 20 micro-seconds for doubler */ - UDELAY (20); + printk("%s: the chip cannot lock the frequency\n", + ncr_name(np)); + + } else /* Wait 120 micro-seconds for multiplier*/ + UDELAY (120); + OUTB(nc_stest3, HSC); /* Halt the scsi clock */ OUTB(nc_scntl3, scntl3); OUTB(nc_stest1, (DBLEN|DBLSEL));/* Select clock multiplier */ @@ -11489,6 +12699,7 @@ static unsigned __init ncrgetfreq (ncb_p np, int gen) { unsigned int ms = 0; unsigned int f; + int count; /* * Measure GEN timer delay in order @@ -11505,15 +12716,21 @@ static unsigned __init ncrgetfreq (ncb_p np, int gen) * performed trust the higher delay * (lower frequency returned). */ - OUTW (nc_sien , 0); /* mask all scsi interrupts */ + OUTW (nc_sien , 0x0);/* mask all scsi interrupts */ + /* enable general purpose timer */ (void) INW (nc_sist); /* clear pending scsi interrupt */ OUTB (nc_dien , 0); /* mask all dma interrupts */ (void) INW (nc_sist); /* another one, just to be sure :) */ OUTB (nc_scntl3, 4); /* set pre-scaler to divide by 3 */ OUTB (nc_stime1, 0); /* disable general purpose timer */ OUTB (nc_stime1, gen); /* set to nominal delay of 1<<gen * 125us */ - while (!(INW(nc_sist) & GEN) && ms++ < 100000) - UDELAY (1000); /* count ms */ + /* Temporary fix for udelay issue with Alpha + platform */ + while (!(INW(nc_sist) & GEN) && ms++ < 100000) { + /* count 1ms */ + for (count = 0; count < 10; count++) + UDELAY (100); + } OUTB (nc_stime1, 0); /* disable general purpose timer */ /* * set prescaler to divide by whatever 0 means @@ -11524,7 +12741,14 @@ static unsigned __init ncrgetfreq (ncb_p np, int gen) /* * adjust for prescaler, and convert into KHz + * scale values derived empirically. C1010 uses + * different dividers */ +#if 0 + if (np->device_id == PCI_DEVICE_ID_LSI_53C1010) + f = ms ? ((1 << gen) * 2866 ) / ms : 0; + else +#endif f = ms ? ((1 << gen) * 4340) / ms : 0; if (bootverbose >= 2) @@ -11568,11 +12792,19 @@ static void __init ncr_getclock (ncb_p np, int mult) } /* + ** If multiplier not found but a C1010, assume a mult of 4. ** If multiplier not found or scntl3 not 7,5,3, ** reset chip and get frequency from general purpose timer. ** Otherwise trust scntl3 BIOS setting. */ - if (np->multiplier != mult || (scntl3 & 7) < 3 || !(scntl3 & 1)) { + if ((np->device_id == PCI_DEVICE_ID_LSI_53C1010) || + (np->device_id == PCI_DEVICE_ID_LSI_53C1010_66)) { + f1=40000; + np->multiplier = mult; + if (bootverbose >= 2) + printk ("%s: clock multiplier assumed\n", ncr_name(np)); + } + else if (np->multiplier != mult || (scntl3 & 7) < 3 || !(scntl3 & 1)) { OUTB (nc_stest1, 0); /* make sure doubler is OFF */ f1 = ncr_getfreq (np); @@ -11587,8 +12819,14 @@ static void __init ncr_getclock (ncb_p np, int mult) ** to make sure our frequency calculation algorithm ** is not too biased. */ - np->pciclock_min = (33000*55+80-1)/80; - np->pciclock_max = (33000*55)/40; + if (np->features & FE_66MHZ) { + np->pciclock_min = (66000*55+80-1)/80; + np->pciclock_max = (66000*55)/40; + } + else { + np->pciclock_min = (33000*55+80-1)/80; + np->pciclock_max = (33000*55)/40; + } if (f1 == 40000 && mult > 1) { if (bootverbose >= 2) @@ -11728,7 +12966,8 @@ int __init sym53c8xx_setup(char *str) #ifdef SCSI_NCR_BOOT_COMMAND_LINE_SUPPORT char *cur = str; char *pc, *pv; - int i, val, c; + unsigned long val; + int i, c; int xi = 0; while (cur != NULL && (pc = strchr(cur, ':')) != NULL) { @@ -12165,7 +13404,7 @@ next: static int __init sym53c8xx_pci_init(Scsi_Host_Template *tpnt, pcidev_t pdev, ncr_device *device) { - u_short vendor_id, device_id, command; + u_short vendor_id, device_id, command, status_reg; u_char cache_line_size, latency_timer; u_char suggested_cache_line_size = 0; u_char pci_fix_up = driver_setup.pci_fix_up; @@ -12205,6 +13444,7 @@ sym53c8xx_pci_init(Scsi_Host_Template *tpnt, pcidev_t pdev, ncr_device *device) pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision); pci_read_config_byte(pdev, PCI_CACHE_LINE_SIZE, &cache_line_size); pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &latency_timer); + pci_read_config_word(pdev, PCI_STATUS, &status_reg); #ifdef SCSI_NCR_PQS_PDS_SUPPORT /* @@ -12402,16 +13642,53 @@ sym53c8xx_pci_init(Scsi_Host_Template *tpnt, pcidev_t pdev, ncr_device *device) if (driver_setup.special_features & 4) chip->features &= ~FE_NOPM; } + + /* + ** Work around for errant bit in 895A. The 66Mhz + ** capable bit is set erroneously. Clear this bit. + ** (Item 1 DEL 533) + ** + ** Make sure Config space and Features agree. + ** + ** Recall: writes are not normal to status register - + ** write a 1 to clear and a 0 to leave unchanged. + ** Can only reset bits. + */ + if (chip->features & FE_66MHZ) { + if (!(status_reg & PCI_STATUS_66MHZ)) + chip->features &= ~FE_66MHZ; + } + else { + if (status_reg & PCI_STATUS_66MHZ) { + status_reg = PCI_STATUS_66MHZ; + pci_write_config_word(pdev, PCI_STATUS, status_reg); + pci_read_config_word(pdev, PCI_STATUS, &status_reg); + } + } + + if (driver_setup.ultra_scsi < 3 && (chip->features & FE_ULTRA3)) { + chip->features |= FE_ULTRA2; + chip->features &= ~FE_ULTRA3; + } if (driver_setup.ultra_scsi < 2 && (chip->features & FE_ULTRA2)) { chip->features |= FE_ULTRA; chip->features &= ~FE_ULTRA2; } if (driver_setup.ultra_scsi < 1) chip->features &= ~FE_ULTRA; + if (!driver_setup.max_wide) chip->features &= ~FE_WIDE; /* + * C1010 Ultra3 support requires 16 bit data transfers. + */ + if (!driver_setup.max_wide && (chip->features & FE_ULTRA3)) { + chip->features |= FE_ULTRA2; + chip->features |= ~FE_ULTRA3; + } + + /* ** Some features are required to be enabled in order to ** work around some chip problems. :) ;) ** (ITEM 12 of a DEL about the 896 I haven't yet). diff --git a/drivers/scsi/sym53c8xx_comm.h b/drivers/scsi/sym53c8xx_comm.h index 2ffbd6271..703b36c31 100644 --- a/drivers/scsi/sym53c8xx_comm.h +++ b/drivers/scsi/sym53c8xx_comm.h @@ -155,6 +155,7 @@ #define DEBUG_NEGO (0x0200) #define DEBUG_TAGS (0x0400) #define DEBUG_SCATTER (0x0800) +#define DEBUG_IC (0x1000) /* ** Enable/Disable debug messages. @@ -2414,6 +2415,11 @@ sym53c8xx_pci_init(Scsi_Host_Template *tpnt, pcidev_t pdev, ncr_device *device) /* ** Check if the chip is supported */ + if ((device_id == PCI_DEVICE_ID_LSI_53C1010) || + (device_id == PCI_DEVICE_ID_LSI_53C1010_66)){ + printk(NAME53C8XX ": not initializing, device not supported\n"); + return -1; + } chip = 0; for (i = 0; i < sizeof(ncr_chip_table)/sizeof(ncr_chip_table[0]); i++) { if (device_id != ncr_chip_table[i].device_id) diff --git a/drivers/scsi/sym53c8xx_defs.h b/drivers/scsi/sym53c8xx_defs.h index 14ab35a19..0ab0d2745 100644 --- a/drivers/scsi/sym53c8xx_defs.h +++ b/drivers/scsi/sym53c8xx_defs.h @@ -102,6 +102,14 @@ # define SCSI_NCR_USER_INFO_SUPPORT #endif +/* +** To disable integrity checking, do not define the +** following option. +*/ +#ifdef CONFIG_SCSI_NCR53C8XX_INTEGRITY_CHECK +# define SCSI_NCR_ENABLE_INTEGRITY_CHECK +#endif + /*========================================================== ** ** nvram settings - #define SCSI_NCR_NVRAM_SUPPORT to enable @@ -121,10 +129,9 @@ */ /* - * For Ultra2 SCSI support option, use special features and allow 40Mhz - * synchronous data transfers. + * For Ultra2 and Ultra3 SCSI support option, use special features. * - * Value 5 (default) means: + * Value (default) means: * bit 0 : all features enabled, except: * bit 1 : PCI Write And Invalidate. * bit 2 : Data Phase Mismatch handling from SCRIPTS. @@ -133,8 +140,20 @@ * enabled by the driver. */ #define SCSI_NCR_SETUP_SPECIAL_FEATURES (3) -#define SCSI_NCR_SETUP_ULTRA_SCSI (2) -#define SCSI_NCR_MAX_SYNC (40) + +/* + * For Ultra2 and Ultra3 SCSI support allow 80Mhz synchronous data transfers. + * Value means: + * 0 - Ultra speeds disabled + * 1 - Ultra enabled (Maximum 20Mtrans/sec) + * 2 - Ultra2 enabled (Maximum 40Mtrans/sec) + * 3 - Ultra3 enabled (Maximum 80Mtrans/sec) + * + * Use boot options sym53c8xx=ultra:3 to enable Ultra3 support. + */ + +#define SCSI_NCR_SETUP_ULTRA_SCSI (3) +#define SCSI_NCR_MAX_SYNC (80) /* * Allow tags from 2 to 256, default 8 @@ -190,7 +209,7 @@ /* * Sync transfer frequency at startup. - * Allow from 5Mhz to 40Mhz default 20 Mhz. + * Allow from 5Mhz to 80Mhz default 20 Mhz. */ #ifndef CONFIG_SCSI_NCR53C8XX_SYNC #define CONFIG_SCSI_NCR53C8XX_SYNC (20) @@ -207,8 +226,10 @@ #define SCSI_NCR_SETUP_DEFAULT_SYNC (250/(CONFIG_SCSI_NCR53C8XX_SYNC)) #elif CONFIG_SCSI_NCR53C8XX_SYNC <= 33 #define SCSI_NCR_SETUP_DEFAULT_SYNC (11) -#else +#elif CONFIG_SCSI_NCR53C8XX_SYNC <= 40 #define SCSI_NCR_SETUP_DEFAULT_SYNC (10) +#else +#define SCSI_NCR_SETUP_DEFAULT_SYNC (9) #endif /* @@ -469,6 +490,15 @@ #define PCI_DEVICE_ID_NCR_53C1510D 0xa #endif +#ifndef PCI_DEVICE_ID_LSI_53C1010 +#define PCI_DEVICE_ID_LSI_53C1010 0x20 +#endif + +#ifndef PCI_DEVICE_ID_LSI_53C1010_66 +#define PCI_DEVICE_ID_LSI_53C1010_66 0x21 +#endif + + /* ** NCR53C8XX devices features table. */ @@ -502,6 +532,8 @@ typedef struct { #define FE_NOPM (1<<19) /* Scripts handles phase mismatch */ #define FE_LEDC (1<<20) /* Hardware control of LED */ #define FE_DIFF (1<<21) /* Support Differential SCSI */ +#define FE_ULTRA3 (1<<22) /* Ultra-3 80Mtrans/sec */ +#define FE_66MHZ (1<<23) /* 66MHz PCI Support */ #define FE_CACHE_SET (FE_ERL|FE_CLSE|FE_WRIE|FE_ERMP) #define FE_SCSI_SET (FE_WIDE|FE_ULTRA|FE_ULTRA2|FE_DBLR|FE_QUAD|F_CLK80) @@ -586,7 +618,15 @@ typedef struct { , \ {PCI_DEVICE_ID_NCR_53C1510D, 0xff, "1510D", 7, 31, 7, \ FE_WIDE|FE_ULTRA2|FE_QUAD|FE_CACHE_SET|FE_BOF|FE_DFS|FE_LDSTR|FE_PFEN| \ - FE_RAM|FE_IO256}\ + FE_RAM|FE_IO256} \ + , \ + {PCI_DEVICE_ID_LSI_53C1010, 0xff, "1010", 6, 62, 7, \ + FE_WIDE|FE_QUAD|FE_CACHE_SET|FE_BOF|FE_DFS|FE_LDSTR|FE_PFEN| \ + FE_RAM|FE_RAM8K|FE_64BIT|FE_IO256|FE_NOPM|FE_LEDC|FE_ULTRA3} \ + , \ + {PCI_DEVICE_ID_LSI_53C1010_66, 0xff, "1010_66", 6, 62, 7, \ + FE_WIDE|FE_QUAD|FE_CACHE_SET|FE_BOF|FE_DFS|FE_LDSTR|FE_PFEN| \ + FE_RAM|FE_RAM8K|FE_64BIT|FE_IO256|FE_NOPM|FE_LEDC|FE_ULTRA3|FE_66MHZ} \ } /* @@ -605,7 +645,9 @@ typedef struct { PCI_DEVICE_ID_NCR_53C895, \ PCI_DEVICE_ID_NCR_53C896, \ PCI_DEVICE_ID_NCR_53C895A, \ - PCI_DEVICE_ID_NCR_53C1510D \ + PCI_DEVICE_ID_NCR_53C1510D, \ + PCI_DEVICE_ID_LSI_53C1010, \ + PCI_DEVICE_ID_LSI_53C1010_66 \ } /* @@ -640,7 +682,7 @@ struct ncr_driver_setup { u_char recovery; u_char host_id; u_short iarb; - u_int excludes[SCSI_NCR_MAX_EXCLUDES]; + u_long excludes[SCSI_NCR_MAX_EXCLUDES]; char tag_ctrl[100]; }; @@ -662,7 +704,7 @@ struct ncr_driver_setup { 1, \ SCSI_NCR_SETUP_DEFAULT_TAGS, \ SCSI_NCR_SETUP_DEFAULT_SYNC, \ - 0x00, \ + 0x0200, \ 7, \ SCSI_NCR_SETUP_LED_PIN, \ 1, \ @@ -864,12 +906,14 @@ struct ncr_reg { /*03*/ u_char nc_scntl3; /* cnf system clock dependent */ #define EWS 0x08 /* cmd: enable wide scsi [W]*/ #define ULTRA 0x80 /* cmd: ULTRA enable */ + /* bits 0-2, 7 rsvd for C1010 */ /*04*/ u_char nc_scid; /* cnf host adapter scsi address */ #define RRE 0x40 /* r/w:e enable response to resel. */ #define SRE 0x20 /* r/w:e enable response to select */ /*05*/ u_char nc_sxfer; /* ### Sync speed and count */ + /* bits 6-7 rsvd for C1010 */ /*06*/ u_char nc_sdid; /* ### Destination-ID */ @@ -944,12 +988,14 @@ struct ncr_reg { /*1a*/ u_char nc_ctest2; #define CSIGP 0x40 + /* bits 0-2,7 rsvd for C1010 */ /*1b*/ u_char nc_ctest3; #define FLF 0x08 /* cmd: flush dma fifo */ #define CLF 0x04 /* cmd: clear dma fifo */ #define FM 0x02 /* mod: fetch pin mode */ #define WRIE 0x01 /* mod: write and invalidate enable */ + /* bits 4-7 rsvd for C1010 */ /*1c*/ u_int32 nc_temp; /* ### Temporary stack */ @@ -960,6 +1006,7 @@ struct ncr_reg { /*22*/ u_char nc_ctest5; #define DFS 0x20 /* mod: dma fifo size */ + /* bits 0-1, 3-7 rsvd for C1010 */ /*23*/ u_char nc_ctest6; /*24*/ u_int32 nc_dbc; /* ### Byte count and command */ @@ -991,6 +1038,7 @@ struct ncr_reg { #define STD 0x04 /* cmd: start dma mode */ #define IRQD 0x02 /* mod: irq disable */ #define NOCOM 0x01 /* cmd: protect sfbr while reselect */ + /* bits 0-1 rsvd for C1010 */ /*3c*/ u_int32 nc_adder; @@ -1041,6 +1089,7 @@ struct ncr_reg { #define SMODE_SE 0x80 /* Single Ended */ #define SMODE_LVD 0xc0 /* Low Voltage Differential */ #define LCKFRQ 0x20 /* Frequency Lock (895/6 only) */ + /* bits 0-5 rsvd for C1010 */ /*53*/ u_char nc_53_; /*54*/ u_short nc_sodl; /* Lowlevel: data out to scsi data */ @@ -1054,6 +1103,7 @@ struct ncr_reg { /*57*/ u_char nc_ccntl1; /* Chip Control 1 (896) */ #define ZMOD 0x80 /* High Impedance Mode */ + #define DIC 0x10 /* Disable Internal Cycles */ #define DDAC 0x08 /* Disable Dual Address Cycle */ #define XTIMOD 0x04 /* 64-bit Table Ind. Indexing Mode */ #define EXTIBMV 0x02 /* Enable 64-bit Table Ind. BMOV */ @@ -1075,7 +1125,16 @@ struct ncr_reg { /*b0*/ u_int32 nc_sbms; /* Static Block Move Selector */ /*b4*/ u_int32 nc_dbms; /* Dynamic Block Move Selector */ /*b8*/ u_int32 nc_dnad64; /* DMA Next Address 64 */ -/*bc*/ u_int32 nc_bc_; +/*bc*/ u_short nc_scntl4; /* C1010 only */ + #define U3EN 0x80 /* Enable Ultra 3 */ + #define AIPEN 0x40 /* Allow check upper byte lanes */ + #define XCLKH_DT 0x08 /* Extra clock of data hold on DT + transfer edge */ + #define XCLKH_ST 0x04 /* Extra clock of data hold on ST + transfer edge */ + +/*be*/ u_char nc_aipcntl0; /* Epat Control 1 C1010 only */ +/*bf*/ u_char nc_aipcntl1; /* AIP Control C1010_66 Only */ /*c0*/ u_int32 nc_pmjad1; /* Phase Mismatch Jump Address 1 */ /*c4*/ u_int32 nc_pmjad2; /* Phase Mismatch Jump Address 2 */ @@ -1095,6 +1154,17 @@ struct ncr_reg { /*d7*/ u_char nc_ia3; /*d8*/ u_int32 nc_sbc; /* SCSI Byte Count (3 bytes only) */ /*dc*/ u_int32 nc_csbc; /* Cumulative SCSI Byte Count */ + + /* Following for C1010 only */ +/*e0*/ u_short nc_crcpad; /* CRC Value */ +/*e2*/ u_char nc_crccntl0; /* CRC control register */ + #define SNDCRC 0x10 /* Send CRC Request */ +/*e3*/ u_char nc_crccntl1; /* CRC control register */ +/*e4*/ u_int32 nc_crcdata; /* CRC data register */ +/*e8*/ u_int32 nc_e8_; /* rsvd */ +/*ec*/ u_int32 nc_ec_; /* rsvd */ +/*f0*/ u_short nc_dfbc; /* DMA FIFO byte count */ + }; /*----------------------------------------------------------- @@ -1113,6 +1183,8 @@ typedef u_int32 ncrcmd; ** ** SCSI phases ** +** DT phases illegal for ncr driver. +** **----------------------------------------------------------- */ @@ -1120,11 +1192,14 @@ typedef u_int32 ncrcmd; #define SCR_DATA_IN 0x01000000 #define SCR_COMMAND 0x02000000 #define SCR_STATUS 0x03000000 -#define SCR_ILG_OUT 0x04000000 -#define SCR_ILG_IN 0x05000000 +#define SCR_DT_DATA_OUT 0x04000000 +#define SCR_DT_DATA_IN 0x05000000 #define SCR_MSG_OUT 0x06000000 #define SCR_MSG_IN 0x07000000 +#define SCR_ILG_OUT 0x04000000 +#define SCR_ILG_IN 0x05000000 + /*----------------------------------------------------------- ** ** Data transfer via SCSI. @@ -1179,7 +1254,7 @@ struct scr_tblmove { #define SCR_SEL_TBL_ATN 0x43000000 struct scr_tblsel { - u_char sel_0; + u_char sel_scntl4; u_char sel_sxfer; u_char sel_id; u_char sel_scntl3; @@ -1463,6 +1538,7 @@ struct scr_tblsel { #define M_X_MODIFY_DP (0x00) #define M_X_SYNC_REQ (0x01) #define M_X_WIDE_REQ (0x03) +#define M_X_PPR_REQ (0x04) /* ** Status diff --git a/drivers/scsi/tmscsim.c b/drivers/scsi/tmscsim.c index 4b6b5d510..a1779ad10 100644 --- a/drivers/scsi/tmscsim.c +++ b/drivers/scsi/tmscsim.c @@ -319,7 +319,7 @@ # define PCI_PRESENT pci_present () # define PCI_SET_MASTER pci_set_master (pdev) # define PCI_FIND_DEVICE(vend, id) (pdev = pci_find_device (vend, id, pdev)) -# define PCI_GET_IO_AND_IRQ io_port = pdev->resource[0].start; irq = pdev->irq +# define PCI_GET_IO_AND_IRQ io_port = pci_resource_start(pdev, 0); irq = pdev->irq; #else # include <linux/bios32.h> # define PDEV pbus, pdevfn @@ -2002,6 +2002,8 @@ int __init DC390_detect (Scsi_Host_Template *psht) if ( PCI_PRESENT ) while (PCI_FIND_DEVICE (PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD53C974)) { + if (pci_enable_device(pdev)) + continue; DC390_LOCK_IO; /* Remove this when going to new eh */ PCI_GET_IO_AND_IRQ; DEBUG0(printk(KERN_INFO "DC390(%i): IO_PORT=%04x,IRQ=%x\n", dc390_adapterCnt, (UINT) io_port, irq);) |