Commit 755b8d21 authored by James Bottomley's avatar James Bottomley

Merge raven.il.steeleye.com:/home/jejb/BK/scsi-misc-2.5

into raven.il.steeleye.com:/home/jejb/BK/scsi-for-linus-2.5
parents 1d0619c5 a6257edd
......@@ -1346,6 +1346,7 @@ int ata_attach(ide_drive_t *drive)
spin_unlock(&drivers_lock);
spin_lock(&drives_lock);
list_add_tail(&drive->list, &ata_unused);
drive->gendev.driver = NULL;
spin_unlock(&drives_lock);
return 1;
}
......@@ -2308,6 +2309,8 @@ void ide_unregister_driver(ide_driver_t *driver)
list_del(&driver->drivers);
spin_unlock(&drivers_lock);
driver_unregister(&driver->gen_driver);
while(!list_empty(&driver->drives)) {
drive = list_entry(driver->drives.next, ide_drive_t, list);
if (driver->cleanup(drive)) {
......
......@@ -8,6 +8,8 @@
#ifndef _53C700_H
#define _53C700_H
#include <asm/io.h>
/* Turn on for general debugging---too verbose for normal use */
#undef NCR_700_DEBUG
/* Debug the tag queues, checking hash queue allocation and deallocation
......
......@@ -964,6 +964,16 @@ config SCSI_SYM53C8XX_2
Please read <file:drivers/scsi/sym53c8xx_2/Documentation.txt> for more
information.
config SCSI_ZALON
tristate "Zalon SCSI support"
depends on GSC && SCSI
help
The Zalon is a GSC/HSC bus interface chip that sits between the
PA-RISC processor and the NCR 53c720 SCSI controller on C100,
C110, J200, J210 and some D, K & R-class machines. It's also
used on the add-in Bluefish, Barracuda & Shrike SCSI cards.
Say Y here if you have one of these machines or cards.
config SCSI_SYM53C8XX_DMA_ADDRESSING_MODE
int "DMA addressing mode"
depends on SCSI_SYM53C8XX_2
......@@ -1068,7 +1078,7 @@ config SCSI_SYM53C8XX
config SCSI_NCR53C8XX_DEFAULT_TAGS
int "default tagged command queue depth"
depends on PCI && SCSI_SYM53C8XX_2!=y && (SCSI_NCR53C8XX || SCSI_SYM53C8XX)
depends on PCI && SCSI_SYM53C8XX_2!=y && (SCSI_NCR53C8XX || SCSI_SYM53C8XX || SCSI_ZALON)
default "8"
---help---
"Tagged command queuing" is a feature of SCSI-2 which improves
......@@ -1094,7 +1104,7 @@ config SCSI_NCR53C8XX_DEFAULT_TAGS
config SCSI_NCR53C8XX_MAX_TAGS
int "maximum number of queued commands"
depends on PCI && SCSI_SYM53C8XX_2!=y && (SCSI_NCR53C8XX || SCSI_SYM53C8XX)
depends on PCI && SCSI_SYM53C8XX_2!=y && (SCSI_NCR53C8XX || SCSI_SYM53C8XX || SCSI_ZALON)
default "32"
---help---
This option allows you to specify the maximum number of commands
......@@ -1111,7 +1121,7 @@ config SCSI_NCR53C8XX_MAX_TAGS
config SCSI_NCR53C8XX_SYNC
int "synchronous transfers frequency in MHz"
depends on PCI && SCSI_SYM53C8XX_2!=y && (SCSI_NCR53C8XX || SCSI_SYM53C8XX)
depends on PCI && SCSI_SYM53C8XX_2!=y && (SCSI_NCR53C8XX || SCSI_SYM53C8XX || SCSI_ZALON)
default "20"
---help---
The SCSI Parallel Interface-2 Standard defines 5 classes of transfer
......@@ -1145,7 +1155,7 @@ config SCSI_NCR53C8XX_SYNC
config SCSI_NCR53C8XX_PROFILE
bool "enable profiling"
depends on PCI && SCSI_SYM53C8XX_2!=y && (SCSI_NCR53C8XX || SCSI_SYM53C8XX)
depends on PCI && SCSI_SYM53C8XX_2!=y && (SCSI_NCR53C8XX || SCSI_SYM53C8XX || SCSI_ZALON)
help
This option allows you to enable profiling information gathering.
These statistics are not very accurate due to the low frequency
......@@ -1156,7 +1166,7 @@ config SCSI_NCR53C8XX_PROFILE
config SCSI_NCR53C8XX_IOMAPPED
bool "use normal IO"
depends on PCI && SCSI_SYM53C8XX_2!=y && (SCSI_NCR53C8XX || SCSI_SYM53C8XX)
depends on PCI && SCSI_SYM53C8XX_2!=y && (SCSI_NCR53C8XX || SCSI_SYM53C8XX) && !SCSI_ZALON
help
If you say Y here, the driver will use normal IO, as opposed to
memory mapped IO. Memory mapped IO has less latency than normal IO
......@@ -1181,7 +1191,7 @@ config SCSI_NCR53C8XX_PQS_PDS
config SCSI_NCR53C8XX_NO_DISCONNECT
bool "not allow targets to disconnect"
depends on PCI && SCSI_SYM53C8XX_2!=y && (SCSI_NCR53C8XX || SCSI_SYM53C8XX) && SCSI_NCR53C8XX_DEFAULT_TAGS=0
depends on PCI && SCSI_SYM53C8XX_2!=y && (SCSI_NCR53C8XX || SCSI_SYM53C8XX || SCSI_ZALON) && SCSI_NCR53C8XX_DEFAULT_TAGS=0
help
This option is only provided for safety if you suspect some SCSI
device of yours to not support properly the target-disconnect
......@@ -1191,7 +1201,7 @@ config SCSI_NCR53C8XX_NO_DISCONNECT
config SCSI_NCR53C8XX_SYMBIOS_COMPAT
bool "assume boards are SYMBIOS compatible (EXPERIMENTAL)"
depends on PCI && SCSI_SYM53C8XX_2!=y && (SCSI_NCR53C8XX || SCSI_SYM53C8XX) && EXPERIMENTAL
depends on PCI && SCSI_SYM53C8XX_2!=y && (SCSI_NCR53C8XX || SCSI_SYM53C8XX || SCSI_ZALON) && EXPERIMENTAL
---help---
This option allows you to enable some features depending on GPIO
wiring. These General Purpose Input/Output pins can be used for
......
......@@ -84,6 +84,7 @@ obj-$(CONFIG_SCSI_NCR53C7xx) += 53c7,8xx.o
obj-$(CONFIG_SCSI_SYM53C8XX_2) += sym53c8xx_2/
obj-$(CONFIG_SCSI_SYM53C8XX) += sym53c8xx.o
obj-$(CONFIG_SCSI_NCR53C8XX) += ncr53c8xx.o
obj-$(CONFIG_SCSI_ZALON) += zalon7xx.o
obj-$(CONFIG_SCSI_EATA_DMA) += eata_dma.o
obj-$(CONFIG_SCSI_EATA_PIO) += eata_pio.o
obj-$(CONFIG_SCSI_7000FASST) += wd7000.o
......@@ -135,6 +136,7 @@ sd_mod-objs := sd.o
sr_mod-objs := sr.o sr_ioctl.o sr_vendor.o
initio-objs := ini9100u.o i91uscsi.o
a100u2w-objs := inia100.o i60uscsi.o
zalon7xx-objs := zalon.o ncr53c8xx.o
cpqfc-objs := cpqfcTSinit.o cpqfcTScontrol.o cpqfcTSi2c.o \
cpqfcTSworker.o cpqfcTStrigger.o
......
......@@ -289,6 +289,7 @@ static int idescsi_check_condition(ide_drive_t *drive, struct request *failed_co
pc->timeout = jiffies + WAIT_READY;
/* NOTE! Save the failed packet command in "rq->buffer" */
rq->buffer = (void *) failed_command->special;
pc->scsi_cmd = ((idescsi_pc_t *) failed_command->special)->scsi_cmd;
if (test_bit(IDESCSI_LOG_CMD, &scsi->log)) {
printk ("ide-scsi: %s: queue cmd = ", drive->name);
hexdump(pc->c, 6);
......@@ -590,6 +591,7 @@ static void idescsi_setup (ide_drive_t *drive, idescsi_scsi_t *scsi, int id)
set_bit(IDESCSI_LOG_CMD, &scsi->log);
#endif /* IDESCSI_DEBUG_LOG */
idescsi_add_settings(drive);
DRIVER(drive)->busy--;
}
static int idescsi_cleanup (ide_drive_t *drive)
......@@ -876,7 +878,8 @@ int idescsi_abort (Scsi_Cmnd *cmd)
/* is cmd active?
* need to lock so this stuff doesn't change under us */
spin_lock_irqsave(&ide_lock, flags);
if (scsi->pc && scsi->pc->scsi_cmd->serial_number == cmd->serial_number) {
if (scsi->pc && scsi->pc->scsi_cmd &&
scsi->pc->scsi_cmd->serial_number == cmd->serial_number) {
/* yep - let's give it some more time -
* we can do that, we're in _our_ error kernel thread */
spin_unlock_irqrestore(&ide_lock, flags);
......@@ -995,7 +998,7 @@ static void __exit exit_idescsi_module(void)
for (id = 0; id < MAX_HWIFS * MAX_DRIVES; id++) {
drive = idescsi_drives[id];
if (drive)
DRIVER(drive)->busy--;
DRIVER(drive)->busy = 0;
}
scsi_unregister (idescsi_host);
device_unregister(&idescsi_primary);
......
......@@ -178,12 +178,8 @@
#include <linux/stat.h>
#include <linux/config.h>
#if LINUX_VERSION_CODE >= LinuxVersionCode(2,4,0)
#include <linux/spinlock.h>
#include <linux/init.h>
#else
#include <asm/spinlock.h>
#endif
#include <linux/spinlock.h>
#include <linux/init.h>
#include <linux/smp.h>
......@@ -199,45 +195,10 @@
#define IPS_VERSION_HIGH "5.10"
#define IPS_VERSION_LOW ".13-BETA "
#if LINUX_VERSION_CODE < LinuxVersionCode(2,4,0)
struct proc_dir_entry proc_scsi_ips = {
0,
3, "ips",
S_IFDIR | S_IRUGO | S_IXUGO, 2
};
#endif
#if !defined(__i386__) && !defined(__ia64__)
#error "This driver has only been tested on the x86/ia64 platforms"
#endif
#if LINUX_VERSION_CODE < LinuxVersionCode(2,2,0)
#error "This driver only works with kernel 2.2.0 and later"
#elif LINUX_VERSION_CODE <= LinuxVersionCode(2,3,18)
#define dma_addr_t uint32_t
static inline void *pci_alloc_consistent(struct pci_dev *dev,int size,
dma_addr_t *dmahandle) {
void * ptr = kmalloc(size, GFP_ATOMIC);
if(ptr){
*dmahandle = (uint32_t)virt_to_bus(ptr);
}
return ptr;
}
#define pci_free_consistent(a,size,address,dmahandle) kfree(address)
#define pci_map_sg(a,b,n,z) (n)
#define pci_unmap_sg(a,b,c,d)
#define pci_map_single(a,b,c,d) ((uint32_t)virt_to_bus(b))
#define pci_unmap_single(a,b,c,d)
#ifndef sg_dma_address
#define sg_dma_address(x) ((uint32_t)virt_to_bus((x)->address))
#define sg_dma_len(x) ((x)->length)
#endif
#define pci_unregister_driver(x)
#endif
#if LINUX_VERSION_CODE <= LinuxVersionCode(2,5,0)
#define IPS_SG_ADDRESS(sg) ((sg)->address)
#define IPS_LOCK_SAVE(lock,flags) spin_lock_irqsave(&io_request_lock,flags)
......@@ -289,7 +250,6 @@ static uint32_t MaxLiteCmds = 32; /* Max Active Cmds for a Li
IPS_DEFINE_COMPAT_TABLE( Compatable ); /* Version Compatability Table */
#if LINUX_VERSION_CODE >= LinuxVersionCode(2,4,0)
/* This table describes any / all ServeRAID Adapters */
static struct pci_device_id ips_pci_table[] __devinitdata = {
{ 0x1014, 0x002E, PCI_ANY_ID, PCI_ANY_ID, 0, 0 },
......@@ -338,7 +298,6 @@ IPS_DEFINE_COMPAT_TABLE( Compatable ); /* Version Compatability Ta
.remove = __devexit_p(ips_remove_device),
};
#endif
/*
* Necessary forward function protoypes
......@@ -497,6 +456,7 @@ static void ips_done(ips_ha_t *, ips_scb_t *);
static void ips_free(ips_ha_t *);
static void ips_init_scb(ips_ha_t *, ips_scb_t *);
static void ips_freescb(ips_ha_t *, ips_scb_t *);
static void ips_setup_funclist(ips_ha_t *);
static void ips_statinit(ips_ha_t *);
static void ips_statinit_memio(ips_ha_t *);
static void ips_fix_ffdc_time(ips_ha_t *, ips_scb_t *, time_t);
......@@ -533,9 +493,7 @@ static void ips_version_check(ips_ha_t *ha, int intr);
static int ips_abort_init(ips_ha_t *ha, struct Scsi_Host *sh, int index);
static int ips_init_phase2( int index );
#if LINUX_VERSION_CODE >= LinuxVersionCode(2,4,0)
static int ips_init_phase1( struct pci_dev *pci_dev, int *indexPtr );
#endif
/*--------------------------------------------------------------------------*/
/* Exported Functions */
......@@ -550,13 +508,8 @@ static int ips_init_phase1( struct pci_dev *pci_dev, int *indexPtr );
/* setup parameters to the driver */
/* */
/****************************************************************************/
#if LINUX_VERSION_CODE >= LinuxVersionCode(2,4,0)
static int
ips_setup(char *ips_str) {
#else
void
ips_setup(char *ips_str, int *dummy) {
#endif
int i;
char *key;
......@@ -570,7 +523,6 @@ ips_setup(char *ips_str, int *dummy) {
};
/* Don't use strtok() anymore ( if 2.4 Kernel or beyond ) */
#if LINUX_VERSION_CODE >= LinuxVersionCode(2,4,0)
/* Search for value */
while ((key = strsep(&ips_str, ",."))) {
if (!*key)
......@@ -598,43 +550,6 @@ ips_setup(char *ips_str, int *dummy) {
__setup("ips=", ips_setup);
#else
char *p;
char tokens[3] = {',', '.', 0};
for (key = strtok(ips_str, tokens); key; key = strtok(NULL, tokens)) {
p = key;
/* Search for value */
while ((p) && (*p != ':'))
p++;
if (p) {
*p = '\0';
value = p+1;
} else
value = NULL;
/*
* We now have key/value pairs.
* Update the variables
*/
for (i = 0; i < (sizeof(options) / sizeof(options[0])); i++) {
if (strnicmp(key, options[i].option_name, strlen(ips_str)) == 0) {
if (value)
*options[i].option_flag = simple_strtoul(value, NULL, 0);
else
*options[i].option_flag = options[i].option_value;
break;
}
}
}
}
#endif
/****************************************************************************/
/* */
/* Routine Name: ips_detect */
......@@ -648,42 +563,12 @@ __setup("ips=", ips_setup);
/****************************************************************************/
int
ips_detect(Scsi_Host_Template *SHT) {
struct Scsi_Host *sh;
ips_ha_t *ha;
uint32_t io_addr;
uint32_t mem_addr;
uint32_t io_len;
uint32_t mem_len;
uint16_t planer;
uint8_t revision_id;
uint8_t bus;
uint8_t func;
uint8_t irq;
uint16_t deviceID[2];
uint16_t subdevice_id;
int i;
int j;
uint32_t count;
char *ioremap_ptr;
char *mem_ptr;
struct pci_dev *dev[2];
struct pci_dev *morpheus = NULL;
struct pci_dev *trombone = NULL;
#if LINUX_VERSION_CODE < LinuxVersionCode(2,4,0)
uint32_t currbar;
uint32_t maskbar;
uint8_t barnum;
#endif
METHOD_TRACE("ips_detect", 1);
#ifdef MODULE
if (ips)
#if LINUX_VERSION_CODE >= LinuxVersionCode(2,4,0)
ips_setup(ips);
#else
ips_setup(ips, NULL);
#endif
#endif
/* If Booting from the ServeRAID Manager CD, Allocate a large Flash */
......@@ -697,69 +582,8 @@ ips_detect(Scsi_Host_Template *SHT) {
}
SHT->proc_info = ips_proc_info;
#if LINUX_VERSION_CODE < LinuxVersionCode(2,4,0)
SHT->proc_dir = &proc_scsi_ips;
#else
SHT->proc_name = "ips";
#endif
#if defined(CONFIG_PCI)
/* initalize number of controllers */
ips_num_controllers = 0;
ips_next_controller = 0;
ips_released_controllers = 0;
if (!pci_present())
return (0);
morpheus = pci_find_device(IPS_VENDORID, IPS_DEVICEID_MORPHEUS, morpheus);
trombone = pci_find_device(IPS_VENDORID, IPS_DEVICEID_COPPERHEAD, trombone);
/* determine which controller to probe first */
if (!morpheus) {
/* we only have trombone */
dev[0] = trombone;
dev[1] = NULL;
deviceID[0] = IPS_DEVICEID_COPPERHEAD;
} else if (!trombone) {
/* we only have morpheus */
dev[0] = morpheus;
dev[1] = NULL;
deviceID[0] = IPS_DEVICEID_MORPHEUS;
} else {
/* we have both in the system */
if (trombone->bus->number < morpheus->bus->number) {
dev[0] = trombone;
dev[1] = morpheus;
deviceID[0] = IPS_DEVICEID_COPPERHEAD;
deviceID[1] = IPS_DEVICEID_MORPHEUS;
} else if (trombone->bus->number > morpheus->bus->number) {
dev[0] = morpheus;
dev[1] = trombone;
deviceID[0] = IPS_DEVICEID_MORPHEUS;
deviceID[1] = IPS_DEVICEID_COPPERHEAD;
} else {
/* further detection required */
if (trombone->devfn < morpheus->devfn) {
dev[0] = trombone;
dev[1] = morpheus;
deviceID[0] = IPS_DEVICEID_COPPERHEAD;
deviceID[1] = IPS_DEVICEID_MORPHEUS;
} else {
dev[0] = morpheus;
dev[1] = trombone;
deviceID[0] = IPS_DEVICEID_MORPHEUS;
deviceID[1] = IPS_DEVICEID_COPPERHEAD;
}
}
}
/**********************************************************************************/
/* For Kernel Versions 2.4 or greater, use new PCI ( Hot Pluggable ) architecture */
/**********************************************************************************/
#if LINUX_VERSION_CODE >= LinuxVersionCode(2,4,0)
#if LINUX_VERSION_CODE < LinuxVersionCode(2,5,0)
spin_unlock_irq(&io_request_lock);
#endif
......@@ -779,485 +603,64 @@ ips_detect(Scsi_Host_Template *SHT) {
register_reboot_notifier(&ips_notifier);
return (ips_num_controllers);
#endif
/* Now scan the controllers */
for (i = 0; i < 2; i++) {
if (!dev[i])
break;
do {
if (ips_next_controller >= IPS_MAX_ADAPTERS)
break;
#if LINUX_VERSION_CODE >= LinuxVersionCode(2,4,0)
if (pci_enable_device(dev[i]))
break;
#endif
/* stuff that we get in dev */
irq = dev[i]->irq;
bus = dev[i]->bus->number;
func = dev[i]->devfn;
/* Init MEM/IO addresses to 0 */
mem_addr = 0;
io_addr = 0;
mem_len = 0;
io_len = 0;
for (j = 0; j < 2; j++) {
#if LINUX_VERSION_CODE >= LinuxVersionCode(2,4,0)
if (!pci_resource_start(dev[i], j))
break;
if (pci_resource_flags(dev[i], j) & IORESOURCE_IO) {
io_addr = pci_resource_start(dev[i], j);
io_len = pci_resource_len(dev[i], j);
} else {
mem_addr = pci_resource_start(dev[i], j);
mem_len = pci_resource_len(dev[i], j);
}
#else
if (!dev[i]->base_address[j])
break;
if ((dev[i]->base_address[j] & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_IO) {
barnum = PCI_BASE_ADDRESS_0 + (j * 4);
io_addr = dev[i]->base_address[j] & PCI_BASE_ADDRESS_IO_MASK;
/* Get Size */
pci_read_config_dword(dev[i], barnum, &currbar);
pci_write_config_dword(dev[i], barnum, ~0);
pci_read_config_dword(dev[i], barnum, &maskbar);
pci_write_config_dword(dev[i], barnum, currbar);
io_len = ~(maskbar & PCI_BASE_ADDRESS_IO_MASK) + 1;
} else {
barnum = PCI_BASE_ADDRESS_0 + (j * 4);
mem_addr = dev[i]->base_address[j] & PCI_BASE_ADDRESS_MEM_MASK;
/* Get Size */
pci_read_config_dword(dev[i], barnum, &currbar);
pci_write_config_dword(dev[i], barnum, ~0);
pci_read_config_dword(dev[i], barnum, &maskbar);
pci_write_config_dword(dev[i], barnum, currbar);
mem_len = ~(maskbar & PCI_BASE_ADDRESS_MEM_MASK) + 1;
}
#endif
}
/* setup memory mapped area (if applicable) */
if (mem_addr) {
uint32_t base;
uint32_t offs;
DEBUG_VAR(1, "(%s%d) detect, Memory region %x, size: %d",
ips_name, ips_next_controller, mem_addr, mem_len);
#if LINUX_VERSION_CODE >= LinuxVersionCode(2,4,0)
if (!request_mem_region(mem_addr, mem_len, "ips")) {
/* Couldn't allocate io space */
printk(KERN_WARNING "(%s%d) couldn't allocate IO space %x len %d.\n",
ips_name, ips_next_controller, io_addr, io_len);
ips_next_controller++;
continue;
}
#endif
base = mem_addr & PAGE_MASK;
offs = mem_addr - base;
ioremap_ptr = ioremap(base, PAGE_SIZE);
mem_ptr = ioremap_ptr + offs;
} else {
ioremap_ptr = NULL;
mem_ptr = NULL;
}
/* setup I/O mapped area (if applicable) */
if (io_addr) {
DEBUG_VAR(1, "(%s%d) detect, IO region %x, size: %d",
ips_name, ips_next_controller, io_addr, io_len);
if (!request_region(io_addr, io_len, "ips")) {
/* Couldn't allocate io space */
printk(KERN_WARNING "(%s%d) couldn't allocate IO space %x len %d.\n",
ips_name, ips_next_controller, io_addr, io_len);
ips_next_controller++;
continue;
}
}
/* get planer status */
if (pci_read_config_word(dev[i], 0x04, &planer)) {
printk(KERN_WARNING "(%s%d) can't get planer status.\n",
ips_name, ips_next_controller);
ips_next_controller++;
continue;
}
/* check to see if an onboard planer controller is disabled */
if (!(planer & 0x000C)) {
DEBUG_VAR(1, "(%s%d) detect, Onboard ServeRAID disabled by BIOS",
ips_name, ips_next_controller);
ips_next_controller++;
continue;
}
DEBUG_VAR(1, "(%s%d) detect bus %d, func %x, irq %d, io %x, mem: %x, ptr: %p",
ips_name, ips_next_controller, bus, func, irq, io_addr, mem_addr, mem_ptr);
/* get the revision ID */
if (pci_read_config_byte(dev[i], PCI_REVISION_ID, &revision_id)) {
printk(KERN_WARNING "(%s%d) can't get revision id.\n",
ips_name, ips_next_controller);
ips_next_controller++;
continue;
}
#if LINUX_VERSION_CODE < LinuxVersionCode(2,4,0)
/* get the subdevice id */
if (pci_read_config_word(dev[i], PCI_SUBSYSTEM_ID, &subdevice_id)) {
printk(KERN_WARNING "(%s%d) can't get subdevice id.\n",
ips_name, ips_next_controller);
ips_next_controller++;
continue;
}
#else
subdevice_id = dev[i]->subsystem_device;
#endif
/* found a controller */
sh = scsi_register(SHT, sizeof(ips_ha_t));
if (sh == NULL) {
printk(KERN_WARNING "(%s%d) Unable to register controller with SCSI subsystem - skipping controller\n",
ips_name, ips_next_controller);
ips_next_controller++;
continue;
}
ha = IPS_HA(sh);
memset(ha, 0, sizeof(ips_ha_t));
ips_sh[ips_next_controller] = sh;
ips_ha[ips_next_controller] = ha;
ips_num_controllers++;
ha->active = 1;
ha->enq = kmalloc(sizeof(IPS_ENQ), GFP_KERNEL);
if (!ha->enq) {
printk(KERN_WARNING "(%s%d) Unable to allocate host inquiry structure - skipping contoller\n",
ips_name, ips_next_controller);
ha->active = 0;
ips_free(ha);
scsi_unregister(sh);
ips_ha[ips_next_controller] = 0;
ips_sh[ips_next_controller] = 0;
ips_next_controller++;
ips_num_controllers--;
continue;
}
ha->adapt = kmalloc(sizeof(IPS_ADAPTER), GFP_KERNEL);
if (!ha->adapt) {
printk(KERN_WARNING "(%s%d) Unable to allocate host adapt structure - skipping controller\n",
ips_name, ips_next_controller);
ha->active = 0;
ips_free(ha);
scsi_unregister(sh);
ips_ha[ips_next_controller] = 0;
ips_sh[ips_next_controller] = 0;
ips_next_controller++;
ips_num_controllers--;
continue;
}
ha->conf = kmalloc(sizeof(IPS_CONF), GFP_KERNEL);
if (!ha->conf) {
printk(KERN_WARNING "(%s%d) Unable to allocate host conf structure - skipping controller\n",
ips_name, ips_next_controller);
ha->active = 0;
ips_free(ha);
scsi_unregister(sh);
ips_ha[ips_next_controller] = 0;
ips_sh[ips_next_controller] = 0;
ips_next_controller++;
ips_num_controllers--;
continue;
}
ha->nvram = kmalloc(sizeof(IPS_NVRAM_P5), GFP_KERNEL);
if (!ha->nvram) {
printk(KERN_WARNING "(%s%d) Unable to allocate host nvram structure - skipping controller\n",
ips_name, ips_next_controller);
ha->active = 0;
ips_free(ha);
scsi_unregister(sh);
ips_ha[ips_next_controller] = 0;
ips_sh[ips_next_controller] = 0;
ips_next_controller++;
ips_num_controllers--;
continue;
}
ha->subsys = kmalloc(sizeof(IPS_SUBSYS), GFP_KERNEL);
if (!ha->subsys) {
printk(KERN_WARNING "(%s%d) Unable to allocate host subsystem structure - skipping controller\n",
ips_name, ips_next_controller);
ha->active = 0;
ips_free(ha);
scsi_unregister(sh);
ips_ha[ips_next_controller] = 0;
ips_sh[ips_next_controller] = 0;
ips_next_controller++;
ips_num_controllers--;
continue;
}
ha->dummy = kmalloc(sizeof(IPS_IO_CMD), GFP_KERNEL);
if (!ha->dummy) {
printk(KERN_WARNING "(%s%d) Unable to allocate host dummy structure - skipping controller\n",
ips_name, ips_next_controller);
ha->active = 0;
ips_free(ha);
scsi_unregister(sh);
ips_ha[ips_next_controller] = 0;
ips_sh[ips_next_controller] = 0;
ips_next_controller++;
ips_num_controllers--;
continue;
}
for (count = PAGE_SIZE, ha->ioctl_order = 0;
count < ips_ioctlsize;
ha->ioctl_order++, count <<= 1);
ha->ioctl_data = (char *) __get_free_pages(GFP_KERNEL, ha->ioctl_order);
ha->ioctl_datasize = count;
if (!ha->ioctl_data) {
printk(KERN_WARNING "(%s%d) Unable to allocate ioctl data\n",
ips_name, ips_next_controller);
ha->ioctl_data = NULL;
ha->ioctl_order = 0;
ha->ioctl_datasize = 0;
}
/* Store away needed values for later use */
sh->io_port = io_addr;
sh->n_io_port = io_addr ? 255 : 0;
sh->unique_id = (io_addr) ? io_addr : mem_addr;
sh->irq = irq;
//sh->select_queue_depths = ips_select_queue_depth;
sh->sg_tablesize = sh->hostt->sg_tablesize;
sh->can_queue = sh->hostt->can_queue;
sh->cmd_per_lun = sh->hostt->cmd_per_lun;
sh->unchecked_isa_dma = sh->hostt->unchecked_isa_dma;
sh->use_clustering = sh->hostt->use_clustering;
#if LINUX_VERSION_CODE >= LinuxVersionCode(2,4,7)
sh->max_sectors = 128;
#endif
#if LINUX_VERSION_CODE < LinuxVersionCode(2,4,0)
sh->wish_block = FALSE;
#endif
/* Store info in HA structure */
ha->irq = irq;
ha->io_addr = io_addr;
ha->io_len = io_len;
ha->mem_addr = mem_addr;
ha->mem_len = mem_len;
ha->mem_ptr = mem_ptr;
ha->ioremap_ptr = ioremap_ptr;
ha->host_num = ips_next_controller;
ha->revision_id = revision_id;
ha->slot_num = PCI_SLOT(dev[i]->devfn);
ha->device_id = deviceID[i];
ha->subdevice_id = subdevice_id;
ha->pcidev = dev[i];
/*
* Setup Functions
*/
if (IPS_IS_MORPHEUS(ha)) {
/* morpheus */
ha->func.isintr = ips_isintr_morpheus;
ha->func.isinit = ips_isinit_morpheus;
ha->func.issue = ips_issue_i2o_memio;
ha->func.init = ips_init_morpheus;
ha->func.statupd = ips_statupd_morpheus;
ha->func.reset = ips_reset_morpheus;
ha->func.intr = ips_intr_morpheus;
ha->func.enableint = ips_enable_int_morpheus;
} else if (IPS_USE_MEMIO(ha)) {
/* copperhead w/MEMIO */
ha->func.isintr = ips_isintr_copperhead_memio;
ha->func.isinit = ips_isinit_copperhead_memio;
ha->func.init = ips_init_copperhead_memio;
ha->func.statupd = ips_statupd_copperhead_memio;
ha->func.statinit = ips_statinit_memio;
ha->func.reset = ips_reset_copperhead_memio;
ha->func.intr = ips_intr_copperhead;
ha->func.erasebios = ips_erase_bios_memio;
ha->func.programbios = ips_program_bios_memio;
ha->func.verifybios = ips_verify_bios_memio;
ha->func.enableint = ips_enable_int_copperhead_memio;
if (IPS_USE_I2O_DELIVER(ha))
ha->func.issue = ips_issue_i2o_memio;
else
ha->func.issue = ips_issue_copperhead_memio;
} else {
/* copperhead */
ha->func.isintr = ips_isintr_copperhead;
ha->func.isinit = ips_isinit_copperhead;
ha->func.init = ips_init_copperhead;
ha->func.statupd = ips_statupd_copperhead;
ha->func.statinit = ips_statinit;
ha->func.reset = ips_reset_copperhead;
ha->func.intr = ips_intr_copperhead;
ha->func.erasebios = ips_erase_bios;
ha->func.programbios = ips_program_bios;
ha->func.verifybios = ips_verify_bios;
ha->func.enableint = ips_enable_int_copperhead;
if (IPS_USE_I2O_DELIVER(ha))
ha->func.issue = ips_issue_i2o;
else
ha->func.issue = ips_issue_copperhead;
}
/*
* Initialize the card if it isn't already
*/
if (!(*ha->func.isinit)(ha)) {
if (!(*ha->func.init)(ha)) {
/*
* Initialization failed
*/
printk(KERN_WARNING "(%s%d) unable to initialize controller - skipping controller\n",
ips_name, ips_next_controller);
ha->active = 0;
ips_free(ha);
scsi_unregister(sh);
ips_ha[ips_next_controller] = 0;
ips_sh[ips_next_controller] = 0;
ips_next_controller++;
ips_num_controllers--;
continue;
}
}
/* install the interrupt handler */
if (request_irq(irq, do_ipsintr, SA_SHIRQ, ips_name, ha)) {
printk(KERN_WARNING "(%s%d) unable to install interrupt handler - skipping controller\n",
ips_name, ips_next_controller);
ha->active = 0;
ips_free(ha);
scsi_unregister(sh);
ips_ha[ips_next_controller] = 0;
ips_sh[ips_next_controller] = 0;
ips_next_controller++;
ips_num_controllers--;
continue;
}
}
/*
* Allocate a temporary SCB for initialization
*/
ha->max_cmds = 1;
if (!ips_allocatescbs(ha)) {
/* couldn't allocate a temp SCB */
printk(KERN_WARNING "(%s%d) unable to allocate CCBs - skipping contoller\n",
ips_name, ips_next_controller);
ha->active = 0;
ips_free(ha);
scsi_unregister(sh);
ips_ha[ips_next_controller] = 0;
ips_sh[ips_next_controller] = 0;
free_irq(ha->irq, ha);
ips_next_controller++;
ips_num_controllers--;
continue;
}
ips_next_controller++;
} while ((dev[i] = pci_find_device(IPS_VENDORID, deviceID[i], dev[i])));
}
/****************************************************************************/
/* configure the function pointers to use the functions that will work */
/* with the found version of the adapter */
/****************************************************************************/
static void ips_setup_funclist(ips_ha_t *ha){
/*
* Do Phase 2 Initialization
* Controller init
/*
* Setup Functions
*/
for (i = 0; i < ips_next_controller; i++) {
if (ips_ha[i] == 0) {
printk(KERN_WARNING "(%s%d) ignoring bad controller\n", ips_name, i);
continue;
}
if (ips_init_phase2(i) != SUCCESS)
ips_num_controllers--;
if (IPS_IS_MORPHEUS(ha)) {
/* morpheus / marco / sebring */
ha->func.isintr = ips_isintr_morpheus;
ha->func.isinit = ips_isinit_morpheus;
ha->func.issue = ips_issue_i2o_memio;
ha->func.init = ips_init_morpheus;
ha->func.statupd = ips_statupd_morpheus;
ha->func.reset = ips_reset_morpheus;
ha->func.intr = ips_intr_morpheus;
ha->func.enableint = ips_enable_int_morpheus;
} else if (IPS_USE_MEMIO(ha)) {
/* copperhead w/MEMIO */
ha->func.isintr = ips_isintr_copperhead_memio;
ha->func.isinit = ips_isinit_copperhead_memio;
ha->func.init = ips_init_copperhead_memio;
ha->func.statupd = ips_statupd_copperhead_memio;
ha->func.statinit = ips_statinit_memio;
ha->func.reset = ips_reset_copperhead_memio;
ha->func.intr = ips_intr_copperhead;
ha->func.erasebios = ips_erase_bios_memio;
ha->func.programbios = ips_program_bios_memio;
ha->func.verifybios = ips_verify_bios_memio;
ha->func.enableint = ips_enable_int_copperhead_memio;
if (IPS_USE_I2O_DELIVER(ha))
ha->func.issue = ips_issue_i2o_memio;
else
ha->func.issue = ips_issue_copperhead_memio;
} else {
/* copperhead */
ha->func.isintr = ips_isintr_copperhead;
ha->func.isinit = ips_isinit_copperhead;
ha->func.init = ips_init_copperhead;
ha->func.statupd = ips_statupd_copperhead;
ha->func.statinit = ips_statinit;
ha->func.reset = ips_reset_copperhead;
ha->func.intr = ips_intr_copperhead;
ha->func.erasebios = ips_erase_bios;
ha->func.programbios = ips_program_bios;
ha->func.verifybios = ips_verify_bios;
ha->func.enableint = ips_enable_int_copperhead;
if (IPS_USE_I2O_DELIVER(ha))
ha->func.issue = ips_issue_i2o;
else
ha->func.issue = ips_issue_copperhead;
}
if (ips_num_controllers > 0)
register_reboot_notifier(&ips_notifier);
return (ips_num_controllers);
#else
/* No PCI -- No ServeRAID */
return (0);
#endif /* CONFIG_PCI */
}
/****************************************************************************/
......@@ -1282,9 +685,7 @@ ips_release(struct Scsi_Host *sh) {
if (i == IPS_MAX_ADAPTERS) {
printk(KERN_WARNING "(%s) release, invalid Scsi_Host pointer.\n",
ips_name);
#if LINUX_VERSION_CODE >= LinuxVersionCode(2,4,0)
BUG();
#endif
return (FALSE);
}
......@@ -3303,7 +2704,7 @@ ips_next(ips_ha_t *ha, int intr) {
sg = SC->request_buffer;
scb->sg_count = pci_map_sg(ha->pcidev, sg, SC->use_sg,
IPS_DMA_DIR(scb));
scsi_to_pci_dma_dir(SC->sc_data_direction));
scb->flags |= IPS_SCB_MAP_SG;
if (scb->sg_count == 1) {
if (sg_dma_len(sg) > ha->max_xfer) {
......@@ -3363,7 +2764,8 @@ ips_next(ips_ha_t *ha, int intr) {
scb->dcdb.transfer_length = scb->data_len;
scb->data_busaddr = pci_map_single(ha->pcidev, SC->request_buffer,
scb->data_len, IPS_DMA_DIR(scb));
scb->data_len,
scsi_to_pci_dma_dir(SC->sc_data_direction));
scb->flags |= IPS_SCB_MAP_SINGLE;
scb->sg_len = 0;
} else {
......@@ -4957,10 +4359,8 @@ ips_free(ips_ha_t *ha) {
ha->mem_ptr = NULL;
}
#if LINUX_VERSION_CODE >= LinuxVersionCode(2,4,0)
if (ha->mem_addr)
release_mem_region(ha->mem_addr, ha->mem_len);
#endif
ha->mem_addr = 0;
}
......@@ -5489,6 +4889,29 @@ ips_init_morpheus(ips_ha_t *ha) {
Post = readl(ha->mem_ptr + IPS_REG_I960_MSG0);
if (Post == 0x4F00) { /* If Flashing the Battery PIC */
printk(KERN_WARNING "Flashing Battery PIC, Please wait ...\n" );
/* Clear the interrupt bit */
Isr = (uint32_t) IPS_BIT_I960_MSG0I;
writel(Isr, ha->mem_ptr + IPS_REG_I2O_HIR);
for (i = 0; i < 120; i++) { /* Wait Up to 2 Min. for Completion */
Post = readl(ha->mem_ptr + IPS_REG_I960_MSG0);
if (Post != 0x4F00)
break;
/* Delay for 1 Second */
MDELAY(IPS_ONE_SEC);
}
if (i >= 120) {
printk(KERN_WARNING "(%s%d) timeout waiting for Battery PIC Flash\n",
ips_name, ha->host_num);
return (0);
}
}
/* Clear the interrupt bit */
Isr = (uint32_t) IPS_BIT_I960_MSG0I;
writel(Isr, ha->mem_ptr + IPS_REG_I2O_HIR);
......@@ -6144,8 +5567,7 @@ ips_write_driver_status(ips_ha_t *ha, int intr) {
if (le32_to_cpu(ha->nvram->signature) != IPS_NVRAM_P5_SIG) {
DEBUG_VAR(1, "(%s%d) NVRAM page 5 has an invalid signature: %X.",
ips_name, ha->host_num, ha->nvram->signature);
return (1);
ha->nvram->signature = IPS_NVRAM_P5_SIG;
}
DEBUG_VAR(2, "(%s%d) Ad Type: %d, Ad Slot: %d, BIOS: %c%c%c%c %c%c%c%c.",
......@@ -7186,10 +6608,8 @@ static int ips_get_version_info(ips_ha_t *ha, IPS_VERSION_DATA *Buffer, int intr
#if defined (MODULE) || (LINUX_VERSION_CODE >= LinuxVersionCode(2,4,0))
static Scsi_Host_Template driver_template = IPS;
#include "scsi_module.c"
#endif
static int ips_abort_init(ips_ha_t *ha, struct Scsi_Host *sh, int index){
ha->active = 0;
......@@ -7200,7 +6620,6 @@ static int ips_abort_init(ips_ha_t *ha, struct Scsi_Host *sh, int index){
return -1;
}
#if LINUX_VERSION_CODE >= LinuxVersionCode(2,4,0)
/*---------------------------------------------------------------------------*/
/* Routine Name: ips_remove_device */
......@@ -7285,6 +6704,7 @@ static int ips_init_phase1( struct pci_dev *pci_dev, int *indexPtr )
dma_addr_t dma_address;
char *ioremap_ptr;
char *mem_ptr;
uint32_t IsDead;
METHOD_TRACE("ips_init_phase1", 1);
index = IPS_MAX_ADAPTERS;
......@@ -7382,7 +6802,7 @@ static int ips_init_phase1( struct pci_dev *pci_dev, int *indexPtr )
return ips_abort_init(ha, sh, index);
}
ha->adapt = pci_alloc_consistent(ha->pcidev, sizeof(IPS_ADAPTER) +
ha->adapt = pci_alloc_consistent(pci_dev, sizeof(IPS_ADAPTER) +
sizeof(IPS_IO_CMD), &dma_address);
if (!ha->adapt) {
printk(KERN_WARNING "Unable to allocate host adapt & dummy structures\n");
......@@ -7460,54 +6880,15 @@ static int ips_init_phase1( struct pci_dev *pci_dev, int *indexPtr )
/*
* Setup Functions
*/
if (IPS_IS_MORPHEUS(ha)) {
/* morpheus */
ha->func.isintr = ips_isintr_morpheus;
ha->func.isinit = ips_isinit_morpheus;
ha->func.issue = ips_issue_i2o_memio;
ha->func.init = ips_init_morpheus;
ha->func.statupd = ips_statupd_morpheus;
ha->func.reset = ips_reset_morpheus;
ha->func.intr = ips_intr_morpheus;
ha->func.enableint = ips_enable_int_morpheus;
} else if (IPS_USE_MEMIO(ha)) {
/* copperhead w/MEMIO */
ha->func.isintr = ips_isintr_copperhead_memio;
ha->func.isinit = ips_isinit_copperhead_memio;
ha->func.init = ips_init_copperhead_memio;
ha->func.statupd = ips_statupd_copperhead_memio;
ha->func.statinit = ips_statinit_memio;
ha->func.reset = ips_reset_copperhead_memio;
ha->func.intr = ips_intr_copperhead;
ha->func.erasebios = ips_erase_bios_memio;
ha->func.programbios = ips_program_bios_memio;
ha->func.verifybios = ips_verify_bios_memio;
ha->func.enableint = ips_enable_int_copperhead_memio;
if (IPS_USE_I2O_DELIVER(ha))
ha->func.issue = ips_issue_i2o_memio;
else
ha->func.issue = ips_issue_copperhead_memio;
} else {
/* copperhead */
ha->func.isintr = ips_isintr_copperhead;
ha->func.isinit = ips_isinit_copperhead;
ha->func.init = ips_init_copperhead;
ha->func.statupd = ips_statupd_copperhead;
ha->func.statinit = ips_statinit;
ha->func.reset = ips_reset_copperhead;
ha->func.intr = ips_intr_copperhead;
ha->func.erasebios = ips_erase_bios;
ha->func.programbios = ips_program_bios;
ha->func.verifybios = ips_verify_bios;
ha->func.enableint = ips_enable_int_copperhead;
if (IPS_USE_I2O_DELIVER(ha))
ha->func.issue = ips_issue_i2o;
else
ha->func.issue = ips_issue_copperhead;
}
ips_setup_funclist(ha);
if ( IPS_IS_MORPHEUS( ha ) ) {
/* If Morpheus appears dead, reset it */
IsDead = readl( ha->mem_ptr + IPS_REG_I960_MSG1 );
if ( IsDead == 0xDEADBEEF ) {
ips_reset_morpheus( ha );
}
}
/*
* Initialize the card if it isn't already
*/
......@@ -7542,7 +6923,6 @@ static int ips_init_phase1( struct pci_dev *pci_dev, int *indexPtr )
return SUCCESS;
}
#endif
/*---------------------------------------------------------------------------*/
/* Routine Name: ips_init_phase2 */
......
......@@ -349,28 +349,9 @@
#define IPS_SCSI_MP3_Removeable 0x04
#define IPS_SCSI_MP3_AllocateSurface 0x08
/*
* Configuration Structure Flags
*/
#define IPS_CFG_USEROPT_UPDATECOUNT(cfg) (((cfg)->UserOpt & 0xffff000) >> 16)
#define IPS_CFG_USEROPT_CONCURSTART(cfg) (((cfg)->UserOpt & 0xf000) >> 12)
#define IPS_CFG_USEROPT_STARTUPDELAY(cfg) (((cfg)->UserOpt & 0xf00) >> 8)
#define IPS_CFG_USEROPT_REARRANGE(cfg) ((cfg)->UserOpt & 0x80)
#define IPS_CFG_USEROPT_CDBOOT(cfg) ((cfg)->UserOpt & 0x40)
#define IPS_CFG_USEROPT_CLUSTER(cfg) ((cfg)->UserOpt & 0x20)
/*
* Host adapter Flags (bit numbers)
*/
#define IPS_IN_INTR 0
#define IPS_IN_ABORT 1
#define IPS_IN_RESET 2
/*
* SCB Flags
*/
#define IPS_SCB_ACTIVE 0x00001
#define IPS_SCB_WAITING 0x00002
#define IPS_SCB_MAP_SG 0x00008
#define IPS_SCB_MAP_SINGLE 0X00010
......@@ -381,7 +362,6 @@
#define IPS_COPPIOCCMD (('C'<<8) | 66)
#define IPS_NUMCTRLS (('C'<<8) | 68)
#define IPS_CTRLINFO (('C'<<8) | 69)
#define IPS_FLASHBIOS (('C'<<8) | 70)
/* flashing defines */
#define IPS_FW_IMAGE 0x00
......@@ -406,36 +386,7 @@
/*
* Scsi_Host Template
*/
#if LINUX_VERSION_CODE < LinuxVersionCode(2,4,0)
#define IPS { \
.module = NULL, \
.proc_info = NULL, \
.proc_dir = NULL, \
.name = NULL, \
.detect = ips_detect, \
.release = ips_release, \
.info = ips_info, \
.command = NULL, \
.queuecommand = ips_queue, \
.eh_strategy_handler = NULL, \
.eh_abort_handler = ips_eh_abort, \
.eh_device_reset_handler = NULL, \
.eh_bus_reset_handler = NULL, \
.eh_host_reset_handler = ips_eh_reset, \
.abort = NULL, \
.reset = NULL, \
.slave_attach = NULL, \
.bios_param = ips_biosparam,\
.can_queue = 0, \
.this_id = -1, \
.sg_tablesize = IPS_MAX_SG, \
.cmd_per_lun = 3, \
.present = 0, \
.unchecked_isa_dma = 0, \
.use_clustering = ENABLE_CLUSTERING, \
.use_new_eh_code = 1 \
}
#elif LINUX_VERSION_CODE < LinuxVersionCode(2,5,0)
#if LINUX_VERSION_CODE < LinuxVersionCode(2,5,0)
#define IPS{ \
.module = NULL, \
.proc_info = NULL, \
......@@ -1005,19 +956,6 @@ typedef struct {
int option_value;
} IPS_OPTION;
typedef struct {
void *userbuffer;
uint32_t usersize;
void *kernbuffer;
uint32_t kernsize;
void *ha;
void *SC;
void *pt;
struct semaphore *sem;
uint32_t offset;
uint32_t retcode;
} IPS_FLASH_DATA;
/*
* Status Info
*/
......
......@@ -50,8 +50,8 @@
#include <asm/pgtable.h>
#include <asm/irq.h>
#include <asm/hardware.h>
#include <asm/parisc-device.h>
#include <asm/delay.h>
#include <asm/gsc.h>
#include <linux/module.h>
......
......@@ -82,6 +82,7 @@
** Etc...
**
** Supported NCR/SYMBIOS chips:
** 53C720 (Wide, Fast SCSI-2, HP Zalon)
** 53C810 (8 bits, Fast SCSI-2, no rom BIOS)
** 53C815 (8 bits, Fast SCSI-2, on board rom BIOS)
** 53C820 (Wide, Fast SCSI-2, no rom BIOS)
......@@ -130,6 +131,8 @@
#include <linux/sched.h>
#include <linux/errno.h>
#include <linux/pci.h>
#include <linux/dma-mapping.h>
#include <linux/interrupt.h>
#include <linux/string.h>
#include <linux/mm.h>
#include <linux/ioport.h>
......@@ -178,6 +181,24 @@
typedef u32 u_int32;
typedef u64 u_int64;
typedef u_long vm_offset_t;
#ifdef __hppa__
/*
* Yuck. Current plan is to use ncr58c8xx.c for non-pci big endian
* chips, and sym53c8xx.c for pci little endian chips. Define this
* here so it gets seen by sym53c8xx_defs.h, pulled in via ncr53c8xx.h.
*/
#define SCSI_NCR_BIG_ENDIAN
/* INTFLY interrupts don't always seem to get serviced atm..... */
#define SIMULATED_INTFLY
#endif
#if defined(CONFIG_SCSI_ZALON) || defined(CONFIG_SCSI_ZALON_MODULE)
#define ENABLE_SCSI_ZALON
#include <asm/parisc-device.h>
#include "zalon.h"
#endif
#include "ncr53c8xx.h"
/*
......@@ -379,6 +400,8 @@ static Scsi_Host_Template *the_template = NULL;
static void ncr53c8xx_intr(int irq, void *dev_id, struct pt_regs * regs);
static void ncr53c8xx_timeout(unsigned long np);
static int ncr53c8xx_proc_info(char *buffer, char **start, off_t offset,
int length, int hostno, int func);
#define initverbose (driver_setup.verbose)
#define bootverbose (np->verbose)
......@@ -450,7 +473,8 @@ static u_char Tekram_sync[16] __initdata =
#define SIR_RESEL_BAD_I_T_L (15)
#define SIR_RESEL_BAD_I_T_L_Q (16)
#define SIR_DONE_OVERFLOW (17)
#define SIR_MAX (17)
#define SIR_INTFLY (18)
#define SIR_MAX (18)
/*==========================================================
**
......@@ -622,6 +646,15 @@ struct tcb {
** negotiation of wide and synch transfer and device quirks.
**----------------------------------------------------------------
*/
#ifdef SCSI_NCR_BIG_ENDIAN
/*0*/ u_short period;
/*2*/ u_char sval;
/*3*/ u_char minsync;
/*0*/ u_char wval;
/*1*/ u_char widedone;
/*2*/ u_char quirks;
/*3*/ u_char maxoffs;
#else
/*0*/ u_char minsync;
/*1*/ u_char sval;
/*2*/ u_short period;
......@@ -629,6 +662,7 @@ struct tcb {
/*1*/ u_char quirks;
/*2*/ u_char widedone;
/*3*/ u_char wval;
#endif
#ifdef SCSI_NCR_INTEGRITY_CHECKING
u_char ic_min_sync;
......@@ -839,10 +873,17 @@ struct head {
/*
** Last four bytes (host)
*/
#ifdef SCSI_NCR_BIG_ENDIAN
#define actualquirks phys.header.status[3]
#define host_status phys.header.status[2]
#define scsi_status phys.header.status[1]
#define parity_status phys.header.status[0]
#else
#define actualquirks phys.header.status[0]
#define host_status phys.header.status[1]
#define scsi_status phys.header.status[2]
#define parity_status phys.header.status[3]
#endif
/*
** First four bytes (script)
......@@ -1026,8 +1067,8 @@ struct ncb {
** be used for probing adapter implementation differences.
**----------------------------------------------------------------
*/
u_char sv_scntl0, sv_scntl3, sv_dmode, sv_dcntl, sv_ctest3, sv_ctest4,
sv_ctest5, sv_gpcntl, sv_stest2, sv_stest4;
u_char sv_scntl0, sv_scntl3, sv_dmode, sv_dcntl, sv_ctest0, sv_ctest3,
sv_ctest4, sv_ctest5, sv_gpcntl, sv_stest2, sv_stest4;
/*----------------------------------------------------------------
** Actual initial value of IO register bits used by the
......@@ -1035,8 +1076,8 @@ struct ncb {
** features that are to be enabled.
**----------------------------------------------------------------
*/
u_char rv_scntl0, rv_scntl3, rv_dmode, rv_dcntl, rv_ctest3, rv_ctest4,
rv_ctest5, rv_stest2;
u_char rv_scntl0, rv_scntl3, rv_dmode, rv_dcntl, rv_ctest0, rv_ctest3,
rv_ctest4, rv_ctest5, rv_stest2;
/*----------------------------------------------------------------
** Targets management.
......@@ -1078,7 +1119,7 @@ struct ncb {
** General controller parameters and configuration.
**----------------------------------------------------------------
*/
pcidev_t pdev;
device_t dev;
u_short device_id; /* PCI device id */
u_char revision_id; /* PCI device revision id */
u_char bus; /* PCI BUS number */
......@@ -1158,7 +1199,7 @@ struct ncb {
*/
struct ccb *ccb; /* Global CCB */
struct usrcmd user; /* Command from user */
u_char release_stage; /* Synchronisation stage on release */
volatile u_char release_stage; /* Synchronisation stage on release */
#ifdef SCSI_NCR_INTEGRITY_CHECKING
/*----------------------------------------------------------------
......@@ -1196,6 +1237,23 @@ struct ncb {
**----------------------------------------------------------
*/
/*
** For HP Zalon/53c720 systems, the Zalon interface
** between CPU and 53c720 does prefetches, which causes
** problems with self modifying scripts. The problem
** is overcome by calling a dummy subroutine after each
** modification, to force a refetch of the script on
** return from the subroutine.
*/
#ifdef ENABLE_SCSI_ZALON
#define PREFETCH_FLUSH_CNT 2
#define PREFETCH_FLUSH SCR_CALL, PADDRH (wait_dma),
#else
#define PREFETCH_FLUSH_CNT 0
#define PREFETCH_FLUSH
#endif
/*
** Script fragments which are loaded into the on-chip RAM
** of 825A, 875 and 895 chips.
......@@ -1204,7 +1262,7 @@ struct script {
ncrcmd start [ 5];
ncrcmd startpos [ 1];
ncrcmd select [ 6];
ncrcmd select2 [ 9];
ncrcmd select2 [ 9 + PREFETCH_FLUSH_CNT];
ncrcmd loadpos [ 4];
ncrcmd send_ident [ 9];
ncrcmd prepare [ 6];
......@@ -1220,7 +1278,7 @@ struct script {
ncrcmd setmsg [ 7];
ncrcmd cleanup [ 6];
ncrcmd complete [ 9];
ncrcmd cleanup_ok [ 8];
ncrcmd cleanup_ok [ 8 + PREFETCH_FLUSH_CNT];
ncrcmd cleanup0 [ 1];
#ifndef SCSI_NCR_CCB_DONE_SUPPORT
ncrcmd signal [ 12];
......@@ -1238,11 +1296,11 @@ struct script {
ncrcmd idle [ 2];
ncrcmd reselect [ 8];
ncrcmd reselected [ 8];
ncrcmd resel_dsa [ 6];
ncrcmd resel_dsa [ 6 + PREFETCH_FLUSH_CNT];
ncrcmd loadpos1 [ 4];
ncrcmd resel_lun [ 6];
ncrcmd resel_tag [ 6];
ncrcmd jump_to_nexus [ 4];
ncrcmd jump_to_nexus [ 4 + PREFETCH_FLUSH_CNT];
ncrcmd nexus_indirect [ 4];
ncrcmd resel_notag [ 4];
ncrcmd data_in [MAX_SCATTERL * 4];
......@@ -1263,7 +1321,7 @@ struct scripth {
#endif
ncrcmd select_no_atn [ 8];
ncrcmd cancel [ 4];
ncrcmd skip [ 9];
ncrcmd skip [ 9 + PREFETCH_FLUSH_CNT];
ncrcmd skip2 [ 19];
ncrcmd par_err_data_in [ 6];
ncrcmd par_err_other [ 4];
......@@ -1296,9 +1354,10 @@ struct scripth {
ncrcmd bad_i_t_l_q [ 4];
ncrcmd bad_target [ 8];
ncrcmd bad_status [ 8];
ncrcmd start_ram [ 4];
ncrcmd start_ram [ 4 + PREFETCH_FLUSH_CNT];
ncrcmd start_ram0 [ 4];
ncrcmd sto_restart [ 5];
ncrcmd wait_dma [ 2];
ncrcmd snooptest [ 9];
ncrcmd snoopend [ 2];
};
......@@ -1324,6 +1383,7 @@ static lcb_p ncr_setup_lcb (ncb_p np, u_char tn, u_char ln,
static void ncr_getclock (ncb_p np, int mult);
static void ncr_selectclock (ncb_p np, u_char scntl3);
static ccb_p ncr_get_ccb (ncb_p np, u_char tn, u_char ln);
static void ncr_chip_reset (ncb_p np, int delay);
static void ncr_init (ncb_p np, int reset, char * msg, u_long code);
static int ncr_int_sbmc (ncb_p np);
static int ncr_int_par (ncb_p np);
......@@ -1523,6 +1583,10 @@ static struct script script0 __initdata = {
RADDR (dsa),
PADDR (loadpos),
/*
** Flush script prefetch if required
*/
PREFETCH_FLUSH
/*
** then we do the actual copy.
*/
SCR_COPY (sizeof (struct head)),
......@@ -1823,6 +1887,10 @@ static struct script script0 __initdata = {
SCR_COPY_F (4),
RADDR (dsa),
PADDR (cleanup0),
/*
** Flush script prefetch if required
*/
PREFETCH_FLUSH
SCR_COPY (sizeof (struct head)),
NADDR (header),
}/*-------------------------< CLEANUP0 >--------------------*/,{
......@@ -1852,8 +1920,13 @@ static struct script script0 __initdata = {
/*
** ... signal completion to the host
*/
#ifdef SIMULATED_INTFLY
SCR_INT,
SIR_INTFLY,
#else
SCR_INT_FLY,
0,
#endif
/*
** Auf zu neuen Schandtaten!
*/
......@@ -1872,8 +1945,13 @@ static struct script script0 __initdata = {
SCR_INT,
SIR_DONE_OVERFLOW,
}/*------------------------< DONE_END >---------------------*/,{
#ifdef SIMULATED_INTFLY
SCR_INT,
SIR_INTFLY,
#else
SCR_INT_FLY,
0,
#endif
SCR_COPY (4),
RADDR (temp),
PADDR (done_pos),
......@@ -2051,6 +2129,10 @@ static struct script script0 __initdata = {
RADDR (dsa),
PADDR (loadpos1),
/*
** Flush script prefetch if required
*/
PREFETCH_FLUSH
/*
** then we do the actual copy.
*/
SCR_COPY (sizeof (struct head)),
......@@ -2112,6 +2194,10 @@ static struct script script0 __initdata = {
SCR_COPY_F (4),
RADDR (temp),
PADDR (nexus_indirect),
/*
** Flush script prefetch if required
*/
PREFETCH_FLUSH
SCR_COPY (4),
}/*-------------------------< NEXUS_INDIRECT >-------------------*/,{
0,
......@@ -2268,6 +2354,10 @@ static struct scripth scripth0 __initdata = {
RADDR (dsa),
PADDRH (skip2),
/*
** Flush script prefetch if required
*/
PREFETCH_FLUSH
/*
** then we do the actual copy.
*/
SCR_COPY (sizeof (struct head)),
......@@ -2778,6 +2868,10 @@ static struct scripth scripth0 __initdata = {
SCR_COPY_F (4),
RADDR (scratcha),
PADDRH (start_ram0),
/*
** Flush script prefetch if required
*/
PREFETCH_FLUSH
SCR_COPY (sizeof (struct script)),
}/*-------------------------< START_RAM0 >--------------------*/,{
0,
......@@ -2795,6 +2889,17 @@ static struct scripth scripth0 __initdata = {
PADDR (startpos),
SCR_JUMP,
PADDR (start),
}/*-------------------------< WAIT_DMA >-------------------*/,{
/*
** For HP Zalon/53c720 systems, the Zalon interface
** between CPU and 53c720 does prefetches, which causes
** problems with self modifying scripts. The problem
** is overcome by calling a dummy subroutine after each
** modification, to force a refetch of the script on
** return from the subroutine.
*/
SCR_RETURN,
0,
}/*-------------------------< SNOOPTEST >-------------------*/,{
/*
** Read the variable.
......@@ -3128,9 +3233,12 @@ static u_long div_10M[] =
#define burst_length(bc) (!(bc))? 0 : 1 << (bc)
/*
* Burst code from io register bits.
* Burst code from io register bits. Burst enable is ctest0 for c720,
* ctest4 for others.
*/
#define burst_code(dmode, ctest4, ctest5) \
#define burst_code(dmode, ctest0, ctest4, ctest5) \
(np->device_id == PSEUDO_ZALON_720_ID) ? \
(ctest0) & 0x80? 0 : (((dmode) & 0xc0) >> 6) + 1 : \
(ctest4) & 0x80? 0 : (((dmode) & 0xc0) >> 6) + ((ctest5) & 0x04) + 1
/*
......@@ -3138,12 +3246,14 @@ static u_long div_10M[] =
*/
static inline void ncr_init_burst(ncb_p np, u_char bc)
{
np->rv_ctest4 &= ~0x80;
u_char *be = (np->device_id == PSEUDO_ZALON_720_ID) ?
&np->rv_ctest0 : &np->rv_ctest4;
*be &= ~0x80;
np->rv_dmode &= ~(0x3 << 6);
np->rv_ctest5 &= ~0x4;
if (!bc) {
np->rv_ctest4 |= 0x80;
*be |= 0x80;
}
else {
--bc;
......@@ -3220,6 +3330,7 @@ static int __init ncr_prepare_setting(ncb_p np, ncr_nvram *nvram)
np->sv_scntl3 = INB(nc_scntl3) & 0x07;
np->sv_dmode = INB(nc_dmode) & 0xce;
np->sv_dcntl = INB(nc_dcntl) & 0xa8;
np->sv_ctest0 = INB(nc_ctest0) & 0x84;
np->sv_ctest3 = INB(nc_ctest3) & 0x01;
np->sv_ctest4 = INB(nc_ctest4) & 0x80;
np->sv_ctest5 = INB(nc_ctest5) & 0x24;
......@@ -3306,10 +3417,11 @@ static int __init ncr_prepare_setting(ncb_p np, ncr_nvram *nvram)
np->rv_scntl0 = np->sv_scntl0;
np->rv_dmode = np->sv_dmode;
np->rv_dcntl = np->sv_dcntl;
np->rv_ctest0 = np->sv_ctest0;
np->rv_ctest3 = np->sv_ctest3;
np->rv_ctest4 = np->sv_ctest4;
np->rv_ctest5 = np->sv_ctest5;
burst_max = burst_code(np->sv_dmode, np->sv_ctest4, np->sv_ctest5);
burst_max = burst_code(np->sv_dmode, np->sv_ctest0, np->sv_ctest4, np->sv_ctest5);
#else
/*
......@@ -3317,7 +3429,7 @@ static int __init ncr_prepare_setting(ncb_p np, ncr_nvram *nvram)
*/
burst_max = driver_setup.burst_max;
if (burst_max == 255)
burst_max = burst_code(np->sv_dmode, np->sv_ctest4, np->sv_ctest5);
burst_max = burst_code(np->sv_dmode, np->sv_ctest0, np->sv_ctest4, np->sv_ctest5);
if (burst_max > 7)
burst_max = 7;
if (burst_max > np->maxburst)
......@@ -3340,6 +3452,12 @@ static int __init ncr_prepare_setting(ncb_p np, ncr_nvram *nvram)
np->rv_ctest3 |= WRIE; /* Write and Invalidate */
if (np->features & FE_DFS)
np->rv_ctest5 |= DFS; /* Dma Fifo Size */
if (np->features & FE_MUX)
np->rv_ctest4 |= MUX; /* Host bus multiplex mode */
if (np->features & FE_EA)
np->rv_dcntl |= EA; /* Enable ACK */
if (np->features & FE_EHP)
np->rv_ctest0 |= EHP; /* Even host parity */
/*
** Select some other
......@@ -3539,6 +3657,7 @@ ncr_attach (Scsi_Host_Template *tpnt, int unit, ncr_device *device)
ncr_nvram *nvram = device->nvram;
int i;
#ifndef ENABLE_SCSI_ZALON
printk(KERN_INFO "ncr53c%s-%d: rev 0x%x on pci bus %d device %d function %d "
#ifdef __sparc__
"irq %s\n",
......@@ -3552,6 +3671,7 @@ ncr_attach (Scsi_Host_Template *tpnt, int unit, ncr_device *device)
__irq_itoa(device->slot.irq));
#else
device->slot.irq);
#endif
#endif
/*
......@@ -3564,11 +3684,11 @@ ncr_attach (Scsi_Host_Template *tpnt, int unit, ncr_device *device)
/*
** Allocate the host control block.
*/
np = __m_calloc_dma(device->pdev, sizeof(struct ncb), "NCB");
np = __m_calloc_dma(device->dev, sizeof(struct ncb), "NCB");
if (!np)
goto attach_error;
NCR_INIT_LOCK_NCB(np);
np->pdev = device->pdev;
np->dev = device->dev;
np->p_ncb = vtobus(np);
host_data->ncb = np;
......@@ -3650,7 +3770,9 @@ ncr_attach (Scsi_Host_Template *tpnt, int unit, ncr_device *device)
** Try to map the controller chip into iospace.
*/
#ifndef ENABLE_SCSI_ZALON
request_region(device->slot.io_port, 128, "ncr53c8xx");
#endif
np->base_io = device->slot.io_port;
#ifdef SCSI_NCR_NVRAM_SUPPORT
......@@ -3707,7 +3829,7 @@ 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);
scsi_set_pci_device(instance, device->pdev);
scsi_set_device(instance, device->dev);
#ifdef SCSI_NCR_INTEGRITY_CHECKING
np->check_integrity = 0;
......@@ -3762,10 +3884,7 @@ ncr_attach (Scsi_Host_Template *tpnt, int unit, ncr_device *device)
/*
** Reset chip.
*/
OUTB (nc_istat, SRST);
UDELAY (100);
OUTB (nc_istat, 0 );
ncr_chip_reset(np, 100);
/*
** Now check the cache handling of the pci chipset.
......@@ -3882,7 +4001,9 @@ ncr_attach (Scsi_Host_Template *tpnt, int unit, ncr_device *device)
#ifdef DEBUG_NCR53C8XX
printk(KERN_DEBUG "%s: releasing IO region %x[%d]\n", ncr_name(np), np->base_io, 128);
#endif
#ifndef ENABLE_SCSI_ZALON
release_region(np->base_io, 128);
#endif
}
if (np->irq) {
#ifdef DEBUG_NCR53C8XX
......@@ -3907,7 +4028,7 @@ ncr_attach (Scsi_Host_Template *tpnt, int unit, ncr_device *device)
scsi_unregister(instance);
return -1;
}
}
/*==========================================================
......@@ -4694,9 +4815,7 @@ static int ncr_reset_scsi_bus(ncb_p np, int enab_int, int settle_delay)
"command processing suspended for %d seconds\n",
ncr_name(np), settle_delay);
OUTB (nc_istat, SRST);
UDELAY (100);
OUTB (nc_istat, 0);
ncr_chip_reset(np, 100);
UDELAY (2000); /* The 895 needs time for the bus mode to settle */
if (enab_int)
OUTW (nc_sien, RST);
......@@ -4705,7 +4824,8 @@ static int ncr_reset_scsi_bus(ncb_p np, int enab_int, int settle_delay)
** properly set IRQ mode, prior to resetting the bus.
*/
OUTB (nc_stest3, TE);
OUTB (nc_dcntl, (np->rv_dcntl & IRQM));
if (np->device_id != PSEUDO_ZALON_720_ID)
OUTB (nc_dcntl, (np->rv_dcntl & IRQM));
OUTB (nc_scntl1, CRST);
UDELAY (200);
......@@ -4912,6 +5032,10 @@ static int ncr_detach(ncb_p np)
lcb_p lp;
int target, lun;
int i;
char inst_name[16];
/* Local copy so we don't access np after freeing it! */
strncpy(inst_name, ncr_name(np), 16);
printk("%s: releasing host resources\n", ncr_name(np));
......@@ -4958,12 +5082,11 @@ static int ncr_detach(ncb_p np)
*/
printk("%s: resetting chip\n", ncr_name(np));
OUTB (nc_istat, SRST);
UDELAY (100);
OUTB (nc_istat, 0 );
ncr_chip_reset(np, 100);
OUTB(nc_dmode, np->sv_dmode);
OUTB(nc_dcntl, np->sv_dcntl);
OUTB(nc_ctest0, np->sv_ctest0);
OUTB(nc_ctest3, np->sv_ctest3);
OUTB(nc_ctest4, np->sv_ctest4);
OUTB(nc_ctest5, np->sv_ctest5);
......@@ -4986,7 +5109,9 @@ static int ncr_detach(ncb_p np)
#ifdef DEBUG_NCR53C8XX
printk("%s: releasing IO region %x[%d]\n", ncr_name(np), np->base_io, 128);
#endif
#ifndef ENABLE_SCSI_ZALON
release_region(np->base_io, 128);
#endif
/*
** Free allocated ccb(s)
......@@ -5031,7 +5156,7 @@ static int ncr_detach(ncb_p np)
m_free_dma(np->ccb, sizeof(struct ccb), "CCB");
m_free_dma(np, sizeof(struct ncb), "NCB");
printk("%s: host resources successfully released\n", ncr_name(np));
printk("%s: host resources successfully released\n", inst_name);
return 1;
}
......@@ -5423,6 +5548,27 @@ void ncr_wakeup (ncb_p np, u_long code)
}
}
/*
** Reset ncr chip.
*/
/* Some initialisation must be done immediately following reset, for 53c720,
* at least. EA (dcntl bit 5) isn't set here as it is set once only in
* the _detect function.
*/
static void ncr_chip_reset(ncb_p np, int delay)
{
OUTB (nc_istat, SRST);
UDELAY (delay);
OUTB (nc_istat, 0 );
if (np->features & FE_EHP)
OUTB (nc_ctest0, EHP);
if (np->features & FE_MUX)
OUTB (nc_ctest4, MUX);
}
/*==========================================================
**
**
......@@ -5469,6 +5615,7 @@ void ncr_init (ncb_p np, int reset, char * msg, u_long code)
np->squeueput = 0;
np->script0->startpos[0] = cpu_to_scr(NCB_SCRIPTH_PHYS (np, tryloop));
#ifdef SCSI_NCR_CCB_DONE_SUPPORT
/*
** Clear Done Queue
*/
......@@ -5477,6 +5624,7 @@ void ncr_init (ncb_p np, int reset, char * msg, u_long code)
np->scripth0->done_queue[5*i + 4] =
cpu_to_scr(NCB_SCRIPT_PHYS (np, done_end));
}
#endif
/*
** Start at first entry.
......@@ -5495,8 +5643,11 @@ void ncr_init (ncb_p np, int reset, char * msg, u_long code)
** Init chip.
*/
OUTB (nc_istat, 0x00 ); /* Remove Reset, abort */
UDELAY (2000); /* The 895 needs time for the bus mode to settle */
/*
** Remove reset; big delay because the 895 needs time for the
** bus mode to settle
*/
ncr_chip_reset(np, 2000);
OUTB (nc_scntl0, np->rv_scntl0 | 0xc0);
/* full arb., ena parity, par->ATN */
......@@ -5511,6 +5662,7 @@ void ncr_init (ncb_p np, int reset, char * msg, u_long code)
OUTB (nc_ctest5, np->rv_ctest5); /* Large fifo + large burst */
OUTB (nc_dcntl , NOCOM|np->rv_dcntl); /* Protect SFBR */
OUTB (nc_ctest0, np->rv_ctest0); /* 720: CDIS and EHP */
OUTB (nc_ctest3, np->rv_ctest3); /* Write and invalidate */
OUTB (nc_ctest4, np->rv_ctest4); /* Master parity checking */
......@@ -7095,6 +7247,18 @@ void ncr_int_sir (ncb_p np)
if (DEBUG_FLAGS & DEBUG_TINY) printk ("I#%d", num);
switch (num) {
case SIR_INTFLY:
/*
** This is used for HP Zalon/53c720 where INTFLY
** operation is currently broken.
*/
ncr_wakeup_done(np);
#ifdef SCSI_NCR_CCB_DONE_SUPPORT
OUTL(nc_dsp, NCB_SCRIPT_PHYS (np, done_end) + 8);
#else
OUTL(nc_dsp, NCB_SCRIPT_PHYS (np, start));
#endif
return;
case SIR_RESEL_NO_MSG_IN:
case SIR_RESEL_NO_IDENTIFY:
/*
......@@ -7841,15 +8005,23 @@ static void ncr_init_tcb (ncb_p np, u_char tn)
*/
tp->getscr[0] = cpu_to_scr(copy_1);
tp->getscr[1] = cpu_to_scr(vtobus (&tp->sval));
#ifdef SCSI_NCR_BIG_ENDIAN
tp->getscr[2] = cpu_to_scr(ncr_reg_bus_addr(nc_sxfer) ^ 3);
#else
tp->getscr[2] = cpu_to_scr(ncr_reg_bus_addr(nc_sxfer));
#endif
/*
** Load the timing register.
** COPY @(tp->wval), @(scntl3)
*/
tp->getscr[3] = cpu_to_scr(copy_1);
tp->getscr[4] = cpu_to_scr(vtobus (&tp->wval));
#ifdef SCSI_NCR_BIG_ENDIAN
tp->getscr[5] = cpu_to_scr(ncr_reg_bus_addr(nc_scntl3) ^ 3);
#else
tp->getscr[5] = cpu_to_scr(ncr_reg_bus_addr(nc_scntl3));
#endif
/*
** Get the IDENTIFY message and the lun.
......@@ -7878,10 +8050,17 @@ static void ncr_init_tcb (ncb_p np, u_char tn)
/*
** These assert's should be moved at driver initialisations.
*/
#ifdef SCSI_NCR_BIG_ENDIAN
assert (( (offsetof(struct ncr_reg, nc_sxfer) ^
offsetof(struct tcb , sval )) &3) == 3);
assert (( (offsetof(struct ncr_reg, nc_scntl3) ^
offsetof(struct tcb , wval )) &3) == 3);
#else
assert (( (offsetof(struct ncr_reg, nc_sxfer) ^
offsetof(struct tcb , sval )) &3) == 0);
assert (( (offsetof(struct ncr_reg, nc_scntl3) ^
offsetof(struct tcb , wval )) &3) == 0);
#endif
}
......@@ -8122,14 +8301,10 @@ static int ncr_scatter(ncb_p np, ccb_p cp, Scsi_Cmnd *cmd)
segment = 1;
}
}
else {
else if (use_sg <= MAX_SCATTER) {
struct scatterlist *scatter = (struct scatterlist *)cmd->buffer;
use_sg = map_scsi_sg_data(np, cmd);
if (use_sg > MAX_SCATTER) {
unmap_scsi_data(np, cmd);
return -1;
}
data = &data[MAX_SCATTER - use_sg];
while (segment < use_sg) {
......@@ -8142,6 +8317,9 @@ static int ncr_scatter(ncb_p np, ccb_p cp, Scsi_Cmnd *cmd)
++segment;
}
}
else {
return -1;
}
return segment;
}
......@@ -8226,9 +8404,7 @@ static int __init ncr_snooptest (struct ncb* np)
/*
** Reset ncr chip
*/
OUTB (nc_istat, SRST);
UDELAY (100);
OUTB (nc_istat, 0 );
ncr_chip_reset(np, 100);
/*
** check for timeout
*/
......@@ -8455,7 +8631,7 @@ static void __init ncr_getclock (ncb_p np, int mult)
if (np->multiplier != mult || (scntl3 & 7) < 3 || !(scntl3 & 1)) {
unsigned f2;
OUTB(nc_istat, SRST); UDELAY (5); OUTB(nc_istat, 0);
ncr_chip_reset(np, 5);
(void) ncrgetfreq (np, 11); /* throw away first result */
f1 = ncrgetfreq (np, 11);
......@@ -9202,6 +9378,7 @@ __setup("ncr53c8xx=", ncr53c8xx_setup);
*/
static u_short ncr_chip_ids[] __initdata = {
PSEUDO_ZALON_720_ID,
PCI_DEVICE_ID_NCR_53C810,
PCI_DEVICE_ID_NCR_53C815,
PCI_DEVICE_ID_NCR_53C820,
......@@ -9216,6 +9393,74 @@ static u_short ncr_chip_ids[] __initdata = {
PCI_DEVICE_ID_NCR_53C1510D
};
#ifdef ENABLE_SCSI_ZALON
/* Attach a 53c720 interfaced via Zalon chip on HP boxes. */
int zalon_attach(Scsi_Host_Template *tpnt, unsigned long io_port,
struct parisc_device *dev, int irq, int unit)
{
u_short device_id;
u_char revision;
int i;
ncr_chip *chip;
ncr_device device;
tpnt->proc_name = NAME53C8XX;
tpnt->proc_info = ncr53c8xx_proc_info;
#if defined(SCSI_NCR_BOOT_COMMAND_LINE_SUPPORT) && defined(MODULE)
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();
memset(&device, 0, sizeof(ncr_device));
chip = 0;
device_id = PSEUDO_ZALON_720_ID;
revision = 0;
for (i = 0; i < sizeof(ncr_chip_table)/sizeof(ncr_chip_table[0]); i++) { if (device_id != ncr_chip_table[i].device_id)
continue;
chip = &device.chip;
memcpy(chip, &ncr_chip_table[i], sizeof(*chip));
chip->revision_id = revision;
break;
}
if (!chip) {
printk(NAME53C8XX ": not initializing, device not supported\n"); return -1;
}
/* Fix some features according to driver setup. */
driver_setup.diff_support = 2;
/* The following three are needed before any other access. */
writeb(0x20, io_port + 0x38); /* DCNTL_REG, EA */
writeb(0x04, io_port + 0x1b); /* CTEST0_REG, EHP */
writeb(0x80, io_port + 0x22); /* CTEST4_REG, MUX */
/* Initialise ncr_device structure with items required by ncr_attach. */
device.host_id = driver_setup.host_id;
device.dev = &dev->dev;
device.slot.bus = 0;
device.slot.device_fn = 0;
device.slot.base = (u_long)io_port;
device.slot.base_c = (u_long)io_port;
device.slot.base_2 = 0;
device.slot.base_2_c = 0;
device.slot.io_port = io_port;
device.slot.irq = irq;
device.attach_done = 0;
printk(KERN_INFO NAME53C8XX ": 53c%s detected\n", device.chip.name);
return ncr_attach(tpnt, unit, &device);
}
#endif
/*==========================================================
**
** Chip detection entry point.
......@@ -9265,6 +9510,23 @@ MODULE_LICENSE("GPL");
static
#endif
#if LINUX_VERSION_CODE >= LinuxVersionCode(2,4,0) || defined(MODULE)
#ifdef ENABLE_SCSI_ZALON
Scsi_Host_Template driver_template = {
.proc_name = "zalon720",
.detect = zalon7xx_detect,
.release = zalon7xx_release,
.info = ncr53c8xx_info,
.queuecommand = ncr53c8xx_queue_command,
.can_queue = SCSI_NCR_CAN_QUEUE,
.this_id = 7,
.sg_tablesize = SCSI_NCR_SG_TABLESIZE,
.cmd_per_lun = SCSI_NCR_CMD_PER_LUN,
.use_clustering = DISABLE_CLUSTERING,
};
#else
Scsi_Host_Template driver_template = NCR53C8XX;
#endif
#include "scsi_module.c"
#endif
......@@ -2,13 +2,13 @@
#include <linux/sched.h>
#include <linux/mm.h>
#include <linux/fs.h>
#include <asm/uaccess.h>
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/blk.h>
#include <linux/blkpg.h>
#include <linux/cdrom.h>
#include <asm/io.h>
#include <asm/uaccess.h>
#include "scsi.h"
#include "hosts.h"
......
......@@ -265,6 +265,7 @@ static inline struct xpt_quehead *xpt_remque_tail(struct xpt_quehead *head)
#if LINUX_VERSION_CODE >= LinuxVersionCode(2,2,0)
typedef struct pci_dev *pcidev_t;
typedef struct device *device_t;
#define PCIDEV_NULL (0)
#define PciBusNumber(d) (d)->bus->number
#define PciDeviceFn(d) (d)->devfn
......@@ -312,6 +313,7 @@ pci_get_base_address(struct pci_dev *pdev, int index, u_long *base)
#else /* Incomplete emulation of current PCI code for pre-2.2 kernels */
typedef unsigned int pcidev_t;
typedef unsinged int device_t;
#define PCIDEV_NULL (~0u)
#define PciBusNumber(d) ((d)>>8)
#define PciDeviceFn(d) ((d)&0xff)
......@@ -564,7 +566,7 @@ static void MDELAY(long ms) { while (ms--) UDELAY(1000); }
#define MEMO_CLUSTER_MASK (MEMO_CLUSTER_SIZE-1)
typedef u_long m_addr_t; /* Enough bits to bit-hack addresses */
typedef pcidev_t m_bush_t; /* Something that addresses DMAable */
typedef struct device *m_bush_t; /* Something that addresses DMAable */
typedef struct m_link { /* Link between free memory chunks */
struct m_link *next;
......@@ -793,7 +795,7 @@ static m_addr_t ___dma_getp(m_pool_s *mp)
vbp = __m_calloc(&mp0, sizeof(*vbp), "VTOB");
if (vbp) {
dma_addr_t daddr;
vp = (m_addr_t) pci_alloc_consistent(mp->bush,
vp = (m_addr_t) dma_alloc_coherent(mp->bush,
PAGE_SIZE<<MEMO_PAGE_ORDER,
&daddr);
if (vp) {
......@@ -822,8 +824,8 @@ static void ___dma_freep(m_pool_s *mp, m_addr_t m)
if (*vbpp) {
vbp = *vbpp;
*vbpp = (*vbpp)->next;
pci_free_consistent(mp->bush, PAGE_SIZE<<MEMO_PAGE_ORDER,
(void *)vbp->vaddr, (dma_addr_t)vbp->baddr);
dma_free_coherent(mp->bush, PAGE_SIZE<<MEMO_PAGE_ORDER,
(void *)vbp->vaddr, (dma_addr_t)vbp->baddr);
__m_free(&mp0, vbp, sizeof(*vbp), "VTOB");
--mp->nump;
}
......@@ -917,11 +919,11 @@ static m_addr_t __vtobus(m_bush_t bush, void *m)
#endif /* SCSI_NCR_DYNAMIC_DMA_MAPPING */
#define _m_calloc_dma(np, s, n) __m_calloc_dma(np->pdev, s, n)
#define _m_free_dma(np, p, s, n) __m_free_dma(np->pdev, p, s, n)
#define _m_calloc_dma(np, s, n) __m_calloc_dma(np->dev, s, n)
#define _m_free_dma(np, p, s, n) __m_free_dma(np->dev, p, s, n)
#define m_calloc_dma(s, n) _m_calloc_dma(np, s, n)
#define m_free_dma(p, s, n) _m_free_dma(np, p, s, n)
#define _vtobus(np, p) __vtobus(np->pdev, p)
#define _vtobus(np, p) __vtobus(np->dev, p)
#define vtobus(p) _vtobus(np, p)
/*
......@@ -932,10 +934,10 @@ static m_addr_t __vtobus(m_bush_t bush, void *m)
/* Linux versions prior to pci bus iommu kernel interface */
#define __unmap_scsi_data(pdev, cmd) do {; } while (0)
#define __map_scsi_single_data(pdev, cmd) (__vtobus(pdev,(cmd)->request_buffer))
#define __map_scsi_sg_data(pdev, cmd) ((cmd)->use_sg)
#define __sync_scsi_data(pdev, cmd) do {; } while (0)
#define __unmap_scsi_data(dev, cmd) do {; } while (0)
#define __map_scsi_single_data(dev, cmd) (__vtobus(dev,(cmd)->request_buffer))
#define __map_scsi_sg_data(dev, cmd) ((cmd)->use_sg)
#define __sync_scsi_data(dev, cmd) do {; } while (0)
#define scsi_sg_dma_address(sc) vtobus((sc)->address)
#define scsi_sg_dma_len(sc) ((sc)->length)
......@@ -948,31 +950,34 @@ static m_addr_t __vtobus(m_bush_t bush, void *m)
#define __data_mapped SCp.phase
#define __data_mapping SCp.have_data_in
static void __unmap_scsi_data(pcidev_t pdev, Scsi_Cmnd *cmd)
static void __unmap_scsi_data(device_t dev, Scsi_Cmnd *cmd)
{
int dma_dir = scsi_to_pci_dma_dir(cmd->sc_data_direction);
enum dma_data_direction dma_dir =
(enum dma_data_direction)scsi_to_pci_dma_dir(cmd->sc_data_direction);
switch(cmd->__data_mapped) {
case 2:
pci_unmap_sg(pdev, cmd->buffer, cmd->use_sg, dma_dir);
dma_unmap_sg(dev, cmd->buffer, cmd->use_sg, dma_dir);
break;
case 1:
pci_unmap_single(pdev, cmd->__data_mapping,
dma_unmap_single(dev, cmd->__data_mapping,
cmd->request_bufflen, dma_dir);
break;
}
cmd->__data_mapped = 0;
}
static u_long __map_scsi_single_data(pcidev_t pdev, Scsi_Cmnd *cmd)
static u_long __map_scsi_single_data(device_t dev, Scsi_Cmnd *cmd)
{
dma_addr_t mapping;
int dma_dir = scsi_to_pci_dma_dir(cmd->sc_data_direction);
enum dma_data_direction dma_dir =
(enum dma_data_direction)scsi_to_pci_dma_dir(cmd->sc_data_direction);
if (cmd->request_bufflen == 0)
return 0;
mapping = pci_map_single(pdev, cmd->request_buffer,
mapping = dma_map_single(dev, cmd->request_buffer,
cmd->request_bufflen, dma_dir);
cmd->__data_mapped = 1;
cmd->__data_mapping = mapping;
......@@ -980,32 +985,34 @@ static u_long __map_scsi_single_data(pcidev_t pdev, Scsi_Cmnd *cmd)
return mapping;
}
static int __map_scsi_sg_data(pcidev_t pdev, Scsi_Cmnd *cmd)
static int __map_scsi_sg_data(device_t dev, Scsi_Cmnd *cmd)
{
int use_sg;
int dma_dir = scsi_to_pci_dma_dir(cmd->sc_data_direction);
enum dma_data_direction dma_dir =
(enum dma_data_direction)scsi_to_pci_dma_dir(cmd->sc_data_direction);
if (cmd->use_sg == 0)
return 0;
use_sg = pci_map_sg(pdev, cmd->buffer, cmd->use_sg, dma_dir);
use_sg = dma_map_sg(dev, cmd->buffer, cmd->use_sg, dma_dir);
cmd->__data_mapped = 2;
cmd->__data_mapping = use_sg;
return use_sg;
}
static void __sync_scsi_data(pcidev_t pdev, Scsi_Cmnd *cmd)
static void __sync_scsi_data(device_t dev, Scsi_Cmnd *cmd)
{
int dma_dir = scsi_to_pci_dma_dir(cmd->sc_data_direction);
enum dma_data_direction dma_dir =
(enum dma_data_direction)scsi_to_pci_dma_dir(cmd->sc_data_direction);
switch(cmd->__data_mapped) {
case 2:
pci_dma_sync_sg(pdev, cmd->buffer, cmd->use_sg, dma_dir);
dma_sync_sg(dev, cmd->buffer, cmd->use_sg, dma_dir);
break;
case 1:
pci_dma_sync_single(pdev, cmd->__data_mapping,
cmd->request_bufflen, dma_dir);
dma_sync_single(dev, cmd->__data_mapping,
cmd->request_bufflen, dma_dir);
break;
}
}
......@@ -1015,10 +1022,10 @@ static void __sync_scsi_data(pcidev_t pdev, Scsi_Cmnd *cmd)
#endif /* SCSI_NCR_DYNAMIC_DMA_MAPPING */
#define unmap_scsi_data(np, cmd) __unmap_scsi_data(np->pdev, cmd)
#define map_scsi_single_data(np, cmd) __map_scsi_single_data(np->pdev, cmd)
#define map_scsi_sg_data(np, cmd) __map_scsi_sg_data(np->pdev, cmd)
#define sync_scsi_data(np, cmd) __sync_scsi_data(np->pdev, cmd)
#define unmap_scsi_data(np, cmd) __unmap_scsi_data(np->dev, cmd)
#define map_scsi_single_data(np, cmd) __map_scsi_single_data(np->dev, cmd)
#define map_scsi_sg_data(np, cmd) __map_scsi_sg_data(np->dev, cmd)
#define sync_scsi_data(np, cmd) __sync_scsi_data(np->dev, cmd)
/*==========================================================
**
......@@ -1140,7 +1147,7 @@ typedef struct {
**==========================================================
*/
typedef struct {
pcidev_t pdev;
device_t dev;
ncr_slot slot;
ncr_chip chip;
ncr_nvram *nvram;
......@@ -2486,7 +2493,7 @@ sym53c8xx_pci_init(Scsi_Host_Template *tpnt, pcidev_t pdev, ncr_device *device)
/*
** Initialise ncr_device structure with items required by ncr_attach.
*/
device->pdev = pdev;
device->dev = &pdev->dev;
device->slot.bus = PciBusNumber(pdev);
device->slot.device_fn = PciDeviceFn(pdev);
device->slot.base = base;
......
......@@ -51,6 +51,13 @@
** NVRAM detection and reading.
** Copyright (C) 1997 Richard Waltham <dormouse@farsrobt.demon.co.uk>
**
** Added support for MIPS big endian systems.
** Carsten Langgaard, carstenl@mips.com
** Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved.
**
** Added support for HP PARISC big endian systems.
** Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved.
**
*******************************************************************************
*/
......@@ -78,8 +85,10 @@
/*
* No more an option, enabled by default.
*/
#ifndef CONFIG_SCSI_NCR53C8XX_NVRAM_DETECT
#define CONFIG_SCSI_NCR53C8XX_NVRAM_DETECT
#ifndef ENABLE_SCSI_ZALON
# ifndef CONFIG_SCSI_NCR53C8XX_NVRAM_DETECT
# define CONFIG_SCSI_NCR53C8XX_NVRAM_DETECT
# endif
#endif
/*
......@@ -181,6 +190,8 @@
#endif
#elif defined(__sparc__)
#undef SCSI_NCR_IOMAPPED
#elif defined(__hppa__) && defined(ENABLE_SCSI_ZALON)
#undef SCSI_NCR_IOMAPPED
#endif
/*
......@@ -379,16 +390,24 @@
#define readb_raw readb
#define writeb_raw writeb
#if defined(__hppa__)
#define readw_l2b(a) le16_to_cpu(readw(a))
#define readl_l2b(a) le32_to_cpu(readl(a))
#define writew_b2l(v,a) writew(cpu_to_le16(v),a)
#define writel_b2l(v,a) writel(cpu_to_le32(v),a)
#else /* Other bid-endian */
#if defined(SCSI_NCR_BIG_ENDIAN)
#define readw_l2b __raw_readw
#define readl_l2b __raw_readl
#define writew_b2l __raw_writew
#define writel_b2l __raw_writel
#define readw_raw __raw_readw
#define readl_raw(a) __raw_readl((unsigned long)(a))
#define writew_raw __raw_writew
#define writel_raw(v,a) __raw_writel(v,(unsigned long)(a))
#else /* Other big-endian */
#define readw_l2b readw
#define readl_l2b readl
#define writew_b2l writew
#define writel_b2l writel
#define readw_raw readw
#define readl_raw readl
#define writew_raw writew
#define writel_raw writel
#endif
#else /* little endian */
......@@ -417,9 +436,11 @@
#endif
#endif
#if !defined(__hppa__) && !defined(__mips__)
#ifdef SCSI_NCR_BIG_ENDIAN
#error "The NCR in BIG ENDIAN addressing mode is not (yet) supported"
#endif
#endif
/*
......@@ -572,10 +593,20 @@
#else
#ifdef ENABLE_SCSI_ZALON
/* Only 8 or 32 bit transfers allowed */
#define INW_OFF(o) (readb((char *)np->reg + ncr_offw(o)) << 8 | readb((char *)np->reg + ncr_offw(o) + 1))
#else
#define INW_OFF(o) readw_raw((char *)np->reg + ncr_offw(o))
#endif
#define INL_OFF(o) readl_raw((char *)np->reg + (o))
#ifdef ENABLE_SCSI_ZALON
/* Only 8 or 32 bit transfers allowed */
#define OUTW_OFF(o, val) do { writeb((char)((val) >> 8), (char *)np->reg + ncr_offw(o)); writeb((char)(val), (char *)np->reg + ncr_offw(o) + 1); } while (0)
#else
#define OUTW_OFF(o, val) writew_raw((val), (char *)np->reg + ncr_offw(o))
#endif
#define OUTL_OFF(o, val) writel_raw((val), (char *)np->reg + (o))
#endif
......@@ -623,6 +654,10 @@
** NCR53C8XX Device Ids
*/
#ifndef PSEUDO_ZALON_720_ID
#define PSEUDO_ZALON_720_ID 0x5a00
#endif
#ifndef PCI_DEVICE_ID_NCR_53C810
#define PCI_DEVICE_ID_NCR_53C810 1
#endif
......@@ -726,6 +761,9 @@ typedef struct {
#define FE_DAC (1<<24) /* Support DAC cycles (64 bit addressing) */
#define FE_ISTAT1 (1<<25) /* Have ISTAT1, MBOX0, MBOX1 registers */
#define FE_DAC_IN_USE (1<<26) /* Platform does DAC cycles */
#define FE_EHP (1<<27) /* 720: Even host parity */
#define FE_MUX (1<<28) /* 720: Multiplexed bus */
#define FE_EA (1<<29) /* 720: Enable Ack */
#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)
......@@ -747,6 +785,9 @@ typedef struct {
#define SCSI_NCR_CHIP_TABLE \
{ \
{PSEUDO_ZALON_720_ID, 0x0f, "720", 3, 8, 4, \
FE_WIDE|FE_DIFF|FE_EHP|FE_MUX|FE_EA} \
, \
{PCI_DEVICE_ID_NCR_53C810, 0x0f, "810", 4, 8, 4, \
FE_ERL} \
, \
......@@ -819,6 +860,7 @@ typedef struct {
*/
#define SCSI_NCR_CHIP_IDS \
{ \
PSEUDO_ZALON_720_ID, \
PCI_DEVICE_ID_NCR_53C810, \
PCI_DEVICE_ID_NCR_53C815, \
PCI_DEVICE_ID_NCR_53C820, \
......@@ -1170,6 +1212,7 @@ struct ncr_reg {
/*17*/ u_char nc_mbox1; /* 896 and later cores only */
/*18*/ u_char nc_ctest0;
#define EHP 0x04 /* 720 even host parity */
/*19*/ u_char nc_ctest1;
/*1a*/ u_char nc_ctest2;
......@@ -1187,6 +1230,7 @@ struct ncr_reg {
/*20*/ u_char nc_dfifo;
/*21*/ u_char nc_ctest4;
#define MUX 0x80 /* 720 host bus multiplex mode */
#define BDIS 0x80 /* mod: burst disable */
#define MPEE 0x08 /* mod: master parity error enable */
......@@ -1219,6 +1263,7 @@ struct ncr_reg {
#define CLSE 0x80 /* mod: cache line size enable */
#define PFF 0x40 /* cmd: pre-fetch flush */
#define PFEN 0x20 /* mod: pre-fetch enable */
#define EA 0x20 /* mod: 720 enable-ack */
#define SSM 0x10 /* mod: single step mode */
#define IRQM 0x08 /* mod: irq mode (1 = totem pole !) */
#define STD 0x04 /* cmd: start dma mode */
......@@ -1261,6 +1306,7 @@ struct ncr_reg {
/*4e*/ u_char nc_stest2;
#define ROF 0x40 /* reset scsi offset (after gross error!) */
#define DIF 0x20 /* 720 SCSI differential mode */
#define EXT 0x02 /* extended filtering */
/*4f*/ u_char nc_stest3;
......@@ -1439,12 +1485,22 @@ struct scr_tblmove {
#define SCR_SEL_TBL 0x42000000
#define SCR_SEL_TBL_ATN 0x43000000
#ifdef SCSI_NCR_BIG_ENDIAN
struct scr_tblsel {
u_char sel_scntl3;
u_char sel_id;
u_char sel_sxfer;
u_char sel_scntl4;
};
#else
struct scr_tblsel {
u_char sel_scntl4;
u_char sel_sxfer;
u_char sel_id;
u_char sel_scntl3;
};
#endif
#define SCR_JMP_REL 0x04000000
#define SCR_ID(id) (((u_int32)(id)) << 16)
......
/*
* Zalon 53c7xx device driver.
* By Richard Hirst (rhirst@linuxcare.com)
*/
#include <linux/init.h>
#include <linux/types.h>
#include <linux/stat.h>
#include <linux/mm.h>
#include <linux/blk.h>
#include <linux/sched.h>
#include <linux/version.h>
#include <linux/config.h>
#include <linux/module.h>
#include <asm/page.h>
#include <asm/pgtable.h>
#include <asm/irq.h>
#include <asm/hardware.h>
#include <asm/delay.h>
#include <asm/io.h>
#include "../parisc/gsc.h"
#include "scsi.h"
#include "hosts.h"
/*
* ** Define the BSD style u_int32 and u_int64 type.
* ** Are in fact u_int32_t and u_int64_t :-)
* */
typedef u32 u_int32;
typedef u64 u_int64;
typedef u_long vm_offset_t;
#include "zalon.h"
/* hosts_* are kluges to pass info between the zalon7xx_detected()
** and the register_parisc_driver() callbacks.
*/
static Scsi_Host_Template *hosts_tptr;
static int hosts_used=0;
static int zalon_id = 0;
extern int zalon_attach(Scsi_Host_Template *tpnt,
unsigned long base_addr,
struct parisc_device *dev,
int irq_vector,
int unit
);
#if 0
/* FIXME:
* Is this function dead code? or is someone planning on using it in the
* future. The clock = (int) pdc_result[16] does not look correct to
* me ... I think it should be iodc_data[16]. Since this cause a compile
* error with the new encapsulated PDC, I'm not compiling in this function.
* - RB
*/
/* poke SCSI clock out of iodc data */
static u8 iodc_data[32] __attribute__ ((aligned (64)));
static unsigned long pdc_result[32] __attribute__ ((aligned (16))) ={0,0,0,0};
static int
lasi_scsi_clock(void * hpa, int defaultclock)
{
int clock, status;
status = pdc_iodc_read(&pdc_result, hpa, 0, &iodc_data, 32 );
if (status == PDC_RET_OK) {
clock = (int) pdc_result[16];
} else {
printk(KERN_WARNING "%s: pdc_iodc_read returned %d\n", __FUNCTION__, status);
clock = defaultclock;
}
printk(KERN_DEBUG "%s: SCSI clock %d\n", __FUNCTION__, clock);
return clock;
}
#endif
static int __init
zalon_scsi_callback(struct parisc_device *dev)
{
struct gsc_irq gsc_irq;
u32 zalon_vers;
int irq;
unsigned long zalon = dev->hpa;
__raw_writel(CMD_RESET, zalon + IO_MODULE_IO_COMMAND);
while (!(__raw_readl(zalon + IO_MODULE_IO_STATUS) & IOSTATUS_RY))
;
__raw_writel(IOIIDATA_MINT5EN | IOIIDATA_PACKEN | IOIIDATA_PREFETCHEN,
zalon + IO_MODULE_II_CDATA);
/* XXX: Save the Zalon version for bug workarounds? */
zalon_vers = __raw_readl(dev->hpa + IO_MODULE_II_CDATA) & 0x07000000;
zalon_vers >>= 24;
/* Setup the interrupts first.
** Later on request_irq() will register the handler.
*/
irq = gsc_alloc_irq(&gsc_irq);
printk("%s: Zalon vers field is 0x%x, IRQ %d\n", __FUNCTION__,
zalon_vers, irq);
__raw_writel(gsc_irq.txn_addr | gsc_irq.txn_data, dev->hpa + IO_MODULE_EIM);
if ( zalon_vers == 0)
printk(KERN_WARNING "%s: Zalon 1.1 or earlier\n", __FUNCTION__);
/*
** zalon_attach: returns -1 on failure, 0 on success
*/
hosts_used = zalon_attach(hosts_tptr, dev->hpa + GSC_SCSI_ZALON_OFFSET,
dev, irq, zalon_id);
if (hosts_used == 0)
zalon_id++;
hosts_used = (hosts_used == 0);
return (hosts_used == 0);
}
static struct parisc_device_id zalon_tbl[] = {
{ HPHW_A_DMA, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x00089 },
{ 0, }
};
MODULE_DEVICE_TABLE(parisc, zalon_tbl);
static struct parisc_driver zalon_driver = {
.name = "GSC SCSI (Zalon)",
.id_table = zalon_tbl,
.probe = zalon_scsi_callback,
};
int zalon7xx_detect(Scsi_Host_Template *tpnt)
{
/* "pass" the parameter to the callback functions */
hosts_tptr = tpnt;
hosts_used = 0;
/* claim all zalon cards. */
register_parisc_driver(&zalon_driver);
/* Check if any callbacks actually found/claimed anything. */
return (hosts_used != 0);
}
#ifdef MODULE
extern int ncr53c8xx_release(struct Scsi_Host *host);
int zalon7xx_release(struct Scsi_Host *host)
{
ncr53c8xx_release(host);
unregister_parisc_driver(&zalon_driver);
return 1;
}
#endif
#ifndef ZALON7XX_H
#define ZALON7XX_H
#include <linux/types.h>
#include "sym53c8xx_defs.h"
extern int zalon7xx_detect(Scsi_Host_Template *);
#include <scsi/scsicam.h>
extern struct proc_dir_entry proc_scsi_zalon7xx;
/* borrowed from drivers/scsi/ncr53c8xx.h */
int zalon7xx_detect(Scsi_Host_Template *tpnt);
const char *ncr53c8xx_info(struct Scsi_Host *host);
int ncr53c8xx_queue_command(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
#ifdef MODULE
int zalon7xx_release(struct Scsi_Host *);
#else
#define zalon7xx_release NULL
#endif
#define GSC_SCSI_ZALON_OFFSET 0x800
#define IO_MODULE_EIM (1*4)
#define IO_MODULE_DC_ADATA (2*4)
#define IO_MODULE_II_CDATA (3*4)
#define IO_MODULE_IO_COMMAND (12*4)
#define IO_MODULE_IO_STATUS (13*4)
#define IOSTATUS_RY 0x40
#define IOSTATUS_FE 0x80
#define IOIIDATA_SMINT5L 0x40000000
#define IOIIDATA_MINT5EN 0x20000000
#define IOIIDATA_PACKEN 0x10000000
#define IOIIDATA_PREFETCHEN 0x08000000
#define IOIIDATA_IOII 0x00000020
#define CMD_RESET 5
#endif /* ZALON7XX_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment