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).
This commit is contained in:
kaf24@scramble.cl.cam.ac.uk committed 2003-08-07 12:24:12 +00:00
1 parent 4a30b340d9
commit 6737c35322
12 files changed
+2474 -2309

No files matched your search

-4
View File
@@ -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)
+15 -2
View File
@@ -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
+1
View File
@@ -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.
File diff suppressed because it is too large. Load diff
+79 -71
View File
@@ -1,17 +1,14 @@
/* #define dprintk(x) */
// #define dprintk(x) printk x
#define dprintk(x)
#include <asm/byteorder.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 */
//#define dprintk(x) printk x
#if (!defined(dprintk))
# define dprintk(x)
#endif
/* Start of Xen additions XXX */
#include <asm/byteorder.h>
#include <xeno/interrupt.h>
#define TRY_TASKLET
/* 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);
+33 -26
View File
@@ -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);
}
/*
+34 -36
View File
@@ -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);
File diff suppressed because it is too large. Load diff
+52 -29
View File
@@ -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;
fast = (int) (entry->addr & 0x01);
hwfib = addr2fib(entry->addr & ~0x01);
aac_consumer_free(dev, q, HostNormRespQueue);
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];
aac_consumer_free(dev, q, HostNormRespQueue);
/*
* 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);
}
}
+367 -383
View File
@@ -35,21 +35,21 @@
*
*/
#define AAC_DRIVER_VERSION "0.9.9ac6-TEST"
#define AAC_DRIVER_BUILD_DATE __DATE__
#define AAC_DRIVER_VERSION "1.1.2"
#define AAC_DRIVER_BUILD_DATE __DATE__ " " __TIME__
#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>
#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);
printk(KERN_INFO "Red Hat/Adaptec aacraid driver (%s %s)\n", AAC_DRIVER_VERSION, AAC_DRIVER_BUILD_DATE);
/* setting up the proc directory structure */
template->proc_name = "aacraid";
spin_unlock_irq(&io_request_lock);
/*
** 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);
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));
/* 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;
dev = NULL;
while((dev = pci_find_device(vendor_id, device_id, dev))) {
if (pci_enable_device(dev))
continue;
pci_set_master(dev);
/*
* 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);
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;
}
}
}
/* XXX SMH: restore lock and IPL for SCSI layer */
spin_lock_irq(&io_request_lock);
#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"));
struct diskparm *param = (struct diskparm *)geom;
#if 0
struct buffer_head * buf;
#endif
/*
* 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 */
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)
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))
{
end_head = first->end_head;
end_sec = first->end_sector & 0x3f;
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));
}
}
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
+291 -319
View File
@@ -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);
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);
}
}
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;
}
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))
{
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);
/*
* 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;
}
/*
* Restore interrupt mask even though we timed out
* 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 -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;
u32 status;
struct aac_init *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);
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;
}
// dprintk((KERN_ERR "aac_rx_init: XXX\n"));
#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);
#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;
#ifdef TRY_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
unsigned long start;
unsigned long status;
int instance;
const char * name;
/*
* Tell the adapter that all is configured, and it can start
* accepting requests
*/
aac_rx_start_adapter(dev);
return 0;
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;
}
/*
* 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);
#endif
}
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);
#else
/*
* 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;
}
+21 -17
View File
@@ -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
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.