Merge HEAD from ../scsi-misc-2.6-tmp
This commit is contained in:
commit
7a93aef7fb
72 changed files with 3837 additions and 8035 deletions
|
@ -1,5 +1,5 @@
|
|||
====================================================================
|
||||
= Adaptec Aic7xxx Fast -> Ultra160 Family Manager Set v6.2.28 =
|
||||
= Adaptec Aic7xxx Fast -> Ultra160 Family Manager Set v7.0 =
|
||||
= README for =
|
||||
= The Linux Operating System =
|
||||
====================================================================
|
||||
|
@ -131,6 +131,10 @@ The following information is available in this file:
|
|||
SCSI "stub" effects.
|
||||
|
||||
2. Version History
|
||||
7.0 (4th August, 2005)
|
||||
- Updated driver to use SCSI transport class infrastructure
|
||||
- Upported sequencer and core fixes from last adaptec released
|
||||
version of the driver.
|
||||
6.2.36 (June 3rd, 2003)
|
||||
- Correct code that disables PCI parity error checking.
|
||||
- Correct and simplify handling of the ignore wide residue
|
||||
|
|
|
@ -824,6 +824,13 @@ L: emu10k1-devel@lists.sourceforge.net
|
|||
W: http://sourceforge.net/projects/emu10k1/
|
||||
S: Maintained
|
||||
|
||||
EMULEX LPFC FC SCSI DRIVER
|
||||
P: James Smart
|
||||
M: james.smart@emulex.com
|
||||
L: linux-scsi@vger.kernel.org
|
||||
W: http://sourceforge.net/projects/lpfcxxxx
|
||||
S: Supported
|
||||
|
||||
EPSON 1355 FRAMEBUFFER DRIVER
|
||||
P: Christopher Hoover
|
||||
M: ch@murgatroid.com, ch@hpl.hp.com
|
||||
|
|
|
@ -58,6 +58,7 @@ attribute_container_register(struct attribute_container *cont)
|
|||
{
|
||||
INIT_LIST_HEAD(&cont->node);
|
||||
INIT_LIST_HEAD(&cont->containers);
|
||||
spin_lock_init(&cont->containers_lock);
|
||||
|
||||
down(&attribute_container_mutex);
|
||||
list_add_tail(&cont->node, &attribute_container_list);
|
||||
|
@ -77,11 +78,13 @@ attribute_container_unregister(struct attribute_container *cont)
|
|||
{
|
||||
int retval = -EBUSY;
|
||||
down(&attribute_container_mutex);
|
||||
spin_lock(&cont->containers_lock);
|
||||
if (!list_empty(&cont->containers))
|
||||
goto out;
|
||||
retval = 0;
|
||||
list_del(&cont->node);
|
||||
out:
|
||||
spin_unlock(&cont->containers_lock);
|
||||
up(&attribute_container_mutex);
|
||||
return retval;
|
||||
|
||||
|
@ -151,7 +154,9 @@ attribute_container_add_device(struct device *dev,
|
|||
fn(cont, dev, &ic->classdev);
|
||||
else
|
||||
attribute_container_add_class_device(&ic->classdev);
|
||||
spin_lock(&cont->containers_lock);
|
||||
list_add_tail(&ic->node, &cont->containers);
|
||||
spin_unlock(&cont->containers_lock);
|
||||
}
|
||||
up(&attribute_container_mutex);
|
||||
}
|
||||
|
@ -189,6 +194,7 @@ attribute_container_remove_device(struct device *dev,
|
|||
|
||||
if (!cont->match(cont, dev))
|
||||
continue;
|
||||
spin_lock(&cont->containers_lock);
|
||||
list_for_each_entry_safe(ic, tmp, &cont->containers, node) {
|
||||
if (dev != ic->classdev.dev)
|
||||
continue;
|
||||
|
@ -200,6 +206,7 @@ attribute_container_remove_device(struct device *dev,
|
|||
class_device_unregister(&ic->classdev);
|
||||
}
|
||||
}
|
||||
spin_unlock(&cont->containers_lock);
|
||||
}
|
||||
up(&attribute_container_mutex);
|
||||
}
|
||||
|
@ -230,10 +237,17 @@ attribute_container_device_trigger(struct device *dev,
|
|||
if (!cont->match(cont, dev))
|
||||
continue;
|
||||
|
||||
if (attribute_container_no_classdevs(cont)) {
|
||||
fn(cont, dev, NULL);
|
||||
continue;
|
||||
}
|
||||
|
||||
spin_lock(&cont->containers_lock);
|
||||
list_for_each_entry_safe(ic, tmp, &cont->containers, node) {
|
||||
if (dev == ic->classdev.dev)
|
||||
fn(cont, dev, &ic->classdev);
|
||||
}
|
||||
spin_unlock(&cont->containers_lock);
|
||||
}
|
||||
up(&attribute_container_mutex);
|
||||
}
|
||||
|
@ -368,6 +382,35 @@ attribute_container_class_device_del(struct class_device *classdev)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(attribute_container_class_device_del);
|
||||
|
||||
/**
|
||||
* attribute_container_find_class_device - find the corresponding class_device
|
||||
*
|
||||
* @cont: the container
|
||||
* @dev: the generic device
|
||||
*
|
||||
* Looks up the device in the container's list of class devices and returns
|
||||
* the corresponding class_device.
|
||||
*/
|
||||
struct class_device *
|
||||
attribute_container_find_class_device(struct attribute_container *cont,
|
||||
struct device *dev)
|
||||
{
|
||||
struct class_device *cdev = NULL;
|
||||
struct internal_container *ic;
|
||||
|
||||
spin_lock(&cont->containers_lock);
|
||||
list_for_each_entry(ic, &cont->containers, node) {
|
||||
if (ic->classdev.dev == dev) {
|
||||
cdev = &ic->classdev;
|
||||
break;
|
||||
}
|
||||
}
|
||||
spin_unlock(&cont->containers_lock);
|
||||
|
||||
return cdev;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(attribute_container_find_class_device);
|
||||
|
||||
int __init
|
||||
attribute_container_init(void)
|
||||
{
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
* This file is licensed under GPLv2
|
||||
*
|
||||
* The basic idea here is to allow any "device controller" (which
|
||||
* would most often be a Host Bus Adapter" to use the services of one
|
||||
* would most often be a Host Bus Adapter to use the services of one
|
||||
* or more tranport classes for performing transport specific
|
||||
* services. Transport specific services are things that the generic
|
||||
* command layer doesn't want to know about (speed settings, line
|
||||
|
@ -64,7 +64,9 @@ void transport_class_unregister(struct transport_class *tclass)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(transport_class_unregister);
|
||||
|
||||
static int anon_transport_dummy_function(struct device *dev)
|
||||
static int anon_transport_dummy_function(struct transport_container *tc,
|
||||
struct device *dev,
|
||||
struct class_device *cdev)
|
||||
{
|
||||
/* do nothing */
|
||||
return 0;
|
||||
|
@ -115,9 +117,10 @@ static int transport_setup_classdev(struct attribute_container *cont,
|
|||
struct class_device *classdev)
|
||||
{
|
||||
struct transport_class *tclass = class_to_transport_class(cont->class);
|
||||
struct transport_container *tcont = attribute_container_to_transport_container(cont);
|
||||
|
||||
if (tclass->setup)
|
||||
tclass->setup(dev);
|
||||
tclass->setup(tcont, dev, classdev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -178,12 +181,14 @@ void transport_add_device(struct device *dev)
|
|||
EXPORT_SYMBOL_GPL(transport_add_device);
|
||||
|
||||
static int transport_configure(struct attribute_container *cont,
|
||||
struct device *dev)
|
||||
struct device *dev,
|
||||
struct class_device *cdev)
|
||||
{
|
||||
struct transport_class *tclass = class_to_transport_class(cont->class);
|
||||
struct transport_container *tcont = attribute_container_to_transport_container(cont);
|
||||
|
||||
if (tclass->configure)
|
||||
tclass->configure(dev);
|
||||
tclass->configure(tcont, dev, cdev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -202,7 +207,7 @@ static int transport_configure(struct attribute_container *cont,
|
|||
*/
|
||||
void transport_configure_device(struct device *dev)
|
||||
{
|
||||
attribute_container_trigger(dev, transport_configure);
|
||||
attribute_container_device_trigger(dev, transport_configure);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(transport_configure_device);
|
||||
|
||||
|
@ -215,7 +220,7 @@ static int transport_remove_classdev(struct attribute_container *cont,
|
|||
struct transport_class *tclass = class_to_transport_class(cont->class);
|
||||
|
||||
if (tclass->remove)
|
||||
tclass->remove(dev);
|
||||
tclass->remove(tcont, dev, classdev);
|
||||
|
||||
if (tclass->remove != anon_transport_dummy_function) {
|
||||
if (tcont->statistics)
|
||||
|
|
|
@ -133,6 +133,7 @@ struct inquiry_data {
|
|||
|
||||
static unsigned long aac_build_sg(struct scsi_cmnd* scsicmd, struct sgmap* sgmap);
|
||||
static unsigned long aac_build_sg64(struct scsi_cmnd* scsicmd, struct sgmap64* psg);
|
||||
static unsigned long aac_build_sgraw(struct scsi_cmnd* scsicmd, struct sgmapraw* psg);
|
||||
static int aac_send_srb_fib(struct scsi_cmnd* scsicmd);
|
||||
#ifdef AAC_DETAILED_STATUS_INFO
|
||||
static char *aac_get_status_string(u32 status);
|
||||
|
@ -348,6 +349,27 @@ static void aac_io_done(struct scsi_cmnd * scsicmd)
|
|||
spin_unlock_irqrestore(host->host_lock, cpu_flags);
|
||||
}
|
||||
|
||||
static void aac_internal_transfer(struct scsi_cmnd *scsicmd, void *data, unsigned int offset, unsigned int len)
|
||||
{
|
||||
void *buf;
|
||||
unsigned int transfer_len;
|
||||
struct scatterlist *sg = scsicmd->request_buffer;
|
||||
|
||||
if (scsicmd->use_sg) {
|
||||
buf = kmap_atomic(sg->page, KM_IRQ0) + sg->offset;
|
||||
transfer_len = min(sg->length, len + offset);
|
||||
} else {
|
||||
buf = scsicmd->request_buffer;
|
||||
transfer_len = min(scsicmd->request_bufflen, len + offset);
|
||||
}
|
||||
|
||||
memcpy(buf + offset, data, transfer_len - offset);
|
||||
|
||||
if (scsicmd->use_sg)
|
||||
kunmap_atomic(buf - sg->offset, KM_IRQ0);
|
||||
|
||||
}
|
||||
|
||||
static void get_container_name_callback(void *context, struct fib * fibptr)
|
||||
{
|
||||
struct aac_get_name_resp * get_name_reply;
|
||||
|
@ -363,18 +385,22 @@ static void get_container_name_callback(void *context, struct fib * fibptr)
|
|||
/* Failure is irrelevant, using default value instead */
|
||||
if ((le32_to_cpu(get_name_reply->status) == CT_OK)
|
||||
&& (get_name_reply->data[0] != '\0')) {
|
||||
int count;
|
||||
char * dp;
|
||||
char * sp = get_name_reply->data;
|
||||
char *sp = get_name_reply->data;
|
||||
sp[sizeof(((struct aac_get_name_resp *)NULL)->data)-1] = '\0';
|
||||
while (*sp == ' ')
|
||||
++sp;
|
||||
count = sizeof(((struct inquiry_data *)NULL)->inqd_pid);
|
||||
dp = ((struct inquiry_data *)scsicmd->request_buffer)->inqd_pid;
|
||||
if (*sp) do {
|
||||
if (*sp) {
|
||||
char d[sizeof(((struct inquiry_data *)NULL)->inqd_pid)];
|
||||
int count = sizeof(d);
|
||||
char *dp = d;
|
||||
do {
|
||||
*dp++ = (*sp) ? *sp++ : ' ';
|
||||
} while (--count > 0);
|
||||
aac_internal_transfer(scsicmd, d,
|
||||
offsetof(struct inquiry_data, inqd_pid), sizeof(d));
|
||||
}
|
||||
}
|
||||
|
||||
scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;
|
||||
|
||||
fib_complete(fibptr);
|
||||
|
@ -777,6 +803,7 @@ int aac_get_adapter_info(struct aac_dev* dev)
|
|||
/*
|
||||
* 57 scatter gather elements
|
||||
*/
|
||||
if (!(dev->raw_io_interface)) {
|
||||
dev->scsi_host_ptr->sg_tablesize = (dev->max_fib_size -
|
||||
sizeof(struct aac_fibhdr) -
|
||||
sizeof(struct aac_write) + sizeof(struct sgmap)) /
|
||||
|
@ -806,6 +833,7 @@ int aac_get_adapter_info(struct aac_dev* dev)
|
|||
dev->scsi_host_ptr->max_sectors =
|
||||
(dev->scsi_host_ptr->sg_tablesize * 8) + 112;
|
||||
}
|
||||
}
|
||||
|
||||
fib_complete(fibptr);
|
||||
fib_free(fibptr);
|
||||
|
@ -814,12 +842,11 @@ int aac_get_adapter_info(struct aac_dev* dev)
|
|||
}
|
||||
|
||||
|
||||
static void read_callback(void *context, struct fib * fibptr)
|
||||
static void io_callback(void *context, struct fib * fibptr)
|
||||
{
|
||||
struct aac_dev *dev;
|
||||
struct aac_read_reply *readreply;
|
||||
struct scsi_cmnd *scsicmd;
|
||||
u32 lba;
|
||||
u32 cid;
|
||||
|
||||
scsicmd = (struct scsi_cmnd *) context;
|
||||
|
@ -827,8 +854,7 @@ static void read_callback(void *context, struct fib * fibptr)
|
|||
dev = (struct aac_dev *)scsicmd->device->host->hostdata;
|
||||
cid = ID_LUN_TO_CONTAINER(scsicmd->device->id, scsicmd->device->lun);
|
||||
|
||||
lba = ((scsicmd->cmnd[1] & 0x1F) << 16) | (scsicmd->cmnd[2] << 8) | scsicmd->cmnd[3];
|
||||
dprintk((KERN_DEBUG "read_callback[cpu %d]: lba = %u, t = %ld.\n", smp_processor_id(), lba, jiffies));
|
||||
dprintk((KERN_DEBUG "io_callback[cpu %d]: lba = %u, t = %ld.\n", smp_processor_id(), ((scsicmd->cmnd[1] & 0x1F) << 16) | (scsicmd->cmnd[2] << 8) | scsicmd->cmnd[3], jiffies));
|
||||
|
||||
if (fibptr == NULL)
|
||||
BUG();
|
||||
|
@ -847,7 +873,7 @@ static void read_callback(void *context, struct fib * fibptr)
|
|||
scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;
|
||||
else {
|
||||
#ifdef AAC_DETAILED_STATUS_INFO
|
||||
printk(KERN_WARNING "read_callback: io failed, status = %d\n",
|
||||
printk(KERN_WARNING "io_callback: io failed, status = %d\n",
|
||||
le32_to_cpu(readreply->status));
|
||||
#endif
|
||||
scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_CHECK_CONDITION;
|
||||
|
@ -867,53 +893,6 @@ static void read_callback(void *context, struct fib * fibptr)
|
|||
aac_io_done(scsicmd);
|
||||
}
|
||||
|
||||
static void write_callback(void *context, struct fib * fibptr)
|
||||
{
|
||||
struct aac_dev *dev;
|
||||
struct aac_write_reply *writereply;
|
||||
struct scsi_cmnd *scsicmd;
|
||||
u32 lba;
|
||||
u32 cid;
|
||||
|
||||
scsicmd = (struct scsi_cmnd *) context;
|
||||
dev = (struct aac_dev *)scsicmd->device->host->hostdata;
|
||||
cid = ID_LUN_TO_CONTAINER(scsicmd->device->id, scsicmd->device->lun);
|
||||
|
||||
lba = ((scsicmd->cmnd[1] & 0x1F) << 16) | (scsicmd->cmnd[2] << 8) | scsicmd->cmnd[3];
|
||||
dprintk((KERN_DEBUG "write_callback[cpu %d]: lba = %u, t = %ld.\n", smp_processor_id(), lba, jiffies));
|
||||
if (fibptr == NULL)
|
||||
BUG();
|
||||
|
||||
if(scsicmd->use_sg)
|
||||
pci_unmap_sg(dev->pdev,
|
||||
(struct scatterlist *)scsicmd->buffer,
|
||||
scsicmd->use_sg,
|
||||
scsicmd->sc_data_direction);
|
||||
else if(scsicmd->request_bufflen)
|
||||
pci_unmap_single(dev->pdev, scsicmd->SCp.dma_handle,
|
||||
scsicmd->request_bufflen,
|
||||
scsicmd->sc_data_direction);
|
||||
|
||||
writereply = (struct aac_write_reply *) fib_data(fibptr);
|
||||
if (le32_to_cpu(writereply->status) == ST_OK)
|
||||
scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;
|
||||
else {
|
||||
printk(KERN_WARNING "write_callback: write failed, status = %d\n", writereply->status);
|
||||
scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_CHECK_CONDITION;
|
||||
set_sense((u8 *) &dev->fsa_dev[cid].sense_data,
|
||||
HARDWARE_ERROR,
|
||||
SENCODE_INTERNAL_TARGET_FAILURE,
|
||||
ASENCODE_INTERNAL_TARGET_FAILURE, 0, 0,
|
||||
0, 0);
|
||||
memcpy(scsicmd->sense_buffer, &dev->fsa_dev[cid].sense_data,
|
||||
sizeof(struct sense_data));
|
||||
}
|
||||
|
||||
fib_complete(fibptr);
|
||||
fib_free(fibptr);
|
||||
aac_io_done(scsicmd);
|
||||
}
|
||||
|
||||
static int aac_read(struct scsi_cmnd * scsicmd, int cid)
|
||||
{
|
||||
u32 lba;
|
||||
|
@ -954,7 +933,32 @@ static int aac_read(struct scsi_cmnd * scsicmd, int cid)
|
|||
|
||||
fib_init(cmd_fibcontext);
|
||||
|
||||
if (dev->dac_support == 1) {
|
||||
if (dev->raw_io_interface) {
|
||||
struct aac_raw_io *readcmd;
|
||||
readcmd = (struct aac_raw_io *) fib_data(cmd_fibcontext);
|
||||
readcmd->block[0] = cpu_to_le32(lba);
|
||||
readcmd->block[1] = 0;
|
||||
readcmd->count = cpu_to_le32(count<<9);
|
||||
readcmd->cid = cpu_to_le16(cid);
|
||||
readcmd->flags = cpu_to_le16(1);
|
||||
readcmd->bpTotal = 0;
|
||||
readcmd->bpComplete = 0;
|
||||
|
||||
aac_build_sgraw(scsicmd, &readcmd->sg);
|
||||
fibsize = sizeof(struct aac_raw_io) + ((le32_to_cpu(readcmd->sg.count) - 1) * sizeof (struct sgentryraw));
|
||||
if (fibsize > (dev->max_fib_size - sizeof(struct aac_fibhdr)))
|
||||
BUG();
|
||||
/*
|
||||
* Now send the Fib to the adapter
|
||||
*/
|
||||
status = fib_send(ContainerRawIo,
|
||||
cmd_fibcontext,
|
||||
fibsize,
|
||||
FsaNormal,
|
||||
0, 1,
|
||||
(fib_callback) io_callback,
|
||||
(void *) scsicmd);
|
||||
} else if (dev->dac_support == 1) {
|
||||
struct aac_read64 *readcmd;
|
||||
readcmd = (struct aac_read64 *) fib_data(cmd_fibcontext);
|
||||
readcmd->command = cpu_to_le32(VM_CtHostRead64);
|
||||
|
@ -978,7 +982,7 @@ static int aac_read(struct scsi_cmnd * scsicmd, int cid)
|
|||
fibsize,
|
||||
FsaNormal,
|
||||
0, 1,
|
||||
(fib_callback) read_callback,
|
||||
(fib_callback) io_callback,
|
||||
(void *) scsicmd);
|
||||
} else {
|
||||
struct aac_read *readcmd;
|
||||
|
@ -1002,7 +1006,7 @@ static int aac_read(struct scsi_cmnd * scsicmd, int cid)
|
|||
fibsize,
|
||||
FsaNormal,
|
||||
0, 1,
|
||||
(fib_callback) read_callback,
|
||||
(fib_callback) io_callback,
|
||||
(void *) scsicmd);
|
||||
}
|
||||
|
||||
|
@ -1061,7 +1065,32 @@ static int aac_write(struct scsi_cmnd * scsicmd, int cid)
|
|||
}
|
||||
fib_init(cmd_fibcontext);
|
||||
|
||||
if(dev->dac_support == 1) {
|
||||
if (dev->raw_io_interface) {
|
||||
struct aac_raw_io *writecmd;
|
||||
writecmd = (struct aac_raw_io *) fib_data(cmd_fibcontext);
|
||||
writecmd->block[0] = cpu_to_le32(lba);
|
||||
writecmd->block[1] = 0;
|
||||
writecmd->count = cpu_to_le32(count<<9);
|
||||
writecmd->cid = cpu_to_le16(cid);
|
||||
writecmd->flags = 0;
|
||||
writecmd->bpTotal = 0;
|
||||
writecmd->bpComplete = 0;
|
||||
|
||||
aac_build_sgraw(scsicmd, &writecmd->sg);
|
||||
fibsize = sizeof(struct aac_raw_io) + ((le32_to_cpu(writecmd->sg.count) - 1) * sizeof (struct sgentryraw));
|
||||
if (fibsize > (dev->max_fib_size - sizeof(struct aac_fibhdr)))
|
||||
BUG();
|
||||
/*
|
||||
* Now send the Fib to the adapter
|
||||
*/
|
||||
status = fib_send(ContainerRawIo,
|
||||
cmd_fibcontext,
|
||||
fibsize,
|
||||
FsaNormal,
|
||||
0, 1,
|
||||
(fib_callback) io_callback,
|
||||
(void *) scsicmd);
|
||||
} else if (dev->dac_support == 1) {
|
||||
struct aac_write64 *writecmd;
|
||||
writecmd = (struct aac_write64 *) fib_data(cmd_fibcontext);
|
||||
writecmd->command = cpu_to_le32(VM_CtHostWrite64);
|
||||
|
@ -1085,7 +1114,7 @@ static int aac_write(struct scsi_cmnd * scsicmd, int cid)
|
|||
fibsize,
|
||||
FsaNormal,
|
||||
0, 1,
|
||||
(fib_callback) write_callback,
|
||||
(fib_callback) io_callback,
|
||||
(void *) scsicmd);
|
||||
} else {
|
||||
struct aac_write *writecmd;
|
||||
|
@ -1111,7 +1140,7 @@ static int aac_write(struct scsi_cmnd * scsicmd, int cid)
|
|||
fibsize,
|
||||
FsaNormal,
|
||||
0, 1,
|
||||
(fib_callback) write_callback,
|
||||
(fib_callback) io_callback,
|
||||
(void *) scsicmd);
|
||||
}
|
||||
|
||||
|
@ -1340,44 +1369,45 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
|
|||
switch (scsicmd->cmnd[0]) {
|
||||
case INQUIRY:
|
||||
{
|
||||
struct inquiry_data *inq_data_ptr;
|
||||
struct inquiry_data inq_data;
|
||||
|
||||
dprintk((KERN_DEBUG "INQUIRY command, ID: %d.\n", scsicmd->device->id));
|
||||
inq_data_ptr = (struct inquiry_data *)scsicmd->request_buffer;
|
||||
memset(inq_data_ptr, 0, sizeof (struct inquiry_data));
|
||||
memset(&inq_data, 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;
|
||||
inq_data.inqd_ver = 2; /* claim compliance to SCSI-2 */
|
||||
inq_data.inqd_dtq = 0x80; /* set RMB bit to one indicating that the medium is removable */
|
||||
inq_data.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.inqd_len = 31;
|
||||
/*Format for "pad2" is RelAdr | WBus32 | WBus16 | Sync | Linked |Reserved| CmdQue | SftRe */
|
||||
inq_data_ptr->inqd_pad2= 0x32 ; /*WBus16|Sync|CmdQue */
|
||||
inq_data.inqd_pad2= 0x32 ; /*WBus16|Sync|CmdQue */
|
||||
/*
|
||||
* Set the Vendor, Product, and Revision Level
|
||||
* see: <vendor>.c i.e. aac.c
|
||||
*/
|
||||
if (scsicmd->device->id == host->this_id) {
|
||||
setinqstr(cardtype, (void *) (inq_data_ptr->inqd_vid), (sizeof(container_types)/sizeof(char *)));
|
||||
inq_data_ptr->inqd_pdt = INQD_PDT_PROC; /* Processor device */
|
||||
setinqstr(cardtype, (void *) (inq_data.inqd_vid), (sizeof(container_types)/sizeof(char *)));
|
||||
inq_data.inqd_pdt = INQD_PDT_PROC; /* Processor device */
|
||||
aac_internal_transfer(scsicmd, &inq_data, 0, sizeof(inq_data));
|
||||
scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;
|
||||
scsicmd->scsi_done(scsicmd);
|
||||
return 0;
|
||||
}
|
||||
setinqstr(cardtype, (void *) (inq_data_ptr->inqd_vid), fsa_dev_ptr[cid].type);
|
||||
inq_data_ptr->inqd_pdt = INQD_PDT_DA; /* Direct/random access device */
|
||||
setinqstr(cardtype, (void *) (inq_data.inqd_vid), fsa_dev_ptr[cid].type);
|
||||
inq_data.inqd_pdt = INQD_PDT_DA; /* Direct/random access device */
|
||||
aac_internal_transfer(scsicmd, &inq_data, 0, sizeof(inq_data));
|
||||
return aac_get_container_name(scsicmd, cid);
|
||||
}
|
||||
case READ_CAPACITY:
|
||||
{
|
||||
u32 capacity;
|
||||
char *cp;
|
||||
char cp[8];
|
||||
|
||||
dprintk((KERN_DEBUG "READ CAPACITY command.\n"));
|
||||
if (fsa_dev_ptr[cid].size <= 0x100000000LL)
|
||||
capacity = fsa_dev_ptr[cid].size - 1;
|
||||
else
|
||||
capacity = (u32)-1;
|
||||
cp = scsicmd->request_buffer;
|
||||
|
||||
cp[0] = (capacity >> 24) & 0xff;
|
||||
cp[1] = (capacity >> 16) & 0xff;
|
||||
cp[2] = (capacity >> 8) & 0xff;
|
||||
|
@ -1386,6 +1416,7 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
|
|||
cp[5] = 0;
|
||||
cp[6] = 2;
|
||||
cp[7] = 0;
|
||||
aac_internal_transfer(scsicmd, cp, 0, sizeof(cp));
|
||||
|
||||
scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;
|
||||
scsicmd->scsi_done(scsicmd);
|
||||
|
@ -1395,15 +1426,15 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
|
|||
|
||||
case MODE_SENSE:
|
||||
{
|
||||
char *mode_buf;
|
||||
char mode_buf[4];
|
||||
|
||||
dprintk((KERN_DEBUG "MODE SENSE command.\n"));
|
||||
mode_buf = scsicmd->request_buffer;
|
||||
mode_buf[0] = 3; /* Mode data length */
|
||||
mode_buf[1] = 0; /* Medium type - default */
|
||||
mode_buf[2] = 0; /* Device-specific param, bit 8: 0/1 = write enabled/protected */
|
||||
mode_buf[3] = 0; /* Block descriptor length */
|
||||
|
||||
aac_internal_transfer(scsicmd, mode_buf, 0, sizeof(mode_buf));
|
||||
scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;
|
||||
scsicmd->scsi_done(scsicmd);
|
||||
|
||||
|
@ -1411,10 +1442,9 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
|
|||
}
|
||||
case MODE_SENSE_10:
|
||||
{
|
||||
char *mode_buf;
|
||||
char mode_buf[8];
|
||||
|
||||
dprintk((KERN_DEBUG "MODE SENSE 10 byte 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 */
|
||||
|
@ -1423,6 +1453,7 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
|
|||
mode_buf[5] = 0; /* reserved */
|
||||
mode_buf[6] = 0; /* Block descriptor length (MSB) */
|
||||
mode_buf[7] = 0; /* Block descriptor length (LSB) */
|
||||
aac_internal_transfer(scsicmd, mode_buf, 0, sizeof(mode_buf));
|
||||
|
||||
scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;
|
||||
scsicmd->scsi_done(scsicmd);
|
||||
|
@ -1894,7 +1925,7 @@ static int aac_send_srb_fib(struct scsi_cmnd* scsicmd)
|
|||
srbcmd->id = cpu_to_le32(scsicmd->device->id);
|
||||
srbcmd->lun = cpu_to_le32(scsicmd->device->lun);
|
||||
srbcmd->flags = cpu_to_le32(flag);
|
||||
timeout = (scsicmd->timeout-jiffies)/HZ;
|
||||
timeout = scsicmd->timeout_per_command/HZ;
|
||||
if(timeout == 0){
|
||||
timeout = 1;
|
||||
}
|
||||
|
@ -2077,6 +2108,76 @@ static unsigned long aac_build_sg64(struct scsi_cmnd* scsicmd, struct sgmap64* p
|
|||
return byte_count;
|
||||
}
|
||||
|
||||
static unsigned long aac_build_sgraw(struct scsi_cmnd* scsicmd, struct sgmapraw* psg)
|
||||
{
|
||||
struct Scsi_Host *host = scsicmd->device->host;
|
||||
struct aac_dev *dev = (struct aac_dev *)host->hostdata;
|
||||
unsigned long byte_count = 0;
|
||||
|
||||
// Get rid of old data
|
||||
psg->count = 0;
|
||||
psg->sg[0].next = 0;
|
||||
psg->sg[0].prev = 0;
|
||||
psg->sg[0].addr[0] = 0;
|
||||
psg->sg[0].addr[1] = 0;
|
||||
psg->sg[0].count = 0;
|
||||
psg->sg[0].flags = 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,
|
||||
scsicmd->sc_data_direction);
|
||||
|
||||
for (i = 0; i < sg_count; i++) {
|
||||
int count = sg_dma_len(sg);
|
||||
u64 addr = sg_dma_address(sg);
|
||||
psg->sg[i].next = 0;
|
||||
psg->sg[i].prev = 0;
|
||||
psg->sg[i].addr[1] = cpu_to_le32((u32)(addr>>32));
|
||||
psg->sg[i].addr[0] = cpu_to_le32((u32)(addr & 0xffffffff));
|
||||
psg->sg[i].count = cpu_to_le32(count);
|
||||
psg->sg[i].flags = 0;
|
||||
byte_count += count;
|
||||
sg++;
|
||||
}
|
||||
psg->count = cpu_to_le32(sg_count);
|
||||
/* hba wants the size to be exact */
|
||||
if(byte_count > scsicmd->request_bufflen){
|
||||
u32 temp = le32_to_cpu(psg->sg[i-1].count) -
|
||||
(byte_count - scsicmd->request_bufflen);
|
||||
psg->sg[i-1].count = cpu_to_le32(temp);
|
||||
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);
|
||||
}
|
||||
}
|
||||
else if(scsicmd->request_bufflen) {
|
||||
int count;
|
||||
u64 addr;
|
||||
scsicmd->SCp.dma_handle = pci_map_single(dev->pdev,
|
||||
scsicmd->request_buffer,
|
||||
scsicmd->request_bufflen,
|
||||
scsicmd->sc_data_direction);
|
||||
addr = scsicmd->SCp.dma_handle;
|
||||
count = scsicmd->request_bufflen;
|
||||
psg->count = cpu_to_le32(1);
|
||||
psg->sg[0].next = 0;
|
||||
psg->sg[0].prev = 0;
|
||||
psg->sg[0].addr[1] = cpu_to_le32((u32)(addr>>32));
|
||||
psg->sg[0].addr[0] = cpu_to_le32((u32)(addr & 0xffffffff));
|
||||
psg->sg[0].count = cpu_to_le32(count);
|
||||
psg->sg[0].flags = 0;
|
||||
byte_count = scsicmd->request_bufflen;
|
||||
}
|
||||
return byte_count;
|
||||
}
|
||||
|
||||
#ifdef AAC_DETAILED_STATUS_INFO
|
||||
|
||||
struct aac_srb_status_info {
|
||||
|
|
|
@ -110,6 +110,22 @@ struct user_sgentry64 {
|
|||
u32 count; /* Length. */
|
||||
};
|
||||
|
||||
struct sgentryraw {
|
||||
__le32 next; /* reserved for F/W use */
|
||||
__le32 prev; /* reserved for F/W use */
|
||||
__le32 addr[2];
|
||||
__le32 count;
|
||||
__le32 flags; /* reserved for F/W use */
|
||||
};
|
||||
|
||||
struct user_sgentryraw {
|
||||
u32 next; /* reserved for F/W use */
|
||||
u32 prev; /* reserved for F/W use */
|
||||
u32 addr[2];
|
||||
u32 count;
|
||||
u32 flags; /* reserved for F/W use */
|
||||
};
|
||||
|
||||
/*
|
||||
* SGMAP
|
||||
*
|
||||
|
@ -137,6 +153,16 @@ struct user_sgmap64 {
|
|||
struct user_sgentry64 sg[1];
|
||||
};
|
||||
|
||||
struct sgmapraw {
|
||||
__le32 count;
|
||||
struct sgentryraw sg[1];
|
||||
};
|
||||
|
||||
struct user_sgmapraw {
|
||||
u32 count;
|
||||
struct user_sgentryraw sg[1];
|
||||
};
|
||||
|
||||
struct creation_info
|
||||
{
|
||||
u8 buildnum; /* e.g., 588 */
|
||||
|
@ -351,6 +377,7 @@ struct hw_fib {
|
|||
*/
|
||||
#define ContainerCommand 500
|
||||
#define ContainerCommand64 501
|
||||
#define ContainerRawIo 502
|
||||
/*
|
||||
* Cluster Commands
|
||||
*/
|
||||
|
@ -456,6 +483,7 @@ struct adapter_ops
|
|||
{
|
||||
void (*adapter_interrupt)(struct aac_dev *dev);
|
||||
void (*adapter_notify)(struct aac_dev *dev, u32 event);
|
||||
void (*adapter_disable_int)(struct aac_dev *dev);
|
||||
int (*adapter_sync_cmd)(struct aac_dev *dev, u32 command, u32 p1, u32 p2, u32 p3, u32 p4, u32 p5, u32 p6, u32 *status, u32 *r1, u32 *r2, u32 *r3, u32 *r4);
|
||||
int (*adapter_check_health)(struct aac_dev *dev);
|
||||
};
|
||||
|
@ -981,6 +1009,9 @@ struct aac_dev
|
|||
u8 nondasd_support;
|
||||
u8 dac_support;
|
||||
u8 raid_scsi_mode;
|
||||
/* macro side-effects BEWARE */
|
||||
# define raw_io_interface \
|
||||
init->InitStructRevision==cpu_to_le32(ADAPTER_INIT_STRUCT_REVISION_4)
|
||||
u8 printf_enabled;
|
||||
};
|
||||
|
||||
|
@ -990,6 +1021,9 @@ struct aac_dev
|
|||
#define aac_adapter_notify(dev, event) \
|
||||
(dev)->a_ops.adapter_notify(dev, event)
|
||||
|
||||
#define aac_adapter_disable_int(dev) \
|
||||
(dev)->a_ops.adapter_disable_int(dev)
|
||||
|
||||
#define aac_adapter_sync_cmd(dev, command, p1, p2, p3, p4, p5, p6, status, r1, r2, r3, r4) \
|
||||
(dev)->a_ops.adapter_sync_cmd(dev, command, p1, p2, p3, p4, p5, p6, status, r1, r2, r3, r4)
|
||||
|
||||
|
@ -1156,6 +1190,17 @@ struct aac_write_reply
|
|||
__le32 committed;
|
||||
};
|
||||
|
||||
struct aac_raw_io
|
||||
{
|
||||
__le32 block[2];
|
||||
__le32 count;
|
||||
__le16 cid;
|
||||
__le16 flags; /* 00 W, 01 R */
|
||||
__le16 bpTotal; /* reserved for F/W use */
|
||||
__le16 bpComplete; /* reserved for F/W use */
|
||||
struct sgmapraw sg;
|
||||
};
|
||||
|
||||
#define CT_FLUSH_CACHE 129
|
||||
struct aac_synchronize {
|
||||
__le32 command; /* VM_ContainerConfig */
|
||||
|
@ -1196,7 +1241,7 @@ struct aac_srb
|
|||
};
|
||||
|
||||
/*
|
||||
* This and assocated data structs are used by the
|
||||
* This and associated data structs are used by the
|
||||
* ioctl caller and are in cpu order.
|
||||
*/
|
||||
struct user_aac_srb
|
||||
|
@ -1508,11 +1553,12 @@ struct fib_ioctl
|
|||
|
||||
struct revision
|
||||
{
|
||||
u32 compat;
|
||||
u32 version;
|
||||
u32 build;
|
||||
__le32 compat;
|
||||
__le32 version;
|
||||
__le32 build;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Ugly - non Linux like ioctl coding for back compat.
|
||||
*/
|
||||
|
@ -1733,3 +1779,4 @@ int aac_get_adapter_info(struct aac_dev* dev);
|
|||
int aac_send_shutdown(struct aac_dev *dev);
|
||||
extern int numacb;
|
||||
extern int acbsize;
|
||||
extern char aac_driver_version[];
|
||||
|
|
|
@ -287,7 +287,6 @@ static int next_getadapter_fib(struct aac_dev * dev, void __user *arg)
|
|||
kfree(fib->hw_fib);
|
||||
kfree(fib);
|
||||
status = 0;
|
||||
fibctx->jiffies = jiffies/HZ;
|
||||
} else {
|
||||
spin_unlock_irqrestore(&dev->fib_lock, flags);
|
||||
if (f.wait) {
|
||||
|
@ -302,6 +301,7 @@ static int next_getadapter_fib(struct aac_dev * dev, void __user *arg)
|
|||
status = -EAGAIN;
|
||||
}
|
||||
}
|
||||
fibctx->jiffies = jiffies/HZ;
|
||||
return status;
|
||||
}
|
||||
|
||||
|
@ -405,10 +405,20 @@ static int close_getadapter_fib(struct aac_dev * dev, void __user *arg)
|
|||
static int check_revision(struct aac_dev *dev, void __user *arg)
|
||||
{
|
||||
struct revision response;
|
||||
char *driver_version = aac_driver_version;
|
||||
u32 version;
|
||||
|
||||
response.compat = 1;
|
||||
response.version = le32_to_cpu(dev->adapter_info.kernelrev);
|
||||
response.build = le32_to_cpu(dev->adapter_info.kernelbuild);
|
||||
response.compat = cpu_to_le32(1);
|
||||
version = (simple_strtol(driver_version,
|
||||
&driver_version, 10) << 24) | 0x00000400;
|
||||
version += simple_strtol(driver_version + 1, &driver_version, 10) << 16;
|
||||
version += simple_strtol(driver_version + 1, NULL, 10);
|
||||
response.version = cpu_to_le32(version);
|
||||
# if (defined(AAC_DRIVER_BUILD))
|
||||
response.build = cpu_to_le32(AAC_DRIVER_BUILD);
|
||||
# else
|
||||
response.build = cpu_to_le32(9999);
|
||||
# endif
|
||||
|
||||
if (copy_to_user(arg, &response, sizeof(response)))
|
||||
return -EFAULT;
|
||||
|
|
|
@ -44,7 +44,9 @@
|
|||
|
||||
#include "aacraid.h"
|
||||
|
||||
struct aac_common aac_config;
|
||||
struct aac_common aac_config = {
|
||||
.irq_mod = 1
|
||||
};
|
||||
|
||||
static int aac_alloc_comm(struct aac_dev *dev, void **commaddr, unsigned long commsize, unsigned long commalign)
|
||||
{
|
||||
|
|
|
@ -254,6 +254,7 @@ static 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;
|
||||
unsigned long idx;
|
||||
|
||||
/*
|
||||
* All of the queues wrap when they reach the end, so we check
|
||||
|
@ -264,9 +265,22 @@ static int aac_get_entry (struct aac_dev * dev, u32 qid, struct aac_entry **entr
|
|||
|
||||
q = &dev->queues->queue[qid];
|
||||
|
||||
*index = le32_to_cpu(*(q->headers.producer));
|
||||
if ((*index - 2) == le32_to_cpu(*(q->headers.consumer)))
|
||||
idx = *index = le32_to_cpu(*(q->headers.producer));
|
||||
/* Interrupt Moderation, only interrupt for first two entries */
|
||||
if (idx != le32_to_cpu(*(q->headers.consumer))) {
|
||||
if (--idx == 0) {
|
||||
if (qid == AdapHighCmdQueue)
|
||||
idx = ADAP_HIGH_CMD_ENTRIES;
|
||||
else if (qid == AdapNormCmdQueue)
|
||||
idx = ADAP_NORM_CMD_ENTRIES;
|
||||
else if (qid == AdapHighRespQueue)
|
||||
idx = ADAP_HIGH_RESP_ENTRIES;
|
||||
else if (qid == AdapNormRespQueue)
|
||||
idx = ADAP_NORM_RESP_ENTRIES;
|
||||
}
|
||||
if (idx != le32_to_cpu(*(q->headers.consumer)))
|
||||
*nonotify = 1;
|
||||
}
|
||||
|
||||
if (qid == AdapHighCmdQueue) {
|
||||
if (*index >= ADAP_HIGH_CMD_ENTRIES)
|
||||
|
|
|
@ -27,8 +27,11 @@
|
|||
* Abstract: Linux Driver entry module for Adaptec RAID Array Controller
|
||||
*/
|
||||
|
||||
#define AAC_DRIVER_VERSION "1.1.2-lk2"
|
||||
#define AAC_DRIVER_BUILD_DATE __DATE__
|
||||
#define AAC_DRIVER_VERSION "1.1-4"
|
||||
#ifndef AAC_DRIVER_BRANCH
|
||||
#define AAC_DRIVER_BRANCH ""
|
||||
#endif
|
||||
#define AAC_DRIVER_BUILD_DATE __DATE__ " " __TIME__
|
||||
#define AAC_DRIVERNAME "aacraid"
|
||||
|
||||
#include <linux/compat.h>
|
||||
|
@ -58,16 +61,24 @@
|
|||
|
||||
#include "aacraid.h"
|
||||
|
||||
#ifdef AAC_DRIVER_BUILD
|
||||
#define _str(x) #x
|
||||
#define str(x) _str(x)
|
||||
#define AAC_DRIVER_FULL_VERSION AAC_DRIVER_VERSION "[" str(AAC_DRIVER_BUILD) "]" AAC_DRIVER_BRANCH
|
||||
#else
|
||||
#define AAC_DRIVER_FULL_VERSION AAC_DRIVER_VERSION AAC_DRIVER_BRANCH " " AAC_DRIVER_BUILD_DATE
|
||||
#endif
|
||||
|
||||
MODULE_AUTHOR("Red Hat Inc and Adaptec");
|
||||
MODULE_DESCRIPTION("Dell PERC2, 2/Si, 3/Si, 3/Di, "
|
||||
"Adaptec Advanced Raid Products, "
|
||||
"and HP NetRAID-4M SCSI driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_VERSION(AAC_DRIVER_VERSION);
|
||||
MODULE_VERSION(AAC_DRIVER_FULL_VERSION);
|
||||
|
||||
static LIST_HEAD(aac_devices);
|
||||
static int aac_cfg_major = -1;
|
||||
char aac_driver_version[] = AAC_DRIVER_FULL_VERSION;
|
||||
|
||||
/*
|
||||
* Because of the way Linux names scsi devices, the order in this table has
|
||||
|
@ -109,36 +120,39 @@ static struct pci_device_id aac_pci_tbl[] = {
|
|||
{ 0x9005, 0x0286, 0x9005, 0x02a3, 0, 0, 29 }, /* ICP5085AU (Hurricane) */
|
||||
{ 0x9005, 0x0285, 0x9005, 0x02a4, 0, 0, 30 }, /* ICP9085LI (Marauder-X) */
|
||||
{ 0x9005, 0x0285, 0x9005, 0x02a5, 0, 0, 31 }, /* ICP5085BR (Marauder-E) */
|
||||
{ 0x9005, 0x0287, 0x9005, 0x0800, 0, 0, 32 }, /* Themisto Jupiter Platform */
|
||||
{ 0x9005, 0x0200, 0x9005, 0x0200, 0, 0, 32 }, /* Themisto Jupiter Platform */
|
||||
{ 0x9005, 0x0286, 0x9005, 0x0800, 0, 0, 33 }, /* Callisto Jupiter Platform */
|
||||
{ 0x9005, 0x0285, 0x9005, 0x028e, 0, 0, 34 }, /* ASR-2020SA SATA PCI-X ZCR (Skyhawk) */
|
||||
{ 0x9005, 0x0285, 0x9005, 0x028f, 0, 0, 35 }, /* ASR-2025SA SATA SO-DIMM PCI-X ZCR (Terminator) */
|
||||
{ 0x9005, 0x0285, 0x9005, 0x0290, 0, 0, 36 }, /* AAR-2410SA PCI SATA 4ch (Jaguar II) */
|
||||
{ 0x9005, 0x0285, 0x1028, 0x0291, 0, 0, 37 }, /* CERC SATA RAID 2 PCI SATA 6ch (DellCorsair) */
|
||||
{ 0x9005, 0x0285, 0x9005, 0x0292, 0, 0, 38 }, /* AAR-2810SA PCI SATA 8ch (Corsair-8) */
|
||||
{ 0x9005, 0x0285, 0x9005, 0x0293, 0, 0, 39 }, /* AAR-21610SA PCI SATA 16ch (Corsair-16) */
|
||||
{ 0x9005, 0x0285, 0x9005, 0x0294, 0, 0, 40 }, /* ESD SO-DIMM PCI-X SATA ZCR (Prowler) */
|
||||
{ 0x9005, 0x0285, 0x103C, 0x3227, 0, 0, 41 }, /* AAR-2610SA PCI SATA 6ch */
|
||||
{ 0x9005, 0x0285, 0x9005, 0x0296, 0, 0, 42 }, /* ASR-2240S (SabreExpress) */
|
||||
{ 0x9005, 0x0285, 0x9005, 0x0297, 0, 0, 43 }, /* ASR-4005SAS */
|
||||
{ 0x9005, 0x0285, 0x1014, 0x02F2, 0, 0, 44 }, /* IBM 8i (AvonPark) */
|
||||
{ 0x9005, 0x0285, 0x1014, 0x0312, 0, 0, 44 }, /* IBM 8i (AvonPark Lite) */
|
||||
{ 0x9005, 0x0285, 0x9005, 0x0298, 0, 0, 45 }, /* ASR-4000SAS (BlackBird) */
|
||||
{ 0x9005, 0x0285, 0x9005, 0x0299, 0, 0, 46 }, /* ASR-4800SAS (Marauder-X) */
|
||||
{ 0x9005, 0x0285, 0x9005, 0x029a, 0, 0, 47 }, /* ASR-4805SAS (Marauder-E) */
|
||||
{ 0x9005, 0x0286, 0x9005, 0x02a2, 0, 0, 48 }, /* ASR-4810SAS (Hurricane */
|
||||
{ 0x9005, 0x0286, 0x9005, 0x02a6, 0, 0, 32 }, /* ICP9067MA (Intruder-6) */
|
||||
{ 0x9005, 0x0287, 0x9005, 0x0800, 0, 0, 33 }, /* Themisto Jupiter Platform */
|
||||
{ 0x9005, 0x0200, 0x9005, 0x0200, 0, 0, 33 }, /* Themisto Jupiter Platform */
|
||||
{ 0x9005, 0x0286, 0x9005, 0x0800, 0, 0, 34 }, /* Callisto Jupiter Platform */
|
||||
{ 0x9005, 0x0285, 0x9005, 0x028e, 0, 0, 35 }, /* ASR-2020SA SATA PCI-X ZCR (Skyhawk) */
|
||||
{ 0x9005, 0x0285, 0x9005, 0x028f, 0, 0, 36 }, /* ASR-2025SA SATA SO-DIMM PCI-X ZCR (Terminator) */
|
||||
{ 0x9005, 0x0285, 0x9005, 0x0290, 0, 0, 37 }, /* AAR-2410SA PCI SATA 4ch (Jaguar II) */
|
||||
{ 0x9005, 0x0285, 0x1028, 0x0291, 0, 0, 38 }, /* CERC SATA RAID 2 PCI SATA 6ch (DellCorsair) */
|
||||
{ 0x9005, 0x0285, 0x9005, 0x0292, 0, 0, 39 }, /* AAR-2810SA PCI SATA 8ch (Corsair-8) */
|
||||
{ 0x9005, 0x0285, 0x9005, 0x0293, 0, 0, 40 }, /* AAR-21610SA PCI SATA 16ch (Corsair-16) */
|
||||
{ 0x9005, 0x0285, 0x9005, 0x0294, 0, 0, 41 }, /* ESD SO-DIMM PCI-X SATA ZCR (Prowler) */
|
||||
{ 0x9005, 0x0285, 0x103C, 0x3227, 0, 0, 42 }, /* AAR-2610SA PCI SATA 6ch */
|
||||
{ 0x9005, 0x0285, 0x9005, 0x0296, 0, 0, 43 }, /* ASR-2240S (SabreExpress) */
|
||||
{ 0x9005, 0x0285, 0x9005, 0x0297, 0, 0, 44 }, /* ASR-4005SAS */
|
||||
{ 0x9005, 0x0285, 0x1014, 0x02F2, 0, 0, 45 }, /* IBM 8i (AvonPark) */
|
||||
{ 0x9005, 0x0285, 0x1014, 0x0312, 0, 0, 45 }, /* IBM 8i (AvonPark Lite) */
|
||||
{ 0x9005, 0x0286, 0x1014, 0x9580, 0, 0, 46 }, /* IBM 8k/8k-l8 (Aurora) */
|
||||
{ 0x9005, 0x0286, 0x1014, 0x9540, 0, 0, 47 }, /* IBM 8k/8k-l4 (Aurora Lite) */
|
||||
{ 0x9005, 0x0285, 0x9005, 0x0298, 0, 0, 48 }, /* ASR-4000SAS (BlackBird) */
|
||||
{ 0x9005, 0x0285, 0x9005, 0x0299, 0, 0, 49 }, /* ASR-4800SAS (Marauder-X) */
|
||||
{ 0x9005, 0x0285, 0x9005, 0x029a, 0, 0, 50 }, /* ASR-4805SAS (Marauder-E) */
|
||||
{ 0x9005, 0x0286, 0x9005, 0x02a2, 0, 0, 51 }, /* ASR-4810SAS (Hurricane */
|
||||
|
||||
{ 0x9005, 0x0285, 0x1028, 0x0287, 0, 0, 49 }, /* Perc 320/DC*/
|
||||
{ 0x1011, 0x0046, 0x9005, 0x0365, 0, 0, 50 }, /* Adaptec 5400S (Mustang)*/
|
||||
{ 0x1011, 0x0046, 0x9005, 0x0364, 0, 0, 51 }, /* Adaptec 5400S (Mustang)*/
|
||||
{ 0x1011, 0x0046, 0x9005, 0x1364, 0, 0, 52 }, /* Dell PERC2/QC */
|
||||
{ 0x1011, 0x0046, 0x103c, 0x10c2, 0, 0, 53 }, /* HP NetRAID-4M */
|
||||
{ 0x9005, 0x0285, 0x1028, 0x0287, 0, 0, 52 }, /* Perc 320/DC*/
|
||||
{ 0x1011, 0x0046, 0x9005, 0x0365, 0, 0, 53 }, /* Adaptec 5400S (Mustang)*/
|
||||
{ 0x1011, 0x0046, 0x9005, 0x0364, 0, 0, 54 }, /* Adaptec 5400S (Mustang)*/
|
||||
{ 0x1011, 0x0046, 0x9005, 0x1364, 0, 0, 55 }, /* Dell PERC2/QC */
|
||||
{ 0x1011, 0x0046, 0x103c, 0x10c2, 0, 0, 56 }, /* HP NetRAID-4M */
|
||||
|
||||
{ 0x9005, 0x0285, 0x1028, PCI_ANY_ID, 0, 0, 54 }, /* Dell Catchall */
|
||||
{ 0x9005, 0x0285, 0x17aa, PCI_ANY_ID, 0, 0, 55 }, /* Legend Catchall */
|
||||
{ 0x9005, 0x0285, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 56 }, /* Adaptec Catch All */
|
||||
{ 0x9005, 0x0286, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 57 }, /* Adaptec Rocket Catch All */
|
||||
{ 0x9005, 0x0285, 0x1028, PCI_ANY_ID, 0, 0, 57 }, /* Dell Catchall */
|
||||
{ 0x9005, 0x0285, 0x17aa, PCI_ANY_ID, 0, 0, 58 }, /* Legend Catchall */
|
||||
{ 0x9005, 0x0285, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 59 }, /* Adaptec Catch All */
|
||||
{ 0x9005, 0x0286, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 60 }, /* Adaptec Rocket Catch All */
|
||||
{ 0,}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(pci, aac_pci_tbl);
|
||||
|
@ -180,8 +194,9 @@ static struct aac_driver_ident aac_drivers[] = {
|
|||
{ aac_rkt_init, "aacraid", "ICP ", "ICP9047MA ", 1 }, /* ICP9047MA (Lancer) */
|
||||
{ aac_rkt_init, "aacraid", "ICP ", "ICP9087MA ", 1 }, /* ICP9087MA (Lancer) */
|
||||
{ aac_rkt_init, "aacraid", "ICP ", "ICP5085AU ", 1 }, /* ICP5085AU (Hurricane) */
|
||||
{ aac_rkt_init, "aacraid", "ICP ", "ICP9085LI ", 1 }, /* ICP9085LI (Marauder-X) */
|
||||
{ aac_rkt_init, "aacraid", "ICP ", "ICP5085BR ", 1 }, /* ICP5085BR (Marauder-E) */
|
||||
{ aac_rx_init, "aacraid", "ICP ", "ICP9085LI ", 1 }, /* ICP9085LI (Marauder-X) */
|
||||
{ aac_rx_init, "aacraid", "ICP ", "ICP5085BR ", 1 }, /* ICP5085BR (Marauder-E) */
|
||||
{ aac_rkt_init, "aacraid", "ICP ", "ICP9067MA ", 1 }, /* ICP9067MA (Intruder-6) */
|
||||
{ NULL , "aacraid", "ADAPTEC ", "Themisto ", 0, AAC_QUIRK_SLAVE }, /* Jupiter Platform */
|
||||
{ aac_rkt_init, "aacraid", "ADAPTEC ", "Callisto ", 2, AAC_QUIRK_MASTER }, /* Jupiter Platform */
|
||||
{ aac_rx_init, "aacraid", "ADAPTEC ", "ASR-2020SA ", 1 }, /* ASR-2020SA SATA PCI-X ZCR (Skyhawk) */
|
||||
|
@ -195,10 +210,12 @@ static struct aac_driver_ident aac_drivers[] = {
|
|||
{ aac_rx_init, "aacraid", "ADAPTEC ", "ASR-2240S ", 1 }, /* ASR-2240S (SabreExpress) */
|
||||
{ aac_rx_init, "aacraid", "ADAPTEC ", "ASR-4005SAS ", 1 }, /* ASR-4005SAS */
|
||||
{ aac_rx_init, "ServeRAID","IBM ", "ServeRAID 8i ", 1 }, /* IBM 8i (AvonPark) */
|
||||
{ aac_rkt_init, "ServeRAID","IBM ", "ServeRAID 8k-l8 ", 1 }, /* IBM 8k/8k-l8 (Aurora) */
|
||||
{ aac_rkt_init, "ServeRAID","IBM ", "ServeRAID 8k-l4 ", 1 }, /* IBM 8k/8k-l4 (Aurora Lite) */
|
||||
{ aac_rx_init, "aacraid", "ADAPTEC ", "ASR-4000SAS ", 1 }, /* ASR-4000SAS (BlackBird & AvonPark) */
|
||||
{ aac_rx_init, "aacraid", "ADAPTEC ", "ASR-4800SAS ", 1 }, /* ASR-4800SAS (Marauder-X) */
|
||||
{ aac_rx_init, "aacraid", "ADAPTEC ", "ASR-4805SAS ", 1 }, /* ASR-4805SAS (Marauder-E) */
|
||||
{ aac_rx_init, "aacraid", "ADAPTEC ", "ASR-4810SAS ", 1 }, /* ASR-4810SAS (Hurricane) */
|
||||
{ aac_rkt_init, "aacraid", "ADAPTEC ", "ASR-4810SAS ", 1 }, /* ASR-4810SAS (Hurricane) */
|
||||
|
||||
{ aac_rx_init, "percraid", "DELL ", "PERC 320/DC ", 2, AAC_QUIRK_31BIT | AAC_QUIRK_34SG }, /* Perc 320/DC*/
|
||||
{ aac_sa_init, "aacraid", "ADAPTEC ", "Adaptec 5400S ", 4, AAC_QUIRK_34SG }, /* Adaptec 5400S (Mustang)*/
|
||||
|
@ -839,11 +856,12 @@ static int __devinit aac_probe_one(struct pci_dev *pdev,
|
|||
|
||||
return 0;
|
||||
|
||||
out_deinit:
|
||||
out_deinit:
|
||||
kill_proc(aac->thread_pid, SIGKILL, 0);
|
||||
wait_for_completion(&aac->aif_completion);
|
||||
|
||||
aac_send_shutdown(aac);
|
||||
aac_adapter_disable_int(aac);
|
||||
fib_map_free(aac);
|
||||
pci_free_consistent(aac->pdev, aac->comm_size, aac->comm_addr, aac->comm_phys);
|
||||
kfree(aac->queues);
|
||||
|
@ -860,6 +878,13 @@ static int __devinit aac_probe_one(struct pci_dev *pdev,
|
|||
return error;
|
||||
}
|
||||
|
||||
static void aac_shutdown(struct pci_dev *dev)
|
||||
{
|
||||
struct Scsi_Host *shost = pci_get_drvdata(dev);
|
||||
struct aac_dev *aac = (struct aac_dev *)shost->hostdata;
|
||||
aac_send_shutdown(aac);
|
||||
}
|
||||
|
||||
static void __devexit aac_remove_one(struct pci_dev *pdev)
|
||||
{
|
||||
struct Scsi_Host *shost = pci_get_drvdata(pdev);
|
||||
|
@ -871,6 +896,7 @@ static void __devexit aac_remove_one(struct pci_dev *pdev)
|
|||
wait_for_completion(&aac->aif_completion);
|
||||
|
||||
aac_send_shutdown(aac);
|
||||
aac_adapter_disable_int(aac);
|
||||
fib_map_free(aac);
|
||||
pci_free_consistent(aac->pdev, aac->comm_size, aac->comm_addr,
|
||||
aac->comm_phys);
|
||||
|
@ -891,14 +917,15 @@ static struct pci_driver aac_pci_driver = {
|
|||
.id_table = aac_pci_tbl,
|
||||
.probe = aac_probe_one,
|
||||
.remove = __devexit_p(aac_remove_one),
|
||||
.shutdown = aac_shutdown,
|
||||
};
|
||||
|
||||
static int __init aac_init(void)
|
||||
{
|
||||
int error;
|
||||
|
||||
printk(KERN_INFO "Red Hat/Adaptec aacraid driver (%s %s)\n",
|
||||
AAC_DRIVER_VERSION, AAC_DRIVER_BUILD_DATE);
|
||||
printk(KERN_INFO "Adaptec %s driver (%s)\n",
|
||||
AAC_DRIVERNAME, aac_driver_version);
|
||||
|
||||
error = pci_module_init(&aac_pci_driver);
|
||||
if (error)
|
||||
|
@ -909,6 +936,7 @@ static int __init aac_init(void)
|
|||
printk(KERN_WARNING
|
||||
"aacraid: unable to register \"aac\" device.\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -87,6 +87,16 @@ static irqreturn_t aac_rkt_intr(int irq, void *dev_id, struct pt_regs *regs)
|
|||
return IRQ_NONE;
|
||||
}
|
||||
|
||||
/**
|
||||
* aac_rkt_disable_interrupt - Disable interrupts
|
||||
* @dev: Adapter
|
||||
*/
|
||||
|
||||
static void aac_rkt_disable_interrupt(struct aac_dev *dev)
|
||||
{
|
||||
rkt_writeb(dev, MUnit.OIMR, dev->OIMR = 0xff);
|
||||
}
|
||||
|
||||
/**
|
||||
* rkt_sync_cmd - send a command and wait
|
||||
* @dev: Adapter
|
||||
|
@ -412,10 +422,19 @@ int aac_rkt_init(struct aac_dev *dev)
|
|||
* Fill in the function dispatch table.
|
||||
*/
|
||||
dev->a_ops.adapter_interrupt = aac_rkt_interrupt_adapter;
|
||||
dev->a_ops.adapter_disable_int = aac_rkt_disable_interrupt;
|
||||
dev->a_ops.adapter_notify = aac_rkt_notify_adapter;
|
||||
dev->a_ops.adapter_sync_cmd = rkt_sync_cmd;
|
||||
dev->a_ops.adapter_check_health = aac_rkt_check_health;
|
||||
|
||||
/*
|
||||
* First clear out all interrupts. Then enable the one's that we
|
||||
* can handle.
|
||||
*/
|
||||
rkt_writeb(dev, MUnit.OIMR, 0xff);
|
||||
rkt_writel(dev, MUnit.ODR, 0xffffffff);
|
||||
rkt_writeb(dev, MUnit.OIMR, dev->OIMR = 0xfb);
|
||||
|
||||
if (aac_init_adapter(dev) == NULL)
|
||||
goto error_irq;
|
||||
/*
|
||||
|
@ -438,6 +457,7 @@ int aac_rkt_init(struct aac_dev *dev)
|
|||
kfree(dev->queues);
|
||||
|
||||
error_irq:
|
||||
rkt_writeb(dev, MUnit.OIMR, dev->OIMR = 0xff);
|
||||
free_irq(dev->scsi_host_ptr->irq, (void *)dev);
|
||||
|
||||
error_iounmap:
|
||||
|
|
|
@ -87,6 +87,16 @@ static irqreturn_t aac_rx_intr(int irq, void *dev_id, struct pt_regs *regs)
|
|||
return IRQ_NONE;
|
||||
}
|
||||
|
||||
/**
|
||||
* aac_rx_disable_interrupt - Disable interrupts
|
||||
* @dev: Adapter
|
||||
*/
|
||||
|
||||
static void aac_rx_disable_interrupt(struct aac_dev *dev)
|
||||
{
|
||||
rx_writeb(dev, MUnit.OIMR, dev->OIMR = 0xff);
|
||||
}
|
||||
|
||||
/**
|
||||
* rx_sync_cmd - send a command and wait
|
||||
* @dev: Adapter
|
||||
|
@ -412,10 +422,19 @@ int aac_rx_init(struct aac_dev *dev)
|
|||
* Fill in the function dispatch table.
|
||||
*/
|
||||
dev->a_ops.adapter_interrupt = aac_rx_interrupt_adapter;
|
||||
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;
|
||||
dev->a_ops.adapter_check_health = aac_rx_check_health;
|
||||
|
||||
/*
|
||||
* 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, dev->OIMR = 0xfb);
|
||||
|
||||
if (aac_init_adapter(dev) == NULL)
|
||||
goto error_irq;
|
||||
/*
|
||||
|
@ -438,6 +457,7 @@ int aac_rx_init(struct aac_dev *dev)
|
|||
kfree(dev->queues);
|
||||
|
||||
error_irq:
|
||||
rx_writeb(dev, MUnit.OIMR, dev->OIMR = 0xff);
|
||||
free_irq(dev->scsi_host_ptr->irq, (void *)dev);
|
||||
|
||||
error_iounmap:
|
||||
|
|
|
@ -81,6 +81,16 @@ static irqreturn_t aac_sa_intr(int irq, void *dev_id, struct pt_regs *regs)
|
|||
return IRQ_NONE;
|
||||
}
|
||||
|
||||
/**
|
||||
* aac_sa_disable_interrupt - disable interrupt
|
||||
* @dev: Which adapter to enable.
|
||||
*/
|
||||
|
||||
static void aac_sa_disable_interrupt (struct aac_dev *dev)
|
||||
{
|
||||
sa_writew(dev, SaDbCSR.PRISETIRQMASK, 0xffff);
|
||||
}
|
||||
|
||||
/**
|
||||
* aac_sa_notify_adapter - handle adapter notification
|
||||
* @dev: Adapter that notification is for
|
||||
|
@ -214,9 +224,8 @@ static int sa_sync_cmd(struct aac_dev *dev, u32 command,
|
|||
|
||||
static void aac_sa_interrupt_adapter (struct aac_dev *dev)
|
||||
{
|
||||
u32 ret;
|
||||
sa_sync_cmd(dev, BREAKPOINT_REQUEST, 0, 0, 0, 0, 0, 0,
|
||||
&ret, NULL, NULL, NULL, NULL);
|
||||
NULL, NULL, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -352,10 +361,18 @@ int aac_sa_init(struct aac_dev *dev)
|
|||
*/
|
||||
|
||||
dev->a_ops.adapter_interrupt = aac_sa_interrupt_adapter;
|
||||
dev->a_ops.adapter_disable_int = aac_sa_disable_interrupt;
|
||||
dev->a_ops.adapter_notify = aac_sa_notify_adapter;
|
||||
dev->a_ops.adapter_sync_cmd = sa_sync_cmd;
|
||||
dev->a_ops.adapter_check_health = aac_sa_check_health;
|
||||
|
||||
/*
|
||||
* First clear out all interrupts. Then enable the one's that
|
||||
* we can handle.
|
||||
*/
|
||||
sa_writew(dev, SaDbCSR.PRISETIRQMASK, 0xffff);
|
||||
sa_writew(dev, SaDbCSR.PRICLEARIRQMASK, (PrintfReady | DOORBELL_1 |
|
||||
DOORBELL_2 | DOORBELL_3 | DOORBELL_4));
|
||||
|
||||
if(aac_init_adapter(dev) == NULL)
|
||||
goto error_irq;
|
||||
|
@ -381,6 +398,7 @@ int aac_sa_init(struct aac_dev *dev)
|
|||
kfree(dev->queues);
|
||||
|
||||
error_irq:
|
||||
sa_writew(dev, SaDbCSR.PRISETIRQMASK, 0xffff);
|
||||
free_irq(dev->scsi_host_ptr->irq, (void *)dev);
|
||||
|
||||
error_iounmap:
|
||||
|
|
|
@ -9200,8 +9200,8 @@ asc_prt_scsi_cmnd(struct scsi_cmnd *s)
|
|||
(unsigned) s->serial_number, s->retries, s->allowed);
|
||||
|
||||
printk(
|
||||
" timeout_per_command %d, timeout_total %d, timeout %d\n",
|
||||
s->timeout_per_command, s->timeout_total, s->timeout);
|
||||
" timeout_per_command %d\n",
|
||||
s->timeout_per_command);
|
||||
|
||||
printk(
|
||||
" scsi_done 0x%lx, done 0x%lx, host_scribble 0x%lx, result 0x%x\n",
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
config SCSI_AIC79XX
|
||||
tristate "Adaptec AIC79xx U320 support"
|
||||
depends on PCI && SCSI
|
||||
select SCSI_SPI_ATTRS
|
||||
help
|
||||
This driver supports all of Adaptec's Ultra 320 PCI-X
|
||||
based SCSI controllers.
|
||||
|
|
|
@ -126,7 +126,6 @@ aic7770_find_device(uint32_t id)
|
|||
int
|
||||
aic7770_config(struct ahc_softc *ahc, struct aic7770_identity *entry, u_int io)
|
||||
{
|
||||
u_long l;
|
||||
int error;
|
||||
int have_seeprom;
|
||||
u_int hostconf;
|
||||
|
|
|
@ -1247,9 +1247,6 @@ struct ahd_softc {
|
|||
uint16_t user_tagenable;/* Tagged Queuing allowed */
|
||||
};
|
||||
|
||||
TAILQ_HEAD(ahd_softc_tailq, ahd_softc);
|
||||
extern struct ahd_softc_tailq ahd_tailq;
|
||||
|
||||
/*************************** IO Cell Configuration ****************************/
|
||||
#define AHD_PRECOMP_SLEW_INDEX \
|
||||
(AHD_ANNEXCOL_PRECOMP_SLEW - AHD_ANNEXCOL_PER_DEV0)
|
||||
|
@ -1374,8 +1371,6 @@ void ahd_enable_coalescing(struct ahd_softc *ahd,
|
|||
void ahd_pause_and_flushwork(struct ahd_softc *ahd);
|
||||
int ahd_suspend(struct ahd_softc *ahd);
|
||||
int ahd_resume(struct ahd_softc *ahd);
|
||||
void ahd_softc_insert(struct ahd_softc *);
|
||||
struct ahd_softc *ahd_find_softc(struct ahd_softc *ahd);
|
||||
void ahd_set_unit(struct ahd_softc *, int);
|
||||
void ahd_set_name(struct ahd_softc *, char *);
|
||||
struct scb *ahd_get_scb(struct ahd_softc *ahd, u_int col_idx);
|
||||
|
@ -1524,7 +1519,6 @@ void ahd_print_scb(struct scb *scb);
|
|||
void ahd_print_devinfo(struct ahd_softc *ahd,
|
||||
struct ahd_devinfo *devinfo);
|
||||
void ahd_dump_sglist(struct scb *scb);
|
||||
void ahd_dump_all_cards_state(void);
|
||||
void ahd_dump_card_state(struct ahd_softc *ahd);
|
||||
int ahd_print_register(ahd_reg_parse_entry_t *table,
|
||||
u_int num_entries,
|
||||
|
|
|
@ -52,8 +52,6 @@
|
|||
#include <dev/aic7xxx/aicasm/aicasm_insformat.h>
|
||||
#endif
|
||||
|
||||
/******************************** Globals *************************************/
|
||||
struct ahd_softc_tailq ahd_tailq = TAILQ_HEAD_INITIALIZER(ahd_tailq);
|
||||
|
||||
/***************************** Lookup Tables **********************************/
|
||||
char *ahd_chip_names[] =
|
||||
|
@ -5179,74 +5177,6 @@ ahd_softc_init(struct ahd_softc *ahd)
|
|||
return (0);
|
||||
}
|
||||
|
||||
void
|
||||
ahd_softc_insert(struct ahd_softc *ahd)
|
||||
{
|
||||
struct ahd_softc *list_ahd;
|
||||
|
||||
#if AHD_PCI_CONFIG > 0
|
||||
/*
|
||||
* Second Function PCI devices need to inherit some
|
||||
* settings from function 0.
|
||||
*/
|
||||
if ((ahd->features & AHD_MULTI_FUNC) != 0) {
|
||||
TAILQ_FOREACH(list_ahd, &ahd_tailq, links) {
|
||||
ahd_dev_softc_t list_pci;
|
||||
ahd_dev_softc_t pci;
|
||||
|
||||
list_pci = list_ahd->dev_softc;
|
||||
pci = ahd->dev_softc;
|
||||
if (ahd_get_pci_slot(list_pci) == ahd_get_pci_slot(pci)
|
||||
&& ahd_get_pci_bus(list_pci) == ahd_get_pci_bus(pci)) {
|
||||
struct ahd_softc *master;
|
||||
struct ahd_softc *slave;
|
||||
|
||||
if (ahd_get_pci_function(list_pci) == 0) {
|
||||
master = list_ahd;
|
||||
slave = ahd;
|
||||
} else {
|
||||
master = ahd;
|
||||
slave = list_ahd;
|
||||
}
|
||||
slave->flags &= ~AHD_BIOS_ENABLED;
|
||||
slave->flags |=
|
||||
master->flags & AHD_BIOS_ENABLED;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Insertion sort into our list of softcs.
|
||||
*/
|
||||
list_ahd = TAILQ_FIRST(&ahd_tailq);
|
||||
while (list_ahd != NULL
|
||||
&& ahd_softc_comp(ahd, list_ahd) <= 0)
|
||||
list_ahd = TAILQ_NEXT(list_ahd, links);
|
||||
if (list_ahd != NULL)
|
||||
TAILQ_INSERT_BEFORE(list_ahd, ahd, links);
|
||||
else
|
||||
TAILQ_INSERT_TAIL(&ahd_tailq, ahd, links);
|
||||
ahd->init_level++;
|
||||
}
|
||||
|
||||
/*
|
||||
* Verify that the passed in softc pointer is for a
|
||||
* controller that is still configured.
|
||||
*/
|
||||
struct ahd_softc *
|
||||
ahd_find_softc(struct ahd_softc *ahd)
|
||||
{
|
||||
struct ahd_softc *list_ahd;
|
||||
|
||||
TAILQ_FOREACH(list_ahd, &ahd_tailq, links) {
|
||||
if (list_ahd == ahd)
|
||||
return (ahd);
|
||||
}
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
void
|
||||
ahd_set_unit(struct ahd_softc *ahd, int unit)
|
||||
{
|
||||
|
@ -7902,18 +7832,10 @@ ahd_reset_channel(struct ahd_softc *ahd, char channel, int initiate_reset)
|
|||
static void
|
||||
ahd_reset_poll(void *arg)
|
||||
{
|
||||
struct ahd_softc *ahd;
|
||||
struct ahd_softc *ahd = arg;
|
||||
u_int scsiseq1;
|
||||
u_long l;
|
||||
u_long s;
|
||||
|
||||
ahd_list_lock(&l);
|
||||
ahd = ahd_find_softc((struct ahd_softc *)arg);
|
||||
if (ahd == NULL) {
|
||||
printf("ahd_reset_poll: Instance %p no longer exists\n", arg);
|
||||
ahd_list_unlock(&l);
|
||||
return;
|
||||
}
|
||||
ahd_lock(ahd, &s);
|
||||
ahd_pause(ahd);
|
||||
ahd_update_modes(ahd);
|
||||
|
@ -7924,7 +7846,6 @@ ahd_reset_poll(void *arg)
|
|||
ahd_reset_poll, ahd);
|
||||
ahd_unpause(ahd);
|
||||
ahd_unlock(ahd, &s);
|
||||
ahd_list_unlock(&l);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -7936,25 +7857,16 @@ ahd_reset_poll(void *arg)
|
|||
ahd->flags &= ~AHD_RESET_POLL_ACTIVE;
|
||||
ahd_unlock(ahd, &s);
|
||||
ahd_release_simq(ahd);
|
||||
ahd_list_unlock(&l);
|
||||
}
|
||||
|
||||
/**************************** Statistics Processing ***************************/
|
||||
static void
|
||||
ahd_stat_timer(void *arg)
|
||||
{
|
||||
struct ahd_softc *ahd;
|
||||
u_long l;
|
||||
struct ahd_softc *ahd = arg;
|
||||
u_long s;
|
||||
int enint_coal;
|
||||
|
||||
ahd_list_lock(&l);
|
||||
ahd = ahd_find_softc((struct ahd_softc *)arg);
|
||||
if (ahd == NULL) {
|
||||
printf("ahd_stat_timer: Instance %p no longer exists\n", arg);
|
||||
ahd_list_unlock(&l);
|
||||
return;
|
||||
}
|
||||
ahd_lock(ahd, &s);
|
||||
|
||||
enint_coal = ahd->hs_mailbox & ENINT_COALESCE;
|
||||
|
@ -7981,7 +7893,6 @@ ahd_stat_timer(void *arg)
|
|||
ahd_timer_reset(&ahd->stat_timer, AHD_STAT_UPDATE_US,
|
||||
ahd_stat_timer, ahd);
|
||||
ahd_unlock(ahd, &s);
|
||||
ahd_list_unlock(&l);
|
||||
}
|
||||
|
||||
/****************************** Status Processing *****************************/
|
||||
|
@ -8745,16 +8656,6 @@ ahd_probe_stack_size(struct ahd_softc *ahd)
|
|||
return (last_probe);
|
||||
}
|
||||
|
||||
void
|
||||
ahd_dump_all_cards_state(void)
|
||||
{
|
||||
struct ahd_softc *list_ahd;
|
||||
|
||||
TAILQ_FOREACH(list_ahd, &ahd_tailq, links) {
|
||||
ahd_dump_card_state(list_ahd);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
ahd_print_register(ahd_reg_parse_entry_t *table, u_int num_entries,
|
||||
const char *name, u_int address, u_int value,
|
||||
|
@ -9039,7 +8940,6 @@ ahd_dump_card_state(struct ahd_softc *ahd)
|
|||
ahd_outb(ahd, STACK, (ahd->saved_stack[i] >> 8) & 0xFF);
|
||||
}
|
||||
printf("\n<<<<<<<<<<<<<<<<< Dump Card State Ends >>>>>>>>>>>>>>>>>>\n");
|
||||
ahd_platform_dump_card_state(ahd);
|
||||
ahd_restore_modes(ahd, saved_modes);
|
||||
if (paused == 0)
|
||||
ahd_unpause(ahd);
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -42,6 +42,7 @@
|
|||
#ifndef _AIC79XX_LINUX_H_
|
||||
#define _AIC79XX_LINUX_H_
|
||||
|
||||
#include <linux/config.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/blkdev.h>
|
||||
#include <linux/delay.h>
|
||||
|
@ -49,18 +50,23 @@
|
|||
#include <linux/pci.h>
|
||||
#include <linux/smp_lock.h>
|
||||
#include <linux/version.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/slab.h>
|
||||
#include <asm/byteorder.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
#include <linux/interrupt.h> /* For tasklet support. */
|
||||
#include <linux/config.h>
|
||||
#include <linux/slab.h>
|
||||
#include <scsi/scsi.h>
|
||||
#include <scsi/scsi_cmnd.h>
|
||||
#include <scsi/scsi_eh.h>
|
||||
#include <scsi/scsi_device.h>
|
||||
#include <scsi/scsi_host.h>
|
||||
#include <scsi/scsi_tcq.h>
|
||||
#include <scsi/scsi_transport.h>
|
||||
#include <scsi/scsi_transport_spi.h>
|
||||
|
||||
/* Core SCSI definitions */
|
||||
#define AIC_LIB_PREFIX ahd
|
||||
#include "scsi.h"
|
||||
#include <scsi/scsi_host.h>
|
||||
|
||||
/* Name space conflict with BSD queue macros */
|
||||
#ifdef LIST_HEAD
|
||||
|
@ -95,7 +101,7 @@
|
|||
/************************* Forward Declarations *******************************/
|
||||
struct ahd_softc;
|
||||
typedef struct pci_dev *ahd_dev_softc_t;
|
||||
typedef Scsi_Cmnd *ahd_io_ctx_t;
|
||||
typedef struct scsi_cmnd *ahd_io_ctx_t;
|
||||
|
||||
/******************************* Byte Order ***********************************/
|
||||
#define ahd_htobe16(x) cpu_to_be16(x)
|
||||
|
@ -114,8 +120,7 @@ typedef Scsi_Cmnd *ahd_io_ctx_t;
|
|||
|
||||
/************************* Configuration Data *********************************/
|
||||
extern uint32_t aic79xx_allow_memio;
|
||||
extern int aic79xx_detect_complete;
|
||||
extern Scsi_Host_Template aic79xx_driver_template;
|
||||
extern struct scsi_host_template aic79xx_driver_template;
|
||||
|
||||
/***************************** Bus Space/DMA **********************************/
|
||||
|
||||
|
@ -145,11 +150,7 @@ struct ahd_linux_dma_tag
|
|||
};
|
||||
typedef struct ahd_linux_dma_tag* bus_dma_tag_t;
|
||||
|
||||
struct ahd_linux_dmamap
|
||||
{
|
||||
dma_addr_t bus_addr;
|
||||
};
|
||||
typedef struct ahd_linux_dmamap* bus_dmamap_t;
|
||||
typedef dma_addr_t bus_dmamap_t;
|
||||
|
||||
typedef int bus_dma_filter_t(void*, dma_addr_t);
|
||||
typedef void bus_dmamap_callback_t(void *, bus_dma_segment_t *, int, int);
|
||||
|
@ -226,12 +227,12 @@ typedef struct timer_list ahd_timer_t;
|
|||
#define ahd_timer_init init_timer
|
||||
#define ahd_timer_stop del_timer_sync
|
||||
typedef void ahd_linux_callback_t (u_long);
|
||||
static __inline void ahd_timer_reset(ahd_timer_t *timer, u_int usec,
|
||||
static __inline void ahd_timer_reset(ahd_timer_t *timer, int usec,
|
||||
ahd_callback_t *func, void *arg);
|
||||
static __inline void ahd_scb_timer_reset(struct scb *scb, u_int usec);
|
||||
|
||||
static __inline void
|
||||
ahd_timer_reset(ahd_timer_t *timer, u_int usec, ahd_callback_t *func, void *arg)
|
||||
ahd_timer_reset(ahd_timer_t *timer, int usec, ahd_callback_t *func, void *arg)
|
||||
{
|
||||
struct ahd_softc *ahd;
|
||||
|
||||
|
@ -252,43 +253,8 @@ ahd_scb_timer_reset(struct scb *scb, u_int usec)
|
|||
/***************************** SMP support ************************************/
|
||||
#include <linux/spinlock.h>
|
||||
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) || defined(SCSI_HAS_HOST_LOCK))
|
||||
#define AHD_SCSI_HAS_HOST_LOCK 1
|
||||
#else
|
||||
#define AHD_SCSI_HAS_HOST_LOCK 0
|
||||
#endif
|
||||
|
||||
#define AIC79XX_DRIVER_VERSION "1.3.11"
|
||||
|
||||
/**************************** Front End Queues ********************************/
|
||||
/*
|
||||
* Data structure used to cast the Linux struct scsi_cmnd to something
|
||||
* that allows us to use the queue macros. The linux structure has
|
||||
* plenty of space to hold the links fields as required by the queue
|
||||
* macros, but the queue macors require them to have the correct type.
|
||||
*/
|
||||
struct ahd_cmd_internal {
|
||||
/* Area owned by the Linux scsi layer. */
|
||||
uint8_t private[offsetof(struct scsi_cmnd, SCp.Status)];
|
||||
union {
|
||||
STAILQ_ENTRY(ahd_cmd) ste;
|
||||
LIST_ENTRY(ahd_cmd) le;
|
||||
TAILQ_ENTRY(ahd_cmd) tqe;
|
||||
} links;
|
||||
uint32_t end;
|
||||
};
|
||||
|
||||
struct ahd_cmd {
|
||||
union {
|
||||
struct ahd_cmd_internal icmd;
|
||||
struct scsi_cmnd scsi_cmd;
|
||||
} un;
|
||||
};
|
||||
|
||||
#define acmd_icmd(cmd) ((cmd)->un.icmd)
|
||||
#define acmd_scsi_cmd(cmd) ((cmd)->un.scsi_cmd)
|
||||
#define acmd_links un.icmd.links
|
||||
|
||||
/*************************** Device Data Structures ***************************/
|
||||
/*
|
||||
* A per probed device structure used to deal with some error recovery
|
||||
|
@ -297,22 +263,17 @@ struct ahd_cmd {
|
|||
* after a successfully completed inquiry command to the target when
|
||||
* that inquiry data indicates a lun is present.
|
||||
*/
|
||||
TAILQ_HEAD(ahd_busyq, ahd_cmd);
|
||||
|
||||
typedef enum {
|
||||
AHD_DEV_UNCONFIGURED = 0x01,
|
||||
AHD_DEV_FREEZE_TIL_EMPTY = 0x02, /* Freeze queue until active == 0 */
|
||||
AHD_DEV_TIMER_ACTIVE = 0x04, /* Our timer is active */
|
||||
AHD_DEV_ON_RUN_LIST = 0x08, /* Queued to be run later */
|
||||
AHD_DEV_Q_BASIC = 0x10, /* Allow basic device queuing */
|
||||
AHD_DEV_Q_TAGGED = 0x20, /* Allow full SCSI2 command queueing */
|
||||
AHD_DEV_PERIODIC_OTAG = 0x40, /* Send OTAG to prevent starvation */
|
||||
AHD_DEV_SLAVE_CONFIGURED = 0x80 /* slave_configure() has been called */
|
||||
} ahd_linux_dev_flags;
|
||||
|
||||
struct ahd_linux_target;
|
||||
struct ahd_linux_device {
|
||||
TAILQ_ENTRY(ahd_linux_device) links;
|
||||
struct ahd_busyq busyq;
|
||||
|
||||
/*
|
||||
* The number of transactions currently
|
||||
|
@ -388,62 +349,12 @@ struct ahd_linux_device {
|
|||
*/
|
||||
u_int commands_since_idle_or_otag;
|
||||
#define AHD_OTAG_THRESH 500
|
||||
|
||||
int lun;
|
||||
Scsi_Device *scsi_device;
|
||||
struct ahd_linux_target *target;
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
AHD_DV_REQUIRED = 0x01,
|
||||
AHD_INQ_VALID = 0x02,
|
||||
AHD_BASIC_DV = 0x04,
|
||||
AHD_ENHANCED_DV = 0x08
|
||||
} ahd_linux_targ_flags;
|
||||
|
||||
/* DV States */
|
||||
typedef enum {
|
||||
AHD_DV_STATE_EXIT = 0,
|
||||
AHD_DV_STATE_INQ_SHORT_ASYNC,
|
||||
AHD_DV_STATE_INQ_ASYNC,
|
||||
AHD_DV_STATE_INQ_ASYNC_VERIFY,
|
||||
AHD_DV_STATE_TUR,
|
||||
AHD_DV_STATE_REBD,
|
||||
AHD_DV_STATE_INQ_VERIFY,
|
||||
AHD_DV_STATE_WEB,
|
||||
AHD_DV_STATE_REB,
|
||||
AHD_DV_STATE_SU,
|
||||
AHD_DV_STATE_BUSY
|
||||
} ahd_dv_state;
|
||||
|
||||
struct ahd_linux_target {
|
||||
struct ahd_linux_device *devices[AHD_NUM_LUNS];
|
||||
int channel;
|
||||
int target;
|
||||
int refcount;
|
||||
struct scsi_device *sdev[AHD_NUM_LUNS];
|
||||
struct ahd_transinfo last_tinfo;
|
||||
struct ahd_softc *ahd;
|
||||
ahd_linux_targ_flags flags;
|
||||
struct scsi_inquiry_data *inq_data;
|
||||
/*
|
||||
* The next "fallback" period to use for narrow/wide transfers.
|
||||
*/
|
||||
uint8_t dv_next_narrow_period;
|
||||
uint8_t dv_next_wide_period;
|
||||
uint8_t dv_max_width;
|
||||
uint8_t dv_max_ppr_options;
|
||||
uint8_t dv_last_ppr_options;
|
||||
u_int dv_echo_size;
|
||||
ahd_dv_state dv_state;
|
||||
u_int dv_state_retry;
|
||||
uint8_t *dv_buffer;
|
||||
uint8_t *dv_buffer1;
|
||||
|
||||
/*
|
||||
* Cumulative counter of errors.
|
||||
*/
|
||||
u_long errors_detected;
|
||||
u_long cmds_since_error;
|
||||
};
|
||||
|
||||
/********************* Definitions Required by the Core ***********************/
|
||||
|
@ -453,32 +364,16 @@ struct ahd_linux_target {
|
|||
* manner and are allocated below 4GB, the number of S/G segments is
|
||||
* unrestricted.
|
||||
*/
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
|
||||
/*
|
||||
* We dynamically adjust the number of segments in pre-2.5 kernels to
|
||||
* avoid fragmentation issues in the SCSI mid-layer's private memory
|
||||
* allocator. See aic79xx_osm.c ahd_linux_size_nseg() for details.
|
||||
*/
|
||||
extern u_int ahd_linux_nseg;
|
||||
#define AHD_NSEG ahd_linux_nseg
|
||||
#define AHD_LINUX_MIN_NSEG 64
|
||||
#else
|
||||
#define AHD_NSEG 128
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Per-SCB OSM storage.
|
||||
*/
|
||||
typedef enum {
|
||||
AHD_SCB_UP_EH_SEM = 0x1
|
||||
} ahd_linux_scb_flags;
|
||||
|
||||
struct scb_platform_data {
|
||||
struct ahd_linux_device *dev;
|
||||
dma_addr_t buf_busaddr;
|
||||
uint32_t xfer_len;
|
||||
uint32_t sense_resid; /* Auto-Sense residual */
|
||||
ahd_linux_scb_flags flags;
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -487,44 +382,23 @@ struct scb_platform_data {
|
|||
* alignment restrictions of the various platforms supported by
|
||||
* this driver.
|
||||
*/
|
||||
typedef enum {
|
||||
AHD_DV_WAIT_SIMQ_EMPTY = 0x01,
|
||||
AHD_DV_WAIT_SIMQ_RELEASE = 0x02,
|
||||
AHD_DV_ACTIVE = 0x04,
|
||||
AHD_DV_SHUTDOWN = 0x08,
|
||||
AHD_RUN_CMPLT_Q_TIMER = 0x10
|
||||
} ahd_linux_softc_flags;
|
||||
|
||||
TAILQ_HEAD(ahd_completeq, ahd_cmd);
|
||||
|
||||
struct ahd_platform_data {
|
||||
/*
|
||||
* Fields accessed from interrupt context.
|
||||
*/
|
||||
struct ahd_linux_target *targets[AHD_NUM_TARGETS];
|
||||
TAILQ_HEAD(, ahd_linux_device) device_runq;
|
||||
struct ahd_completeq completeq;
|
||||
struct scsi_target *starget[AHD_NUM_TARGETS];
|
||||
|
||||
spinlock_t spin_lock;
|
||||
struct tasklet_struct runq_tasklet;
|
||||
u_int qfrozen;
|
||||
pid_t dv_pid;
|
||||
struct timer_list completeq_timer;
|
||||
struct timer_list reset_timer;
|
||||
struct timer_list stats_timer;
|
||||
struct semaphore eh_sem;
|
||||
struct semaphore dv_sem;
|
||||
struct semaphore dv_cmd_sem; /* XXX This needs to be in
|
||||
* the target struct
|
||||
*/
|
||||
struct scsi_device *dv_scsi_dev;
|
||||
struct Scsi_Host *host; /* pointer to scsi host */
|
||||
#define AHD_LINUX_NOIRQ ((uint32_t)~0)
|
||||
uint32_t irq; /* IRQ for this adapter */
|
||||
uint32_t bios_address;
|
||||
uint32_t mem_busaddr; /* Mem Base Addr */
|
||||
uint64_t hw_dma_mask;
|
||||
ahd_linux_softc_flags flags;
|
||||
#define AHD_SCB_UP_EH_SEM 0x1
|
||||
uint32_t flags;
|
||||
};
|
||||
|
||||
/************************** OS Utility Wrappers *******************************/
|
||||
|
@ -641,7 +515,7 @@ ahd_insb(struct ahd_softc * ahd, long port, uint8_t *array, int count)
|
|||
|
||||
/**************************** Initialization **********************************/
|
||||
int ahd_linux_register_host(struct ahd_softc *,
|
||||
Scsi_Host_Template *);
|
||||
struct scsi_host_template *);
|
||||
|
||||
uint64_t ahd_linux_get_memsize(void);
|
||||
|
||||
|
@ -657,28 +531,6 @@ void ahd_format_transinfo(struct info_str *info,
|
|||
struct ahd_transinfo *tinfo);
|
||||
|
||||
/******************************** Locking *************************************/
|
||||
/* Lock protecting internal data structures */
|
||||
static __inline void ahd_lockinit(struct ahd_softc *);
|
||||
static __inline void ahd_lock(struct ahd_softc *, unsigned long *flags);
|
||||
static __inline void ahd_unlock(struct ahd_softc *, unsigned long *flags);
|
||||
|
||||
/* Lock acquisition and release of the above lock in midlayer entry points. */
|
||||
static __inline void ahd_midlayer_entrypoint_lock(struct ahd_softc *,
|
||||
unsigned long *flags);
|
||||
static __inline void ahd_midlayer_entrypoint_unlock(struct ahd_softc *,
|
||||
unsigned long *flags);
|
||||
|
||||
/* Lock held during command compeletion to the upper layer */
|
||||
static __inline void ahd_done_lockinit(struct ahd_softc *);
|
||||
static __inline void ahd_done_lock(struct ahd_softc *, unsigned long *flags);
|
||||
static __inline void ahd_done_unlock(struct ahd_softc *, unsigned long *flags);
|
||||
|
||||
/* Lock held during ahd_list manipulation and ahd softc frees */
|
||||
extern spinlock_t ahd_list_spinlock;
|
||||
static __inline void ahd_list_lockinit(void);
|
||||
static __inline void ahd_list_lock(unsigned long *flags);
|
||||
static __inline void ahd_list_unlock(unsigned long *flags);
|
||||
|
||||
static __inline void
|
||||
ahd_lockinit(struct ahd_softc *ahd)
|
||||
{
|
||||
|
@ -697,75 +549,6 @@ ahd_unlock(struct ahd_softc *ahd, unsigned long *flags)
|
|||
spin_unlock_irqrestore(&ahd->platform_data->spin_lock, *flags);
|
||||
}
|
||||
|
||||
static __inline void
|
||||
ahd_midlayer_entrypoint_lock(struct ahd_softc *ahd, unsigned long *flags)
|
||||
{
|
||||
/*
|
||||
* In 2.5.X and some 2.4.X versions, the midlayer takes our
|
||||
* lock just before calling us, so we avoid locking again.
|
||||
* For other kernel versions, the io_request_lock is taken
|
||||
* just before our entry point is called. In this case, we
|
||||
* trade the io_request_lock for our per-softc lock.
|
||||
*/
|
||||
#if AHD_SCSI_HAS_HOST_LOCK == 0
|
||||
spin_unlock(&io_request_lock);
|
||||
spin_lock(&ahd->platform_data->spin_lock);
|
||||
#endif
|
||||
}
|
||||
|
||||
static __inline void
|
||||
ahd_midlayer_entrypoint_unlock(struct ahd_softc *ahd, unsigned long *flags)
|
||||
{
|
||||
#if AHD_SCSI_HAS_HOST_LOCK == 0
|
||||
spin_unlock(&ahd->platform_data->spin_lock);
|
||||
spin_lock(&io_request_lock);
|
||||
#endif
|
||||
}
|
||||
|
||||
static __inline void
|
||||
ahd_done_lockinit(struct ahd_softc *ahd)
|
||||
{
|
||||
/*
|
||||
* In 2.5.X, our own lock is held during completions.
|
||||
* In previous versions, the io_request_lock is used.
|
||||
* In either case, we can't initialize this lock again.
|
||||
*/
|
||||
}
|
||||
|
||||
static __inline void
|
||||
ahd_done_lock(struct ahd_softc *ahd, unsigned long *flags)
|
||||
{
|
||||
#if AHD_SCSI_HAS_HOST_LOCK == 0
|
||||
spin_lock(&io_request_lock);
|
||||
#endif
|
||||
}
|
||||
|
||||
static __inline void
|
||||
ahd_done_unlock(struct ahd_softc *ahd, unsigned long *flags)
|
||||
{
|
||||
#if AHD_SCSI_HAS_HOST_LOCK == 0
|
||||
spin_unlock(&io_request_lock);
|
||||
#endif
|
||||
}
|
||||
|
||||
static __inline void
|
||||
ahd_list_lockinit(void)
|
||||
{
|
||||
spin_lock_init(&ahd_list_spinlock);
|
||||
}
|
||||
|
||||
static __inline void
|
||||
ahd_list_lock(unsigned long *flags)
|
||||
{
|
||||
spin_lock_irqsave(&ahd_list_spinlock, *flags);
|
||||
}
|
||||
|
||||
static __inline void
|
||||
ahd_list_unlock(unsigned long *flags)
|
||||
{
|
||||
spin_unlock_irqrestore(&ahd_list_spinlock, *flags);
|
||||
}
|
||||
|
||||
/******************************* PCI Definitions ******************************/
|
||||
/*
|
||||
* PCIM_xxx: mask to locate subfield in register
|
||||
|
@ -925,27 +708,17 @@ ahd_flush_device_writes(struct ahd_softc *ahd)
|
|||
}
|
||||
|
||||
/**************************** Proc FS Support *********************************/
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
|
||||
int ahd_linux_proc_info(char *, char **, off_t, int, int, int);
|
||||
#else
|
||||
int ahd_linux_proc_info(struct Scsi_Host *, char *, char **,
|
||||
off_t, int, int);
|
||||
#endif
|
||||
|
||||
/*************************** Domain Validation ********************************/
|
||||
#define AHD_DV_CMD(cmd) ((cmd)->scsi_done == ahd_linux_dv_complete)
|
||||
#define AHD_DV_SIMQ_FROZEN(ahd) \
|
||||
((((ahd)->platform_data->flags & AHD_DV_ACTIVE) != 0) \
|
||||
&& (ahd)->platform_data->qfrozen == 1)
|
||||
|
||||
/*********************** Transaction Access Wrappers **************************/
|
||||
static __inline void ahd_cmd_set_transaction_status(Scsi_Cmnd *, uint32_t);
|
||||
static __inline void ahd_cmd_set_transaction_status(struct scsi_cmnd *, uint32_t);
|
||||
static __inline void ahd_set_transaction_status(struct scb *, uint32_t);
|
||||
static __inline void ahd_cmd_set_scsi_status(Scsi_Cmnd *, uint32_t);
|
||||
static __inline void ahd_cmd_set_scsi_status(struct scsi_cmnd *, uint32_t);
|
||||
static __inline void ahd_set_scsi_status(struct scb *, uint32_t);
|
||||
static __inline uint32_t ahd_cmd_get_transaction_status(Scsi_Cmnd *cmd);
|
||||
static __inline uint32_t ahd_cmd_get_transaction_status(struct scsi_cmnd *cmd);
|
||||
static __inline uint32_t ahd_get_transaction_status(struct scb *);
|
||||
static __inline uint32_t ahd_cmd_get_scsi_status(Scsi_Cmnd *cmd);
|
||||
static __inline uint32_t ahd_cmd_get_scsi_status(struct scsi_cmnd *cmd);
|
||||
static __inline uint32_t ahd_get_scsi_status(struct scb *);
|
||||
static __inline void ahd_set_transaction_tag(struct scb *, int, u_int);
|
||||
static __inline u_long ahd_get_transfer_length(struct scb *);
|
||||
|
@ -964,7 +737,7 @@ static __inline void ahd_platform_scb_free(struct ahd_softc *ahd,
|
|||
static __inline void ahd_freeze_scb(struct scb *scb);
|
||||
|
||||
static __inline
|
||||
void ahd_cmd_set_transaction_status(Scsi_Cmnd *cmd, uint32_t status)
|
||||
void ahd_cmd_set_transaction_status(struct scsi_cmnd *cmd, uint32_t status)
|
||||
{
|
||||
cmd->result &= ~(CAM_STATUS_MASK << 16);
|
||||
cmd->result |= status << 16;
|
||||
|
@ -977,7 +750,7 @@ void ahd_set_transaction_status(struct scb *scb, uint32_t status)
|
|||
}
|
||||
|
||||
static __inline
|
||||
void ahd_cmd_set_scsi_status(Scsi_Cmnd *cmd, uint32_t status)
|
||||
void ahd_cmd_set_scsi_status(struct scsi_cmnd *cmd, uint32_t status)
|
||||
{
|
||||
cmd->result &= ~0xFFFF;
|
||||
cmd->result |= status;
|
||||
|
@ -990,7 +763,7 @@ void ahd_set_scsi_status(struct scb *scb, uint32_t status)
|
|||
}
|
||||
|
||||
static __inline
|
||||
uint32_t ahd_cmd_get_transaction_status(Scsi_Cmnd *cmd)
|
||||
uint32_t ahd_cmd_get_transaction_status(struct scsi_cmnd *cmd)
|
||||
{
|
||||
return ((cmd->result >> 16) & CAM_STATUS_MASK);
|
||||
}
|
||||
|
@ -1002,7 +775,7 @@ uint32_t ahd_get_transaction_status(struct scb *scb)
|
|||
}
|
||||
|
||||
static __inline
|
||||
uint32_t ahd_cmd_get_scsi_status(Scsi_Cmnd *cmd)
|
||||
uint32_t ahd_cmd_get_scsi_status(struct scsi_cmnd *cmd)
|
||||
{
|
||||
return (cmd->result & 0xFFFF);
|
||||
}
|
||||
|
@ -1117,7 +890,6 @@ void ahd_done(struct ahd_softc*, struct scb*);
|
|||
void ahd_send_async(struct ahd_softc *, char channel,
|
||||
u_int target, u_int lun, ac_code, void *);
|
||||
void ahd_print_path(struct ahd_softc *, struct scb *);
|
||||
void ahd_platform_dump_card_state(struct ahd_softc *ahd);
|
||||
|
||||
#ifdef CONFIG_PCI
|
||||
#define AHD_PCI_CONFIG 1
|
||||
|
|
|
@ -92,27 +92,31 @@ struct pci_driver aic79xx_pci_driver = {
|
|||
static void
|
||||
ahd_linux_pci_dev_remove(struct pci_dev *pdev)
|
||||
{
|
||||
struct ahd_softc *ahd;
|
||||
u_long l;
|
||||
|
||||
/*
|
||||
* We should be able to just perform
|
||||
* the free directly, but check our
|
||||
* list for extra sanity.
|
||||
*/
|
||||
ahd_list_lock(&l);
|
||||
ahd = ahd_find_softc((struct ahd_softc *)pci_get_drvdata(pdev));
|
||||
if (ahd != NULL) {
|
||||
struct ahd_softc *ahd = pci_get_drvdata(pdev);
|
||||
u_long s;
|
||||
|
||||
TAILQ_REMOVE(&ahd_tailq, ahd, links);
|
||||
ahd_list_unlock(&l);
|
||||
ahd_lock(ahd, &s);
|
||||
ahd_intr_enable(ahd, FALSE);
|
||||
ahd_unlock(ahd, &s);
|
||||
ahd_free(ahd);
|
||||
}
|
||||
|
||||
static void
|
||||
ahd_linux_pci_inherit_flags(struct ahd_softc *ahd)
|
||||
{
|
||||
struct pci_dev *pdev = ahd->dev_softc, *master_pdev;
|
||||
unsigned int master_devfn = PCI_DEVFN(PCI_SLOT(pdev->devfn), 0);
|
||||
|
||||
master_pdev = pci_get_slot(pdev->bus, master_devfn);
|
||||
if (master_pdev) {
|
||||
struct ahd_softc *master = pci_get_drvdata(master_pdev);
|
||||
if (master) {
|
||||
ahd->flags &= ~AHD_BIOS_ENABLED;
|
||||
ahd->flags |= master->flags & AHD_BIOS_ENABLED;
|
||||
} else
|
||||
ahd_list_unlock(&l);
|
||||
printk(KERN_ERR "aic79xx: no multichannel peer found!\n");
|
||||
pci_dev_put(master_pdev);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -125,22 +129,6 @@ ahd_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
|||
char *name;
|
||||
int error;
|
||||
|
||||
/*
|
||||
* Some BIOSen report the same device multiple times.
|
||||
*/
|
||||
TAILQ_FOREACH(ahd, &ahd_tailq, links) {
|
||||
struct pci_dev *probed_pdev;
|
||||
|
||||
probed_pdev = ahd->dev_softc;
|
||||
if (probed_pdev->bus->number == pdev->bus->number
|
||||
&& probed_pdev->devfn == pdev->devfn)
|
||||
break;
|
||||
}
|
||||
if (ahd != NULL) {
|
||||
/* Skip duplicate. */
|
||||
return (-ENODEV);
|
||||
}
|
||||
|
||||
pci = pdev;
|
||||
entry = ahd_find_pci_device(pci);
|
||||
if (entry == NULL)
|
||||
|
@ -177,15 +165,12 @@ ahd_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
|||
if (memsize >= 0x8000000000ULL
|
||||
&& pci_set_dma_mask(pdev, DMA_64BIT_MASK) == 0) {
|
||||
ahd->flags |= AHD_64BIT_ADDRESSING;
|
||||
ahd->platform_data->hw_dma_mask = DMA_64BIT_MASK;
|
||||
} else if (memsize > 0x80000000
|
||||
&& pci_set_dma_mask(pdev, mask_39bit) == 0) {
|
||||
ahd->flags |= AHD_39BIT_ADDRESSING;
|
||||
ahd->platform_data->hw_dma_mask = mask_39bit;
|
||||
}
|
||||
} else {
|
||||
pci_set_dma_mask(pdev, DMA_32BIT_MASK);
|
||||
ahd->platform_data->hw_dma_mask = DMA_32BIT_MASK;
|
||||
}
|
||||
ahd->dev_softc = pci;
|
||||
error = ahd_pci_config(ahd, entry);
|
||||
|
@ -193,16 +178,17 @@ ahd_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
|||
ahd_free(ahd);
|
||||
return (-error);
|
||||
}
|
||||
|
||||
/*
|
||||
* Second Function PCI devices need to inherit some
|
||||
* * settings from function 0.
|
||||
*/
|
||||
if ((ahd->features & AHD_MULTI_FUNC) && PCI_FUNC(pdev->devfn) != 0)
|
||||
ahd_linux_pci_inherit_flags(ahd);
|
||||
|
||||
pci_set_drvdata(pdev, ahd);
|
||||
if (aic79xx_detect_complete) {
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
|
||||
|
||||
ahd_linux_register_host(ahd, &aic79xx_driver_template);
|
||||
#else
|
||||
printf("aic79xx: ignoring PCI device found after "
|
||||
"initialization\n");
|
||||
return (-ENODEV);
|
||||
#endif
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
|
|
@ -283,7 +283,6 @@ int
|
|||
ahd_pci_config(struct ahd_softc *ahd, struct ahd_pci_identity *entry)
|
||||
{
|
||||
struct scb_data *shared_scb_data;
|
||||
u_long l;
|
||||
u_int command;
|
||||
uint32_t devconfig;
|
||||
uint16_t subvendor;
|
||||
|
@ -373,16 +372,9 @@ ahd_pci_config(struct ahd_softc *ahd, struct ahd_pci_identity *entry)
|
|||
* Allow interrupts now that we are completely setup.
|
||||
*/
|
||||
error = ahd_pci_map_int(ahd);
|
||||
if (error != 0)
|
||||
return (error);
|
||||
|
||||
ahd_list_lock(&l);
|
||||
/*
|
||||
* Link this softc in with all other ahd instances.
|
||||
*/
|
||||
ahd_softc_insert(ahd);
|
||||
ahd_list_unlock(&l);
|
||||
return (0);
|
||||
if (!error)
|
||||
ahd->init_level++;
|
||||
return error;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -49,7 +49,7 @@ static void ahd_dump_target_state(struct ahd_softc *ahd,
|
|||
u_int our_id, char channel,
|
||||
u_int target_id, u_int target_offset);
|
||||
static void ahd_dump_device_state(struct info_str *info,
|
||||
struct ahd_linux_device *dev);
|
||||
struct scsi_device *sdev);
|
||||
static int ahd_proc_write_seeprom(struct ahd_softc *ahd,
|
||||
char *buffer, int length);
|
||||
|
||||
|
@ -167,6 +167,7 @@ ahd_dump_target_state(struct ahd_softc *ahd, struct info_str *info,
|
|||
u_int target_offset)
|
||||
{
|
||||
struct ahd_linux_target *targ;
|
||||
struct scsi_target *starget;
|
||||
struct ahd_initiator_tinfo *tinfo;
|
||||
struct ahd_tmode_tstate *tstate;
|
||||
int lun;
|
||||
|
@ -176,20 +177,20 @@ ahd_dump_target_state(struct ahd_softc *ahd, struct info_str *info,
|
|||
copy_info(info, "Target %d Negotiation Settings\n", target_id);
|
||||
copy_info(info, "\tUser: ");
|
||||
ahd_format_transinfo(info, &tinfo->user);
|
||||
targ = ahd->platform_data->targets[target_offset];
|
||||
if (targ == NULL)
|
||||
starget = ahd->platform_data->starget[target_offset];
|
||||
if (starget == NULL)
|
||||
return;
|
||||
targ = scsi_transport_target_data(starget);
|
||||
|
||||
copy_info(info, "\tGoal: ");
|
||||
ahd_format_transinfo(info, &tinfo->goal);
|
||||
copy_info(info, "\tCurr: ");
|
||||
ahd_format_transinfo(info, &tinfo->curr);
|
||||
copy_info(info, "\tTransmission Errors %ld\n", targ->errors_detected);
|
||||
|
||||
for (lun = 0; lun < AHD_NUM_LUNS; lun++) {
|
||||
struct ahd_linux_device *dev;
|
||||
struct scsi_device *dev;
|
||||
|
||||
dev = targ->devices[lun];
|
||||
dev = targ->sdev[lun];
|
||||
|
||||
if (dev == NULL)
|
||||
continue;
|
||||
|
@ -199,10 +200,13 @@ ahd_dump_target_state(struct ahd_softc *ahd, struct info_str *info,
|
|||
}
|
||||
|
||||
static void
|
||||
ahd_dump_device_state(struct info_str *info, struct ahd_linux_device *dev)
|
||||
ahd_dump_device_state(struct info_str *info, struct scsi_device *sdev)
|
||||
{
|
||||
struct ahd_linux_device *dev = scsi_transport_device_data(sdev);
|
||||
|
||||
copy_info(info, "\tChannel %c Target %d Lun %d Settings\n",
|
||||
dev->target->channel + 'A', dev->target->target, dev->lun);
|
||||
sdev->sdev_target->channel + 'A',
|
||||
sdev->sdev_target->id, sdev->lun);
|
||||
|
||||
copy_info(info, "\t\tCommands Queued %ld\n", dev->commands_issued);
|
||||
copy_info(info, "\t\tCommands Active %d\n", dev->active);
|
||||
|
@ -278,36 +282,16 @@ ahd_proc_write_seeprom(struct ahd_softc *ahd, char *buffer, int length)
|
|||
* Return information to handle /proc support for the driver.
|
||||
*/
|
||||
int
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
|
||||
ahd_linux_proc_info(char *buffer, char **start, off_t offset,
|
||||
int length, int hostno, int inout)
|
||||
#else
|
||||
ahd_linux_proc_info(struct Scsi_Host *shost, char *buffer, char **start,
|
||||
off_t offset, int length, int inout)
|
||||
#endif
|
||||
{
|
||||
struct ahd_softc *ahd;
|
||||
struct ahd_softc *ahd = *(struct ahd_softc **)shost->hostdata;
|
||||
struct info_str info;
|
||||
char ahd_info[256];
|
||||
u_long l;
|
||||
u_int max_targ;
|
||||
u_int i;
|
||||
int retval;
|
||||
|
||||
retval = -EINVAL;
|
||||
ahd_list_lock(&l);
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
|
||||
TAILQ_FOREACH(ahd, &ahd_tailq, links) {
|
||||
if (ahd->platform_data->host->host_no == hostno)
|
||||
break;
|
||||
}
|
||||
#else
|
||||
ahd = ahd_find_softc(*(struct ahd_softc **)shost->hostdata);
|
||||
#endif
|
||||
|
||||
if (ahd == NULL)
|
||||
goto done;
|
||||
|
||||
/* Has data been written to the file? */
|
||||
if (inout == TRUE) {
|
||||
retval = ahd_proc_write_seeprom(ahd, buffer, length);
|
||||
|
@ -357,6 +341,5 @@ ahd_linux_proc_info(struct Scsi_Host *shost, char *buffer, char **start,
|
|||
}
|
||||
retval = info.pos > info.offset ? info.pos - info.offset : 0;
|
||||
done:
|
||||
ahd_list_unlock(&l);
|
||||
return (retval);
|
||||
}
|
||||
|
|
|
@ -37,7 +37,7 @@
|
|||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGES.
|
||||
*
|
||||
* $Id: //depot/aic7xxx/aic7xxx/aic7xxx.h#79 $
|
||||
* $Id: //depot/aic7xxx/aic7xxx/aic7xxx.h#85 $
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
@ -243,7 +243,7 @@ typedef enum {
|
|||
*/
|
||||
AHC_AIC7850_FE = AHC_SPIOCAP|AHC_AUTOPAUSE|AHC_TARGETMODE|AHC_ULTRA,
|
||||
AHC_AIC7860_FE = AHC_AIC7850_FE,
|
||||
AHC_AIC7870_FE = AHC_TARGETMODE,
|
||||
AHC_AIC7870_FE = AHC_TARGETMODE|AHC_AUTOPAUSE,
|
||||
AHC_AIC7880_FE = AHC_AIC7870_FE|AHC_ULTRA,
|
||||
/*
|
||||
* Although we have space for both the initiator and
|
||||
|
|
|
@ -39,7 +39,7 @@
|
|||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic7xxx.reg#39 $"
|
||||
VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic7xxx.reg#40 $"
|
||||
|
||||
/*
|
||||
* This file is processed by the aic7xxx_asm utility for use in assembling
|
||||
|
@ -1306,7 +1306,6 @@ scratch_ram {
|
|||
*/
|
||||
MWI_RESIDUAL {
|
||||
size 1
|
||||
alias TARG_IMMEDIATE_SCB
|
||||
}
|
||||
/*
|
||||
* SCBID of the next SCB to be started by the controller.
|
||||
|
@ -1461,6 +1460,7 @@ scratch_ram {
|
|||
*/
|
||||
LAST_MSG {
|
||||
size 1
|
||||
alias TARG_IMMEDIATE_SCB
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -40,7 +40,7 @@
|
|||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic7xxx.seq#56 $"
|
||||
VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic7xxx.seq#58 $"
|
||||
PATCH_ARG_LIST = "struct ahc_softc *ahc"
|
||||
PREFIX = "ahc_"
|
||||
|
||||
|
@ -679,6 +679,7 @@ await_busfree:
|
|||
clr SCSIBUSL; /* Prevent bit leakage durint SELTO */
|
||||
}
|
||||
and SXFRCTL0, ~SPIOEN;
|
||||
mvi SEQ_FLAGS, NOT_IDENTIFIED|NO_CDB_SENT;
|
||||
test SSTAT1,REQINIT|BUSFREE jz .;
|
||||
test SSTAT1, BUSFREE jnz poll_for_work;
|
||||
mvi MISSED_BUSFREE call set_seqint;
|
||||
|
@ -1097,7 +1098,7 @@ ultra2_dmahalt:
|
|||
test SCB_RESIDUAL_DATACNT[3], SG_LAST_SEG jz dma_mid_sg;
|
||||
if ((ahc->flags & AHC_TARGETROLE) != 0) {
|
||||
test SSTAT0, TARGET jz dma_last_sg;
|
||||
if ((ahc->flags & AHC_TMODE_WIDEODD_BUG) != 0) {
|
||||
if ((ahc->bugs & AHC_TMODE_WIDEODD_BUG) != 0) {
|
||||
test DMAPARAMS, DIRECTION jz dma_mid_sg;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,9 +28,7 @@
|
|||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: //depot/aic7xxx/aic7xxx/aic7xxx_93cx6.c#17 $
|
||||
*
|
||||
* $FreeBSD$
|
||||
* $Id: //depot/aic7xxx/aic7xxx/aic7xxx_93cx6.c#19 $
|
||||
*/
|
||||
|
||||
/*
|
||||
|
@ -64,7 +62,6 @@
|
|||
* is preceded by an initial zero (leading 0, followed by 16-bits, MSB
|
||||
* first). The clock cycling from low to high initiates the next data
|
||||
* bit to be sent from the chip.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef __linux__
|
||||
|
@ -81,14 +78,22 @@
|
|||
* Right now, we only have to read the SEEPROM. But we make it easier to
|
||||
* add other 93Cx6 functions.
|
||||
*/
|
||||
static struct seeprom_cmd {
|
||||
struct seeprom_cmd {
|
||||
uint8_t len;
|
||||
uint8_t bits[9];
|
||||
} seeprom_read = {3, {1, 1, 0}};
|
||||
uint8_t bits[11];
|
||||
};
|
||||
|
||||
/* Short opcodes for the c46 */
|
||||
static struct seeprom_cmd seeprom_ewen = {9, {1, 0, 0, 1, 1, 0, 0, 0, 0}};
|
||||
static struct seeprom_cmd seeprom_ewds = {9, {1, 0, 0, 0, 0, 0, 0, 0, 0}};
|
||||
|
||||
/* Long opcodes for the C56/C66 */
|
||||
static struct seeprom_cmd seeprom_long_ewen = {11, {1, 0, 0, 1, 1, 0, 0, 0, 0}};
|
||||
static struct seeprom_cmd seeprom_long_ewds = {11, {1, 0, 0, 0, 0, 0, 0, 0, 0}};
|
||||
|
||||
/* Common opcodes */
|
||||
static struct seeprom_cmd seeprom_write = {3, {1, 0, 1}};
|
||||
static struct seeprom_cmd seeprom_read = {3, {1, 1, 0}};
|
||||
|
||||
/*
|
||||
* Wait for the SEERDY to go high; about 800 ns.
|
||||
|
@ -222,12 +227,25 @@ int
|
|||
ahc_write_seeprom(struct seeprom_descriptor *sd, uint16_t *buf,
|
||||
u_int start_addr, u_int count)
|
||||
{
|
||||
struct seeprom_cmd *ewen, *ewds;
|
||||
uint16_t v;
|
||||
uint8_t temp;
|
||||
int i, k;
|
||||
|
||||
/* Place the chip into write-enable mode */
|
||||
send_seeprom_cmd(sd, &seeprom_ewen);
|
||||
if (sd->sd_chip == C46) {
|
||||
ewen = &seeprom_ewen;
|
||||
ewds = &seeprom_ewds;
|
||||
} else if (sd->sd_chip == C56_66) {
|
||||
ewen = &seeprom_long_ewen;
|
||||
ewds = &seeprom_long_ewds;
|
||||
} else {
|
||||
printf("ahc_write_seeprom: unsupported seeprom type %d\n",
|
||||
sd->sd_chip);
|
||||
return (0);
|
||||
}
|
||||
|
||||
send_seeprom_cmd(sd, ewen);
|
||||
reset_seeprom(sd);
|
||||
|
||||
/* Write all requested data out to the seeprom. */
|
||||
|
@ -277,7 +295,7 @@ ahc_write_seeprom(struct seeprom_descriptor *sd, uint16_t *buf,
|
|||
}
|
||||
|
||||
/* Put the chip back into write-protect mode */
|
||||
send_seeprom_cmd(sd, &seeprom_ewds);
|
||||
send_seeprom_cmd(sd, ewds);
|
||||
reset_seeprom(sd);
|
||||
|
||||
return (1);
|
||||
|
|
|
@ -37,9 +37,7 @@
|
|||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGES.
|
||||
*
|
||||
* $Id: //depot/aic7xxx/aic7xxx/aic7xxx.c#134 $
|
||||
*
|
||||
* $FreeBSD$
|
||||
* $Id: //depot/aic7xxx/aic7xxx/aic7xxx.c#155 $
|
||||
*/
|
||||
|
||||
#ifdef __linux__
|
||||
|
@ -287,10 +285,19 @@ ahc_restart(struct ahc_softc *ahc)
|
|||
ahc_outb(ahc, SEQ_FLAGS2,
|
||||
ahc_inb(ahc, SEQ_FLAGS2) & ~SCB_DMA);
|
||||
}
|
||||
|
||||
/*
|
||||
* Clear any pending sequencer interrupt. It is no
|
||||
* longer relevant since we're resetting the Program
|
||||
* Counter.
|
||||
*/
|
||||
ahc_outb(ahc, CLRINT, CLRSEQINT);
|
||||
|
||||
ahc_outb(ahc, MWI_RESIDUAL, 0);
|
||||
ahc_outb(ahc, SEQCTL, ahc->seqctl);
|
||||
ahc_outb(ahc, SEQADDR0, 0);
|
||||
ahc_outb(ahc, SEQADDR1, 0);
|
||||
|
||||
ahc_unpause(ahc);
|
||||
}
|
||||
|
||||
|
@ -1174,19 +1181,20 @@ ahc_handle_scsiint(struct ahc_softc *ahc, u_int intstat)
|
|||
scb_index);
|
||||
}
|
||||
#endif
|
||||
/*
|
||||
* Force a renegotiation with this target just in
|
||||
* case the cable was pulled and will later be
|
||||
* re-attached. The target may forget its negotiation
|
||||
* settings with us should it attempt to reselect
|
||||
* during the interruption. The target will not issue
|
||||
* a unit attention in this case, so we must always
|
||||
* renegotiate.
|
||||
*/
|
||||
ahc_scb_devinfo(ahc, &devinfo, scb);
|
||||
ahc_force_renegotiation(ahc, &devinfo);
|
||||
ahc_set_transaction_status(scb, CAM_SEL_TIMEOUT);
|
||||
ahc_freeze_devq(ahc, scb);
|
||||
|
||||
/*
|
||||
* Cancel any pending transactions on the device
|
||||
* now that it seems to be missing. This will
|
||||
* also revert us to async/narrow transfers until
|
||||
* we can renegotiate with the device.
|
||||
*/
|
||||
ahc_handle_devreset(ahc, &devinfo,
|
||||
CAM_SEL_TIMEOUT,
|
||||
"Selection Timeout",
|
||||
/*verbose_level*/1);
|
||||
}
|
||||
ahc_outb(ahc, CLRINT, CLRSCSIINT);
|
||||
ahc_restart(ahc);
|
||||
|
@ -3763,6 +3771,7 @@ ahc_handle_devreset(struct ahc_softc *ahc, struct ahc_devinfo *devinfo,
|
|||
/*period*/0, /*offset*/0, /*ppr_options*/0,
|
||||
AHC_TRANS_CUR, /*paused*/TRUE);
|
||||
|
||||
if (status != CAM_SEL_TIMEOUT)
|
||||
ahc_send_async(ahc, devinfo->channel, devinfo->target,
|
||||
CAM_LUN_WILDCARD, AC_SENT_BDR, NULL);
|
||||
|
||||
|
@ -4003,14 +4012,6 @@ ahc_reset(struct ahc_softc *ahc, int reinit)
|
|||
* to disturb the integrity of the bus.
|
||||
*/
|
||||
ahc_pause(ahc);
|
||||
if ((ahc_inb(ahc, HCNTRL) & CHIPRST) != 0) {
|
||||
/*
|
||||
* The chip has not been initialized since
|
||||
* PCI/EISA/VLB bus reset. Don't trust
|
||||
* "left over BIOS data".
|
||||
*/
|
||||
ahc->flags |= AHC_NO_BIOS_INIT;
|
||||
}
|
||||
sxfrctl1_b = 0;
|
||||
if ((ahc->chip & AHC_CHIPID_MASK) == AHC_AIC7770) {
|
||||
u_int sblkctl;
|
||||
|
@ -5036,14 +5037,23 @@ ahc_pause_and_flushwork(struct ahc_softc *ahc)
|
|||
ahc->flags |= AHC_ALL_INTERRUPTS;
|
||||
paused = FALSE;
|
||||
do {
|
||||
if (paused)
|
||||
if (paused) {
|
||||
ahc_unpause(ahc);
|
||||
/*
|
||||
* Give the sequencer some time to service
|
||||
* any active selections.
|
||||
*/
|
||||
ahc_delay(500);
|
||||
}
|
||||
ahc_intr(ahc);
|
||||
ahc_pause(ahc);
|
||||
paused = TRUE;
|
||||
ahc_outb(ahc, SCSISEQ, ahc_inb(ahc, SCSISEQ) & ~ENSELO);
|
||||
intstat = ahc_inb(ahc, INTSTAT);
|
||||
if ((intstat & INT_PEND) == 0) {
|
||||
ahc_clear_critical_section(ahc);
|
||||
intstat = ahc_inb(ahc, INTSTAT);
|
||||
}
|
||||
} while (--maxloops
|
||||
&& (intstat != 0xFF || (ahc->features & AHC_REMOVABLE) == 0)
|
||||
&& ((intstat & INT_PEND) != 0
|
||||
|
|
|
@ -635,6 +635,8 @@ ahc_linux_slave_alloc(struct scsi_device *sdev)
|
|||
|
||||
targ->sdev[sdev->lun] = sdev;
|
||||
|
||||
spi_period(starget) = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1612,9 +1614,9 @@ ahc_send_async(struct ahc_softc *ahc, char channel,
|
|||
if (channel == 'B')
|
||||
target_offset += 8;
|
||||
starget = ahc->platform_data->starget[target_offset];
|
||||
targ = scsi_transport_target_data(starget);
|
||||
if (targ == NULL)
|
||||
if (starget == NULL)
|
||||
break;
|
||||
targ = scsi_transport_target_data(starget);
|
||||
|
||||
target_ppr_options =
|
||||
(spi_dt(starget) ? MSG_EXT_PPR_DT_REQ : 0)
|
||||
|
@ -2329,8 +2331,6 @@ ahc_platform_dump_card_state(struct ahc_softc *ahc)
|
|||
{
|
||||
}
|
||||
|
||||
static void ahc_linux_exit(void);
|
||||
|
||||
static void ahc_linux_set_width(struct scsi_target *starget, int width)
|
||||
{
|
||||
struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
|
||||
|
|
|
@ -265,7 +265,7 @@ ahc_scb_timer_reset(struct scb *scb, u_int usec)
|
|||
/***************************** SMP support ************************************/
|
||||
#include <linux/spinlock.h>
|
||||
|
||||
#define AIC7XXX_DRIVER_VERSION "6.2.36"
|
||||
#define AIC7XXX_DRIVER_VERSION "7.0"
|
||||
|
||||
/*************************** Device Data Structures ***************************/
|
||||
/*
|
||||
|
|
|
@ -149,6 +149,27 @@ ahc_linux_pci_dev_remove(struct pci_dev *pdev)
|
|||
ahc_free(ahc);
|
||||
}
|
||||
|
||||
static void
|
||||
ahc_linux_pci_inherit_flags(struct ahc_softc *ahc)
|
||||
{
|
||||
struct pci_dev *pdev = ahc->dev_softc, *master_pdev;
|
||||
unsigned int master_devfn = PCI_DEVFN(PCI_SLOT(pdev->devfn), 0);
|
||||
|
||||
master_pdev = pci_get_slot(pdev->bus, master_devfn);
|
||||
if (master_pdev) {
|
||||
struct ahc_softc *master = pci_get_drvdata(master_pdev);
|
||||
if (master) {
|
||||
ahc->flags &= ~AHC_BIOS_ENABLED;
|
||||
ahc->flags |= master->flags & AHC_BIOS_ENABLED;
|
||||
|
||||
ahc->flags &= ~AHC_PRIMARY_CHANNEL;
|
||||
ahc->flags |= master->flags & AHC_PRIMARY_CHANNEL;
|
||||
} else
|
||||
printk(KERN_ERR "aic7xxx: no multichannel peer found!\n");
|
||||
pci_dev_put(master_pdev);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
ahc_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
{
|
||||
|
@ -203,6 +224,14 @@ ahc_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
|||
ahc_free(ahc);
|
||||
return (-error);
|
||||
}
|
||||
|
||||
/*
|
||||
* Second Function PCI devices need to inherit some
|
||||
* settings from function 0.
|
||||
*/
|
||||
if ((ahc->features & AHC_MULTI_FUNC) && PCI_FUNC(pdev->devfn) != 0)
|
||||
ahc_linux_pci_inherit_flags(ahc);
|
||||
|
||||
pci_set_drvdata(pdev, ahc);
|
||||
ahc_linux_register_host(ahc, &aic7xxx_driver_template);
|
||||
return (0);
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
* DO NOT EDIT - This file is automatically generated
|
||||
* from the following source files:
|
||||
*
|
||||
* $Id: //depot/aic7xxx/aic7xxx/aic7xxx.seq#56 $
|
||||
* $Id: //depot/aic7xxx/aic7xxx/aic7xxx.reg#39 $
|
||||
* $Id: //depot/aic7xxx/aic7xxx/aic7xxx.seq#58 $
|
||||
* $Id: //depot/aic7xxx/aic7xxx/aic7xxx.reg#40 $
|
||||
*/
|
||||
typedef int (ahc_reg_print_t)(u_int, u_int *, u_int);
|
||||
typedef struct ahc_reg_parse_entry {
|
||||
|
@ -1298,7 +1298,6 @@ ahc_reg_print_t ahc_sg_cache_pre_print;
|
|||
#define CMDSIZE_TABLE_TAIL 0x34
|
||||
|
||||
#define MWI_RESIDUAL 0x38
|
||||
#define TARG_IMMEDIATE_SCB 0x38
|
||||
|
||||
#define NEXT_QUEUED_SCB 0x39
|
||||
|
||||
|
@ -1380,6 +1379,7 @@ ahc_reg_print_t ahc_sg_cache_pre_print;
|
|||
#define RETURN_2 0x52
|
||||
|
||||
#define LAST_MSG 0x53
|
||||
#define TARG_IMMEDIATE_SCB 0x53
|
||||
|
||||
#define SCSISEQ_TEMPLATE 0x54
|
||||
#define ENSELO 0x40
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
* DO NOT EDIT - This file is automatically generated
|
||||
* from the following source files:
|
||||
*
|
||||
* $Id: //depot/aic7xxx/aic7xxx/aic7xxx.seq#56 $
|
||||
* $Id: //depot/aic7xxx/aic7xxx/aic7xxx.reg#39 $
|
||||
* $Id: //depot/aic7xxx/aic7xxx/aic7xxx.seq#58 $
|
||||
* $Id: //depot/aic7xxx/aic7xxx/aic7xxx.reg#40 $
|
||||
*/
|
||||
|
||||
#include "aic7xxx_osm.h"
|
||||
|
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -57,121 +57,6 @@
|
|||
#ifndef _AICLIB_H
|
||||
#define _AICLIB_H
|
||||
|
||||
/*
|
||||
* Linux Interrupt Support.
|
||||
*/
|
||||
#ifndef IRQ_RETVAL
|
||||
typedef void irqreturn_t;
|
||||
#define IRQ_RETVAL(x)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* SCSI command format
|
||||
*/
|
||||
|
||||
/*
|
||||
* Define dome bits that are in ALL (or a lot of) scsi commands
|
||||
*/
|
||||
#define SCSI_CTL_LINK 0x01
|
||||
#define SCSI_CTL_FLAG 0x02
|
||||
#define SCSI_CTL_VENDOR 0xC0
|
||||
#define SCSI_CMD_LUN 0xA0 /* these two should not be needed */
|
||||
#define SCSI_CMD_LUN_SHIFT 5 /* LUN in the cmd is no longer SCSI */
|
||||
|
||||
#define SCSI_MAX_CDBLEN 16 /*
|
||||
* 16 byte commands are in the
|
||||
* SCSI-3 spec
|
||||
*/
|
||||
/* 6byte CDBs special case 0 length to be 256 */
|
||||
#define SCSI_CDB6_LEN(len) ((len) == 0 ? 256 : len)
|
||||
|
||||
/*
|
||||
* This type defines actions to be taken when a particular sense code is
|
||||
* received. Right now, these flags are only defined to take up 16 bits,
|
||||
* but can be expanded in the future if necessary.
|
||||
*/
|
||||
typedef enum {
|
||||
SS_NOP = 0x000000, /* Do nothing */
|
||||
SS_RETRY = 0x010000, /* Retry the command */
|
||||
SS_FAIL = 0x020000, /* Bail out */
|
||||
SS_START = 0x030000, /* Send a Start Unit command to the device,
|
||||
* then retry the original command.
|
||||
*/
|
||||
SS_TUR = 0x040000, /* Send a Test Unit Ready command to the
|
||||
* device, then retry the original command.
|
||||
*/
|
||||
SS_REQSENSE = 0x050000, /* Send a RequestSense command to the
|
||||
* device, then retry the original command.
|
||||
*/
|
||||
SS_INQ_REFRESH = 0x060000,
|
||||
SS_MASK = 0xff0000
|
||||
} aic_sense_action;
|
||||
|
||||
typedef enum {
|
||||
SSQ_NONE = 0x0000,
|
||||
SSQ_DECREMENT_COUNT = 0x0100, /* Decrement the retry count */
|
||||
SSQ_MANY = 0x0200, /* send lots of recovery commands */
|
||||
SSQ_RANGE = 0x0400, /*
|
||||
* This table entry represents the
|
||||
* end of a range of ASCQs that
|
||||
* have identical error actions
|
||||
* and text.
|
||||
*/
|
||||
SSQ_PRINT_SENSE = 0x0800,
|
||||
SSQ_DELAY = 0x1000, /* Delay before retry. */
|
||||
SSQ_DELAY_RANDOM = 0x2000, /* Randomized delay before retry. */
|
||||
SSQ_FALLBACK = 0x4000, /* Do a speed fallback to recover */
|
||||
SSQ_MASK = 0xff00
|
||||
} aic_sense_action_qualifier;
|
||||
|
||||
/* Mask for error status values */
|
||||
#define SS_ERRMASK 0xff
|
||||
|
||||
/* The default, retyable, error action */
|
||||
#define SS_RDEF SS_RETRY|SSQ_DECREMENT_COUNT|SSQ_PRINT_SENSE|EIO
|
||||
|
||||
/* The retyable, error action, with table specified error code */
|
||||
#define SS_RET SS_RETRY|SSQ_DECREMENT_COUNT|SSQ_PRINT_SENSE
|
||||
|
||||
/* Fatal error action, with table specified error code */
|
||||
#define SS_FATAL SS_FAIL|SSQ_PRINT_SENSE
|
||||
|
||||
struct scsi_generic
|
||||
{
|
||||
uint8_t opcode;
|
||||
uint8_t bytes[11];
|
||||
};
|
||||
|
||||
struct scsi_request_sense
|
||||
{
|
||||
uint8_t opcode;
|
||||
uint8_t byte2;
|
||||
uint8_t unused[2];
|
||||
uint8_t length;
|
||||
uint8_t control;
|
||||
};
|
||||
|
||||
struct scsi_test_unit_ready
|
||||
{
|
||||
uint8_t opcode;
|
||||
uint8_t byte2;
|
||||
uint8_t unused[3];
|
||||
uint8_t control;
|
||||
};
|
||||
|
||||
struct scsi_send_diag
|
||||
{
|
||||
uint8_t opcode;
|
||||
uint8_t byte2;
|
||||
#define SSD_UOL 0x01
|
||||
#define SSD_DOL 0x02
|
||||
#define SSD_SELFTEST 0x04
|
||||
#define SSD_PF 0x10
|
||||
uint8_t unused[1];
|
||||
uint8_t paramlen[2];
|
||||
uint8_t control;
|
||||
};
|
||||
|
||||
struct scsi_sense
|
||||
{
|
||||
uint8_t opcode;
|
||||
|
@ -181,537 +66,12 @@ struct scsi_sense
|
|||
uint8_t control;
|
||||
};
|
||||
|
||||
struct scsi_inquiry
|
||||
{
|
||||
uint8_t opcode;
|
||||
uint8_t byte2;
|
||||
#define SI_EVPD 0x01
|
||||
uint8_t page_code;
|
||||
uint8_t reserved;
|
||||
uint8_t length;
|
||||
uint8_t control;
|
||||
};
|
||||
|
||||
struct scsi_mode_sense_6
|
||||
{
|
||||
uint8_t opcode;
|
||||
uint8_t byte2;
|
||||
#define SMS_DBD 0x08
|
||||
uint8_t page;
|
||||
#define SMS_PAGE_CODE 0x3F
|
||||
#define SMS_VENDOR_SPECIFIC_PAGE 0x00
|
||||
#define SMS_DISCONNECT_RECONNECT_PAGE 0x02
|
||||
#define SMS_PERIPHERAL_DEVICE_PAGE 0x09
|
||||
#define SMS_CONTROL_MODE_PAGE 0x0A
|
||||
#define SMS_ALL_PAGES_PAGE 0x3F
|
||||
#define SMS_PAGE_CTRL_MASK 0xC0
|
||||
#define SMS_PAGE_CTRL_CURRENT 0x00
|
||||
#define SMS_PAGE_CTRL_CHANGEABLE 0x40
|
||||
#define SMS_PAGE_CTRL_DEFAULT 0x80
|
||||
#define SMS_PAGE_CTRL_SAVED 0xC0
|
||||
uint8_t unused;
|
||||
uint8_t length;
|
||||
uint8_t control;
|
||||
};
|
||||
|
||||
struct scsi_mode_sense_10
|
||||
{
|
||||
uint8_t opcode;
|
||||
uint8_t byte2; /* same bits as small version */
|
||||
uint8_t page; /* same bits as small version */
|
||||
uint8_t unused[4];
|
||||
uint8_t length[2];
|
||||
uint8_t control;
|
||||
};
|
||||
|
||||
struct scsi_mode_select_6
|
||||
{
|
||||
uint8_t opcode;
|
||||
uint8_t byte2;
|
||||
#define SMS_SP 0x01
|
||||
#define SMS_PF 0x10
|
||||
uint8_t unused[2];
|
||||
uint8_t length;
|
||||
uint8_t control;
|
||||
};
|
||||
|
||||
struct scsi_mode_select_10
|
||||
{
|
||||
uint8_t opcode;
|
||||
uint8_t byte2; /* same bits as small version */
|
||||
uint8_t unused[5];
|
||||
uint8_t length[2];
|
||||
uint8_t control;
|
||||
};
|
||||
|
||||
/*
|
||||
* When sending a mode select to a tape drive, the medium type must be 0.
|
||||
*/
|
||||
struct scsi_mode_hdr_6
|
||||
{
|
||||
uint8_t datalen;
|
||||
uint8_t medium_type;
|
||||
uint8_t dev_specific;
|
||||
uint8_t block_descr_len;
|
||||
};
|
||||
|
||||
struct scsi_mode_hdr_10
|
||||
{
|
||||
uint8_t datalen[2];
|
||||
uint8_t medium_type;
|
||||
uint8_t dev_specific;
|
||||
uint8_t reserved[2];
|
||||
uint8_t block_descr_len[2];
|
||||
};
|
||||
|
||||
struct scsi_mode_block_descr
|
||||
{
|
||||
uint8_t density_code;
|
||||
uint8_t num_blocks[3];
|
||||
uint8_t reserved;
|
||||
uint8_t block_len[3];
|
||||
};
|
||||
|
||||
struct scsi_log_sense
|
||||
{
|
||||
uint8_t opcode;
|
||||
uint8_t byte2;
|
||||
#define SLS_SP 0x01
|
||||
#define SLS_PPC 0x02
|
||||
uint8_t page;
|
||||
#define SLS_PAGE_CODE 0x3F
|
||||
#define SLS_ALL_PAGES_PAGE 0x00
|
||||
#define SLS_OVERRUN_PAGE 0x01
|
||||
#define SLS_ERROR_WRITE_PAGE 0x02
|
||||
#define SLS_ERROR_READ_PAGE 0x03
|
||||
#define SLS_ERROR_READREVERSE_PAGE 0x04
|
||||
#define SLS_ERROR_VERIFY_PAGE 0x05
|
||||
#define SLS_ERROR_NONMEDIUM_PAGE 0x06
|
||||
#define SLS_ERROR_LASTN_PAGE 0x07
|
||||
#define SLS_PAGE_CTRL_MASK 0xC0
|
||||
#define SLS_PAGE_CTRL_THRESHOLD 0x00
|
||||
#define SLS_PAGE_CTRL_CUMULATIVE 0x40
|
||||
#define SLS_PAGE_CTRL_THRESH_DEFAULT 0x80
|
||||
#define SLS_PAGE_CTRL_CUMUL_DEFAULT 0xC0
|
||||
uint8_t reserved[2];
|
||||
uint8_t paramptr[2];
|
||||
uint8_t length[2];
|
||||
uint8_t control;
|
||||
};
|
||||
|
||||
struct scsi_log_select
|
||||
{
|
||||
uint8_t opcode;
|
||||
uint8_t byte2;
|
||||
/* SLS_SP 0x01 */
|
||||
#define SLS_PCR 0x02
|
||||
uint8_t page;
|
||||
/* SLS_PAGE_CTRL_MASK 0xC0 */
|
||||
/* SLS_PAGE_CTRL_THRESHOLD 0x00 */
|
||||
/* SLS_PAGE_CTRL_CUMULATIVE 0x40 */
|
||||
/* SLS_PAGE_CTRL_THRESH_DEFAULT 0x80 */
|
||||
/* SLS_PAGE_CTRL_CUMUL_DEFAULT 0xC0 */
|
||||
uint8_t reserved[4];
|
||||
uint8_t length[2];
|
||||
uint8_t control;
|
||||
};
|
||||
|
||||
struct scsi_log_header
|
||||
{
|
||||
uint8_t page;
|
||||
uint8_t reserved;
|
||||
uint8_t datalen[2];
|
||||
};
|
||||
|
||||
struct scsi_log_param_header {
|
||||
uint8_t param_code[2];
|
||||
uint8_t param_control;
|
||||
#define SLP_LP 0x01
|
||||
#define SLP_LBIN 0x02
|
||||
#define SLP_TMC_MASK 0x0C
|
||||
#define SLP_TMC_ALWAYS 0x00
|
||||
#define SLP_TMC_EQUAL 0x04
|
||||
#define SLP_TMC_NOTEQUAL 0x08
|
||||
#define SLP_TMC_GREATER 0x0C
|
||||
#define SLP_ETC 0x10
|
||||
#define SLP_TSD 0x20
|
||||
#define SLP_DS 0x40
|
||||
#define SLP_DU 0x80
|
||||
uint8_t param_len;
|
||||
};
|
||||
|
||||
struct scsi_control_page {
|
||||
uint8_t page_code;
|
||||
uint8_t page_length;
|
||||
uint8_t rlec;
|
||||
#define SCB_RLEC 0x01 /*Report Log Exception Cond*/
|
||||
uint8_t queue_flags;
|
||||
#define SCP_QUEUE_ALG_MASK 0xF0
|
||||
#define SCP_QUEUE_ALG_RESTRICTED 0x00
|
||||
#define SCP_QUEUE_ALG_UNRESTRICTED 0x10
|
||||
#define SCP_QUEUE_ERR 0x02 /*Queued I/O aborted for CACs*/
|
||||
#define SCP_QUEUE_DQUE 0x01 /*Queued I/O disabled*/
|
||||
uint8_t eca_and_aen;
|
||||
#define SCP_EECA 0x80 /*Enable Extended CA*/
|
||||
#define SCP_RAENP 0x04 /*Ready AEN Permission*/
|
||||
#define SCP_UAAENP 0x02 /*UA AEN Permission*/
|
||||
#define SCP_EAENP 0x01 /*Error AEN Permission*/
|
||||
uint8_t reserved;
|
||||
uint8_t aen_holdoff_period[2];
|
||||
};
|
||||
|
||||
struct scsi_reserve
|
||||
{
|
||||
uint8_t opcode;
|
||||
uint8_t byte2;
|
||||
uint8_t unused[2];
|
||||
uint8_t length;
|
||||
uint8_t control;
|
||||
};
|
||||
|
||||
struct scsi_release
|
||||
{
|
||||
uint8_t opcode;
|
||||
uint8_t byte2;
|
||||
uint8_t unused[2];
|
||||
uint8_t length;
|
||||
uint8_t control;
|
||||
};
|
||||
|
||||
struct scsi_prevent
|
||||
{
|
||||
uint8_t opcode;
|
||||
uint8_t byte2;
|
||||
uint8_t unused[2];
|
||||
uint8_t how;
|
||||
uint8_t control;
|
||||
};
|
||||
#define PR_PREVENT 0x01
|
||||
#define PR_ALLOW 0x00
|
||||
|
||||
struct scsi_sync_cache
|
||||
{
|
||||
uint8_t opcode;
|
||||
uint8_t byte2;
|
||||
uint8_t begin_lba[4];
|
||||
uint8_t reserved;
|
||||
uint8_t lb_count[2];
|
||||
uint8_t control;
|
||||
};
|
||||
|
||||
|
||||
struct scsi_changedef
|
||||
{
|
||||
uint8_t opcode;
|
||||
uint8_t byte2;
|
||||
uint8_t unused1;
|
||||
uint8_t how;
|
||||
uint8_t unused[4];
|
||||
uint8_t datalen;
|
||||
uint8_t control;
|
||||
};
|
||||
|
||||
struct scsi_read_buffer
|
||||
{
|
||||
uint8_t opcode;
|
||||
uint8_t byte2;
|
||||
#define RWB_MODE 0x07
|
||||
#define RWB_MODE_HDR_DATA 0x00
|
||||
#define RWB_MODE_DATA 0x02
|
||||
#define RWB_MODE_DOWNLOAD 0x04
|
||||
#define RWB_MODE_DOWNLOAD_SAVE 0x05
|
||||
uint8_t buffer_id;
|
||||
uint8_t offset[3];
|
||||
uint8_t length[3];
|
||||
uint8_t control;
|
||||
};
|
||||
|
||||
struct scsi_write_buffer
|
||||
{
|
||||
uint8_t opcode;
|
||||
uint8_t byte2;
|
||||
uint8_t buffer_id;
|
||||
uint8_t offset[3];
|
||||
uint8_t length[3];
|
||||
uint8_t control;
|
||||
};
|
||||
|
||||
struct scsi_rw_6
|
||||
{
|
||||
uint8_t opcode;
|
||||
uint8_t addr[3];
|
||||
/* only 5 bits are valid in the MSB address byte */
|
||||
#define SRW_TOPADDR 0x1F
|
||||
uint8_t length;
|
||||
uint8_t control;
|
||||
};
|
||||
|
||||
struct scsi_rw_10
|
||||
{
|
||||
uint8_t opcode;
|
||||
#define SRW10_RELADDR 0x01
|
||||
#define SRW10_FUA 0x08
|
||||
#define SRW10_DPO 0x10
|
||||
uint8_t byte2;
|
||||
uint8_t addr[4];
|
||||
uint8_t reserved;
|
||||
uint8_t length[2];
|
||||
uint8_t control;
|
||||
};
|
||||
|
||||
struct scsi_rw_12
|
||||
{
|
||||
uint8_t opcode;
|
||||
#define SRW12_RELADDR 0x01
|
||||
#define SRW12_FUA 0x08
|
||||
#define SRW12_DPO 0x10
|
||||
uint8_t byte2;
|
||||
uint8_t addr[4];
|
||||
uint8_t length[4];
|
||||
uint8_t reserved;
|
||||
uint8_t control;
|
||||
};
|
||||
|
||||
struct scsi_start_stop_unit
|
||||
{
|
||||
uint8_t opcode;
|
||||
uint8_t byte2;
|
||||
#define SSS_IMMED 0x01
|
||||
uint8_t reserved[2];
|
||||
uint8_t how;
|
||||
#define SSS_START 0x01
|
||||
#define SSS_LOEJ 0x02
|
||||
uint8_t control;
|
||||
};
|
||||
|
||||
#define SC_SCSI_1 0x01
|
||||
#define SC_SCSI_2 0x03
|
||||
|
||||
/*
|
||||
* Opcodes
|
||||
*/
|
||||
|
||||
#define TEST_UNIT_READY 0x00
|
||||
#define REQUEST_SENSE 0x03
|
||||
#define READ_6 0x08
|
||||
#define WRITE_6 0x0a
|
||||
#define INQUIRY 0x12
|
||||
#define MODE_SELECT_6 0x15
|
||||
#define MODE_SENSE_6 0x1a
|
||||
#define START_STOP_UNIT 0x1b
|
||||
#define START_STOP 0x1b
|
||||
#define RESERVE 0x16
|
||||
#define RELEASE 0x17
|
||||
#define RECEIVE_DIAGNOSTIC 0x1c
|
||||
#define SEND_DIAGNOSTIC 0x1d
|
||||
#define PREVENT_ALLOW 0x1e
|
||||
#define READ_CAPACITY 0x25
|
||||
#define READ_10 0x28
|
||||
#define WRITE_10 0x2a
|
||||
#define POSITION_TO_ELEMENT 0x2b
|
||||
#define SYNCHRONIZE_CACHE 0x35
|
||||
#define WRITE_BUFFER 0x3b
|
||||
#define READ_BUFFER 0x3c
|
||||
#define CHANGE_DEFINITION 0x40
|
||||
#define LOG_SELECT 0x4c
|
||||
#define LOG_SENSE 0x4d
|
||||
#ifdef XXXCAM
|
||||
#define MODE_SENSE_10 0x5A
|
||||
#endif
|
||||
#define MODE_SELECT_10 0x55
|
||||
#define MOVE_MEDIUM 0xa5
|
||||
#define READ_12 0xa8
|
||||
#define WRITE_12 0xaa
|
||||
#define READ_ELEMENT_STATUS 0xb8
|
||||
|
||||
|
||||
/*
|
||||
* Device Types
|
||||
*/
|
||||
#define T_DIRECT 0x00
|
||||
#define T_SEQUENTIAL 0x01
|
||||
#define T_PRINTER 0x02
|
||||
#define T_PROCESSOR 0x03
|
||||
#define T_WORM 0x04
|
||||
#define T_CDROM 0x05
|
||||
#define T_SCANNER 0x06
|
||||
#define T_OPTICAL 0x07
|
||||
#define T_CHANGER 0x08
|
||||
#define T_COMM 0x09
|
||||
#define T_ASC0 0x0a
|
||||
#define T_ASC1 0x0b
|
||||
#define T_STORARRAY 0x0c
|
||||
#define T_ENCLOSURE 0x0d
|
||||
#define T_RBC 0x0e
|
||||
#define T_OCRW 0x0f
|
||||
#define T_NODEVICE 0x1F
|
||||
#define T_ANY 0xFF /* Used in Quirk table matches */
|
||||
|
||||
#define T_REMOV 1
|
||||
#define T_FIXED 0
|
||||
|
||||
/*
|
||||
* This length is the initial inquiry length used by the probe code, as
|
||||
* well as the legnth necessary for aic_print_inquiry() to function
|
||||
* correctly. If either use requires a different length in the future,
|
||||
* the two values should be de-coupled.
|
||||
*/
|
||||
#define SHORT_INQUIRY_LENGTH 36
|
||||
|
||||
struct scsi_inquiry_data
|
||||
{
|
||||
uint8_t device;
|
||||
#define SID_TYPE(inq_data) ((inq_data)->device & 0x1f)
|
||||
#define SID_QUAL(inq_data) (((inq_data)->device & 0xE0) >> 5)
|
||||
#define SID_QUAL_LU_CONNECTED 0x00 /*
|
||||
* The specified peripheral device
|
||||
* type is currently connected to
|
||||
* logical unit. If the target cannot
|
||||
* determine whether or not a physical
|
||||
* device is currently connected, it
|
||||
* shall also use this peripheral
|
||||
* qualifier when returning the INQUIRY
|
||||
* data. This peripheral qualifier
|
||||
* does not mean that the device is
|
||||
* ready for access by the initiator.
|
||||
*/
|
||||
#define SID_QUAL_LU_OFFLINE 0x01 /*
|
||||
* The target is capable of supporting
|
||||
* the specified peripheral device type
|
||||
* on this logical unit; however, the
|
||||
* physical device is not currently
|
||||
* connected to this logical unit.
|
||||
*/
|
||||
#define SID_QUAL_RSVD 0x02
|
||||
#define SID_QUAL_BAD_LU 0x03 /*
|
||||
* The target is not capable of
|
||||
* supporting a physical device on
|
||||
* this logical unit. For this
|
||||
* peripheral qualifier the peripheral
|
||||
* device type shall be set to 1Fh to
|
||||
* provide compatibility with previous
|
||||
* versions of SCSI. All other
|
||||
* peripheral device type values are
|
||||
* reserved for this peripheral
|
||||
* qualifier.
|
||||
*/
|
||||
#define SID_QUAL_IS_VENDOR_UNIQUE(inq_data) ((SID_QUAL(inq_data) & 0x08) != 0)
|
||||
uint8_t dev_qual2;
|
||||
#define SID_QUAL2 0x7F
|
||||
#define SID_IS_REMOVABLE(inq_data) (((inq_data)->dev_qual2 & 0x80) != 0)
|
||||
uint8_t version;
|
||||
#define SID_ANSI_REV(inq_data) ((inq_data)->version & 0x07)
|
||||
#define SCSI_REV_0 0
|
||||
#define SCSI_REV_CCS 1
|
||||
#define SCSI_REV_2 2
|
||||
#define SCSI_REV_SPC 3
|
||||
#define SCSI_REV_SPC2 4
|
||||
|
||||
#define SID_ECMA 0x38
|
||||
#define SID_ISO 0xC0
|
||||
uint8_t response_format;
|
||||
#define SID_AENC 0x80
|
||||
#define SID_TrmIOP 0x40
|
||||
uint8_t additional_length;
|
||||
uint8_t reserved[2];
|
||||
uint8_t flags;
|
||||
#define SID_SftRe 0x01
|
||||
#define SID_CmdQue 0x02
|
||||
#define SID_Linked 0x08
|
||||
#define SID_Sync 0x10
|
||||
#define SID_WBus16 0x20
|
||||
#define SID_WBus32 0x40
|
||||
#define SID_RelAdr 0x80
|
||||
#define SID_VENDOR_SIZE 8
|
||||
char vendor[SID_VENDOR_SIZE];
|
||||
#define SID_PRODUCT_SIZE 16
|
||||
char product[SID_PRODUCT_SIZE];
|
||||
#define SID_REVISION_SIZE 4
|
||||
char revision[SID_REVISION_SIZE];
|
||||
/*
|
||||
* The following fields were taken from SCSI Primary Commands - 2
|
||||
* (SPC-2) Revision 14, Dated 11 November 1999
|
||||
*/
|
||||
#define SID_VENDOR_SPECIFIC_0_SIZE 20
|
||||
uint8_t vendor_specific0[SID_VENDOR_SPECIFIC_0_SIZE];
|
||||
/*
|
||||
* An extension of SCSI Parallel Specific Values
|
||||
*/
|
||||
#define SID_SPI_IUS 0x01
|
||||
#define SID_SPI_QAS 0x02
|
||||
#define SID_SPI_CLOCK_ST 0x00
|
||||
#define SID_SPI_CLOCK_DT 0x04
|
||||
#define SID_SPI_CLOCK_DT_ST 0x0C
|
||||
#define SID_SPI_MASK 0x0F
|
||||
uint8_t spi3data;
|
||||
uint8_t reserved2;
|
||||
/*
|
||||
* Version Descriptors, stored 2 byte values.
|
||||
*/
|
||||
uint8_t version1[2];
|
||||
uint8_t version2[2];
|
||||
uint8_t version3[2];
|
||||
uint8_t version4[2];
|
||||
uint8_t version5[2];
|
||||
uint8_t version6[2];
|
||||
uint8_t version7[2];
|
||||
uint8_t version8[2];
|
||||
|
||||
uint8_t reserved3[22];
|
||||
|
||||
#define SID_VENDOR_SPECIFIC_1_SIZE 160
|
||||
uint8_t vendor_specific1[SID_VENDOR_SPECIFIC_1_SIZE];
|
||||
};
|
||||
|
||||
struct scsi_vpd_unit_serial_number
|
||||
{
|
||||
uint8_t device;
|
||||
uint8_t page_code;
|
||||
#define SVPD_UNIT_SERIAL_NUMBER 0x80
|
||||
uint8_t reserved;
|
||||
uint8_t length; /* serial number length */
|
||||
#define SVPD_SERIAL_NUM_SIZE 251
|
||||
uint8_t serial_num[SVPD_SERIAL_NUM_SIZE];
|
||||
};
|
||||
|
||||
struct scsi_read_capacity
|
||||
{
|
||||
uint8_t opcode;
|
||||
uint8_t byte2;
|
||||
uint8_t addr[4];
|
||||
uint8_t unused[3];
|
||||
uint8_t control;
|
||||
};
|
||||
|
||||
struct scsi_read_capacity_data
|
||||
{
|
||||
uint8_t addr[4];
|
||||
uint8_t length[4];
|
||||
};
|
||||
|
||||
struct scsi_report_luns
|
||||
{
|
||||
uint8_t opcode;
|
||||
uint8_t byte2;
|
||||
uint8_t unused[3];
|
||||
uint8_t addr[4];
|
||||
uint8_t control;
|
||||
};
|
||||
|
||||
struct scsi_report_luns_data {
|
||||
uint8_t length[4]; /* length of LUN inventory, in bytes */
|
||||
uint8_t reserved[4]; /* unused */
|
||||
/*
|
||||
* LUN inventory- we only support the type zero form for now.
|
||||
*/
|
||||
struct {
|
||||
uint8_t lundata[8];
|
||||
} luns[1];
|
||||
};
|
||||
#define RPL_LUNDATA_ATYP_MASK 0xc0 /* MBZ for type 0 lun */
|
||||
#define RPL_LUNDATA_T0LUN 1 /* @ lundata[1] */
|
||||
|
||||
|
||||
struct scsi_sense_data
|
||||
{
|
||||
uint8_t error_code;
|
||||
|
@ -757,41 +117,6 @@ struct scsi_sense_data
|
|||
#define SSD_FULL_SIZE sizeof(struct scsi_sense_data)
|
||||
};
|
||||
|
||||
struct scsi_mode_header_6
|
||||
{
|
||||
uint8_t data_length; /* Sense data length */
|
||||
uint8_t medium_type;
|
||||
uint8_t dev_spec;
|
||||
uint8_t blk_desc_len;
|
||||
};
|
||||
|
||||
struct scsi_mode_header_10
|
||||
{
|
||||
uint8_t data_length[2];/* Sense data length */
|
||||
uint8_t medium_type;
|
||||
uint8_t dev_spec;
|
||||
uint8_t unused[2];
|
||||
uint8_t blk_desc_len[2];
|
||||
};
|
||||
|
||||
struct scsi_mode_page_header
|
||||
{
|
||||
uint8_t page_code;
|
||||
uint8_t page_length;
|
||||
};
|
||||
|
||||
struct scsi_mode_blk_desc
|
||||
{
|
||||
uint8_t density;
|
||||
uint8_t nblocks[3];
|
||||
uint8_t reserved;
|
||||
uint8_t blklen[3];
|
||||
};
|
||||
|
||||
#define SCSI_DEFAULT_DENSITY 0x00 /* use 'default' density */
|
||||
#define SCSI_SAME_DENSITY 0x7f /* use 'same' density- >= SCSI-2 only */
|
||||
|
||||
|
||||
/*
|
||||
* Status Byte
|
||||
*/
|
||||
|
@ -807,76 +132,7 @@ struct scsi_mode_blk_desc
|
|||
#define SCSI_STATUS_ACA_ACTIVE 0x30
|
||||
#define SCSI_STATUS_TASK_ABORTED 0x40
|
||||
|
||||
struct scsi_inquiry_pattern {
|
||||
uint8_t type;
|
||||
uint8_t media_type;
|
||||
#define SIP_MEDIA_REMOVABLE 0x01
|
||||
#define SIP_MEDIA_FIXED 0x02
|
||||
const char *vendor;
|
||||
const char *product;
|
||||
const char *revision;
|
||||
};
|
||||
|
||||
struct scsi_static_inquiry_pattern {
|
||||
uint8_t type;
|
||||
uint8_t media_type;
|
||||
char vendor[SID_VENDOR_SIZE+1];
|
||||
char product[SID_PRODUCT_SIZE+1];
|
||||
char revision[SID_REVISION_SIZE+1];
|
||||
};
|
||||
|
||||
struct scsi_sense_quirk_entry {
|
||||
struct scsi_inquiry_pattern inq_pat;
|
||||
int num_sense_keys;
|
||||
int num_ascs;
|
||||
struct sense_key_table_entry *sense_key_info;
|
||||
struct asc_table_entry *asc_info;
|
||||
};
|
||||
|
||||
struct sense_key_table_entry {
|
||||
uint8_t sense_key;
|
||||
uint32_t action;
|
||||
const char *desc;
|
||||
};
|
||||
|
||||
struct asc_table_entry {
|
||||
uint8_t asc;
|
||||
uint8_t ascq;
|
||||
uint32_t action;
|
||||
const char *desc;
|
||||
};
|
||||
|
||||
struct op_table_entry {
|
||||
uint8_t opcode;
|
||||
uint16_t opmask;
|
||||
const char *desc;
|
||||
};
|
||||
|
||||
struct scsi_op_quirk_entry {
|
||||
struct scsi_inquiry_pattern inq_pat;
|
||||
int num_ops;
|
||||
struct op_table_entry *op_table;
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
SSS_FLAG_NONE = 0x00,
|
||||
SSS_FLAG_PRINT_COMMAND = 0x01
|
||||
} scsi_sense_string_flags;
|
||||
|
||||
extern const char *scsi_sense_key_text[];
|
||||
|
||||
/************************* Large Disk Handling ********************************/
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
|
||||
static __inline int aic_sector_div(u_long capacity, int heads, int sectors);
|
||||
|
||||
static __inline int
|
||||
aic_sector_div(u_long capacity, int heads, int sectors)
|
||||
{
|
||||
return (capacity / (heads * sectors));
|
||||
}
|
||||
#else
|
||||
static __inline int aic_sector_div(sector_t capacity, int heads, int sectors);
|
||||
|
||||
static __inline int
|
||||
aic_sector_div(sector_t capacity, int heads, int sectors)
|
||||
{
|
||||
|
@ -884,7 +140,6 @@ aic_sector_div(sector_t capacity, int heads, int sectors)
|
|||
sector_div(capacity, (heads * sectors));
|
||||
return (int)capacity;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**************************** Module Library Hack *****************************/
|
||||
/*
|
||||
|
@ -899,138 +154,15 @@ aic_sector_div(sector_t capacity, int heads, int sectors)
|
|||
#define AIC_LIB_ENTRY_EXPAND(x, prefix) AIC_LIB_ENTRY_CONCAT(x, prefix)
|
||||
#define AIC_LIB_ENTRY(x) AIC_LIB_ENTRY_EXPAND(x, AIC_LIB_PREFIX)
|
||||
|
||||
#define aic_sense_desc AIC_LIB_ENTRY(_sense_desc)
|
||||
#define aic_sense_error_action AIC_LIB_ENTRY(_sense_error_action)
|
||||
#define aic_error_action AIC_LIB_ENTRY(_error_action)
|
||||
#define aic_op_desc AIC_LIB_ENTRY(_op_desc)
|
||||
#define aic_cdb_string AIC_LIB_ENTRY(_cdb_string)
|
||||
#define aic_print_inquiry AIC_LIB_ENTRY(_print_inquiry)
|
||||
#define aic_calc_syncsrate AIC_LIB_ENTRY(_calc_syncrate)
|
||||
#define aic_calc_syncparam AIC_LIB_ENTRY(_calc_syncparam)
|
||||
#define aic_calc_speed AIC_LIB_ENTRY(_calc_speed)
|
||||
#define aic_inquiry_match AIC_LIB_ENTRY(_inquiry_match)
|
||||
#define aic_static_inquiry_match AIC_LIB_ENTRY(_static_inquiry_match)
|
||||
#define aic_parse_brace_option AIC_LIB_ENTRY(_parse_brace_option)
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
void aic_sense_desc(int /*sense_key*/, int /*asc*/,
|
||||
int /*ascq*/, struct scsi_inquiry_data*,
|
||||
const char** /*sense_key_desc*/,
|
||||
const char** /*asc_desc*/);
|
||||
aic_sense_action aic_sense_error_action(struct scsi_sense_data*,
|
||||
struct scsi_inquiry_data*,
|
||||
uint32_t /*sense_flags*/);
|
||||
uint32_t aic_error_action(struct scsi_cmnd *,
|
||||
struct scsi_inquiry_data *,
|
||||
cam_status, u_int);
|
||||
|
||||
#define SF_RETRY_UA 0x01
|
||||
#define SF_NO_PRINT 0x02
|
||||
#define SF_QUIET_IR 0x04 /* Be quiet about Illegal Request reponses */
|
||||
#define SF_PRINT_ALWAYS 0x08
|
||||
|
||||
|
||||
const char * aic_op_desc(uint16_t /*opcode*/, struct scsi_inquiry_data*);
|
||||
char * aic_cdb_string(uint8_t* /*cdb_ptr*/, char* /*cdb_string*/,
|
||||
size_t /*len*/);
|
||||
void aic_print_inquiry(struct scsi_inquiry_data*);
|
||||
|
||||
u_int aic_calc_syncsrate(u_int /*period_factor*/);
|
||||
u_int aic_calc_syncparam(u_int /*period*/);
|
||||
u_int aic_calc_speed(u_int width, u_int period, u_int offset,
|
||||
u_int min_rate);
|
||||
|
||||
int aic_inquiry_match(caddr_t /*inqbuffer*/,
|
||||
caddr_t /*table_entry*/);
|
||||
int aic_static_inquiry_match(caddr_t /*inqbuffer*/,
|
||||
caddr_t /*table_entry*/);
|
||||
|
||||
typedef void aic_option_callback_t(u_long, int, int, int32_t);
|
||||
char * aic_parse_brace_option(char *opt_name, char *opt_arg,
|
||||
char *end, int depth,
|
||||
aic_option_callback_t *, u_long);
|
||||
|
||||
static __inline void scsi_extract_sense(struct scsi_sense_data *sense,
|
||||
int *error_code, int *sense_key,
|
||||
int *asc, int *ascq);
|
||||
static __inline void scsi_ulto2b(uint32_t val, uint8_t *bytes);
|
||||
static __inline void scsi_ulto3b(uint32_t val, uint8_t *bytes);
|
||||
static __inline void scsi_ulto4b(uint32_t val, uint8_t *bytes);
|
||||
static __inline uint32_t scsi_2btoul(uint8_t *bytes);
|
||||
static __inline uint32_t scsi_3btoul(uint8_t *bytes);
|
||||
static __inline int32_t scsi_3btol(uint8_t *bytes);
|
||||
static __inline uint32_t scsi_4btoul(uint8_t *bytes);
|
||||
|
||||
static __inline void scsi_extract_sense(struct scsi_sense_data *sense,
|
||||
int *error_code, int *sense_key,
|
||||
int *asc, int *ascq)
|
||||
{
|
||||
*error_code = sense->error_code & SSD_ERRCODE;
|
||||
*sense_key = sense->flags & SSD_KEY;
|
||||
*asc = (sense->extra_len >= 5) ? sense->add_sense_code : 0;
|
||||
*ascq = (sense->extra_len >= 6) ? sense->add_sense_code_qual : 0;
|
||||
}
|
||||
|
||||
static __inline void
|
||||
scsi_ulto2b(uint32_t val, uint8_t *bytes)
|
||||
{
|
||||
|
||||
bytes[0] = (val >> 8) & 0xff;
|
||||
bytes[1] = val & 0xff;
|
||||
}
|
||||
|
||||
static __inline void
|
||||
scsi_ulto3b(uint32_t val, uint8_t *bytes)
|
||||
{
|
||||
|
||||
bytes[0] = (val >> 16) & 0xff;
|
||||
bytes[1] = (val >> 8) & 0xff;
|
||||
bytes[2] = val & 0xff;
|
||||
}
|
||||
|
||||
static __inline void
|
||||
scsi_ulto4b(uint32_t val, uint8_t *bytes)
|
||||
{
|
||||
|
||||
bytes[0] = (val >> 24) & 0xff;
|
||||
bytes[1] = (val >> 16) & 0xff;
|
||||
bytes[2] = (val >> 8) & 0xff;
|
||||
bytes[3] = val & 0xff;
|
||||
}
|
||||
|
||||
static __inline uint32_t
|
||||
scsi_2btoul(uint8_t *bytes)
|
||||
{
|
||||
uint32_t rv;
|
||||
|
||||
rv = (bytes[0] << 8) |
|
||||
bytes[1];
|
||||
return (rv);
|
||||
}
|
||||
|
||||
static __inline uint32_t
|
||||
scsi_3btoul(uint8_t *bytes)
|
||||
{
|
||||
uint32_t rv;
|
||||
|
||||
rv = (bytes[0] << 16) |
|
||||
(bytes[1] << 8) |
|
||||
bytes[2];
|
||||
return (rv);
|
||||
}
|
||||
|
||||
static __inline int32_t
|
||||
scsi_3btol(uint8_t *bytes)
|
||||
{
|
||||
uint32_t rc = scsi_3btoul(bytes);
|
||||
|
||||
if (rc & 0x00800000)
|
||||
rc |= 0xff000000;
|
||||
|
||||
return (int32_t) rc;
|
||||
}
|
||||
|
||||
static __inline uint32_t
|
||||
scsi_4btoul(uint8_t *bytes)
|
||||
{
|
||||
|
|
|
@ -20,7 +20,6 @@
|
|||
#include <linux/interrupt.h>
|
||||
#include <linux/blkdev.h>
|
||||
#include <linux/completion.h>
|
||||
#include <linux/devfs_fs_kernel.h>
|
||||
#include <linux/ioctl32.h>
|
||||
#include <linux/compat.h>
|
||||
#include <linux/chio.h> /* here are all the ioctls */
|
||||
|
@ -940,8 +939,6 @@ static int ch_probe(struct device *dev)
|
|||
if (init)
|
||||
ch_init_elem(ch);
|
||||
|
||||
devfs_mk_cdev(MKDEV(SCSI_CHANGER_MAJOR,ch->minor),
|
||||
S_IFCHR | S_IRUGO | S_IWUGO, ch->name);
|
||||
class_device_create(ch_sysfs_class,
|
||||
MKDEV(SCSI_CHANGER_MAJOR,ch->minor),
|
||||
dev, "s%s", ch->name);
|
||||
|
@ -974,7 +971,6 @@ static int ch_remove(struct device *dev)
|
|||
|
||||
class_device_destroy(ch_sysfs_class,
|
||||
MKDEV(SCSI_CHANGER_MAJOR,ch->minor));
|
||||
devfs_remove(ch->name);
|
||||
kfree(ch->dt);
|
||||
kfree(ch);
|
||||
ch_devcount--;
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include <scsi/scsi_host.h>
|
||||
#include <scsi/scsi_request.h>
|
||||
#include <scsi/scsi_eh.h>
|
||||
#include <scsi/scsi_dbg.h>
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -52,21 +52,80 @@ static struct class shost_class = {
|
|||
};
|
||||
|
||||
/**
|
||||
* scsi_host_cancel - cancel outstanding IO to this host
|
||||
* @shost: pointer to struct Scsi_Host
|
||||
* recovery: recovery requested to run.
|
||||
* scsi_host_set_state - Take the given host through the host
|
||||
* state model.
|
||||
* @shost: scsi host to change the state of.
|
||||
* @state: state to change to.
|
||||
*
|
||||
* Returns zero if unsuccessful or an error if the requested
|
||||
* transition is illegal.
|
||||
**/
|
||||
static void scsi_host_cancel(struct Scsi_Host *shost, int recovery)
|
||||
int scsi_host_set_state(struct Scsi_Host *shost, enum scsi_host_state state)
|
||||
{
|
||||
struct scsi_device *sdev;
|
||||
enum scsi_host_state oldstate = shost->shost_state;
|
||||
|
||||
set_bit(SHOST_CANCEL, &shost->shost_state);
|
||||
shost_for_each_device(sdev, shost) {
|
||||
scsi_device_cancel(sdev, recovery);
|
||||
if (state == oldstate)
|
||||
return 0;
|
||||
|
||||
switch (state) {
|
||||
case SHOST_CREATED:
|
||||
/* There are no legal states that come back to
|
||||
* created. This is the manually initialised start
|
||||
* state */
|
||||
goto illegal;
|
||||
|
||||
case SHOST_RUNNING:
|
||||
switch (oldstate) {
|
||||
case SHOST_CREATED:
|
||||
case SHOST_RECOVERY:
|
||||
break;
|
||||
default:
|
||||
goto illegal;
|
||||
}
|
||||
wait_event(shost->host_wait, (!test_bit(SHOST_RECOVERY,
|
||||
&shost->shost_state)));
|
||||
break;
|
||||
|
||||
case SHOST_RECOVERY:
|
||||
switch (oldstate) {
|
||||
case SHOST_RUNNING:
|
||||
break;
|
||||
default:
|
||||
goto illegal;
|
||||
}
|
||||
break;
|
||||
|
||||
case SHOST_CANCEL:
|
||||
switch (oldstate) {
|
||||
case SHOST_CREATED:
|
||||
case SHOST_RUNNING:
|
||||
break;
|
||||
default:
|
||||
goto illegal;
|
||||
}
|
||||
break;
|
||||
|
||||
case SHOST_DEL:
|
||||
switch (oldstate) {
|
||||
case SHOST_CANCEL:
|
||||
break;
|
||||
default:
|
||||
goto illegal;
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
shost->shost_state = state;
|
||||
return 0;
|
||||
|
||||
illegal:
|
||||
SCSI_LOG_ERROR_RECOVERY(1,
|
||||
dev_printk(KERN_ERR, &shost->shost_gendev,
|
||||
"Illegal host state transition"
|
||||
"%s->%s\n",
|
||||
scsi_host_state_name(oldstate),
|
||||
scsi_host_state_name(state)));
|
||||
return -EINVAL;
|
||||
}
|
||||
EXPORT_SYMBOL(scsi_host_set_state);
|
||||
|
||||
/**
|
||||
* scsi_remove_host - remove a scsi host
|
||||
|
@ -74,11 +133,13 @@ static void scsi_host_cancel(struct Scsi_Host *shost, int recovery)
|
|||
**/
|
||||
void scsi_remove_host(struct Scsi_Host *shost)
|
||||
{
|
||||
down(&shost->scan_mutex);
|
||||
scsi_host_set_state(shost, SHOST_CANCEL);
|
||||
up(&shost->scan_mutex);
|
||||
scsi_forget_host(shost);
|
||||
scsi_host_cancel(shost, 0);
|
||||
scsi_proc_host_rm(shost);
|
||||
|
||||
set_bit(SHOST_DEL, &shost->shost_state);
|
||||
scsi_host_set_state(shost, SHOST_DEL);
|
||||
|
||||
transport_unregister_device(&shost->shost_gendev);
|
||||
class_device_unregister(&shost->shost_classdev);
|
||||
|
@ -115,7 +176,7 @@ int scsi_add_host(struct Scsi_Host *shost, struct device *dev)
|
|||
if (error)
|
||||
goto out;
|
||||
|
||||
set_bit(SHOST_ADD, &shost->shost_state);
|
||||
scsi_host_set_state(shost, SHOST_RUNNING);
|
||||
get_device(shost->shost_gendev.parent);
|
||||
|
||||
error = class_device_add(&shost->shost_classdev);
|
||||
|
@ -226,6 +287,7 @@ struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *sht, int privsize)
|
|||
|
||||
spin_lock_init(&shost->default_lock);
|
||||
scsi_assign_lock(shost, &shost->default_lock);
|
||||
shost->shost_state = SHOST_CREATED;
|
||||
INIT_LIST_HEAD(&shost->__devices);
|
||||
INIT_LIST_HEAD(&shost->__targets);
|
||||
INIT_LIST_HEAD(&shost->eh_cmd_q);
|
||||
|
@ -382,7 +444,7 @@ EXPORT_SYMBOL(scsi_host_lookup);
|
|||
**/
|
||||
struct Scsi_Host *scsi_host_get(struct Scsi_Host *shost)
|
||||
{
|
||||
if (test_bit(SHOST_DEL, &shost->shost_state) ||
|
||||
if ((shost->shost_state == SHOST_DEL) ||
|
||||
!get_device(&shost->shost_gendev))
|
||||
return NULL;
|
||||
return shost;
|
||||
|
|
|
@ -594,7 +594,7 @@ static int ibmvscsi_queuecommand(struct scsi_cmnd *cmnd,
|
|||
init_event_struct(evt_struct,
|
||||
handle_cmd_rsp,
|
||||
VIOSRP_SRP_FORMAT,
|
||||
cmnd->timeout);
|
||||
cmnd->timeout_per_command/HZ);
|
||||
|
||||
evt_struct->cmnd = cmnd;
|
||||
evt_struct->cmnd_done = done;
|
||||
|
@ -826,11 +826,13 @@ static int ibmvscsi_eh_abort_handler(struct scsi_cmnd *cmd)
|
|||
struct srp_event_struct *tmp_evt, *found_evt;
|
||||
union viosrp_iu srp_rsp;
|
||||
int rsp_rc;
|
||||
unsigned long flags;
|
||||
u16 lun = lun_from_dev(cmd->device);
|
||||
|
||||
/* First, find this command in our sent list so we can figure
|
||||
* out the correct tag
|
||||
*/
|
||||
spin_lock_irqsave(hostdata->host->host_lock, flags);
|
||||
found_evt = NULL;
|
||||
list_for_each_entry(tmp_evt, &hostdata->sent, list) {
|
||||
if (tmp_evt->cmnd == cmd) {
|
||||
|
@ -839,11 +841,14 @@ static int ibmvscsi_eh_abort_handler(struct scsi_cmnd *cmd)
|
|||
}
|
||||
}
|
||||
|
||||
if (!found_evt)
|
||||
if (!found_evt) {
|
||||
spin_unlock_irqrestore(hostdata->host->host_lock, flags);
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
evt = get_event_struct(&hostdata->pool);
|
||||
if (evt == NULL) {
|
||||
spin_unlock_irqrestore(hostdata->host->host_lock, flags);
|
||||
printk(KERN_ERR "ibmvscsi: failed to allocate abort event\n");
|
||||
return FAILED;
|
||||
}
|
||||
|
@ -867,7 +872,9 @@ static int ibmvscsi_eh_abort_handler(struct scsi_cmnd *cmd)
|
|||
|
||||
evt->sync_srp = &srp_rsp;
|
||||
init_completion(&evt->comp);
|
||||
if (ibmvscsi_send_srp_event(evt, hostdata) != 0) {
|
||||
rsp_rc = ibmvscsi_send_srp_event(evt, hostdata);
|
||||
spin_unlock_irqrestore(hostdata->host->host_lock, flags);
|
||||
if (rsp_rc != 0) {
|
||||
printk(KERN_ERR "ibmvscsi: failed to send abort() event\n");
|
||||
return FAILED;
|
||||
}
|
||||
|
@ -901,6 +908,7 @@ static int ibmvscsi_eh_abort_handler(struct scsi_cmnd *cmd)
|
|||
* The event is no longer in our list. Make sure it didn't
|
||||
* complete while we were aborting
|
||||
*/
|
||||
spin_lock_irqsave(hostdata->host->host_lock, flags);
|
||||
found_evt = NULL;
|
||||
list_for_each_entry(tmp_evt, &hostdata->sent, list) {
|
||||
if (tmp_evt->cmnd == cmd) {
|
||||
|
@ -910,6 +918,7 @@ static int ibmvscsi_eh_abort_handler(struct scsi_cmnd *cmd)
|
|||
}
|
||||
|
||||
if (found_evt == NULL) {
|
||||
spin_unlock_irqrestore(hostdata->host->host_lock, flags);
|
||||
printk(KERN_INFO
|
||||
"ibmvscsi: aborted task tag 0x%lx completed\n",
|
||||
tsk_mgmt->managed_task_tag);
|
||||
|
@ -924,6 +933,7 @@ static int ibmvscsi_eh_abort_handler(struct scsi_cmnd *cmd)
|
|||
list_del(&found_evt->list);
|
||||
unmap_cmd_data(&found_evt->iu.srp.cmd, found_evt->hostdata->dev);
|
||||
free_event_struct(&found_evt->hostdata->pool, found_evt);
|
||||
spin_unlock_irqrestore(hostdata->host->host_lock, flags);
|
||||
atomic_inc(&hostdata->request_limit);
|
||||
return SUCCESS;
|
||||
}
|
||||
|
@ -943,10 +953,13 @@ static int ibmvscsi_eh_device_reset_handler(struct scsi_cmnd *cmd)
|
|||
struct srp_event_struct *tmp_evt, *pos;
|
||||
union viosrp_iu srp_rsp;
|
||||
int rsp_rc;
|
||||
unsigned long flags;
|
||||
u16 lun = lun_from_dev(cmd->device);
|
||||
|
||||
spin_lock_irqsave(hostdata->host->host_lock, flags);
|
||||
evt = get_event_struct(&hostdata->pool);
|
||||
if (evt == NULL) {
|
||||
spin_unlock_irqrestore(hostdata->host->host_lock, flags);
|
||||
printk(KERN_ERR "ibmvscsi: failed to allocate reset event\n");
|
||||
return FAILED;
|
||||
}
|
||||
|
@ -969,7 +982,9 @@ static int ibmvscsi_eh_device_reset_handler(struct scsi_cmnd *cmd)
|
|||
|
||||
evt->sync_srp = &srp_rsp;
|
||||
init_completion(&evt->comp);
|
||||
if (ibmvscsi_send_srp_event(evt, hostdata) != 0) {
|
||||
rsp_rc = ibmvscsi_send_srp_event(evt, hostdata);
|
||||
spin_unlock_irqrestore(hostdata->host->host_lock, flags);
|
||||
if (rsp_rc != 0) {
|
||||
printk(KERN_ERR "ibmvscsi: failed to send reset event\n");
|
||||
return FAILED;
|
||||
}
|
||||
|
@ -1002,6 +1017,7 @@ static int ibmvscsi_eh_device_reset_handler(struct scsi_cmnd *cmd)
|
|||
/* We need to find all commands for this LUN that have not yet been
|
||||
* responded to, and fail them with DID_RESET
|
||||
*/
|
||||
spin_lock_irqsave(hostdata->host->host_lock, flags);
|
||||
list_for_each_entry_safe(tmp_evt, pos, &hostdata->sent, list) {
|
||||
if ((tmp_evt->cmnd) && (tmp_evt->cmnd->device == cmd->device)) {
|
||||
if (tmp_evt->cmnd)
|
||||
|
@ -1017,6 +1033,7 @@ static int ibmvscsi_eh_device_reset_handler(struct scsi_cmnd *cmd)
|
|||
tmp_evt->done(tmp_evt);
|
||||
}
|
||||
}
|
||||
spin_unlock_irqrestore(hostdata->host->host_lock, flags);
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
|
|
|
@ -342,9 +342,6 @@ struct lpfc_hba {
|
|||
#define VPD_MASK 0xf /* mask for any vpd data */
|
||||
|
||||
struct timer_list els_tmofunc;
|
||||
|
||||
void *link_stats;
|
||||
|
||||
/*
|
||||
* stat counters
|
||||
*/
|
||||
|
@ -370,6 +367,8 @@ struct lpfc_hba {
|
|||
struct list_head freebufList;
|
||||
struct list_head ctrspbuflist;
|
||||
struct list_head rnidrspbuflist;
|
||||
|
||||
struct fc_host_statistics link_stats;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include <linux/pci.h>
|
||||
#include <linux/interrupt.h>
|
||||
|
||||
#include <scsi/scsi.h>
|
||||
#include <scsi/scsi_device.h>
|
||||
#include <scsi/scsi_host.h>
|
||||
#include <scsi/scsi_tcq.h>
|
||||
|
@ -988,8 +989,7 @@ lpfc_get_stats(struct Scsi_Host *shost)
|
|||
{
|
||||
struct lpfc_hba *phba = (struct lpfc_hba *)shost->hostdata[0];
|
||||
struct lpfc_sli *psli = &phba->sli;
|
||||
struct fc_host_statistics *hs =
|
||||
(struct fc_host_statistics *)phba->link_stats;
|
||||
struct fc_host_statistics *hs = &phba->link_stats;
|
||||
LPFC_MBOXQ_t *pmboxq;
|
||||
MAILBOX_t *pmb;
|
||||
int rc=0;
|
||||
|
@ -1020,6 +1020,8 @@ lpfc_get_stats(struct Scsi_Host *shost)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
memset(hs, 0, sizeof (struct fc_host_statistics));
|
||||
|
||||
hs->tx_frames = pmb->un.varRdStatus.xmitFrameCnt;
|
||||
hs->tx_words = (pmb->un.varRdStatus.xmitByteCnt * 256);
|
||||
hs->rx_frames = pmb->un.varRdStatus.rcvFrameCnt;
|
||||
|
|
|
@ -27,8 +27,10 @@
|
|||
#include <linux/interrupt.h>
|
||||
#include <linux/utsname.h>
|
||||
|
||||
#include <scsi/scsi.h>
|
||||
#include <scsi/scsi_device.h>
|
||||
#include <scsi/scsi_host.h>
|
||||
#include <scsi/scsi_transport_fc.h>
|
||||
|
||||
#include "lpfc_hw.h"
|
||||
#include "lpfc_sli.h"
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include <linux/pci.h>
|
||||
#include <linux/interrupt.h>
|
||||
|
||||
#include <scsi/scsi.h>
|
||||
#include <scsi/scsi_device.h>
|
||||
#include <scsi/scsi_host.h>
|
||||
#include <scsi/scsi_transport_fc.h>
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include <linux/kthread.h>
|
||||
#include <linux/interrupt.h>
|
||||
|
||||
#include <scsi/scsi.h>
|
||||
#include <scsi/scsi_device.h>
|
||||
#include <scsi/scsi_host.h>
|
||||
#include <scsi/scsi_transport_fc.h>
|
||||
|
@ -1135,6 +1136,8 @@ lpfc_nlp_list(struct lpfc_hba * phba, struct lpfc_nodelist * nlp, int list)
|
|||
switch(list) {
|
||||
case NLP_NO_LIST: /* No list, just remove it */
|
||||
lpfc_nlp_remove(phba, nlp);
|
||||
/* as node removed - stop further transport calls */
|
||||
rport_del = none;
|
||||
break;
|
||||
case NLP_UNUSED_LIST:
|
||||
spin_lock_irq(phba->host->host_lock);
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include <linux/pci.h>
|
||||
#include <linux/spinlock.h>
|
||||
|
||||
#include <scsi/scsi.h>
|
||||
#include <scsi/scsi_device.h>
|
||||
#include <scsi/scsi_host.h>
|
||||
#include <scsi/scsi_transport_fc.h>
|
||||
|
@ -1339,14 +1340,12 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid)
|
|||
if (pci_request_regions(pdev, LPFC_DRIVER_NAME))
|
||||
goto out_disable_device;
|
||||
|
||||
host = scsi_host_alloc(&lpfc_template,
|
||||
sizeof (struct lpfc_hba) + sizeof (unsigned long));
|
||||
host = scsi_host_alloc(&lpfc_template, sizeof (struct lpfc_hba));
|
||||
if (!host)
|
||||
goto out_release_regions;
|
||||
|
||||
phba = (struct lpfc_hba*)host->hostdata;
|
||||
memset(phba, 0, sizeof (struct lpfc_hba));
|
||||
phba->link_stats = (void *)&phba[1];
|
||||
phba->host = host;
|
||||
|
||||
phba->fc_flag |= FC_LOADING;
|
||||
|
|
|
@ -23,6 +23,11 @@
|
|||
#include <linux/pci.h>
|
||||
#include <linux/interrupt.h>
|
||||
|
||||
#include <scsi/scsi_device.h>
|
||||
#include <scsi/scsi_transport_fc.h>
|
||||
|
||||
#include <scsi/scsi.h>
|
||||
|
||||
#include "lpfc_hw.h"
|
||||
#include "lpfc_sli.h"
|
||||
#include "lpfc_disc.h"
|
||||
|
|
|
@ -23,6 +23,11 @@
|
|||
#include <linux/pci.h>
|
||||
#include <linux/interrupt.h>
|
||||
|
||||
#include <scsi/scsi_device.h>
|
||||
#include <scsi/scsi_transport_fc.h>
|
||||
|
||||
#include <scsi/scsi.h>
|
||||
|
||||
#include "lpfc_hw.h"
|
||||
#include "lpfc_sli.h"
|
||||
#include "lpfc_disc.h"
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include <linux/pci.h>
|
||||
#include <linux/interrupt.h>
|
||||
|
||||
#include <scsi/scsi.h>
|
||||
#include <scsi/scsi_device.h>
|
||||
#include <scsi/scsi_host.h>
|
||||
#include <scsi/scsi_transport_fc.h>
|
||||
|
|
|
@ -40,11 +40,6 @@
|
|||
#define LPFC_RESET_WAIT 2
|
||||
#define LPFC_ABORT_WAIT 2
|
||||
|
||||
static inline void lpfc_put_lun(struct fcp_cmnd *fcmd, unsigned int lun)
|
||||
{
|
||||
fcmd->fcpLunLsl = 0;
|
||||
fcmd->fcpLunMsl = swab16((uint16_t)lun);
|
||||
}
|
||||
|
||||
/*
|
||||
* This routine allocates a scsi buffer, which contains all the necessary
|
||||
|
@ -238,6 +233,8 @@ lpfc_scsi_prep_dma_buf(struct lpfc_hba * phba, struct lpfc_scsi_buf * lpfc_cmd)
|
|||
bpl->tus.f.bdeSize = scsi_cmnd->request_bufflen;
|
||||
if (datadir == DMA_TO_DEVICE)
|
||||
bpl->tus.f.bdeFlags = 0;
|
||||
else
|
||||
bpl->tus.f.bdeFlags = BUFF_USE_RCV;
|
||||
bpl->tus.w = le32_to_cpu(bpl->tus.w);
|
||||
num_bde = 1;
|
||||
bpl++;
|
||||
|
@ -245,8 +242,11 @@ lpfc_scsi_prep_dma_buf(struct lpfc_hba * phba, struct lpfc_scsi_buf * lpfc_cmd)
|
|||
|
||||
/*
|
||||
* Finish initializing those IOCB fields that are dependent on the
|
||||
* scsi_cmnd request_buffer
|
||||
* scsi_cmnd request_buffer. Note that the bdeSize is explicitly
|
||||
* reinitialized since all iocb memory resources are used many times
|
||||
* for transmit, receive, and continuation bpl's.
|
||||
*/
|
||||
iocb_cmd->un.fcpi64.bdl.bdeSize = (2 * sizeof (struct ulp_bde64));
|
||||
iocb_cmd->un.fcpi64.bdl.bdeSize +=
|
||||
(num_bde * sizeof (struct ulp_bde64));
|
||||
iocb_cmd->ulpBdeCount = 1;
|
||||
|
@ -445,8 +445,11 @@ lpfc_scsi_prep_cmnd(struct lpfc_hba * phba, struct lpfc_scsi_buf * lpfc_cmd,
|
|||
int datadir = scsi_cmnd->sc_data_direction;
|
||||
|
||||
lpfc_cmd->fcp_rsp->rspSnsLen = 0;
|
||||
/* clear task management bits */
|
||||
lpfc_cmd->fcp_cmnd->fcpCntl2 = 0;
|
||||
|
||||
lpfc_put_lun(lpfc_cmd->fcp_cmnd, lpfc_cmd->pCmd->device->lun);
|
||||
int_to_scsilun(lpfc_cmd->pCmd->device->lun,
|
||||
&lpfc_cmd->fcp_cmnd->fcp_lun);
|
||||
|
||||
memcpy(&fcp_cmnd->fcpCdb[0], scsi_cmnd->cmnd, 16);
|
||||
|
||||
|
@ -545,7 +548,8 @@ lpfc_scsi_prep_task_mgmt_cmd(struct lpfc_hba *phba,
|
|||
piocb = &piocbq->iocb;
|
||||
|
||||
fcp_cmnd = lpfc_cmd->fcp_cmnd;
|
||||
lpfc_put_lun(lpfc_cmd->fcp_cmnd, lpfc_cmd->pCmd->device->lun);
|
||||
int_to_scsilun(lpfc_cmd->pCmd->device->lun,
|
||||
&lpfc_cmd->fcp_cmnd->fcp_lun);
|
||||
fcp_cmnd->fcpCntl2 = task_mgmt_cmd;
|
||||
|
||||
piocb->ulpCommand = CMD_FCP_ICMND64_CR;
|
||||
|
@ -746,6 +750,10 @@ lpfc_queuecommand(struct scsi_cmnd *cmnd, void (*done) (struct scsi_cmnd *))
|
|||
cmnd->result = ScsiResult(DID_NO_CONNECT, 0);
|
||||
goto out_fail_command;
|
||||
}
|
||||
else if (ndlp->nlp_state == NLP_STE_NPR_NODE) {
|
||||
cmnd->result = ScsiResult(DID_BUS_BUSY, 0);
|
||||
goto out_fail_command;
|
||||
}
|
||||
/*
|
||||
* The device is most likely recovered and the driver
|
||||
* needs a bit more time to finish. Ask the midlayer
|
||||
|
|
|
@ -78,18 +78,7 @@ struct fcp_rsp {
|
|||
};
|
||||
|
||||
struct fcp_cmnd {
|
||||
uint32_t fcpLunMsl; /* most significant lun word (32 bits) */
|
||||
uint32_t fcpLunLsl; /* least significant lun word (32 bits) */
|
||||
/* # of bits to shift lun id to end up in right
|
||||
* payload word, little endian = 8, big = 16.
|
||||
*/
|
||||
#ifdef __BIG_ENDIAN
|
||||
#define FC_LUN_SHIFT 16
|
||||
#define FC_ADDR_MODE_SHIFT 24
|
||||
#else /* __LITTLE_ENDIAN */
|
||||
#define FC_LUN_SHIFT 8
|
||||
#define FC_ADDR_MODE_SHIFT 0
|
||||
#endif
|
||||
struct scsi_lun fcp_lun;
|
||||
|
||||
uint8_t fcpCntl0; /* FCP_CNTL byte 0 (reserved) */
|
||||
uint8_t fcpCntl1; /* FCP_CNTL byte 1 task codes */
|
||||
|
|
|
@ -24,9 +24,11 @@
|
|||
#include <linux/interrupt.h>
|
||||
#include <linux/delay.h>
|
||||
|
||||
#include <scsi/scsi.h>
|
||||
#include <scsi/scsi_cmnd.h>
|
||||
#include <scsi/scsi_device.h>
|
||||
#include <scsi/scsi_host.h>
|
||||
#include <scsi/scsi_transport_fc.h>
|
||||
|
||||
#include "lpfc_hw.h"
|
||||
#include "lpfc_sli.h"
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
* included with this package. *
|
||||
*******************************************************************/
|
||||
|
||||
#define LPFC_DRIVER_VERSION "8.0.29"
|
||||
#define LPFC_DRIVER_VERSION "8.0.30"
|
||||
|
||||
#define LPFC_DRIVER_NAME "lpfc"
|
||||
|
||||
|
|
|
@ -996,7 +996,6 @@ qla1280_error_action(struct scsi_cmnd *cmd, enum action action)
|
|||
break;
|
||||
|
||||
case ABORT_DEVICE:
|
||||
ha->flags.in_reset = 1;
|
||||
if (qla1280_verbose)
|
||||
printk(KERN_INFO
|
||||
"scsi(%ld:%d:%d:%d): Queueing abort device "
|
||||
|
@ -1010,7 +1009,6 @@ qla1280_error_action(struct scsi_cmnd *cmd, enum action action)
|
|||
printk(KERN_INFO
|
||||
"scsi(%ld:%d:%d:%d): Queueing device reset "
|
||||
"command.\n", ha->host_no, bus, target, lun);
|
||||
ha->flags.in_reset = 1;
|
||||
if (qla1280_device_reset(ha, bus, target) == 0)
|
||||
result = SUCCESS;
|
||||
break;
|
||||
|
@ -1019,7 +1017,6 @@ qla1280_error_action(struct scsi_cmnd *cmd, enum action action)
|
|||
if (qla1280_verbose)
|
||||
printk(KERN_INFO "qla1280(%ld:%d): Issuing BUS "
|
||||
"DEVICE RESET\n", ha->host_no, bus);
|
||||
ha->flags.in_reset = 1;
|
||||
if (qla1280_bus_reset(ha, bus == 0))
|
||||
result = SUCCESS;
|
||||
|
||||
|
@ -1047,7 +1044,6 @@ qla1280_error_action(struct scsi_cmnd *cmd, enum action action)
|
|||
|
||||
if (!list_empty(&ha->done_q))
|
||||
qla1280_done(ha);
|
||||
ha->flags.in_reset = 0;
|
||||
|
||||
/* If we didn't manage to issue the action, or we have no
|
||||
* command to wait for, exit here */
|
||||
|
@ -1270,6 +1266,22 @@ qla1280_biosparam_old(Disk * disk, kdev_t dev, int geom[])
|
|||
}
|
||||
#endif
|
||||
|
||||
/* disable risc and host interrupts */
|
||||
static inline void
|
||||
qla1280_disable_intrs(struct scsi_qla_host *ha)
|
||||
{
|
||||
WRT_REG_WORD(&ha->iobase->ictrl, 0);
|
||||
RD_REG_WORD(&ha->iobase->ictrl); /* PCI Posted Write flush */
|
||||
}
|
||||
|
||||
/* enable risc and host interrupts */
|
||||
static inline void
|
||||
qla1280_enable_intrs(struct scsi_qla_host *ha)
|
||||
{
|
||||
WRT_REG_WORD(&ha->iobase->ictrl, (ISP_EN_INT | ISP_EN_RISC));
|
||||
RD_REG_WORD(&ha->iobase->ictrl); /* PCI Posted Write flush */
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
* qla1280_intr_handler
|
||||
* Handles the H/W interrupt
|
||||
|
@ -1290,7 +1302,7 @@ qla1280_intr_handler(int irq, void *dev_id, struct pt_regs *regs)
|
|||
ha->isr_count++;
|
||||
reg = ha->iobase;
|
||||
|
||||
WRT_REG_WORD(®->ictrl, 0); /* disable our interrupt. */
|
||||
qla1280_disable_intrs(ha);
|
||||
|
||||
data = qla1280_debounce_register(®->istatus);
|
||||
/* Check for pending interrupts. */
|
||||
|
@ -1303,8 +1315,7 @@ qla1280_intr_handler(int irq, void *dev_id, struct pt_regs *regs)
|
|||
|
||||
spin_unlock(HOST_LOCK);
|
||||
|
||||
/* enable our interrupt. */
|
||||
WRT_REG_WORD(®->ictrl, (ISP_EN_INT | ISP_EN_RISC));
|
||||
qla1280_enable_intrs(ha);
|
||||
|
||||
LEAVE_INTR("qla1280_intr_handler");
|
||||
return IRQ_RETVAL(handled);
|
||||
|
@ -1317,7 +1328,7 @@ qla1280_set_target_parameters(struct scsi_qla_host *ha, int bus, int target)
|
|||
uint8_t mr;
|
||||
uint16_t mb[MAILBOX_REGISTER_COUNT];
|
||||
struct nvram *nv;
|
||||
int status;
|
||||
int status, lun;
|
||||
|
||||
nv = &ha->nvram;
|
||||
|
||||
|
@ -1325,24 +1336,38 @@ qla1280_set_target_parameters(struct scsi_qla_host *ha, int bus, int target)
|
|||
|
||||
/* Set Target Parameters. */
|
||||
mb[0] = MBC_SET_TARGET_PARAMETERS;
|
||||
mb[1] = (uint16_t) (bus ? target | BIT_7 : target);
|
||||
mb[1] <<= 8;
|
||||
|
||||
mb[2] = (nv->bus[bus].target[target].parameter.c << 8);
|
||||
mb[1] = (uint16_t)((bus ? target | BIT_7 : target) << 8);
|
||||
mb[2] = nv->bus[bus].target[target].parameter.renegotiate_on_error << 8;
|
||||
mb[2] |= nv->bus[bus].target[target].parameter.stop_queue_on_check << 9;
|
||||
mb[2] |= nv->bus[bus].target[target].parameter.auto_request_sense << 10;
|
||||
mb[2] |= nv->bus[bus].target[target].parameter.tag_queuing << 11;
|
||||
mb[2] |= nv->bus[bus].target[target].parameter.enable_sync << 12;
|
||||
mb[2] |= nv->bus[bus].target[target].parameter.enable_wide << 13;
|
||||
mb[2] |= nv->bus[bus].target[target].parameter.parity_checking << 14;
|
||||
mb[2] |= nv->bus[bus].target[target].parameter.disconnect_allowed << 15;
|
||||
|
||||
if (IS_ISP1x160(ha)) {
|
||||
mb[2] |= nv->bus[bus].target[target].ppr_1x160.flags.enable_ppr << 5;
|
||||
mb[3] = (nv->bus[bus].target[target].flags.flags1x160.sync_offset << 8) |
|
||||
nv->bus[bus].target[target].sync_period;
|
||||
mb[3] = (nv->bus[bus].target[target].flags.flags1x160.sync_offset << 8);
|
||||
mb[6] = (nv->bus[bus].target[target].ppr_1x160.flags.ppr_options << 8) |
|
||||
nv->bus[bus].target[target].ppr_1x160.flags.ppr_bus_width;
|
||||
mr |= BIT_6;
|
||||
} else {
|
||||
mb[3] = (nv->bus[bus].target[target].flags.flags1x80.sync_offset << 8) |
|
||||
nv->bus[bus].target[target].sync_period;
|
||||
mb[3] = (nv->bus[bus].target[target].flags.flags1x80.sync_offset << 8);
|
||||
}
|
||||
mb[3] |= nv->bus[bus].target[target].sync_period;
|
||||
|
||||
status = qla1280_mailbox_command(ha, mr, &mb[0]);
|
||||
status = qla1280_mailbox_command(ha, mr, mb);
|
||||
|
||||
/* Set Device Queue Parameters. */
|
||||
for (lun = 0; lun < MAX_LUNS; lun++) {
|
||||
mb[0] = MBC_SET_DEVICE_QUEUE;
|
||||
mb[1] = (uint16_t)((bus ? target | BIT_7 : target) << 8);
|
||||
mb[1] |= lun;
|
||||
mb[2] = nv->bus[bus].max_queue_depth;
|
||||
mb[3] = nv->bus[bus].target[target].execution_throttle;
|
||||
status |= qla1280_mailbox_command(ha, 0x0f, mb);
|
||||
}
|
||||
|
||||
if (status)
|
||||
printk(KERN_WARNING "scsi(%ld:%i:%i): "
|
||||
|
@ -1389,19 +1414,19 @@ qla1280_slave_configure(struct scsi_device *device)
|
|||
}
|
||||
|
||||
#if LINUX_VERSION_CODE > 0x020500
|
||||
nv->bus[bus].target[target].parameter.f.enable_sync = device->sdtr;
|
||||
nv->bus[bus].target[target].parameter.f.enable_wide = device->wdtr;
|
||||
nv->bus[bus].target[target].parameter.enable_sync = device->sdtr;
|
||||
nv->bus[bus].target[target].parameter.enable_wide = device->wdtr;
|
||||
nv->bus[bus].target[target].ppr_1x160.flags.enable_ppr = device->ppr;
|
||||
#endif
|
||||
|
||||
if (driver_setup.no_sync ||
|
||||
(driver_setup.sync_mask &&
|
||||
(~driver_setup.sync_mask & (1 << target))))
|
||||
nv->bus[bus].target[target].parameter.f.enable_sync = 0;
|
||||
nv->bus[bus].target[target].parameter.enable_sync = 0;
|
||||
if (driver_setup.no_wide ||
|
||||
(driver_setup.wide_mask &&
|
||||
(~driver_setup.wide_mask & (1 << target))))
|
||||
nv->bus[bus].target[target].parameter.f.enable_wide = 0;
|
||||
nv->bus[bus].target[target].parameter.enable_wide = 0;
|
||||
if (IS_ISP1x160(ha)) {
|
||||
if (driver_setup.no_ppr ||
|
||||
(driver_setup.ppr_mask &&
|
||||
|
@ -1410,7 +1435,7 @@ qla1280_slave_configure(struct scsi_device *device)
|
|||
}
|
||||
|
||||
spin_lock_irqsave(HOST_LOCK, flags);
|
||||
if (nv->bus[bus].target[target].parameter.f.enable_sync)
|
||||
if (nv->bus[bus].target[target].parameter.enable_sync)
|
||||
status = qla1280_set_target_parameters(ha, bus, target);
|
||||
qla1280_get_target_parameters(ha, device);
|
||||
spin_unlock_irqrestore(HOST_LOCK, flags);
|
||||
|
@ -1448,7 +1473,6 @@ qla1280_select_queue_depth(struct Scsi_Host *host, struct scsi_device *sdev_q)
|
|||
*
|
||||
* Input:
|
||||
* ha = adapter block pointer.
|
||||
* done_q = done queue.
|
||||
*/
|
||||
static void
|
||||
qla1280_done(struct scsi_qla_host *ha)
|
||||
|
@ -1522,7 +1546,7 @@ qla1280_return_status(struct response * sts, struct scsi_cmnd *cp)
|
|||
int host_status = DID_ERROR;
|
||||
uint16_t comp_status = le16_to_cpu(sts->comp_status);
|
||||
uint16_t state_flags = le16_to_cpu(sts->state_flags);
|
||||
uint16_t residual_length = le16_to_cpu(sts->residual_length);
|
||||
uint16_t residual_length = le32_to_cpu(sts->residual_length);
|
||||
uint16_t scsi_status = le16_to_cpu(sts->scsi_status);
|
||||
#if DEBUG_QLA1280_INTR
|
||||
static char *reason[] = {
|
||||
|
@ -1582,7 +1606,7 @@ qla1280_return_status(struct response * sts, struct scsi_cmnd *cp)
|
|||
|
||||
case CS_DATA_OVERRUN:
|
||||
dprintk(2, "Data overrun 0x%x\n", residual_length);
|
||||
dprintk(2, "qla1280_isr: response packet data\n");
|
||||
dprintk(2, "qla1280_return_status: response packet data\n");
|
||||
qla1280_dump_buffer(2, (char *)sts, RESPONSE_ENTRY_SIZE);
|
||||
host_status = DID_ERROR;
|
||||
break;
|
||||
|
@ -1617,40 +1641,6 @@ qla1280_return_status(struct response * sts, struct scsi_cmnd *cp)
|
|||
/* QLogic ISP1280 Hardware Support Functions. */
|
||||
/****************************************************************************/
|
||||
|
||||
/*
|
||||
* qla2100_enable_intrs
|
||||
* qla2100_disable_intrs
|
||||
*
|
||||
* Input:
|
||||
* ha = adapter block pointer.
|
||||
*
|
||||
* Returns:
|
||||
* None
|
||||
*/
|
||||
static inline void
|
||||
qla1280_enable_intrs(struct scsi_qla_host *ha)
|
||||
{
|
||||
struct device_reg __iomem *reg;
|
||||
|
||||
reg = ha->iobase;
|
||||
/* enable risc and host interrupts */
|
||||
WRT_REG_WORD(®->ictrl, (ISP_EN_INT | ISP_EN_RISC));
|
||||
RD_REG_WORD(®->ictrl); /* PCI Posted Write flush */
|
||||
ha->flags.ints_enabled = 1;
|
||||
}
|
||||
|
||||
static inline void
|
||||
qla1280_disable_intrs(struct scsi_qla_host *ha)
|
||||
{
|
||||
struct device_reg __iomem *reg;
|
||||
|
||||
reg = ha->iobase;
|
||||
/* disable risc and host interrupts */
|
||||
WRT_REG_WORD(®->ictrl, 0);
|
||||
RD_REG_WORD(®->ictrl); /* PCI Posted Write flush */
|
||||
ha->flags.ints_enabled = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* qla1280_initialize_adapter
|
||||
* Initialize board.
|
||||
|
@ -1679,7 +1669,6 @@ qla1280_initialize_adapter(struct scsi_qla_host *ha)
|
|||
ha->flags.reset_active = 0;
|
||||
ha->flags.abort_isp_active = 0;
|
||||
|
||||
ha->flags.ints_enabled = 0;
|
||||
#if defined(CONFIG_IA64_GENERIC) || defined(CONFIG_IA64_SGI_SN2)
|
||||
if (ia64_platform_is("sn2")) {
|
||||
printk(KERN_INFO "scsi(%li): Enabling SN2 PCI DMA "
|
||||
|
@ -1758,69 +1747,6 @@ qla1280_initialize_adapter(struct scsi_qla_host *ha)
|
|||
return status;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* ISP Firmware Test
|
||||
* Checks if present version of RISC firmware is older than
|
||||
* driver firmware.
|
||||
*
|
||||
* Input:
|
||||
* ha = adapter block pointer.
|
||||
*
|
||||
* Returns:
|
||||
* 0 = firmware does not need to be loaded.
|
||||
*/
|
||||
static int
|
||||
qla1280_isp_firmware(struct scsi_qla_host *ha)
|
||||
{
|
||||
struct nvram *nv = (struct nvram *) ha->response_ring;
|
||||
int status = 0; /* dg 2/27 always loads RISC */
|
||||
uint16_t mb[MAILBOX_REGISTER_COUNT];
|
||||
|
||||
ENTER("qla1280_isp_firmware");
|
||||
|
||||
dprintk(1, "scsi(%li): Determining if RISC is loaded\n", ha->host_no);
|
||||
|
||||
/* Bad NVRAM data, load RISC code. */
|
||||
if (!ha->nvram_valid) {
|
||||
ha->flags.disable_risc_code_load = 0;
|
||||
} else
|
||||
ha->flags.disable_risc_code_load =
|
||||
nv->cntr_flags_1.disable_loading_risc_code;
|
||||
|
||||
if (ha->flags.disable_risc_code_load) {
|
||||
dprintk(3, "qla1280_isp_firmware: Telling RISC to verify "
|
||||
"checksum of loaded BIOS code.\n");
|
||||
|
||||
/* Verify checksum of loaded RISC code. */
|
||||
mb[0] = MBC_VERIFY_CHECKSUM;
|
||||
/* mb[1] = ql12_risc_code_addr01; */
|
||||
mb[1] = *ql1280_board_tbl[ha->devnum].fwstart;
|
||||
|
||||
if (!(status =
|
||||
qla1280_mailbox_command(ha, BIT_1 | BIT_0, &mb[0]))) {
|
||||
/* Start firmware execution. */
|
||||
dprintk(3, "qla1280_isp_firmware: Startng F/W "
|
||||
"execution.\n");
|
||||
|
||||
mb[0] = MBC_EXECUTE_FIRMWARE;
|
||||
/* mb[1] = ql12_risc_code_addr01; */
|
||||
mb[1] = *ql1280_board_tbl[ha->devnum].fwstart;
|
||||
qla1280_mailbox_command(ha, BIT_1 | BIT_0, &mb[0]);
|
||||
} else
|
||||
printk(KERN_INFO "qla1280: RISC checksum failed.\n");
|
||||
} else {
|
||||
dprintk(1, "qla1280: NVRAM configured to load RISC load.\n");
|
||||
status = 1;
|
||||
}
|
||||
|
||||
if (status)
|
||||
dprintk(2, "qla1280_isp_firmware: **** Load RISC code ****\n");
|
||||
|
||||
LEAVE("qla1280_isp_firmware");
|
||||
return status;
|
||||
}
|
||||
|
||||
/*
|
||||
* Chip diagnostics
|
||||
* Test chip for proper operation.
|
||||
|
@ -2006,7 +1932,7 @@ qla1280_load_firmware_dma(struct scsi_qla_host *ha)
|
|||
"%d,%d(0x%x)\n",
|
||||
risc_code_address, cnt, num, risc_address);
|
||||
for(i = 0; i < cnt; i++)
|
||||
((uint16_t *)ha->request_ring)[i] =
|
||||
((__le16 *)ha->request_ring)[i] =
|
||||
cpu_to_le16(risc_code_address[i]);
|
||||
|
||||
mb[0] = MBC_LOAD_RAM;
|
||||
|
@ -2085,7 +2011,7 @@ qla1280_start_firmware(struct scsi_qla_host *ha)
|
|||
mb[1] = *ql1280_board_tbl[ha->devnum].fwstart;
|
||||
err = qla1280_mailbox_command(ha, BIT_1 | BIT_0, mb);
|
||||
if (err) {
|
||||
printk(KERN_ERR "scsi(%li): Failed checksum\n", ha->host_no);
|
||||
printk(KERN_ERR "scsi(%li): RISC checksum failed.\n", ha->host_no);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -2105,14 +2031,7 @@ qla1280_start_firmware(struct scsi_qla_host *ha)
|
|||
static int
|
||||
qla1280_load_firmware(struct scsi_qla_host *ha)
|
||||
{
|
||||
int err = -ENODEV;
|
||||
|
||||
/* If firmware needs to be loaded */
|
||||
if (!qla1280_isp_firmware(ha)) {
|
||||
printk(KERN_ERR "scsi(%li): isp_firmware() failed!\n",
|
||||
ha->host_no);
|
||||
goto out;
|
||||
}
|
||||
int err;
|
||||
|
||||
err = qla1280_chip_diag(ha);
|
||||
if (err)
|
||||
|
@ -2246,17 +2165,17 @@ qla1280_set_target_defaults(struct scsi_qla_host *ha, int bus, int target)
|
|||
{
|
||||
struct nvram *nv = &ha->nvram;
|
||||
|
||||
nv->bus[bus].target[target].parameter.f.renegotiate_on_error = 1;
|
||||
nv->bus[bus].target[target].parameter.f.auto_request_sense = 1;
|
||||
nv->bus[bus].target[target].parameter.f.tag_queuing = 1;
|
||||
nv->bus[bus].target[target].parameter.f.enable_sync = 1;
|
||||
nv->bus[bus].target[target].parameter.renegotiate_on_error = 1;
|
||||
nv->bus[bus].target[target].parameter.auto_request_sense = 1;
|
||||
nv->bus[bus].target[target].parameter.tag_queuing = 1;
|
||||
nv->bus[bus].target[target].parameter.enable_sync = 1;
|
||||
#if 1 /* Some SCSI Processors do not seem to like this */
|
||||
nv->bus[bus].target[target].parameter.f.enable_wide = 1;
|
||||
nv->bus[bus].target[target].parameter.enable_wide = 1;
|
||||
#endif
|
||||
nv->bus[bus].target[target].parameter.f.parity_checking = 1;
|
||||
nv->bus[bus].target[target].parameter.f.disconnect_allowed = 1;
|
||||
nv->bus[bus].target[target].execution_throttle =
|
||||
nv->bus[bus].max_queue_depth - 1;
|
||||
nv->bus[bus].target[target].parameter.parity_checking = 1;
|
||||
nv->bus[bus].target[target].parameter.disconnect_allowed = 1;
|
||||
|
||||
if (IS_ISP1x160(ha)) {
|
||||
nv->bus[bus].target[target].flags.flags1x160.device_enable = 1;
|
||||
|
@ -2284,9 +2203,9 @@ qla1280_set_defaults(struct scsi_qla_host *ha)
|
|||
/* nv->cntr_flags_1.disable_loading_risc_code = 1; */
|
||||
nv->firmware_feature.f.enable_fast_posting = 1;
|
||||
nv->firmware_feature.f.disable_synchronous_backoff = 1;
|
||||
nv->termination.f.scsi_bus_0_control = 3;
|
||||
nv->termination.f.scsi_bus_1_control = 3;
|
||||
nv->termination.f.auto_term_support = 1;
|
||||
nv->termination.scsi_bus_0_control = 3;
|
||||
nv->termination.scsi_bus_1_control = 3;
|
||||
nv->termination.auto_term_support = 1;
|
||||
|
||||
/*
|
||||
* Set default FIFO magic - What appropriate values would be here
|
||||
|
@ -2296,7 +2215,12 @@ qla1280_set_defaults(struct scsi_qla_host *ha)
|
|||
* header file provided by QLogic seems to be bogus or incomplete
|
||||
* at best.
|
||||
*/
|
||||
nv->isp_config.c = ISP_CFG1_BENAB|ISP_CFG1_F128;
|
||||
nv->isp_config.burst_enable = 1;
|
||||
if (IS_ISP1040(ha))
|
||||
nv->isp_config.fifo_threshold |= 3;
|
||||
else
|
||||
nv->isp_config.fifo_threshold |= 4;
|
||||
|
||||
if (IS_ISP1x160(ha))
|
||||
nv->isp_parameter = 0x01; /* fast memory enable */
|
||||
|
||||
|
@ -2327,66 +2251,53 @@ qla1280_config_target(struct scsi_qla_host *ha, int bus, int target)
|
|||
struct nvram *nv = &ha->nvram;
|
||||
uint16_t mb[MAILBOX_REGISTER_COUNT];
|
||||
int status, lun;
|
||||
uint16_t flag;
|
||||
|
||||
/* Set Target Parameters. */
|
||||
mb[0] = MBC_SET_TARGET_PARAMETERS;
|
||||
mb[1] = (uint16_t) (bus ? target | BIT_7 : target);
|
||||
mb[1] <<= 8;
|
||||
mb[1] = (uint16_t)((bus ? target | BIT_7 : target) << 8);
|
||||
|
||||
/*
|
||||
* Do not enable wide, sync, and ppr for the initial
|
||||
* INQUIRY run. We enable this later if we determine
|
||||
* the target actually supports it.
|
||||
* Do not enable sync and ppr for the initial INQUIRY run. We
|
||||
* enable this later if we determine the target actually
|
||||
* supports it.
|
||||
*/
|
||||
nv->bus[bus].target[target].parameter.f.
|
||||
auto_request_sense = 1;
|
||||
nv->bus[bus].target[target].parameter.f.
|
||||
stop_queue_on_check = 0;
|
||||
|
||||
if (IS_ISP1x160(ha))
|
||||
nv->bus[bus].target[target].ppr_1x160.
|
||||
flags.enable_ppr = 0;
|
||||
|
||||
/*
|
||||
* No sync, wide, etc. while probing
|
||||
*/
|
||||
mb[2] = (nv->bus[bus].target[target].parameter.c << 8) &
|
||||
~(TP_SYNC /*| TP_WIDE | TP_PPR*/);
|
||||
mb[2] = (TP_RENEGOTIATE | TP_AUTO_REQUEST_SENSE | TP_TAGGED_QUEUE
|
||||
| TP_WIDE | TP_PARITY | TP_DISCONNECT);
|
||||
|
||||
if (IS_ISP1x160(ha))
|
||||
mb[3] = nv->bus[bus].target[target].flags.flags1x160.sync_offset << 8;
|
||||
else
|
||||
mb[3] = nv->bus[bus].target[target].flags.flags1x80.sync_offset << 8;
|
||||
mb[3] |= nv->bus[bus].target[target].sync_period;
|
||||
|
||||
status = qla1280_mailbox_command(ha, BIT_3 | BIT_2 | BIT_1 | BIT_0, &mb[0]);
|
||||
status = qla1280_mailbox_command(ha, 0x0f, mb);
|
||||
|
||||
/* Save Tag queuing enable flag. */
|
||||
mb[0] = BIT_0 << target;
|
||||
if (nv->bus[bus].target[target].parameter.f.tag_queuing)
|
||||
ha->bus_settings[bus].qtag_enables |= mb[0];
|
||||
flag = (BIT_0 << target) & mb[0];
|
||||
if (nv->bus[bus].target[target].parameter.tag_queuing)
|
||||
ha->bus_settings[bus].qtag_enables |= flag;
|
||||
|
||||
/* Save Device enable flag. */
|
||||
if (IS_ISP1x160(ha)) {
|
||||
if (nv->bus[bus].target[target].flags.flags1x160.device_enable)
|
||||
ha->bus_settings[bus].device_enables |= mb[0];
|
||||
ha->bus_settings[bus].device_enables |= flag;
|
||||
ha->bus_settings[bus].lun_disables |= 0;
|
||||
} else {
|
||||
if (nv->bus[bus].target[target].flags.flags1x80.device_enable)
|
||||
ha->bus_settings[bus].device_enables |= mb[0];
|
||||
ha->bus_settings[bus].device_enables |= flag;
|
||||
/* Save LUN disable flag. */
|
||||
if (nv->bus[bus].target[target].flags.flags1x80.lun_disable)
|
||||
ha->bus_settings[bus].lun_disables |= mb[0];
|
||||
ha->bus_settings[bus].lun_disables |= flag;
|
||||
}
|
||||
|
||||
/* Set Device Queue Parameters. */
|
||||
for (lun = 0; lun < MAX_LUNS; lun++) {
|
||||
mb[0] = MBC_SET_DEVICE_QUEUE;
|
||||
mb[1] = (uint16_t)(bus ? target | BIT_7 : target);
|
||||
mb[1] = mb[1] << 8 | lun;
|
||||
mb[1] = (uint16_t)((bus ? target | BIT_7 : target) << 8);
|
||||
mb[1] |= lun;
|
||||
mb[2] = nv->bus[bus].max_queue_depth;
|
||||
mb[3] = nv->bus[bus].target[target].execution_throttle;
|
||||
status |= qla1280_mailbox_command(ha, 0x0f, &mb[0]);
|
||||
status |= qla1280_mailbox_command(ha, 0x0f, mb);
|
||||
}
|
||||
|
||||
return status;
|
||||
|
@ -2431,7 +2342,6 @@ qla1280_nvram_config(struct scsi_qla_host *ha)
|
|||
struct nvram *nv = &ha->nvram;
|
||||
int bus, target, status = 0;
|
||||
uint16_t mb[MAILBOX_REGISTER_COUNT];
|
||||
uint16_t mask;
|
||||
|
||||
ENTER("qla1280_nvram_config");
|
||||
|
||||
|
@ -2439,7 +2349,7 @@ qla1280_nvram_config(struct scsi_qla_host *ha)
|
|||
/* Always force AUTO sense for LINUX SCSI */
|
||||
for (bus = 0; bus < MAX_BUSES; bus++)
|
||||
for (target = 0; target < MAX_TARGETS; target++) {
|
||||
nv->bus[bus].target[target].parameter.f.
|
||||
nv->bus[bus].target[target].parameter.
|
||||
auto_request_sense = 1;
|
||||
}
|
||||
} else {
|
||||
|
@ -2457,31 +2367,40 @@ qla1280_nvram_config(struct scsi_qla_host *ha)
|
|||
|
||||
hwrev = RD_REG_WORD(®->cfg_0) & ISP_CFG0_HWMSK;
|
||||
|
||||
cfg1 = RD_REG_WORD(®->cfg_1);
|
||||
cfg1 = RD_REG_WORD(®->cfg_1) & ~(BIT_4 | BIT_5 | BIT_6);
|
||||
cdma_conf = RD_REG_WORD(®->cdma_cfg);
|
||||
ddma_conf = RD_REG_WORD(®->ddma_cfg);
|
||||
|
||||
/* Busted fifo, says mjacob. */
|
||||
if (hwrev == ISP_CFG0_1040A)
|
||||
WRT_REG_WORD(®->cfg_1, cfg1 | ISP_CFG1_F64);
|
||||
else
|
||||
WRT_REG_WORD(®->cfg_1, cfg1 | ISP_CFG1_F64 | ISP_CFG1_BENAB);
|
||||
if (hwrev != ISP_CFG0_1040A)
|
||||
cfg1 |= nv->isp_config.fifo_threshold << 4;
|
||||
|
||||
cfg1 |= nv->isp_config.burst_enable << 2;
|
||||
WRT_REG_WORD(®->cfg_1, cfg1);
|
||||
|
||||
WRT_REG_WORD(®->cdma_cfg, cdma_conf | CDMA_CONF_BENAB);
|
||||
WRT_REG_WORD(®->ddma_cfg, cdma_conf | DDMA_CONF_BENAB);
|
||||
} else {
|
||||
uint16_t cfg1, term;
|
||||
|
||||
/* Set ISP hardware DMA burst */
|
||||
mb[0] = nv->isp_config.c;
|
||||
cfg1 = nv->isp_config.fifo_threshold << 4;
|
||||
cfg1 |= nv->isp_config.burst_enable << 2;
|
||||
/* Enable DMA arbitration on dual channel controllers */
|
||||
if (ha->ports > 1)
|
||||
mb[0] |= BIT_13;
|
||||
WRT_REG_WORD(®->cfg_1, mb[0]);
|
||||
cfg1 |= BIT_13;
|
||||
WRT_REG_WORD(®->cfg_1, cfg1);
|
||||
|
||||
/* Set SCSI termination. */
|
||||
WRT_REG_WORD(®->gpio_enable, (BIT_3 + BIT_2 + BIT_1 + BIT_0));
|
||||
mb[0] = nv->termination.c & (BIT_3 + BIT_2 + BIT_1 + BIT_0);
|
||||
WRT_REG_WORD(®->gpio_data, mb[0]);
|
||||
WRT_REG_WORD(®->gpio_enable,
|
||||
BIT_7 | BIT_3 | BIT_2 | BIT_1 | BIT_0);
|
||||
term = nv->termination.scsi_bus_1_control;
|
||||
term |= nv->termination.scsi_bus_0_control << 2;
|
||||
term |= nv->termination.auto_term_support << 7;
|
||||
RD_REG_WORD(®->id_l); /* Flush PCI write */
|
||||
WRT_REG_WORD(®->gpio_data, term);
|
||||
}
|
||||
RD_REG_WORD(®->id_l); /* Flush PCI write */
|
||||
|
||||
/* ISP parameter word. */
|
||||
mb[0] = MBC_SET_SYSTEM_PARAMETER;
|
||||
|
@ -2497,16 +2416,17 @@ qla1280_nvram_config(struct scsi_qla_host *ha)
|
|||
|
||||
/* Firmware feature word. */
|
||||
mb[0] = MBC_SET_FIRMWARE_FEATURES;
|
||||
mask = BIT_5 | BIT_1 | BIT_0;
|
||||
mb[1] = le16_to_cpu(nv->firmware_feature.w) & (mask);
|
||||
mb[1] = nv->firmware_feature.f.enable_fast_posting;
|
||||
mb[1] |= nv->firmware_feature.f.report_lvd_bus_transition << 1;
|
||||
mb[1] |= nv->firmware_feature.f.disable_synchronous_backoff << 5;
|
||||
#if defined(CONFIG_IA64_GENERIC) || defined (CONFIG_IA64_SGI_SN2)
|
||||
if (ia64_platform_is("sn2")) {
|
||||
printk(KERN_INFO "scsi(%li): Enabling SN2 PCI DMA "
|
||||
"workaround\n", ha->host_no);
|
||||
mb[1] |= BIT_9;
|
||||
mb[1] |= nv->firmware_feature.f.unused_9 << 9; /* XXX */
|
||||
}
|
||||
#endif
|
||||
status |= qla1280_mailbox_command(ha, mask, &mb[0]);
|
||||
status |= qla1280_mailbox_command(ha, BIT_1 | BIT_0, mb);
|
||||
|
||||
/* Retry count and delay. */
|
||||
mb[0] = MBC_SET_RETRY_COUNT;
|
||||
|
@ -2535,27 +2455,27 @@ qla1280_nvram_config(struct scsi_qla_host *ha)
|
|||
mb[2] |= BIT_5;
|
||||
if (nv->bus[1].config_2.data_line_active_negation)
|
||||
mb[2] |= BIT_4;
|
||||
status |= qla1280_mailbox_command(ha, BIT_2 | BIT_1 | BIT_0, &mb[0]);
|
||||
status |= qla1280_mailbox_command(ha, BIT_2 | BIT_1 | BIT_0, mb);
|
||||
|
||||
mb[0] = MBC_SET_DATA_OVERRUN_RECOVERY;
|
||||
mb[1] = 2; /* Reset SCSI bus and return all outstanding IO */
|
||||
status |= qla1280_mailbox_command(ha, BIT_1 | BIT_0, &mb[0]);
|
||||
status |= qla1280_mailbox_command(ha, BIT_1 | BIT_0, mb);
|
||||
|
||||
/* thingy */
|
||||
mb[0] = MBC_SET_PCI_CONTROL;
|
||||
mb[1] = 2; /* Data DMA Channel Burst Enable */
|
||||
mb[2] = 2; /* Command DMA Channel Burst Enable */
|
||||
status |= qla1280_mailbox_command(ha, BIT_2 | BIT_1 | BIT_0, &mb[0]);
|
||||
mb[1] = BIT_1; /* Data DMA Channel Burst Enable */
|
||||
mb[2] = BIT_1; /* Command DMA Channel Burst Enable */
|
||||
status |= qla1280_mailbox_command(ha, BIT_2 | BIT_1 | BIT_0, mb);
|
||||
|
||||
mb[0] = MBC_SET_TAG_AGE_LIMIT;
|
||||
mb[1] = 8;
|
||||
status |= qla1280_mailbox_command(ha, BIT_1 | BIT_0, &mb[0]);
|
||||
status |= qla1280_mailbox_command(ha, BIT_1 | BIT_0, mb);
|
||||
|
||||
/* Selection timeout. */
|
||||
mb[0] = MBC_SET_SELECTION_TIMEOUT;
|
||||
mb[1] = nv->bus[0].selection_timeout;
|
||||
mb[2] = nv->bus[1].selection_timeout;
|
||||
status |= qla1280_mailbox_command(ha, BIT_2 | BIT_1 | BIT_0, &mb[0]);
|
||||
status |= qla1280_mailbox_command(ha, BIT_2 | BIT_1 | BIT_0, mb);
|
||||
|
||||
for (bus = 0; bus < ha->ports; bus++)
|
||||
status |= qla1280_config_bus(ha, bus);
|
||||
|
@ -3066,7 +2986,7 @@ qla1280_64bit_start_scsi(struct scsi_qla_host *ha, struct srb * sp)
|
|||
struct scsi_cmnd *cmd = sp->cmd;
|
||||
cmd_a64_entry_t *pkt;
|
||||
struct scatterlist *sg = NULL;
|
||||
u32 *dword_ptr;
|
||||
__le32 *dword_ptr;
|
||||
dma_addr_t dma_handle;
|
||||
int status = 0;
|
||||
int cnt;
|
||||
|
@ -3104,10 +3024,13 @@ qla1280_64bit_start_scsi(struct scsi_qla_host *ha, struct srb * sp)
|
|||
REQUEST_ENTRY_CNT - (ha->req_ring_index - cnt);
|
||||
}
|
||||
|
||||
dprintk(3, "Number of free entries=(%d) seg_cnt=0x%x\n",
|
||||
ha->req_q_cnt, seg_cnt);
|
||||
|
||||
/* If room for request in request ring. */
|
||||
if ((req_cnt + 2) >= ha->req_q_cnt) {
|
||||
status = 1;
|
||||
dprintk(2, "qla1280_64bit_start_scsi: in-ptr=0x%x req_q_cnt="
|
||||
dprintk(2, "qla1280_start_scsi: in-ptr=0x%x req_q_cnt="
|
||||
"0x%xreq_cnt=0x%x", ha->req_ring_index, ha->req_q_cnt,
|
||||
req_cnt);
|
||||
goto out;
|
||||
|
@ -3119,7 +3042,7 @@ qla1280_64bit_start_scsi(struct scsi_qla_host *ha, struct srb * sp)
|
|||
|
||||
if (cnt >= MAX_OUTSTANDING_COMMANDS) {
|
||||
status = 1;
|
||||
dprintk(2, "qla1280_64bit_start_scsi: NO ROOM IN "
|
||||
dprintk(2, "qla1280_start_scsi: NO ROOM IN "
|
||||
"OUTSTANDING ARRAY, req_q_cnt=0x%x", ha->req_q_cnt);
|
||||
goto out;
|
||||
}
|
||||
|
@ -3128,7 +3051,7 @@ qla1280_64bit_start_scsi(struct scsi_qla_host *ha, struct srb * sp)
|
|||
ha->req_q_cnt -= req_cnt;
|
||||
CMD_HANDLE(sp->cmd) = (unsigned char *)(unsigned long)(cnt + 1);
|
||||
|
||||
dprintk(2, "64bit_start: cmd=%p sp=%p CDB=%xm, handle %lx\n", cmd, sp,
|
||||
dprintk(2, "start: cmd=%p sp=%p CDB=%xm, handle %lx\n", cmd, sp,
|
||||
cmd->cmnd[0], (long)CMD_HANDLE(sp->cmd));
|
||||
dprintk(2, " bus %i, target %i, lun %i\n",
|
||||
SCSI_BUS_32(cmd), SCSI_TCN_32(cmd), SCSI_LUN_32(cmd));
|
||||
|
@ -3350,7 +3273,7 @@ qla1280_32bit_start_scsi(struct scsi_qla_host *ha, struct srb * sp)
|
|||
struct scsi_cmnd *cmd = sp->cmd;
|
||||
struct cmd_entry *pkt;
|
||||
struct scatterlist *sg = NULL;
|
||||
uint32_t *dword_ptr;
|
||||
__le32 *dword_ptr;
|
||||
int status = 0;
|
||||
int cnt;
|
||||
int req_cnt;
|
||||
|
@ -3993,21 +3916,21 @@ qla1280_get_target_options(struct scsi_cmnd *cmd, struct scsi_qla_host *ha)
|
|||
result = cmd->request_buffer;
|
||||
n = &ha->nvram;
|
||||
|
||||
n->bus[bus].target[target].parameter.f.enable_wide = 0;
|
||||
n->bus[bus].target[target].parameter.f.enable_sync = 0;
|
||||
n->bus[bus].target[target].parameter.enable_wide = 0;
|
||||
n->bus[bus].target[target].parameter.enable_sync = 0;
|
||||
n->bus[bus].target[target].ppr_1x160.flags.enable_ppr = 0;
|
||||
|
||||
if (result[7] & 0x60)
|
||||
n->bus[bus].target[target].parameter.f.enable_wide = 1;
|
||||
n->bus[bus].target[target].parameter.enable_wide = 1;
|
||||
if (result[7] & 0x10)
|
||||
n->bus[bus].target[target].parameter.f.enable_sync = 1;
|
||||
n->bus[bus].target[target].parameter.enable_sync = 1;
|
||||
if ((result[2] >= 3) && (result[4] + 5 > 56) &&
|
||||
(result[56] & 0x4))
|
||||
n->bus[bus].target[target].ppr_1x160.flags.enable_ppr = 1;
|
||||
|
||||
dprintk(2, "get_target_options(): wide %i, sync %i, ppr %i\n",
|
||||
n->bus[bus].target[target].parameter.f.enable_wide,
|
||||
n->bus[bus].target[target].parameter.f.enable_sync,
|
||||
n->bus[bus].target[target].parameter.enable_wide,
|
||||
n->bus[bus].target[target].parameter.enable_sync,
|
||||
n->bus[bus].target[target].ppr_1x160.flags.enable_ppr);
|
||||
}
|
||||
#endif
|
||||
|
@ -4071,7 +3994,7 @@ qla1280_status_entry(struct scsi_qla_host *ha, struct response *pkt,
|
|||
/* Save ISP completion status */
|
||||
CMD_RESULT(cmd) = qla1280_return_status(pkt, cmd);
|
||||
|
||||
if (scsi_status & SS_CHECK_CONDITION) {
|
||||
if (scsi_status & SAM_STAT_CHECK_CONDITION) {
|
||||
if (comp_status != CS_ARS_FAILED) {
|
||||
uint16_t req_sense_length =
|
||||
le16_to_cpu(pkt->req_sense_length);
|
||||
|
@ -4650,7 +4573,7 @@ qla1280_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
|
|||
if (pci_set_dma_mask(ha->pdev, (dma_addr_t) ~ 0ULL)) {
|
||||
if (pci_set_dma_mask(ha->pdev, 0xffffffff)) {
|
||||
printk(KERN_WARNING "scsi(%li): Unable to set a "
|
||||
" suitable DMA mask - aboring\n", ha->host_no);
|
||||
"suitable DMA mask - aborting\n", ha->host_no);
|
||||
error = -ENODEV;
|
||||
goto error_free_irq;
|
||||
}
|
||||
|
@ -4660,14 +4583,14 @@ qla1280_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
|
|||
#else
|
||||
if (pci_set_dma_mask(ha->pdev, 0xffffffff)) {
|
||||
printk(KERN_WARNING "scsi(%li): Unable to set a "
|
||||
" suitable DMA mask - aboring\n", ha->host_no);
|
||||
"suitable DMA mask - aborting\n", ha->host_no);
|
||||
error = -ENODEV;
|
||||
goto error_free_irq;
|
||||
}
|
||||
#endif
|
||||
|
||||
ha->request_ring = pci_alloc_consistent(ha->pdev,
|
||||
((REQUEST_ENTRY_CNT + 1) * (sizeof(request_t))),
|
||||
((REQUEST_ENTRY_CNT + 1) * sizeof(request_t)),
|
||||
&ha->request_dma);
|
||||
if (!ha->request_ring) {
|
||||
printk(KERN_INFO "qla1280: Failed to get request memory\n");
|
||||
|
@ -4675,7 +4598,7 @@ qla1280_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
|
|||
}
|
||||
|
||||
ha->response_ring = pci_alloc_consistent(ha->pdev,
|
||||
((RESPONSE_ENTRY_CNT + 1) * (sizeof(struct response))),
|
||||
((RESPONSE_ENTRY_CNT + 1) * sizeof(struct response)),
|
||||
&ha->response_dma);
|
||||
if (!ha->response_ring) {
|
||||
printk(KERN_INFO "qla1280: Failed to get response memory\n");
|
||||
|
@ -4758,7 +4681,7 @@ qla1280_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
|
|||
|
||||
#if LINUX_VERSION_CODE >= 0x020600
|
||||
error_disable_adapter:
|
||||
WRT_REG_WORD(&ha->iobase->ictrl, 0);
|
||||
qla1280_disable_intrs(ha);
|
||||
#endif
|
||||
error_free_irq:
|
||||
free_irq(pdev->irq, ha);
|
||||
|
@ -4770,11 +4693,11 @@ qla1280_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
|
|||
#endif
|
||||
error_free_response_ring:
|
||||
pci_free_consistent(ha->pdev,
|
||||
((RESPONSE_ENTRY_CNT + 1) * (sizeof(struct response))),
|
||||
((RESPONSE_ENTRY_CNT + 1) * sizeof(struct response)),
|
||||
ha->response_ring, ha->response_dma);
|
||||
error_free_request_ring:
|
||||
pci_free_consistent(ha->pdev,
|
||||
((REQUEST_ENTRY_CNT + 1) * (sizeof(request_t))),
|
||||
((REQUEST_ENTRY_CNT + 1) * sizeof(request_t)),
|
||||
ha->request_ring, ha->request_dma);
|
||||
error_put_host:
|
||||
scsi_host_put(host);
|
||||
|
@ -4795,7 +4718,7 @@ qla1280_remove_one(struct pci_dev *pdev)
|
|||
scsi_remove_host(host);
|
||||
#endif
|
||||
|
||||
WRT_REG_WORD(&ha->iobase->ictrl, 0);
|
||||
qla1280_disable_intrs(ha);
|
||||
|
||||
free_irq(pdev->irq, ha);
|
||||
|
||||
|
|
|
@ -94,9 +94,6 @@
|
|||
#define REQUEST_ENTRY_CNT 256 /* Number of request entries. */
|
||||
#define RESPONSE_ENTRY_CNT 16 /* Number of response entries. */
|
||||
|
||||
/* Number of segments 1 - 65535 */
|
||||
#define SG_SEGMENTS 32 /* Cmd entry + 6 continuations */
|
||||
|
||||
/*
|
||||
* SCSI Request Block structure (sp) that is placed
|
||||
* on cmd->SCp location of every I/O
|
||||
|
@ -378,21 +375,16 @@ struct nvram {
|
|||
uint16_t unused_12; /* 12, 13 */
|
||||
uint16_t unused_14; /* 14, 15 */
|
||||
|
||||
union {
|
||||
uint8_t c;
|
||||
struct {
|
||||
uint8_t reserved:2;
|
||||
uint8_t burst_enable:1;
|
||||
uint8_t reserved_1:1;
|
||||
uint8_t fifo_threshold:4;
|
||||
} f;
|
||||
} isp_config; /* 16 */
|
||||
|
||||
/* Termination
|
||||
* 0 = Disable, 1 = high only, 3 = Auto term
|
||||
*/
|
||||
union {
|
||||
uint8_t c;
|
||||
struct {
|
||||
uint8_t scsi_bus_1_control:2;
|
||||
uint8_t scsi_bus_0_control:2;
|
||||
|
@ -400,7 +392,6 @@ struct nvram {
|
|||
uint8_t unused_1:1;
|
||||
uint8_t unused_2:1;
|
||||
uint8_t auto_term_support:1;
|
||||
} f;
|
||||
} termination; /* 17 */
|
||||
|
||||
uint16_t isp_parameter; /* 18, 19 */
|
||||
|
@ -460,8 +451,6 @@ struct nvram {
|
|||
uint16_t unused_38; /* 38, 39 */
|
||||
|
||||
struct {
|
||||
union {
|
||||
uint8_t c;
|
||||
struct {
|
||||
uint8_t renegotiate_on_error:1;
|
||||
uint8_t stop_queue_on_check:1;
|
||||
|
@ -471,7 +460,6 @@ struct nvram {
|
|||
uint8_t enable_wide:1;
|
||||
uint8_t parity_checking:1;
|
||||
uint8_t disconnect_allowed:1;
|
||||
} f;
|
||||
} parameter; /* 40 */
|
||||
|
||||
uint8_t execution_throttle; /* 41 */
|
||||
|
@ -528,23 +516,23 @@ struct cmd_entry {
|
|||
uint8_t entry_count; /* Entry count. */
|
||||
uint8_t sys_define; /* System defined. */
|
||||
uint8_t entry_status; /* Entry Status. */
|
||||
uint32_t handle; /* System handle. */
|
||||
__le32 handle; /* System handle. */
|
||||
uint8_t lun; /* SCSI LUN */
|
||||
uint8_t target; /* SCSI ID */
|
||||
uint16_t cdb_len; /* SCSI command length. */
|
||||
uint16_t control_flags; /* Control flags. */
|
||||
uint16_t reserved;
|
||||
uint16_t timeout; /* Command timeout. */
|
||||
uint16_t dseg_count; /* Data segment count. */
|
||||
__le16 cdb_len; /* SCSI command length. */
|
||||
__le16 control_flags; /* Control flags. */
|
||||
__le16 reserved;
|
||||
__le16 timeout; /* Command timeout. */
|
||||
__le16 dseg_count; /* Data segment count. */
|
||||
uint8_t scsi_cdb[MAX_CMDSZ]; /* SCSI command words. */
|
||||
uint32_t dseg_0_address; /* Data segment 0 address. */
|
||||
uint32_t dseg_0_length; /* Data segment 0 length. */
|
||||
uint32_t dseg_1_address; /* Data segment 1 address. */
|
||||
uint32_t dseg_1_length; /* Data segment 1 length. */
|
||||
uint32_t dseg_2_address; /* Data segment 2 address. */
|
||||
uint32_t dseg_2_length; /* Data segment 2 length. */
|
||||
uint32_t dseg_3_address; /* Data segment 3 address. */
|
||||
uint32_t dseg_3_length; /* Data segment 3 length. */
|
||||
__le32 dseg_0_address; /* Data segment 0 address. */
|
||||
__le32 dseg_0_length; /* Data segment 0 length. */
|
||||
__le32 dseg_1_address; /* Data segment 1 address. */
|
||||
__le32 dseg_1_length; /* Data segment 1 length. */
|
||||
__le32 dseg_2_address; /* Data segment 2 address. */
|
||||
__le32 dseg_2_length; /* Data segment 2 length. */
|
||||
__le32 dseg_3_address; /* Data segment 3 address. */
|
||||
__le32 dseg_3_length; /* Data segment 3 length. */
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -556,21 +544,21 @@ struct cont_entry {
|
|||
uint8_t entry_count; /* Entry count. */
|
||||
uint8_t sys_define; /* System defined. */
|
||||
uint8_t entry_status; /* Entry Status. */
|
||||
uint32_t reserved; /* Reserved */
|
||||
uint32_t dseg_0_address; /* Data segment 0 address. */
|
||||
uint32_t dseg_0_length; /* Data segment 0 length. */
|
||||
uint32_t dseg_1_address; /* Data segment 1 address. */
|
||||
uint32_t dseg_1_length; /* Data segment 1 length. */
|
||||
uint32_t dseg_2_address; /* Data segment 2 address. */
|
||||
uint32_t dseg_2_length; /* Data segment 2 length. */
|
||||
uint32_t dseg_3_address; /* Data segment 3 address. */
|
||||
uint32_t dseg_3_length; /* Data segment 3 length. */
|
||||
uint32_t dseg_4_address; /* Data segment 4 address. */
|
||||
uint32_t dseg_4_length; /* Data segment 4 length. */
|
||||
uint32_t dseg_5_address; /* Data segment 5 address. */
|
||||
uint32_t dseg_5_length; /* Data segment 5 length. */
|
||||
uint32_t dseg_6_address; /* Data segment 6 address. */
|
||||
uint32_t dseg_6_length; /* Data segment 6 length. */
|
||||
__le32 reserved; /* Reserved */
|
||||
__le32 dseg_0_address; /* Data segment 0 address. */
|
||||
__le32 dseg_0_length; /* Data segment 0 length. */
|
||||
__le32 dseg_1_address; /* Data segment 1 address. */
|
||||
__le32 dseg_1_length; /* Data segment 1 length. */
|
||||
__le32 dseg_2_address; /* Data segment 2 address. */
|
||||
__le32 dseg_2_length; /* Data segment 2 length. */
|
||||
__le32 dseg_3_address; /* Data segment 3 address. */
|
||||
__le32 dseg_3_length; /* Data segment 3 length. */
|
||||
__le32 dseg_4_address; /* Data segment 4 address. */
|
||||
__le32 dseg_4_length; /* Data segment 4 length. */
|
||||
__le32 dseg_5_address; /* Data segment 5 address. */
|
||||
__le32 dseg_5_length; /* Data segment 5 length. */
|
||||
__le32 dseg_6_address; /* Data segment 6 address. */
|
||||
__le32 dseg_6_length; /* Data segment 6 length. */
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -586,10 +574,10 @@ struct response {
|
|||
#define RF_FULL BIT_1 /* Full */
|
||||
#define RF_BAD_HEADER BIT_2 /* Bad header. */
|
||||
#define RF_BAD_PAYLOAD BIT_3 /* Bad payload. */
|
||||
uint32_t handle; /* System handle. */
|
||||
uint16_t scsi_status; /* SCSI status. */
|
||||
uint16_t comp_status; /* Completion status. */
|
||||
uint16_t state_flags; /* State flags. */
|
||||
__le32 handle; /* System handle. */
|
||||
__le16 scsi_status; /* SCSI status. */
|
||||
__le16 comp_status; /* Completion status. */
|
||||
__le16 state_flags; /* State flags. */
|
||||
#define SF_TRANSFER_CMPL BIT_14 /* Transfer Complete. */
|
||||
#define SF_GOT_SENSE BIT_13 /* Got Sense */
|
||||
#define SF_GOT_STATUS BIT_12 /* Got Status */
|
||||
|
@ -597,11 +585,11 @@ struct response {
|
|||
#define SF_SENT_CDB BIT_10 /* Send CDB */
|
||||
#define SF_GOT_TARGET BIT_9 /* */
|
||||
#define SF_GOT_BUS BIT_8 /* */
|
||||
uint16_t status_flags; /* Status flags. */
|
||||
uint16_t time; /* Time. */
|
||||
uint16_t req_sense_length; /* Request sense data length. */
|
||||
uint32_t residual_length; /* Residual transfer length. */
|
||||
uint16_t reserved[4];
|
||||
__le16 status_flags; /* Status flags. */
|
||||
__le16 time; /* Time. */
|
||||
__le16 req_sense_length;/* Request sense data length. */
|
||||
__le32 residual_length; /* Residual transfer length. */
|
||||
__le16 reserved[4];
|
||||
uint8_t req_sense_data[32]; /* Request sense data. */
|
||||
};
|
||||
|
||||
|
@ -614,7 +602,7 @@ struct mrk_entry {
|
|||
uint8_t entry_count; /* Entry count. */
|
||||
uint8_t sys_define; /* System defined. */
|
||||
uint8_t entry_status; /* Entry Status. */
|
||||
uint32_t reserved;
|
||||
__le32 reserved;
|
||||
uint8_t lun; /* SCSI LUN */
|
||||
uint8_t target; /* SCSI ID */
|
||||
uint8_t modifier; /* Modifier (7-0). */
|
||||
|
@ -638,11 +626,11 @@ struct ecmd_entry {
|
|||
uint32_t handle; /* System handle. */
|
||||
uint8_t lun; /* SCSI LUN */
|
||||
uint8_t target; /* SCSI ID */
|
||||
uint16_t cdb_len; /* SCSI command length. */
|
||||
uint16_t control_flags; /* Control flags. */
|
||||
uint16_t reserved;
|
||||
uint16_t timeout; /* Command timeout. */
|
||||
uint16_t dseg_count; /* Data segment count. */
|
||||
__le16 cdb_len; /* SCSI command length. */
|
||||
__le16 control_flags; /* Control flags. */
|
||||
__le16 reserved;
|
||||
__le16 timeout; /* Command timeout. */
|
||||
__le16 dseg_count; /* Data segment count. */
|
||||
uint8_t scsi_cdb[88]; /* SCSI command words. */
|
||||
};
|
||||
|
||||
|
@ -655,20 +643,20 @@ typedef struct {
|
|||
uint8_t entry_count; /* Entry count. */
|
||||
uint8_t sys_define; /* System defined. */
|
||||
uint8_t entry_status; /* Entry Status. */
|
||||
uint32_t handle; /* System handle. */
|
||||
__le32 handle; /* System handle. */
|
||||
uint8_t lun; /* SCSI LUN */
|
||||
uint8_t target; /* SCSI ID */
|
||||
uint16_t cdb_len; /* SCSI command length. */
|
||||
uint16_t control_flags; /* Control flags. */
|
||||
uint16_t reserved;
|
||||
uint16_t timeout; /* Command timeout. */
|
||||
uint16_t dseg_count; /* Data segment count. */
|
||||
__le16 cdb_len; /* SCSI command length. */
|
||||
__le16 control_flags; /* Control flags. */
|
||||
__le16 reserved;
|
||||
__le16 timeout; /* Command timeout. */
|
||||
__le16 dseg_count; /* Data segment count. */
|
||||
uint8_t scsi_cdb[MAX_CMDSZ]; /* SCSI command words. */
|
||||
uint32_t reserved_1[2]; /* unused */
|
||||
uint32_t dseg_0_address[2]; /* Data segment 0 address. */
|
||||
uint32_t dseg_0_length; /* Data segment 0 length. */
|
||||
uint32_t dseg_1_address[2]; /* Data segment 1 address. */
|
||||
uint32_t dseg_1_length; /* Data segment 1 length. */
|
||||
__le32 reserved_1[2]; /* unused */
|
||||
__le32 dseg_0_address[2]; /* Data segment 0 address. */
|
||||
__le32 dseg_0_length; /* Data segment 0 length. */
|
||||
__le32 dseg_1_address[2]; /* Data segment 1 address. */
|
||||
__le32 dseg_1_length; /* Data segment 1 length. */
|
||||
} cmd_a64_entry_t, request_t;
|
||||
|
||||
/*
|
||||
|
@ -680,16 +668,16 @@ struct cont_a64_entry {
|
|||
uint8_t entry_count; /* Entry count. */
|
||||
uint8_t sys_define; /* System defined. */
|
||||
uint8_t entry_status; /* Entry Status. */
|
||||
uint32_t dseg_0_address[2]; /* Data segment 0 address. */
|
||||
uint32_t dseg_0_length; /* Data segment 0 length. */
|
||||
uint32_t dseg_1_address[2]; /* Data segment 1 address. */
|
||||
uint32_t dseg_1_length; /* Data segment 1 length. */
|
||||
uint32_t dseg_2_address[2]; /* Data segment 2 address. */
|
||||
uint32_t dseg_2_length; /* Data segment 2 length. */
|
||||
uint32_t dseg_3_address[2]; /* Data segment 3 address. */
|
||||
uint32_t dseg_3_length; /* Data segment 3 length. */
|
||||
uint32_t dseg_4_address[2]; /* Data segment 4 address. */
|
||||
uint32_t dseg_4_length; /* Data segment 4 length. */
|
||||
__le32 dseg_0_address[2]; /* Data segment 0 address. */
|
||||
__le32 dseg_0_length; /* Data segment 0 length. */
|
||||
__le32 dseg_1_address[2]; /* Data segment 1 address. */
|
||||
__le32 dseg_1_length; /* Data segment 1 length. */
|
||||
__le32 dseg_2_address[2]; /* Data segment 2 address. */
|
||||
__le32 dseg_2_length; /* Data segment 2 length. */
|
||||
__le32 dseg_3_address[2]; /* Data segment 3 address. */
|
||||
__le32 dseg_3_length; /* Data segment 3 length. */
|
||||
__le32 dseg_4_address[2]; /* Data segment 4 address. */
|
||||
__le32 dseg_4_length; /* Data segment 4 length. */
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -701,10 +689,10 @@ struct elun_entry {
|
|||
uint8_t entry_count; /* Entry count. */
|
||||
uint8_t reserved_1;
|
||||
uint8_t entry_status; /* Entry Status not used. */
|
||||
uint32_t reserved_2;
|
||||
uint16_t lun; /* Bit 15 is bus number. */
|
||||
uint16_t reserved_4;
|
||||
uint32_t option_flags;
|
||||
__le32 reserved_2;
|
||||
__le16 lun; /* Bit 15 is bus number. */
|
||||
__le16 reserved_4;
|
||||
__le32 option_flags;
|
||||
uint8_t status;
|
||||
uint8_t reserved_5;
|
||||
uint8_t command_count; /* Number of ATIOs allocated. */
|
||||
|
@ -714,8 +702,8 @@ struct elun_entry {
|
|||
/* commands (2-26). */
|
||||
uint8_t group_7_length; /* SCSI CDB length for group 7 */
|
||||
/* commands (2-26). */
|
||||
uint16_t timeout; /* 0 = 30 seconds, 0xFFFF = disable */
|
||||
uint16_t reserved_6[20];
|
||||
__le16 timeout; /* 0 = 30 seconds, 0xFFFF = disable */
|
||||
__le16 reserved_6[20];
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -729,20 +717,20 @@ struct modify_lun_entry {
|
|||
uint8_t entry_count; /* Entry count. */
|
||||
uint8_t reserved_1;
|
||||
uint8_t entry_status; /* Entry Status. */
|
||||
uint32_t reserved_2;
|
||||
__le32 reserved_2;
|
||||
uint8_t lun; /* SCSI LUN */
|
||||
uint8_t reserved_3;
|
||||
uint8_t operators;
|
||||
uint8_t reserved_4;
|
||||
uint32_t option_flags;
|
||||
__le32 option_flags;
|
||||
uint8_t status;
|
||||
uint8_t reserved_5;
|
||||
uint8_t command_count; /* Number of ATIOs allocated. */
|
||||
uint8_t immed_notify_count; /* Number of Immediate Notify */
|
||||
/* entries allocated. */
|
||||
uint16_t reserved_6;
|
||||
uint16_t timeout; /* 0 = 30 seconds, 0xFFFF = disable */
|
||||
uint16_t reserved_7[20];
|
||||
__le16 reserved_6;
|
||||
__le16 timeout; /* 0 = 30 seconds, 0xFFFF = disable */
|
||||
__le16 reserved_7[20];
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -754,20 +742,20 @@ struct notify_entry {
|
|||
uint8_t entry_count; /* Entry count. */
|
||||
uint8_t reserved_1;
|
||||
uint8_t entry_status; /* Entry Status. */
|
||||
uint32_t reserved_2;
|
||||
__le32 reserved_2;
|
||||
uint8_t lun;
|
||||
uint8_t initiator_id;
|
||||
uint8_t reserved_3;
|
||||
uint8_t target_id;
|
||||
uint32_t option_flags;
|
||||
__le32 option_flags;
|
||||
uint8_t status;
|
||||
uint8_t reserved_4;
|
||||
uint8_t tag_value; /* Received queue tag message value */
|
||||
uint8_t tag_type; /* Received queue tag message type */
|
||||
/* entries allocated. */
|
||||
uint16_t seq_id;
|
||||
__le16 seq_id;
|
||||
uint8_t scsi_msg[8]; /* SCSI message not handled by ISP */
|
||||
uint16_t reserved_5[8];
|
||||
__le16 reserved_5[8];
|
||||
uint8_t sense_data[18];
|
||||
};
|
||||
|
||||
|
@ -780,16 +768,16 @@ struct nack_entry {
|
|||
uint8_t entry_count; /* Entry count. */
|
||||
uint8_t reserved_1;
|
||||
uint8_t entry_status; /* Entry Status. */
|
||||
uint32_t reserved_2;
|
||||
__le32 reserved_2;
|
||||
uint8_t lun;
|
||||
uint8_t initiator_id;
|
||||
uint8_t reserved_3;
|
||||
uint8_t target_id;
|
||||
uint32_t option_flags;
|
||||
__le32 option_flags;
|
||||
uint8_t status;
|
||||
uint8_t event;
|
||||
uint16_t seq_id;
|
||||
uint16_t reserved_4[22];
|
||||
__le16 seq_id;
|
||||
__le16 reserved_4[22];
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -801,12 +789,12 @@ struct atio_entry {
|
|||
uint8_t entry_count; /* Entry count. */
|
||||
uint8_t reserved_1;
|
||||
uint8_t entry_status; /* Entry Status. */
|
||||
uint32_t reserved_2;
|
||||
__le32 reserved_2;
|
||||
uint8_t lun;
|
||||
uint8_t initiator_id;
|
||||
uint8_t cdb_len;
|
||||
uint8_t target_id;
|
||||
uint32_t option_flags;
|
||||
__le32 option_flags;
|
||||
uint8_t status;
|
||||
uint8_t scsi_status;
|
||||
uint8_t tag_value; /* Received queue tag message value */
|
||||
|
@ -824,28 +812,28 @@ struct ctio_entry {
|
|||
uint8_t entry_count; /* Entry count. */
|
||||
uint8_t reserved_1;
|
||||
uint8_t entry_status; /* Entry Status. */
|
||||
uint32_t reserved_2;
|
||||
__le32 reserved_2;
|
||||
uint8_t lun; /* SCSI LUN */
|
||||
uint8_t initiator_id;
|
||||
uint8_t reserved_3;
|
||||
uint8_t target_id;
|
||||
uint32_t option_flags;
|
||||
__le32 option_flags;
|
||||
uint8_t status;
|
||||
uint8_t scsi_status;
|
||||
uint8_t tag_value; /* Received queue tag message value */
|
||||
uint8_t tag_type; /* Received queue tag message type */
|
||||
uint32_t transfer_length;
|
||||
uint32_t residual;
|
||||
uint16_t timeout; /* 0 = 30 seconds, 0xFFFF = disable */
|
||||
uint16_t dseg_count; /* Data segment count. */
|
||||
uint32_t dseg_0_address; /* Data segment 0 address. */
|
||||
uint32_t dseg_0_length; /* Data segment 0 length. */
|
||||
uint32_t dseg_1_address; /* Data segment 1 address. */
|
||||
uint32_t dseg_1_length; /* Data segment 1 length. */
|
||||
uint32_t dseg_2_address; /* Data segment 2 address. */
|
||||
uint32_t dseg_2_length; /* Data segment 2 length. */
|
||||
uint32_t dseg_3_address; /* Data segment 3 address. */
|
||||
uint32_t dseg_3_length; /* Data segment 3 length. */
|
||||
__le32 transfer_length;
|
||||
__le32 residual;
|
||||
__le16 timeout; /* 0 = 30 seconds, 0xFFFF = disable */
|
||||
__le16 dseg_count; /* Data segment count. */
|
||||
__le32 dseg_0_address; /* Data segment 0 address. */
|
||||
__le32 dseg_0_length; /* Data segment 0 length. */
|
||||
__le32 dseg_1_address; /* Data segment 1 address. */
|
||||
__le32 dseg_1_length; /* Data segment 1 length. */
|
||||
__le32 dseg_2_address; /* Data segment 2 address. */
|
||||
__le32 dseg_2_length; /* Data segment 2 length. */
|
||||
__le32 dseg_3_address; /* Data segment 3 address. */
|
||||
__le32 dseg_3_length; /* Data segment 3 length. */
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -857,24 +845,24 @@ struct ctio_ret_entry {
|
|||
uint8_t entry_count; /* Entry count. */
|
||||
uint8_t reserved_1;
|
||||
uint8_t entry_status; /* Entry Status. */
|
||||
uint32_t reserved_2;
|
||||
__le32 reserved_2;
|
||||
uint8_t lun; /* SCSI LUN */
|
||||
uint8_t initiator_id;
|
||||
uint8_t reserved_3;
|
||||
uint8_t target_id;
|
||||
uint32_t option_flags;
|
||||
__le32 option_flags;
|
||||
uint8_t status;
|
||||
uint8_t scsi_status;
|
||||
uint8_t tag_value; /* Received queue tag message value */
|
||||
uint8_t tag_type; /* Received queue tag message type */
|
||||
uint32_t transfer_length;
|
||||
uint32_t residual;
|
||||
uint16_t timeout; /* 0 = 30 seconds, 0xFFFF = disable */
|
||||
uint16_t dseg_count; /* Data segment count. */
|
||||
uint32_t dseg_0_address; /* Data segment 0 address. */
|
||||
uint32_t dseg_0_length; /* Data segment 0 length. */
|
||||
uint32_t dseg_1_address; /* Data segment 1 address. */
|
||||
uint16_t dseg_1_length; /* Data segment 1 length. */
|
||||
__le32 transfer_length;
|
||||
__le32 residual;
|
||||
__le16 timeout; /* 0 = 30 seconds, 0xFFFF = disable */
|
||||
__le16 dseg_count; /* Data segment count. */
|
||||
__le32 dseg_0_address; /* Data segment 0 address. */
|
||||
__le32 dseg_0_length; /* Data segment 0 length. */
|
||||
__le32 dseg_1_address; /* Data segment 1 address. */
|
||||
__le16 dseg_1_length; /* Data segment 1 length. */
|
||||
uint8_t sense_data[18];
|
||||
};
|
||||
|
||||
|
@ -887,25 +875,25 @@ struct ctio_a64_entry {
|
|||
uint8_t entry_count; /* Entry count. */
|
||||
uint8_t reserved_1;
|
||||
uint8_t entry_status; /* Entry Status. */
|
||||
uint32_t reserved_2;
|
||||
__le32 reserved_2;
|
||||
uint8_t lun; /* SCSI LUN */
|
||||
uint8_t initiator_id;
|
||||
uint8_t reserved_3;
|
||||
uint8_t target_id;
|
||||
uint32_t option_flags;
|
||||
__le32 option_flags;
|
||||
uint8_t status;
|
||||
uint8_t scsi_status;
|
||||
uint8_t tag_value; /* Received queue tag message value */
|
||||
uint8_t tag_type; /* Received queue tag message type */
|
||||
uint32_t transfer_length;
|
||||
uint32_t residual;
|
||||
uint16_t timeout; /* 0 = 30 seconds, 0xFFFF = disable */
|
||||
uint16_t dseg_count; /* Data segment count. */
|
||||
uint32_t reserved_4[2];
|
||||
uint32_t dseg_0_address[2]; /* Data segment 0 address. */
|
||||
uint32_t dseg_0_length; /* Data segment 0 length. */
|
||||
uint32_t dseg_1_address[2]; /* Data segment 1 address. */
|
||||
uint32_t dseg_1_length; /* Data segment 1 length. */
|
||||
__le32 transfer_length;
|
||||
__le32 residual;
|
||||
__le16 timeout; /* 0 = 30 seconds, 0xFFFF = disable */
|
||||
__le16 dseg_count; /* Data segment count. */
|
||||
__le32 reserved_4[2];
|
||||
__le32 dseg_0_address[2];/* Data segment 0 address. */
|
||||
__le32 dseg_0_length; /* Data segment 0 length. */
|
||||
__le32 dseg_1_address[2];/* Data segment 1 address. */
|
||||
__le32 dseg_1_length; /* Data segment 1 length. */
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -917,21 +905,21 @@ struct ctio_a64_ret_entry {
|
|||
uint8_t entry_count; /* Entry count. */
|
||||
uint8_t reserved_1;
|
||||
uint8_t entry_status; /* Entry Status. */
|
||||
uint32_t reserved_2;
|
||||
__le32 reserved_2;
|
||||
uint8_t lun; /* SCSI LUN */
|
||||
uint8_t initiator_id;
|
||||
uint8_t reserved_3;
|
||||
uint8_t target_id;
|
||||
uint32_t option_flags;
|
||||
__le32 option_flags;
|
||||
uint8_t status;
|
||||
uint8_t scsi_status;
|
||||
uint8_t tag_value; /* Received queue tag message value */
|
||||
uint8_t tag_type; /* Received queue tag message type */
|
||||
uint32_t transfer_length;
|
||||
uint32_t residual;
|
||||
uint16_t timeout; /* 0 = 30 seconds, 0xFFFF = disable */
|
||||
uint16_t dseg_count; /* Data segment count. */
|
||||
uint16_t reserved_4[7];
|
||||
__le32 transfer_length;
|
||||
__le32 residual;
|
||||
__le16 timeout; /* 0 = 30 seconds, 0xFFFF = disable */
|
||||
__le16 dseg_count; /* Data segment count. */
|
||||
__le16 reserved_4[7];
|
||||
uint8_t sense_data[18];
|
||||
};
|
||||
|
||||
|
@ -978,14 +966,6 @@ struct ctio_a64_ret_entry {
|
|||
#define CS_UNKNOWN 0x81 /* Driver defined */
|
||||
#define CS_RETRY 0x82 /* Driver defined */
|
||||
|
||||
/*
|
||||
* ISP status entry - SCSI status byte bit definitions.
|
||||
*/
|
||||
#define SS_CHECK_CONDITION BIT_1
|
||||
#define SS_CONDITION_MET BIT_2
|
||||
#define SS_BUSY_CONDITION BIT_3
|
||||
#define SS_RESERVE_CONFLICT (BIT_4 | BIT_3)
|
||||
|
||||
/*
|
||||
* ISP target entries - Option flags bit definitions.
|
||||
*/
|
||||
|
@ -1082,10 +1062,6 @@ struct scsi_qla_host {
|
|||
uint32_t reset_active:1; /* 3 */
|
||||
uint32_t abort_isp_active:1; /* 4 */
|
||||
uint32_t disable_risc_code_load:1; /* 5 */
|
||||
uint32_t enable_64bit_addressing:1; /* 6 */
|
||||
uint32_t in_reset:1; /* 7 */
|
||||
uint32_t ints_enabled:1;
|
||||
uint32_t ignore_nvram:1;
|
||||
#ifdef __ia64__
|
||||
uint32_t use_pci_vchannel:1;
|
||||
#endif
|
||||
|
|
|
@ -268,6 +268,7 @@ struct scsi_cmnd *scsi_get_command(struct scsi_device *dev, int gfp_mask)
|
|||
} else
|
||||
put_device(&dev->sdev_gendev);
|
||||
|
||||
cmd->jiffies_at_alloc = jiffies;
|
||||
return cmd;
|
||||
}
|
||||
EXPORT_SYMBOL(scsi_get_command);
|
||||
|
@ -627,7 +628,7 @@ int scsi_dispatch_cmd(struct scsi_cmnd *cmd)
|
|||
spin_lock_irqsave(host->host_lock, flags);
|
||||
scsi_cmd_get_serial(host, cmd);
|
||||
|
||||
if (unlikely(test_bit(SHOST_CANCEL, &host->shost_state))) {
|
||||
if (unlikely(host->shost_state == SHOST_DEL)) {
|
||||
cmd->result = (DID_NO_CONNECT << 16);
|
||||
scsi_done(cmd);
|
||||
} else {
|
||||
|
@ -798,9 +799,23 @@ static void scsi_softirq(struct softirq_action *h)
|
|||
while (!list_empty(&local_q)) {
|
||||
struct scsi_cmnd *cmd = list_entry(local_q.next,
|
||||
struct scsi_cmnd, eh_entry);
|
||||
/* The longest time any command should be outstanding is the
|
||||
* per command timeout multiplied by the number of retries.
|
||||
*
|
||||
* For a typical command, this is 2.5 minutes */
|
||||
unsigned long wait_for
|
||||
= cmd->allowed * cmd->timeout_per_command;
|
||||
list_del_init(&cmd->eh_entry);
|
||||
|
||||
disposition = scsi_decide_disposition(cmd);
|
||||
if (disposition != SUCCESS &&
|
||||
time_before(cmd->jiffies_at_alloc + wait_for, jiffies)) {
|
||||
dev_printk(KERN_ERR, &cmd->device->sdev_gendev,
|
||||
"timing out command, waited %lus\n",
|
||||
wait_for/HZ);
|
||||
disposition = SUCCESS;
|
||||
}
|
||||
|
||||
scsi_log_completion(cmd, disposition);
|
||||
switch (disposition) {
|
||||
case SUCCESS:
|
||||
|
|
|
@ -114,6 +114,7 @@ static struct {
|
|||
{"YAMAHA", "CDR102", "1.00", BLIST_NOLUN}, /* locks up */
|
||||
{"YAMAHA", "CRW8424S", "1.0", BLIST_NOLUN}, /* locks up */
|
||||
{"YAMAHA", "CRW6416S", "1.0c", BLIST_NOLUN}, /* locks up */
|
||||
{"", "Scanner", "1.80", BLIST_NOLUN}, /* responds to all lun */
|
||||
|
||||
/*
|
||||
* Other types of devices that have special flags.
|
||||
|
@ -135,7 +136,7 @@ static struct {
|
|||
{"COMPAQ", "MSA1000 VOLUME", NULL, BLIST_SPARSELUN | BLIST_NOSTARTONADD},
|
||||
{"COMPAQ", "HSV110", NULL, BLIST_REPORTLUN2 | BLIST_NOSTARTONADD},
|
||||
{"DDN", "SAN DataDirector", "*", BLIST_SPARSELUN},
|
||||
{"DEC", "HSG80", NULL, BLIST_SPARSELUN | BLIST_NOSTARTONADD},
|
||||
{"DEC", "HSG80", NULL, BLIST_REPORTLUN2 | BLIST_NOSTARTONADD},
|
||||
{"DELL", "PV660F", NULL, BLIST_SPARSELUN},
|
||||
{"DELL", "PV660F PSEUDO", NULL, BLIST_SPARSELUN},
|
||||
{"DELL", "PSEUDO DEVICE .", NULL, BLIST_SPARSELUN}, /* Dell PV 530F */
|
||||
|
|
|
@ -75,7 +75,7 @@ int scsi_eh_scmd_add(struct scsi_cmnd *scmd, int eh_flag)
|
|||
|
||||
scmd->eh_eflags |= eh_flag;
|
||||
list_add_tail(&scmd->eh_entry, &shost->eh_cmd_q);
|
||||
set_bit(SHOST_RECOVERY, &shost->shost_state);
|
||||
scsi_host_set_state(shost, SHOST_RECOVERY);
|
||||
shost->host_failed++;
|
||||
scsi_eh_wakeup(shost);
|
||||
spin_unlock_irqrestore(shost->host_lock, flags);
|
||||
|
@ -197,7 +197,8 @@ int scsi_block_when_processing_errors(struct scsi_device *sdev)
|
|||
{
|
||||
int online;
|
||||
|
||||
wait_event(sdev->host->host_wait, (!test_bit(SHOST_RECOVERY, &sdev->host->shost_state)));
|
||||
wait_event(sdev->host->host_wait, (sdev->host->shost_state !=
|
||||
SHOST_RECOVERY));
|
||||
|
||||
online = scsi_device_online(sdev);
|
||||
|
||||
|
@ -1458,7 +1459,7 @@ static void scsi_restart_operations(struct Scsi_Host *shost)
|
|||
SCSI_LOG_ERROR_RECOVERY(3, printk("%s: waking up host to restart\n",
|
||||
__FUNCTION__));
|
||||
|
||||
clear_bit(SHOST_RECOVERY, &shost->shost_state);
|
||||
scsi_host_set_state(shost, SHOST_RUNNING);
|
||||
|
||||
wake_up(&shost->host_wait);
|
||||
|
||||
|
|
|
@ -475,8 +475,7 @@ int scsi_nonblockable_ioctl(struct scsi_device *sdev, int cmd,
|
|||
* error processing, as long as the device was opened
|
||||
* non-blocking */
|
||||
if (filp && filp->f_flags & O_NONBLOCK) {
|
||||
if (test_bit(SHOST_RECOVERY,
|
||||
&sdev->host->shost_state))
|
||||
if (sdev->host->shost_state == SHOST_RECOVERY)
|
||||
return -ENODEV;
|
||||
} else if (!scsi_block_when_processing_errors(sdev))
|
||||
return -ENODEV;
|
||||
|
|
|
@ -400,7 +400,7 @@ void scsi_device_unbusy(struct scsi_device *sdev)
|
|||
|
||||
spin_lock_irqsave(shost->host_lock, flags);
|
||||
shost->host_busy--;
|
||||
if (unlikely(test_bit(SHOST_RECOVERY, &shost->shost_state) &&
|
||||
if (unlikely((shost->shost_state == SHOST_RECOVERY) &&
|
||||
shost->host_failed))
|
||||
scsi_eh_wakeup(shost);
|
||||
spin_unlock(shost->host_lock);
|
||||
|
@ -1281,7 +1281,7 @@ static inline int scsi_host_queue_ready(struct request_queue *q,
|
|||
struct Scsi_Host *shost,
|
||||
struct scsi_device *sdev)
|
||||
{
|
||||
if (test_bit(SHOST_RECOVERY, &shost->shost_state))
|
||||
if (shost->shost_state == SHOST_RECOVERY)
|
||||
return 0;
|
||||
if (shost->host_busy == 0 && shost->host_blocked) {
|
||||
/*
|
||||
|
|
|
@ -1251,9 +1251,12 @@ struct scsi_device *__scsi_add_device(struct Scsi_Host *shost, uint channel,
|
|||
|
||||
get_device(&starget->dev);
|
||||
down(&shost->scan_mutex);
|
||||
res = scsi_probe_and_add_lun(starget, lun, NULL, &sdev, 1, hostdata);
|
||||
if (scsi_host_scan_allowed(shost)) {
|
||||
res = scsi_probe_and_add_lun(starget, lun, NULL, &sdev, 1,
|
||||
hostdata);
|
||||
if (res != SCSI_SCAN_LUN_PRESENT)
|
||||
sdev = ERR_PTR(-ENODEV);
|
||||
}
|
||||
up(&shost->scan_mutex);
|
||||
scsi_target_reap(starget);
|
||||
put_device(&starget->dev);
|
||||
|
@ -1403,11 +1406,15 @@ int scsi_scan_host_selected(struct Scsi_Host *shost, unsigned int channel,
|
|||
return -EINVAL;
|
||||
|
||||
down(&shost->scan_mutex);
|
||||
if (scsi_host_scan_allowed(shost)) {
|
||||
if (channel == SCAN_WILD_CARD)
|
||||
for (channel = 0; channel <= shost->max_channel; channel++)
|
||||
scsi_scan_channel(shost, channel, id, lun, rescan);
|
||||
for (channel = 0; channel <= shost->max_channel;
|
||||
channel++)
|
||||
scsi_scan_channel(shost, channel, id, lun,
|
||||
rescan);
|
||||
else
|
||||
scsi_scan_channel(shost, channel, id, lun, rescan);
|
||||
}
|
||||
up(&shost->scan_mutex);
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -48,6 +48,30 @@ const char *scsi_device_state_name(enum scsi_device_state state)
|
|||
return name;
|
||||
}
|
||||
|
||||
static struct {
|
||||
enum scsi_host_state value;
|
||||
char *name;
|
||||
} shost_states[] = {
|
||||
{ SHOST_CREATED, "created" },
|
||||
{ SHOST_RUNNING, "running" },
|
||||
{ SHOST_CANCEL, "cancel" },
|
||||
{ SHOST_DEL, "deleted" },
|
||||
{ SHOST_RECOVERY, "recovery" },
|
||||
};
|
||||
const char *scsi_host_state_name(enum scsi_host_state state)
|
||||
{
|
||||
int i;
|
||||
char *name = NULL;
|
||||
|
||||
for (i = 0; i < sizeof(shost_states)/sizeof(shost_states[0]); i++) {
|
||||
if (shost_states[i].value == state) {
|
||||
name = shost_states[i].name;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
static int check_set(unsigned int *val, char *src)
|
||||
{
|
||||
char *last;
|
||||
|
@ -124,6 +148,43 @@ static ssize_t store_scan(struct class_device *class_dev, const char *buf,
|
|||
};
|
||||
static CLASS_DEVICE_ATTR(scan, S_IWUSR, NULL, store_scan);
|
||||
|
||||
static ssize_t
|
||||
store_shost_state(struct class_device *class_dev, const char *buf, size_t count)
|
||||
{
|
||||
int i;
|
||||
struct Scsi_Host *shost = class_to_shost(class_dev);
|
||||
enum scsi_host_state state = 0;
|
||||
|
||||
for (i = 0; i < sizeof(shost_states)/sizeof(shost_states[0]); i++) {
|
||||
const int len = strlen(shost_states[i].name);
|
||||
if (strncmp(shost_states[i].name, buf, len) == 0 &&
|
||||
buf[len] == '\n') {
|
||||
state = shost_states[i].value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!state)
|
||||
return -EINVAL;
|
||||
|
||||
if (scsi_host_set_state(shost, state))
|
||||
return -EINVAL;
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
show_shost_state(struct class_device *class_dev, char *buf)
|
||||
{
|
||||
struct Scsi_Host *shost = class_to_shost(class_dev);
|
||||
const char *name = scsi_host_state_name(shost->shost_state);
|
||||
|
||||
if (!name)
|
||||
return -EINVAL;
|
||||
|
||||
return snprintf(buf, 20, "%s\n", name);
|
||||
}
|
||||
|
||||
static CLASS_DEVICE_ATTR(state, S_IRUGO | S_IWUSR, show_shost_state, store_shost_state);
|
||||
|
||||
shost_rd_attr(unique_id, "%u\n");
|
||||
shost_rd_attr(host_busy, "%hu\n");
|
||||
shost_rd_attr(cmd_per_lun, "%hd\n");
|
||||
|
@ -139,6 +200,7 @@ static struct class_device_attribute *scsi_sysfs_shost_attrs[] = {
|
|||
&class_device_attr_unchecked_isa_dma,
|
||||
&class_device_attr_proc_name,
|
||||
&class_device_attr_scan,
|
||||
&class_device_attr_state,
|
||||
NULL
|
||||
};
|
||||
|
||||
|
|
|
@ -252,7 +252,8 @@ struct fc_internal {
|
|||
|
||||
#define to_fc_internal(tmpl) container_of(tmpl, struct fc_internal, t)
|
||||
|
||||
static int fc_target_setup(struct device *dev)
|
||||
static int fc_target_setup(struct transport_container *tc, struct device *dev,
|
||||
struct class_device *cdev)
|
||||
{
|
||||
struct scsi_target *starget = to_scsi_target(dev);
|
||||
struct fc_rport *rport = starget_to_rport(starget);
|
||||
|
@ -281,7 +282,8 @@ static DECLARE_TRANSPORT_CLASS(fc_transport_class,
|
|||
NULL,
|
||||
NULL);
|
||||
|
||||
static int fc_host_setup(struct device *dev)
|
||||
static int fc_host_setup(struct transport_container *tc, struct device *dev,
|
||||
struct class_device *cdev)
|
||||
{
|
||||
struct Scsi_Host *shost = dev_to_shost(dev);
|
||||
|
||||
|
|
|
@ -35,7 +35,7 @@
|
|||
|
||||
#define SPI_PRINTK(x, l, f, a...) dev_printk(l, &(x)->dev, f , ##a)
|
||||
|
||||
#define SPI_NUM_ATTRS 13 /* increase this if you add attributes */
|
||||
#define SPI_NUM_ATTRS 14 /* increase this if you add attributes */
|
||||
#define SPI_OTHER_ATTRS 1 /* Increase this if you add "always
|
||||
* on" attributes */
|
||||
#define SPI_HOST_ATTRS 1
|
||||
|
@ -162,7 +162,8 @@ static inline enum spi_signal_type spi_signal_to_value(const char *name)
|
|||
return SPI_SIGNAL_UNKNOWN;
|
||||
}
|
||||
|
||||
static int spi_host_setup(struct device *dev)
|
||||
static int spi_host_setup(struct transport_container *tc, struct device *dev,
|
||||
struct class_device *cdev)
|
||||
{
|
||||
struct Scsi_Host *shost = dev_to_shost(dev);
|
||||
|
||||
|
@ -196,7 +197,9 @@ static int spi_host_match(struct attribute_container *cont,
|
|||
return &i->t.host_attrs.ac == cont;
|
||||
}
|
||||
|
||||
static int spi_device_configure(struct device *dev)
|
||||
static int spi_device_configure(struct transport_container *tc,
|
||||
struct device *dev,
|
||||
struct class_device *cdev)
|
||||
{
|
||||
struct scsi_device *sdev = to_scsi_device(dev);
|
||||
struct scsi_target *starget = sdev->sdev_target;
|
||||
|
@ -214,7 +217,9 @@ static int spi_device_configure(struct device *dev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int spi_setup_transport_attrs(struct device *dev)
|
||||
static int spi_setup_transport_attrs(struct transport_container *tc,
|
||||
struct device *dev,
|
||||
struct class_device *cdev)
|
||||
{
|
||||
struct scsi_target *starget = to_scsi_target(dev);
|
||||
|
||||
|
@ -231,6 +236,7 @@ static int spi_setup_transport_attrs(struct device *dev)
|
|||
spi_rd_strm(starget) = 0;
|
||||
spi_rti(starget) = 0;
|
||||
spi_pcomp_en(starget) = 0;
|
||||
spi_hold_mcs(starget) = 0;
|
||||
spi_dv_pending(starget) = 0;
|
||||
spi_initial_dv(starget) = 0;
|
||||
init_MUTEX(&spi_dv_sem(starget));
|
||||
|
@ -347,6 +353,7 @@ spi_transport_rd_attr(wr_flow, "%d\n");
|
|||
spi_transport_rd_attr(rd_strm, "%d\n");
|
||||
spi_transport_rd_attr(rti, "%d\n");
|
||||
spi_transport_rd_attr(pcomp_en, "%d\n");
|
||||
spi_transport_rd_attr(hold_mcs, "%d\n");
|
||||
|
||||
/* we only care about the first child device so we return 1 */
|
||||
static int child_iter(struct device *dev, void *data)
|
||||
|
@ -1028,10 +1035,17 @@ void spi_display_xfer_agreement(struct scsi_target *starget)
|
|||
sprint_frac(tmp, picosec, 1000);
|
||||
|
||||
dev_info(&starget->dev,
|
||||
"%s %sSCSI %d.%d MB/s %s%s%s (%s ns, offset %d)\n",
|
||||
"%s %sSCSI %d.%d MB/s %s%s%s%s%s%s%s%s (%s ns, offset %d)\n",
|
||||
scsi, tp->width ? "WIDE " : "", kb100/10, kb100 % 10,
|
||||
tp->dt ? "DT" : "ST", tp->iu ? " IU" : "",
|
||||
tp->qas ? " QAS" : "", tmp, tp->offset);
|
||||
tp->dt ? "DT" : "ST",
|
||||
tp->iu ? " IU" : "",
|
||||
tp->qas ? " QAS" : "",
|
||||
tp->rd_strm ? " RDSTRM" : "",
|
||||
tp->rti ? " RTI" : "",
|
||||
tp->wr_flow ? " WRFLOW" : "",
|
||||
tp->pcomp_en ? " PCOMP" : "",
|
||||
tp->hold_mcs ? " HMCS" : "",
|
||||
tmp, tp->offset);
|
||||
} else {
|
||||
dev_info(&starget->dev, "%sasynchronous.\n",
|
||||
tp->width ? "wide " : "");
|
||||
|
@ -1073,6 +1087,7 @@ static int spi_device_match(struct attribute_container *cont,
|
|||
{
|
||||
struct scsi_device *sdev;
|
||||
struct Scsi_Host *shost;
|
||||
struct spi_internal *i;
|
||||
|
||||
if (!scsi_is_sdev_device(dev))
|
||||
return 0;
|
||||
|
@ -1085,6 +1100,9 @@ static int spi_device_match(struct attribute_container *cont,
|
|||
/* Note: this class has no device attributes, so it has
|
||||
* no per-HBA allocation and thus we don't need to distinguish
|
||||
* the attribute containers for the device */
|
||||
i = to_spi_internal(shost->transportt);
|
||||
if (i->f->deny_binding && i->f->deny_binding(sdev->sdev_target))
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -1092,6 +1110,7 @@ static int spi_target_match(struct attribute_container *cont,
|
|||
struct device *dev)
|
||||
{
|
||||
struct Scsi_Host *shost;
|
||||
struct scsi_target *starget;
|
||||
struct spi_internal *i;
|
||||
|
||||
if (!scsi_is_target_device(dev))
|
||||
|
@ -1103,6 +1122,10 @@ static int spi_target_match(struct attribute_container *cont,
|
|||
return 0;
|
||||
|
||||
i = to_spi_internal(shost->transportt);
|
||||
starget = to_scsi_target(dev);
|
||||
|
||||
if (i->f->deny_binding && i->f->deny_binding(starget))
|
||||
return 0;
|
||||
|
||||
return &i->t.target_attrs.ac == cont;
|
||||
}
|
||||
|
@ -1154,6 +1177,7 @@ spi_attach_transport(struct spi_function_template *ft)
|
|||
SETUP_ATTRIBUTE(rd_strm);
|
||||
SETUP_ATTRIBUTE(rti);
|
||||
SETUP_ATTRIBUTE(pcomp_en);
|
||||
SETUP_ATTRIBUTE(hold_mcs);
|
||||
|
||||
/* if you add an attribute but forget to increase SPI_NUM_ATTRS
|
||||
* this bug will trigger */
|
||||
|
|
|
@ -1027,8 +1027,7 @@ sg_ioctl(struct inode *inode, struct file *filp,
|
|||
if (sdp->detached)
|
||||
return -ENODEV;
|
||||
if (filp->f_flags & O_NONBLOCK) {
|
||||
if (test_bit(SHOST_RECOVERY,
|
||||
&sdp->device->host->shost_state))
|
||||
if (sdp->device->host->shost_state == SHOST_RECOVERY)
|
||||
return -EBUSY;
|
||||
} else if (!scsi_block_when_processing_errors(sdp->device))
|
||||
return -EBUSY;
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
Last modified: 18-JAN-1998 Richard Gooch <rgooch@atnf.csiro.au> Devfs support
|
||||
*/
|
||||
|
||||
static char *verstr = "20050501";
|
||||
static char *verstr = "20050802";
|
||||
|
||||
#include <linux/module.h>
|
||||
|
||||
|
@ -219,6 +219,12 @@ static int switch_partition(struct scsi_tape *);
|
|||
|
||||
static int st_int_ioctl(struct scsi_tape *, unsigned int, unsigned long);
|
||||
|
||||
static void scsi_tape_release(struct kref *);
|
||||
|
||||
#define to_scsi_tape(obj) container_of(obj, struct scsi_tape, kref)
|
||||
|
||||
static DECLARE_MUTEX(st_ref_sem);
|
||||
|
||||
|
||||
#include "osst_detect.h"
|
||||
#ifndef SIGS_FROM_OSST
|
||||
|
@ -230,6 +236,46 @@ static int st_int_ioctl(struct scsi_tape *, unsigned int, unsigned long);
|
|||
{"OnStream", "FW-", "", "osst"}
|
||||
#endif
|
||||
|
||||
static struct scsi_tape *scsi_tape_get(int dev)
|
||||
{
|
||||
struct scsi_tape *STp = NULL;
|
||||
|
||||
down(&st_ref_sem);
|
||||
write_lock(&st_dev_arr_lock);
|
||||
|
||||
if (dev < st_dev_max && scsi_tapes != NULL)
|
||||
STp = scsi_tapes[dev];
|
||||
if (!STp) goto out;
|
||||
|
||||
kref_get(&STp->kref);
|
||||
|
||||
if (!STp->device)
|
||||
goto out_put;
|
||||
|
||||
if (scsi_device_get(STp->device))
|
||||
goto out_put;
|
||||
|
||||
goto out;
|
||||
|
||||
out_put:
|
||||
kref_put(&STp->kref, scsi_tape_release);
|
||||
STp = NULL;
|
||||
out:
|
||||
write_unlock(&st_dev_arr_lock);
|
||||
up(&st_ref_sem);
|
||||
return STp;
|
||||
}
|
||||
|
||||
static void scsi_tape_put(struct scsi_tape *STp)
|
||||
{
|
||||
struct scsi_device *sdev = STp->device;
|
||||
|
||||
down(&st_ref_sem);
|
||||
kref_put(&STp->kref, scsi_tape_release);
|
||||
scsi_device_put(sdev);
|
||||
up(&st_ref_sem);
|
||||
}
|
||||
|
||||
struct st_reject_data {
|
||||
char *vendor;
|
||||
char *model;
|
||||
|
@ -311,7 +357,7 @@ static int st_chk_result(struct scsi_tape *STp, struct scsi_request * SRpnt)
|
|||
return 0;
|
||||
|
||||
cmdstatp = &STp->buffer->cmdstat;
|
||||
st_analyze_sense(STp->buffer->last_SRpnt, cmdstatp);
|
||||
st_analyze_sense(SRpnt, cmdstatp);
|
||||
|
||||
if (cmdstatp->have_sense)
|
||||
scode = STp->buffer->cmdstat.sense_hdr.sense_key;
|
||||
|
@ -399,9 +445,9 @@ static void st_sleep_done(struct scsi_cmnd * SCpnt)
|
|||
|
||||
(STp->buffer)->cmdstat.midlevel_result = SCpnt->result;
|
||||
SCpnt->request->rq_status = RQ_SCSI_DONE;
|
||||
(STp->buffer)->last_SRpnt = SCpnt->sc_request;
|
||||
DEB( STp->write_pending = 0; )
|
||||
|
||||
if (SCpnt->request->waiting)
|
||||
complete(SCpnt->request->waiting);
|
||||
}
|
||||
|
||||
|
@ -412,8 +458,20 @@ static struct scsi_request *
|
|||
st_do_scsi(struct scsi_request * SRpnt, struct scsi_tape * STp, unsigned char *cmd,
|
||||
int bytes, int direction, int timeout, int retries, int do_wait)
|
||||
{
|
||||
struct completion *waiting;
|
||||
unsigned char *bp;
|
||||
|
||||
/* if async, make sure there's no command outstanding */
|
||||
if (!do_wait && ((STp->buffer)->last_SRpnt)) {
|
||||
printk(KERN_ERR "%s: Async command already active.\n",
|
||||
tape_name(STp));
|
||||
if (signal_pending(current))
|
||||
(STp->buffer)->syscall_result = (-EINTR);
|
||||
else
|
||||
(STp->buffer)->syscall_result = (-EBUSY);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (SRpnt == NULL) {
|
||||
SRpnt = scsi_allocate_request(STp->device, GFP_ATOMIC);
|
||||
if (SRpnt == NULL) {
|
||||
|
@ -427,7 +485,13 @@ st_do_scsi(struct scsi_request * SRpnt, struct scsi_tape * STp, unsigned char *c
|
|||
}
|
||||
}
|
||||
|
||||
init_completion(&STp->wait);
|
||||
/* If async IO, set last_SRpnt. This ptr tells write_behind_check
|
||||
which IO is outstanding. It's nulled out when the IO completes. */
|
||||
if (!do_wait)
|
||||
(STp->buffer)->last_SRpnt = SRpnt;
|
||||
|
||||
waiting = &STp->wait;
|
||||
init_completion(waiting);
|
||||
SRpnt->sr_use_sg = STp->buffer->do_dio || (bytes > (STp->buffer)->frp[0].length);
|
||||
if (SRpnt->sr_use_sg) {
|
||||
if (!STp->buffer->do_dio)
|
||||
|
@ -438,17 +502,20 @@ st_do_scsi(struct scsi_request * SRpnt, struct scsi_tape * STp, unsigned char *c
|
|||
bp = (STp->buffer)->b_data;
|
||||
SRpnt->sr_data_direction = direction;
|
||||
SRpnt->sr_cmd_len = 0;
|
||||
SRpnt->sr_request->waiting = &(STp->wait);
|
||||
SRpnt->sr_request->waiting = waiting;
|
||||
SRpnt->sr_request->rq_status = RQ_SCSI_BUSY;
|
||||
SRpnt->sr_request->rq_disk = STp->disk;
|
||||
SRpnt->sr_request->end_io = blk_end_sync_rq;
|
||||
STp->buffer->cmdstat.have_sense = 0;
|
||||
|
||||
scsi_do_req(SRpnt, (void *) cmd, bp, bytes,
|
||||
st_sleep_done, timeout, retries);
|
||||
|
||||
if (do_wait) {
|
||||
wait_for_completion(SRpnt->sr_request->waiting);
|
||||
wait_for_completion(waiting);
|
||||
SRpnt->sr_request->waiting = NULL;
|
||||
if (SRpnt->sr_request->rq_status != RQ_SCSI_DONE)
|
||||
SRpnt->sr_result |= (DRIVER_ERROR << 24);
|
||||
(STp->buffer)->syscall_result = st_chk_result(STp, SRpnt);
|
||||
}
|
||||
return SRpnt;
|
||||
|
@ -465,6 +532,7 @@ static int write_behind_check(struct scsi_tape * STp)
|
|||
struct st_buffer *STbuffer;
|
||||
struct st_partstat *STps;
|
||||
struct st_cmdstatus *cmdstatp;
|
||||
struct scsi_request *SRpnt;
|
||||
|
||||
STbuffer = STp->buffer;
|
||||
if (!STbuffer->writing)
|
||||
|
@ -478,10 +546,14 @@ static int write_behind_check(struct scsi_tape * STp)
|
|||
) /* end DEB */
|
||||
|
||||
wait_for_completion(&(STp->wait));
|
||||
(STp->buffer)->last_SRpnt->sr_request->waiting = NULL;
|
||||
SRpnt = STbuffer->last_SRpnt;
|
||||
STbuffer->last_SRpnt = NULL;
|
||||
SRpnt->sr_request->waiting = NULL;
|
||||
if (SRpnt->sr_request->rq_status != RQ_SCSI_DONE)
|
||||
SRpnt->sr_result |= (DRIVER_ERROR << 24);
|
||||
|
||||
(STp->buffer)->syscall_result = st_chk_result(STp, (STp->buffer)->last_SRpnt);
|
||||
scsi_release_request((STp->buffer)->last_SRpnt);
|
||||
(STp->buffer)->syscall_result = st_chk_result(STp, SRpnt);
|
||||
scsi_release_request(SRpnt);
|
||||
|
||||
STbuffer->buffer_bytes -= STbuffer->writing;
|
||||
STps = &(STp->ps[STp->partition]);
|
||||
|
@ -1055,25 +1127,20 @@ static int st_open(struct inode *inode, struct file *filp)
|
|||
*/
|
||||
filp->f_mode &= ~(FMODE_PREAD | FMODE_PWRITE);
|
||||
|
||||
if (!(STp = scsi_tape_get(dev)))
|
||||
return -ENXIO;
|
||||
|
||||
write_lock(&st_dev_arr_lock);
|
||||
if (dev >= st_dev_max || scsi_tapes == NULL ||
|
||||
((STp = scsi_tapes[dev]) == NULL)) {
|
||||
write_unlock(&st_dev_arr_lock);
|
||||
return (-ENXIO);
|
||||
}
|
||||
filp->private_data = STp;
|
||||
name = tape_name(STp);
|
||||
|
||||
if (STp->in_use) {
|
||||
write_unlock(&st_dev_arr_lock);
|
||||
scsi_tape_put(STp);
|
||||
DEB( printk(ST_DEB_MSG "%s: Device already in use.\n", name); )
|
||||
return (-EBUSY);
|
||||
}
|
||||
|
||||
if(scsi_device_get(STp->device)) {
|
||||
write_unlock(&st_dev_arr_lock);
|
||||
return (-ENXIO);
|
||||
}
|
||||
STp->in_use = 1;
|
||||
write_unlock(&st_dev_arr_lock);
|
||||
STp->rew_at_close = STp->autorew_dev = (iminor(inode) & 0x80) == 0;
|
||||
|
@ -1118,7 +1185,7 @@ static int st_open(struct inode *inode, struct file *filp)
|
|||
err_out:
|
||||
normalize_buffer(STp->buffer);
|
||||
STp->in_use = 0;
|
||||
scsi_device_put(STp->device);
|
||||
scsi_tape_put(STp);
|
||||
return retval;
|
||||
|
||||
}
|
||||
|
@ -1250,7 +1317,7 @@ static int st_release(struct inode *inode, struct file *filp)
|
|||
write_lock(&st_dev_arr_lock);
|
||||
STp->in_use = 0;
|
||||
write_unlock(&st_dev_arr_lock);
|
||||
scsi_device_put(STp->device);
|
||||
scsi_tape_put(STp);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
@ -3887,6 +3954,7 @@ static int st_probe(struct device *dev)
|
|||
goto out_put_disk;
|
||||
}
|
||||
memset(tpnt, 0, sizeof(struct scsi_tape));
|
||||
kref_init(&tpnt->kref);
|
||||
tpnt->disk = disk;
|
||||
sprintf(disk->disk_name, "st%d", i);
|
||||
disk->private_data = &tpnt->driver;
|
||||
|
@ -3902,6 +3970,7 @@ static int st_probe(struct device *dev)
|
|||
tpnt->tape_type = MT_ISSCSI2;
|
||||
|
||||
tpnt->buffer = buffer;
|
||||
tpnt->buffer->last_SRpnt = NULL;
|
||||
|
||||
tpnt->inited = 0;
|
||||
tpnt->dirty = 0;
|
||||
|
@ -4076,6 +4145,32 @@ static int st_remove(struct device *dev)
|
|||
tpnt->modes[mode].cdevs[j] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
down(&st_ref_sem);
|
||||
kref_put(&tpnt->kref, scsi_tape_release);
|
||||
up(&st_ref_sem);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
write_unlock(&st_dev_arr_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* scsi_tape_release - Called to free the Scsi_Tape structure
|
||||
* @kref: pointer to embedded kref
|
||||
*
|
||||
* st_ref_sem must be held entering this routine. Because it is
|
||||
* called on last put, you should always use the scsi_tape_get()
|
||||
* scsi_tape_put() helpers which manipulate the semaphore directly
|
||||
* and never do a direct kref_put().
|
||||
**/
|
||||
static void scsi_tape_release(struct kref *kref)
|
||||
{
|
||||
struct scsi_tape *tpnt = to_scsi_tape(kref);
|
||||
struct gendisk *disk = tpnt->disk;
|
||||
|
||||
tpnt->device = NULL;
|
||||
|
||||
if (tpnt->buffer) {
|
||||
|
@ -4083,14 +4178,11 @@ static int st_remove(struct device *dev)
|
|||
normalize_buffer(tpnt->buffer);
|
||||
kfree(tpnt->buffer);
|
||||
}
|
||||
put_disk(tpnt->disk);
|
||||
kfree(tpnt);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
write_unlock(&st_dev_arr_lock);
|
||||
return 0;
|
||||
disk->private_data = NULL;
|
||||
put_disk(disk);
|
||||
kfree(tpnt);
|
||||
return;
|
||||
}
|
||||
|
||||
static void st_intr(struct scsi_cmnd *SCpnt)
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
#define _ST_H
|
||||
|
||||
#include <linux/completion.h>
|
||||
|
||||
#include <linux/kref.h>
|
||||
|
||||
/* Descriptor for analyzed sense data */
|
||||
struct st_cmdstatus {
|
||||
|
@ -156,6 +156,7 @@ struct scsi_tape {
|
|||
unsigned char last_sense[16];
|
||||
#endif
|
||||
struct gendisk *disk;
|
||||
struct kref kref;
|
||||
};
|
||||
|
||||
/* Bit masks for use_pf */
|
||||
|
|
|
@ -11,10 +11,12 @@
|
|||
|
||||
#include <linux/device.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/spinlock.h>
|
||||
|
||||
struct attribute_container {
|
||||
struct list_head node;
|
||||
struct list_head containers;
|
||||
spinlock_t containers_lock;
|
||||
struct class *class;
|
||||
struct class_device_attribute **attrs;
|
||||
int (*match)(struct attribute_container *, struct device *);
|
||||
|
@ -62,12 +64,8 @@ int attribute_container_add_class_device_adapter(struct attribute_container *con
|
|||
struct class_device *classdev);
|
||||
void attribute_container_remove_attrs(struct class_device *classdev);
|
||||
void attribute_container_class_device_del(struct class_device *classdev);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
struct attribute_container *attribute_container_classdev_to_container(struct class_device *);
|
||||
struct class_device *attribute_container_find_class_device(struct attribute_container *, struct device *);
|
||||
struct class_device_attribute **attribute_container_classdev_to_attrs(const struct class_device *classdev);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -12,11 +12,16 @@
|
|||
#include <linux/device.h>
|
||||
#include <linux/attribute_container.h>
|
||||
|
||||
struct transport_container;
|
||||
|
||||
struct transport_class {
|
||||
struct class class;
|
||||
int (*setup)(struct device *);
|
||||
int (*configure)(struct device *);
|
||||
int (*remove)(struct device *);
|
||||
int (*setup)(struct transport_container *, struct device *,
|
||||
struct class_device *);
|
||||
int (*configure)(struct transport_container *, struct device *,
|
||||
struct class_device *);
|
||||
int (*remove)(struct transport_container *, struct device *,
|
||||
struct class_device *);
|
||||
};
|
||||
|
||||
#define DECLARE_TRANSPORT_CLASS(cls, nm, su, rm, cfg) \
|
||||
|
|
|
@ -51,12 +51,16 @@ struct scsi_cmnd {
|
|||
* printk's to use ->pid, so that we can kill this field.
|
||||
*/
|
||||
unsigned long serial_number;
|
||||
/*
|
||||
* This is set to jiffies as it was when the command was first
|
||||
* allocated. It is used to time how long the command has
|
||||
* been outstanding
|
||||
*/
|
||||
unsigned long jiffies_at_alloc;
|
||||
|
||||
int retries;
|
||||
int allowed;
|
||||
int timeout_per_command;
|
||||
int timeout_total;
|
||||
int timeout;
|
||||
|
||||
unsigned char cmd_len;
|
||||
unsigned char old_cmd_len;
|
||||
|
|
|
@ -429,12 +429,15 @@ struct scsi_host_template {
|
|||
};
|
||||
|
||||
/*
|
||||
* shost states
|
||||
* shost state: If you alter this, you also need to alter scsi_sysfs.c
|
||||
* (for the ascii descriptions) and the state model enforcer:
|
||||
* scsi_host_set_state()
|
||||
*/
|
||||
enum {
|
||||
SHOST_ADD,
|
||||
SHOST_DEL,
|
||||
enum scsi_host_state {
|
||||
SHOST_CREATED = 1,
|
||||
SHOST_RUNNING,
|
||||
SHOST_CANCEL,
|
||||
SHOST_DEL,
|
||||
SHOST_RECOVERY,
|
||||
};
|
||||
|
||||
|
@ -575,7 +578,7 @@ struct Scsi_Host {
|
|||
unsigned int irq;
|
||||
|
||||
|
||||
unsigned long shost_state;
|
||||
enum scsi_host_state shost_state;
|
||||
|
||||
/* ldm bits */
|
||||
struct device shost_gendev;
|
||||
|
@ -633,6 +636,7 @@ extern void scsi_remove_host(struct Scsi_Host *);
|
|||
extern struct Scsi_Host *scsi_host_get(struct Scsi_Host *);
|
||||
extern void scsi_host_put(struct Scsi_Host *t);
|
||||
extern struct Scsi_Host *scsi_host_lookup(unsigned short);
|
||||
extern const char *scsi_host_state_name(enum scsi_host_state);
|
||||
|
||||
extern u64 scsi_calculate_bounce_limit(struct Scsi_Host *);
|
||||
|
||||
|
@ -646,6 +650,15 @@ static inline struct device *scsi_get_device(struct Scsi_Host *shost)
|
|||
return shost->shost_gendev.parent;
|
||||
}
|
||||
|
||||
/**
|
||||
* scsi_host_scan_allowed - Is scanning of this host allowed
|
||||
* @shost: Pointer to Scsi_Host.
|
||||
**/
|
||||
static inline int scsi_host_scan_allowed(struct Scsi_Host *shost)
|
||||
{
|
||||
return shost->shost_state == SHOST_RUNNING;
|
||||
}
|
||||
|
||||
extern void scsi_unblock_requests(struct Scsi_Host *);
|
||||
extern void scsi_block_requests(struct Scsi_Host *);
|
||||
|
||||
|
@ -663,5 +676,6 @@ extern struct scsi_device *scsi_get_host_dev(struct Scsi_Host *);
|
|||
/* legacy interfaces */
|
||||
extern struct Scsi_Host *scsi_register(struct scsi_host_template *, int);
|
||||
extern void scsi_unregister(struct Scsi_Host *);
|
||||
extern int scsi_host_set_state(struct Scsi_Host *, enum scsi_host_state);
|
||||
|
||||
#endif /* _SCSI_SCSI_HOST_H */
|
||||
|
|
|
@ -39,6 +39,7 @@ struct spi_transport_attrs {
|
|||
unsigned int rd_strm:1; /* Read streaming enabled */
|
||||
unsigned int rti:1; /* Retain Training Information */
|
||||
unsigned int pcomp_en:1;/* Precompensation enabled */
|
||||
unsigned int hold_mcs:1;/* Hold Margin Control Settings */
|
||||
unsigned int initial_dv:1; /* DV done to this target yet */
|
||||
unsigned long flags; /* flags field for drivers to use */
|
||||
/* Device Properties fields */
|
||||
|
@ -78,6 +79,7 @@ struct spi_host_attrs {
|
|||
#define spi_rd_strm(x) (((struct spi_transport_attrs *)&(x)->starget_data)->rd_strm)
|
||||
#define spi_rti(x) (((struct spi_transport_attrs *)&(x)->starget_data)->rti)
|
||||
#define spi_pcomp_en(x) (((struct spi_transport_attrs *)&(x)->starget_data)->pcomp_en)
|
||||
#define spi_hold_mcs(x) (((struct spi_transport_attrs *)&(x)->starget_data)->hold_mcs)
|
||||
#define spi_initial_dv(x) (((struct spi_transport_attrs *)&(x)->starget_data)->initial_dv)
|
||||
|
||||
#define spi_support_sync(x) (((struct spi_transport_attrs *)&(x)->starget_data)->support_sync)
|
||||
|
@ -114,8 +116,11 @@ struct spi_function_template {
|
|||
void (*set_rti)(struct scsi_target *, int);
|
||||
void (*get_pcomp_en)(struct scsi_target *);
|
||||
void (*set_pcomp_en)(struct scsi_target *, int);
|
||||
void (*get_hold_mcs)(struct scsi_target *);
|
||||
void (*set_hold_mcs)(struct scsi_target *, int);
|
||||
void (*get_signalling)(struct Scsi_Host *);
|
||||
void (*set_signalling)(struct Scsi_Host *, enum spi_signal_type);
|
||||
int (*deny_binding)(struct scsi_target *);
|
||||
/* The driver sets these to tell the transport class it
|
||||
* wants the attributes displayed in sysfs. If the show_ flag
|
||||
* is not set, the attribute will be private to the transport
|
||||
|
@ -130,6 +135,7 @@ struct spi_function_template {
|
|||
unsigned long show_rd_strm:1;
|
||||
unsigned long show_rti:1;
|
||||
unsigned long show_pcomp_en:1;
|
||||
unsigned long show_hold_mcs:1;
|
||||
};
|
||||
|
||||
struct scsi_transport_template *spi_attach_transport(struct spi_function_template *);
|
||||
|
|
Loading…
Reference in a new issue