diff options
author | kaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk> | 2003-08-07 12:24:12 +0000 |
---|---|---|
committer | kaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk> | 2003-08-07 12:24:12 +0000 |
commit | 6737c35322a2b35f4ca5a58ea37634e7b2b24ffb (patch) | |
tree | 9bd3592102632faa496cfd37b2293d57bb987f41 /xen | |
parent | 4a30b340d959e4223307a7bb6e86ce62ff11be28 (diff) | |
download | xen-6737c35322a2b35f4ca5a58ea37634e7b2b24ffb.tar.gz xen-6737c35322a2b35f4ca5a58ea37634e7b2b24ffb.tar.bz2 xen-6737c35322a2b35f4ca5a58ea37634e7b2b24ffb.zip |
bitkeeper revision 1.392 (3f3244ecABjhViAc-zlxaKkbsstr4Q)
Many files:
Upgraded our aacraid driver to latest Linux-ac version (Linux 2.4.21-ac4 with aacraid v1.1.2).
Diffstat (limited to 'xen')
-rw-r--r-- | xen/drivers/scsi/aacraid/Makefile | 4 | ||||
-rw-r--r-- | xen/drivers/scsi/aacraid/README | 17 | ||||
-rw-r--r-- | xen/drivers/scsi/aacraid/TODO | 1 | ||||
-rw-r--r-- | xen/drivers/scsi/aacraid/aachba.c | 1657 | ||||
-rw-r--r-- | xen/drivers/scsi/aacraid/aacraid.h | 146 | ||||
-rw-r--r-- | xen/drivers/scsi/aacraid/commctrl.c | 59 | ||||
-rw-r--r-- | xen/drivers/scsi/aacraid/comminit.c | 70 | ||||
-rw-r--r-- | xen/drivers/scsi/aacraid/commsup.c | 1396 | ||||
-rw-r--r-- | xen/drivers/scsi/aacraid/dpcsup.c | 79 | ||||
-rw-r--r-- | xen/drivers/scsi/aacraid/linit.c | 760 | ||||
-rw-r--r-- | xen/drivers/scsi/aacraid/rx.c | 602 | ||||
-rw-r--r-- | xen/drivers/scsi/aacraid/sa.c | 38 |
12 files changed, 2497 insertions, 2332 deletions
diff --git a/xen/drivers/scsi/aacraid/Makefile b/xen/drivers/scsi/aacraid/Makefile index 7d802c3bc9..b7235fca4b 100644 --- a/xen/drivers/scsi/aacraid/Makefile +++ b/xen/drivers/scsi/aacraid/Makefile @@ -3,10 +3,6 @@ include $(BASEDIR)/Rules.mk CFLAGS += -I$(BASEDIR)/drivers/scsi - -# -y := linit.o aachba.o commctrl.o comminit.o commsup.o \ -# dpcsup.o rx.o sa.o - default: $(OBJS) $(LD) -r -o aacraid.o $(OBJS) diff --git a/xen/drivers/scsi/aacraid/README b/xen/drivers/scsi/aacraid/README index 9f73c6719b..617258fdc8 100644 --- a/xen/drivers/scsi/aacraid/README +++ b/xen/drivers/scsi/aacraid/README @@ -18,6 +18,12 @@ Supported Cards/Chipsets ADAPTEC 2120S ADAPTEC 2200S ADAPTEC 5400S + Legend S220 + Legend S230 + Adaptec 3230S + Adaptec 3240S + ASR-2020S PCI-X + AAR-2410SA SATA People ------------------------- @@ -28,15 +34,22 @@ Deanna Bonds <deanna_bonds@adaptec.com> (non-DASD support, PAE fibs and 64 bit, added new ioctls, changed scsi interface to use new error handler, increased the number of fibs and outstanding commands to a container) + (fixed 64bit and 64G memory model, changed confusing naming convention + where fibs that go to the hardware are consistently called hw_fibs and + not just fibs like the name of the driver tracking structure) +Mark Salyzyn <Mark_Salyzyn@adaptec.com> Fixed panic issues and added some new product ids for upcoming hbas. + Original Driver ------------------------- Adaptec Unix OEM Product Group Mailing List ------------------------- -None currently. Also note this is very different to Brian's original driver +linux-aacraid-devel@dell.com (Interested parties troll here) +http://mbserver.adaptec.com/ (Currently more Community Support than Devel Support) +Also note this is very different to Brian's original driver so don't expect him to support it. -Adaptec does support this driver. Contact either tech support or deanna bonds. +Adaptec does support this driver. Contact either tech support or Mark Salyzyn. Original by Brian Boerner February 2001 Rewritten by Alan Cox, November 2001 diff --git a/xen/drivers/scsi/aacraid/TODO b/xen/drivers/scsi/aacraid/TODO index 6f71022413..f9ac6ac884 100644 --- a/xen/drivers/scsi/aacraid/TODO +++ b/xen/drivers/scsi/aacraid/TODO @@ -2,3 +2,4 @@ o Testing o More testing o Feature request: display the firmware/bios/etc revisions in the /proc info +o 2.5.0 and beyond. diff --git a/xen/drivers/scsi/aacraid/aachba.c b/xen/drivers/scsi/aacraid/aachba.c index 198e37cace..91153460e8 100644 --- a/xen/drivers/scsi/aacraid/aachba.c +++ b/xen/drivers/scsi/aacraid/aachba.c @@ -22,15 +22,17 @@ * */ -#include <xeno/config.h> -/* #include <xeno/kernel.h> */ -#include <xeno/init.h> -#include <xeno/sched.h> -#include <xeno/pci.h> -/* #include <xeno/spinlock.h> */ -/* #include <xeno/slab.h> */ -/* #include <xeno/completion.h> */ -/* #include <asm/semaphore.h> */ +#include <linux/config.h> +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/types.h> +#include <linux/sched.h> +#include <linux/pci.h> +#include <linux/spinlock.h> +#include <linux/slab.h> +/*#include <linux/completion.h>*/ +/*#include <asm/semaphore.h>*/ #include <asm/uaccess.h> #define MAJOR_NR SCSI_DISK0_MAJOR /* For DEVICE_NR() */ #include <linux/blk.h> @@ -213,8 +215,7 @@ struct sense_data { * M O D U L E G L O B A L S */ -static struct fsa_scsi_hba *fsa_dev[MAXIMUM_NUM_ADAPTERS]; /* SCSI Device - Instance Ptrs */ +static struct fsa_scsi_hba *fsa_dev[MAXIMUM_NUM_ADAPTERS]; /* SCSI Device Instance Pointers */ static struct sense_data sense_data[MAXIMUM_NUM_CONTAINERS]; static void get_sd_devname(int disknum, char *buffer); static unsigned long aac_build_sg(Scsi_Cmnd* scsicmd, struct sgmap* sgmap); @@ -224,6 +225,15 @@ static int aac_send_srb_fib(Scsi_Cmnd* scsicmd); static char *aac_get_status_string(u32 status); #endif +/* + * Non dasd selection is handled entirely in aachba now + */ + +MODULE_PARM(nondasd, "i"); +MODULE_PARM_DESC(nondasd, "Control scanning of hba for nondasd devices. 0=off, 1=on"); + +static int nondasd = -1; + /** * aac_get_containers - list containers * @common: adapter to probe @@ -232,57 +242,59 @@ static char *aac_get_status_string(u32 status); */ int aac_get_containers(struct aac_dev *dev) { - struct fsa_scsi_hba *fsa_dev_ptr; - u32 index, status = 0; - struct aac_query_mount *dinfo; - struct aac_mount *dresp; - struct fib * fibptr; - unsigned instance; - - fsa_dev_ptr = &(dev->fsa_dev); - instance = dev->scsi_host_ptr->unique_id; - - if (!(fibptr = fib_alloc(dev))) - return -ENOMEM; - - for (index = 0; index < MAXIMUM_NUM_CONTAINERS; index++) { - fib_init(fibptr); - dinfo = (struct aac_query_mount *) fib_data(fibptr); - - dinfo->command = cpu_to_le32(VM_NameServe); - dinfo->count = cpu_to_le32(index); - dinfo->type = cpu_to_le32(FT_FILESYS); + struct fsa_scsi_hba *fsa_dev_ptr; + u32 index; + int status = 0; + struct aac_query_mount *dinfo; + struct aac_mount *dresp; + struct fib * fibptr; + unsigned instance; - status = fib_send(ContainerCommand, - fibptr, - sizeof (struct aac_query_mount), - FsaNormal, - 1, 1, - NULL, NULL); - if (status < 0 ) { - printk(KERN_WARNING "ProbeContainers: SendFIB failed.\n"); - break; - } - dresp = (struct aac_mount *)fib_data(fibptr); - - if ((le32_to_cpu(dresp->status) == ST_OK) && - (le32_to_cpu(dresp->mnt[0].vol) != CT_NONE)) { - fsa_dev_ptr->valid[index] = 1; - fsa_dev_ptr->type[index] = le32_to_cpu(dresp->mnt[0].vol); - fsa_dev_ptr->size[index] = le32_to_cpu(dresp->mnt[0].capacity); - if (le32_to_cpu(dresp->mnt[0].state) & FSCS_READONLY) - fsa_dev_ptr->ro[index] = 1; + fsa_dev_ptr = &(dev->fsa_dev); + instance = dev->scsi_host_ptr->unique_id; + + if (!(fibptr = fib_alloc(dev))) + return -ENOMEM; + + for (index = 0; index < MAXIMUM_NUM_CONTAINERS; index++) { + fib_init(fibptr); + dinfo = (struct aac_query_mount *) fib_data(fibptr); + + dinfo->command = cpu_to_le32(VM_NameServe); + dinfo->count = cpu_to_le32(index); + dinfo->type = cpu_to_le32(FT_FILESYS); + + status = fib_send(ContainerCommand, + fibptr, + sizeof (struct aac_query_mount), + FsaNormal, + 1, 1, + NULL, NULL); + if (status < 0 ) { + printk(KERN_WARNING "aac_get_containers: SendFIB failed.\n"); + break; + } + dresp = (struct aac_mount *)fib_data(fibptr); + + if ((le32_to_cpu(dresp->status) == ST_OK) && + (le32_to_cpu(dresp->mnt[0].vol) != CT_NONE) && + (le32_to_cpu(dresp->mnt[0].state) != FSCS_HIDDEN)) { + fsa_dev_ptr->valid[index] = 1; + fsa_dev_ptr->type[index] = le32_to_cpu(dresp->mnt[0].vol); + fsa_dev_ptr->size[index] = le32_to_cpu(dresp->mnt[0].capacity); + if (le32_to_cpu(dresp->mnt[0].state) & FSCS_READONLY) + fsa_dev_ptr->ro[index] = 1; + } + fib_complete(fibptr); + /* + * If there are no more containers, then stop asking. + */ + if ((index + 1) >= le32_to_cpu(dresp->count)) + break; } - fib_complete(fibptr); - /* - * If there are no more containers, then stop asking. - */ - if ((index + 1) >= le32_to_cpu(dresp->count)) - break; - } - fib_free(fibptr); - fsa_dev[instance] = fsa_dev_ptr; - return status; + fib_free(fibptr); + fsa_dev[instance] = fsa_dev_ptr; + return status; } /** @@ -296,54 +308,55 @@ int aac_get_containers(struct aac_dev *dev) static int probe_container(struct aac_dev *dev, int cid) { - struct fsa_scsi_hba *fsa_dev_ptr; - int status; - struct aac_query_mount *dinfo; - struct aac_mount *dresp; - struct fib * fibptr; - unsigned instance; - - fsa_dev_ptr = &(dev->fsa_dev); - instance = dev->scsi_host_ptr->unique_id; - - if (!(fibptr = fib_alloc(dev))) - return -ENOMEM; - - fib_init(fibptr); - - dinfo = (struct aac_query_mount *)fib_data(fibptr); - - dinfo->command = cpu_to_le32(VM_NameServe); - dinfo->count = cpu_to_le32(cid); - dinfo->type = cpu_to_le32(FT_FILESYS); - - status = fib_send(ContainerCommand, - fibptr, - sizeof(struct aac_query_mount), - FsaNormal, - 1, 1, - NULL, NULL); - if (status < 0) { - printk(KERN_WARNING "aacraid: probe_containers query failed.\n"); - goto error; - } - - dresp = (struct aac_mount *) fib_data(fibptr); - - if ((le32_to_cpu(dresp->status) == ST_OK) && - (le32_to_cpu(dresp->mnt[0].vol) != CT_NONE)) { - fsa_dev_ptr->valid[cid] = 1; - fsa_dev_ptr->type[cid] = le32_to_cpu(dresp->mnt[0].vol); - fsa_dev_ptr->size[cid] = le32_to_cpu(dresp->mnt[0].capacity); - if (le32_to_cpu(dresp->mnt[0].state) & FSCS_READONLY) - fsa_dev_ptr->ro[cid] = 1; - } - - error: - fib_complete(fibptr); - fib_free(fibptr); - - return status; + struct fsa_scsi_hba *fsa_dev_ptr; + int status; + struct aac_query_mount *dinfo; + struct aac_mount *dresp; + struct fib * fibptr; + unsigned instance; + + fsa_dev_ptr = &(dev->fsa_dev); + instance = dev->scsi_host_ptr->unique_id; + + if (!(fibptr = fib_alloc(dev))) + return -ENOMEM; + + fib_init(fibptr); + + dinfo = (struct aac_query_mount *)fib_data(fibptr); + + dinfo->command = cpu_to_le32(VM_NameServe); + dinfo->count = cpu_to_le32(cid); + dinfo->type = cpu_to_le32(FT_FILESYS); + + status = fib_send(ContainerCommand, + fibptr, + sizeof(struct aac_query_mount), + FsaNormal, + 1, 1, + NULL, NULL); + if (status < 0) { + printk(KERN_WARNING "aacraid: probe_containers query failed.\n"); + goto error; + } + + dresp = (struct aac_mount *) fib_data(fibptr); + + if ((le32_to_cpu(dresp->status) == ST_OK) && + (le32_to_cpu(dresp->mnt[0].vol) != CT_NONE) && + (le32_to_cpu(dresp->mnt[0].state) != FSCS_HIDDEN)) { + fsa_dev_ptr->valid[cid] = 1; + fsa_dev_ptr->type[cid] = le32_to_cpu(dresp->mnt[0].vol); + fsa_dev_ptr->size[cid] = le32_to_cpu(dresp->mnt[0].capacity); + if (le32_to_cpu(dresp->mnt[0].state) & FSCS_READONLY) + fsa_dev_ptr->ro[cid] = 1; + } + +error: + fib_complete(fibptr); + fib_free(fibptr); + + return status; } /* Local Structure to set SCSI inquiry data strings */ @@ -482,7 +495,6 @@ int aac_get_adapter_info(struct aac_dev* dev) struct aac_adapter_info* info; int rcode; u32 tmp; - if (!(fibptr = fib_alloc(dev))) return -ENOMEM; @@ -520,24 +532,54 @@ int aac_get_adapter_info(struct aac_dev* dev) dev->name, dev->id, dev->adapter_info.serial[0], dev->adapter_info.serial[1]); - dev->pae_support = 0; + dev->nondasd_support = 0; - if( BITS_PER_LONG >= 64 && - (dev->adapter_info.options & AAC_OPT_SGMAP_HOST64)){ - printk(KERN_INFO "%s%d: 64 Bit PAE enabled\n", - dev->name, dev->id); + dev->raid_scsi_mode = 0; + if(dev->adapter_info.options & AAC_OPT_NONDASD){ + dev->nondasd_support = 1; + } + + /* + * If the firmware supports ROMB RAID/SCSI mode and we are currently + * in RAID/SCSI mode, set the flag. For now if in this mode we will + * force nondasd support on. If we decide to allow the non-dasd flag + * additional changes changes will have to be made to support + * RAID/SCSI. the function aac_scsi_cmd in this module will have to be + * changed to support the new dev->raid_scsi_mode flag instead of + * leaching off of the dev->nondasd_support flag. Also in linit.c the + * function aac_detect will have to be modified where it sets up the + * max number of channels based on the aac->nondasd_support flag only. + */ + if ((dev->adapter_info.options & AAC_OPT_SCSI_MANAGED) + && (dev->adapter_info.options & AAC_OPT_RAID_SCSI_MODE)) + { + dev->nondasd_support = 1; + dev->raid_scsi_mode = 1; + } + if (dev->raid_scsi_mode != 0) + printk(KERN_INFO "%s%d: ROMB RAID/SCSI mode enabled\n",dev->name, dev->id); + + if (nondasd != -1) + dev->nondasd_support = (nondasd!=0); + + if(dev->nondasd_support != 0) + printk(KERN_INFO "%s%d: Non-DASD support enabled\n",dev->name, dev->id); + + dev->pae_support = 0; + if( (sizeof(dma_addr_t) > 4) && (dev->adapter_info.options & AAC_OPT_SGMAP_HOST64)){ dev->pae_support = 1; } /* TODO - dmb temporary until fw can set this bit */ dev->pae_support = (BITS_PER_LONG >= 64); - if(dev->pae_support != 0) { - printk(KERN_INFO "%s%d: 64 Bit PAE enabled\n", - dev->name, dev->id); + if(dev->pae_support != 0) + { + printk(KERN_INFO "%s%d: 64 Bit PAE enabled\n", dev->name, dev->id); + pci_set_dma_mask(dev->pdev, (dma_addr_t)0xFFFFFFFFFFFFFFFFULL); } - if(dev->adapter_info.options & AAC_OPT_NONDASD){ - dev->nondasd_support = 1; - } + fib_complete(fibptr); + fib_free(fibptr); + return rcode; } @@ -556,7 +598,7 @@ static void read_callback(void *context, struct fib * fibptr) cid =TARGET_LUN_TO_CONTAINER(scsicmd->target, scsicmd->lun); lba = ((scsicmd->cmnd[1] & 0x1F) << 16) | (scsicmd->cmnd[2] << 8) | scsicmd->cmnd[3]; - dprintk((KERN_DEBUG "read_callback[cpu %d]: lba = %d, t = %ld.\n", smp_processor_id(), lba, jiffies)); + dprintk((KERN_DEBUG "read_callback[cpu %d]: lba = %u, t = %ld.\n", smp_processor_id(), lba, jiffies)); if (fibptr == NULL) BUG(); @@ -601,7 +643,7 @@ static void write_callback(void *context, struct fib * fibptr) cid = TARGET_LUN_TO_CONTAINER(scsicmd->target, scsicmd->lun); lba = ((scsicmd->cmnd[1] & 0x1F) << 16) | (scsicmd->cmnd[2] << 8) | scsicmd->cmnd[3]; - dprintk((KERN_DEBUG "write_callback[cpu %d]: lba = %d, t = %ld.\n", smp_processor_id(), lba, jiffies)); + dprintk((KERN_DEBUG "write_callback[cpu %d]: lba = %u, t = %ld.\n", smp_processor_id(), lba, jiffies)); if (fibptr == NULL) BUG(); @@ -687,8 +729,7 @@ int aac_read(Scsi_Cmnd * scsicmd, int cid) aac_build_sg64(scsicmd, &readcmd->sg); if(readcmd->sg.count > MAX_DRIVER_SG_SEGMENT_COUNT) BUG(); - fibsize = sizeof(struct aac_read64) + - ((readcmd->sg.count - 1) * sizeof (struct sgentry64)); + fibsize = sizeof(struct aac_read64) + ((readcmd->sg.count - 1) * sizeof (struct sgentry64)); /* * Now send the Fib to the adapter */ @@ -713,8 +754,7 @@ int aac_read(Scsi_Cmnd * scsicmd, int cid) aac_build_sg(scsicmd, &readcmd->sg); if(readcmd->sg.count > MAX_DRIVER_SG_SEGMENT_COUNT) BUG(); - fibsize = sizeof(struct aac_read) + - ((readcmd->sg.count - 1) * sizeof (struct sgentry)); + fibsize = sizeof(struct aac_read) + ((readcmd->sg.count - 1) * sizeof (struct sgentry)); /* * Now send the Fib to the adapter */ @@ -734,8 +774,7 @@ int aac_read(Scsi_Cmnd * scsicmd, int cid) if (status == -EINPROGRESS) return 0; - printk(KERN_WARNING "aac_read: fib_send failed with status: %d.\n", - status); + printk(KERN_WARNING "aac_read: fib_send failed with status: %d.\n", status); /* * For some reason, the Fib didn't queue, return QUEUE_FULL */ @@ -770,8 +809,7 @@ static int aac_write(Scsi_Cmnd * scsicmd, int cid) lba = (scsicmd->cmnd[2] << 24) | (scsicmd->cmnd[3] << 16) | (scsicmd->cmnd[4] << 8) | scsicmd->cmnd[5]; count = (scsicmd->cmnd[7] << 8) | scsicmd->cmnd[8]; } - dprintk((KERN_DEBUG "aac_write[cpu %d]: lba = %u, t = %ld.\n", - smp_processor_id(), lba, jiffies)); + dprintk((KERN_DEBUG "aac_write[cpu %d]: lba = %u, t = %ld.\n", smp_processor_id(), lba, jiffies)); /* * Allocate and initialize a Fib then setup a BlockWrite command */ @@ -796,8 +834,7 @@ static int aac_write(Scsi_Cmnd * scsicmd, int cid) aac_build_sg64(scsicmd, &writecmd->sg); if(writecmd->sg.count > MAX_DRIVER_SG_SEGMENT_COUNT) BUG(); - fibsize = sizeof(struct aac_write64) + - ((writecmd->sg.count - 1) * sizeof (struct sgentry64)); + fibsize = sizeof(struct aac_write64) + ((writecmd->sg.count - 1) * sizeof (struct sgentry64)); /* * Now send the Fib to the adapter */ @@ -825,8 +862,7 @@ static int aac_write(Scsi_Cmnd * scsicmd, int cid) aac_build_sg(scsicmd, &writecmd->sg); if(writecmd->sg.count > MAX_DRIVER_SG_SEGMENT_COUNT) BUG(); - fibsize = sizeof(struct aac_write) + - ((writecmd->sg.count - 1) * sizeof (struct sgentry)); + fibsize = sizeof(struct aac_write) + ((writecmd->sg.count - 1) * sizeof (struct sgentry)); /* * Now send the Fib to the adapter */ @@ -869,358 +905,351 @@ static int aac_write(Scsi_Cmnd * scsicmd, int cid) int aac_scsi_cmd(Scsi_Cmnd * scsicmd) { - u32 cid = 0; - struct fsa_scsi_hba *fsa_dev_ptr; - int cardtype; - int ret; - struct aac_dev *dev = (struct aac_dev *)scsicmd->host->hostdata; - - cardtype = dev->cardtype; - - fsa_dev_ptr = fsa_dev[scsicmd->host->unique_id]; - - /* - * If the bus, target or lun is out of range, return fail - * Test does not apply to ID 16, the pseudo id for the controller - * itself. - */ - if (scsicmd->target != scsicmd->host->this_id) { - if ((scsicmd->channel == 0) ){ - if( (scsicmd->target >= AAC_MAX_TARGET) || (scsicmd->lun != 0)){ - scsicmd->result = DID_NO_CONNECT << 16; - __aac_io_done(scsicmd); - return 0; - } - cid = TARGET_LUN_TO_CONTAINER(scsicmd->target, scsicmd->lun); - - /* - * If the target container doesn't exist, it may have - * been newly created - */ - if (fsa_dev_ptr->valid[cid] == 0) { - switch (scsicmd->cmnd[0]) { - case SS_INQUIR: - case SS_RDCAP: - case SS_TEST: - spin_unlock_irq(&io_request_lock); - probe_container(dev, cid); - spin_lock_irq(&io_request_lock); - if (fsa_dev_ptr->valid[cid] == 0) { - scsicmd->result = DID_NO_CONNECT << 16; - __aac_io_done(scsicmd); - return 0; - } - default: - break; + u32 cid = 0; + struct fsa_scsi_hba *fsa_dev_ptr; + int cardtype; + int ret; + struct aac_dev *dev = (struct aac_dev *)scsicmd->host->hostdata; + + cardtype = dev->cardtype; + + fsa_dev_ptr = fsa_dev[scsicmd->host->unique_id]; + + /* + * If the bus, target or lun is out of range, return fail + * Test does not apply to ID 16, the pseudo id for the controller + * itself. + */ + if (scsicmd->target != scsicmd->host->this_id) { + if ((scsicmd->channel == 0) ){ + if( (scsicmd->target >= AAC_MAX_TARGET) || (scsicmd->lun != 0)){ + scsicmd->result = DID_NO_CONNECT << 16; + __aac_io_done(scsicmd); + return 0; + } + cid = TARGET_LUN_TO_CONTAINER(scsicmd->target, scsicmd->lun); + + /* + * If the target container doesn't exist, it may have + * been newly created + */ + if (fsa_dev_ptr->valid[cid] == 0) { + switch (scsicmd->cmnd[0]) { + case SS_INQUIR: + case SS_RDCAP: + case SS_TEST: + spin_unlock_irq(&io_request_lock); + probe_container(dev, cid); + spin_lock_irq(&io_request_lock); + if (fsa_dev_ptr->valid[cid] == 0) { + scsicmd->result = DID_NO_CONNECT << 16; + __aac_io_done(scsicmd); + return 0; + } + default: + break; + } + } + /* + * If the target container still doesn't exist, + * return failure + */ + if (fsa_dev_ptr->valid[cid] == 0) { + scsicmd->result = DID_BAD_TARGET << 16; + __aac_io_done(scsicmd); + return -1; + } + } else { /* check for physical non-dasd devices */ + if(dev->nondasd_support == 1){ + return aac_send_srb_fib(scsicmd); + } else { + scsicmd->result = DID_NO_CONNECT << 16; + __aac_io_done(scsicmd); + return 0; + } } - } - /* - * If the target container still doesn't exist, - * return failure - */ - if (fsa_dev_ptr->valid[cid] == 0) { - scsicmd->result = DID_BAD_TARGET << 16; + } + /* + * else Command for the controller itself + */ + else if ((scsicmd->cmnd[0] != SS_INQUIR) && /* only INQUIRY & TUR cmnd supported for controller */ + (scsicmd->cmnd[0] != SS_TEST)) + { + dprintk((KERN_WARNING "Only INQUIRY & TUR command supported for controller, rcvd = 0x%x.\n", scsicmd->cmnd[0])); + scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | CHECK_CONDITION; + set_sense((u8 *) &sense_data[cid], + SENKEY_ILLEGAL, + SENCODE_INVALID_COMMAND, + ASENCODE_INVALID_COMMAND, 0, 0, 0, 0); __aac_io_done(scsicmd); return -1; - } - } else { /* check for physical non-dasd devices */ - if(dev->nondasd_support == 1){ - return aac_send_srb_fib(scsicmd); - } else { - scsicmd->result = DID_NO_CONNECT << 16; + } + + + /* Handle commands here that don't really require going out to the adapter */ + switch (scsicmd->cmnd[0]) { + case SS_INQUIR: + { + struct inquiry_data *inq_data_ptr; + + dprintk((KERN_DEBUG "INQUIRY command, ID: %d.\n", scsicmd->target)); + inq_data_ptr = (struct inquiry_data *)scsicmd->request_buffer; + memset(inq_data_ptr, 0, sizeof (struct inquiry_data)); + + inq_data_ptr->inqd_ver = 2; /* claim compliance to SCSI-2 */ + inq_data_ptr->inqd_dtq = 0x80; /* set RMB bit to one indicating that the medium is removable */ + inq_data_ptr->inqd_rdf = 2; /* A response data format value of two indicates that the data shall be in the format specified in SCSI-2 */ + inq_data_ptr->inqd_len = 31; + /*Format for "pad2" is RelAdr | WBus32 | WBus16 | Sync | Linked |Reserved| CmdQue | SftRe */ + inq_data_ptr->inqd_pad2= 0x32 ; /*WBus16|Sync|CmdQue */ + /* + * Set the Vendor, Product, and Revision Level + * see: <vendor>.c i.e. aac.c + */ + setinqstr(cardtype, (void *) (inq_data_ptr->inqd_vid), fsa_dev_ptr->type[cid]); + if (scsicmd->target == scsicmd->host->this_id) + inq_data_ptr->inqd_pdt = INQD_PDT_PROC; /* Processor device */ + else + inq_data_ptr->inqd_pdt = INQD_PDT_DA; /* Direct/random access device */ + scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | GOOD; __aac_io_done(scsicmd); return 0; - } } - } - /* - * else Command for the controller itself - */ - else if ((scsicmd->cmnd[0] != SS_INQUIR) && - (scsicmd->cmnd[0] != SS_TEST)) - { - /* only INQUIRY & TUR cmnd supported for controller */ - dprintk((KERN_WARNING "Only INQUIRY & TUR command supported for " - "controller, rcvd = 0x%x.\n", scsicmd->cmnd[0])); - scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | - CHECK_CONDITION; - set_sense((u8 *) &sense_data[cid], - SENKEY_ILLEGAL, - SENCODE_INVALID_COMMAND, - ASENCODE_INVALID_COMMAND, 0, 0, 0, 0); - __aac_io_done(scsicmd); - return -1; - } - - - /* Handle commands here that don't require going out to the adapter */ - switch (scsicmd->cmnd[0]) { - case SS_INQUIR: - { - struct inquiry_data *inq_data_ptr; - - dprintk((KERN_DEBUG "INQUIRY command, ID: %d.\n", scsicmd->target)); - inq_data_ptr = (struct inquiry_data *)scsicmd->request_buffer; - memset(inq_data_ptr, 0, sizeof (struct inquiry_data)); - - inq_data_ptr->inqd_ver = 2; /* claim compliance to SCSI-2 */ - inq_data_ptr->inqd_dtq = 0x80; /* set RMB bit to one indicating that the medium is removable */ - inq_data_ptr->inqd_rdf = 2; /* A response data format value of two indicates that the data shall be in the format specified in SCSI-2 */ - inq_data_ptr->inqd_len = 31; - /*Format for "pad2" is RelAdr | WBus32 | WBus16 | Sync | Linked |Reserved| CmdQue | SftRe */ - inq_data_ptr->inqd_pad2= 0x32 ; /*WBus16|Sync|CmdQue */ - /* - * Set the Vendor, Product, and Revision Level - * see: <vendor>.c i.e. aac.c - */ - setinqstr(cardtype, (void *) (inq_data_ptr->inqd_vid), fsa_dev_ptr->type[cid]); - if (scsicmd->target == scsicmd->host->this_id) - inq_data_ptr->inqd_pdt = INQD_PDT_PROC; /* Processor device */ - else - inq_data_ptr->inqd_pdt = INQD_PDT_DA; /* Direct/random access device */ - scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | GOOD; - __aac_io_done(scsicmd); - return 0; - } - case SS_RDCAP: - { - int capacity; - char *cp; - - dprintk((KERN_DEBUG "READ CAPACITY command.\n")); - capacity = fsa_dev_ptr->size[cid] - 1; - cp = scsicmd->request_buffer; - cp[0] = (capacity >> 24) & 0xff; - cp[1] = (capacity >> 16) & 0xff; - cp[2] = (capacity >> 8) & 0xff; - cp[3] = (capacity >> 0) & 0xff; - cp[4] = 0; - cp[5] = 0; - cp[6] = 2; - cp[7] = 0; - - scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | GOOD; - __aac_io_done(scsicmd); - - return 0; - } - - case SS_MODESEN: - { - char *mode_buf; - - dprintk((KERN_DEBUG "MODE SENSE command.\n")); - mode_buf = scsicmd->request_buffer; - mode_buf[0] = 0; /* Mode data length (MSB) */ - mode_buf[1] = 6; /* Mode data length (LSB) */ - mode_buf[2] = 0; /* Medium type - default */ - mode_buf[3] = 0; /* Device-specific param, - bit 8: 0/1 = write enabled/protected */ - mode_buf[4] = 0; /* reserved */ - mode_buf[5] = 0; /* reserved */ - mode_buf[6] = 0; /* Block descriptor length (MSB) */ - mode_buf[7] = 0; /* Block descriptor length (LSB) */ - - scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | GOOD; - __aac_io_done(scsicmd); - - return 0; - } - case SS_REQSEN: - dprintk((KERN_DEBUG "REQUEST SENSE command.\n")); - memcpy(scsicmd->sense_buffer, &sense_data[cid], - sizeof (struct sense_data)); - memset(&sense_data[cid], 0, sizeof (struct sense_data)); - scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | GOOD; - __aac_io_done(scsicmd); - return (0); - - case SS_LOCK: - dprintk((KERN_DEBUG "LOCK command.\n")); - if (scsicmd->cmnd[4]) - fsa_dev_ptr->locked[cid] = 1; - else - fsa_dev_ptr->locked[cid] = 0; - - scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | GOOD; - __aac_io_done(scsicmd); - return 0; + case SS_RDCAP: + { + int capacity; + char *cp; + + dprintk((KERN_DEBUG "READ CAPACITY command.\n")); + capacity = fsa_dev_ptr->size[cid] - 1; + cp = scsicmd->request_buffer; + cp[0] = (capacity >> 24) & 0xff; + cp[1] = (capacity >> 16) & 0xff; + cp[2] = (capacity >> 8) & 0xff; + cp[3] = (capacity >> 0) & 0xff; + cp[4] = 0; + cp[5] = 0; + cp[6] = 2; + cp[7] = 0; + + scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | GOOD; + __aac_io_done(scsicmd); + + return 0; + } + + case SS_MODESEN: + { + char *mode_buf; + + dprintk((KERN_DEBUG "MODE SENSE command.\n")); + mode_buf = scsicmd->request_buffer; + mode_buf[0] = 0; /* Mode data length (MSB) */ + mode_buf[1] = 6; /* Mode data length (LSB) */ + mode_buf[2] = 0; /* Medium type - default */ + mode_buf[3] = 0; /* Device-specific param, bit 8: 0/1 = write enabled/protected */ + mode_buf[4] = 0; /* reserved */ + mode_buf[5] = 0; /* reserved */ + mode_buf[6] = 0; /* Block descriptor length (MSB) */ + mode_buf[7] = 0; /* Block descriptor length (LSB) */ + + scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | GOOD; + __aac_io_done(scsicmd); + + return 0; + } + case SS_REQSEN: + dprintk((KERN_DEBUG "REQUEST SENSE command.\n")); + memcpy(scsicmd->sense_buffer, &sense_data[cid], sizeof (struct sense_data)); + memset(&sense_data[cid], 0, sizeof (struct sense_data)); + scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | GOOD; + __aac_io_done(scsicmd); + return (0); + + case SS_LOCK: + dprintk((KERN_DEBUG "LOCK command.\n")); + if (scsicmd->cmnd[4]) + fsa_dev_ptr->locked[cid] = 1; + else + fsa_dev_ptr->locked[cid] = 0; + + scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | GOOD; + __aac_io_done(scsicmd); + return 0; /* * These commands are all No-Ops */ - case SS_TEST: - case SS_RESERV: - case SS_RELES: - case SS_REZERO: - case SS_REASGN: - case SS_SEEK: - case SS_ST_SP: - scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | GOOD; - __aac_io_done(scsicmd); - return (0); - } - - switch (scsicmd->cmnd[0]) - { - case SS_READ: - case SM_READ: - /* - * Hack to keep track of ordinal number of the device that - * corresponds to a container. Needed to convert - * containers to /dev/sd device names - */ - - spin_unlock_irq(&io_request_lock); - fsa_dev_ptr->devno[cid] = DEVICE_NR(scsicmd->request.rq_dev); - ret = aac_read(scsicmd, cid); - spin_lock_irq(&io_request_lock); - return ret; - - case SS_WRITE: - case SM_WRITE: - spin_unlock_irq(&io_request_lock); - ret = aac_write(scsicmd, cid); - spin_lock_irq(&io_request_lock); - return ret; - default: - /* - * Unhandled commands - */ - printk(KERN_WARNING "Unhandled SCSI Command: 0x%x.\n", - scsicmd->cmnd[0]); - scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | - CHECK_CONDITION; - set_sense((u8 *) &sense_data[cid], - SENKEY_ILLEGAL, SENCODE_INVALID_COMMAND, - ASENCODE_INVALID_COMMAND, 0, 0, 0, 0); - __aac_io_done(scsicmd); - return -1; - } + case SS_TEST: + case SS_RESERV: + case SS_RELES: + case SS_REZERO: + case SS_REASGN: + case SS_SEEK: + case SS_ST_SP: + scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | GOOD; + __aac_io_done(scsicmd); + return (0); + } + + switch (scsicmd->cmnd[0]) + { + case SS_READ: + case SM_READ: + /* + * Hack to keep track of ordinal number of the device that + * corresponds to a container. Needed to convert + * containers to /dev/sd device names + */ + + spin_unlock_irq(&io_request_lock); + fsa_dev_ptr->devno[cid] = DEVICE_NR(scsicmd->request.rq_dev); + ret = aac_read(scsicmd, cid); + spin_lock_irq(&io_request_lock); + return ret; + + case SS_WRITE: + case SM_WRITE: + spin_unlock_irq(&io_request_lock); + ret = aac_write(scsicmd, cid); + spin_lock_irq(&io_request_lock); + return ret; + default: + /* + * Unhandled commands + */ + printk(KERN_WARNING "Unhandled SCSI Command: 0x%x.\n", scsicmd->cmnd[0]); + scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | CHECK_CONDITION; + set_sense((u8 *) &sense_data[cid], + SENKEY_ILLEGAL, SENCODE_INVALID_COMMAND, + ASENCODE_INVALID_COMMAND, 0, 0, 0, 0); + __aac_io_done(scsicmd); + return -1; + } } static int query_disk(struct aac_dev *dev, void *arg) { - struct aac_query_disk qd; - struct fsa_scsi_hba *fsa_dev_ptr; - - fsa_dev_ptr = &(dev->fsa_dev); - if (copy_from_user(&qd, arg, sizeof (struct aac_query_disk))) - return -EFAULT; - if (qd.cnum == -1) - qd.cnum = TARGET_LUN_TO_CONTAINER(qd.target, qd.lun); - else if ((qd.bus == -1) && (qd.target == -1) && (qd.lun == -1)) - { - if (qd.cnum < 0 || qd.cnum > MAXIMUM_NUM_CONTAINERS) - return -EINVAL; - qd.instance = dev->scsi_host_ptr->host_no; - qd.bus = 0; - qd.target = CONTAINER_TO_TARGET(qd.cnum); - qd.lun = CONTAINER_TO_LUN(qd.cnum); - } - else return -EINVAL; - - qd.valid = fsa_dev_ptr->valid[qd.cnum]; - qd.locked = fsa_dev_ptr->locked[qd.cnum]; - qd.deleted = fsa_dev_ptr->deleted[qd.cnum]; - - if (fsa_dev_ptr->devno[qd.cnum] == -1) - qd.unmapped = 1; - else - qd.unmapped = 0; - - get_sd_devname(fsa_dev_ptr->devno[qd.cnum], qd.name); - - if (copy_to_user(arg, &qd, sizeof (struct aac_query_disk))) - return -EFAULT; - return 0; + struct aac_query_disk qd; + struct fsa_scsi_hba *fsa_dev_ptr; + + fsa_dev_ptr = &(dev->fsa_dev); + if (copy_from_user(&qd, arg, sizeof (struct aac_query_disk))) + return -EFAULT; + if (qd.cnum == -1) + qd.cnum = TARGET_LUN_TO_CONTAINER(qd.target, qd.lun); + else if ((qd.bus == -1) && (qd.target == -1) && (qd.lun == -1)) + { + if (qd.cnum < 0 || qd.cnum > MAXIMUM_NUM_CONTAINERS) + return -EINVAL; + qd.instance = dev->scsi_host_ptr->host_no; + qd.bus = 0; + qd.target = CONTAINER_TO_TARGET(qd.cnum); + qd.lun = CONTAINER_TO_LUN(qd.cnum); + } + else return -EINVAL; + + qd.valid = fsa_dev_ptr->valid[qd.cnum]; + qd.locked = fsa_dev_ptr->locked[qd.cnum]; + qd.deleted = fsa_dev_ptr->deleted[qd.cnum]; + + if (fsa_dev_ptr->devno[qd.cnum] == -1) + qd.unmapped = 1; + else + qd.unmapped = 0; + + get_sd_devname(fsa_dev_ptr->devno[qd.cnum], qd.name); + + if (copy_to_user(arg, &qd, sizeof (struct aac_query_disk))) + return -EFAULT; + return 0; } static void get_sd_devname(int disknum, char *buffer) { - if (disknum < 0) { - sprintf(buffer, "%s", ""); - return; - } - - if (disknum < 26) - sprintf(buffer, "sd%c", 'a' + disknum); - else { - unsigned int min1; - unsigned int min2; - /* - * For larger numbers of disks, we need to go to a new - * naming scheme. - */ - min1 = disknum / 26; - min2 = disknum % 26; - sprintf(buffer, "sd%c%c", 'a' + min1 - 1, 'a' + min2); - } + if (disknum < 0) { + sprintf(buffer, "%s", ""); + return; + } + + if (disknum < 26) + sprintf(buffer, "sd%c", 'a' + disknum); + else { + unsigned int min1; + unsigned int min2; + /* + * For larger numbers of disks, we need to go to a new + * naming scheme. + */ + min1 = disknum / 26; + min2 = disknum % 26; + sprintf(buffer, "sd%c%c", 'a' + min1 - 1, 'a' + min2); + } } static int force_delete_disk(struct aac_dev *dev, void *arg) { - struct aac_delete_disk dd; - struct fsa_scsi_hba *fsa_dev_ptr; - - fsa_dev_ptr = &(dev->fsa_dev); - - if (copy_from_user(&dd, arg, sizeof (struct aac_delete_disk))) - return -EFAULT; - - if (dd.cnum > MAXIMUM_NUM_CONTAINERS) - return -EINVAL; - /* - * Mark this container as being deleted. - */ - fsa_dev_ptr->deleted[dd.cnum] = 1; - /* - * Mark the container as no longer valid - */ - fsa_dev_ptr->valid[dd.cnum] = 0; - return 0; + struct aac_delete_disk dd; + struct fsa_scsi_hba *fsa_dev_ptr; + + fsa_dev_ptr = &(dev->fsa_dev); + + if (copy_from_user(&dd, arg, sizeof (struct aac_delete_disk))) + return -EFAULT; + + if (dd.cnum > MAXIMUM_NUM_CONTAINERS) + return -EINVAL; + /* + * Mark this container as being deleted. + */ + fsa_dev_ptr->deleted[dd.cnum] = 1; + /* + * Mark the container as no longer valid + */ + fsa_dev_ptr->valid[dd.cnum] = 0; + return 0; } static int delete_disk(struct aac_dev *dev, void *arg) { - struct aac_delete_disk dd; - struct fsa_scsi_hba *fsa_dev_ptr; - - fsa_dev_ptr = &(dev->fsa_dev); - - if (copy_from_user(&dd, arg, sizeof (struct aac_delete_disk))) - return -EFAULT; - - if (dd.cnum > MAXIMUM_NUM_CONTAINERS) - return -EINVAL; - /* - * If the container is locked, it can not be deleted by the API. - */ - if (fsa_dev_ptr->locked[dd.cnum]) - return -EBUSY; - else { + struct aac_delete_disk dd; + struct fsa_scsi_hba *fsa_dev_ptr; + + fsa_dev_ptr = &(dev->fsa_dev); + + if (copy_from_user(&dd, arg, sizeof (struct aac_delete_disk))) + return -EFAULT; + + if (dd.cnum > MAXIMUM_NUM_CONTAINERS) + return -EINVAL; /* - * Mark the container as no longer being valid. + * If the container is locked, it can not be deleted by the API. */ - fsa_dev_ptr->valid[dd.cnum] = 0; - fsa_dev_ptr->devno[dd.cnum] = -1; - return 0; - } + if (fsa_dev_ptr->locked[dd.cnum]) + return -EBUSY; + else { + /* + * Mark the container as no longer being valid. + */ + fsa_dev_ptr->valid[dd.cnum] = 0; + fsa_dev_ptr->devno[dd.cnum] = -1; + return 0; + } } int aac_dev_ioctl(struct aac_dev *dev, int cmd, void *arg) { - switch (cmd) { - case FSACTL_QUERY_DISK: - return query_disk(dev, arg); - case FSACTL_DELETE_DISK: - return delete_disk(dev, arg); - case FSACTL_FORCE_DELETE_DISK: - return force_delete_disk(dev, arg); - case 2131: - return aac_get_containers(dev); - default: - return -ENOTTY; - } + switch (cmd) { + case FSACTL_QUERY_DISK: + return query_disk(dev, arg); + case FSACTL_DELETE_DISK: + return delete_disk(dev, arg); + case FSACTL_FORCE_DELETE_DISK: + return force_delete_disk(dev, arg); + case 2131: + return aac_get_containers(dev); + default: + return -ENOTTY; + } } /** @@ -1235,160 +1264,189 @@ int aac_dev_ioctl(struct aac_dev *dev, int cmd, void *arg) static void aac_srb_callback(void *context, struct fib * fibptr) { - struct aac_dev *dev; - struct aac_srb_reply *srbreply; - Scsi_Cmnd *scsicmd; - - scsicmd = (Scsi_Cmnd *) context; - dev = (struct aac_dev *)scsicmd->host->hostdata; - - if (fibptr == NULL) - BUG(); - - srbreply = (struct aac_srb_reply *) fib_data(fibptr); - - scsicmd->sense_buffer[0] = '\0'; // initialize sense valid flag to false - // calculate resid for sg - scsicmd->resid = scsicmd->request_bufflen - srbreply->data_xfer_length; - - if(scsicmd->use_sg) - pci_unmap_sg(dev->pdev, - (struct scatterlist *)scsicmd->buffer, - scsicmd->use_sg, - scsi_to_pci_dma_dir(scsicmd->sc_data_direction)); - else if(scsicmd->request_bufflen) - pci_unmap_single(dev->pdev, (ulong)scsicmd->SCp.ptr, - scsicmd->request_bufflen, - scsi_to_pci_dma_dir(scsicmd->sc_data_direction)); - - /* - * First check the fib status - */ - - if (le32_to_cpu(srbreply->status) != ST_OK){ - int len; - printk(KERN_WARNING "aac_srb_callback: srb failed, status = %d\n", - le32_to_cpu(srbreply->status)); - len = (srbreply->sense_data_size > sizeof(scsicmd->sense_buffer))? - sizeof(scsicmd->sense_buffer):srbreply->sense_data_size; - scsicmd->result = DID_ERROR << 16 | COMMAND_COMPLETE << 8 | - CHECK_CONDITION; - memcpy(scsicmd->sense_buffer, srbreply->sense_data, len); - } - - /* - * Next check the srb status - */ - switch(le32_to_cpu(srbreply->srb_status)){ - case SRB_STATUS_ERROR_RECOVERY: - case SRB_STATUS_PENDING: - case SRB_STATUS_SUCCESS: - if(scsicmd->cmnd[0] == INQUIRY ){ - u8 b; - /* We can't expose disk devices because we can't tell whether they - * are the raw container drives or stand alone drives - */ - b = *(u8*)scsicmd->buffer; - if( (b & 0x0f) == TYPE_DISK ){ - scsicmd->result = DID_NO_CONNECT << 16 | COMMAND_COMPLETE << 8; - } - } else { - scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8; + struct aac_dev *dev; + struct aac_srb_reply *srbreply; + Scsi_Cmnd *scsicmd; + + scsicmd = (Scsi_Cmnd *) context; + dev = (struct aac_dev *)scsicmd->host->hostdata; + + if (fibptr == NULL) + BUG(); + + srbreply = (struct aac_srb_reply *) fib_data(fibptr); + + scsicmd->sense_buffer[0] = '\0'; // initialize sense valid flag to false + // calculate resid for sg + scsicmd->resid = scsicmd->request_bufflen - srbreply->data_xfer_length; + + if(scsicmd->use_sg) + pci_unmap_sg(dev->pdev, + (struct scatterlist *)scsicmd->buffer, + scsicmd->use_sg, + scsi_to_pci_dma_dir(scsicmd->sc_data_direction)); + else if(scsicmd->request_bufflen) + pci_unmap_single(dev->pdev, (ulong)scsicmd->SCp.ptr, scsicmd->request_bufflen, + scsi_to_pci_dma_dir(scsicmd->sc_data_direction)); + + /* + * First check the fib status + */ + + if (le32_to_cpu(srbreply->status) != ST_OK){ + int len; + printk(KERN_WARNING "aac_srb_callback: srb failed, status = %d\n", le32_to_cpu(srbreply->status)); + len = (srbreply->sense_data_size > sizeof(scsicmd->sense_buffer))? + sizeof(scsicmd->sense_buffer):srbreply->sense_data_size; + scsicmd->result = DID_ERROR << 16 | COMMAND_COMPLETE << 8 | CHECK_CONDITION; + memcpy(scsicmd->sense_buffer, srbreply->sense_data, len); } - break; - case SRB_STATUS_DATA_OVERRUN: - switch(scsicmd->cmnd[0]){ - case READ_6: - case WRITE_6: - case READ_10: - case WRITE_10: - case READ_12: - case WRITE_12: - if(le32_to_cpu(srbreply->data_xfer_length) < scsicmd->underflow ) { - printk(KERN_WARNING"aacraid: SCSI CMD underflow\n"); - } else { - printk(KERN_WARNING"aacraid: SCSI CMD Data Overrun\n"); - } - scsicmd->result = DID_ERROR << 16 | COMMAND_COMPLETE << 8; - break; + + /* + * Next check the srb status + */ + switch( (le32_to_cpu(srbreply->srb_status))&0x3f){ + case SRB_STATUS_ERROR_RECOVERY: + case SRB_STATUS_PENDING: + case SRB_STATUS_SUCCESS: + if(scsicmd->cmnd[0] == INQUIRY ){ + u8 b; + u8 b1; + /* We can't expose disk devices because we can't tell whether they + * are the raw container drives or stand alone drives. If they have + * the removable bit set then we should expose them though. + */ + b = (*(u8*)scsicmd->buffer)&0x1f; + b1 = ((u8*)scsicmd->buffer)[1]; + if( b==TYPE_TAPE || b==TYPE_WORM || b==TYPE_ROM || b==TYPE_MOD|| b==TYPE_MEDIUM_CHANGER + || (b==TYPE_DISK && (b1&0x80)) ){ + scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8; + /* + * We will allow disk devices if in RAID/SCSI mode and + * the channel is 2 + */ + } else if((dev->raid_scsi_mode)&&(scsicmd->channel == 2)){ + scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8; + } else { + scsicmd->result = DID_NO_CONNECT << 16 | COMMAND_COMPLETE << 8; + } + } else { + scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8; + } + break; + case SRB_STATUS_DATA_OVERRUN: + switch(scsicmd->cmnd[0]){ + case READ_6: + case WRITE_6: + case READ_10: + case WRITE_10: + case READ_12: + case WRITE_12: + if(le32_to_cpu(srbreply->data_xfer_length) < scsicmd->underflow ) { + printk(KERN_WARNING"aacraid: SCSI CMD underflow\n"); + } else { + printk(KERN_WARNING"aacraid: SCSI CMD Data Overrun\n"); + } + scsicmd->result = DID_ERROR << 16 | COMMAND_COMPLETE << 8; + break; + case INQUIRY: { + u8 b; + u8 b1; + /* We can't expose disk devices because we can't tell whether they + * are the raw container drives or stand alone drives + */ + b = (*(u8*)scsicmd->buffer)&0x0f; + b1 = ((u8*)scsicmd->buffer)[1]; + if( b==TYPE_TAPE || b==TYPE_WORM || b==TYPE_ROM || b==TYPE_MOD|| b==TYPE_MEDIUM_CHANGER + || (b==TYPE_DISK && (b1&0x80)) ){ + scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8; + /* + * We will allow disk devices if in RAID/SCSI mode and + * the channel is 2 + */ + } else if((dev->raid_scsi_mode)&&(scsicmd->channel == 2)){ + scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8; + } else { + scsicmd->result = DID_NO_CONNECT << 16 | COMMAND_COMPLETE << 8; + } + break; + } + default: + scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8; + break; + } + break; + case SRB_STATUS_ABORTED: + scsicmd->result = DID_ABORT << 16 | ABORT << 8; + break; + case SRB_STATUS_ABORT_FAILED: + // Not sure about this one - but assuming the hba was trying to abort for some reason + scsicmd->result = DID_ERROR << 16 | ABORT << 8; + break; + case SRB_STATUS_PARITY_ERROR: + scsicmd->result = DID_PARITY << 16 | MSG_PARITY_ERROR << 8; + break; + case SRB_STATUS_NO_DEVICE: + case SRB_STATUS_INVALID_PATH_ID: + case SRB_STATUS_INVALID_TARGET_ID: + case SRB_STATUS_INVALID_LUN: + case SRB_STATUS_SELECTION_TIMEOUT: + scsicmd->result = DID_NO_CONNECT << 16 | COMMAND_COMPLETE << 8; + break; + + case SRB_STATUS_COMMAND_TIMEOUT: + case SRB_STATUS_TIMEOUT: + scsicmd->result = DID_TIME_OUT << 16 | COMMAND_COMPLETE << 8; + break; + + case SRB_STATUS_BUSY: + scsicmd->result = DID_NO_CONNECT << 16 | COMMAND_COMPLETE << 8; + break; + + case SRB_STATUS_BUS_RESET: + scsicmd->result = DID_RESET << 16 | COMMAND_COMPLETE << 8; + break; + + case SRB_STATUS_MESSAGE_REJECTED: + scsicmd->result = DID_ERROR << 16 | MESSAGE_REJECT << 8; + break; + case SRB_STATUS_REQUEST_FLUSHED: + case SRB_STATUS_ERROR: + case SRB_STATUS_INVALID_REQUEST: + case SRB_STATUS_REQUEST_SENSE_FAILED: + case SRB_STATUS_NO_HBA: + case SRB_STATUS_UNEXPECTED_BUS_FREE: + case SRB_STATUS_PHASE_SEQUENCE_FAILURE: + case SRB_STATUS_BAD_SRB_BLOCK_LENGTH: + case SRB_STATUS_DELAYED_RETRY: + case SRB_STATUS_BAD_FUNCTION: + case SRB_STATUS_NOT_STARTED: + case SRB_STATUS_NOT_IN_USE: + case SRB_STATUS_FORCE_ABORT: + case SRB_STATUS_DOMAIN_VALIDATION_FAIL: default: - scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8; - break; - } - break; - case SRB_STATUS_ABORTED: - scsicmd->result = DID_ABORT << 16 | ABORT << 8; - break; - case SRB_STATUS_ABORT_FAILED: - // Not sure about this one - but assuming the hba was trying - // to abort for some reason - scsicmd->result = DID_ERROR << 16 | ABORT << 8; - break; - case SRB_STATUS_PARITY_ERROR: - scsicmd->result = DID_PARITY << 16 | MSG_PARITY_ERROR << 8; - break; - case SRB_STATUS_NO_DEVICE: - case SRB_STATUS_INVALID_PATH_ID: - case SRB_STATUS_INVALID_TARGET_ID: - case SRB_STATUS_INVALID_LUN: - case SRB_STATUS_SELECTION_TIMEOUT: - scsicmd->result = DID_NO_CONNECT << 16 | COMMAND_COMPLETE << 8; - break; - - case SRB_STATUS_COMMAND_TIMEOUT: - case SRB_STATUS_TIMEOUT: - scsicmd->result = DID_TIME_OUT << 16 | COMMAND_COMPLETE << 8; - break; - - case SRB_STATUS_BUSY: - scsicmd->result = DID_NO_CONNECT << 16 | COMMAND_COMPLETE << 8; - break; - - case SRB_STATUS_BUS_RESET: - scsicmd->result = DID_RESET << 16 | COMMAND_COMPLETE << 8; - break; - - case SRB_STATUS_MESSAGE_REJECTED: - scsicmd->result = DID_ERROR << 16 | MESSAGE_REJECT << 8; - break; - case SRB_STATUS_REQUEST_FLUSHED: - case SRB_STATUS_ERROR: - case SRB_STATUS_INVALID_REQUEST: - case SRB_STATUS_REQUEST_SENSE_FAILED: - case SRB_STATUS_NO_HBA: - case SRB_STATUS_UNEXPECTED_BUS_FREE: - case SRB_STATUS_PHASE_SEQUENCE_FAILURE: - case SRB_STATUS_BAD_SRB_BLOCK_LENGTH: - case SRB_STATUS_DELAYED_RETRY: - case SRB_STATUS_BAD_FUNCTION: - case SRB_STATUS_NOT_STARTED: - case SRB_STATUS_NOT_IN_USE: - case SRB_STATUS_FORCE_ABORT: - case SRB_STATUS_DOMAIN_VALIDATION_FAIL: - default: #ifdef AAC_DETAILED_STATUS_INFO - printk("aacraid: SRB ERROR (%s)\n", - aac_get_status_string(le32_to_cpu(srbreply->srb_status))); + printk("aacraid: SRB ERROR(%u) %s scsi cmd 0x%x - scsi status 0x%x\n",le32_to_cpu(srbreply->srb_status&0x3f),aac_get_status_string(le32_to_cpu(srbreply->srb_status)), scsicmd->cmnd[0], le32_to_cpu(srbreply->scsi_status) ); #endif - scsicmd->result = DID_ERROR << 16 | COMMAND_COMPLETE << 8; - break; - } - if (le32_to_cpu(srbreply->scsi_status) == 0x02 ){ // Check Condition - int len; - len = (srbreply->sense_data_size > sizeof(scsicmd->sense_buffer))? - sizeof(scsicmd->sense_buffer):srbreply->sense_data_size; - printk(KERN_WARNING "aac_srb_callback: check condition, " - "status = %d len=%d\n", le32_to_cpu(srbreply->status), len); - memcpy(scsicmd->sense_buffer, srbreply->sense_data, len); - } - /* - * OR in the scsi status (already shifted up a bit) - */ - scsicmd->result |= le32_to_cpu(srbreply->scsi_status); - - fib_complete(fibptr); - fib_free(fibptr); - aac_io_done(scsicmd); + scsicmd->result = DID_ERROR << 16 | COMMAND_COMPLETE << 8; + break; + } + if (le32_to_cpu(srbreply->scsi_status) == 0x02 ){ // Check Condition + int len; + scsicmd->result |= CHECK_CONDITION; + len = (srbreply->sense_data_size > sizeof(scsicmd->sense_buffer))? + sizeof(scsicmd->sense_buffer):srbreply->sense_data_size; + printk(KERN_WARNING "aac_srb_callback: check condition, status = %d len=%d\n", le32_to_cpu(srbreply->status), len); + memcpy(scsicmd->sense_buffer, srbreply->sense_data, len); + } + /* + * OR in the scsi status (already shifted up a bit) + */ + scsicmd->result |= le32_to_cpu(srbreply->scsi_status); + + fib_complete(fibptr); + fib_free(fibptr); + aac_io_done(scsicmd); } /** @@ -1402,227 +1460,230 @@ static void aac_srb_callback(void *context, struct fib * fibptr) static int aac_send_srb_fib(Scsi_Cmnd* scsicmd) { - struct fib* cmd_fibcontext; - struct aac_dev* dev; - int status; - struct aac_srb *srbcmd; - u16 fibsize; - u32 flag; - - if( scsicmd->target > 15 || scsicmd->lun > 7) { - scsicmd->result = DID_NO_CONNECT << 16; - __aac_io_done(scsicmd); - return 0; - } - - dev = (struct aac_dev *)scsicmd->host->hostdata; - switch(scsicmd->sc_data_direction){ - case SCSI_DATA_WRITE: - flag = SRB_DataOut; - break; - case SCSI_DATA_UNKNOWN: - flag = SRB_DataIn | SRB_DataOut; - break; - case SCSI_DATA_READ: - flag = SRB_DataIn; - break; - case SCSI_DATA_NONE: - default: - flag = SRB_NoDataXfer; - break; - } - - - /* - * Allocate and initialize a Fib then setup a BlockWrite command - */ - if (!(cmd_fibcontext = fib_alloc(dev))) { - scsicmd->result = DID_ERROR << 16; - __aac_io_done(scsicmd); - return -1; - } - fib_init(cmd_fibcontext); - - srbcmd = (struct aac_srb*) fib_data(cmd_fibcontext); - srbcmd->function = cpu_to_le32(SRBF_ExecuteScsi); - srbcmd->channel = cpu_to_le32(aac_logical_to_phys(scsicmd->channel)); - srbcmd->target = cpu_to_le32(scsicmd->target); - srbcmd->lun = cpu_to_le32(scsicmd->lun); - srbcmd->flags = cpu_to_le32(flag); - srbcmd->timeout = cpu_to_le32(0); // timeout not used - srbcmd->retry_limit =cpu_to_le32(0); // Obsolete parameter - srbcmd->cdb_size = cpu_to_le32(scsicmd->cmd_len); - - if( dev->pae_support ==1 ) { - aac_build_sg64(scsicmd, (struct sgmap64*) &srbcmd->sg); - srbcmd->count = cpu_to_le32(scsicmd->request_bufflen); + struct fib* cmd_fibcontext; + struct aac_dev* dev; + int status; + struct aac_srb *srbcmd; + u16 fibsize; + u32 flag; + u32 timeout; + + if( scsicmd->target > 15 || scsicmd->lun > 7) { + scsicmd->result = DID_NO_CONNECT << 16; + __aac_io_done(scsicmd); + return 0; + } + + dev = (struct aac_dev *)scsicmd->host->hostdata; + switch(scsicmd->sc_data_direction){ + case SCSI_DATA_WRITE: + flag = SRB_DataOut; + break; + case SCSI_DATA_UNKNOWN: + flag = SRB_DataIn | SRB_DataOut; + break; + case SCSI_DATA_READ: + flag = SRB_DataIn; + break; + case SCSI_DATA_NONE: + default: + flag = SRB_NoDataXfer; + break; + } - memset(srbcmd->cdb, 0, sizeof(srbcmd->cdb)); - memcpy(srbcmd->cdb, scsicmd->cmnd, scsicmd->cmd_len); - /* - * Build Scatter/Gather list - */ - fibsize = sizeof (struct aac_srb) + (((srbcmd->sg.count & 0xff) - 1) - * sizeof (struct sgentry64)); /* - * Now send the Fib to the adapter + * Allocate and initialize a Fib then setup a BlockWrite command */ - status = fib_send(ScsiPortCommand64, cmd_fibcontext, fibsize, - FsaNormal, 0, 1, (fib_callback) aac_srb_callback, - (void *) scsicmd); - } else { - aac_build_sg(scsicmd, (struct sgmap*)&srbcmd->sg); - srbcmd->count = cpu_to_le32(scsicmd->request_bufflen); + if (!(cmd_fibcontext = fib_alloc(dev))) { + scsicmd->result = DID_ERROR << 16; + __aac_io_done(scsicmd); + return -1; + } + fib_init(cmd_fibcontext); + + srbcmd = (struct aac_srb*) fib_data(cmd_fibcontext); + srbcmd->function = cpu_to_le32(SRBF_ExecuteScsi); + srbcmd->channel = cpu_to_le32(aac_logical_to_phys(scsicmd->channel)); + srbcmd->target = cpu_to_le32(scsicmd->target); + srbcmd->lun = cpu_to_le32(scsicmd->lun); + srbcmd->flags = cpu_to_le32(flag); + timeout = (scsicmd->timeout-jiffies)/HZ; + if(timeout == 0){ + timeout = 1; + } + srbcmd->timeout = cpu_to_le32(timeout); // timeout in seconds + srbcmd->retry_limit =cpu_to_le32(0); // Obsolete parameter + srbcmd->cdb_size = cpu_to_le32(scsicmd->cmd_len); + + if( dev->pae_support ==1 ) { + aac_build_sg64(scsicmd, (struct sgmap64*) &srbcmd->sg); + srbcmd->count = cpu_to_le32(scsicmd->request_bufflen); + + memset(srbcmd->cdb, 0, sizeof(srbcmd->cdb)); + memcpy(srbcmd->cdb, scsicmd->cmnd, scsicmd->cmd_len); + /* + * Build Scatter/Gather list + */ + fibsize = sizeof (struct aac_srb) + (((srbcmd->sg.count & 0xff) - 1) * sizeof (struct sgentry64)); + + /* + * Now send the Fib to the adapter + */ + status = fib_send(ScsiPortCommand64, cmd_fibcontext, fibsize, FsaNormal, 0, 1, + (fib_callback) aac_srb_callback, (void *) scsicmd); + } else { + aac_build_sg(scsicmd, (struct sgmap*)&srbcmd->sg); + srbcmd->count = cpu_to_le32(scsicmd->request_bufflen); + + memset(srbcmd->cdb, 0, sizeof(srbcmd->cdb)); + memcpy(srbcmd->cdb, scsicmd->cmnd, scsicmd->cmd_len); + /* + * Build Scatter/Gather list + */ + fibsize = sizeof (struct aac_srb) + (((srbcmd->sg.count & 0xff) - 1) * sizeof (struct sgentry)); - memset(srbcmd->cdb, 0, sizeof(srbcmd->cdb)); - memcpy(srbcmd->cdb, scsicmd->cmnd, scsicmd->cmd_len); + /* + * Now send the Fib to the adapter + */ + status = fib_send(ScsiPortCommand, cmd_fibcontext, fibsize, FsaNormal, 0, 1, + (fib_callback) aac_srb_callback, (void *) scsicmd); + } /* - * Build Scatter/Gather list + * Check that the command queued to the controller */ - fibsize = sizeof (struct aac_srb) + (((srbcmd->sg.count & 0xff) - 1) - * sizeof (struct sgentry)); + if (status == -EINPROGRESS){ + return 0; + } + printk(KERN_WARNING "aac_srb: fib_send failed with status: %d\n", status); /* - * Now send the Fib to the adapter + * For some reason, the Fib didn't queue, return QUEUE_FULL */ - status = fib_send(ScsiPortCommand, cmd_fibcontext, fibsize, - FsaNormal, 0, 1, (fib_callback) aac_srb_callback, - (void *) scsicmd); - } - /* - * Check that the command queued to the controller - */ - if (status == -EINPROGRESS){ - return 0; - } - - printk(KERN_WARNING "aac_srb: fib_send failed with status: %d\n", status); - /* - * For some reason, the Fib didn't queue, return QUEUE_FULL - */ - scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | QUEUE_FULL; - __aac_io_done(scsicmd); + scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | QUEUE_FULL; + __aac_io_done(scsicmd); - fib_complete(cmd_fibcontext); - fib_free(cmd_fibcontext); + fib_complete(cmd_fibcontext); + fib_free(cmd_fibcontext); - return -1; + return -1; } static unsigned long aac_build_sg(Scsi_Cmnd* scsicmd, struct sgmap* psg) { - struct aac_dev *dev; - unsigned long byte_count = 0; - - dev = (struct aac_dev *)scsicmd->host->hostdata; - // Get rid of old data - psg->count = cpu_to_le32(0); - psg->sg[0].addr = cpu_to_le32(NULL); - psg->sg[0].count = cpu_to_le32(0); - if (scsicmd->use_sg) { - struct scatterlist *sg; - int i; - int sg_count; - sg = (struct scatterlist *) scsicmd->request_buffer; + struct aac_dev *dev; + unsigned long byte_count = 0; - sg_count = pci_map_sg(dev->pdev, sg, scsicmd->use_sg, - scsi_to_pci_dma_dir(scsicmd->sc_data_direction)); - psg->count = cpu_to_le32(sg_count); + dev = (struct aac_dev *)scsicmd->host->hostdata; + // Get rid of old data + psg->count = cpu_to_le32(0); + psg->sg[0].addr = cpu_to_le32(NULL); + psg->sg[0].count = cpu_to_le32(0); + if (scsicmd->use_sg) { + struct scatterlist *sg; + int i; + int sg_count; + sg = (struct scatterlist *) scsicmd->request_buffer; + + sg_count = pci_map_sg(dev->pdev, sg, scsicmd->use_sg, + scsi_to_pci_dma_dir(scsicmd->sc_data_direction)); + psg->count = cpu_to_le32(sg_count); - byte_count = 0; + byte_count = 0; - for (i = 0; i < sg_count; i++) { - psg->sg[i].addr = cpu_to_le32(sg_dma_address(sg)); - psg->sg[i].count = cpu_to_le32(sg_dma_len(sg)); - byte_count += sg_dma_len(sg); - sg++; - } - /* hba wants the size to be exact */ - if(byte_count > scsicmd->request_bufflen){ - psg->sg[i-1].count -= (byte_count - scsicmd->request_bufflen); - byte_count = scsicmd->request_bufflen; + for (i = 0; i < sg_count; i++) { + psg->sg[i].addr = cpu_to_le32(sg_dma_address(sg)); + psg->sg[i].count = cpu_to_le32(sg_dma_len(sg)); + byte_count += sg_dma_len(sg); + sg++; + } + /* hba wants the size to be exact */ + if(byte_count > scsicmd->request_bufflen){ + psg->sg[i-1].count -= (byte_count - scsicmd->request_bufflen); + byte_count = scsicmd->request_bufflen; + } + /* Check for command underflow */ + if(scsicmd->underflow && (byte_count < scsicmd->underflow)){ + printk(KERN_WARNING"aacraid: cmd len %08lX cmd underflow %08X\n", + byte_count, scsicmd->underflow); + } } - /* Check for command underflow */ - if(scsicmd->underflow && (byte_count < scsicmd->underflow)){ - printk(KERN_WARNING"aacraid: cmd len %08lX cmd underflow %08X\n", - byte_count, scsicmd->underflow); + else if(scsicmd->request_bufflen) { + dma_addr_t addr; + addr = pci_map_single(dev->pdev, + scsicmd->request_buffer, + scsicmd->request_bufflen, + scsi_to_pci_dma_dir(scsicmd->sc_data_direction)); + psg->count = cpu_to_le32(1); + psg->sg[0].addr = cpu_to_le32(addr); + psg->sg[0].count = cpu_to_le32(scsicmd->request_bufflen); + /* Cast to pointer from integer of different size */ + scsicmd->SCp.ptr = (void *)addr; + byte_count = scsicmd->request_bufflen; } - } - else if(scsicmd->request_bufflen) { - dma_addr_t addr; - addr = pci_map_single(dev->pdev, - scsicmd->request_buffer, - scsicmd->request_bufflen, - scsi_to_pci_dma_dir(scsicmd->sc_data_direction)); - psg->count = cpu_to_le32(1); - psg->sg[0].addr = cpu_to_le32(addr); - psg->sg[0].count = cpu_to_le32(scsicmd->request_bufflen); - scsicmd->SCp.ptr = (void *)addr; - byte_count = scsicmd->request_bufflen; - } - return byte_count; + return byte_count; } static unsigned long aac_build_sg64(Scsi_Cmnd* scsicmd, struct sgmap64* psg) { - struct aac_dev *dev; - unsigned long byte_count = 0; - u64 le_addr; - - dev = (struct aac_dev *)scsicmd->host->hostdata; - // Get rid of old data - psg->count = cpu_to_le32(0); - psg->sg[0].addr[0] = cpu_to_le32(NULL); - psg->sg[0].addr[1] = cpu_to_le32(NULL); - psg->sg[0].count = cpu_to_le32(0); - if (scsicmd->use_sg) { - struct scatterlist *sg; - int i; - int sg_count; - sg = (struct scatterlist *) scsicmd->request_buffer; - - sg_count = pci_map_sg(dev->pdev, sg, scsicmd->use_sg, - scsi_to_pci_dma_dir(scsicmd->sc_data_direction)); - psg->count = cpu_to_le32(sg_count); - - byte_count = 0; - - for (i = 0; i < sg_count; i++) { - le_addr = cpu_to_le64(sg_dma_address(sg)); - psg->sg[i].addr[1] = (u32)(le_addr>>32); - psg->sg[i].addr[0] = (u32)(le_addr & 0xffffffff); - psg->sg[i].count = cpu_to_le32(sg_dma_len(sg)); - byte_count += sg_dma_len(sg); - sg++; - } - /* hba wants the size to be exact */ - if(byte_count > scsicmd->request_bufflen){ - psg->sg[i-1].count -= (byte_count - scsicmd->request_bufflen); - byte_count = scsicmd->request_bufflen; + struct aac_dev *dev; + unsigned long byte_count = 0; + u64 le_addr; + + dev = (struct aac_dev *)scsicmd->host->hostdata; + // Get rid of old data + psg->count = cpu_to_le32(0); + psg->sg[0].addr[0] = cpu_to_le32(NULL); + psg->sg[0].addr[1] = cpu_to_le32(NULL); + psg->sg[0].count = cpu_to_le32(0); + if (scsicmd->use_sg) { + struct scatterlist *sg; + int i; + int sg_count; + sg = (struct scatterlist *) scsicmd->request_buffer; + + sg_count = pci_map_sg(dev->pdev, sg, scsicmd->use_sg, + scsi_to_pci_dma_dir(scsicmd->sc_data_direction)); + psg->count = cpu_to_le32(sg_count); + + byte_count = 0; + + for (i = 0; i < sg_count; i++) { + le_addr = cpu_to_le64(sg_dma_address(sg)); + psg->sg[i].addr[1] = (u32)(le_addr>>32); + psg->sg[i].addr[0] = (u32)(le_addr & 0xffffffff); + psg->sg[i].count = cpu_to_le32(sg_dma_len(sg)); + byte_count += sg_dma_len(sg); + sg++; + } + /* hba wants the size to be exact */ + if(byte_count > scsicmd->request_bufflen){ + psg->sg[i-1].count -= (byte_count - scsicmd->request_bufflen); + byte_count = scsicmd->request_bufflen; + } + /* Check for command underflow */ + if(scsicmd->underflow && (byte_count < scsicmd->underflow)){ + printk(KERN_WARNING"aacraid: cmd len %08lX cmd underflow %08X\n", + byte_count, scsicmd->underflow); + } } - /* Check for command underflow */ - if(scsicmd->underflow && (byte_count < scsicmd->underflow)){ - printk(KERN_WARNING"aacraid: cmd len %08lX cmd underflow %08X\n", - byte_count, scsicmd->underflow); + else if(scsicmd->request_bufflen) { + dma_addr_t addr; + addr = pci_map_single(dev->pdev, + scsicmd->request_buffer, + scsicmd->request_bufflen, + scsi_to_pci_dma_dir(scsicmd->sc_data_direction)); + psg->count = cpu_to_le32(1); + le_addr = cpu_to_le64(addr); + psg->sg[0].addr[1] = (u32)(le_addr>>32); + psg->sg[0].addr[0] = (u32)(le_addr & 0xffffffff); + psg->sg[0].count = cpu_to_le32(scsicmd->request_bufflen); + /* Cast to pointer from integer of different size */ + scsicmd->SCp.ptr = (void *)addr; + byte_count = scsicmd->request_bufflen; } - } - else if(scsicmd->request_bufflen) { - dma_addr_t addr; - addr = pci_map_single(dev->pdev, - scsicmd->request_buffer, - scsicmd->request_bufflen, - scsi_to_pci_dma_dir(scsicmd->sc_data_direction)); - psg->count = cpu_to_le32(1); - le_addr = cpu_to_le64(addr); - psg->sg[0].addr[1] = (u32)(le_addr>>32); - psg->sg[0].addr[0] = (u32)(le_addr & 0xffffffff); - psg->sg[0].count = cpu_to_le32(scsicmd->request_bufflen); - scsicmd->SCp.ptr = (void *)addr; - byte_count = scsicmd->request_bufflen; - } - return byte_count; + return byte_count; } #ifdef AAC_DETAILED_STATUS_INFO diff --git a/xen/drivers/scsi/aacraid/aacraid.h b/xen/drivers/scsi/aacraid/aacraid.h index ce6566bcc1..eb38cd1361 100644 --- a/xen/drivers/scsi/aacraid/aacraid.h +++ b/xen/drivers/scsi/aacraid/aacraid.h @@ -1,16 +1,13 @@ +//#define dprintk(x) printk x +#if (!defined(dprintk)) +# define dprintk(x) +#endif -/* #define dprintk(x) */ -// #define dprintk(x) printk x -#define dprintk(x) - - +/* Start of Xen additions XXX */ #include <asm/byteorder.h> - +#include <xeno/interrupt.h> #define TRY_TASKLET -#ifdef TRY_TASKLET -/* XXX SMH: trying to use softirqs to trigger stuff done prev by threads */ -#include <xeno/interrupt.h> /* for tasklet/softirq stuff */ -#endif +/* End of Xen additions XXX */ /*------------------------------------------------------------------------------ * D E F I N E S @@ -19,12 +16,13 @@ #define MAXIMUM_NUM_CONTAINERS 31 #define MAXIMUM_NUM_ADAPTERS 8 -#define AAC_NUM_FIB 578 -#define AAC_NUM_IO_FIB 512 +#define AAC_NUM_FIB 578 +//#define AAC_NUM_IO_FIB 512 +#define AAC_NUM_IO_FIB 100 -#define AAC_MAX_TARGET (MAXIMUM_NUM_CONTAINERS+1) +#define AAC_MAX_TARGET (MAXIMUM_NUM_CONTAINERS+1) //#define AAC_MAX_TARGET (16) -#define AAC_MAX_LUN (8) +#define AAC_MAX_LUN (8) /* * These macros convert from physical channels to virtual channels @@ -266,27 +264,25 @@ enum aac_queue_types { */ struct aac_fibhdr { - u32 XferState; // Current transfer state for this CCB - u16 Command; // Routing information for the destination - u8 StructType; // Type FIB - u8 Flags; // Flags for FIB - u16 Size; // Size of this FIB in bytes - u16 SenderSize; // Size of the FIB in the sender (for - // response sizing) - u32 SenderFibAddress; // Host defined data in the FIB - u32 ReceiverFibAddress; // Logical address of this FIB for the adapter - u32 SenderData; // Place holder for the sender to store data - union { - struct { - u32 _ReceiverTimeStart; // Timestamp for receipt of fib - u32 _ReceiverTimeDone; // Timestamp for completion of fib - } _s; - struct list_head _FibLinks; // Used to link Adapter Initiated - // Fibs on the host - } _u; + u32 XferState; // Current transfer state for this CCB + u16 Command; // Routing information for the destination + u8 StructType; // Type FIB + u8 Flags; // Flags for FIB + u16 Size; // Size of this FIB in bytes + u16 SenderSize; // Size of the FIB in the sender (for response sizing) + u32 SenderFibAddress; // Host defined data in the FIB + u32 ReceiverFibAddress; // Logical address of this FIB for the adapter + u32 SenderData; // Place holder for the sender to store data + union { + struct { + u32 _ReceiverTimeStart; // Timestamp for receipt of fib + u32 _ReceiverTimeDone; // Timestamp for completion of fib + } _s; +// struct aac_list_head _FibLinks; // Used to link Adapter Initiated Fibs on the host + } _u; }; -#define FibLinks _u._FibLinks +//#define FibLinks _u._FibLinks #define FIB_DATA_SIZE_IN_BYTES (512 - sizeof(struct aac_fibhdr)) @@ -451,6 +447,8 @@ struct aac_driver_ident char * vname; char * model; u16 channels; + int quirks; +#define AAC_QUIRK_31BIT 1 }; /* @@ -471,8 +469,7 @@ struct aac_queue { #if 0 wait_queue_head_t qfull; /* Event to wait on if the queue is full */ wait_queue_head_t cmdready; /* Indicates there is a Command ready from the adapter on this queue. */ -#endif - /* This is only valid for adapter to host command queues. */ +#endif /* This is only valid for adapter to host command queues. */ spinlock_t *lock; /* Spinlock for this queue must take this lock before accessing the lock */ spinlock_t lockdata; /* Actual lock (used only on one side of the lock) */ unsigned long SavedIrql; /* Previous IRQL when the spin lock is taken */ @@ -646,7 +643,7 @@ struct aac_fib_context { #endif int wait; // Set to true when thread is in WaitForSingleObject unsigned long count; // total number of FIBs on FibList - struct list_head fibs; + struct list_head fib_list; // this holds fibs which should be 32 bit addresses }; struct fsa_scsi_hba { @@ -656,7 +653,7 @@ struct fsa_scsi_hba { u8 ro[MAXIMUM_NUM_CONTAINERS]; u8 locked[MAXIMUM_NUM_CONTAINERS]; u8 deleted[MAXIMUM_NUM_CONTAINERS]; - u32 devno[MAXIMUM_NUM_CONTAINERS]; + s32 devno[MAXIMUM_NUM_CONTAINERS]; }; struct fib { @@ -667,7 +664,6 @@ struct fib { * The Adapter that this I/O is destined for. */ struct aac_dev *dev; - u64 logicaladdr; /* 64 bit */ #if 0 /* * This is the event the sendfib routine will wait on if the @@ -686,9 +682,14 @@ struct fib { * Outstanding I/O queue. */ struct list_head queue; - + /* + * And for the internal issue/reply queues (we may be able + * to merge these two) + */ + struct list_head fiblink; void *data; - struct hw_fib *fib; /* Actual shared object */ + struct hw_fib *hw_fib; /* Actual shared object */ + dma_addr_t hw_fib_pa; /* physical address of hw_fib*/ }; /* @@ -715,6 +716,7 @@ struct aac_adapter_info u32 biosrev; u32 biosbuild; u32 cluster; + u32 clusterchannelmask; u32 serial[2]; u32 battery; u32 options; @@ -739,19 +741,22 @@ struct aac_adapter_info /* * Supported Options */ -#define AAC_OPT_SNAPSHOT cpu_to_le32(1) -#define AAC_OPT_CLUSTERS cpu_to_le32(1<<1) -#define AAC_OPT_WRITE_CACHE cpu_to_le32(1<<2) -#define AAC_OPT_64BIT_DATA cpu_to_le32(1<<3) -#define AAC_OPT_HOST_TIME_FIB cpu_to_le32(1<<4) -#define AAC_OPT_RAID50 cpu_to_le32(1<<5) -#define AAC_OPT_4GB_WINDOW cpu_to_le32(1<<6) -#define AAC_OPT_SCSI_UPGRADEABLE cpu_to_le32(1<<7) -#define AAC_OPT_SOFT_ERR_REPORT cpu_to_le32(1<<8) -#define AAC_OPT_SUPPORTED_RECONDITION cpu_to_le32(1<<9) -#define AAC_OPT_SGMAP_HOST64 cpu_to_le32(1<<10) -#define AAC_OPT_ALARM cpu_to_le32(1<<11) -#define AAC_OPT_NONDASD cpu_to_le32(1<<12) +#define AAC_OPT_SNAPSHOT cpu_to_le32(1) +#define AAC_OPT_CLUSTERS cpu_to_le32(1<<1) +#define AAC_OPT_WRITE_CACHE cpu_to_le32(1<<2) +#define AAC_OPT_64BIT_DATA cpu_to_le32(1<<3) +#define AAC_OPT_HOST_TIME_FIB cpu_to_le32(1<<4) +#define AAC_OPT_RAID50 cpu_to_le32(1<<5) +#define AAC_OPT_4GB_WINDOW cpu_to_le32(1<<6) +#define AAC_OPT_SCSI_UPGRADEABLE cpu_to_le32(1<<7) +#define AAC_OPT_SOFT_ERR_REPORT cpu_to_le32(1<<8) +#define AAC_OPT_SUPPORTED_RECONDITION cpu_to_le32(1<<9) +#define AAC_OPT_SGMAP_HOST64 cpu_to_le32(1<<10) +#define AAC_OPT_ALARM cpu_to_le32(1<<11) +#define AAC_OPT_NONDASD cpu_to_le32(1<<12) +#define AAC_OPT_SCSI_MANAGED cpu_to_le32(1<<13) +#define AAC_OPT_RAID_SCSI_MODE cpu_to_le32(1<<14) +#define AAC_OPT_SUPPLEMENT_ADAPTER_INFO cpu_to_le32(1<<15) struct aac_dev { @@ -765,13 +770,12 @@ struct aac_dev */ dma_addr_t hw_fib_pa; struct hw_fib *hw_fib_va; -#if BITS_PER_LONG >= 64 ulong fib_base_va; -#endif /* * Fib Headers */ - struct fib fibs[AAC_NUM_FIB]; + struct fib *fibs; + struct fib *free_fib; struct fib *timeout_fib; spinlock_t fib_lock; @@ -800,7 +804,9 @@ struct aac_dev struct Scsi_Host *scsi_host_ptr; struct fsa_scsi_hba fsa_dev; - int thread_pid; +#if 0 + pid_t thread_pid; +#endif int cardtype; /* @@ -825,8 +831,15 @@ struct aac_dev */ u8 nondasd_support; u8 pae_support; + u8 raid_scsi_mode; }; +#define AllocateAndMapFibSpace(dev, MapFibContext) \ + dev->a_ops.AllocateAndMapFibSpace(dev, MapFibContext) + +#define UnmapAndFreeFibSpace(dev, MapFibContext) \ + dev->a_ops.UnmapAndFreeFibSpace(dev, MapFibContext) + #define aac_adapter_interrupt(dev) \ dev->a_ops.adapter_interrupt(dev) @@ -1163,7 +1176,9 @@ struct aac_mntent { u32 altoid; // != oid <==> snapshot or broken mirror exists }; -#define FSCS_READONLY 0x0002 /* possible result of broken mirror */ +#define FSCS_NOTCLEAN 0x0001 /* fsck is neccessary before mounting */ +#define FSCS_READONLY 0x0002 /* possible result of broken mirror */ +#define FSCS_HIDDEN 0x0004 /* should be ignored - set during a clear */ struct aac_query_mount { u32 command; @@ -1347,9 +1362,12 @@ extern struct aac_common aac_config; */ #define AifCmdEventNotify 1 /* Notify of event */ +#define AifEnContainerChange 4 /* Container configuration change */ #define AifCmdJobProgress 2 /* Progress report */ #define AifCmdAPIReport 3 /* Report from other user of API */ #define AifCmdDriverNotify 4 /* Notify host driver of event */ +#define AifDenMorphComplete 200 /* A morph operation completed */ +#define AifDenVolumeExtendComplete 201 /* A volume expand operation completed */ #define AifReqJobList 100 /* Gets back complete job list */ #define AifReqJobsForCtr 101 /* Gets back jobs for specific container */ #define AifReqJobsForScsi 102 /* Gets back jobs for specific SCSI device */ @@ -1374,16 +1392,6 @@ struct aac_aifcmd { u8 data[1]; /* Undefined length (from kernel viewpoint) */ }; -static inline u32 fib2addr(struct hw_fib *hw) -{ - return (u32)hw; -} - -static inline struct hw_fib *addr2fib(u32 addr) -{ - return (struct hw_fib *)addr; -} - const char *aac_driverinfo(struct Scsi_Host *); struct fib *fib_alloc(struct aac_dev *dev); int fib_setup(struct aac_dev *dev); @@ -1397,7 +1405,7 @@ int aac_consumer_get(struct aac_dev * dev, struct aac_queue * q, struct aac_entr int aac_consumer_avail(struct aac_dev * dev, struct aac_queue * q); void aac_consumer_free(struct aac_dev * dev, struct aac_queue * q, u32 qnum); int fib_complete(struct fib * context); -#define fib_data(fibctx) ((void *)(fibctx)->fib->data) +#define fib_data(fibctx) ((void *)(fibctx)->hw_fib->data) int aac_detach(struct aac_dev *dev); struct aac_dev *aac_init_adapter(struct aac_dev *dev); int aac_get_containers(struct aac_dev *dev); diff --git a/xen/drivers/scsi/aacraid/commctrl.c b/xen/drivers/scsi/aacraid/commctrl.c index 15b6a62c6f..2169d34f43 100644 --- a/xen/drivers/scsi/aacraid/commctrl.c +++ b/xen/drivers/scsi/aacraid/commctrl.c @@ -28,17 +28,17 @@ * */ -#include <xeno/config.h> -/* #include <xeno/kernel.h> */ -#include <xeno/init.h> -#include <xeno/types.h> -#include <xeno/sched.h> -#include <xeno/pci.h> -/* #include <xeno/spinlock.h> */ -/* #include <xeno/slab.h> */ -/* #include <xeno/completion.h> */ -#include <xeno/blk.h> -/* #include <asm/semaphore.h> */ +#include <linux/config.h> +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/types.h> +#include <linux/sched.h> +#include <linux/pci.h> +#include <linux/spinlock.h> +#include <linux/slab.h> +/*#include <linux/completion.h>*/ +#include <linux/blk.h> +/*#include <asm/semaphore.h>*/ #include <asm/uaccess.h> #include "scsi.h" #include "hosts.h" @@ -63,7 +63,7 @@ static int ioctl_send_fib(struct aac_dev * dev, void *arg) if(fibptr == NULL) return -ENOMEM; - kfib = fibptr->fib; + kfib = fibptr->hw_fib; /* * First copy in the header so that we can check the size field. */ @@ -152,7 +152,7 @@ static int open_getadapter_fib(struct aac_dev * dev, void *arg) * the list to 0. */ fibctx->count = 0; - INIT_LIST_HEAD(&fibctx->fibs); + INIT_LIST_HEAD(&fibctx->fib_list); fibctx->jiffies = jiffies/HZ; /* * Now add this context onto the adapter's @@ -183,7 +183,7 @@ static int next_getadapter_fib(struct aac_dev * dev, void *arg) { struct fib_ioctl f; struct aac_fib_context *fibctx, *aifcp; - struct hw_fib * fib; + struct fib * fib; int status; struct list_head * entry; int found; @@ -213,12 +213,16 @@ static int next_getadapter_fib(struct aac_dev * dev, void *arg) } entry = entry->next; } - if (found == 0) + if (found == 0) { + dprintk ((KERN_INFO "Fib not found\n")); return -EINVAL; + } if((fibctx->type != FSAFS_NTC_GET_ADAPTER_FIB_CONTEXT) || - (fibctx->size != sizeof(struct aac_fib_context))) + (fibctx->size != sizeof(struct aac_fib_context))) { + dprintk ((KERN_INFO "Fib Context corrupt?\n")); return -EINVAL; + } status = 0; spin_lock_irqsave(&dev->fib_lock, flags); /* @@ -226,27 +230,28 @@ static int next_getadapter_fib(struct aac_dev * dev, void *arg) * -EAGAIN */ return_fib: - if (!list_empty(&fibctx->fibs)) { + if (!list_empty(&fibctx->fib_list)) { struct list_head * entry; /* * Pull the next fib from the fibs */ - entry = fibctx->fibs.next; + entry = fibctx->fib_list.next; list_del(entry); - fib = list_entry(entry, struct hw_fib, header.FibLinks); + fib = list_entry(entry, struct fib, fiblink); fibctx->count--; spin_unlock_irqrestore(&dev->fib_lock, flags); - if (copy_to_user(f.fib, fib, sizeof(struct hw_fib))) { + if (copy_to_user(f.fib, fib->hw_fib, sizeof(struct hw_fib))) { + kfree(fib->hw_fib); kfree(fib); return -EFAULT; } /* * Free the space occupied by this copy of the fib. */ + kfree(fib->hw_fib); kfree(fib); status = 0; - fibctx->jiffies = jiffies/HZ; } else { spin_unlock_irqrestore(&dev->fib_lock, flags); if (f.wait) { @@ -255,7 +260,7 @@ return_fib: status = -EINTR; } else { #else - { + { #endif /* Lock again and retry */ spin_lock_irqsave(&dev->fib_lock, flags); @@ -265,28 +270,30 @@ return_fib: status = -EAGAIN; } } + fibctx->jiffies = jiffies/HZ; return status; } int aac_close_fib_context(struct aac_dev * dev, struct aac_fib_context * fibctx) { - struct hw_fib *fib; + struct fib *fib; /* * First free any FIBs that have not been consumed. */ - while (!list_empty(&fibctx->fibs)) { + while (!list_empty(&fibctx->fib_list)) { struct list_head * entry; /* * Pull the next fib from the fibs */ - entry = fibctx->fibs.next; + entry = fibctx->fib_list.next; list_del(entry); - fib = list_entry(entry, struct hw_fib, header.FibLinks); + fib = list_entry(entry, struct fib, fiblink); fibctx->count--; /* * Free the space occupied by this copy of the fib. */ + kfree(fib->hw_fib); kfree(fib); } /* diff --git a/xen/drivers/scsi/aacraid/comminit.c b/xen/drivers/scsi/aacraid/comminit.c index b4681a473b..531361e55d 100644 --- a/xen/drivers/scsi/aacraid/comminit.c +++ b/xen/drivers/scsi/aacraid/comminit.c @@ -29,17 +29,18 @@ * */ -#include <xeno/config.h> -/* #include <xeno/kernel.h> */ -#include <xeno/init.h> -#include <xeno/types.h> -#include <xeno/sched.h> -#include <xeno/pci.h> -#include <xeno/spinlock.h> -/* #include <xeno/slab.h> */ -#include <xeno/blk.h> -/* #include <xeno/completion.h> */ -/* #include <asm/semaphore.h> */ +#include <linux/config.h> +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/types.h> +#include <linux/sched.h> +#include <linux/pci.h> +#include <linux/spinlock.h> +#include <linux/slab.h> +#include <linux/blk.h> +/*#include <linux/completion.h>*/ +#include <linux/mm.h> +/*#include <asm/semaphore.h>*/ #include "scsi.h" #include "hosts.h" @@ -58,7 +59,6 @@ static int aac_alloc_comm(struct aac_dev *dev, void **commaddr, unsigned long co struct aac_init *init; dma_addr_t phys; - /* FIXME: Adaptec add 128 bytes to this value - WHY ?? */ size = fibsize + sizeof(struct aac_init) + commsize + commalign + printfbufsiz; base = pci_alloc_consistent(dev->pdev, size, &phys); @@ -74,14 +74,6 @@ static int aac_alloc_comm(struct aac_dev *dev, void **commaddr, unsigned long co dev->init = (struct aac_init *)(base + fibsize); dev->init_pa = phys + fibsize; - /* - * Cache the upper bits of the virtual mapping for 64bit boxes - * FIXME: this crap should be rewritten - */ -#if BITS_PER_LONG >= 64 - dev->fib_base_va = ((ulong)base & 0xffffffff00000000); -#endif - init = dev->init; init->InitStructRevision = cpu_to_le32(ADAPTER_INIT_STRUCT_REVISION); @@ -92,16 +84,20 @@ static int aac_alloc_comm(struct aac_dev *dev, void **commaddr, unsigned long co * Adapter Fibs are the first thing allocated so that they * start page aligned */ - init->AdapterFibsVirtualAddress = cpu_to_le32((u32)base); - init->AdapterFibsPhysicalAddress = cpu_to_le32(phys); + dev->fib_base_va = (ulong)base; + + /* We submit the physical address for AIF tags to limit to 32 bits */ + init->AdapterFibsVirtualAddress = cpu_to_le32((u32)phys); + init->AdapterFibsPhysicalAddress = cpu_to_le32((u32)phys); init->AdapterFibsSize = cpu_to_le32(fibsize); init->AdapterFibAlign = cpu_to_le32(sizeof(struct hw_fib)); + init->HostPhysMemPages = cpu_to_le32(4096); // number of 4k pages of host physical memory /* * Increment the base address by the amount already used */ base = base + fibsize + sizeof(struct aac_init); - phys = phys + fibsize + sizeof(struct aac_init); + phys = (dma_addr_t)((ulong)phys + fibsize + sizeof(struct aac_init)); /* * Align the beginning of Headers to commalign */ @@ -111,8 +107,8 @@ static int aac_alloc_comm(struct aac_dev *dev, void **commaddr, unsigned long co /* * Fill in addresses of the Comm Area Headers and Queues */ - *commaddr = (unsigned long *)base; - init->CommHeaderAddress = cpu_to_le32(phys); + *commaddr = base; + init->CommHeaderAddress = cpu_to_le32((u32)phys); /* * Increment the base address by the size of the CommArea */ @@ -144,8 +140,8 @@ static void aac_queue_init(struct aac_dev * dev, struct aac_queue * q, u32 *mem, q->lock = &q->lockdata; q->headers.producer = mem; q->headers.consumer = mem+1; - *q->headers.producer = cpu_to_le32(qsize); - *q->headers.consumer = cpu_to_le32(qsize); + *(q->headers.producer) = cpu_to_le32(qsize); + *(q->headers.consumer) = cpu_to_le32(qsize); q->entries = qsize; } @@ -250,9 +246,9 @@ int aac_comm_init(struct aac_dev * dev) if (!aac_alloc_comm(dev, (void * *)&headers, size, QUEUE_ALIGNMENT)) return -ENOMEM; - queues = (struct aac_entry *)((unsigned char *)headers + hdrsize); + queues = (struct aac_entry *)(((ulong)headers) + hdrsize); - /* Adapter to Host normal proirity Command queue */ + /* Adapter to Host normal priority Command queue */ comm->queue[HostNormCmdQueue].base = queues; aac_queue_init(dev, &comm->queue[HostNormCmdQueue], headers, HOST_NORM_CMD_ENTRIES); queues += HOST_NORM_CMD_ENTRIES; @@ -317,23 +313,25 @@ struct aac_dev *aac_init_adapter(struct aac_dev *dev) /* * Ok now init the communication subsystem */ - dev->queues = (struct aac_queue_block *) - kmalloc(sizeof(struct aac_queue_block), GFP_KERNEL); + dev->queues = (struct aac_queue_block *) kmalloc(sizeof(struct aac_queue_block), GFP_KERNEL); if (dev->queues == NULL) { printk(KERN_ERR "Error could not allocate comm region.\n"); return NULL; } memset(dev->queues, 0, sizeof(struct aac_queue_block)); - if (aac_comm_init(dev)<0) + if (aac_comm_init(dev)<0){ + kfree(dev->queues); return NULL; - + } /* * Initialize the list of fibs */ - if(fib_setup(dev)<0) - return NULL; - + if(fib_setup(dev)<0){ + kfree(dev->queues); + return NULL; + } + INIT_LIST_HEAD(&dev->fib_list); #if 0 init_completion(&dev->aif_completion); diff --git a/xen/drivers/scsi/aacraid/commsup.c b/xen/drivers/scsi/aacraid/commsup.c index a1fabe7b19..84c77464f5 100644 --- a/xen/drivers/scsi/aacraid/commsup.c +++ b/xen/drivers/scsi/aacraid/commsup.c @@ -31,21 +31,22 @@ * */ -#include <xeno/config.h> -/* #include <xeno/kernel.h> */ -#include <xeno/init.h> -#include <xeno/types.h> -#include <xeno/sched.h> -#include <xeno/pci.h> -#include <xeno/spinlock.h> - -#include <xeno/interrupt.h> /* tasklet stuff */ - -/* #include <xeno/slab.h> */ -/* #include <xeno/completion.h> */ -/* #include <asm/semaphore.h> */ -#include <xeno/blk.h> +#include <linux/config.h> +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/types.h> +#include <linux/sched.h> +#include <linux/pci.h> +#include <linux/spinlock.h> +#include <linux/slab.h> +/*#include <linux/completion.h>*/ +/*#include <asm/semaphore.h>*/ +#include <linux/blk.h> +#include <asm/uaccess.h> + +#include <xeno/interrupt.h> #include <xeno/delay.h> + #include "scsi.h" #include "hosts.h" @@ -61,11 +62,9 @@ static int fib_map_alloc(struct aac_dev *dev) { - if((dev->hw_fib_va = - pci_alloc_consistent(dev->pdev, sizeof(struct hw_fib) * AAC_NUM_FIB, - &dev->hw_fib_pa))==NULL) - return -ENOMEM; - return 0; + if((dev->hw_fib_va = pci_alloc_consistent(dev->pdev, sizeof(struct hw_fib) * AAC_NUM_FIB, &dev->hw_fib_pa))==NULL) + return -ENOMEM; + return 0; } /** @@ -78,8 +77,7 @@ static int fib_map_alloc(struct aac_dev *dev) void fib_map_free(struct aac_dev *dev) { - pci_free_consistent(dev->pdev, sizeof(struct hw_fib) * AAC_NUM_FIB, - dev->hw_fib_va, dev->hw_fib_pa); + pci_free_consistent(dev->pdev, sizeof(struct hw_fib) * AAC_NUM_FIB, dev->hw_fib_va, dev->hw_fib_pa); } /** @@ -92,45 +90,45 @@ void fib_map_free(struct aac_dev *dev) int fib_setup(struct aac_dev * dev) { - struct fib *fibptr; - struct hw_fib *fib; - dma_addr_t fibpa; - int i; - - if(fib_map_alloc(dev)<0) - return -ENOMEM; - - fib = dev->hw_fib_va; - fibpa = dev->hw_fib_pa; - memset(fib, 0, sizeof(struct hw_fib) * AAC_NUM_FIB); - /* - * Initialise the fibs - */ - for (i = 0, fibptr = &dev->fibs[i]; i < AAC_NUM_FIB; i++, fibptr++) - { - fibptr->dev = dev; - fibptr->fib = fib; - fibptr->data = (void *) fibptr->fib->data; - fibptr->next = fibptr+1; /* Forward chain the fibs */ + struct fib *fibptr; + struct hw_fib *hw_fib_va; + dma_addr_t hw_fib_pa; + int i; + + if(fib_map_alloc(dev)<0) + return -ENOMEM; + + hw_fib_va = dev->hw_fib_va; + hw_fib_pa = dev->hw_fib_pa; + memset(hw_fib_va, 0, sizeof(struct hw_fib) * AAC_NUM_FIB); + /* + * Initialise the fibs + */ + for (i = 0, fibptr = &dev->fibs[i]; i < AAC_NUM_FIB; i++, fibptr++) + { + fibptr->dev = dev; + fibptr->hw_fib = hw_fib_va; + fibptr->data = (void *) fibptr->hw_fib->data; + fibptr->next = fibptr+1; /* Forward chain the fibs */ #if 0 - init_MUTEX_LOCKED(&fibptr->event_wait); + init_MUTEX_LOCKED(&fibptr->event_wait); #endif - spin_lock_init(&fibptr->event_lock); - fib->header.XferState = cpu_to_le32(0xffffffff); - fib->header.SenderSize = cpu_to_le16(sizeof(struct hw_fib)); - fibptr->logicaladdr = (unsigned long) fibpa; - fib = (struct hw_fib *)((unsigned char *)fib + sizeof(struct hw_fib)); - fibpa = fibpa + sizeof(struct hw_fib); - } - /* - * Add the fib chain to the free list - */ - dev->fibs[AAC_NUM_FIB-1].next = NULL; - /* - * Enable this to debug out of queue space - */ - dev->free_fib = &dev->fibs[0]; - return 0; + spin_lock_init(&fibptr->event_lock); + hw_fib_va->header.XferState = cpu_to_le32(0xffffffff); + hw_fib_va->header.SenderSize = cpu_to_le16(sizeof(struct hw_fib)); + fibptr->hw_fib_pa = hw_fib_pa; + hw_fib_va = (struct hw_fib *)((unsigned char *)hw_fib_va + sizeof(struct hw_fib)); + hw_fib_pa = hw_fib_pa + sizeof(struct hw_fib); + } + /* + * Add the fib chain to the free list + */ + dev->fibs[AAC_NUM_FIB-1].next = NULL; + /* + * Enable this to debug out of queue space + */ + dev->free_fib = &dev->fibs[0]; + return 0; } /** @@ -143,29 +141,29 @@ int fib_setup(struct aac_dev * dev) struct fib * fib_alloc(struct aac_dev *dev) { - struct fib * fibptr; - unsigned long flags; - - spin_lock_irqsave(&dev->fib_lock, flags); - fibptr = dev->free_fib; - if(!fibptr) - BUG(); - dev->free_fib = fibptr->next; - spin_unlock_irqrestore(&dev->fib_lock, flags); - /* - * Set the proper node type code and node byte size - */ - fibptr->type = FSAFS_NTC_FIB_CONTEXT; - fibptr->size = sizeof(struct fib); - /* - * Null out fields that depend on being zero at the start of - * each I/O - */ - fibptr->fib->header.XferState = cpu_to_le32(0); - fibptr->callback = NULL; - fibptr->callback_data = NULL; - - return fibptr; + struct fib * fibptr; + unsigned long flags; + + spin_lock_irqsave(&dev->fib_lock, flags); + fibptr = dev->free_fib; + if(!fibptr) + BUG(); + dev->free_fib = fibptr->next; + spin_unlock_irqrestore(&dev->fib_lock, flags); + /* + * Set the proper node type code and node byte size + */ + fibptr->type = FSAFS_NTC_FIB_CONTEXT; + fibptr->size = sizeof(struct fib); + /* + * Null out fields that depend on being zero at the start of + * each I/O + */ + fibptr->hw_fib->header.XferState = cpu_to_le32(0); + fibptr->callback = NULL; + fibptr->callback_data = NULL; + + return fibptr; } /** @@ -178,24 +176,23 @@ struct fib * fib_alloc(struct aac_dev *dev) void fib_free(struct fib * fibptr) { - unsigned long flags; - - spin_lock_irqsave(&fibptr->dev->fib_lock, flags); - - if (fibptr->flags & FIB_CONTEXT_FLAG_TIMED_OUT) { - aac_config.fib_timeouts++; - fibptr->next = fibptr->dev->timeout_fib; - fibptr->dev->timeout_fib = fibptr; - } else { - if (fibptr->fib->header.XferState != 0) { - printk(KERN_WARNING "fib_free, XferState != 0, " - "fibptr = 0x%p, XferState = 0x%x\n", - (void *)fibptr, fibptr->fib->header.XferState); - } - fibptr->next = fibptr->dev->free_fib; - fibptr->dev->free_fib = fibptr; - } - spin_unlock_irqrestore(&fibptr->dev->fib_lock, flags); + unsigned long flags; + + spin_lock_irqsave(&fibptr->dev->fib_lock, flags); + + if (fibptr->flags & FIB_CONTEXT_FLAG_TIMED_OUT) { + aac_config.fib_timeouts++; + fibptr->next = fibptr->dev->timeout_fib; + fibptr->dev->timeout_fib = fibptr; + } else { + if (fibptr->hw_fib->header.XferState != 0) { + printk(KERN_WARNING "fib_free, XferState != 0, fibptr = 0x%p, XferState = 0x%x\n", + (void*)fibptr, fibptr->hw_fib->header.XferState); + } + fibptr->next = fibptr->dev->free_fib; + fibptr->dev->free_fib = fibptr; + } + spin_unlock_irqrestore(&fibptr->dev->fib_lock, flags); } /** @@ -207,15 +204,14 @@ void fib_free(struct fib * fibptr) void fib_init(struct fib *fibptr) { - struct hw_fib *fib = fibptr->fib; - - fib->header.StructType = FIB_MAGIC; - fib->header.Size = cpu_to_le16(sizeof(struct hw_fib)); - fib->header.XferState = cpu_to_le32(HostOwned | FibInitialized | - FibEmpty | FastResponseCapable); - fib->header.SenderFibAddress = cpu_to_le32(0); - fib->header.ReceiverFibAddress = cpu_to_le32(0); - fib->header.SenderSize = cpu_to_le16(sizeof(struct hw_fib)); + struct hw_fib *hw_fib = fibptr->hw_fib; + + hw_fib->header.StructType = FIB_MAGIC; + hw_fib->header.Size = cpu_to_le16(sizeof(struct hw_fib)); + hw_fib->header.XferState = cpu_to_le32(HostOwned | FibInitialized | FibEmpty | FastResponseCapable); + hw_fib->header.SenderFibAddress = cpu_to_le32(fibptr->hw_fib_pa); + hw_fib->header.ReceiverFibAddress = cpu_to_le32(fibptr->hw_fib_pa); + hw_fib->header.SenderSize = cpu_to_le16(sizeof(struct hw_fib)); } /** @@ -228,10 +224,10 @@ void fib_init(struct fib *fibptr) void fib_dealloc(struct fib * fibptr) { - struct hw_fib *fib = fibptr->fib; - if(fib->header.StructType != FIB_MAGIC) - BUG(); - fib->header.XferState = cpu_to_le32(0); + struct hw_fib *hw_fib = fibptr->hw_fib; + if(hw_fib->header.StructType != FIB_MAGIC) + BUG(); + hw_fib->header.XferState = cpu_to_le32(0); } /* @@ -256,48 +252,47 @@ void fib_dealloc(struct fib * fibptr) static int aac_get_entry (struct aac_dev * dev, u32 qid, struct aac_entry **entry, u32 * index, unsigned long *nonotify) { - struct aac_queue * q; + struct aac_queue * q; - /* - * All of the queues wrap when they reach the end, so we check - * to see if they have reached the end and if they have we just - * set the index back to zero. This is a wrap. You could or off - * the high bits in all updates but this is a bit faster I think. - */ + /* + * All of the queues wrap when they reach the end, so we check + * to see if they have reached the end and if they have we just + * set the index back to zero. This is a wrap. You could or off + * the high bits in all updates but this is a bit faster I think. + */ - q = &dev->queues->queue[qid]; + q = &dev->queues->queue[qid]; - *index = le32_to_cpu(*(q->headers.producer)); - if (*index - 2 == le32_to_cpu(*(q->headers.consumer))) - *nonotify = 1; - - if (qid == AdapHighCmdQueue) { - if (*index >= ADAP_HIGH_CMD_ENTRIES) - *index = 0; - } else if (qid == AdapNormCmdQueue) { - if (*index >= ADAP_NORM_CMD_ENTRIES) - *index = 0; /* Wrap to front of the Producer Queue. */ - } - else if (qid == AdapHighRespQueue) - { - if (*index >= ADAP_HIGH_RESP_ENTRIES) - *index = 0; - } - else if (qid == AdapNormRespQueue) - { - if (*index >= ADAP_NORM_RESP_ENTRIES) - *index = 0; /* Wrap to front of the Producer Queue. */ - } - else BUG(); - - if (*index + 1 == le32_to_cpu(*(q->headers.consumer))) { /* Queue full */ - printk(KERN_WARNING "Queue %d full, %ld outstanding.\n", - qid, q->numpending); - return 0; - } else { - *entry = q->base + *index; - return 1; - } + *index = le32_to_cpu(*(q->headers.producer)); + if ((*index - 2) == le32_to_cpu(*(q->headers.consumer))) + *nonotify = 1; + + if (qid == AdapHighCmdQueue) { + if (*index >= ADAP_HIGH_CMD_ENTRIES) + *index = 0; + } else if (qid == AdapNormCmdQueue) { + if (*index >= ADAP_NORM_CMD_ENTRIES) + *index = 0; /* Wrap to front of the Producer Queue. */ + } + else if (qid == AdapHighRespQueue) + { + if (*index >= ADAP_HIGH_RESP_ENTRIES) + *index = 0; + } + else if (qid == AdapNormRespQueue) + { + if (*index >= ADAP_NORM_RESP_ENTRIES) + *index = 0; /* Wrap to front of the Producer Queue. */ + } + else BUG(); + + if (*index + 1 == le32_to_cpu(*(q->headers.consumer))) { /* Queue is full */ + printk(KERN_WARNING "Queue %d full, %ld outstanding.\n", qid, q->numpending); + return 0; + } else { + *entry = q->base + *index; + return 1; + } } /** @@ -316,48 +311,49 @@ static int aac_get_entry (struct aac_dev * dev, u32 qid, struct aac_entry **entr * success. */ -static int aac_queue_get(struct aac_dev * dev, u32 * index, u32 qid, struct hw_fib * fib, int wait, struct fib * fibptr, unsigned long *nonotify) +static int aac_queue_get(struct aac_dev * dev, u32 * index, u32 qid, struct hw_fib * hw_fib, int wait, struct fib * fibptr, unsigned long *nonotify) { - struct aac_entry * entry = NULL; - int map = 0; - struct aac_queue * q = &dev->queues->queue[qid]; + struct aac_entry * entry = NULL; + int map = 0; + struct aac_queue * q = &dev->queues->queue[qid]; - spin_lock_irqsave(q->lock, q->SavedIrql); + spin_lock_irqsave(q->lock, q->SavedIrql); - if (qid == AdapHighCmdQueue || qid == AdapNormCmdQueue) - { - /* if no entries wait for some if caller wants to */ - while (!aac_get_entry(dev, qid, &entry, index, nonotify)) + if (qid == AdapHighCmdQueue || qid == AdapNormCmdQueue) { - printk(KERN_ERR "GetEntries failed\n"); + /* if no entries wait for some if caller wants to */ + while (!aac_get_entry(dev, qid, &entry, index, nonotify)) + { + printk(KERN_ERR "GetEntries failed\n"); + } + /* + * Setup queue entry with a command, status and fib mapped + */ + entry->size = cpu_to_le32(le16_to_cpu(hw_fib->header.Size)); + map = 1; } - /* - * Setup queue entry with a command, status and fib mapped - */ - entry->size = cpu_to_le32(le16_to_cpu(fib->header.Size)); - map = 1; - } - else if (qid == AdapHighRespQueue || qid == AdapNormRespQueue) - { - while(!aac_get_entry(dev, qid, &entry, index, nonotify)) + else if (qid == AdapHighRespQueue || qid == AdapNormRespQueue) { - /* if no entries wait for some if caller wants to */ - } + while(!aac_get_entry(dev, qid, &entry, index, nonotify)) + { + /* if no entries wait for some if caller wants to */ + } + /* + * Setup queue entry with command, status and fib mapped + */ + entry->size = cpu_to_le32(le16_to_cpu(hw_fib->header.Size)); + entry->addr = hw_fib->header.SenderFibAddress; + /* Restore adapters pointer to the FIB */ + hw_fib->header.ReceiverFibAddress = hw_fib->header.SenderFibAddress; /* Let the adapter now where to find its data */ + map = 0; + } /* - * Setup queue entry with command, status and fib mapped + * If MapFib is true than we need to map the Fib and put pointers + * in the queue entry. */ - entry->size = cpu_to_le32(le16_to_cpu(fib->header.Size)); - entry->addr = cpu_to_le32(fib->header.SenderFibAddress); /* Restore adapters pointer to the FIB */ - fib->header.ReceiverFibAddress = fib->header.SenderFibAddress; /* Let the adapter now where to find its data */ - map = 0; - } - /* - * If MapFib is true than we need to map the Fib and put pointers - * in the queue entry. - */ - if (map) - entry->addr = cpu_to_le32((unsigned long)(fibptr->logicaladdr)); - return 0; + if (map) + entry->addr = fibptr->hw_fib_pa; + return 0; } @@ -376,24 +372,24 @@ static int aac_queue_get(struct aac_dev * dev, u32 * index, u32 qid, struct hw_f static int aac_insert_entry(struct aac_dev * dev, u32 index, u32 qid, unsigned long nonotify) { - struct aac_queue * q = &dev->queues->queue[qid]; - - if(q == NULL) - BUG(); - *(q->headers.producer) = cpu_to_le32(index + 1); - spin_unlock_irqrestore(q->lock, q->SavedIrql); - - if (qid == AdapHighCmdQueue || - qid == AdapNormCmdQueue || - qid == AdapHighRespQueue || - qid == AdapNormRespQueue) - { - if (!nonotify) - aac_adapter_notify(dev, qid); - } - else - printk("Suprise insert!\n"); - return 0; + struct aac_queue * q = &dev->queues->queue[qid]; + + if(q == NULL) + BUG(); + *(q->headers.producer) = cpu_to_le32(index + 1); + spin_unlock_irqrestore(q->lock, q->SavedIrql); + + if (qid == AdapHighCmdQueue || + qid == AdapNormCmdQueue || + qid == AdapHighRespQueue || + qid == AdapNormRespQueue) + { + if (!nonotify) + aac_adapter_notify(dev, qid); + } + else + printk("Suprise insert!\n"); + return 0; } /* @@ -423,149 +419,141 @@ static int aac_insert_entry(struct aac_dev * dev, u32 index, u32 qid, unsigned l int fib_send(u16 command, struct fib * fibptr, unsigned long size, int priority, int wait, int reply, fib_callback callback, void * callback_data) { - u32 index; - u32 qid; - struct aac_dev * dev = fibptr->dev; - unsigned long nointr = 0; - struct hw_fib * fib = fibptr->fib; - struct aac_queue * q; - unsigned long flags = 0; - - if (!(le32_to_cpu(fib->header.XferState) & HostOwned)) - return -EBUSY; - /* - * There are 5 cases with the wait and reponse requested flags. - * The only invalid cases are if the caller requests to wait and - * does not request a response and if the caller does not want a - * response and the Fibis not allocated from pool. If a response - * is not requesed the Fib will just be deallocaed by the DPC - * routine when the response comes back from the adapter. No - * further processing will be done besides deleting the Fib. We - * will have a debug mode where the adapter can notify the host - * it had a problem and the host can log that fact. - */ - if (wait && !reply) { - return -EINVAL; - } else if (!wait && reply) { - fib->header.XferState |= cpu_to_le32(Async | ResponseExpected); - FIB_COUNTER_INCREMENT(aac_config.AsyncSent); - } else if (!wait && !reply) { - fib->header.XferState |= cpu_to_le32(NoResponseExpected); - FIB_COUNTER_INCREMENT(aac_config.NoResponseSent); - } else if (wait && reply) { - fib->header.XferState |= cpu_to_le32(ResponseExpected); - FIB_COUNTER_INCREMENT(aac_config.NormalSent); - } - /* - * Map the fib into 32bits by using the fib number - */ - fib->header.SenderData = fibptr-&dev->fibs[0]; /* for callback */ - /* - * Set FIB state to indicate where it came from and if we want a - * response from the adapter. Also load the command from the - * caller. - * - * Map the hw fib pointer as a 32bit value - */ - fib->header.SenderFibAddress = fib2addr(fib); - fib->header.Command = cpu_to_le16(command); - fib->header.XferState |= cpu_to_le32(SentFromHost); - fibptr->fib->header.Flags = 0; /* Zero flags field - its internal only */ - /* - * Set the size of the Fib we want to send to the adapter - */ - fib->header.Size = cpu_to_le16(sizeof(struct aac_fibhdr) + size); - if (le16_to_cpu(fib->header.Size) > le16_to_cpu(fib->header.SenderSize)) { - return -EMSGSIZE; - } - /* - * Get a queue entry connect the FIB to it and send an notify - * the adapter a command is ready. - */ - if (priority == FsaHigh) { - fib->header.XferState |= cpu_to_le32(HighPriority); - qid = AdapHighCmdQueue; - } else { - fib->header.XferState |= cpu_to_le32(NormalPriority); - qid = AdapNormCmdQueue; - } - q = &dev->queues->queue[qid]; - - if(wait) - spin_lock_irqsave(&fibptr->event_lock, flags); - - if(aac_queue_get( dev, &index, qid, fib, 1, fibptr, &nointr)<0) - return -EWOULDBLOCK; - dprintk((KERN_DEBUG "fib_send: inserting a queue entry at index %d.\n", - index)); - dprintk((KERN_DEBUG "Fib contents:.\n")); - dprintk((KERN_DEBUG " Command = %d.\n", - fib->header.Command)); - dprintk((KERN_DEBUG " XferState = %x.\n", - fib->header.XferState)); - /* - * Fill in the Callback and CallbackContext if we are not - * going to wait. - */ - if (!wait) { - fibptr->callback = callback; - fibptr->callback_data = callback_data; - } - FIB_COUNTER_INCREMENT(aac_config.FibsSent); - list_add_tail(&fibptr->queue, &q->pendingq); - q->numpending++; - - fibptr->done = 0; - - if(aac_insert_entry(dev, index, qid, - (nointr & aac_config.irq_mod)) < 0) - return -EWOULDBLOCK; - /* - * If the caller wanted us to wait for response wait now. - */ + u32 index; + u32 qid; + struct aac_dev * dev = fibptr->dev; + unsigned long nointr = 0; + struct hw_fib * hw_fib = fibptr->hw_fib; + struct aac_queue * q; + unsigned long flags = 0; + + if (!(le32_to_cpu(hw_fib->header.XferState) & HostOwned)) + return -EBUSY; + /* + * There are 5 cases with the wait and reponse requested flags. + * The only invalid cases are if the caller requests to wait and + * does not request a response and if the caller does not want a + * response and the Fibis not allocated from pool. If a response + * is not requesed the Fib will just be deallocaed by the DPC + * routine when the response comes back from the adapter. No + * further processing will be done besides deleting the Fib. We + * will have a debug mode where the adapter can notify the host + * it had a problem and the host can log that fact. + */ + if (wait && !reply) { + return -EINVAL; + } else if (!wait && reply) { + hw_fib->header.XferState |= cpu_to_le32(Async | ResponseExpected); + FIB_COUNTER_INCREMENT(aac_config.AsyncSent); + } else if (!wait && !reply) { + hw_fib->header.XferState |= cpu_to_le32(NoResponseExpected); + FIB_COUNTER_INCREMENT(aac_config.NoResponseSent); + } else if (wait && reply) { + hw_fib->header.XferState |= cpu_to_le32(ResponseExpected); + FIB_COUNTER_INCREMENT(aac_config.NormalSent); + } + /* + * Map the fib into 32bits by using the fib number + */ + +// hw_fib->header.SenderFibAddress = ((u32)(fibptr-dev->fibs)) << 1; + hw_fib->header.SenderFibAddress = cpu_to_le32((u32)(ulong)fibptr->hw_fib_pa); + hw_fib->header.SenderData = (u32)(fibptr - dev->fibs); + /* + * Set FIB state to indicate where it came from and if we want a + * response from the adapter. Also load the command from the + * caller. + * + * Map the hw fib pointer as a 32bit value + */ + hw_fib->header.Command = cpu_to_le16(command); + hw_fib->header.XferState |= cpu_to_le32(SentFromHost); + fibptr->hw_fib->header.Flags = 0; /* 0 the flags field - internal only*/ + /* + * Set the size of the Fib we want to send to the adapter + */ + hw_fib->header.Size = cpu_to_le16(sizeof(struct aac_fibhdr) + size); + if (le16_to_cpu(hw_fib->header.Size) > le16_to_cpu(hw_fib->header.SenderSize)) { + return -EMSGSIZE; + } + /* + * Get a queue entry connect the FIB to it and send an notify + * the adapter a command is ready. + */ + if (priority == FsaHigh) { + hw_fib->header.XferState |= cpu_to_le32(HighPriority); + qid = AdapHighCmdQueue; + } else { + hw_fib->header.XferState |= cpu_to_le32(NormalPriority); + qid = AdapNormCmdQueue; + } + q = &dev->queues->queue[qid]; + + if(wait) + spin_lock_irqsave(&fibptr->event_lock, flags); + if(aac_queue_get( dev, &index, qid, hw_fib, 1, fibptr, &nointr)<0) + return -EWOULDBLOCK; + dprintk((KERN_DEBUG "fib_send: inserting a queue entry at index %d.\n",index)); + dprintk((KERN_DEBUG "Fib contents:.\n")); + dprintk((KERN_DEBUG " Command = %d.\n", hw_fib->header.Command)); + dprintk((KERN_DEBUG " XferState = %x.\n", hw_fib->header.XferState)); + dprintk((KERN_DEBUG " hw_fib va being sent=%p\n",fibptr->hw_fib)); + dprintk((KERN_DEBUG " hw_fib pa being sent=%lx\n",(ulong)fibptr->hw_fib_pa)); + dprintk((KERN_DEBUG " fib being sent=%p\n",fibptr)); + /* + * Fill in the Callback and CallbackContext if we are not + * going to wait. + */ + if (!wait) { + fibptr->callback = callback; + fibptr->callback_data = callback_data; + } + FIB_COUNTER_INCREMENT(aac_config.FibsSent); + list_add_tail(&fibptr->queue, &q->pendingq); + q->numpending++; + + fibptr->done = 0; + fibptr->flags = 0; + + if(aac_insert_entry(dev, index, qid, (nointr & aac_config.irq_mod)) < 0) + return -EWOULDBLOCK; + /* + * If the caller wanted us to wait for response wait now. + */ - if (wait) { - spin_unlock_irqrestore(&fibptr->event_lock, flags); + if (wait) { + spin_unlock_irqrestore(&fibptr->event_lock, flags); #if 0 - down(&fibptr->event_wait); + down(&fibptr->event_wait); + if(fibptr->done == 0) + BUG(); #endif #ifdef TRY_TASKLET - /* - * XXX KAF: Well, this is pretty gross. We should probably - * do_softirq() after scheduling the tasklet, as long as we - * are _sure_ we hold no locks here... - */ -// printk("about to softirq aac_command_thread...\n"); while (!fibptr->done) { - tasklet_schedule(&aac_command_tasklet); - do_softirq(); /* force execution */ -// mdelay(100); + tasklet_schedule(&aac_command_tasklet); + do_softirq(); /* force execution */ } -// printk("back from softirq cmd thread and fibptr->done!\n"); #else - printk("about to bail at aac_command_thread...\n"); while (!fibptr->done) { - mdelay(100); - aac_command_thread(dev); + mdelay(100); + aac_command_thread(dev); } - printk("back from command thread and fibptr->done!\n"); #endif -/* if(fibptr->done == 0) */ -/* BUG(); */ + - if((fibptr->flags & FIB_CONTEXT_FLAG_TIMED_OUT)) - return -ETIMEDOUT; + if((fibptr->flags & FIB_CONTEXT_FLAG_TIMED_OUT)) + return -ETIMEDOUT; + else + return 0; + } + /* + * If the user does not want a response than return success otherwise + * return pending + */ + if (reply) + return -EINPROGRESS; else - return 0; - } - /* - * If the user does not want a response than return success otherwise - * return pending - */ - if (reply) - return -EINPROGRESS; - else - return 0; + return 0; } /** @@ -574,37 +562,36 @@ int fib_send(u16 command, struct fib * fibptr, unsigned long size, int priority * @q: Queue * @entry: Return entry * - * Will return a pointer to the entry on the top of the queue - * requested that we are a consumer of, and return the address of - * the queue entry. It does * not change the state of the queue. + * Will return a pointer to the entry on the top of the queue requested that + * we are a consumer of, and return the address of the queue entry. It does + * not change the state of the queue. */ int aac_consumer_get(struct aac_dev * dev, struct aac_queue * q, struct aac_entry **entry) { - u32 index; - int status; - - if (*q->headers.producer == *q->headers.consumer) { - status = 0; - } else { - /* - * The consumer index must be wrapped if we have reached - * the end of the queue, else we just use the entry - * pointed to by the header index - */ - if (le32_to_cpu(*q->headers.consumer) >= q->entries) - index = 0; - else - index = le32_to_cpu(*q->headers.consumer); - *entry = q->base + index; - status = 1; - } - return(status); + u32 index; + int status; + if (le32_to_cpu(*q->headers.producer) == le32_to_cpu(*q->headers.consumer)) { + status = 0; + } else { + /* + * The consumer index must be wrapped if we have reached + * the end of the queue, else we just use the entry + * pointed to by the header index + */ + if (le32_to_cpu(*q->headers.consumer) >= q->entries) + index = 0; + else + index = le32_to_cpu(*q->headers.consumer); + *entry = q->base + index; + status = 1; + } + return(status); } int aac_consumer_avail(struct aac_dev *dev, struct aac_queue * q) { - return (*q->headers.producer != *q->headers.consumer); + return (le32_to_cpu(*q->headers.producer) != le32_to_cpu(*q->headers.consumer)); } @@ -620,39 +607,38 @@ int aac_consumer_avail(struct aac_dev *dev, struct aac_queue * q) void aac_consumer_free(struct aac_dev * dev, struct aac_queue *q, u32 qid) { - int wasfull = 0; - u32 notify; + int wasfull = 0; + u32 notify; - if (*q->headers.producer+1 == *q->headers.consumer) - wasfull = 1; + if ((le32_to_cpu(*q->headers.producer)+1) == le32_to_cpu(*q->headers.consumer)) + wasfull = 1; - if (le32_to_cpu(*q->headers.consumer) >= q->entries) - *q->headers.consumer = cpu_to_le32(1); - else - *q->headers.consumer = - cpu_to_le32(le32_to_cpu(*q->headers.consumer)+1); + if (le32_to_cpu(*q->headers.consumer) >= q->entries) + *q->headers.consumer = cpu_to_le32(1); + else + *q->headers.consumer = cpu_to_le32(le32_to_cpu(*q->headers.consumer)+1); - if (wasfull) { - switch (qid) { - - case HostNormCmdQueue: - notify = HostNormCmdNotFull; - break; - case HostHighCmdQueue: - notify = HostHighCmdNotFull; - break; - case HostNormRespQueue: - notify = HostNormRespNotFull; - break; - case HostHighRespQueue: - notify = HostHighRespNotFull; - break; - default: - BUG(); - return; + if (wasfull) { + switch (qid) { + + case HostNormCmdQueue: + notify = HostNormCmdNotFull; + break; + case HostHighCmdQueue: + notify = HostHighCmdNotFull; + break; + case HostNormRespQueue: + notify = HostNormRespNotFull; + break; + case HostHighRespQueue: + notify = HostHighRespNotFull; + break; + default: + BUG(); + return; + } + aac_adapter_notify(dev, notify); } - aac_adapter_notify(dev, notify); - } } /** @@ -666,70 +652,65 @@ void aac_consumer_free(struct aac_dev * dev, struct aac_queue *q, u32 qid) int fib_adapter_complete(struct fib * fibptr, unsigned short size) { - struct hw_fib * fib = fibptr->fib; - struct aac_dev * dev = fibptr->dev; - unsigned long nointr = 0; - - if (le32_to_cpu(fib->header.XferState) == 0) - return 0; - /* - * If we plan to do anything check the structure type first. - */ - if ( fib->header.StructType != FIB_MAGIC ) { - return -EINVAL; - } - /* - * This block handles the case where the adapter had sent us a - * command and we have finished processing the command. We - * call completeFib when we are done processing the command - * and want to send a response back to the adapter. This will - * send the completed cdb to the adapter. - */ - if (fib->header.XferState & cpu_to_le32(SentFromAdapter)) { - fib->header.XferState |= cpu_to_le32(HostProcessed); - if (fib->header.XferState & cpu_to_le32(HighPriority)) { - u32 index; - if (size) - { - size += sizeof(struct aac_fibhdr); - if (size > le16_to_cpu(fib->header.SenderSize)) - return -EMSGSIZE; - fib->header.Size = cpu_to_le16(size); - } - if(aac_queue_get(dev, &index, AdapHighRespQueue, - fib, 1, NULL, &nointr) < 0) { - return -EWOULDBLOCK; - } - if (aac_insert_entry(dev, index, AdapHighRespQueue, - (nointr & (int)aac_config.irq_mod)) != 0) { - } + struct hw_fib * hw_fib = fibptr->hw_fib; + struct aac_dev * dev = fibptr->dev; + unsigned long nointr = 0; + if (le32_to_cpu(hw_fib->header.XferState) == 0) + return 0; + /* + * If we plan to do anything check the structure type first. + */ + if ( hw_fib->header.StructType != FIB_MAGIC ) { + return -EINVAL; } - else if (fib->header.XferState & NormalPriority) - { - u32 index; - - if (size) { - size += sizeof(struct aac_fibhdr); - if (size > le16_to_cpu(fib->header.SenderSize)) - return -EMSGSIZE; - fib->header.Size = cpu_to_le16(size); - } - if (aac_queue_get(dev, &index, AdapNormRespQueue, - fib, 1, NULL, &nointr) < 0) - return -EWOULDBLOCK; - if (aac_insert_entry(dev, index, AdapNormRespQueue, - (nointr & (int)aac_config.irq_mod)) != 0) - { - } + /* + * This block handles the case where the adapter had sent us a + * command and we have finished processing the command. We + * call completeFib when we are done processing the command + * and want to send a response back to the adapter. This will + * send the completed cdb to the adapter. + */ + if (hw_fib->header.XferState & cpu_to_le32(SentFromAdapter)) { + hw_fib->header.XferState |= cpu_to_le32(HostProcessed); + if (hw_fib->header.XferState & cpu_to_le32(HighPriority)) { + u32 index; + if (size) + { + size += sizeof(struct aac_fibhdr); + if (size > le16_to_cpu(hw_fib->header.SenderSize)) + return -EMSGSIZE; + hw_fib->header.Size = cpu_to_le16(size); + } + if(aac_queue_get(dev, &index, AdapHighRespQueue, hw_fib, 1, NULL, &nointr) < 0) { + return -EWOULDBLOCK; + } + if (aac_insert_entry(dev, index, AdapHighRespQueue, (nointr & (int)aac_config.irq_mod)) != 0) { + } + } + else if (hw_fib->header.XferState & NormalPriority) + { + u32 index; + + if (size) { + size += sizeof(struct aac_fibhdr); + if (size > le16_to_cpu(hw_fib->header.SenderSize)) + return -EMSGSIZE; + hw_fib->header.Size = cpu_to_le16(size); + } + if (aac_queue_get(dev, &index, AdapNormRespQueue, hw_fib, 1, NULL, &nointr) < 0) + return -EWOULDBLOCK; + if (aac_insert_entry(dev, index, AdapNormRespQueue, + (nointr & (int)aac_config.irq_mod)) != 0) + { + } + } } - } - else - { - printk(KERN_WARNING - "fib_adapter_complete: Unknown xferstate detected.\n"); - BUG(); - } - return 0; + else + { + printk(KERN_WARNING "fib_adapter_complete: Unknown xferstate detected.\n"); + BUG(); + } + return 0; } /** @@ -741,44 +722,44 @@ int fib_adapter_complete(struct fib * fibptr, unsigned short size) int fib_complete(struct fib * fibptr) { - struct hw_fib * fib = fibptr->fib; + struct hw_fib * hw_fib = fibptr->hw_fib; - /* - * Check for a fib which has already been completed - */ + /* + * Check for a fib which has already been completed + */ - if (fib->header.XferState == cpu_to_le32(0)) - return 0; - /* - * If we plan to do anything check the structure type first. - */ - - if (fib->header.StructType != FIB_MAGIC) - return -EINVAL; - /* - * This block completes a cdb which orginated on the host and we - * just need to deallocate the cdb or reinit it. At this point the - * command is complete that we had sent to the adapter and this - * cdb could be reused. - */ - if((fib->header.XferState & cpu_to_le32(SentFromHost)) && - (fib->header.XferState & cpu_to_le32(AdapterProcessed))) - { - fib_dealloc(fibptr); - } - else if(fib->header.XferState & cpu_to_le32(SentFromHost)) - { + if (hw_fib->header.XferState == cpu_to_le32(0)) + return 0; + /* + * If we plan to do anything check the structure type first. + */ + + if (hw_fib->header.StructType != FIB_MAGIC) + return -EINVAL; /* - * This handles the case when the host has aborted the I/O - * to the adapter because the adapter is not responding + * This block completes a cdb which orginated on the host and we + * just need to deallocate the cdb or reinit it. At this point the + * command is complete that we had sent to the adapter and this + * cdb could be reused. */ - fib_dealloc(fibptr); - } else if(fib->header.XferState & cpu_to_le32(HostOwned)) { - fib_dealloc(fibptr); - } else { - BUG(); - } - return 0; + if((hw_fib->header.XferState & cpu_to_le32(SentFromHost)) && + (hw_fib->header.XferState & cpu_to_le32(AdapterProcessed))) + { + fib_dealloc(fibptr); + } + else if(hw_fib->header.XferState & cpu_to_le32(SentFromHost)) + { + /* + * This handles the case when the host has aborted the I/O + * to the adapter because the adapter is not responding + */ + fib_dealloc(fibptr); + } else if(hw_fib->header.XferState & cpu_to_le32(HostOwned)) { + fib_dealloc(fibptr); + } else { + BUG(); + } + return 0; } /** @@ -792,23 +773,23 @@ int fib_complete(struct fib * fibptr) void aac_printf(struct aac_dev *dev, u32 val) { - int length = val & 0xffff; - int level = (val >> 16) & 0xffff; - char *cp = dev->printfbuf; + int length = val & 0xffff; + int level = (val >> 16) & 0xffff; + char *cp = dev->printfbuf; - /* - * The size of the printfbuf is set in port.c - * There is no variable or define for it - */ - if (length > 255) - length = 255; - if (cp[length] != 0) - cp[length] = 0; - if (level == LOG_HIGH_ERROR) - printk(KERN_WARNING "aacraid:%s", cp); - else - printk(KERN_INFO "aacraid:%s", cp); - memset(cp, 0, 256); + /* + * The size of the printfbuf is set in port.c + * There is no variable or define for it + */ + if (length > 255) + length = 255; + if (cp[length] != 0) + cp[length] = 0; + if (level == LOG_HIGH_ERROR) + printk(KERN_WARNING "aacraid:%s", cp); + else + printk(KERN_INFO "aacraid:%s", cp); + memset(cp, 0, 256); } @@ -821,16 +802,117 @@ void aac_printf(struct aac_dev *dev, u32 val) * dispatches it to the appropriate routine for handling. */ +#define CONTAINER_TO_BUS(cont) (0) +#define CONTAINER_TO_TARGET(cont) ((cont)) +#define CONTAINER_TO_LUN(cont) (0) + static void aac_handle_aif(struct aac_dev * dev, struct fib * fibptr) { - struct hw_fib * fib = fibptr->fib; - /* - * Set the status of this FIB to be Invalid parameter. - * - * *(u32 *)fib->data = ST_INVAL; - */ - *(u32 *)fib->data = cpu_to_le32(ST_OK); - fib_adapter_complete(fibptr, sizeof(u32)); +#if 0 + struct hw_fib * hw_fib = fibptr->hw_fib; + struct aac_aifcmd * aifcmd = (struct aac_aifcmd *)hw_fib->data; + int busy; + u32 container; + mm_segment_t fs; + + /* Sniff for container changes */ + dprintk ((KERN_INFO "AifCmdDriverNotify=%x\n", le32_to_cpu(*(u32 *)aifcmd->data))); + switch (le32_to_cpu(*(u32 *)aifcmd->data)) { + case AifDenMorphComplete: + case AifDenVolumeExtendComplete: + case AifEnContainerChange: /* Not really a driver notify Event */ + + busy = 0; + container = le32_to_cpu(((u32 *)aifcmd->data)[1]); + dprintk ((KERN_INFO "container=%d(%d,%d,%d,%d) ", + container, + (dev && dev->scsi_host_ptr) + ? dev->scsi_host_ptr->host_no + : -1, + CONTAINER_TO_BUS(container), + CONTAINER_TO_TARGET(container), + CONTAINER_TO_LUN(container))); + + /* + * Find the Scsi_Device associated with the SCSI address, + * and mark it as changed, invalidating the cache. This deals + * with changes to existing device IDs. + */ + + if ((dev != (struct aac_dev *)NULL) + && (dev->scsi_host_ptr != (struct Scsi_Host *)NULL)) { + Scsi_Device * device; + + for (device = dev->scsi_host_ptr->host_queue; + device != (Scsi_Device *)NULL; + device = device->next) { + dprintk((KERN_INFO + "aifd: device (%d,%d,%d,%d)?\n", + dev->scsi_host_ptr->host_no, + device->channel, + device->id, + device->lun)); + if ((device->channel == CONTAINER_TO_BUS(container)) + && (device->id == CONTAINER_TO_TARGET(container)) + && (device->lun == CONTAINER_TO_LUN(container))) { + busy |= (device->access_count != 0); + if (busy == 0) { + device->removable = TRUE; + } + } + } + } + dprintk (("busy=%d\n", busy)); + + /* + * if (busy == 0) { + * scan_scsis(dev->scsi_host_ptr, 1, + * CONTAINER_TO_BUS(container), + * CONTAINER_TO_TARGET(container), + * CONTAINER_TO_LUN(container)); + * } + * is not exported as accessible, so we need to go around it + * another way. So, we look for the "proc/scsi/scsi" entry in + * the proc filesystem (using proc_scsi as a shortcut) and send + * it a message. This deals with new devices that have + * appeared. If the device has gone offline, scan_scsis will + * also discover this, but we do not want the device to + * go away. We need to check the access_count for the + * device since we are not wanting the devices to go away. + */ + if (busy == 0 && proc_scsi != NULL) { + struct proc_dir_entry * entry; + + dprintk((KERN_INFO "proc_scsi=%p ", proc_scsi)); + for (entry = proc_scsi->subdir; entry != (struct proc_dir_entry *)NULL; entry = entry->next) { + dprintk(("\"%.*s\"[%d]=%x ", entry->namelen, + entry->name, entry->namelen, entry->low_ino)); + if ((entry->low_ino != 0) && (entry->namelen == 4) && (memcmp ("scsi", entry->name, 4) == 0)) { + dprintk(("%p->write_proc=%p ", entry, entry->write_proc)); + if (entry->write_proc != (int (*)(struct file *, const char *, unsigned long, void *))NULL) { + char buffer[80]; + int length; + + sprintf (buffer, + "scsi add-single-device %d %d %d %d\n", + dev->scsi_host_ptr->host_no, + CONTAINER_TO_BUS(container), + CONTAINER_TO_TARGET(container), + CONTAINER_TO_LUN(container)); + length = strlen (buffer); + dprintk((KERN_INFO "echo %.*s > /proc/scsi/scsi\n", length-1, buffer)); + fs = get_fs(); + set_fs(get_ds()); + length = entry->write_proc(NULL, buffer, length, NULL); + set_fs(fs); + dprintk((KERN_INFO "returns %d\n", length)); + } + break; + } + } + } + } +#endif } /** @@ -842,7 +924,6 @@ static void aac_handle_aif(struct aac_dev * dev, struct fib * fibptr) * until the queue is empty. When the queue is empty it will wait for * more FIBs. */ - #ifndef TRY_TASKLET int aac_command_thread(struct aac_dev * dev) { @@ -850,176 +931,193 @@ int aac_command_thread(struct aac_dev * dev) DECLARE_TASKLET_DISABLED(aac_command_tasklet, aac_command_thread, 0); void aac_command_thread(unsigned long data) #define return(_x) return -{ - struct aac_dev *dev = (struct aac_dev *)data; +{ + struct aac_dev *dev = (struct aac_dev *)data; #endif - struct hw_fib *fib, *newfib; - struct fib fibptr; /* for error logging */ - struct aac_queue_block *queues = dev->queues; - struct aac_fib_context *fibctx; - unsigned long flags; + struct hw_fib *hw_fib, *hw_newfib; + struct fib *fib, *newfib; + struct aac_queue_block *queues = dev->queues; + struct aac_fib_context *fibctx; + unsigned long flags; #if 0 - DECLARE_WAITQUEUE(wait, current); + DECLARE_WAITQUEUE(wait, current); #endif - /* - * We can only have one thread per adapter for AIF's. - */ - if (dev->aif_thread) - return(-EINVAL); - + /* + * We can only have one thread per adapter for AIF's. + */ + if (dev->aif_thread) + return(-EINVAL); #if 0 - /* - * Set up the name that will appear in 'ps' - * stored in task_struct.comm[16]. - */ - sprintf(current->comm, "aacraid"); - daemonize(); + /* + * Set up the name that will appear in 'ps' + * stored in task_struct.comm[16]. + */ + sprintf(current->comm, "aacraid"); + daemonize(); #endif - - /* - * Let the DPC know it has a place to send the AIF's to. - */ - dev->aif_thread = 1; - memset(&fibptr, 0, sizeof(struct fib)); + /* + * Let the DPC know it has a place to send the AIF's to. + */ + dev->aif_thread = 1; #if 0 - add_wait_queue(&queues->queue[HostNormCmdQueue].cmdready, &wait); - set_current_state(TASK_INTERRUPTIBLE); + add_wait_queue(&queues->queue[HostNormCmdQueue].cmdready, &wait); + set_current_state(TASK_INTERRUPTIBLE); + dprintk ((KERN_INFO "aac_command_thread start\n")); + while(1) #endif -// while(1) - { - - spin_lock_irqsave(queues->queue[HostNormCmdQueue].lock, flags); - while(!list_empty(&(queues->queue[HostNormCmdQueue].cmdq))) { - struct list_head *entry; - struct aac_aifcmd * aifcmd; + { + spin_lock_irqsave(queues->queue[HostNormCmdQueue].lock, flags); + while(!list_empty(&(queues->queue[HostNormCmdQueue].cmdq))) { + struct list_head *entry; + struct aac_aifcmd * aifcmd; #if 0 - set_current_state(TASK_RUNNING); + set_current_state(TASK_RUNNING); #endif - - entry = queues->queue[HostNormCmdQueue].cmdq.next; - list_del(entry); + entry = queues->queue[HostNormCmdQueue].cmdq.next; + list_del(entry); + + spin_unlock_irqrestore(queues->queue[HostNormCmdQueue].lock, flags); + fib = list_entry(entry, struct fib, fiblink); + /* + * We will process the FIB here or pass it to a + * worker thread that is TBD. We Really can't + * do anything at this point since we don't have + * anything defined for this thread to do. + */ + hw_fib = fib->hw_fib; - spin_unlock_irqrestore(queues->queue[HostNormCmdQueue].lock,flags); - fib = list_entry(entry, struct hw_fib, header.FibLinks); - /* - * We will process the FIB here or pass it to a - * worker thread that is TBD. We Really can't - * do anything at this point since we don't have - * anything defined for this thread to do. - */ - memset(&fibptr, 0, sizeof(struct fib)); - fibptr.type = FSAFS_NTC_FIB_CONTEXT; - fibptr.size = sizeof( struct fib ); - fibptr.fib = fib; - fibptr.data = fib->data; - fibptr.dev = dev; - /* - * We only handle AifRequest fibs from the adapter. - */ - aifcmd = (struct aac_aifcmd *) fib->data; - if (aifcmd->command == le16_to_cpu(AifCmdDriverNotify)) { - aac_handle_aif(dev, &fibptr); - } else { - /* The u32 here is important and intended. We are using - 32bit wrapping time to fit the adapter field */ - u32 time_now, time_last; - unsigned long flagv; - - time_now = jiffies/HZ; - - spin_lock_irqsave(&dev->fib_lock, flagv); - entry = dev->fib_list.next; + memset(fib, 0, sizeof(struct fib)); + fib->type = FSAFS_NTC_FIB_CONTEXT; + fib->size = sizeof( struct fib ); + fib->hw_fib = hw_fib; + fib->data = hw_fib->data; + fib->dev = dev; + /* + * We only handle AifRequest fibs from the adapter. + */ + aifcmd = (struct aac_aifcmd *) hw_fib->data; + if (aifcmd->command == cpu_to_le32(AifCmdDriverNotify)) { + /* Handle Driver Notify Events */ + aac_handle_aif(dev, fib); + *(u32 *)hw_fib->data = cpu_to_le32(ST_OK); + fib_adapter_complete(fib, sizeof(u32)); + } else { + struct list_head *entry; + /* The u32 here is important and intended. We are using + 32bit wrapping time to fit the adapter field */ + + u32 time_now, time_last; + unsigned long flagv; + + /* Sniff events */ + if (aifcmd->command == cpu_to_le32(AifCmdEventNotify)) + aac_handle_aif(dev, fib); + + time_now = jiffies/HZ; + + spin_lock_irqsave(&dev->fib_lock, flagv); + entry = dev->fib_list.next; /* * For each Context that is on the * fibctxList, make a copy of the * fib, and then set the event to wake up the * thread that is waiting for it. */ - while (entry != &dev->fib_list) { - /* - * Extract the fibctx - */ - fibctx = list_entry(entry, struct aac_fib_context, next); - /* - * Check if the queue is getting - * backlogged - */ - if (fibctx->count > 20) - { - time_last = fibctx->jiffies; - /* - * Has it been > 2 minutes - * since the last read off - * the queue? - */ - if ((time_now - time_last) > 120) { - entry = entry->next; - aac_close_fib_context(dev, fibctx); - continue; - } - } - /* - * Warning: no sleep allowed while - * holding spinlock - */ - newfib = kmalloc(sizeof(struct hw_fib), GFP_ATOMIC); - if (newfib) { - /* - * Make the copy of the FIB - */ - memcpy(newfib, fib, sizeof(struct hw_fib)); - /* - * Put the FIB onto the - * fibctx's fibs - */ - list_add_tail(&newfib->header.FibLinks, &fibctx->fibs); - fibctx->count++; + while (entry != &dev->fib_list) { + /* + * Extract the fibctx + */ + fibctx = list_entry(entry, struct aac_fib_context, next); + /* + * Check if the queue is getting + * backlogged + */ + if (fibctx->count > 20) + { + /* + * It's *not* jiffies folks, + * but jiffies / HZ, so do not + * panic ... + */ + time_last = fibctx->jiffies; + /* + * Has it been > 2 minutes + * since the last read off + * the queue? + */ + if ((time_now - time_last) > 120) { + entry = entry->next; + aac_close_fib_context(dev, fibctx); + continue; + } + } + /* + * Warning: no sleep allowed while + * holding spinlock + */ + hw_newfib = kmalloc(sizeof(struct hw_fib), GFP_ATOMIC); + newfib = kmalloc(sizeof(struct fib), GFP_ATOMIC); + if (newfib && hw_newfib) { + /* + * Make the copy of the FIB + * FIXME: check if we need to fix other fields up + */ + memcpy(hw_newfib, hw_fib, sizeof(struct hw_fib)); + memcpy(newfib, fib, sizeof(struct fib)); + newfib->hw_fib = hw_newfib; + /* + * Put the FIB onto the + * fibctx's fibs + */ + list_add_tail(&newfib->fiblink, &fibctx->fib_list); + fibctx->count++; #if 0 - /* - * Set the event to wake up the - * thread that will waiting. - */ - up(&fibctx->wait_sem); + /* + * Set the event to wake up the + * thread that will waiting. + */ + up(&fibctx->wait_sem); #endif - } else { - printk(KERN_WARNING "aifd: didn't allocate NewFib.\n"); - } - entry = entry->next; - } + } else { + printk(KERN_WARNING "aifd: didn't allocate NewFib.\n"); + if(newfib) + kfree(newfib); + if(hw_newfib) + kfree(hw_newfib); + } + entry = entry->next; + } /* * Set the status of this FIB */ - *(u32 *)fib->data = cpu_to_le32(ST_OK); - fib_adapter_complete(&fibptr, sizeof(u32)); - spin_unlock_irqrestore(&dev->fib_lock, flagv); - } - spin_lock_irqsave(queues->queue[HostNormCmdQueue].lock, flags); - } - /* - * There are no more AIF's - */ - spin_unlock_irqrestore(queues->queue[HostNormCmdQueue].lock, flags); + *(u32 *)hw_fib->data = cpu_to_le32(ST_OK); + fib_adapter_complete(fib, sizeof(u32)); + spin_unlock_irqrestore(&dev->fib_lock, flagv); + } + spin_lock_irqsave(queues->queue[HostNormCmdQueue].lock, flags); + kfree(fib); + } + /* + * There are no more AIF's + */ + spin_unlock_irqrestore(queues->queue[HostNormCmdQueue].lock, flags); #if 0 - schedule(); + schedule(); - if(signal_pending(current)) - break; - set_current_state(TASK_INTERRUPTIBLE); + if(signal_pending(current)) + break; + set_current_state(TASK_INTERRUPTIBLE); #endif - - } - + } #if 0 - remove_wait_queue(&queues->queue[HostNormCmdQueue].cmdready, &wait); - dev->aif_thread = 0; - complete_and_exit(&dev->aif_completion, 0); + remove_wait_queue(&queues->queue[HostNormCmdQueue].cmdready, &wait); + dev->aif_thread = 0; + complete_and_exit(&dev->aif_completion, 0); #else - mdelay(50); - dev->aif_thread = 0; - + mdelay(50); + dev->aif_thread = 0; #endif - return(0); } diff --git a/xen/drivers/scsi/aacraid/dpcsup.c b/xen/drivers/scsi/aacraid/dpcsup.c index c9b4dfe123..fab58f32de 100644 --- a/xen/drivers/scsi/aacraid/dpcsup.c +++ b/xen/drivers/scsi/aacraid/dpcsup.c @@ -29,17 +29,17 @@ * */ -#include <xeno/config.h> -/* #include <xeno/kernel.h> */ -#include <xeno/init.h> -#include <xeno/types.h> -#include <xeno/sched.h> -#include <xeno/pci.h> -/* #include <xeno/spinlock.h> */ -/* #include <xeno/slab.h> */ -/* #include <xeno/completion.h> */ -#include <xeno/blk.h> -/* #include <asm/semaphore.h> */ +#include <linux/config.h> +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/types.h> +#include <linux/sched.h> +#include <linux/pci.h> +#include <linux/spinlock.h> +#include <linux/slab.h> +/*#include <linux/completion.h>*/ +#include <linux/blk.h> +/*#include <asm/semaphore.h>*/ #include "scsi.h" #include "hosts.h" @@ -74,12 +74,14 @@ unsigned int aac_response_normal(struct aac_queue * q) */ while(aac_consumer_get(dev, q, &entry)) { - int fast; + u32 fast ; + fast = (entry->addr & cpu_to_le32(0x01)); +// fib = &dev->fibs[(entry->addr >> 1)]; +// hwfib = fib->hw_fib; + hwfib = bus_to_virt(le32_to_cpu(entry->addr & cpu_to_le32(~0x01))); + fib = &dev->fibs[hwfib->header.SenderData]; - fast = (int) (entry->addr & 0x01); - hwfib = addr2fib(entry->addr & ~0x01); aac_consumer_free(dev, q, HostNormRespQueue); - fib = &dev->fibs[hwfib->header.SenderData]; /* * Remove this fib from the Outstanding I/O queue. * But only if it has not already been timed out. @@ -173,32 +175,53 @@ unsigned int aac_command_normal(struct aac_queue *q) * up the waiters until there are no more QEs. We then return * back to the system. */ + dprintk((KERN_INFO + "dev=%p, dev->comm_phys=%x, dev->comm_addr=%p, dev->comm_size=%u\n", + dev, (u32)dev->comm_phys, dev->comm_addr, (unsigned)dev->comm_size)); + while(aac_consumer_get(dev, q, &entry)) { - struct hw_fib * fib; - fib = addr2fib(entry->addr); + struct fib fibctx; + struct fib *fib = &fibctx; + u32 hw_fib_pa = le32_to_cpu(entry->addr & cpu_to_le32(~0x01)); + struct hw_fib * hw_fib_va = ((dev->comm_phys <= hw_fib_pa) + && (hw_fib_pa < (dev->comm_phys + dev->comm_size))) + ? dev->comm_addr + (hw_fib_pa - dev->comm_phys) + : /* inconceivable */ bus_to_virt(hw_fib_pa); + dprintk((KERN_INFO "hw_fib_pa=%x hw_fib_va=%p\n", hw_fib_pa, hw_fib_va)); - if (dev->aif_thread) { - list_add_tail(&fib->header.FibLinks, &q->cmdq); + /* + * Allocate a FIB at all costs. For non queued stuff + * we can just use the stack so we are happy. We need + * a fib object in order to manage the linked lists + */ + if (dev->aif_thread) + if((fib = kmalloc(sizeof(struct fib), GFP_ATOMIC))==NULL) + fib = &fibctx; + + memset(fib, 0, sizeof(struct fib)); + INIT_LIST_HEAD(&fib->fiblink); + fib->type = FSAFS_NTC_FIB_CONTEXT; + fib->size = sizeof(struct fib); + fib->hw_fib = hw_fib_va; + fib->data = hw_fib_va->data; + fib->dev = dev; + + if (dev->aif_thread && fib != &fibctx) + { + list_add_tail(&fib->fiblink, &q->cmdq); aac_consumer_free(dev, q, HostNormCmdQueue); #if 0 wake_up_interruptible(&q->cmdready); #endif } else { - struct fib fibctx; aac_consumer_free(dev, q, HostNormCmdQueue); spin_unlock_irqrestore(q->lock, flags); - memset(&fibctx, 0, sizeof(struct fib)); - fibctx.type = FSAFS_NTC_FIB_CONTEXT; - fibctx.size = sizeof(struct fib); - fibctx.fib = fib; - fibctx.data = fib->data; - fibctx.dev = dev; /* * Set the status of this FIB */ - *(u32 *)fib->data = cpu_to_le32(ST_OK); - fib_adapter_complete(&fibctx, sizeof(u32)); + *(u32 *)hw_fib_va->data = cpu_to_le32(ST_OK); + fib_adapter_complete(fib, sizeof(u32)); spin_lock_irqsave(q->lock, flags); } } diff --git a/xen/drivers/scsi/aacraid/linit.c b/xen/drivers/scsi/aacraid/linit.c index 3e3d60f8ac..f68872d7f2 100644 --- a/xen/drivers/scsi/aacraid/linit.c +++ b/xen/drivers/scsi/aacraid/linit.c @@ -35,21 +35,21 @@ * */ -#define AAC_DRIVER_VERSION "0.9.9ac6-TEST" -#define AAC_DRIVER_BUILD_DATE __DATE__ - -#include <xeno/module.h> -#include <xeno/config.h> -#include <xeno/kernel.h> -#include <xeno/init.h> -#include <xeno/types.h> -#include <xeno/sched.h> -#include <xeno/pci.h> -#include <xeno/spinlock.h> -/* #include <xeno/slab.h> */ -/* #include <xeno/completion.h> */ -/* #include <asm/semaphore.h> */ -#include <xeno/blk.h> +#define AAC_DRIVER_VERSION "1.1.2" +#define AAC_DRIVER_BUILD_DATE __DATE__ " " __TIME__ + +#include <linux/module.h> +#include <linux/config.h> +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/types.h> +#include <linux/sched.h> +#include <linux/pci.h> +#include <linux/spinlock.h> +#include <linux/slab.h> +/*#include <linux/completion.h>*/ +/*#include <asm/semaphore.h>*/ +#include <linux/blk.h> #include "scsi.h" #include "hosts.h" @@ -59,12 +59,14 @@ #define AAC_DRIVERNAME "aacraid" MODULE_AUTHOR("Red Hat Inc and Adaptec"); -MODULE_DESCRIPTION("Supports Dell PERC2, 2/Si, 3/Si, 3/Di, PERC 320/DC, Adaptec 2120S, 2200S, 5400S, and HP NetRAID-4M devices. http://domsch.com/xeno/ or http://linux.adaptec.com"); +MODULE_DESCRIPTION("Supports Dell PERC2, 2/Si, 3/Si, 3/Di, Adaptec Advanced Raid Products, and HP NetRAID-4M devices. http://domsch.com/linux/ or http://linux.adaptec.com"); MODULE_LICENSE("GPL"); -MODULE_PARM(nondasd, "i"); -MODULE_PARM_DESC(nondasd, "Control scanning of hba for nondasd devices. 0=off, 1=on"); +MODULE_PARM(paemode, "i"); +MODULE_PARM_DESC(paemode, "Control whether dma addressing is using PAE. 0=off, 1=on"); -static int nondasd=-1; +#if 0 +static int paemode = -1; +#endif struct aac_dev *aac_devices[MAXIMUM_NUM_ADAPTERS]; @@ -81,25 +83,41 @@ static int aac_cfg_major = -1; */ static struct aac_driver_ident aac_drivers[] = { - { 0x1028, 0x0001, 0x1028, 0x0001, aac_rx_init, "percraid", "DELL ", "PERCRAID ", 2 }, /* PERC 2/Si */ - { 0x1028, 0x0002, 0x1028, 0x0002, aac_rx_init, "percraid", "DELL ", "PERCRAID ", 2 }, /* PERC 3/Di */ - { 0x1028, 0x0003, 0x1028, 0x0003, aac_rx_init, "percraid", "DELL ", "PERCRAID ", 2 }, /* PERC 3/Si */ - { 0x1028, 0x0004, 0x1028, 0x00d0, aac_rx_init, "percraid", "DELL ", "PERCRAID ", 2 }, /* PERC 3/Si */ - { 0x1028, 0x0002, 0x1028, 0x00d1, aac_rx_init, "percraid", "DELL ", "PERCRAID ", 2 }, /* PERC 3/Di */ - { 0x1028, 0x0002, 0x1028, 0x00d9, aac_rx_init, "percraid", "DELL ", "PERCRAID ", 2 }, /* PERC 3/Di */ - { 0x1028, 0x000a, 0x1028, 0x0106, aac_rx_init, "percraid", "DELL ", "PERCRAID ", 2 }, /* PERC 3/Di */ - { 0x1028, 0x000a, 0x1028, 0x011b, aac_rx_init, "percraid", "DELL ", "PERCRAID ", 2 }, /* PERC 3/Di */ - { 0x1028, 0x000a, 0x1028, 0x0121, aac_rx_init, "percraid", "DELL ", "PERCRAID ", 2 }, /* PERC 3/Di */ - { 0x9005, 0x0283, 0x9005, 0x0283, aac_rx_init, "aacraid", "ADAPTEC ", "catapult ", 2 }, /* catapult*/ - { 0x9005, 0x0284, 0x9005, 0x0284, aac_rx_init, "aacraid", "ADAPTEC ", "tomcat ", 2 }, /* tomcat*/ - { 0x9005, 0x0285, 0x9005, 0x0286, aac_rx_init, "aacraid", "ADAPTEC ", "Adaptec 2120S ", 1 }, /* Adaptec 2120S (Crusader)*/ - { 0x9005, 0x0285, 0x9005, 0x0285, aac_rx_init, "aacraid", "ADAPTEC ", "Adaptec 2200S ", 2 }, /* Adaptec 2200S (Vulcan)*/ - { 0x9005, 0x0285, 0x9005, 0x0287, aac_rx_init, "aacraid", "ADAPTEC ", "Adaptec 2200S ", 2 }, /* Adaptec 2200S (Vulcan-2m)*/ - { 0x9005, 0x0285, 0x1028, 0x0287, aac_rx_init, "percraid", "DELL ", "PERCRAID ", 2 }, /* Dell PERC 320/DC */ - { 0x1011, 0x0046, 0x9005, 0x0365, aac_sa_init, "aacraid", "ADAPTEC ", "Adaptec 5400S ", 4 }, /* Adaptec 5400S (Mustang)*/ - { 0x1011, 0x0046, 0x9005, 0x0364, aac_sa_init, "aacraid", "ADAPTEC ", "AAC-364 ", 4 }, /* Adaptec 5400S (Mustang)*/ - { 0x1011, 0x0046, 0x9005, 0x1364, aac_sa_init, "percraid", "DELL ", "PERCRAID ", 4 }, /* Dell PERC2 "Quad Channel" */ - { 0x1011, 0x0046, 0x103c, 0x10c2, aac_sa_init, "hpnraid", "HP ", "NetRAID-4M ", 4 } /* HP NetRAID-4M */ + { 0x1028, 0x0001, 0x1028, 0x0001, aac_rx_init, "percraid", "DELL ", "PERCRAID ", 2 }, /* PERC 2/Si (Iguana/PERC2Si) */ + { 0x1028, 0x0002, 0x1028, 0x0002, aac_rx_init, "percraid", "DELL ", "PERCRAID ", 2 }, /* PERC 3/Di (Opal/PERC3Di) */ + { 0x1028, 0x0003, 0x1028, 0x0003, aac_rx_init, "percraid", "DELL ", "PERCRAID ", 2 }, /* PERC 3/Si (SlimFast/PERC3Si */ + { 0x1028, 0x0004, 0x1028, 0x00d0, aac_rx_init, "percraid", "DELL ", "PERCRAID ", 2 }, /* PERC 3/Di (Iguana FlipChip/PERC3DiF */ + { 0x1028, 0x0002, 0x1028, 0x00d1, aac_rx_init, "percraid", "DELL ", "PERCRAID ", 2 }, /* PERC 3/Di (Viper/PERC3DiV) */ + { 0x1028, 0x0002, 0x1028, 0x00d9, aac_rx_init, "percraid", "DELL ", "PERCRAID ", 2 }, /* PERC 3/Di (Lexus/PERC3DiL) */ + { 0x1028, 0x000a, 0x1028, 0x0106, aac_rx_init, "percraid", "DELL ", "PERCRAID ", 2 }, /* PERC 3/Di (Jaguar/PERC3DiJ) */ + { 0x1028, 0x000a, 0x1028, 0x011b, aac_rx_init, "percraid", "DELL ", "PERCRAID ", 2 }, /* PERC 3/Di (Dagger/PERC3DiD) */ + { 0x1028, 0x000a, 0x1028, 0x0121, aac_rx_init, "percraid", "DELL ", "PERCRAID ", 2 }, /* PERC 3/Di (Boxster/PERC3DiB) */ + { 0x9005, 0x0283, 0x9005, 0x0283, aac_rx_init, "aacraid", "ADAPTEC ", "catapult ", 2 }, /* catapult */ + { 0x9005, 0x0284, 0x9005, 0x0284, aac_rx_init, "aacraid", "ADAPTEC ", "tomcat ", 2 }, /* tomcat */ + { 0x9005, 0x0285, 0x9005, 0x0286, aac_rx_init, "aacraid", "ADAPTEC ", "Adaptec 2120S ", 1, AAC_QUIRK_31BIT },/* Adaptec 2120S (Crusader) */ + { 0x9005, 0x0285, 0x9005, 0x0285, aac_rx_init, "aacraid", "ADAPTEC ", "Adaptec 2200S ", 2, AAC_QUIRK_31BIT },/* Adaptec 2200S (Vulcan) */ + { 0x9005, 0x0285, 0x9005, 0x0287, aac_rx_init, "aacraid", "ADAPTEC ", "Adaptec 2200S ", 2, AAC_QUIRK_31BIT },/* Adaptec 2200S (Vulcan-2m) */ + { 0x9005, 0x0285, 0x17aa, 0x0286, aac_rx_init, "aacraid", "Legend ", "Legend S220 ", 1 }, /* Legend S220 (Legend Crusader) */ + { 0x9005, 0x0285, 0x17aa, 0x0287, aac_rx_init, "aacraid", "Legend ", "Legend S230 ", 2 }, /* Legend S230 (Legend Vulcan) */ + + { 0x9005, 0x0285, 0x9005, 0x0288, aac_rx_init, "aacraid", "ADAPTEC ", "Adaptec 3230S ", 2 }, /* Adaptec 3230S (Harrier) */ + { 0x9005, 0x0285, 0x9005, 0x0289, aac_rx_init, "aacraid", "ADAPTEC ", "Adaptec 3240S ", 2 }, /* Adaptec 3240S (Tornado) */ + { 0x9005, 0x0285, 0x9005, 0x028a, aac_rx_init, "aacraid", "ADAPTEC ", "ASR-2020S PCI-X ", 2 }, /* ASR-2020S PCI-X ZCR (Skyhawk) */ + { 0x9005, 0x0285, 0x9005, 0x028b, aac_rx_init, "aacraid", "ADAPTEC ", "ASR-2020S PCI-X ", 2 }, /* ASR-2020S SO-DIMM PCI-X ZCR (Terminator) */ + { 0x9005, 0x0285, 0x9005, 0x0290, aac_rx_init, "aacraid", "ADAPTEC ", "AAR-2410SA SATA ", 2 }, /* AAR-2410SA PCI SATA 4ch (Jaguar II) */ + { 0x9005, 0x0285, 0x1028, 0x0291, aac_rx_init, "aacraid", "DELL ", "CERC SATA RAID 2 ", 2 }, /* CERC SATA RAID 2 PCI SATA 8ch (DellCorsair) */ + { 0x9005, 0x0285, 0x9005, 0x0292, aac_rx_init, "aacraid", "ADAPTEC ", "AAR-2810SA SATA ", 2 }, /* AAR-2810SA PCI SATA 8ch (Corsair-8) */ + { 0x9005, 0x0285, 0x9005, 0x0293, aac_rx_init, "aacraid", "ADAPTEC ", "AAR-21610SA SATA ", 2 }, /* AAR-21610SA PCI SATA 16ch (Corsair-16) */ + { 0x9005, 0x0285, 0x9005, 0x0294, aac_rx_init, "aacraid", "ADAPTEC ", "SO-DIMM SATA ZCR ", 2 }, /* ESD SO-DIMM PCI-X SATA ZCR (Prowler) */ + /* ServeRAID */ +/* { 0x9005, 0x0250, 0x1014, 0x0279, aac_rx_init, "aacraid", "ADAPTEC ", "Adaptec ", 2 }, */ /* (Marco) */ +/* { 0x9005, 0x0250, 0x1014, 0x028c, aac_rx_init, "aacraid", "ADAPTEC ", "Adaptec ", 2 }, */ /* (Sebring)*/ + + { 0x9005, 0x0285, 0x1028, 0x0287, aac_rx_init, "percraid", "DELL ", "PERC 320/DC ", 2 }, /* Perc 320/DC*/ + { 0x1011, 0x0046, 0x9005, 0x0365, aac_sa_init, "aacraid", "ADAPTEC ", "Adaptec 5400S ", 4 }, /* Adaptec 5400S (Mustang)*/ + { 0x1011, 0x0046, 0x9005, 0x0364, aac_sa_init, "aacraid", "ADAPTEC ", "AAC-364 ", 4 }, /* Adaptec 5400S (Mustang)*/ + { 0x1011, 0x0046, 0x9005, 0x1364, aac_sa_init, "percraid", "DELL ", "PERCRAID ", 4 }, /* Dell PERC2 "Quad Channel" */ + { 0x1011, 0x0046, 0x103c, 0x10c2, aac_sa_init, "hpnraid", "HP ", "NetRAID ", 4 } /* HP NetRAID-4M */ }; #define NUM_AACTYPES (sizeof(aac_drivers) / sizeof(struct aac_driver_ident)) @@ -111,7 +129,7 @@ static int aac_cfg_open(struct inode * inode, struct file * file); static int aac_cfg_release(struct inode * inode,struct file * file); static struct file_operations aac_cfg_fops = { -/* owner: THIS_MODULE, */ + owner: THIS_MODULE, ioctl: aac_cfg_ioctl, open: aac_cfg_open, release: aac_cfg_release @@ -151,194 +169,156 @@ static void aac_queuedepth(struct Scsi_Host *, Scsi_Device *); * scsi_malloc/scsi_free must not be called. * */ + static int aac_detect(Scsi_Host_Template *template) { - int index; - int container; - u16 vendor_id, device_id; - struct Scsi_Host *host_ptr; - struct pci_dev *dev = NULL; - struct aac_dev *aac; - struct fsa_scsi_hba *fsa_dev_ptr; - char *name = NULL; + int index; + int container; + u16 vendor_id, device_id; + struct Scsi_Host *host_ptr; + struct pci_dev *dev = NULL; + struct aac_dev *aac; + struct fsa_scsi_hba *fsa_dev_ptr; + char *name = NULL; - printk(KERN_INFO "Red Hat/Adaptec aacraid driver, %s\n", - AAC_DRIVER_BUILD_DATE); - - - /* - ** XXX SMH: we need to take interrupts during detect, but the SCSI - ** layer is holding this lock with interrupts disabled. I don't - ** know how this works on vanilla linux (we 'down' on a semaphone - ** at one point during the process -- how do we wake?) - */ - spin_unlock_irq(&io_request_lock); - - - /* setting up the proc directory structure */ - template->proc_name = "aacraid"; - - for( index = 0; index != num_aacdrivers; index++ ) - { - device_id = aac_drivers[index].device; - vendor_id = aac_drivers[index].vendor; - name = aac_drivers[index].name; - dprintk((KERN_DEBUG "Checking %s %x/%x/%x/%x.\n", - name, vendor_id, device_id, - aac_drivers[index].subsystem_vendor, - aac_drivers[index].subsystem_device)); - - dev = NULL; - while((dev = pci_find_device(vendor_id, device_id, dev))) { - if (pci_enable_device(dev)) - continue; - pci_set_master(dev); - pci_set_dma_mask(dev, 0xFFFFFFFFULL); - - if((dev->subsystem_vendor != aac_drivers[index].subsystem_vendor) || - (dev->subsystem_device != aac_drivers[index].subsystem_device)) - continue; - - dprintk((KERN_DEBUG "%s device detected.\n", name)); - dprintk((KERN_DEBUG "%x/%x/%x/%x.\n", vendor_id, device_id, - aac_drivers[index].subsystem_vendor, - aac_drivers[index].subsystem_device)); - /* Increment the host adapter count */ - aac_count++; - /* - * scsi_register() allocates memory for a Scsi_Hosts - * structure and links it into the linked list of host - * adapters. This linked list contains the data for all - * possible <supported> scsi hosts. This is similar to - * the Scsi_Host_Template, except that we have one entry - * for each actual physical host adapter on the system, - * stored as a linked list. If there are two AAC boards, - * then we will need to make two Scsi_Host entries, but - * there will be only one Scsi_Host_Template entry. The - * second argument to scsi_register() specifies the size - * of the extra memory we want to hold any device specific - * information. */ - host_ptr = scsi_register( template, sizeof(struct aac_dev) ); - /* - * These three parameters can be used to allow for wide SCSI - * and for host adapters that support multiple buses. - */ - host_ptr->max_id = 17; - host_ptr->max_lun = 8; - host_ptr->max_channel = 1; - host_ptr->irq = dev->irq; /* Adapter IRQ number */ - /* host_ptr->base = ( char * )(dev->resource[0].start & ~0xff); */ - host_ptr->base = dev->resource[0].start; - scsi_set_pci_device(host_ptr, dev); - dprintk((KERN_DEBUG "Device base address = 0x%lx [0x%lx].\n", - host_ptr->base, dev->resource[0].start)); - dprintk((KERN_DEBUG "Device irq = 0x%x.\n", dev->irq)); - /* - * The unique_id field is a unique identifier that must - * be assigned so that we have some way of identifying - * each host adapter properly and uniquely. For hosts - * that do not support more than one card in the - * system, this does not need to be set. It is - * initialized to zero in scsi_register(). This is the - * value returned as aac->id. - */ - host_ptr->unique_id = aac_count - 1; - /* - * This function is called after the device list has - * been built to find the tagged queueing depth - * supported for each device. - */ - host_ptr->select_queue_depths = aac_queuedepth; - aac = (struct aac_dev *)host_ptr->hostdata; - /* attach a pointer back to Scsi_Host */ - aac->scsi_host_ptr = host_ptr; - aac->pdev = dev; - aac->cardtype = index; - aac->name = aac->scsi_host_ptr->hostt->name; - aac->id = aac->scsi_host_ptr->unique_id; - /* Initialize the ordinal number of the device to -1 */ - fsa_dev_ptr = &(aac->fsa_dev); - for( container=0; container < MAXIMUM_NUM_CONTAINERS; container++) - fsa_dev_ptr->devno[container] = -1; - - dprintk((KERN_DEBUG "Initializing Hardware...\n")); - - if((*aac_drivers[index].init)(aac , host_ptr->unique_id) != 0) - { - /* device initialization failed */ - printk(KERN_WARNING - "aacraid: device initialization failed.\n"); - scsi_unregister(host_ptr); - aac_count--; - continue; - } - dprintk((KERN_DEBUG "%s:%d device initialization successful.\n", - name, host_ptr->unique_id)); - aac_get_adapter_info(aac); - - dprintk((KERN_DEBUG "%s got adapter info.\n", name)); - - if(nondasd != -1) - { - /* someone told us how to set this on the cmdline */ - aac->nondasd_support = (nondasd!=0); - } - if(aac->nondasd_support != 0){ - printk(KERN_INFO "%s%d: Non-DASD support enabled\n", - aac->name, aac->id); - } - dprintk((KERN_DEBUG "%s:%d options flag %04x.\n", name, - host_ptr->unique_id, aac->adapter_info.options)); - if(aac->nondasd_support == 1) - { - /* - * max channel will be the physical - * channels plus 1 virtual channel all - * containers are on the virtual - * channel 0 physical channels are - * address by their actual physical - * number+1 */ - host_ptr->max_channel = aac_drivers[index].channels+1; - } else { - host_ptr->max_channel = 1; - } - dprintk((KERN_DEBUG "Device has %d logical channels\n", - host_ptr->max_channel)); - aac_get_containers(aac); - aac_devices[aac_count-1] = aac; - - /* - * dmb - we may need to move these 3 parms somewhere else once - * we get a fib that can report the actual numbers - */ - host_ptr->max_id = AAC_MAX_TARGET; - host_ptr->max_lun = AAC_MAX_LUN; - - /* - * If we are PAE capable then our future DMA mappings - * (for read/write commands) are 64bit clean and don't - * need bouncing. This assumes we do no other 32bit only - * allocations (eg fib table expands) after this point. - */ - - if(aac->pae_support) - pci_set_dma_mask(dev, 0xFFFFFFFFFFFFFFFFUL); - } - } + printk(KERN_INFO "Red Hat/Adaptec aacraid driver (%s %s)\n", AAC_DRIVER_VERSION, AAC_DRIVER_BUILD_DATE); - /* XXX SMH: restore lock and IPL for SCSI layer */ - spin_lock_irq(&io_request_lock); + /* setting up the proc directory structure */ + template->proc_name = "aacraid"; + spin_unlock_irq(&io_request_lock); + for( index = 0; index != num_aacdrivers; index++ ) + { + device_id = aac_drivers[index].device; + vendor_id = aac_drivers[index].vendor; + name = aac_drivers[index].name; + dprintk((KERN_DEBUG "Checking %s %x/%x/%x/%x.\n", + name, vendor_id, device_id, + aac_drivers[index].subsystem_vendor, + aac_drivers[index].subsystem_device)); + + dev = NULL; + while((dev = pci_find_device(vendor_id, device_id, dev))) { + if (pci_enable_device(dev)) + continue; + pci_set_master(dev); + + if(aac_drivers[index].quirks & AAC_QUIRK_31BIT) + pci_set_dma_mask(dev, 0x7FFFFFFFULL); + else + pci_set_dma_mask(dev, 0xFFFFFFFFULL); + + if((dev->subsystem_vendor != aac_drivers[index].subsystem_vendor) || + (dev->subsystem_device != aac_drivers[index].subsystem_device)) + continue; + + dprintk((KERN_DEBUG "%s device detected.\n", name)); + dprintk((KERN_DEBUG "%x/%x/%x/%x.\n", vendor_id, device_id, + aac_drivers[index].subsystem_vendor, aac_drivers[index].subsystem_device)); + /* + * scsi_register() allocates memory for a Scsi_Hosts structure and + * links it into the linked list of host adapters. This linked list + * contains the data for all possible <supported> scsi hosts. + * This is similar to the Scsi_Host_Template, except that we have + * one entry for each actual physical host adapter on the system, + * stored as a linked list. If there are two AAC boards, then we + * will need to make two Scsi_Host entries, but there will be only + * one Scsi_Host_Template entry. The second argument to scsi_register() + * specifies the size of the extra memory we want to hold any device + * specific information. + */ + host_ptr = scsi_register( template, sizeof(struct aac_dev) ); + if(host_ptr == NULL) + continue; + /* Increment the host adapter count */ + aac_count++; + /* + * These three parameters can be used to allow for wide SCSI + * and for host adapters that support multiple buses. + */ + host_ptr->irq = dev->irq; /* Adapter IRQ number */ + /* host_ptr->base = ( char * )(dev->resource[0].start & ~0xff); */ + host_ptr->base = dev->resource[0].start; + scsi_set_pci_device(host_ptr, dev); + dprintk((KERN_DEBUG "Device base address = 0x%lx [0x%lx].\n", host_ptr->base, dev->resource[0].start)); + dprintk((KERN_DEBUG "Device irq = 0x%x.\n", dev->irq)); + /* + * The unique_id field is a unique identifier that must + * be assigned so that we have some way of identifying + * each host adapter properly and uniquely. For hosts + * that do not support more than one card in the + * system, this does not need to be set. It is + * initialized to zero in scsi_register(). This is the + * value returned as aac->id. + */ + host_ptr->unique_id = aac_count - 1; + /* + * This function is called after the device list has + * been built to find the tagged queueing depth + * supported for each device. + */ + host_ptr->select_queue_depths = aac_queuedepth; + aac = (struct aac_dev *)host_ptr->hostdata; + /* attach a pointer back to Scsi_Host */ + aac->scsi_host_ptr = host_ptr; + aac->pdev = dev; + aac->name = aac->scsi_host_ptr->hostt->name; + aac->id = aac->scsi_host_ptr->unique_id; + aac->cardtype = index; + + aac->fibs = (struct fib*) kmalloc(sizeof(struct fib)*AAC_NUM_FIB, GFP_KERNEL); + spin_lock_init(&aac->fib_lock); + + /* Initialize the ordinal number of the device to -1 */ + fsa_dev_ptr = &(aac->fsa_dev); + for( container = 0; container < MAXIMUM_NUM_CONTAINERS; container++ ) + fsa_dev_ptr->devno[container] = -1; + + dprintk((KERN_DEBUG "Initializing Hardware...\n")); + if((*aac_drivers[index].init)(aac , host_ptr->unique_id) != 0) + { + /* device initialization failed */ + printk(KERN_WARNING "aacraid: device initialization failed.\n"); + scsi_unregister(host_ptr); + aac_count--; + continue; + } + dprintk((KERN_DEBUG "%s:%d device initialization successful.\n", name, host_ptr->unique_id)); + aac_get_adapter_info(aac); + if(aac->nondasd_support == 1) + { + /* + * max channel will be the physical channels plus 1 virtual channel + * all containers are on the virtual channel 0 + * physical channels are address by their actual physical number+1 + */ + host_ptr->max_channel = aac_drivers[index].channels+1; + } else { + host_ptr->max_channel = 1; + } + dprintk((KERN_DEBUG "Device has %d logical channels\n", host_ptr->max_channel)); + aac_get_containers(aac); + aac_devices[aac_count-1] = aac; + + /* + * dmb - we may need to move the setting of these parms somewhere else once + * we get a fib that can report the actual numbers + */ + host_ptr->max_id = AAC_MAX_TARGET; + host_ptr->max_lun = AAC_MAX_LUN; + } + } #if 0 - if( aac_count ){ - if((aac_cfg_major = register_chrdev( 0, "aac", &aac_cfg_fops))<0) - printk(KERN_WARNING "aacraid: unable to register 'aac' device.\n"); - } + if( aac_count ){ + if((aac_cfg_major = register_chrdev( 0, "aac", &aac_cfg_fops))<0) + printk(KERN_WARNING "aacraid: unable to register \"aac\" device.\n"); + } #endif + spin_lock_irq(&io_request_lock); - template->present = aac_count; /* # of cards of this type found */ - return aac_count; + template->present = aac_count; /* # of cards of this type found */ + return aac_count; } /** @@ -353,38 +333,37 @@ static int aac_detect(Scsi_Host_Template *template) static int aac_release(struct Scsi_Host *host_ptr) { - struct aac_dev *dev; - dprintk((KERN_DEBUG "aac_release.\n")); - dev = (struct aac_dev *)host_ptr->hostdata; - + struct aac_dev *dev; + dprintk((KERN_DEBUG "aac_release.\n")); + dev = (struct aac_dev *)host_ptr->hostdata; #if 0 - /* - * kill any threads we started - */ - kill_proc(dev->thread_pid, SIGKILL, 0); - wait_for_completion(&dev->aif_completion); + /* + * kill any threads we started + */ + kill_proc(dev->thread_pid, SIGKILL, 0); + wait_for_completion(&dev->aif_completion); #endif - /* - * Call the comm layer to detach from this adapter - */ - aac_detach(dev); - /* Check free orderings... */ - /* remove interrupt binding */ - free_irq(host_ptr->irq, dev); - iounmap((void * )dev->regs.sa); - /* unregister adapter */ - scsi_unregister(host_ptr); - /* - * FIXME: This assumes no hot plugging is going on... - */ - if( aac_cfg_major >= 0 ) - { + /* + * Call the comm layer to detach from this adapter + */ + aac_detach(dev); + /* Check free orderings... */ + /* remove interrupt binding */ + free_irq(host_ptr->irq, dev); + iounmap((void * )dev->regs.sa); + /* unregister adapter */ + scsi_unregister(host_ptr); + /* + * FIXME: This assumes no hot plugging is going on... + */ + if( aac_cfg_major >= 0 ) + { #if 0 - unregister_chrdev(aac_cfg_major, "aac"); + unregister_chrdev(aac_cfg_major, "aac"); #endif - aac_cfg_major = -1; - } - return 0; + aac_cfg_major = -1; + } + return 0; } /** @@ -397,16 +376,16 @@ static int aac_release(struct Scsi_Host *host_ptr) static int aac_queuecommand(Scsi_Cmnd *scsi_cmnd_ptr, void (*complete)(Scsi_Cmnd *)) { - int ret; - - scsi_cmnd_ptr->scsi_done = complete; - /* - * aac_scsi_cmd() handles command processing, setting the - * result code and calling completion routine. - */ - if((ret = aac_scsi_cmd(scsi_cmnd_ptr)) != 0) - dprintk((KERN_DEBUG "aac_scsi_cmd failed.\n")); - return ret; + int ret; + + scsi_cmnd_ptr->scsi_done = complete; + /* + * aac_scsi_cmd() handles command processing, setting the + * result code and calling completion routine. + */ + if((ret = aac_scsi_cmd(scsi_cmnd_ptr)) != 0) + dprintk((KERN_DEBUG "aac_scsi_cmd failed.\n")); + return ret; } /** @@ -418,8 +397,8 @@ static int aac_queuecommand(Scsi_Cmnd *scsi_cmnd_ptr, void (*complete)(Scsi_Cmnd const char *aac_driverinfo(struct Scsi_Host *host_ptr) { - struct aac_dev *dev = (struct aac_dev *)host_ptr->hostdata; - return aac_drivers[dev->cardtype].name; + struct aac_dev *dev = (struct aac_dev *)host_ptr->hostdata; + return aac_drivers[dev->cardtype].name; } /** @@ -456,111 +435,110 @@ struct aac_driver_ident* aac_get_driver_ident(int devtype) static int aac_biosparm(Scsi_Disk *disk, kdev_t dev, int *geom) { - struct diskparm *param = (struct diskparm *)geom; - /*struct buffer_head * buf;*/ - - dprintk((KERN_DEBUG "aac_biosparm.\n")); - - /* - * Assuming extended translation is enabled - #REVISIT# - */ - if( disk->capacity >= 2 * 1024 * 1024 ) /* 1 GB in 512 byte sectors */ - { - if( disk->capacity >= 4 * 1024 * 1024 ) /* 2 GB in 512 byte sectors */ + struct diskparm *param = (struct diskparm *)geom; +#if 0 + struct buffer_head * buf; +#endif + + dprintk((KERN_DEBUG "aac_biosparm.\n")); + + /* + * Assuming extended translation is enabled - #REVISIT# + */ + if( disk->capacity >= 2 * 1024 * 1024 ) /* 1 GB in 512 byte sectors */ { - param->heads = 255; - param->sectors = 63; + if( disk->capacity >= 4 * 1024 * 1024 ) /* 2 GB in 512 byte sectors */ + { + param->heads = 255; + param->sectors = 63; + } + else + { + param->heads = 128; + param->sectors = 32; + } } else { - param->heads = 128; - param->sectors = 32; - } - } - else - { - param->heads = 64; - param->sectors = 32; - } - - param->cylinders = disk->capacity/(param->heads * param->sectors); - -#if 0 - /* - * Read the first 1024 bytes from the disk device - */ - - buf = bread(MKDEV(MAJOR(dev), MINOR(dev)&~0xf), 0, block_size(dev)); - if(buf == NULL) - return 0; - /* - * If the boot sector partition table is valid, search for a partition - * table entry whose end_head matches one of the standard geometry - * translations ( 64/32, 128/32, 255/63 ). - */ - - - if(*(unsigned short *)(buf->b_data + 0x1fe) == cpu_to_le16(0xaa55)) - { - struct partition *first = (struct partition * )(buf->b_data + 0x1be); - struct partition *entry = first; - int saved_cylinders = param->cylinders; - int num; - unsigned char end_head, end_sec; - - for(num = 0; num < 4; num++) - { - end_head = entry->end_head; - end_sec = entry->end_sector & 0x3f; - - if(end_head == 63) - { param->heads = 64; param->sectors = 32; - break; - } - else if(end_head == 127) - { - param->heads = 128; - param->sectors = 32; - break; - } - else if(end_head == 254) - { - param->heads = 255; - param->sectors = 63; - break; - } - entry++; - } - - if(num == 4) - { - end_head = first->end_head; - end_sec = first->end_sector & 0x3f; } - - param->cylinders = disk->capacity / (param->heads * param->sectors); - - if(num < 4 && end_sec == param->sectors) - { - if(param->cylinders != saved_cylinders) - dprintk((KERN_DEBUG "Adopting geometry: heads=%d, " - "sectors=%d from partition table %d.\n", - param->heads, param->sectors, num)); - } - else if(end_head > 0 || end_sec > 0) + + param->cylinders = disk->capacity/(param->heads * param->sectors); + +#if 0 + /* + * Read the first 1024 bytes from the disk device + */ + + buf = bread(MKDEV(MAJOR(dev), MINOR(dev)&~0xf), 0, block_size(dev)); + if(buf == NULL) + return 0; + /* + * If the boot sector partition table is valid, search for a partition + * table entry whose end_head matches one of the standard geometry + * translations ( 64/32, 128/32, 255/63 ). + */ + + if(*(unsigned short *)(buf->b_data + 0x1fe) == cpu_to_le16(0xaa55)) { - dprintk((KERN_DEBUG "Strange geometry: heads=%d, " - "sectors=%d in partition table %d.\n", - end_head + 1, end_sec, num)); - dprintk((KERN_DEBUG "Using geometry: heads=%d, sectors=%d.\n", - param->heads, param->sectors)); + struct partition *first = (struct partition * )(buf->b_data + 0x1be); + struct partition *entry = first; + int saved_cylinders = param->cylinders; + int num; + unsigned char end_head, end_sec; + + for(num = 0; num < 4; num++) + { + end_head = entry->end_head; + end_sec = entry->end_sector & 0x3f; + + if(end_head == 63) + { + param->heads = 64; + param->sectors = 32; + break; + } + else if(end_head == 127) + { + param->heads = 128; + param->sectors = 32; + break; + } + else if(end_head == 254) + { + param->heads = 255; + param->sectors = 63; + break; + } + entry++; + } + + if(num == 4) + { + end_head = first->end_head; + end_sec = first->end_sector & 0x3f; + } + + param->cylinders = disk->capacity / (param->heads * param->sectors); + + if(num < 4 && end_sec == param->sectors) + { + if(param->cylinders != saved_cylinders) + dprintk((KERN_DEBUG "Adopting geometry: heads=%d, sectors=%d from partition table %d.\n", + param->heads, param->sectors, num)); + } + else if(end_head > 0 || end_sec > 0) + { + dprintk((KERN_DEBUG "Strange geometry: heads=%d, sectors=%d in partition table %d.\n", + end_head + 1, end_sec, num)); + dprintk((KERN_DEBUG "Using geometry: heads=%d, sectors=%d.\n", + param->heads, param->sectors)); + } } - } - brelse(buf); + brelse(buf); #endif - return 0; + return 0; } /** @@ -575,20 +553,20 @@ static int aac_biosparm(Scsi_Disk *disk, kdev_t dev, int *geom) static void aac_queuedepth(struct Scsi_Host * host, Scsi_Device * dev ) { - Scsi_Device * dptr; - - dprintk((KERN_DEBUG "aac_queuedepth.\n")); - dprintk((KERN_DEBUG "Device # Q Depth Online\n")); - dprintk((KERN_DEBUG "---------------------------\n")); - for(dptr = dev; dptr != NULL; dptr = dptr->next) - { - if(dptr->host == host) + Scsi_Device * dptr; + + dprintk((KERN_DEBUG "aac_queuedepth.\n")); + dprintk((KERN_DEBUG "Device # Q Depth Online\n")); + dprintk((KERN_DEBUG "---------------------------\n")); + for(dptr = dev; dptr != NULL; dptr = dptr->next) { - dptr->queue_depth = 10; - dprintk((KERN_DEBUG " %2d %d %d\n", - dptr->id, dptr->queue_depth, dptr->online)); + if(dptr->host == host) + { + dptr->queue_depth = 10; + dprintk((KERN_DEBUG " %2d %d %d\n", + dptr->id, dptr->queue_depth, dptr->online)); + } } - } } @@ -603,7 +581,7 @@ static void aac_queuedepth(struct Scsi_Host * host, Scsi_Device * dev ) static int aac_eh_abort(Scsi_Cmnd *cmd) { - return FAILED; + return FAILED; } /** @@ -617,7 +595,7 @@ static int aac_eh_abort(Scsi_Cmnd *cmd) static int aac_eh_device_reset(Scsi_Cmnd *cmd) { - return FAILED; + return FAILED; } /** @@ -631,7 +609,7 @@ static int aac_eh_device_reset(Scsi_Cmnd *cmd) static int aac_eh_bus_reset(Scsi_Cmnd* cmd) { - return FAILED; + return FAILED; } /** @@ -645,8 +623,8 @@ static int aac_eh_bus_reset(Scsi_Cmnd* cmd) static int aac_eh_reset(Scsi_Cmnd* cmd) { - printk(KERN_ERR "aacraid: Host adapter reset request. SCSI hang ?\n"); - return FAILED; + printk(KERN_ERR "aacraid: Host adapter reset request. SCSI hang ?\n"); + return FAILED; } /** @@ -661,10 +639,10 @@ static int aac_eh_reset(Scsi_Cmnd* cmd) static int aac_ioctl(Scsi_Device * scsi_dev_ptr, int cmd, void * arg) { - struct aac_dev *dev; - dprintk((KERN_DEBUG "aac_ioctl.\n")); - dev = (struct aac_dev *)scsi_dev_ptr->host->hostdata; - return aac_do_ioctl(dev, cmd, arg); + struct aac_dev *dev; + dprintk((KERN_DEBUG "aac_ioctl.\n")); + dev = (struct aac_dev *)scsi_dev_ptr->host->hostdata; + return aac_do_ioctl(dev, cmd, arg); } /** @@ -681,10 +659,10 @@ static int aac_ioctl(Scsi_Device * scsi_dev_ptr, int cmd, void * arg) static int aac_cfg_open(struct inode * inode, struct file * file ) { - unsigned minor_number = MINOR(inode->i_rdev); - if(minor_number >= aac_count) - return -ENODEV; - return 0; + unsigned minor_number = MINOR(inode->i_rdev); + if(minor_number >= aac_count) + return -ENODEV; + return 0; } /** @@ -698,7 +676,7 @@ static int aac_cfg_open(struct inode * inode, struct file * file ) static int aac_cfg_release(struct inode * inode, struct file * file ) { - return 0; + return 0; } /** @@ -717,8 +695,8 @@ static int aac_cfg_release(struct inode * inode, struct file * file ) static int aac_cfg_ioctl(struct inode * inode, struct file * file, unsigned int cmd, unsigned long arg ) { - struct aac_dev *dev = aac_devices[MINOR(inode->i_rdev)]; - return aac_do_ioctl(dev, cmd, (void *)arg); + struct aac_dev *dev = aac_devices[MINOR(inode->i_rdev)]; + return aac_do_ioctl(dev, cmd, (void *)arg); } /* @@ -728,9 +706,13 @@ static int aac_cfg_ioctl(struct inode * inode, struct file * file, unsigned int */ static Scsi_Host_Template driver_template = { -/* module: THIS_MODULE, */ +#if 0 + module: THIS_MODULE, +#endif name: "AAC", -/* proc_info: aac_procinfo, */ +#if 0 + proc_info: aac_procinfo, +#endif detect: aac_detect, release: aac_release, info: aac_driverinfo, @@ -780,11 +762,13 @@ static Scsi_Host_Template driver_template = { static int aac_procinfo(char *proc_buffer, char **start_ptr,off_t offset, int bytes_available, int host_no, int write) { - if(write || offset > 0) - return 0; - *start_ptr = proc_buffer; - return sprintf(proc_buffer, "%s %d\n", - "Raid Controller, scsi hba number", host_no); + if(write || offset > 0) + return 0; + *start_ptr = proc_buffer; + return sprintf(proc_buffer, + "Adaptec Raid Controller %s %s, scsi hba number %d\n", + AAC_DRIVER_VERSION, AAC_DRIVER_BUILD_DATE, + host_no); } #endif diff --git a/xen/drivers/scsi/aacraid/rx.c b/xen/drivers/scsi/aacraid/rx.c index 8d4685ba0f..ebb797041e 100644 --- a/xen/drivers/scsi/aacraid/rx.c +++ b/xen/drivers/scsi/aacraid/rx.c @@ -28,18 +28,18 @@ * */ -#include <xeno/config.h> -#include <xeno/kernel.h> -#include <xeno/init.h> -#include <xeno/types.h> -#include <xeno/sched.h> -#include <xeno/pci.h> -/* #include <xeno/spinlock.h> */ -/* #include <xeno/slab.h> */ -#include <xeno/blk.h> -#include <xeno/delay.h> -/* #include <xeno/completion.h> */ -/* #include <asm/semaphore.h> */ +#include <linux/config.h> +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/types.h> +#include <linux/sched.h> +#include <linux/pci.h> +#include <linux/spinlock.h> +#include <linux/slab.h> +#include <linux/blk.h> +#include <linux/delay.h> +/*#include <linux/completion.h>*/ +/*#include <asm/semaphore.h>*/ #include "scsi.h" #include "hosts.h" @@ -47,42 +47,41 @@ static void aac_rx_intr(int irq, void *dev_id, struct pt_regs *regs) { - struct aac_dev *dev = dev_id; - unsigned long bellbits; - u8 intstat, mask; - intstat = rx_readb(dev, MUnit.OISR); - /* - * Read mask and invert because drawbridge is reversed. - * This allows us to only service interrupts that have - * been enabled. - */ - mask = ~(rx_readb(dev, MUnit.OIMR)); - /* Check to see if this is our interrupt. If it isn't just return */ - - if (intstat & mask) - { - bellbits = rx_readl(dev, OutboundDoorbellReg); - if (bellbits & DoorBellPrintfReady) { - aac_printf(dev, le32_to_cpu(rx_readl (dev, IndexRegs.Mailbox[5]))); - rx_writel(dev, MUnit.ODR,DoorBellPrintfReady); - rx_writel(dev, InboundDoorbellReg,DoorBellPrintfDone); - } - else if (bellbits & DoorBellAdapterNormCmdReady) { - aac_command_normal(&dev->queues->queue[HostNormCmdQueue]); - rx_writel(dev, MUnit.ODR, DoorBellAdapterNormCmdReady); - } - else if (bellbits & DoorBellAdapterNormRespReady) { - aac_response_normal(&dev->queues->queue[HostNormRespQueue]); - rx_writel(dev, MUnit.ODR,DoorBellAdapterNormRespReady); - } - else if (bellbits & DoorBellAdapterNormCmdNotFull) { - rx_writel(dev, MUnit.ODR, DoorBellAdapterNormCmdNotFull); - } - else if (bellbits & DoorBellAdapterNormRespNotFull) { - rx_writel(dev, MUnit.ODR, DoorBellAdapterNormCmdNotFull); - rx_writel(dev, MUnit.ODR, DoorBellAdapterNormRespNotFull); + struct aac_dev *dev = dev_id; + unsigned long bellbits; + u8 intstat, mask; + intstat = rx_readb(dev, MUnit.OISR); + /* + * Read mask and invert because drawbridge is reversed. + * This allows us to only service interrupts that have + * been enabled. + */ + mask = ~(rx_readb(dev, MUnit.OIMR)); + /* Check to see if this is our interrupt. If it isn't just return */ + if (intstat & mask) + { + bellbits = rx_readl(dev, OutboundDoorbellReg); + if (bellbits & DoorBellPrintfReady) { + aac_printf(dev, le32_to_cpu(rx_readl (dev, IndexRegs.Mailbox[5]))); + rx_writel(dev, MUnit.ODR,DoorBellPrintfReady); + rx_writel(dev, InboundDoorbellReg,DoorBellPrintfDone); + } + else if (bellbits & DoorBellAdapterNormCmdReady) { + aac_command_normal(&dev->queues->queue[HostNormCmdQueue]); + rx_writel(dev, MUnit.ODR, DoorBellAdapterNormCmdReady); + } + else if (bellbits & DoorBellAdapterNormRespReady) { + aac_response_normal(&dev->queues->queue[HostNormRespQueue]); + rx_writel(dev, MUnit.ODR,DoorBellAdapterNormRespReady); + } + else if (bellbits & DoorBellAdapterNormCmdNotFull) { + rx_writel(dev, MUnit.ODR, DoorBellAdapterNormCmdNotFull); + } + else if (bellbits & DoorBellAdapterNormRespNotFull) { + rx_writel(dev, MUnit.ODR, DoorBellAdapterNormCmdNotFull); + rx_writel(dev, MUnit.ODR, DoorBellAdapterNormRespNotFull); + } } - } } /** @@ -95,24 +94,24 @@ static void aac_rx_intr(int irq, void *dev_id, struct pt_regs *regs) static void aac_rx_enable_interrupt(struct aac_dev * dev, u32 event) { - switch (event) { - - case HostNormCmdQue: - dev->irq_mask &= ~(OUTBOUNDDOORBELL_1); - break; - - case HostNormRespQue: - dev->irq_mask &= ~(OUTBOUNDDOORBELL_2); - break; - - case AdapNormCmdNotFull: - dev->irq_mask &= ~(OUTBOUNDDOORBELL_3); - break; - - case AdapNormRespNotFull: - dev->irq_mask &= ~(OUTBOUNDDOORBELL_4); - break; - } + switch (event) { + + case HostNormCmdQue: + dev->irq_mask &= ~(OUTBOUNDDOORBELL_1); + break; + + case HostNormRespQue: + dev->irq_mask &= ~(OUTBOUNDDOORBELL_2); + break; + + case AdapNormCmdNotFull: + dev->irq_mask &= ~(OUTBOUNDDOORBELL_3); + break; + + case AdapNormRespNotFull: + dev->irq_mask &= ~(OUTBOUNDDOORBELL_4); + break; + } } /** @@ -125,24 +124,24 @@ static void aac_rx_enable_interrupt(struct aac_dev * dev, u32 event) static void aac_rx_disable_interrupt(struct aac_dev *dev, u32 event) { - switch (event) { - - case HostNormCmdQue: - dev->irq_mask |= (OUTBOUNDDOORBELL_1); - break; - - case HostNormRespQue: - dev->irq_mask |= (OUTBOUNDDOORBELL_2); - break; - - case AdapNormCmdNotFull: - dev->irq_mask |= (OUTBOUNDDOORBELL_3); - break; - - case AdapNormRespNotFull: - dev->irq_mask |= (OUTBOUNDDOORBELL_4); - break; - } + switch (event) { + + case HostNormCmdQue: + dev->irq_mask |= (OUTBOUNDDOORBELL_1); + break; + + case HostNormRespQue: + dev->irq_mask |= (OUTBOUNDDOORBELL_2); + break; + + case AdapNormCmdNotFull: + dev->irq_mask |= (OUTBOUNDDOORBELL_3); + break; + + case AdapNormRespNotFull: + dev->irq_mask |= (OUTBOUNDDOORBELL_4); + break; + } } /** @@ -158,91 +157,89 @@ static void aac_rx_disable_interrupt(struct aac_dev *dev, u32 event) static int rx_sync_cmd(struct aac_dev *dev, u32 command, u32 p1, u32 *status) { - unsigned long start; - int ok; - /* - * Write the command into Mailbox 0 - */ - rx_writel(dev, InboundMailbox0, cpu_to_le32(command)); - /* - * Write the parameters into Mailboxes 1 - 4 - */ - rx_writel(dev, InboundMailbox1, cpu_to_le32(p1)); - rx_writel(dev, InboundMailbox2, 0); - rx_writel(dev, InboundMailbox3, 0); - rx_writel(dev, InboundMailbox4, 0); - /* - * Clear the synch command doorbell to start on a clean slate. - */ - rx_writel(dev, OutboundDoorbellReg, OUTBOUNDDOORBELL_0); - /* - * Disable doorbell interrupts - */ - rx_writeb(dev, MUnit.OIMR, rx_readb(dev, MUnit.OIMR) | 0x04); - /* - * Force the completion of the mask register write before issuing - * the interrupt. - */ - rx_readb (dev, MUnit.OIMR); - /* - * Signal that there is a new synch command - */ - rx_writel(dev, InboundDoorbellReg, INBOUNDDOORBELL_0); - - ok = 0; - start = jiffies; - - /* - * Wait up to 30 seconds - */ - while (time_before(jiffies, start+30*HZ)) - { - /* Delay 5 microseconds to let Mon960 get info. */ - udelay(5); + unsigned long start; + int ok; /* - * Mon960 will set doorbell0 bit when its completed the command. + * Write the command into Mailbox 0 */ - if (rx_readl(dev, OutboundDoorbellReg) & OUTBOUNDDOORBELL_0) { - /* - * Clear the doorbell. - */ - rx_writel(dev, OutboundDoorbellReg, OUTBOUNDDOORBELL_0); - ok = 1; - break; - } -#if 0 + rx_writel(dev, InboundMailbox0, cpu_to_le32(command)); /* - * Yield the processor in case we are slow + * Write the parameters into Mailboxes 1 - 4 */ - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(1); -#else - /* XXX SMH: not in xen we don't */ - mdelay(50); + rx_writel(dev, InboundMailbox1, cpu_to_le32(p1)); + rx_writel(dev, InboundMailbox2, 0); + rx_writel(dev, InboundMailbox3, 0); + rx_writel(dev, InboundMailbox4, 0); + /* + * Clear the synch command doorbell to start on a clean slate. + */ + rx_writel(dev, OutboundDoorbellReg, OUTBOUNDDOORBELL_0); + /* + * Disable doorbell interrupts + */ + rx_writeb(dev, MUnit.OIMR, rx_readb(dev, MUnit.OIMR) | 0x04); + /* + * Force the completion of the mask register write before issuing + * the interrupt. + */ + rx_readb (dev, MUnit.OIMR); + /* + * Signal that there is a new synch command + */ + rx_writel(dev, InboundDoorbellReg, INBOUNDDOORBELL_0); + + ok = 0; + start = jiffies; + + /* + * Wait up to 30 seconds + */ + while (time_before(jiffies, start+30*HZ)) + { + udelay(5); /* Delay 5 microseconds to let Mon960 get info. */ + /* + * Mon960 will set doorbell0 bit when it has completed the command. + */ + if (rx_readl(dev, OutboundDoorbellReg) & OUTBOUNDDOORBELL_0) { + /* + * Clear the doorbell. + */ + rx_writel(dev, OutboundDoorbellReg, OUTBOUNDDOORBELL_0); + ok = 1; + break; + } +#if 0 + /* + * Yield the processor in case we are slow + */ + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(1); +#else + /* XXX SMH: not in xen we don't */ + mdelay(50); #endif - - } - if (ok != 1) { + } + if (ok != 1) { + /* + * Restore interrupt mask even though we timed out + */ + rx_writeb(dev, MUnit.OIMR, rx_readl(dev, MUnit.OIMR) & 0xfb); + return -ETIMEDOUT; + } + /* + * Pull the synch status from Mailbox 0. + */ + *status = le32_to_cpu(rx_readl(dev, IndexRegs.Mailbox[0])); /* - * Restore interrupt mask even though we timed out + * Clear the synch command doorbell. + */ + rx_writel(dev, OutboundDoorbellReg, OUTBOUNDDOORBELL_0); + /* + * Restore interrupt mask */ rx_writeb(dev, MUnit.OIMR, rx_readl(dev, MUnit.OIMR) & 0xfb); - return -ETIMEDOUT; - } - /* - * Pull the synch status from Mailbox 0. - */ - *status = le32_to_cpu(rx_readl(dev, IndexRegs.Mailbox[0])); - /* - * Clear the synch command doorbell. - */ - rx_writel(dev, OutboundDoorbellReg, OUTBOUNDDOORBELL_0); - /* - * Restore interrupt mask - */ - rx_writeb(dev, MUnit.OIMR, rx_readl(dev, MUnit.OIMR) & 0xfb); - return 0; - + return 0; + } /** @@ -254,8 +251,8 @@ static int rx_sync_cmd(struct aac_dev *dev, u32 command, u32 p1, u32 *status) static void aac_rx_interrupt_adapter(struct aac_dev *dev) { - u32 ret; - rx_sync_cmd(dev, BREAKPOINT_REQUEST, 0, &ret); + u32 ret; + rx_sync_cmd(dev, BREAKPOINT_REQUEST, 0, &ret); } /** @@ -269,33 +266,33 @@ static void aac_rx_interrupt_adapter(struct aac_dev *dev) static void aac_rx_notify_adapter(struct aac_dev *dev, u32 event) { - switch (event) { - - case AdapNormCmdQue: - rx_writel(dev, MUnit.IDR,INBOUNDDOORBELL_1); - break; - case HostNormRespNotFull: - rx_writel(dev, MUnit.IDR,INBOUNDDOORBELL_4); - break; - case AdapNormRespQue: - rx_writel(dev, MUnit.IDR,INBOUNDDOORBELL_2); - break; - case HostNormCmdNotFull: - rx_writel(dev, MUnit.IDR,INBOUNDDOORBELL_3); - break; - case HostShutdown: + switch (event) { + + case AdapNormCmdQue: + rx_writel(dev, MUnit.IDR,INBOUNDDOORBELL_1); + break; + case HostNormRespNotFull: + rx_writel(dev, MUnit.IDR,INBOUNDDOORBELL_4); + break; + case AdapNormRespQue: + rx_writel(dev, MUnit.IDR,INBOUNDDOORBELL_2); + break; + case HostNormCmdNotFull: + rx_writel(dev, MUnit.IDR,INBOUNDDOORBELL_3); + break; + case HostShutdown: // rx_sync_cmd(dev, HOST_CRASHING, 0, 0, 0, 0, &ret); - break; - case FastIo: - rx_writel(dev, MUnit.IDR,INBOUNDDOORBELL_6); - break; - case AdapPrintfDone: - rx_writel(dev, MUnit.IDR,INBOUNDDOORBELL_5); - break; - default: - BUG(); - break; - } + break; + case FastIo: + rx_writel(dev, MUnit.IDR,INBOUNDDOORBELL_6); + break; + case AdapPrintfDone: + rx_writel(dev, MUnit.IDR,INBOUNDDOORBELL_5); + break; + default: + BUG(); + break; + } } /** @@ -307,31 +304,27 @@ static void aac_rx_notify_adapter(struct aac_dev *dev, u32 event) static void aac_rx_start_adapter(struct aac_dev *dev) { - u32 status; - struct aac_init *init; - - init = dev->init; - - init->HostElapsedSeconds = cpu_to_le32(jiffies/HZ); - /* - * Tell the adapter we are back and up and running so it will scan - * its command queues and enable our interrupts - */ - dev->irq_mask = (DoorBellPrintfReady | OUTBOUNDDOORBELL_1 | - OUTBOUNDDOORBELL_2 | OUTBOUNDDOORBELL_3 | - OUTBOUNDDOORBELL_4); - /* - * First clear out all interrupts. Then enable the one's that we - * can handle. - */ - rx_writeb(dev, MUnit.OIMR, 0xff); - rx_writel(dev, MUnit.ODR, 0xffffffff); + u32 status; + struct aac_init *init; + + init = dev->init; + init->HostElapsedSeconds = cpu_to_le32(jiffies/HZ); + /* + * Tell the adapter we are back and up and running so it will scan + * its command queues and enable our interrupts + */ + dev->irq_mask = (DoorBellPrintfReady | OUTBOUNDDOORBELL_1 | OUTBOUNDDOORBELL_2 | OUTBOUNDDOORBELL_3 | OUTBOUNDDOORBELL_4); + /* + * First clear out all interrupts. Then enable the one's that we + * can handle. + */ + rx_writeb(dev, MUnit.OIMR, 0xff); + rx_writel(dev, MUnit.ODR, 0xffffffff); // rx_writeb(dev, MUnit.OIMR, ~(u8)OUTBOUND_DOORBELL_INTERRUPT_MASK); - rx_writeb(dev, MUnit.OIMR, 0xfb); - - // We can only use a 32 bit address here - rx_sync_cmd(dev, INIT_STRUCT_BASE_ADDRESS, - (u32)(ulong)dev->init_pa, &status); + rx_writeb(dev, MUnit.OIMR, 0xfb); + + // We can only use a 32 bit address here + rx_sync_cmd(dev, INIT_STRUCT_BASE_ADDRESS, (u32)(ulong)dev->init_pa, &status); } /** @@ -346,112 +339,91 @@ static void aac_rx_start_adapter(struct aac_dev *dev) int aac_rx_init(struct aac_dev *dev, unsigned long num) { - unsigned long start; - unsigned long status; - int instance; - const char * name; - - dev->devnum = num; - instance = dev->id; - name = dev->name; - - dprintk((KERN_ERR "aac_rx_init called, num %ld, scsi host ptr = %p\n", - num, (void *)(dev->scsi_host_ptr))); - - dprintk((KERN_ERR "scsi_host_ptr->base is %p\n", - (void *)dev->scsi_host_ptr->base)); - /* - * Map in the registers from the adapter. - */ - if((dev->regs.rx = (struct rx_registers *) - ioremap((unsigned long)dev->scsi_host_ptr->base, 8192))==NULL) - { - printk(KERN_WARNING "aacraid: unable to map i960.\n" ); - return -1; - } - -// dprintk((KERN_ERR "aac_rx_init: AAA\n")); - /* - * Check to see if the board failed any self tests. - */ - if (rx_readl(dev, IndexRegs.Mailbox[7]) & SELF_TEST_FAILED) { - printk(KERN_ERR "%s%d: adapter self-test failed.\n", - dev->name, instance); - return -1; - } - - -// dprintk((KERN_ERR "aac_rx_init: BBB\n")); - /* - * Check to see if the board panic'd while booting. - */ - if (rx_readl(dev, IndexRegs.Mailbox[7]) & KERNEL_PANIC) { - printk(KERN_ERR "%s%d: adapter kernel panic'd.\n", - dev->name, instance); - return -1; - } - start = jiffies; - -// dprintk((KERN_ERR "aac_rx_init: DDD\n")); - /* - * Wait for the adapter to be up and running. Wait up to 3 minutes - */ - while (!(rx_readl(dev, IndexRegs.Mailbox[7]) & KERNEL_UP_AND_RUNNING)) - { - if(time_after(jiffies, start+180*HZ)) - { - status = rx_readl(dev, IndexRegs.Mailbox[7]) >> 16; - printk(KERN_ERR "%s%d: adapter kernel failed to start," - "init status = %ld.\n", dev->name, - instance, status); - return -1; + unsigned long start; + unsigned long status; + int instance; + const char * name; + + dev->devnum = num; + instance = dev->id; + name = dev->name; + + /* + * Map in the registers from the adapter. + */ + if((dev->regs.rx = (struct rx_registers *)ioremap((unsigned long)dev->scsi_host_ptr->base, 8192))==NULL) + { + printk(KERN_WARNING "aacraid: unable to map i960.\n" ); + return -1; + } + /* + * Check to see if the board failed any self tests. + */ + if (rx_readl(dev, IndexRegs.Mailbox[7]) & SELF_TEST_FAILED) { + printk(KERN_ERR "%s%d: adapter self-test failed.\n", dev->name, instance); + return -1; } -// dprintk((KERN_ERR "aac_rx_init: XXX\n")); - -#if 0 - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(1); + /* + * Check to see if the board panic'd while booting. + */ + if (rx_readl(dev, IndexRegs.Mailbox[7]) & KERNEL_PANIC) { + printk(KERN_ERR "%s%d: adapter kernel panic'd.\n", dev->name, instance); + return -1; + } + start = jiffies; + /* + * Wait for the adapter to be up and running. Wait up to 3 minutes + */ + while (!(rx_readl(dev, IndexRegs.Mailbox[7]) & KERNEL_UP_AND_RUNNING)) + { + if(time_after(jiffies, start+180*HZ)) + { + status = rx_readl(dev, IndexRegs.Mailbox[7]) >> 16; + printk(KERN_ERR "%s%d: adapter kernel failed to start, init status = %ld.\n", dev->name, instance, status); + return -1; + } +#if 0 + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(1); #else - /* XXX SMH: no sleeping for us (we're the xen idle task) */ - mdelay(50); + /* XXX SMH: no sleeping for us (we're the xen idle task) */ + mdelay(50); #endif - - } - -// dprintk((KERN_ERR "aac_rx_init: ZZZ!\n")); - if (request_irq(dev->scsi_host_ptr->irq, aac_rx_intr, - SA_SHIRQ|SA_INTERRUPT, "aacraid", (void *)dev) < 0) - { - printk(KERN_ERR "%s%d: Interrupt unavailable.\n", - name, instance); - return -1; - } - /* - * Fill in the function dispatch table. - */ - dev->a_ops.adapter_interrupt = aac_rx_interrupt_adapter; - dev->a_ops.adapter_enable_int = aac_rx_enable_interrupt; - dev->a_ops.adapter_disable_int = aac_rx_disable_interrupt; - dev->a_ops.adapter_notify = aac_rx_notify_adapter; - dev->a_ops.adapter_sync_cmd = rx_sync_cmd; - - if (aac_init_adapter(dev) == NULL) - return -1; + } + if (request_irq(dev->scsi_host_ptr->irq, aac_rx_intr, SA_SHIRQ|SA_INTERRUPT, "aacraid", (void *)dev)<0) + { + printk(KERN_ERR "%s%d: Interrupt unavailable.\n", name, instance); + return -1; + } + /* + * Fill in the function dispatch table. + */ + dev->a_ops.adapter_interrupt = aac_rx_interrupt_adapter; + dev->a_ops.adapter_enable_int = aac_rx_enable_interrupt; + dev->a_ops.adapter_disable_int = aac_rx_disable_interrupt; + dev->a_ops.adapter_notify = aac_rx_notify_adapter; + dev->a_ops.adapter_sync_cmd = rx_sync_cmd; + + if (aac_init_adapter(dev) == NULL) + return -1; #ifdef TRY_TASKLET - aac_command_tasklet.data = (unsigned long)dev; - tasklet_enable(&aac_command_tasklet); + aac_command_tasklet.data = (unsigned long)dev; + tasklet_enable(&aac_command_tasklet); #else - /* - * Start any kernel threads needed - */ - dev->thread_pid = kernel_thread((int (*)(void *))aac_command_thread, - dev, 0); -#endif - - /* - * Tell the adapter that all is configured, and it can start - * accepting requests - */ - aac_rx_start_adapter(dev); - return 0; + /* + * Start any kernel threads needed + */ + dev->thread_pid = kernel_thread((int (*)(void *))aac_command_thread, dev, 0); + if(dev->thread_pid < 0) + { + printk(KERN_ERR "aacraid: Unable to create rx thread.\n"); + return -1; + } +#endif + /* + * Tell the adapter that all is configured, and it can start + * accepting requests + */ + aac_rx_start_adapter(dev); + return 0; } diff --git a/xen/drivers/scsi/aacraid/sa.c b/xen/drivers/scsi/aacraid/sa.c index edb5679d41..9a453176df 100644 --- a/xen/drivers/scsi/aacraid/sa.c +++ b/xen/drivers/scsi/aacraid/sa.c @@ -28,18 +28,18 @@ * */ -#include <xeno/config.h> -#include <xeno/kernel.h> -#include <xeno/init.h> -#include <xeno/types.h> -#include <xeno/sched.h> -/* #include <xeno/pci.h> */ -/* #include <xeno/spinlock.h> */ -/* #include <xeno/slab.h> */ -#include <xeno/blk.h> -#include <xeno/delay.h> -/* #include <xeno/completion.h> */ -/* #include <asm/semaphore.h> */ +#include <linux/config.h> +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/types.h> +#include <linux/sched.h> +#include <linux/pci.h> +#include <linux/spinlock.h> +#include <linux/slab.h> +#include <linux/blk.h> +#include <linux/delay.h> +/*#include <linux/completion.h>*/ +/*#include <asm/semaphore.h>*/ #include "scsi.h" #include "hosts.h" @@ -235,9 +235,9 @@ static int sa_sync_cmd(struct aac_dev *dev, u32 command, u32 p1, u32 *ret) #if 0 set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout(1); +#else + mdelay(100); #endif - mdelay(100); - } if (ok != 1) @@ -353,7 +353,7 @@ int aac_sa_init(struct aac_dev *dev, unsigned long devnum) * Wait for the adapter to be up and running. Wait up to 3 minutes. */ while (!(sa_readl(dev, Mailbox7) & KERNEL_UP_AND_RUNNING)) { - if (time_after(start+180*HZ, jiffies)) { + if (time_after(jiffies, start+180*HZ)) { status = sa_readl(dev, Mailbox7) >> 16; printk(KERN_WARNING "%s%d: adapter kernel failed to start, init status = %d.\n", name, instance, le32_to_cpu(status)); return -1; @@ -361,8 +361,9 @@ int aac_sa_init(struct aac_dev *dev, unsigned long devnum) #if 0 set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout(1); +#else + mdelay(100); #endif - mdelay(100); } dprintk(("ATIRQ\n")); @@ -392,8 +393,11 @@ int aac_sa_init(struct aac_dev *dev, unsigned long devnum) * Start any kernel threads needed */ dev->thread_pid = kernel_thread((int (*)(void *))aac_command_thread, dev, 0); + if (dev->thread_pid < 0) { + printk(KERN_ERR "aacraid: Unable to create command thread.\n"); + return -1; + } #endif - /* * Tell the adapter that all is configure, and it can start * accepting requests |