patch-2.3.34 linux/drivers/scsi/ncr53c8xx.c
Next file: linux/drivers/scsi/scsi.c
Previous file: linux/drivers/scsi/ips.h
Back to the patch index
Back to the overall index
- Lines: 1027
- Date:
Mon Dec 20 15:36:46 1999
- Orig file:
v2.3.33/linux/drivers/scsi/ncr53c8xx.c
- Orig date:
Tue Dec 7 09:32:46 1999
diff -u --recursive --new-file v2.3.33/linux/drivers/scsi/ncr53c8xx.c linux/drivers/scsi/ncr53c8xx.c
@@ -73,7 +73,7 @@
*/
/*
-** Sep 10 1999, version 3.2c
+** December 6 1999, version 3.2d
**
** 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)
+** 53C1510D (Wide, Fast 40, on board rom BIOS)
**
** Other features:
** Memory mapped IO (linux-1.3.X and above only)
@@ -103,7 +104,7 @@
/*
** Name and version of the driver
*/
-#define SCSI_NCR_DRIVER_NAME "ncr53c8xx - 3.2c"
+#define SCSI_NCR_DRIVER_NAME "ncr53c8xx - version 3.2d"
#define SCSI_NCR_DEBUG_FLAGS (0)
@@ -511,6 +512,134 @@
#endif
/*
+** Simple Wrapper to kernel PCI bus interface.
+**
+** This wrapper allows to get rid of old kernel PCI interface
+** and still allows to preserve linux-2.0 compatibilty.
+** In fact, it is mostly an incomplete emulation of the new
+** PCI code for pre-2.2 kernels. When kernel-2.0 support
+** will be dropped, we will just have to remove most of this
+** code.
+*/
+
+#if LINUX_VERSION_CODE >= LinuxVersionCode(2,2,0)
+
+typedef struct pci_dev *pcidev_t;
+#define PCIDEV_NULL (0)
+#define PciBusNumber(d) (d)->bus->number
+#define PciDeviceFn(d) (d)->devfn
+#define PciVendorId(d) (d)->vendor
+#define PciDeviceId(d) (d)->device
+#define PciIrqLine(d) (d)->irq
+
+#if LINUX_VERSION_CODE > LinuxVersionCode(2,3,12)
+
+static int __init
+pci_get_base_address(struct pci_dev *pdev, int index, u_long *base)
+{
+ *base = pdev->resource[index].start;
+ if ((pdev->resource[index].flags & 0x7) == 0x4)
+ ++index;
+ return ++index;
+}
+#else
+static int __init
+pci_get_base_address(struct pci_dev *pdev, int index, u_long *base)
+{
+ *base = pdev->base_address[index++];
+ if ((*base & 0x7) == 0x4) {
+#if BITS_PER_LONG > 32
+ *base |= (((u_long)pdev->base_address[index]) << 32);
+#endif
+ ++index;
+ }
+ return index;
+}
+#endif
+
+#else /* Incomplete emulation of current PCI code for pre-2.2 kernels */
+
+typedef unsigned int pcidev_t;
+#define PCIDEV_NULL (~0u)
+#define PciBusNumber(d) ((d)>>8)
+#define PciDeviceFn(n) ((d)&0xff)
+#define __PciDev(busn, devfn) (((busn)<<8)+(devfn))
+
+#define pci_present pcibios_present
+
+#define pci_read_config_byte(d, w, v) \
+ pcibios_read_config_byte(PciBusNumber(d), PciDeviceFn(d), w, v)
+#define pci_read_config_word(d, w, v) \
+ pcibios_read_config_word(PciBusNumber(d), PciDeviceFn(d), w, v)
+#define pci_read_config_dword(d, w, v) \
+ pcibios_read_config_dword(PciBusNumber(d), PciDeviceFn(d), w, v)
+
+
+#define pci_write_config_byte(d, w, v) \
+ pcibios_write_config_byte(PciBusNumber(d), PciDeviceFn(d), w, v)
+#define pci_write_config_word(d, w, v) \
+ pcibios_write_config_word(PciBusNumber(d), PciDeviceFn(d), w, v)
+#define pci_write_config_dword(d, w, v) \
+ pcibios_write_config_dword(PciBusNumber(d), PciDeviceFn(d), w, v)
+
+static pcidev_t __init
+pci_find_device(unsigned int vendor, unsigned int device, pcidev_t prev)
+{
+ static unsigned short pci_index;
+ int retv;
+ unsigned char bus_number, device_fn;
+
+ if (prev == PCIDEV_NULL)
+ pci_index = 0;
+ else
+ ++pci_index;
+ retv = pcibios_find_device (vendor, device, pci_index,
+ &bus_number, &device_fn);
+ return retv ? PCIDEV_NULL : __PciDev(bus_number, device_fn);
+}
+
+static u_short __init PciVendorId(pcidev_t dev)
+{
+ u_short vendor_id;
+ pcibios_read_config_word(dev, PCI_VENDOR_ID, &vendor_id);
+ return vendor_id;
+}
+
+static u_short __init PciDeviceId(pcidev_t dev)
+{
+ u_short device_id;
+ pci_read_config_word(dev, PCI_DEVICE_ID, &device_id);
+ return device_id;
+}
+
+static u_int __init PciIrqLine(pcidev_t dev)
+{
+ u_short irq;
+ pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq);
+ return irq;
+}
+
+static int __init
+pci_get_base_address(pcidev_t dev, int offset, u_long *base)
+{
+ u_int32 tmp;
+
+ pci_read_config_dword(dev, PCI_BASE_ADDRESS_0 + offset, &tmp);
+ *base = tmp;
+ offset += sizeof(u_int32);
+ if ((tmp & 0x7) == 0x4) {
+#if BITS_PER_LONG > 32
+ pci_read_config_dword(dev, PCI_BASE_ADDRESS_0 + offset, &tmp);
+ *base |= (((u_long)tmp) << 32);
+#endif
+ offset += sizeof(u_int32);
+ }
+ return offset;
+}
+
+#endif /* LINUX_VERSION_CODE >= LinuxVersionCode(2,2,0) */
+
+/*
** SMP threading.
**
** Assuming that SMP systems are generally high end systems and may
@@ -537,20 +666,11 @@
#define NCR_LOCK_NCB(np, flags) spin_lock_irqsave(&np->smp_lock, flags)
#define NCR_UNLOCK_NCB(np, flags) spin_unlock_irqrestore(&np->smp_lock, flags)
-# if LINUX_VERSION_CODE < LinuxVersionCode(2,3,99)
-
-# define NCR_LOCK_SCSI_DONE(np, flags) \
+#define NCR_LOCK_SCSI_DONE(np, flags) \
spin_lock_irqsave(&io_request_lock, flags)
-# define NCR_UNLOCK_SCSI_DONE(np, flags) \
+#define NCR_UNLOCK_SCSI_DONE(np, flags) \
spin_unlock_irqrestore(&io_request_lock, flags)
-# else
-
-# define NCR_LOCK_SCSI_DONE(np, flags) do {;} while (0)
-# define NCR_UNLOCK_SCSI_DONE(np, flags) do {;} while (0)
-
-# endif
-
#else
#if 0 /* not yet needed */
@@ -733,6 +853,12 @@
** /proc directory entry and proc_info function
*/
+#if LINUX_VERSION_CODE < LinuxVersionCode(2,3,27)
+static struct proc_dir_entry proc_scsi_ncr53c8xx = {
+ PROC_SCSI_NCR53C8XX, 9, "ncr53c8xx",
+ S_IFDIR | S_IRUGO | S_IXUGO, 2
+};
+#endif
#ifdef SCSI_NCR_PROC_INFO_SUPPORT
static int ncr53c8xx_proc_info(char *buffer, char **start, off_t offset,
int length, int hostno, int func);
@@ -773,7 +899,8 @@
#define bootverbose (np->verbose)
#ifdef SCSI_NCR_NVRAM_SUPPORT
-static u_char Tekram_sync[12] __initdata = {25,31,37,43,50,62,75,125,12,15,18,21};
+static u_char Tekram_sync[16] __initdata =
+ {25,31,37,43, 50,62,75,125, 12,15,18,21, 6,7,9,10};
#endif /* SCSI_NCR_NVRAM_SUPPORT */
/*
@@ -1763,6 +1890,8 @@
*/
u_short device_id; /* PCI device id */
u_char revision_id; /* PCI device revision id */
+ u_char bus; /* PCI BUS number */
+ u_char device_fn; /* PCI BUS device and function */
u_long port; /* IO space base address */
u_int irq; /* IRQ level */
u_int features; /* Chip features map */
@@ -2060,6 +2189,7 @@
#define reset_waiting_list(np) process_waiting_list((np), DID_RESET)
#ifdef SCSI_NCR_NVRAM_SUPPORT
+static void ncr_get_nvram (ncr_device *devp, ncr_nvram *nvp);
static int ncr_get_Symbios_nvram (ncr_slot *np, Symbios_nvram *nvram);
static int ncr_get_Tekram_nvram (ncr_slot *np, Tekram_nvram *nvram);
#endif
@@ -3938,7 +4068,7 @@
if (tn->flags & TEKRAM_SYNC_NEGO) {
i = tn->sync_index & 0xf;
- tp->usrsync = i < 12 ? Tekram_sync[i] : 255;
+ tp->usrsync = Tekram_sync[i];
}
tp->usrwide = (tn->flags & TEKRAM_WIDE_NEGO) ? 1 : 0;
@@ -4328,7 +4458,7 @@
int sync, j;
struct Tekram_target *tn = &nvram->target[i];
j = tn->sync_index & 0xf;
- sync = j < 12 ? Tekram_sync[j] : 255;
+ sync = Tekram_sync[j];
printk(KERN_DEBUG "%s-%d:%s%s%s%s%s%s PERIOD=%d\n",
ncr_name(np), i,
(tn->flags & TEKRAM_PARITY_CHECK) ? " PARITY" : "",
@@ -4362,16 +4492,21 @@
ncr_nvram *nvram = device->nvram;
int i;
+ printk(KERN_INFO "ncr53c%s-%d: rev 0x%x on pci bus %d device %d function %d "
+#ifdef __sparc__
+ "irq %s\n",
+#else
+ "irq %d\n",
+#endif
+ device->chip.name, unit, device->chip.revision_id,
+ device->slot.bus, (device->slot.device_fn & 0xf8) >> 3,
+ device->slot.device_fn & 7,
#ifdef __sparc__
-printk(KERN_INFO "ncr53c%s-%d: rev=0x%02x, base=0x%lx, io_port=0x%lx, irq=%s\n",
- device->chip.name, unit, device->chip.revision_id, device->slot.base,
- device->slot.io_port, __irq_itoa(device->slot.irq));
-#else
-printk(KERN_INFO "ncr53c%s-%d: rev=0x%02x, base=0x%lx, io_port=0x%lx, irq=%d\n",
- device->chip.name, unit, device->chip.revision_id, device->slot.base,
- device->slot.io_port, device->slot.irq);
+ __irq_itoa(device->slot.irq));
+#else
+ device->slot.irq);
#endif
-
+
/*
** Allocate host_data structure
*/
@@ -4402,6 +4537,8 @@
sprintf(np->inst_name, "ncr53c%s-%d", np->chip_name, np->unit);
np->device_id = device->chip.device_id;
np->revision_id = device->chip.revision_id;
+ np->bus = device->slot.bus;
+ np->device_fn = device->slot.device_fn;
np->features = device->chip.features;
np->clock_divn = device->chip.nr_divisor;
np->maxoffs = device->chip.offset_max;
@@ -4498,7 +4635,11 @@
instance->max_id = np->maxwide ? 16 : 8;
instance->max_lun = SCSI_NCR_MAX_LUN;
#ifndef NCR_IOMAPPED
- instance->base = (unsigned long)np->reg;
+#if LINUX_VERSION_CODE >= LinuxVersionCode(2,3,29)
+ instance->base = (unsigned long) np->reg;
+#else
+ instance->base = (char *) np->reg;
+#endif
#endif
instance->irq = device->slot.irq;
instance->unique_id = device->slot.io_port;
@@ -6073,13 +6214,11 @@
/*
** DEL 441 - 53C876 Rev 5 - Part Number 609-0392787/2788 - ITEM 2.
** Disable overlapped arbitration.
- ** The 896 Rev 1 is also affected by this errata.
+ ** All 896 chips are also affected by this errata.
*/
- if (np->device_id == PCI_DEVICE_ID_NCR_53C875 &&
- np->revision_id >= 0x10 && np->revision_id <= 0x15)
+ if (np->device_id == PCI_DEVICE_ID_NCR_53C875)
OUTB (nc_ctest0, (1<<5));
- else if (np->device_id == PCI_DEVICE_ID_NCR_53C896 &&
- np->revision_id <= 0x1)
+ else if (np->device_id == PCI_DEVICE_ID_NCR_53C896)
OUTB (nc_ccntl0, DPR);
/*
@@ -9217,8 +9356,8 @@
#endif
#endif
-static int ncr53c8xx_pci_init(Scsi_Host_Template *tpnt,
- uchar bus, uchar device_fn, ncr_device *device);
+static int
+ncr53c8xx_pci_init(Scsi_Host_Template *tpnt, pcidev_t pdev, ncr_device *device);
/*
** Linux entry point for NCR53C8XX devices detection routine.
@@ -9273,114 +9412,43 @@
static ncr_chip ncr_chip_table[] __initdata = SCSI_NCR_CHIP_TABLE;
static ushort ncr_chip_ids[] __initdata = SCSI_NCR_CHIP_IDS;
-#ifdef SCSI_NCR_NVRAM_SUPPORT
-static int __init
-ncr_attach_using_nvram(Scsi_Host_Template *tpnt, int nvram_index, int count, ncr_device device[])
-{
- int i, j;
- int attach_count = 0;
- ncr_nvram *nvram;
- ncr_device *devp = 0; /* to shut up gcc */
-
- if (!nvram_index)
- return 0;
-
- /* find first Symbios NVRAM if there is one as we need to check it for host boot order */
- for (i = 0, nvram_index = -1; i < count; i++) {
- devp = &device[i];
- nvram = devp->nvram;
- if (!nvram)
- continue;
- if (nvram->type == SCSI_NCR_SYMBIOS_NVRAM) {
- if (nvram_index == -1)
- nvram_index = i;
-#ifdef SCSI_NCR_DEBUG_NVRAM
- printk("ncr53c8xx: NVRAM: Symbios format Boot Block, 53c%s, PCI bus %d, device %d, function %d\n",
- devp->chip.name, devp->slot.bus,
- (int) (devp->slot.device_fn & 0xf8) >> 3,
- (int) devp->slot.device_fn & 7);
- for (j = 0 ; j < 4 ; j++) {
- Symbios_host *h = &nvram->data.Symbios.host[j];
- printk("ncr53c8xx: BOOT[%d] device_id=%04x vendor_id=%04x device_fn=%02x io_port=%04x %s\n",
- j, h->device_id, h->vendor_id,
- h->device_fn, h->io_port,
- (h->flags & SYMBIOS_INIT_SCAN_AT_BOOT) ? "SCAN AT BOOT" : "");
- }
- }
- else if (nvram->type == SCSI_NCR_TEKRAM_NVRAM) {
- /* display Tekram nvram data */
- printk("ncr53c8xx: NVRAM: Tekram format data, 53c%s, PCI bus %d, device %d, function %d\n",
- devp->chip.name, devp->slot.bus,
- (int) (devp->slot.device_fn & 0xf8) >> 3,
- (int) devp->slot.device_fn & 7);
-#endif
- }
- }
-
- if (nvram_index >= 0 && nvram_index < count)
- nvram = device[nvram_index].nvram;
- else
- nvram = 0;
-
- if (!nvram)
- goto out;
-
- /*
- ** check devices in the boot record against devices detected.
- ** attach devices if we find a match. boot table records that
- ** do not match any detected devices will be ignored.
- ** devices that do not match any boot table will not be attached
- ** here but will attempt to be attached during the device table
- ** rescan.
- */
- for (i = 0; i < 4; i++) {
- Symbios_host *h = &nvram->data.Symbios.host[i];
- for (j = 0 ; j < count ; j++) {
- devp = &device[j];
- if (h->device_fn == devp->slot.device_fn &&
-#if 0 /* bus number location in nvram ? */
- h->bus == devp->slot.bus &&
-#endif
- h->device_id == devp->chip.device_id)
- break;
- }
- if (j < count && !devp->attach_done) {
- if (!ncr_attach (tpnt, attach_count, devp))
- attach_count++;
- devp->attach_done = 1;
- }
- }
-
-out:
- return attach_count;
-}
-#endif /* SCSI_NCR_NVRAM_SUPPORT */
+/*===================================================================
+** Detect all 53c8xx hosts and then attach them.
+**
+** If we are using NVRAM, once all hosts are detected, we need to
+** check any NVRAM for boot order in case detect and boot order
+** differ and attach them using the order in the NVRAM.
+**
+** If no NVRAM is found or data appears invalid attach boards in
+** the the order they are detected.
+**===================================================================
+*/
int __init ncr53c8xx_detect(Scsi_Host_Template *tpnt)
{
- int i, j;
- int chips;
- int count = 0;
- uchar bus, device_fn;
- short index;
+ pcidev_t pcidev;
+ int i, j, chips, hosts, count;
int attach_count = 0;
- ncr_device device[8];
+ ncr_device *devtbl, *devp;
#ifdef SCSI_NCR_NVRAM_SUPPORT
- ncr_nvram nvram[4];
- int k, nvrams;
+ ncr_nvram nvram0, nvram, *nvp;
#endif
- int hosts;
-#ifdef SCSI_NCR_NVRAM_SUPPORT
- int nvram_index = 0;
-#endif
-
-#ifdef SCSI_NCR_DEBUG_INFO_SUPPORT
- ncr_debug = driver_setup.debug;
-#endif
+ /*
+ ** PCI is required.
+ */
+ if (!pci_present())
+ return 0;
- tpnt->proc_name = "ncr53c8xx";
+ /*
+ ** Initialize driver general stuff.
+ */
#ifdef SCSI_NCR_PROC_INFO_SUPPORT
+#if LINUX_VERSION_CODE < LinuxVersionCode(2,3,27)
+ tpnt->proc_dir = &proc_scsi_ncr53c8xx;
+#else
+ tpnt->proc_name = "ncr53c8xx";
+#endif
tpnt->proc_info = ncr53c8xx_proc_info;
#endif
@@ -9388,145 +9456,194 @@
if (ncr53c8xx)
ncr53c8xx_setup(ncr53c8xx);
#endif
+#ifdef SCSI_NCR_DEBUG_INFO_SUPPORT
+ ncr_debug = driver_setup.debug;
+#endif
if (initverbose >= 2)
ncr_print_driver_setup();
- /*
- ** Detect all 53c8xx hosts and then attach them.
- **
- ** If we are using NVRAM, once all hosts are detected, we need to check
- ** any NVRAM for boot order in case detect and boot order differ and
- ** attach them using the order in the NVRAM.
- **
- ** If no NVRAM is found or data appears invalid attach boards in the
- ** the order they are detected.
+ /*
+ ** Allocate the device table since we donnot want to
+ ** overflow the kernel stack.
+ ** 1 x 4K PAGE is enough for more than 40 devices for i386.
*/
-
-#if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,92)
- if (!pci_present())
-#else
- if (!pcibios_present())
-#endif
+ devtbl = kmalloc(4000, GFP_ATOMIC);
+ if (!devtbl)
return 0;
+ /*
+ ** Detect all 53c8xx hosts.
+ ** Save the first Symbios NVRAM content if any
+ ** for the boot order.
+ */
chips = sizeof(ncr_chip_ids) / sizeof(ncr_chip_ids[0]);
- hosts = sizeof(device) / sizeof(device[0]);
+ hosts = 4000 / sizeof(*devtbl);
#ifdef SCSI_NCR_NVRAM_SUPPORT
- k = 0;
- if (driver_setup.use_nvram & 0x1)
- nvrams = sizeof(nvram) / sizeof(nvram[0]);
- else
- nvrams = 0;
+ nvp = (driver_setup.use_nvram & 0x1) ? &nvram0 : 0;
#endif
-
- for (j = 0; j < chips ; ++j) {
- i = driver_setup.reverse_probe ? chips-1 - j : j;
- for (index = 0; ; index++) {
- char *msg = "";
- if ((pcibios_find_device(PCI_VENDOR_ID_NCR, ncr_chip_ids[i],
- index, &bus, &device_fn)) ||
- (count == hosts))
+ j = 0;
+ count = 0;
+ pcidev = PCIDEV_NULL;
+ while (1) {
+ char *msg = "";
+ if (count >= hosts)
+ break;
+ if (j >= chips)
+ break;
+ i = driver_setup.reverse_probe ? chips - 1 - j : j;
+ pcidev = pci_find_device(PCI_VENDOR_ID_NCR, ncr_chip_ids[i],
+ pcidev);
+ if (pcidev == PCIDEV_NULL) {
+ ++j;
+ continue;
+ }
+ /* Some HW as the HP LH4 may report twice PCI devices */
+ for (i = 0; i < count ; i++) {
+ if (devtbl[i].slot.bus == PciBusNumber(pcidev) &&
+ devtbl[i].slot.device_fn == PciDeviceFn(pcidev))
break;
+ }
+ if (i != count) /* Ignore this device if we already have it */
+ continue;
+ devp = &devtbl[count];
+ devp->host_id = driver_setup.host_id;
+ devp->attach_done = 0;
+ if (ncr53c8xx_pci_init(tpnt, pcidev, devp)) {
+ continue;
+ }
+ ++count;
#ifdef SCSI_NCR_NVRAM_SUPPORT
- device[count].nvram = k < nvrams ? &nvram[k] : 0;
-#else
- device[count].nvram = 0;
-#endif
- device[count].host_id = driver_setup.host_id;
- if (ncr53c8xx_pci_init(tpnt, bus, device_fn, &device[count])) {
- device[count].nvram = 0;
- continue;
- }
-#ifdef SCSI_NCR_NVRAM_SUPPORT
- if (device[count].nvram) {
- ++k;
- nvram_index |= device[count].nvram->type;
- switch (device[count].nvram->type) {
- case SCSI_NCR_TEKRAM_NVRAM:
- msg = "with Tekram NVRAM";
- break;
- case SCSI_NCR_SYMBIOS_NVRAM:
- msg = "with Symbios NVRAM";
- break;
- default:
- msg = "";
- device[count].nvram = 0;
- --k;
- }
+ if (nvp) {
+ ncr_get_nvram(devp, nvp);
+ switch(nvp->type) {
+ case SCSI_NCR_SYMBIOS_NVRAM:
+ /*
+ * Switch to the other nvram buffer, so that
+ * nvram0 will contain the first Symbios
+ * format NVRAM content with boot order.
+ */
+ nvp = &nvram;
+ msg = "with Symbios NVRAM";
+ break;
+ case SCSI_NCR_TEKRAM_NVRAM:
+ msg = "with Tekram NVRAM";
+ break;
}
-#endif
- printk(KERN_INFO "ncr53c8xx: 53c%s detected %s\n",
- device[count].chip.name, msg);
- ++count;
}
+#endif
+ printk(KERN_INFO "ncr53c8xx: 53c%s detected %s\n",
+ devp->chip.name, msg);
}
+
+ /*
+ ** If we have found a SYMBIOS NVRAM, use first the NVRAM boot
+ ** sequence as device boot order.
+ ** check devices in the boot record against devices detected.
+ ** attach devices if we find a match. boot table records that
+ ** do not match any detected devices will be ignored.
+ ** devices that do not match any boot table will not be attached
+ ** here but will attempt to be attached during the device table
+ ** rescan.
+ */
#ifdef SCSI_NCR_NVRAM_SUPPORT
- attach_count = ncr_attach_using_nvram(tpnt, nvram_index, count, device);
+ if (!nvp || nvram0.type != SCSI_NCR_SYMBIOS_NVRAM)
+ goto next;
+ for (i = 0; i < 4; i++) {
+ Symbios_host *h = &nvram0.data.Symbios.host[i];
+ for (j = 0 ; j < count ; j++) {
+ devp = &devtbl[j];
+ if (h->device_fn != devp->slot.device_fn ||
+ h->bus_nr != devp->slot.bus ||
+ h->device_id != devp->chip.device_id)
+ continue;
+ if (devp->attach_done)
+ continue;
+ ncr_get_nvram(devp, nvp);
+ if (!ncr_attach (tpnt, attach_count, devp))
+ attach_count++;
+ devp->attach_done = 1;
+ break;
+ }
+ }
+next:
#endif
+
/*
- ** rescan device list to make sure all boards attached.
- ** devices without boot records will not be attached yet
- ** so try to attach them here.
+ ** Rescan device list to make sure all boards attached.
+ ** Devices without boot records will not be attached yet
+ ** so try to attach them here.
*/
for (i= 0; i < count; i++) {
- if (!device[i].attach_done &&
- !ncr_attach (tpnt, attach_count, &device[i])) {
- attach_count++;
+ devp = &devtbl[i];
+ if (!devp->attach_done) {
+#ifdef SCSI_NCR_NVRAM_SUPPORT
+ ncr_get_nvram(devp, nvp);
+#endif
+ if (!ncr_attach (tpnt, attach_count, devp))
+ attach_count++;
}
}
+ kfree(devtbl);
+
return attach_count;
}
-/*
-** Generically read a base address from the PCI configuration space.
-** Return the offset immediately after the base address that has
-** been read. Btw, we blindly assume that the high 32 bits of 64 bit
-** base addresses are set to zero on 32 bit architectures.
+/*===================================================================
+** Detect and try to read SYMBIOS and TEKRAM NVRAM.
+**
+** Data can be used to order booting of boards.
**
+** Data is saved in ncr_device structure if NVRAM found. This
+** is then used to find drive boot order for ncr_attach().
+**
+** NVRAM data is passed to Scsi_Host_Template later during
+** ncr_attach() for any device set up.
+*===================================================================
*/
-#if LINUX_VERSION_CODE <= LinuxVersionCode(2,1,92)
-static int __init
-pci_read_base_address(u_char bus, u_char device_fn, int offset, u_long *base)
+#ifdef SCSI_NCR_NVRAM_SUPPORT
+static void __init ncr_get_nvram(ncr_device *devp, ncr_nvram *nvp)
{
- u_int32 tmp;
-
- pcibios_read_config_dword(bus, device_fn, offset, &tmp);
- *base = tmp;
- offset += sizeof(u_int32);
- if ((tmp & 0x7) == 0x4) {
-#if BITS_PER_LONG > 32
- pcibios_read_config_dword(bus, device_fn, offset, &tmp);
- *base |= (((u_long)tmp) << 32);
+ devp->nvram = nvp;
+ if (!nvp)
+ return;
+ /*
+ ** Get access to chip IO registers
+ */
+#ifdef NCR_IOMAPPED
+ request_region(devp->slot.io_port, 128, "ncr53c8xx");
+ devp->slot.port = devp->slot.io_port;
+#else
+ devp->slot.reg = (struct ncr_reg *) remap_pci_mem(devp->slot.base, 128);
+ if (!devp->slot.reg)
+ return;
#endif
- offset += sizeof(u_int32);
+
+ /*
+ ** Try to read SYMBIOS nvram.
+ ** Try to read TEKRAM nvram if Symbios nvram not found.
+ */
+ if (!ncr_get_Symbios_nvram(&devp->slot, &nvp->data.Symbios))
+ nvp->type = SCSI_NCR_SYMBIOS_NVRAM;
+ else if (!ncr_get_Tekram_nvram(&devp->slot, &nvp->data.Tekram))
+ nvp->type = SCSI_NCR_TEKRAM_NVRAM;
+ else {
+ nvp->type = 0;
+ devp->nvram = 0;
}
- return offset;
-}
-#elif LINUX_VERSION_CODE <= LinuxVersionCode(2,3,12)
-static int __init
-pci_get_base_address(struct pci_dev *pdev, int index, u_long *base)
-{
- *base = pdev->base_address[index++];
- if ((*base & 0x7) == 0x4) {
-#if BITS_PER_LONG > 32
- *base |= (((u_long)pdev->base_address[index]) << 32);
+
+ /*
+ ** Release access to chip IO registers
+ */
+#ifdef NCR_IOMAPPED
+ release_region(devp->slot.port, 128);
+#else
+ unmap_pci_mem((u_long) devp->slot.reg, 128ul);
#endif
- ++index;
- }
- return index;
-}
-#else /* LINUX_VERSION_CODE > LinuxVersionCode(2,3,12) */
-static int __init
-pci_get_base_address(struct pci_dev *pdev, int index, u_long *base)
-{
- *base = pdev->resource[index].start;
- if ((pdev->resource[index].flags & 0x7) == 0x4)
- ++index;
- return ++index;
+
}
-#endif
+#endif /* SCSI_NCR_NVRAM_SUPPORT */
/*
** Read and check the PCI configuration for any detected NCR
@@ -9534,18 +9651,13 @@
** been detected.
*/
-static int __init ncr53c8xx_pci_init(Scsi_Host_Template *tpnt,
- uchar bus, uchar device_fn, ncr_device *device)
+static int __init
+ncr53c8xx_pci_init(Scsi_Host_Template *tpnt, pcidev_t pdev, ncr_device *device)
{
ushort vendor_id, device_id, command;
uchar cache_line_size, latency_timer;
uchar revision;
-#if LINUX_VERSION_CODE > LinuxVersionCode(2,1,92)
- struct pci_dev *pdev;
uint irq;
-#else
- uchar irq;
-#endif
ulong base, base_2, io_port;
int i;
#ifdef SCSI_NCR_NVRAM_SUPPORT
@@ -9555,33 +9667,20 @@
/*
** Read info from the PCI config space.
- ** pcibios_read_config_xxx() functions are assumed to be used for
+ ** pci_read_config_xxx() functions are assumed to be used for
** successfully detected PCI devices.
*/
-#if LINUX_VERSION_CODE > LinuxVersionCode(2,1,92)
- pdev = pci_find_slot(bus, device_fn);
- vendor_id = pdev->vendor;
- device_id = pdev->device;
- irq = pdev->irq;
+ vendor_id = PciVendorId(pdev);
+ device_id = PciDeviceId(pdev);
+ irq = PciIrqLine(pdev);
i = 0;
i = pci_get_base_address(pdev, i, &io_port);
i = pci_get_base_address(pdev, i, &base);
(void) pci_get_base_address(pdev, i, &base_2);
-#else
- pcibios_read_config_word(bus, device_fn, PCI_VENDOR_ID, &vendor_id);
- pcibios_read_config_word(bus, device_fn, PCI_DEVICE_ID, &device_id);
- pcibios_read_config_byte(bus, device_fn, PCI_INTERRUPT_LINE, &irq);
- i = PCI_BASE_ADDRESS_0;
- i = pci_read_base_address(bus, device_fn, i, &io_port);
- i = pci_read_base_address(bus, device_fn, i, &base);
- (void) pci_read_base_address(bus, device_fn, i, &base_2);
-#endif
- pcibios_read_config_word(bus, device_fn, PCI_COMMAND, &command);
- pcibios_read_config_byte(bus, device_fn, PCI_CLASS_REVISION, &revision);
- pcibios_read_config_byte(bus, device_fn, PCI_CACHE_LINE_SIZE,
- &cache_line_size);
- pcibios_read_config_byte(bus, device_fn, PCI_LATENCY_TIMER,
- &latency_timer);
+ pci_read_config_word(pdev, PCI_COMMAND, &command);
+ 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);
/*
** If user excludes this chip, donnot initialize it.
@@ -9631,7 +9730,9 @@
#endif
printk(KERN_INFO "ncr53c8xx: at PCI bus %d, device %d, function %d\n",
- bus, (int) (device_fn & 0xf8) >> 3, (int) device_fn & 7);
+ PciBusNumber(pdev),
+ (int) (PciDeviceFn(pdev) & 0xf8) >> 3,
+ (int) (PciDeviceFn(pdev) & 0x7));
if (!chip) {
printk("ncr53c8xx: not initializing, device not supported\n");
@@ -9646,8 +9747,8 @@
if (!(command & PCI_COMMAND_MASTER)) {
printk("ncr53c8xx: attempting to force PCI_COMMAND_MASTER...");
command |= PCI_COMMAND_MASTER;
- pcibios_write_config_word(bus, device_fn, PCI_COMMAND, command);
- pcibios_read_config_word(bus, device_fn, PCI_COMMAND, &command);
+ pci_write_config_word(pdev, PCI_COMMAND, command);
+ pci_read_config_word(pdev, PCI_COMMAND, &command);
if (!(command & PCI_COMMAND_MASTER)) {
printk("failed!\n");
} else {
@@ -9658,8 +9759,8 @@
if (!(command & PCI_COMMAND_IO)) {
printk("ncr53c8xx: attempting to force PCI_COMMAND_IO...");
command |= PCI_COMMAND_IO;
- pcibios_write_config_word(bus, device_fn, PCI_COMMAND, command);
- pcibios_read_config_word(bus, device_fn, PCI_COMMAND, &command);
+ pci_write_config_word(pdev, PCI_COMMAND, command);
+ pci_read_config_word(pdev, PCI_COMMAND, &command);
if (!(command & PCI_COMMAND_IO)) {
printk("failed!\n");
} else {
@@ -9670,8 +9771,8 @@
if (!(command & PCI_COMMAND_MEMORY)) {
printk("ncr53c8xx: attempting to force PCI_COMMAND_MEMORY...");
command |= PCI_COMMAND_MEMORY;
- pcibios_write_config_word(bus, device_fn, PCI_COMMAND, command);
- pcibios_read_config_word(bus, device_fn, PCI_COMMAND, &command);
+ pci_write_config_word(pdev, PCI_COMMAND, command);
+ pci_read_config_word(pdev, PCI_COMMAND, &command);
if (!(command & PCI_COMMAND_MEMORY)) {
printk("failed!\n");
} else {
@@ -9685,17 +9786,17 @@
if (io_port >= 0x10000000) {
printk("ncr53c8xx: reallocating io_port (Wacky IBM)");
io_port = (io_port & 0x00FFFFFF) | 0x01000000;
- pcibios_write_config_dword(bus, device_fn, PCI_BASE_ADDRESS_0, io_port);
+ pci_write_config_dword(pdev, PCI_BASE_ADDRESS_0, io_port);
}
if (base >= 0x10000000) {
printk("ncr53c8xx: reallocating base (Wacky IBM)");
base = (base & 0x00FFFFFF) | 0x01000000;
- pcibios_write_config_dword(bus, device_fn, PCI_BASE_ADDRESS_1, base);
+ pci_write_config_dword(pdev, PCI_BASE_ADDRESS_1, base);
}
if (base_2 >= 0x10000000) {
printk("ncr53c8xx: reallocating base2 (Wacky IBM)");
base_2 = (base_2 & 0x00FFFFFF) | 0x01000000;
- pcibios_write_config_dword(bus, device_fn, PCI_BASE_ADDRESS_2, base_2);
+ pci_write_config_dword(pdev, PCI_BASE_ADDRESS_2, base_2);
}
}
#endif
@@ -9716,16 +9817,16 @@
if (initverbose >= 2)
printk("ncr53c8xx: setting PCI_COMMAND_MASTER bit (fixup)\n");
command |= PCI_COMMAND_MASTER;
- pcibios_write_config_word(bus, device_fn, PCI_COMMAND, command);
- pcibios_read_config_word(bus, device_fn, PCI_COMMAND, &command);
+ pci_write_config_word(pdev, PCI_COMMAND, command);
+ pci_read_config_word(pdev, PCI_COMMAND, &command);
}
if ((chip->features & FE_WRIE) && !(command & PCI_COMMAND_INVALIDATE)) {
if (initverbose >= 2)
printk("ncr53c8xx: setting PCI_COMMAND_INVALIDATE bit (fixup)\n");
command |= PCI_COMMAND_INVALIDATE;
- pcibios_write_config_word(bus, device_fn, PCI_COMMAND, command);
- pcibios_read_config_word(bus, device_fn, PCI_COMMAND, &command);
+ pci_write_config_word(pdev, PCI_COMMAND, command);
+ pci_read_config_word(pdev, PCI_COMMAND, &command);
}
if ((chip->features & FE_CLSE) && !cache_line_size) {
@@ -9733,20 +9834,16 @@
cache_line_size = 64 / sizeof(u_int32);
if (initverbose >= 2)
printk("ncr53c8xx: setting PCI_CACHE_LINE_SIZE to %d (fixup)\n", cache_line_size);
- pcibios_write_config_byte(bus, device_fn,
- PCI_CACHE_LINE_SIZE, cache_line_size);
- pcibios_read_config_byte(bus, device_fn,
- PCI_CACHE_LINE_SIZE, &cache_line_size);
+ pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, cache_line_size);
+ pci_read_config_byte(pdev, PCI_CACHE_LINE_SIZE, &cache_line_size);
}
if (!latency_timer) {
latency_timer = 128;
if (initverbose >= 2)
printk("ncr53c8xx: setting PCI_LATENCY_TIMER to %d bus clocks (fixup)\n", latency_timer);
- pcibios_write_config_byte(bus, device_fn,
- PCI_LATENCY_TIMER, latency_timer);
- pcibios_read_config_byte(bus, device_fn,
- PCI_LATENCY_TIMER, &latency_timer);
+ pci_write_config_byte(pdev, PCI_LATENCY_TIMER, latency_timer);
+ pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &latency_timer);
}
#endif /* __sparc__ */
@@ -9824,8 +9921,7 @@
case 5: cache_line_size = 8; break;
}
if (cache_line_size)
- (void) pcibios_write_config_byte(bus, device_fn,
- PCI_CACHE_LINE_SIZE, cache_line_size);
+ (void) pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, cache_line_size);
if (initverbose)
printk("ncr53c8xx: setting PCI_CACHE_LINE_SIZE to %d (fix-up).\n", cache_line_size);
}
@@ -9833,8 +9929,7 @@
if ((driver_setup.pci_fix_up & 2) && cache_line_size &&
(chip->features & FE_WRIE) && !(command & PCI_COMMAND_INVALIDATE)) {
command |= PCI_COMMAND_INVALIDATE;
- (void) pcibios_write_config_word(bus, device_fn,
- PCI_COMMAND, command);
+ (void) pci_write_config_word(pdev, PCI_COMMAND, command);
if (initverbose)
printk("ncr53c8xx: setting PCI_COMMAND_INVALIDATE bit (fix-up).\n");
}
@@ -9876,8 +9971,7 @@
latency_timer = lt;
if (initverbose)
printk("ncr53c8xx: setting PCI_LATENCY_TIMER to %d bus clocks (fix-up).\n", latency_timer);
- (void) pcibios_write_config_byte(bus, device_fn,
- PCI_LATENCY_TIMER, latency_timer);
+ (void) pci_write_config_byte(pdev, PCI_LATENCY_TIMER, latency_timer);
}
}
@@ -9900,8 +9994,8 @@
#endif /* SCSI_NCR_PCI_FIX_UP_SUPPORT */
/* initialise ncr_device structure with items required by ncr_attach */
- device->slot.bus = bus;
- device->slot.device_fn = device_fn;
+ device->slot.bus = PciBusNumber(pdev);
+ device->slot.device_fn = PciDeviceFn(pdev);
device->slot.base = base;
device->slot.base_2 = base_2;
device->slot.io_port = io_port;
@@ -10638,29 +10732,28 @@
info.offset = offset;
info.pos = 0;
- copy_info(&info, "General information:\n");
- copy_info(&info, " Chip NCR53C%s, ", np->chip_name);
- copy_info(&info, "device id 0x%x, ", np->device_id);
- copy_info(&info, "revision id 0x%x\n", np->revision_id);
-
- copy_info(&info, " IO port address 0x%lx, ", (u_long) np->port);
+ copy_info(&info, " Chip NCR53C%s, device id 0x%x, "
+ "revision id 0x%x\n",
+ np->chip_name, np->device_id, np->revision_id);
+ copy_info(&info, " On PCI bus %d, device %d, function %d, "
#ifdef __sparc__
- copy_info(&info, "IRQ number %s\n", __irq_itoa(np->irq));
+ "IRQ %s\n",
#else
- copy_info(&info, "IRQ number %d\n", (int) np->irq);
+ "IRQ %d\n",
#endif
-
-#ifndef NCR_IOMAPPED
- if (np->reg)
- copy_info(&info, " Using memory mapped IO at virtual address 0x%lx\n",
- (u_long) np->reg);
+ np->bus, (np->device_fn & 0xf8) >> 3, np->device_fn & 7,
+#ifdef __sparc__
+ __irq_itoa(np->irq));
+#else
+ (int) np->irq);
#endif
- copy_info(&info, " Synchronous period factor %d, ", (int) np->minsync);
- copy_info(&info, "max commands per lun %d\n", MAX_TAGS);
+ copy_info(&info, " Synchronous period factor %d, "
+ "max commands per lun %d\n",
+ (int) np->minsync, MAX_TAGS);
if (driver_setup.debug || driver_setup.verbose > 1) {
- copy_info(&info, " Debug flags 0x%x, ", driver_setup.debug);
- copy_info(&info, "verbosity level %d\n", driver_setup.verbose);
+ copy_info(&info, " Debug flags 0x%x, verbosity level %d\n",
+ driver_setup.debug, driver_setup.verbose);
}
#ifdef SCSI_NCR_PROFILE_SUPPORT
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)