/* 6.10.00 - Remove 1G Addressing Limitations */
/* 6.11.xx - Get VersionInfo buffer off the stack ! DDTS 60401 */
/* 6.11.xx - Make Logical Drive Info structure safe for DMA DDTS 60639 */
-/* 7.10.xx - Add highmem_io flag in SCSI Templete for 2.4 kernels */
+/* 7.10.18 - Add highmem_io flag in SCSI Templete for 2.4 kernels */
/* - Fix path/name for scsi_hosts.h include for 2.6 kernels */
/* - Fix sort order of 7k */
/* - Remove 3 unused "inline" functions */
+/* 7.12.xx - Use STATIC functions whereever possible */
+/* - Clean up deprecated MODULE_PARM calls */
+/* 7.12.05 - Remove Version Matching per IBM request */
/*****************************************************************************/
/*
#include <asm/byteorder.h>
#include <asm/page.h>
#include <linux/stddef.h>
-#include <linux/version.h>
#include <linux/string.h>
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/blkdev.h>
#include <linux/types.h>
+#include <linux/dma-mapping.h>
#include <scsi/sg.h>
-
#include "scsi.h"
-
-#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,0)
-#include "hosts.h"
-#else
#include <scsi/scsi_host.h>
-#endif
#include "ips.h"
#include <linux/module.h>
#include <linux/stat.h>
-#include <linux/config.h>
#include <linux/spinlock.h>
#include <linux/init.h>
/*
* DRIVER_VER
*/
-#define IPS_VERSION_HIGH "7.10"
-#define IPS_VERSION_LOW ".18 "
+#define IPS_VERSION_HIGH IPS_VER_MAJOR_STRING "." IPS_VER_MINOR_STRING
+#define IPS_VERSION_LOW "." IPS_VER_BUILD_STRING " "
#if !defined(__i386__) && !defined(__ia64__) && !defined(__x86_64__)
#warning "This driver has only been tested on the x86/ia64/x86_64 platforms"
#endif
-#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,0)
-#include <linux/blk.h>
-#include "sd.h"
-#define IPS_SG_ADDRESS(sg) ((sg)->address)
-#define IPS_LOCK_SAVE(lock,flags) spin_lock_irqsave(&io_request_lock,flags)
-#define IPS_UNLOCK_RESTORE(lock,flags) spin_unlock_irqrestore(&io_request_lock,flags)
-#ifndef __devexit_p
-#define __devexit_p(x) x
-#endif
-#else
-#define IPS_SG_ADDRESS(sg) (page_address((sg)->page) ? \
- page_address((sg)->page)+(sg)->offset : NULL)
-#define IPS_LOCK_SAVE(lock,flags) do{spin_lock(lock);(void)flags;}while(0)
-#define IPS_UNLOCK_RESTORE(lock,flags) do{spin_unlock(lock);(void)flags;}while(0)
-#endif
-
#define IPS_DMA_DIR(scb) ((!scb->scsi_cmd || ips_is_passthru(scb->scsi_cmd) || \
DMA_NONE == scb->scsi_cmd->sc_data_direction) ? \
PCI_DMA_BIDIRECTIONAL : \
/*
* Function prototypes
*/
-static int ips_detect(Scsi_Host_Template *);
+static int ips_detect(struct scsi_host_template *);
static int ips_release(struct Scsi_Host *);
-static int ips_eh_abort(Scsi_Cmnd *);
-static int ips_eh_reset(Scsi_Cmnd *);
-static int ips_queue(Scsi_Cmnd *, void (*)(Scsi_Cmnd *));
+static int ips_eh_abort(struct scsi_cmnd *);
+static int ips_eh_reset(struct scsi_cmnd *);
+static int ips_queue(struct scsi_cmnd *, void (*)(struct scsi_cmnd *));
static const char *ips_info(struct Scsi_Host *);
-static irqreturn_t do_ipsintr(int, void *, struct pt_regs *);
+static irqreturn_t do_ipsintr(int, void *);
static int ips_hainit(ips_ha_t *);
static int ips_map_status(ips_ha_t *, ips_scb_t *, ips_stat_t *);
static int ips_send_wait(ips_ha_t *, ips_scb_t *, int, int);
static uint32_t ips_statupd_morpheus(ips_ha_t *);
static ips_scb_t *ips_getscb(ips_ha_t *);
static void ips_putq_scb_head(ips_scb_queue_t *, ips_scb_t *);
-static void ips_putq_wait_tail(ips_wait_queue_t *, Scsi_Cmnd *);
+static void ips_putq_wait_tail(ips_wait_queue_t *, struct scsi_cmnd *);
static void ips_putq_copp_tail(ips_copp_queue_t *,
ips_copp_wait_item_t *);
static ips_scb_t *ips_removeq_scb_head(ips_scb_queue_t *);
static ips_scb_t *ips_removeq_scb(ips_scb_queue_t *, ips_scb_t *);
-static Scsi_Cmnd *ips_removeq_wait_head(ips_wait_queue_t *);
-static Scsi_Cmnd *ips_removeq_wait(ips_wait_queue_t *, Scsi_Cmnd *);
+static struct scsi_cmnd *ips_removeq_wait_head(ips_wait_queue_t *);
+static struct scsi_cmnd *ips_removeq_wait(ips_wait_queue_t *,
+ struct scsi_cmnd *);
static ips_copp_wait_item_t *ips_removeq_copp(ips_copp_queue_t *,
ips_copp_wait_item_t *);
static ips_copp_wait_item_t *ips_removeq_copp_head(ips_copp_queue_t *);
-static int ips_is_passthru(Scsi_Cmnd *);
-static int ips_make_passthru(ips_ha_t *, Scsi_Cmnd *, ips_scb_t *, int);
+static int ips_is_passthru(struct scsi_cmnd *);
+static int ips_make_passthru(ips_ha_t *, struct scsi_cmnd *, ips_scb_t *, int);
static int ips_usrcmd(ips_ha_t *, ips_passthru_t *, ips_scb_t *);
static void ips_cleanup_passthru(ips_ha_t *, ips_scb_t *);
-static void ips_scmd_buf_write(Scsi_Cmnd * scmd, void *data,
+static void ips_scmd_buf_write(struct scsi_cmnd * scmd, void *data,
unsigned int count);
-static void ips_scmd_buf_read(Scsi_Cmnd * scmd, void *data, unsigned int count);
+static void ips_scmd_buf_read(struct scsi_cmnd * scmd, void *data,
+ unsigned int count);
static int ips_proc_info(struct Scsi_Host *, char *, char **, off_t, int, int);
static int ips_host_info(ips_ha_t *, char *, off_t, int);
static void copy_mem_info(IPS_INFOSTR *, char *, int);
static int copy_info(IPS_INFOSTR *, char *, ...);
-static int ips_get_version_info(ips_ha_t * ha, dma_addr_t, int intr);
-static void ips_version_check(ips_ha_t * ha, int intr);
static int ips_abort_init(ips_ha_t * ha, int index);
static int ips_init_phase2(int index);
static int ips_init_phase1(struct pci_dev *pci_dev, int *indexPtr);
static int ips_register_scsi(int index);
+static int ips_poll_for_flush_complete(ips_ha_t * ha);
+static void ips_flush_and_reset(ips_ha_t *ha);
+
/*
* global variables
*/
static dma_addr_t ips_flashbusaddr;
static long ips_FlashDataInUse; /* CD Boot - Flash Data In Use Flag */
static uint32_t MaxLiteCmds = 32; /* Max Active Cmds for a Lite Adapter */
-static Scsi_Host_Template ips_driver_template = {
+static struct scsi_host_template ips_driver_template = {
.detect = ips_detect,
.release = ips_release,
.info = ips_info,
.eh_abort_handler = ips_eh_abort,
.eh_host_reset_handler = ips_eh_reset,
.proc_name = "ips",
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
.proc_info = ips_proc_info,
.slave_configure = ips_slave_configure,
-#else
- .proc_info = ips_proc24_info,
- .select_queue_depths = ips_select_queue_depth,
-#endif
.bios_param = ips_biosparam,
.this_id = -1,
.sg_tablesize = IPS_MAX_SG,
.cmd_per_lun = 3,
.use_clustering = ENABLE_CLUSTERING,
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
- .use_new_eh_code = 1,
-#endif
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,20) && LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
- .highmem_io = 1,
-#endif
};
-static IPS_DEFINE_COMPAT_TABLE( Compatable ); /* Version Compatability Table */
-
/* This table describes all ServeRAID Adapters */
static struct pci_device_id ips_pci_table[] = {
MODULE_DEVICE_TABLE( pci, ips_pci_table );
static char ips_hot_plug_name[] = "ips";
-
+
static int __devinit ips_insert_device(struct pci_dev *pci_dev, const struct pci_device_id *ent);
static void __devexit ips_remove_device(struct pci_dev *pci_dev);
-
+
static struct pci_driver ips_pci_driver = {
.name = ips_hot_plug_name,
.id_table = ips_pci_table,
.probe = ips_insert_device,
.remove = __devexit_p(ips_remove_device),
};
-
+
/*
* Necessary forward function protoypes
* We now have key/value pairs.
* Update the variables
*/
- for (i = 0; i < (sizeof (options) / sizeof (options[0])); i++) {
+ for (i = 0; i < ARRAY_SIZE(options); i++) {
if (strnicmp
(key, options[i].option_name,
strlen(options[i].option_name)) == 0) {
/* */
/****************************************************************************/
static int
-ips_detect(Scsi_Host_Template * SHT)
+ips_detect(struct scsi_host_template * SHT)
{
int i;
ips_setup_funclist(ips_ha_t * ha)
{
- /*
+ /*
* Setup Functions
*/
if (IPS_IS_MORPHEUS(ha) || IPS_IS_MARCO(ha)) {
METHOD_TRACE("ips_release", 1);
+ scsi_remove_host(sh);
+
for (i = 0; i < IPS_MAX_ADAPTERS && ips_sh[i] != sh; i++) ;
if (i == IPS_MAX_ADAPTERS) {
/* free extra memory */
ips_free(ha);
- /* Free I/O Region */
- if (ha->io_addr)
- release_region(ha->io_addr, ha->io_len);
-
/* free IRQ */
- free_irq(ha->irq, ha);
+ free_irq(ha->pcidev->irq, ha);
- IPS_REMOVE_HOST(sh);
scsi_host_put(sh);
ips_released_controllers++;
/* Abort a command (using the new error code stuff) */
/* Note: this routine is called under the io_request_lock */
/****************************************************************************/
-int
-ips_eh_abort(Scsi_Cmnd * SC)
+int ips_eh_abort(struct scsi_cmnd *SC)
{
ips_ha_t *ha;
ips_copp_wait_item_t *item;
int ret;
- unsigned long cpu_flags;
struct Scsi_Host *host;
METHOD_TRACE("ips_eh_abort", 1);
if (!ha->active)
return (FAILED);
- IPS_LOCK_SAVE(host->host_lock, cpu_flags);
+ spin_lock(host->host_lock);
/* See if the command is on the copp queue */
item = ha->copp_waitlist.head;
ret = (FAILED);
}
- IPS_UNLOCK_RESTORE(host->host_lock, cpu_flags);
+ spin_unlock(host->host_lock);
return ret;
}
/* NOTE: this routine is called under the io_request_lock spinlock */
/* */
/****************************************************************************/
-static int
-ips_eh_reset(Scsi_Cmnd * SC)
+static int __ips_eh_reset(struct scsi_cmnd *SC)
{
int ret;
int i;
ret = (*ha->func.reset) (ha);
if (!ret) {
- Scsi_Cmnd *scsi_cmd;
+ struct scsi_cmnd *scsi_cmd;
IPS_PRINTK(KERN_NOTICE, ha->pcidev,
"Controller reset failed - controller now offline.\n");
}
if (!ips_clear_adapter(ha, IPS_INTR_IORL)) {
- Scsi_Cmnd *scsi_cmd;
+ struct scsi_cmnd *scsi_cmd;
IPS_PRINTK(KERN_NOTICE, ha->pcidev,
"Controller reset failed - controller now offline.\n");
DEBUG_VAR(1, "(%s%d) Failing active commands", ips_name, ha->host_num);
while ((scb = ips_removeq_scb_head(&ha->scb_activelist))) {
- scb->scsi_cmd->result =
- (DID_RESET << 16) | (SUGGEST_RETRY << 24);
+ scb->scsi_cmd->result = DID_RESET << 16;
scb->scsi_cmd->scsi_done(scb->scsi_cmd);
ips_freescb(ha, scb);
}
}
+static int ips_eh_reset(struct scsi_cmnd *SC)
+{
+ int rc;
+
+ spin_lock_irq(SC->device->host->host_lock);
+ rc = __ips_eh_reset(SC);
+ spin_unlock_irq(SC->device->host->host_lock);
+
+ return rc;
+}
+
/****************************************************************************/
/* */
/* Routine Name: ips_queue */
/* Linux obtains io_request_lock before calling this function */
/* */
/****************************************************************************/
-static int
-ips_queue(Scsi_Cmnd * SC, void (*done) (Scsi_Cmnd *))
+static int ips_queue(struct scsi_cmnd *SC, void (*done) (struct scsi_cmnd *))
{
ips_ha_t *ha;
ips_passthru_t *pt;
SC->device->channel, SC->device->id, SC->device->lun);
/* Check for command to initiator IDs */
- if ((SC->device->channel > 0)
- && (SC->device->id == ha->ha_id[SC->device->channel])) {
+ if ((scmd_channel(SC) > 0)
+ && (scmd_id(SC) == ha->ha_id[scmd_channel(SC)])) {
SC->result = DID_NO_CONNECT << 16;
done(SC);
/* A Reset IOCTL is only sent by the boot CD in extreme cases. */
/* There can never be any system activity ( network or disk ), but check */
/* anyway just as a good practice. */
- pt = (ips_passthru_t *) SC->request_buffer;
+ pt = (ips_passthru_t *) scsi_sglist(SC);
if ((pt->CoppCP.cmd.reset.op_code == IPS_CMD_RESET_CHANNEL) &&
(pt->CoppCP.cmd.reset.adapter_flag == 1)) {
if (ha->scb_activelist.count != 0) {
return (0);
}
ha->ioctl_reset = 1; /* This reset request is from an IOCTL */
- ips_eh_reset(SC);
+ __ips_eh_reset(SC);
SC->result = DID_OK << 16;
SC->scsi_done(SC);
return (0);
/* Set bios geometry for the controller */
/* */
/****************************************************************************/
-static int
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-ips_biosparam(Disk * disk, kdev_t dev, int geom[])
-{
- ips_ha_t *ha = (ips_ha_t *) disk->device->host->hostdata;
- unsigned long capacity = disk->capacity;
-#else
-ips_biosparam(struct scsi_device *sdev, struct block_device *bdev,
- sector_t capacity, int geom[])
+static int ips_biosparam(struct scsi_device *sdev, struct block_device *bdev,
+ sector_t capacity, int geom[])
{
ips_ha_t *ha = (ips_ha_t *) sdev->host->hostdata;
-#endif
int heads;
int sectors;
int cylinders;
return (0);
}
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-
-/* ips_proc24_info is a wrapper around ips_proc_info *
- * for compatibility with the 2.4 scsi parameters */
-static int
-ips_proc24_info(char *buffer, char **start, off_t offset, int length,
- int hostno, int func)
-{
- int i;
-
- for (i = 0; i < ips_next_controller; i++) {
- if (ips_sh[i] && ips_sh[i]->host_no == hostno) {
- return ips_proc_info(ips_sh[i], buffer, start,
- offset, length, func);
- }
- }
- return -EINVAL;
-}
-
-/****************************************************************************/
-/* */
-/* Routine Name: ips_select_queue_depth */
-/* */
-/* Routine Description: */
-/* */
-/* Select queue depths for the devices on the contoller */
-/* */
-/****************************************************************************/
-static void
-ips_select_queue_depth(struct Scsi_Host *host, Scsi_Device * scsi_devs)
-{
- Scsi_Device *device;
- ips_ha_t *ha;
- int count = 0;
- int min;
-
- ha = IPS_HA(host);
- min = ha->max_cmds / 4;
-
- for (device = scsi_devs; device; device = device->next) {
- if (device->host == host) {
- if ((device->channel == 0) && (device->type == 0))
- count++;
- }
- }
-
- for (device = scsi_devs; device; device = device->next) {
- if (device->host == host) {
- if ((device->channel == 0) && (device->type == 0)) {
- device->queue_depth =
- (ha->max_cmds - 1) / count;
- if (device->queue_depth < min)
- device->queue_depth = min;
- } else {
- device->queue_depth = 2;
- }
-
- if (device->queue_depth < 2)
- device->queue_depth = 2;
- }
- }
-}
-
-#else
/****************************************************************************/
/* */
/* Routine Name: ips_slave_configure */
/* */
/****************************************************************************/
static int
-ips_slave_configure(Scsi_Device * SDptr)
+ips_slave_configure(struct scsi_device * SDptr)
{
ips_ha_t *ha;
int min;
min = ha->max_cmds - 1;
scsi_adjust_queue_depth(SDptr, MSG_ORDERED_TAG, min);
}
+
+ SDptr->skip_ms_page_8 = 1;
+ SDptr->skip_ms_page_3f = 1;
return 0;
}
-#endif
/****************************************************************************/
/* */
/* */
/****************************************************************************/
static irqreturn_t
-do_ipsintr(int irq, void *dev_id, struct pt_regs * regs)
+do_ipsintr(int irq, void *dev_id)
{
ips_ha_t *ha;
- unsigned long cpu_flags;
struct Scsi_Host *host;
int irqstatus;
return IRQ_HANDLED;
}
- IPS_LOCK_SAVE(host->host_lock, cpu_flags);
+ spin_lock(host->host_lock);
if (!ha->active) {
- IPS_UNLOCK_RESTORE(host->host_lock, cpu_flags);
+ spin_unlock(host->host_lock);
return IRQ_HANDLED;
}
irqstatus = (*ha->func.intr) (ha);
- IPS_UNLOCK_RESTORE(host->host_lock, cpu_flags);
+ spin_unlock(host->host_lock);
/* start the next command */
ips_next(ha, IPS_INTR_ON);
cstatus.value = (*ha->func.statupd) (ha);
if (cstatus.fields.command_id > (IPS_MAX_CMDS - 1)) {
- /* Spurious Interupt ? */
+ /* Spurious Interrupt ? */
continue;
}
/* Determine if the specified SCSI command is really a passthru command */
/* */
/****************************************************************************/
-static int
-ips_is_passthru(Scsi_Cmnd * SC)
+static int ips_is_passthru(struct scsi_cmnd *SC)
{
+ unsigned long flags;
+
METHOD_TRACE("ips_is_passthru", 1);
if (!SC)
if ((SC->cmnd[0] == IPS_IOCTL_COMMAND) &&
(SC->device->channel == 0) &&
(SC->device->id == IPS_ADAPTER_ID) &&
- (SC->device->lun == 0) && SC->request_buffer) {
- if ((!SC->use_sg) && SC->request_bufflen &&
- (((char *) SC->request_buffer)[0] == 'C') &&
- (((char *) SC->request_buffer)[1] == 'O') &&
- (((char *) SC->request_buffer)[2] == 'P') &&
- (((char *) SC->request_buffer)[3] == 'P'))
- return 1;
- else if (SC->use_sg) {
- struct scatterlist *sg = SC->request_buffer;
- char *buffer = IPS_SG_ADDRESS(sg);
- if (buffer && buffer[0] == 'C' && buffer[1] == 'O' &&
- buffer[2] == 'P' && buffer[3] == 'P')
- return 1;
- }
+ (SC->device->lun == 0) && scsi_sglist(SC)) {
+ struct scatterlist *sg = scsi_sglist(SC);
+ char *buffer;
+
+ /* kmap_atomic() ensures addressability of the user buffer.*/
+ /* local_irq_save() protects the KM_IRQ0 address slot. */
+ local_irq_save(flags);
+ buffer = kmap_atomic(sg_page(sg), KM_IRQ0) + sg->offset;
+ if (buffer && buffer[0] == 'C' && buffer[1] == 'O' &&
+ buffer[2] == 'P' && buffer[3] == 'P') {
+ kunmap_atomic(buffer - sg->offset, KM_IRQ0);
+ local_irq_restore(flags);
+ return 1;
+ }
+ kunmap_atomic(buffer - sg->offset, KM_IRQ0);
+ local_irq_restore(flags);
}
return 0;
}
/* */
/****************************************************************************/
static int
-ips_make_passthru(ips_ha_t * ha, Scsi_Cmnd * SC, ips_scb_t * scb, int intr)
+ips_make_passthru(ips_ha_t *ha, struct scsi_cmnd *SC, ips_scb_t *scb, int intr)
{
ips_passthru_t *pt;
int length = 0;
- int ret;
+ int i, ret;
+ struct scatterlist *sg = scsi_sglist(SC);
METHOD_TRACE("ips_make_passthru", 1);
- if (!SC->use_sg) {
- length = SC->request_bufflen;
- } else {
- struct scatterlist *sg = SC->request_buffer;
- int i;
- for (i = 0; i < SC->use_sg; i++)
- length += sg[i].length;
- }
+ scsi_for_each_sg(SC, sg, scsi_sg_count(SC), i)
+ length += sg->length;
+
if (length < sizeof (ips_passthru_t)) {
/* wrong size */
DEBUG_VAR(1, "(%s%d) Passthru structure wrong size",
return (IPS_FAILURE);
}
- if (ha->device_id == IPS_DEVICEID_COPPERHEAD &&
+ if (ha->pcidev->device == IPS_DEVICEID_COPPERHEAD &&
pt->CoppCP.cmd.flashfw.op_code ==
IPS_CMD_RW_BIOSFW) {
ret = ips_flash_copperhead(ha, pt, scb);
METHOD_TRACE("ips_cleanup_passthru", 1);
- if ((!scb) || (!scb->scsi_cmd) || (!scb->scsi_cmd->request_buffer)) {
+ if ((!scb) || (!scb->scsi_cmd) || (!scsi_sglist(scb->scsi_cmd))) {
DEBUG_VAR(1, "(%s%d) couldn't cleanup after passthru",
ips_name, ha->host_num);
pt->ExtendedStatus = scb->extended_status;
pt->AdapterType = ha->ad_type;
- if (ha->device_id == IPS_DEVICEID_COPPERHEAD &&
+ if (ha->pcidev->device == IPS_DEVICEID_COPPERHEAD &&
(scb->cmd.flashfw.op_code == IPS_CMD_DOWNLOAD ||
scb->cmd.flashfw.op_code == IPS_CMD_RW_BIOSFW))
ips_free_flash_copperhead(ha);
ha->mem_ptr);
}
- copy_info(&info, "\tIRQ number : %d\n", ha->irq);
+ copy_info(&info, "\tIRQ number : %d\n", ha->pcidev->irq);
/* For the Next 3 lines Check for Binary 0 at the end and don't include it if it's there. */
/* That keeps everything happy for "text" operations on the proc file. */
if (le32_to_cpu(ha->nvram->signature) == IPS_NVRAM_P5_SIG) {
- if (ha->nvram->bios_low[3] == 0) {
+ if (ha->nvram->bios_low[3] == 0) {
copy_info(&info,
"\tBIOS Version : %c%c%c%c%c%c%c\n",
ha->nvram->bios_high[0], ha->nvram->bios_high[1],
{
METHOD_TRACE("ips_identify_controller", 1);
- switch (ha->device_id) {
+ switch (ha->pcidev->device) {
case IPS_DEVICEID_COPPERHEAD:
- if (ha->revision_id <= IPS_REVID_SERVERAID) {
+ if (ha->pcidev->revision <= IPS_REVID_SERVERAID) {
ha->ad_type = IPS_ADTYPE_SERVERAID;
- } else if (ha->revision_id == IPS_REVID_SERVERAID2) {
+ } else if (ha->pcidev->revision == IPS_REVID_SERVERAID2) {
ha->ad_type = IPS_ADTYPE_SERVERAID2;
- } else if (ha->revision_id == IPS_REVID_NAVAJO) {
+ } else if (ha->pcidev->revision == IPS_REVID_NAVAJO) {
ha->ad_type = IPS_ADTYPE_NAVAJO;
- } else if ((ha->revision_id == IPS_REVID_SERVERAID2)
+ } else if ((ha->pcidev->revision == IPS_REVID_SERVERAID2)
&& (ha->slot_num == 0)) {
ha->ad_type = IPS_ADTYPE_KIOWA;
- } else if ((ha->revision_id >= IPS_REVID_CLARINETP1) &&
- (ha->revision_id <= IPS_REVID_CLARINETP3)) {
+ } else if ((ha->pcidev->revision >= IPS_REVID_CLARINETP1) &&
+ (ha->pcidev->revision <= IPS_REVID_CLARINETP3)) {
if (ha->enq->ucMaxPhysicalDevices == 15)
ha->ad_type = IPS_ADTYPE_SERVERAID3L;
else
ha->ad_type = IPS_ADTYPE_SERVERAID3;
- } else if ((ha->revision_id >= IPS_REVID_TROMBONE32) &&
- (ha->revision_id <= IPS_REVID_TROMBONE64)) {
+ } else if ((ha->pcidev->revision >= IPS_REVID_TROMBONE32) &&
+ (ha->pcidev->revision <= IPS_REVID_TROMBONE64)) {
ha->ad_type = IPS_ADTYPE_SERVERAID4H;
}
break;
case IPS_DEVICEID_MORPHEUS:
- switch (ha->subdevice_id) {
+ switch (ha->pcidev->subsystem_device) {
case IPS_SUBDEVICEID_4L:
ha->ad_type = IPS_ADTYPE_SERVERAID4L;
break;
break;
case IPS_DEVICEID_MARCO:
- switch (ha->subdevice_id) {
+ switch (ha->pcidev->subsystem_device) {
case IPS_SUBDEVICEID_6M:
ha->ad_type = IPS_ADTYPE_SERVERAID6M;
break;
strncpy(ha->bios_version, " ?", 8);
- if (ha->device_id == IPS_DEVICEID_COPPERHEAD) {
+ if (ha->pcidev->device == IPS_DEVICEID_COPPERHEAD) {
if (IPS_USE_MEMIO(ha)) {
/* Memory Mapped I/O */
/* test 1st byte */
writel(0, ha->mem_ptr + IPS_REG_FLAP);
- if (ha->revision_id == IPS_REVID_TROMBONE64)
+ if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
udelay(25); /* 25 us */
if (readb(ha->mem_ptr + IPS_REG_FLDP) != 0x55)
return;
writel(1, ha->mem_ptr + IPS_REG_FLAP);
- if (ha->revision_id == IPS_REVID_TROMBONE64)
+ if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
udelay(25); /* 25 us */
if (readb(ha->mem_ptr + IPS_REG_FLDP) != 0xAA)
/* Get Major version */
writel(0x1FF, ha->mem_ptr + IPS_REG_FLAP);
- if (ha->revision_id == IPS_REVID_TROMBONE64)
+ if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
udelay(25); /* 25 us */
major = readb(ha->mem_ptr + IPS_REG_FLDP);
/* Get Minor version */
writel(0x1FE, ha->mem_ptr + IPS_REG_FLAP);
- if (ha->revision_id == IPS_REVID_TROMBONE64)
+ if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
udelay(25); /* 25 us */
minor = readb(ha->mem_ptr + IPS_REG_FLDP);
/* Get SubMinor version */
writel(0x1FD, ha->mem_ptr + IPS_REG_FLAP);
- if (ha->revision_id == IPS_REVID_TROMBONE64)
+ if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
udelay(25); /* 25 us */
subminor = readb(ha->mem_ptr + IPS_REG_FLDP);
/* test 1st byte */
outl(0, ha->io_addr + IPS_REG_FLAP);
- if (ha->revision_id == IPS_REVID_TROMBONE64)
+ if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
udelay(25); /* 25 us */
if (inb(ha->io_addr + IPS_REG_FLDP) != 0x55)
return;
- outl(cpu_to_le32(1), ha->io_addr + IPS_REG_FLAP);
- if (ha->revision_id == IPS_REVID_TROMBONE64)
+ outl(1, ha->io_addr + IPS_REG_FLAP);
+ if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
udelay(25); /* 25 us */
if (inb(ha->io_addr + IPS_REG_FLDP) != 0xAA)
return;
/* Get Major version */
- outl(cpu_to_le32(0x1FF), ha->io_addr + IPS_REG_FLAP);
- if (ha->revision_id == IPS_REVID_TROMBONE64)
+ outl(0x1FF, ha->io_addr + IPS_REG_FLAP);
+ if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
udelay(25); /* 25 us */
major = inb(ha->io_addr + IPS_REG_FLDP);
/* Get Minor version */
- outl(cpu_to_le32(0x1FE), ha->io_addr + IPS_REG_FLAP);
- if (ha->revision_id == IPS_REVID_TROMBONE64)
+ outl(0x1FE, ha->io_addr + IPS_REG_FLAP);
+ if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
udelay(25); /* 25 us */
minor = inb(ha->io_addr + IPS_REG_FLDP);
/* Get SubMinor version */
- outl(cpu_to_le32(0x1FD), ha->io_addr + IPS_REG_FLAP);
- if (ha->revision_id == IPS_REVID_TROMBONE64)
+ outl(0x1FD, ha->io_addr + IPS_REG_FLAP);
+ if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
udelay(25); /* 25 us */
subminor = inb(ha->io_addr + IPS_REG_FLDP);
ips_next(ips_ha_t * ha, int intr)
{
ips_scb_t *scb;
- Scsi_Cmnd *SC;
- Scsi_Cmnd *p;
- Scsi_Cmnd *q;
+ struct scsi_cmnd *SC;
+ struct scsi_cmnd *p;
+ struct scsi_cmnd *q;
ips_copp_wait_item_t *item;
int ret;
- unsigned long cpu_flags = 0;
struct Scsi_Host *host;
METHOD_TRACE("ips_next", 1);
* this command won't time out
*/
if (intr == IPS_INTR_ON)
- IPS_LOCK_SAVE(host->host_lock, cpu_flags);
+ spin_lock(host->host_lock);
if ((ha->subsys->param[3] & 0x300000)
&& (ha->scb_activelist.count == 0)) {
item = ips_removeq_copp_head(&ha->copp_waitlist);
ha->num_ioctl++;
if (intr == IPS_INTR_ON)
- IPS_UNLOCK_RESTORE(host->host_lock, cpu_flags);
+ spin_unlock(host->host_lock);
scb->scsi_cmd = item->scsi_cmd;
kfree(item);
ret = ips_make_passthru(ha, scb->scsi_cmd, scb, intr);
if (intr == IPS_INTR_ON)
- IPS_LOCK_SAVE(host->host_lock, cpu_flags);
+ spin_lock(host->host_lock);
switch (ret) {
case IPS_FAILURE:
if (scb->scsi_cmd) {
p = ha->scb_waitlist.head;
while ((p) && (scb = ips_getscb(ha))) {
- if ((p->device->channel > 0)
+ if ((scmd_channel(p) > 0)
&& (ha->
- dcdb_active[p->device->channel -
- 1] & (1 << p->device->id))) {
+ dcdb_active[scmd_channel(p) -
+ 1] & (1 << scmd_id(p)))) {
ips_freescb(ha, scb);
- p = (Scsi_Cmnd *) p->host_scribble;
+ p = (struct scsi_cmnd *) p->host_scribble;
continue;
}
SC = ips_removeq_wait(&ha->scb_waitlist, q);
if (intr == IPS_INTR_ON)
- IPS_UNLOCK_RESTORE(host->host_lock, cpu_flags); /* Unlock HA after command is taken off queue */
+ spin_unlock(host->host_lock); /* Unlock HA after command is taken off queue */
SC->result = DID_OK;
SC->host_scribble = NULL;
- memset(SC->sense_buffer, 0, sizeof (SC->sense_buffer));
-
scb->target_id = SC->device->id;
scb->lun = SC->device->lun;
scb->bus = SC->device->channel;
/* copy in the CDB */
memcpy(scb->cdb, SC->cmnd, SC->cmd_len);
- /* Now handle the data buffer */
- if (SC->use_sg) {
+ scb->sg_count = scsi_dma_map(SC);
+ BUG_ON(scb->sg_count < 0);
+ if (scb->sg_count) {
struct scatterlist *sg;
int i;
- sg = SC->request_buffer;
- scb->sg_count = pci_map_sg(ha->pcidev, sg, SC->use_sg,
- SC->sc_data_direction);
scb->flags |= IPS_SCB_MAP_SG;
- for (i = 0; i < scb->sg_count; i++) {
+
+ scsi_for_each_sg(SC, sg, scb->sg_count, i) {
if (ips_fill_scb_sg_single
- (ha, sg_dma_address(&sg[i]), scb, i,
- sg_dma_len(&sg[i])) < 0)
+ (ha, sg_dma_address(sg), scb, i,
+ sg_dma_len(sg)) < 0)
break;
}
scb->dcdb.transfer_length = scb->data_len;
} else {
- if (SC->request_bufflen) {
- scb->data_busaddr =
- pci_map_single(ha->pcidev,
- SC->request_buffer,
- SC->request_bufflen,
- SC->sc_data_direction);
- scb->flags |= IPS_SCB_MAP_SINGLE;
- ips_fill_scb_sg_single(ha, scb->data_busaddr,
- scb, 0,
- SC->request_bufflen);
- scb->dcdb.transfer_length = scb->data_len;
- } else {
- scb->data_busaddr = 0L;
- scb->sg_len = 0;
- scb->data_len = 0;
- scb->dcdb.transfer_length = 0;
- }
-
+ scb->data_busaddr = 0L;
+ scb->sg_len = 0;
+ scb->data_len = 0;
+ scb->dcdb.transfer_length = 0;
}
scb->dcdb.cmd_attribute =
ips_command_direction[scb->scsi_cmd->cmnd[0]];
- /* Allow a WRITE BUFFER Command to Have no Data */
- /* This is Used by Tape Flash Utilites */
- if ((scb->scsi_cmd->cmnd[0] == WRITE_BUFFER) && (scb->data_len == 0))
- scb->dcdb.cmd_attribute = 0;
+ /* Allow a WRITE BUFFER Command to Have no Data */
+ /* This is Used by Tape Flash Utilites */
+ if ((scb->scsi_cmd->cmnd[0] == WRITE_BUFFER) &&
+ (scb->data_len == 0))
+ scb->dcdb.cmd_attribute = 0;
if (!(scb->dcdb.cmd_attribute & 0x3))
scb->dcdb.transfer_length = 0;
scb->dcdb.transfer_length = 0;
}
if (intr == IPS_INTR_ON)
- IPS_LOCK_SAVE(host->host_lock, cpu_flags);
+ spin_lock(host->host_lock);
ret = ips_send_cmd(ha, scb);
break;
} /* end case */
- p = (Scsi_Cmnd *) p->host_scribble;
+ p = (struct scsi_cmnd *) p->host_scribble;
} /* end while */
if (intr == IPS_INTR_ON)
- IPS_UNLOCK_RESTORE(host->host_lock, cpu_flags);
+ spin_unlock(host->host_lock);
}
/****************************************************************************/
/* ASSUMED to be called from within the HA lock */
/* */
/****************************************************************************/
-static void
-ips_putq_wait_tail(ips_wait_queue_t * queue, Scsi_Cmnd * item)
+static void ips_putq_wait_tail(ips_wait_queue_t *queue, struct scsi_cmnd *item)
{
METHOD_TRACE("ips_putq_wait_tail", 1);
/* ASSUMED to be called from within the HA lock */
/* */
/****************************************************************************/
-static Scsi_Cmnd *
-ips_removeq_wait_head(ips_wait_queue_t * queue)
+static struct scsi_cmnd *ips_removeq_wait_head(ips_wait_queue_t *queue)
{
- Scsi_Cmnd *item;
+ struct scsi_cmnd *item;
METHOD_TRACE("ips_removeq_wait_head", 1);
return (NULL);
}
- queue->head = (Scsi_Cmnd *) item->host_scribble;
+ queue->head = (struct scsi_cmnd *) item->host_scribble;
item->host_scribble = NULL;
if (queue->tail == item)
/* ASSUMED to be called from within the HA lock */
/* */
/****************************************************************************/
-static Scsi_Cmnd *
-ips_removeq_wait(ips_wait_queue_t * queue, Scsi_Cmnd * item)
+static struct scsi_cmnd *ips_removeq_wait(ips_wait_queue_t *queue,
+ struct scsi_cmnd *item)
{
- Scsi_Cmnd *p;
+ struct scsi_cmnd *p;
METHOD_TRACE("ips_removeq_wait", 1);
p = queue->head;
- while ((p) && (item != (Scsi_Cmnd *) p->host_scribble))
- p = (Scsi_Cmnd *) p->host_scribble;
+ while ((p) && (item != (struct scsi_cmnd *) p->host_scribble))
+ p = (struct scsi_cmnd *) p->host_scribble;
if (p) {
/* found a match */
* the rest of the data and continue.
*/
if ((scb->breakup) || (scb->sg_break)) {
+ struct scatterlist *sg;
+ int i, sg_dma_index, ips_sg_index = 0;
+
/* we had a data breakup */
scb->data_len = 0;
- if (scb->sg_count) {
- /* S/G request */
- struct scatterlist *sg;
- int ips_sg_index = 0;
- int sg_dma_index;
-
- sg = scb->scsi_cmd->request_buffer;
-
- /* Spin forward to last dma chunk */
- sg_dma_index = scb->breakup;
-
- /* Take care of possible partial on last chunk */
- ips_fill_scb_sg_single(ha,
- sg_dma_address(&sg
- [sg_dma_index]),
- scb, ips_sg_index++,
- sg_dma_len(&sg
- [sg_dma_index]));
-
- for (; sg_dma_index < scb->sg_count;
- sg_dma_index++) {
- if (ips_fill_scb_sg_single
- (ha,
- sg_dma_address(&sg[sg_dma_index]),
- scb, ips_sg_index++,
- sg_dma_len(&sg[sg_dma_index])) < 0)
- break;
-
- }
-
- } else {
- /* Non S/G Request */
- (void) ips_fill_scb_sg_single(ha,
- scb->
- data_busaddr +
- (scb->sg_break *
- ha->max_xfer),
- scb, 0,
- scb->scsi_cmd->
- request_bufflen -
- (scb->sg_break *
- ha->max_xfer));
- }
+ sg = scsi_sglist(scb->scsi_cmd);
+
+ /* Spin forward to last dma chunk */
+ sg_dma_index = scb->breakup;
+ for (i = 0; i < scb->breakup; i++)
+ sg = sg_next(sg);
+
+ /* Take care of possible partial on last chunk */
+ ips_fill_scb_sg_single(ha,
+ sg_dma_address(sg),
+ scb, ips_sg_index++,
+ sg_dma_len(sg));
+
+ for (; sg_dma_index < scsi_sg_count(scb->scsi_cmd);
+ sg_dma_index++, sg = sg_next(sg)) {
+ if (ips_fill_scb_sg_single
+ (ha,
+ sg_dma_address(sg),
+ scb, ips_sg_index++,
+ sg_dma_len(sg)) < 0)
+ break;
+ }
scb->dcdb.transfer_length = scb->data_len;
scb->dcdb.cmd_attribute |=
int device_error;
uint32_t transfer_len;
IPS_DCDB_TABLE_TAPE *tapeDCDB;
+ IPS_SCSI_INQ_DATA inquiryData;
METHOD_TRACE("ips_map_status", 1);
errcode = DID_OK;
/* Restrict access to physical DASD */
- if ((scb->scsi_cmd->cmnd[0] == INQUIRY) &&
- ((((char *) scb->scsi_cmd->
- buffer)[0] & 0x1f) == TYPE_DISK)) {
- /* underflow -- no error */
- /* restrict access to physical DASD */
- errcode = DID_TIME_OUT;
- break;
+ if (scb->scsi_cmd->cmnd[0] == INQUIRY) {
+ ips_scmd_buf_read(scb->scsi_cmd,
+ &inquiryData, sizeof (inquiryData));
+ if ((inquiryData.DeviceType & 0x1f) == TYPE_DISK) {
+ errcode = DID_TIME_OUT;
+ break;
+ }
}
} else
errcode = DID_ERROR;
(IPS_DCDB_TABLE_TAPE *) & scb->dcdb;
memcpy(scb->scsi_cmd->sense_buffer,
tapeDCDB->sense_info,
- sizeof (scb->scsi_cmd->
- sense_buffer));
+ SCSI_SENSE_BUFFERSIZE);
} else {
memcpy(scb->scsi_cmd->sense_buffer,
scb->dcdb.sense_info,
- sizeof (scb->scsi_cmd->
- sense_buffer));
+ SCSI_SENSE_BUFFERSIZE);
}
device_error = 2; /* check condition */
}
/* Routine Name: ips_scmd_buf_write */
/* */
/* Routine Description: */
-/* Write data to Scsi_Cmnd request_buffer at proper offsets */
+/* Write data to struct scsi_cmnd request_buffer at proper offsets */
/****************************************************************************/
static void
-ips_scmd_buf_write(Scsi_Cmnd * scmd, void *data, unsigned
- int count)
+ips_scmd_buf_write(struct scsi_cmnd *scmd, void *data, unsigned int count)
{
- if (scmd->use_sg) {
- int i;
- unsigned int min_cnt, xfer_cnt;
- char *cdata = (char *) data;
- struct scatterlist *sg = scmd->request_buffer;
- for (i = 0, xfer_cnt = 0;
- (i < scmd->use_sg) && (xfer_cnt < count); i++) {
- if (!IPS_SG_ADDRESS(&sg[i]))
- return;
- min_cnt = min(count - xfer_cnt, sg[i].length);
- memcpy(IPS_SG_ADDRESS(&sg[i]), &cdata[xfer_cnt],
- min_cnt);
- xfer_cnt += min_cnt;
- }
+ unsigned long flags;
- } else {
- unsigned int min_cnt = min(count, scmd->request_bufflen);
- memcpy(scmd->request_buffer, data, min_cnt);
- }
+ local_irq_save(flags);
+ scsi_sg_copy_from_buffer(scmd, data, count);
+ local_irq_restore(flags);
}
/****************************************************************************/
/* Routine Name: ips_scmd_buf_read */
/* */
/* Routine Description: */
-/* Copy data from a Scsi_Cmnd to a new, linear buffer */
+/* Copy data from a struct scsi_cmnd to a new, linear buffer */
/****************************************************************************/
static void
-ips_scmd_buf_read(Scsi_Cmnd * scmd, void *data, unsigned
- int count)
+ips_scmd_buf_read(struct scsi_cmnd *scmd, void *data, unsigned int count)
{
- if (scmd->use_sg) {
- int i;
- unsigned int min_cnt, xfer_cnt;
- char *cdata = (char *) data;
- struct scatterlist *sg = scmd->request_buffer;
- for (i = 0, xfer_cnt = 0;
- (i < scmd->use_sg) && (xfer_cnt < count); i++) {
- if (!IPS_SG_ADDRESS(&sg[i]))
- return;
- min_cnt = min(count - xfer_cnt, sg[i].length);
- memcpy(&cdata[xfer_cnt], IPS_SG_ADDRESS(&sg[i]),
- min_cnt);
- xfer_cnt += min_cnt;
- }
+ unsigned long flags;
- } else {
- unsigned int min_cnt = min(count, scmd->request_bufflen);
- memcpy(data, scmd->request_buffer, min_cnt);
- }
+ local_irq_save(flags);
+ scsi_sg_copy_to_buffer(scmd, data, count);
+ local_irq_restore(flags);
}
/****************************************************************************/
scb->cmd.basic_io.sg_count = scb->sg_len;
if (scb->cmd.basic_io.lba)
- scb->cmd.basic_io.lba =
- cpu_to_le32(le32_to_cpu
- (scb->cmd.basic_io.lba) +
+ le32_add_cpu(&scb->cmd.basic_io.lba,
le16_to_cpu(scb->cmd.basic_io.
sector_count));
else
scb->cmd.basic_io.sg_count = scb->sg_len;
if (scb->cmd.basic_io.lba)
- scb->cmd.basic_io.lba =
- cpu_to_le32(le32_to_cpu
- (scb->cmd.basic_io.lba) +
+ le32_add_cpu(&scb->cmd.basic_io.lba,
le16_to_cpu(scb->cmd.basic_io.
sector_count));
else
/* attempted, a Check Condition occurred, and Sense */
/* Data indicating an Invalid CDB OpCode is returned. */
sp = (char *) scb->scsi_cmd->sense_buffer;
- memset(sp, 0, sizeof (scb->scsi_cmd->sense_buffer));
sp[0] = 0x70; /* Error Code */
sp[2] = ILLEGAL_REQUEST; /* Sense Key 5 Illegal Req. */
scb->cmd.dcdb.segment_4G = 0;
scb->cmd.dcdb.enhanced_sg = 0;
- TimeOut = scb->scsi_cmd->timeout_per_command;
+ TimeOut = scb->scsi_cmd->request->timeout;
if (ha->subsys->param[4] & 0x00100000) { /* If NEW Tape DCDB is Supported */
if (!scb->sg_len) {
uint8_t basic_status;
uint8_t ext_status;
int errcode;
+ IPS_SCSI_INQ_DATA inquiryData;
METHOD_TRACE("ips_chkstatus", 1);
scb->scsi_cmd->result = errcode << 16;
} else { /* bus == 0 */
/* restrict access to physical drives */
- if ((scb->scsi_cmd->cmnd[0] == INQUIRY) &&
- ((((char *) scb->scsi_cmd->buffer)[0] & 0x1f) ==
- TYPE_DISK)) {
-
- scb->scsi_cmd->result = DID_TIME_OUT << 16;
+ if (scb->scsi_cmd->cmnd[0] == INQUIRY) {
+ ips_scmd_buf_read(scb->scsi_cmd,
+ &inquiryData, sizeof (inquiryData));
+ if ((inquiryData.DeviceType & 0x1f) == TYPE_DISK)
+ scb->scsi_cmd->result = DID_TIME_OUT << 16;
}
} /* else */
} else { /* recovered error / success */
METHOD_TRACE("ips_rdcap", 1);
- if (scb->scsi_cmd->bufflen < 8)
+ if (scsi_bufflen(scb->scsi_cmd) < 8)
return (0);
cap.lba =
ha->enq = NULL;
}
- if (ha->conf) {
- kfree(ha->conf);
- ha->conf = NULL;
- }
+ kfree(ha->conf);
+ ha->conf = NULL;
if (ha->adapt) {
pci_free_consistent(ha->pcidev,
ha->logical_drive_info = NULL;
}
- if (ha->nvram) {
- kfree(ha->nvram);
- ha->nvram = NULL;
- }
+ kfree(ha->nvram);
+ ha->nvram = NULL;
- if (ha->subsys) {
- kfree(ha->subsys);
- ha->subsys = NULL;
- }
+ kfree(ha->subsys);
+ ha->subsys = NULL;
if (ha->ioctl_data) {
pci_free_consistent(ha->pcidev, ha->ioctl_len,
ha->mem_ptr = NULL;
}
- if (ha->mem_addr)
- release_mem_region(ha->mem_addr, ha->mem_len);
ha->mem_addr = 0;
}
METHOD_TRACE("ips_freescb", 1);
if (scb->flags & IPS_SCB_MAP_SG)
- pci_unmap_sg(ha->pcidev, scb->scsi_cmd->request_buffer,
- scb->scsi_cmd->use_sg, IPS_DMA_DIR(scb));
+ scsi_dma_unmap(scb->scsi_cmd);
else if (scb->flags & IPS_SCB_MAP_SINGLE)
pci_unmap_single(ha->pcidev, scb->data_busaddr, scb->data_len,
IPS_DMA_DIR(scb));
METHOD_TRACE("ips_is_init_morpheus", 1);
+ if (ips_isintr_morpheus(ha))
+ ips_flush_and_reset(ha);
+
post = readl(ha->mem_ptr + IPS_REG_I960_MSG0);
bits = readl(ha->mem_ptr + IPS_REG_I2O_HIR);
/****************************************************************************/
/* */
+/* Routine Name: ips_flush_and_reset */
+/* */
+/* Routine Description: */
+/* */
+/* Perform cleanup ( FLUSH and RESET ) when the adapter is in an unknown */
+/* state ( was trying to INIT and an interrupt was already pending ) ... */
+/* */
+/****************************************************************************/
+static void
+ips_flush_and_reset(ips_ha_t *ha)
+{
+ ips_scb_t *scb;
+ int ret;
+ int time;
+ int done;
+ dma_addr_t command_dma;
+
+ /* Create a usuable SCB */
+ scb = pci_alloc_consistent(ha->pcidev, sizeof(ips_scb_t), &command_dma);
+ if (scb) {
+ memset(scb, 0, sizeof(ips_scb_t));
+ ips_init_scb(ha, scb);
+ scb->scb_busaddr = command_dma;
+
+ scb->timeout = ips_cmd_timeout;
+ scb->cdb[0] = IPS_CMD_FLUSH;
+
+ scb->cmd.flush_cache.op_code = IPS_CMD_FLUSH;
+ scb->cmd.flush_cache.command_id = IPS_MAX_CMDS; /* Use an ID that would otherwise not exist */
+ scb->cmd.flush_cache.state = IPS_NORM_STATE;
+ scb->cmd.flush_cache.reserved = 0;
+ scb->cmd.flush_cache.reserved2 = 0;
+ scb->cmd.flush_cache.reserved3 = 0;
+ scb->cmd.flush_cache.reserved4 = 0;
+
+ ret = ips_send_cmd(ha, scb); /* Send the Flush Command */
+
+ if (ret == IPS_SUCCESS) {
+ time = 60 * IPS_ONE_SEC; /* Max Wait time is 60 seconds */
+ done = 0;
+
+ while ((time > 0) && (!done)) {
+ done = ips_poll_for_flush_complete(ha);
+ /* This may look evil, but it's only done during extremely rare start-up conditions ! */
+ udelay(1000);
+ time--;
+ }
+ }
+ }
+
+ /* Now RESET and INIT the adapter */
+ (*ha->func.reset) (ha);
+
+ pci_free_consistent(ha->pcidev, sizeof(ips_scb_t), scb, command_dma);
+ return;
+}
+
+/****************************************************************************/
+/* */
+/* Routine Name: ips_poll_for_flush_complete */
+/* */
+/* Routine Description: */
+/* */
+/* Poll for the Flush Command issued by ips_flush_and_reset() to complete */
+/* All other responses are just taken off the queue and ignored */
+/* */
+/****************************************************************************/
+static int
+ips_poll_for_flush_complete(ips_ha_t * ha)
+{
+ IPS_STATUS cstatus;
+
+ while (TRUE) {
+ cstatus.value = (*ha->func.statupd) (ha);
+
+ if (cstatus.value == 0xffffffff) /* If No Interrupt to process */
+ break;
+
+ /* Success is when we see the Flush Command ID */
+ if (cstatus.fields.command_id == IPS_MAX_CMDS)
+ return 1;
+ }
+
+ return 0;
+}
+
+/****************************************************************************/
+/* */
/* Routine Name: ips_enable_int_copperhead */
/* */
/* Routine Description: */
return (0);
/* setup CCCR */
- outl(cpu_to_le32(0x1010), ha->io_addr + IPS_REG_CCCR);
+ outl(0x1010, ha->io_addr + IPS_REG_CCCR);
/* Enable busmastering */
outb(IPS_BIT_EBM, ha->io_addr + IPS_REG_SCPR);
- if (ha->revision_id == IPS_REVID_TROMBONE64)
+ if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
/* fix for anaconda64 */
outl(0, ha->io_addr + IPS_REG_NDAE);
/* Enable busmastering */
writeb(IPS_BIT_EBM, ha->mem_ptr + IPS_REG_SCPR);
- if (ha->revision_id == IPS_REVID_TROMBONE64)
+ if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
/* fix for anaconda64 */
writel(0, ha->mem_ptr + IPS_REG_NDAE);
METHOD_TRACE("ips_reset_copperhead", 1);
DEBUG_VAR(1, "(%s%d) ips_reset_copperhead: io addr: %x, irq: %d",
- ips_name, ha->host_num, ha->io_addr, ha->irq);
+ ips_name, ha->host_num, ha->io_addr, ha->pcidev->irq);
reset_counter = 0;
METHOD_TRACE("ips_reset_copperhead_memio", 1);
DEBUG_VAR(1, "(%s%d) ips_reset_copperhead_memio: mem addr: %x, irq: %d",
- ips_name, ha->host_num, ha->mem_addr, ha->irq);
+ ips_name, ha->host_num, ha->mem_addr, ha->pcidev->irq);
reset_counter = 0;
METHOD_TRACE("ips_reset_morpheus", 1);
DEBUG_VAR(1, "(%s%d) ips_reset_morpheus: mem addr: %x, irq: %d",
- ips_name, ha->host_num, ha->mem_addr, ha->irq);
+ ips_name, ha->host_num, ha->mem_addr, ha->pcidev->irq);
reset_counter = 0;
ha->adapt->p_status_tail = ha->adapt->status;
phys_status_start = ha->adapt->hw_status_start;
- outl(cpu_to_le32(phys_status_start), ha->io_addr + IPS_REG_SQSR);
- outl(cpu_to_le32(phys_status_start + IPS_STATUS_Q_SIZE),
+ outl(phys_status_start, ha->io_addr + IPS_REG_SQSR);
+ outl(phys_status_start + IPS_STATUS_Q_SIZE,
ha->io_addr + IPS_REG_SQER);
- outl(cpu_to_le32(phys_status_start + IPS_STATUS_SIZE),
+ outl(phys_status_start + IPS_STATUS_SIZE,
ha->io_addr + IPS_REG_SQHR);
- outl(cpu_to_le32(phys_status_start), ha->io_addr + IPS_REG_SQTR);
+ outl(phys_status_start, ha->io_addr + IPS_REG_SQTR);
ha->adapt->hw_status_tail = phys_status_start;
}
ha->adapt->hw_status_tail = ha->adapt->hw_status_start;
}
- outl(cpu_to_le32(ha->adapt->hw_status_tail),
+ outl(ha->adapt->hw_status_tail,
ha->io_addr + IPS_REG_SQTR);
return (ha->adapt->p_status_tail->value);
} /* end if */
} /* end while */
- outl(cpu_to_le32(scb->scb_busaddr), ha->io_addr + IPS_REG_CCSAR);
- outw(cpu_to_le32(IPS_BIT_START_CMD), ha->io_addr + IPS_REG_CCCR);
+ outl(scb->scb_busaddr, ha->io_addr + IPS_REG_CCSAR);
+ outw(IPS_BIT_START_CMD, ha->io_addr + IPS_REG_CCCR);
return (IPS_SUCCESS);
}
ips_name, ha->host_num, scb->cmd.basic_io.command_id);
}
- outl(cpu_to_le32(scb->scb_busaddr), ha->io_addr + IPS_REG_I2O_INMSGQ);
+ outl(scb->scb_busaddr, ha->io_addr + IPS_REG_I2O_INMSGQ);
return (IPS_SUCCESS);
}
strncpy((char *) ha->nvram->bios_high, ha->bios_version, 4);
strncpy((char *) ha->nvram->bios_low, ha->bios_version + 4, 4);
- ips_version_check(ha, intr); /* Check BIOS/FW/Driver Versions */
+ ha->nvram->versioning = 0; /* Indicate the Driver Does Not Support Versioning */
/* now update the page */
if (!ips_readwrite_page5(ha, TRUE, intr)) {
return (0);
}
-
+
memcpy(ha->conf, ha->ioctl_data, sizeof(*ha->conf));
return (1);
}
scb->cmd.nvram.buffer_addr = ha->ioctl_busaddr;
if (write)
memcpy(ha->ioctl_data, ha->nvram, sizeof(*ha->nvram));
-
+
/* issue the command */
if (((ret =
ips_send_wait(ha, scb, ips_cmd_timeout, intr)) == IPS_FAILURE)
/* Clear the status register */
outl(0, ha->io_addr + IPS_REG_FLAP);
- if (ha->revision_id == IPS_REVID_TROMBONE64)
+ if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
udelay(25); /* 25 us */
outb(0x50, ha->io_addr + IPS_REG_FLDP);
- if (ha->revision_id == IPS_REVID_TROMBONE64)
+ if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
udelay(25); /* 25 us */
/* Erase Setup */
outb(0x20, ha->io_addr + IPS_REG_FLDP);
- if (ha->revision_id == IPS_REVID_TROMBONE64)
+ if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
udelay(25); /* 25 us */
/* Erase Confirm */
outb(0xD0, ha->io_addr + IPS_REG_FLDP);
- if (ha->revision_id == IPS_REVID_TROMBONE64)
+ if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
udelay(25); /* 25 us */
/* Erase Status */
outb(0x70, ha->io_addr + IPS_REG_FLDP);
- if (ha->revision_id == IPS_REVID_TROMBONE64)
+ if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
udelay(25); /* 25 us */
timeout = 80000; /* 80 seconds */
while (timeout > 0) {
- if (ha->revision_id == IPS_REVID_TROMBONE64) {
+ if (ha->pcidev->revision == IPS_REVID_TROMBONE64) {
outl(0, ha->io_addr + IPS_REG_FLAP);
udelay(25); /* 25 us */
}
/* try to suspend the erase */
outb(0xB0, ha->io_addr + IPS_REG_FLDP);
- if (ha->revision_id == IPS_REVID_TROMBONE64)
+ if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
udelay(25); /* 25 us */
/* wait for 10 seconds */
timeout = 10000;
while (timeout > 0) {
- if (ha->revision_id == IPS_REVID_TROMBONE64) {
+ if (ha->pcidev->revision == IPS_REVID_TROMBONE64) {
outl(0, ha->io_addr + IPS_REG_FLAP);
udelay(25); /* 25 us */
}
/* VPP failure */
return (1);
- /* check for succesful flash */
+ /* check for successful flash */
if (status & 0x30)
/* sequence error */
return (1);
/* Otherwise, we were successful */
/* clear status */
outb(0x50, ha->io_addr + IPS_REG_FLDP);
- if (ha->revision_id == IPS_REVID_TROMBONE64)
+ if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
udelay(25); /* 25 us */
/* enable reads */
outb(0xFF, ha->io_addr + IPS_REG_FLDP);
- if (ha->revision_id == IPS_REVID_TROMBONE64)
+ if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
udelay(25); /* 25 us */
return (0);
/* Clear the status register */
writel(0, ha->mem_ptr + IPS_REG_FLAP);
- if (ha->revision_id == IPS_REVID_TROMBONE64)
+ if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
udelay(25); /* 25 us */
writeb(0x50, ha->mem_ptr + IPS_REG_FLDP);
- if (ha->revision_id == IPS_REVID_TROMBONE64)
+ if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
udelay(25); /* 25 us */
/* Erase Setup */
writeb(0x20, ha->mem_ptr + IPS_REG_FLDP);
- if (ha->revision_id == IPS_REVID_TROMBONE64)
+ if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
udelay(25); /* 25 us */
/* Erase Confirm */
writeb(0xD0, ha->mem_ptr + IPS_REG_FLDP);
- if (ha->revision_id == IPS_REVID_TROMBONE64)
+ if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
udelay(25); /* 25 us */
/* Erase Status */
writeb(0x70, ha->mem_ptr + IPS_REG_FLDP);
- if (ha->revision_id == IPS_REVID_TROMBONE64)
+ if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
udelay(25); /* 25 us */
timeout = 80000; /* 80 seconds */
while (timeout > 0) {
- if (ha->revision_id == IPS_REVID_TROMBONE64) {
+ if (ha->pcidev->revision == IPS_REVID_TROMBONE64) {
writel(0, ha->mem_ptr + IPS_REG_FLAP);
udelay(25); /* 25 us */
}
/* try to suspend the erase */
writeb(0xB0, ha->mem_ptr + IPS_REG_FLDP);
- if (ha->revision_id == IPS_REVID_TROMBONE64)
+ if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
udelay(25); /* 25 us */
/* wait for 10 seconds */
timeout = 10000;
while (timeout > 0) {
- if (ha->revision_id == IPS_REVID_TROMBONE64) {
+ if (ha->pcidev->revision == IPS_REVID_TROMBONE64) {
writel(0, ha->mem_ptr + IPS_REG_FLAP);
udelay(25); /* 25 us */
}
/* VPP failure */
return (1);
- /* check for succesful flash */
+ /* check for successful flash */
if (status & 0x30)
/* sequence error */
return (1);
/* Otherwise, we were successful */
/* clear status */
writeb(0x50, ha->mem_ptr + IPS_REG_FLDP);
- if (ha->revision_id == IPS_REVID_TROMBONE64)
+ if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
udelay(25); /* 25 us */
/* enable reads */
writeb(0xFF, ha->mem_ptr + IPS_REG_FLDP);
- if (ha->revision_id == IPS_REVID_TROMBONE64)
+ if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
udelay(25); /* 25 us */
return (0);
for (i = 0; i < buffersize; i++) {
/* write a byte */
- outl(cpu_to_le32(i + offset), ha->io_addr + IPS_REG_FLAP);
- if (ha->revision_id == IPS_REVID_TROMBONE64)
+ outl(i + offset, ha->io_addr + IPS_REG_FLAP);
+ if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
udelay(25); /* 25 us */
outb(0x40, ha->io_addr + IPS_REG_FLDP);
- if (ha->revision_id == IPS_REVID_TROMBONE64)
+ if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
udelay(25); /* 25 us */
outb(buffer[i], ha->io_addr + IPS_REG_FLDP);
- if (ha->revision_id == IPS_REVID_TROMBONE64)
+ if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
udelay(25); /* 25 us */
/* wait up to one second */
timeout = 1000;
while (timeout > 0) {
- if (ha->revision_id == IPS_REVID_TROMBONE64) {
+ if (ha->pcidev->revision == IPS_REVID_TROMBONE64) {
outl(0, ha->io_addr + IPS_REG_FLAP);
udelay(25); /* 25 us */
}
if (timeout == 0) {
/* timeout error */
outl(0, ha->io_addr + IPS_REG_FLAP);
- if (ha->revision_id == IPS_REVID_TROMBONE64)
+ if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
udelay(25); /* 25 us */
outb(0xFF, ha->io_addr + IPS_REG_FLDP);
- if (ha->revision_id == IPS_REVID_TROMBONE64)
+ if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
udelay(25); /* 25 us */
return (1);
if (status & 0x18) {
/* programming error */
outl(0, ha->io_addr + IPS_REG_FLAP);
- if (ha->revision_id == IPS_REVID_TROMBONE64)
+ if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
udelay(25); /* 25 us */
outb(0xFF, ha->io_addr + IPS_REG_FLDP);
- if (ha->revision_id == IPS_REVID_TROMBONE64)
+ if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
udelay(25); /* 25 us */
return (1);
/* Enable reading */
outl(0, ha->io_addr + IPS_REG_FLAP);
- if (ha->revision_id == IPS_REVID_TROMBONE64)
+ if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
udelay(25); /* 25 us */
outb(0xFF, ha->io_addr + IPS_REG_FLDP);
- if (ha->revision_id == IPS_REVID_TROMBONE64)
+ if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
udelay(25); /* 25 us */
return (0);
for (i = 0; i < buffersize; i++) {
/* write a byte */
writel(i + offset, ha->mem_ptr + IPS_REG_FLAP);
- if (ha->revision_id == IPS_REVID_TROMBONE64)
+ if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
udelay(25); /* 25 us */
writeb(0x40, ha->mem_ptr + IPS_REG_FLDP);
- if (ha->revision_id == IPS_REVID_TROMBONE64)
+ if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
udelay(25); /* 25 us */
writeb(buffer[i], ha->mem_ptr + IPS_REG_FLDP);
- if (ha->revision_id == IPS_REVID_TROMBONE64)
+ if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
udelay(25); /* 25 us */
/* wait up to one second */
timeout = 1000;
while (timeout > 0) {
- if (ha->revision_id == IPS_REVID_TROMBONE64) {
+ if (ha->pcidev->revision == IPS_REVID_TROMBONE64) {
writel(0, ha->mem_ptr + IPS_REG_FLAP);
udelay(25); /* 25 us */
}
if (timeout == 0) {
/* timeout error */
writel(0, ha->mem_ptr + IPS_REG_FLAP);
- if (ha->revision_id == IPS_REVID_TROMBONE64)
+ if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
udelay(25); /* 25 us */
writeb(0xFF, ha->mem_ptr + IPS_REG_FLDP);
- if (ha->revision_id == IPS_REVID_TROMBONE64)
+ if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
udelay(25); /* 25 us */
return (1);
if (status & 0x18) {
/* programming error */
writel(0, ha->mem_ptr + IPS_REG_FLAP);
- if (ha->revision_id == IPS_REVID_TROMBONE64)
+ if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
udelay(25); /* 25 us */
writeb(0xFF, ha->mem_ptr + IPS_REG_FLDP);
- if (ha->revision_id == IPS_REVID_TROMBONE64)
+ if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
udelay(25); /* 25 us */
return (1);
/* Enable reading */
writel(0, ha->mem_ptr + IPS_REG_FLAP);
- if (ha->revision_id == IPS_REVID_TROMBONE64)
+ if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
udelay(25); /* 25 us */
writeb(0xFF, ha->mem_ptr + IPS_REG_FLDP);
- if (ha->revision_id == IPS_REVID_TROMBONE64)
+ if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
udelay(25); /* 25 us */
return (0);
/* test 1st byte */
outl(0, ha->io_addr + IPS_REG_FLAP);
- if (ha->revision_id == IPS_REVID_TROMBONE64)
+ if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
udelay(25); /* 25 us */
if (inb(ha->io_addr + IPS_REG_FLDP) != 0x55)
return (1);
- outl(cpu_to_le32(1), ha->io_addr + IPS_REG_FLAP);
- if (ha->revision_id == IPS_REVID_TROMBONE64)
+ outl(1, ha->io_addr + IPS_REG_FLAP);
+ if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
udelay(25); /* 25 us */
if (inb(ha->io_addr + IPS_REG_FLDP) != 0xAA)
return (1);
checksum = 0xff;
for (i = 2; i < buffersize; i++) {
- outl(cpu_to_le32(i + offset), ha->io_addr + IPS_REG_FLAP);
- if (ha->revision_id == IPS_REVID_TROMBONE64)
+ outl(i + offset, ha->io_addr + IPS_REG_FLAP);
+ if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
udelay(25); /* 25 us */
checksum = (uint8_t) checksum + inb(ha->io_addr + IPS_REG_FLDP);
/* test 1st byte */
writel(0, ha->mem_ptr + IPS_REG_FLAP);
- if (ha->revision_id == IPS_REVID_TROMBONE64)
+ if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
udelay(25); /* 25 us */
if (readb(ha->mem_ptr + IPS_REG_FLDP) != 0x55)
return (1);
writel(1, ha->mem_ptr + IPS_REG_FLAP);
- if (ha->revision_id == IPS_REVID_TROMBONE64)
+ if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
udelay(25); /* 25 us */
if (readb(ha->mem_ptr + IPS_REG_FLDP) != 0xAA)
return (1);
for (i = 2; i < buffersize; i++) {
writel(i + offset, ha->mem_ptr + IPS_REG_FLAP);
- if (ha->revision_id == IPS_REVID_TROMBONE64)
+ if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
udelay(25); /* 25 us */
checksum =
return (0);
}
-/*---------------------------------------------------------------------------*/
-/* Routine Name: ips_version_check */
-/* */
-/* Dependencies: */
-/* Assumes that ips_read_adapter_status() is called first filling in */
-/* the data for SubSystem Parameters. */
-/* Called from ips_write_driver_status() so it also assumes NVRAM Page 5 */
-/* Data is available. */
-/* */
-/*---------------------------------------------------------------------------*/
-static void
-ips_version_check(ips_ha_t * ha, int intr)
-{
- IPS_VERSION_DATA *VersionInfo;
- uint8_t FirmwareVersion[IPS_COMPAT_ID_LENGTH + 1];
- uint8_t BiosVersion[IPS_COMPAT_ID_LENGTH + 1];
- int MatchError;
- int rc;
- char BiosString[10];
- char FirmwareString[10];
-
- METHOD_TRACE("ips_version_check", 1);
-
- VersionInfo = ( IPS_VERSION_DATA * ) ha->ioctl_data;
-
- memset(FirmwareVersion, 0, IPS_COMPAT_ID_LENGTH + 1);
- memset(BiosVersion, 0, IPS_COMPAT_ID_LENGTH + 1);
-
- /* Get the Compatible BIOS Version from NVRAM Page 5 */
- memcpy(BiosVersion, ha->nvram->BiosCompatibilityID,
- IPS_COMPAT_ID_LENGTH);
-
- rc = IPS_FAILURE;
- if (ha->subsys->param[4] & IPS_GET_VERSION_SUPPORT) { /* If Versioning is Supported */
- /* Get the Version Info with a Get Version Command */
- memset( VersionInfo, 0, sizeof (IPS_VERSION_DATA));
- rc = ips_get_version_info(ha, ha->ioctl_busaddr, intr);
- if (rc == IPS_SUCCESS)
- memcpy(FirmwareVersion, VersionInfo->compatibilityId,
- IPS_COMPAT_ID_LENGTH);
- }
-
- if (rc != IPS_SUCCESS) { /* If Data Not Obtainable from a GetVersion Command */
- /* Get the Firmware Version from Enquiry Data */
- memcpy(FirmwareVersion, ha->enq->CodeBlkVersion,
- IPS_COMPAT_ID_LENGTH);
- }
-
- /* printk(KERN_WARNING "Adapter's BIOS Version = %s\n", BiosVersion); */
- /* printk(KERN_WARNING "BIOS Compatible Version = %s\n", IPS_COMPAT_BIOS); */
- /* printk(KERN_WARNING "Adapter's Firmware Version = %s\n", FirmwareVersion); */
- /* printk(KERN_WARNING "Firmware Compatible Version = %s \n", Compatable[ ha->nvram->adapter_type ]); */
-
- MatchError = 0;
-
- if (strncmp
- (FirmwareVersion, Compatable[ha->nvram->adapter_type],
- IPS_COMPAT_ID_LENGTH) != 0)
- MatchError = 1;
-
- if (strncmp(BiosVersion, IPS_COMPAT_BIOS, IPS_COMPAT_ID_LENGTH) != 0)
- MatchError = 1;
-
- ha->nvram->versioning = 1; /* Indicate the Driver Supports Versioning */
-
- if (MatchError) {
- ha->nvram->version_mismatch = 1;
- if (ips_cd_boot == 0) {
- strncpy(&BiosString[0], ha->nvram->bios_high, 4);
- strncpy(&BiosString[4], ha->nvram->bios_low, 4);
- BiosString[8] = 0;
-
- strncpy(&FirmwareString[0], ha->enq->CodeBlkVersion, 8);
- FirmwareString[8] = 0;
-
- IPS_PRINTK(KERN_WARNING, ha->pcidev,
- "Warning ! ! ! ServeRAID Version Mismatch\n");
- IPS_PRINTK(KERN_WARNING, ha->pcidev,
- "Bios = %s, Firmware = %s, Device Driver = %s%s\n",
- BiosString, FirmwareString, IPS_VERSION_HIGH,
- IPS_VERSION_LOW);
- IPS_PRINTK(KERN_WARNING, ha->pcidev,
- "These levels should match to avoid possible compatibility problems.\n");
- }
- } else {
- ha->nvram->version_mismatch = 0;
- }
-
- return;
-}
-
-/*---------------------------------------------------------------------------*/
-/* Routine Name: ips_get_version_info */
-/* */
-/* Routine Description: */
-/* Issue an internal GETVERSION Command */
-/* */
-/* Return Value: */
-/* 0 if Successful, else non-zero */
-/*---------------------------------------------------------------------------*/
-static int
-ips_get_version_info(ips_ha_t * ha, dma_addr_t Buffer, int intr)
-{
- ips_scb_t *scb;
- int rc;
-
- METHOD_TRACE("ips_get_version_info", 1);
-
- scb = &ha->scbs[ha->max_cmds - 1];
-
- ips_init_scb(ha, scb);
-
- scb->timeout = ips_cmd_timeout;
- scb->cdb[0] = IPS_CMD_GET_VERSION_INFO;
- scb->cmd.version_info.op_code = IPS_CMD_GET_VERSION_INFO;
- scb->cmd.version_info.command_id = IPS_COMMAND_ID(ha, scb);
- scb->cmd.version_info.reserved = 0;
- scb->cmd.version_info.count = sizeof (IPS_VERSION_DATA);
- scb->cmd.version_info.reserved2 = 0;
- scb->data_len = sizeof (IPS_VERSION_DATA);
- scb->data_busaddr = Buffer;
- scb->cmd.version_info.buffer_addr = Buffer;
- scb->flags = 0;
-
- /* issue command */
- rc = ips_send_wait(ha, scb, ips_cmd_timeout, intr);
- return (rc);
-}
-
/****************************************************************************/
/* */
/* Routine Name: ips_abort_init */
}
ha = IPS_HA(sh);
memcpy(ha, oldha, sizeof (ips_ha_t));
- free_irq(oldha->irq, oldha);
+ free_irq(oldha->pcidev->irq, oldha);
/* Install the interrupt handler with the new ha */
- if (request_irq(ha->irq, do_ipsintr, SA_SHIRQ, ips_name, ha)) {
+ if (request_irq(ha->pcidev->irq, do_ipsintr, IRQF_SHARED, ips_name, ha)) {
IPS_PRINTK(KERN_WARNING, ha->pcidev,
"Unable to install interrupt handler\n");
- scsi_host_put(sh);
- return -1;
+ goto err_out_sh;
}
kfree(oldha);
- ips_sh[index] = sh;
- ips_ha[index] = ha;
- IPS_SCSI_SET_DEVICE(sh, ha);
/* Store away needed values for later use */
- sh->io_port = ha->io_addr;
- sh->n_io_port = ha->io_addr ? 255 : 0;
sh->unique_id = (ha->io_addr) ? ha->io_addr : ha->mem_addr;
- sh->irq = ha->irq;
sh->sg_tablesize = sh->hostt->sg_tablesize;
sh->can_queue = sh->hostt->can_queue;
sh->cmd_per_lun = sh->hostt->cmd_per_lun;
- sh->unchecked_isa_dma = sh->hostt->unchecked_isa_dma;
sh->use_clustering = sh->hostt->use_clustering;
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,7)
sh->max_sectors = 128;
-#endif
sh->max_id = ha->ntargets;
sh->max_lun = ha->nlun;
sh->max_channel = ha->nbus - 1;
sh->can_queue = ha->max_cmds - 1;
- IPS_ADD_HOST(sh, NULL);
+ if (scsi_add_host(sh, &ha->pcidev->dev))
+ goto err_out;
+
+ ips_sh[index] = sh;
+ ips_ha[index] = ha;
+
+ scsi_scan_host(sh);
+
return 0;
+
+err_out:
+ free_irq(ha->pcidev->irq, ha);
+err_out_sh:
+ scsi_host_put(sh);
+ return -1;
}
/*---------------------------------------------------------------------------*/
static void __devexit
ips_remove_device(struct pci_dev *pci_dev)
{
- int i;
- struct Scsi_Host *sh;
- ips_ha_t *ha;
+ struct Scsi_Host *sh = pci_get_drvdata(pci_dev);
- for (i = 0; i < IPS_MAX_ADAPTERS; i++) {
- ha = ips_ha[i];
- if (ha) {
- if ((pci_dev->bus->number == ha->pcidev->bus->number) &&
- (pci_dev->devfn == ha->pcidev->devfn)) {
- sh = ips_sh[i];
- ips_release(sh);
- }
- }
- }
+ pci_set_drvdata(pci_dev, NULL);
+
+ ips_release(sh);
+
+ pci_release_regions(pci_dev);
+ pci_disable_device(pci_dev);
}
/****************************************************************************/
static int __init
ips_module_init(void)
{
- if (pci_module_init(&ips_pci_driver) < 0)
+ if (pci_register_driver(&ips_pci_driver) < 0)
return -ENODEV;
ips_driver_template.module = THIS_MODULE;
ips_order_controllers();
- if (IPS_REGISTER_HOSTS(&ips_driver_template)) {
+ if (!ips_detect(&ips_driver_template)) {
pci_unregister_driver(&ips_pci_driver);
return -ENODEV;
}
static void __exit
ips_module_exit(void)
{
- IPS_UNREGISTER_HOSTS(&ips_driver_template);
pci_unregister_driver(&ips_pci_driver);
unregister_reboot_notifier(&ips_notifier);
}
static int __devinit
ips_insert_device(struct pci_dev *pci_dev, const struct pci_device_id *ent)
{
- int index;
+ int index = -1;
int rc;
METHOD_TRACE("ips_insert_device", 1);
- if (pci_enable_device(pci_dev))
- return -1;
+ rc = pci_enable_device(pci_dev);
+ if (rc)
+ return rc;
+
+ rc = pci_request_regions(pci_dev, "ips");
+ if (rc)
+ goto err_out;
rc = ips_init_phase1(pci_dev, &index);
if (rc == SUCCESS)
ips_num_controllers++;
ips_next_controller = ips_num_controllers;
+
+ if (rc < 0) {
+ rc = -ENODEV;
+ goto err_out_regions;
+ }
+
+ pci_set_drvdata(pci_dev, ips_sh[index]);
+ return 0;
+
+err_out_regions:
+ pci_release_regions(pci_dev);
+err_out:
+ pci_disable_device(pci_dev);
return rc;
}
uint32_t mem_addr;
uint32_t io_len;
uint32_t mem_len;
- uint8_t revision_id;
uint8_t bus;
uint8_t func;
- uint8_t irq;
- uint16_t subdevice_id;
int j;
int index;
dma_addr_t dma_address;
METHOD_TRACE("ips_init_phase1", 1);
index = IPS_MAX_ADAPTERS;
for (j = 0; j < IPS_MAX_ADAPTERS; j++) {
- if (ips_ha[j] == 0) {
+ if (ips_ha[j] == NULL) {
index = j;
break;
}
return -1;
/* stuff that we get in dev */
- irq = pci_dev->irq;
bus = pci_dev->bus->number;
func = pci_dev->devfn;
uint32_t base;
uint32_t offs;
- if (!request_mem_region(mem_addr, mem_len, "ips")) {
- IPS_PRINTK(KERN_WARNING, pci_dev,
- "Couldn't allocate IO Memory space %x len %d.\n",
- mem_addr, mem_len);
- return -1;
- }
-
base = mem_addr & PAGE_MASK;
offs = mem_addr - base;
ioremap_ptr = ioremap(base, PAGE_SIZE);
+ if (!ioremap_ptr)
+ return -1;
mem_ptr = ioremap_ptr + offs;
} else {
ioremap_ptr = NULL;
mem_ptr = NULL;
}
- /* setup I/O mapped area (if applicable) */
- if (io_addr) {
- if (!request_region(io_addr, io_len, "ips")) {
- IPS_PRINTK(KERN_WARNING, pci_dev,
- "Couldn't allocate IO space %x len %d.\n",
- io_addr, io_len);
- return -1;
- }
- }
-
- /* get the revision ID */
- if (pci_read_config_byte(pci_dev, PCI_REVISION_ID, &revision_id)) {
- IPS_PRINTK(KERN_WARNING, pci_dev, "Can't get revision id.\n");
- return -1;
- }
-
- subdevice_id = pci_dev->subsystem_device;
-
/* found a controller */
- ha = kmalloc(sizeof (ips_ha_t), GFP_KERNEL);
+ ha = kzalloc(sizeof (ips_ha_t), GFP_KERNEL);
if (ha == NULL) {
IPS_PRINTK(KERN_WARNING, pci_dev,
"Unable to allocate temporary ha struct\n");
return -1;
}
- memset(ha, 0, sizeof (ips_ha_t));
-
ips_sh[index] = NULL;
ips_ha[index] = ha;
ha->active = 1;
/* Store info in HA structure */
- ha->irq = irq;
ha->io_addr = io_addr;
ha->io_len = io_len;
ha->mem_addr = mem_addr;
ha->mem_ptr = mem_ptr;
ha->ioremap_ptr = ioremap_ptr;
ha->host_num = (uint32_t) index;
- ha->revision_id = revision_id;
ha->slot_num = PCI_SLOT(pci_dev->devfn);
- ha->device_id = pci_dev->device;
- ha->subdevice_id = subdevice_id;
ha->pcidev = pci_dev;
/*
* are guaranteed to be < 4G.
*/
if (IPS_ENABLE_DMA64 && IPS_HAS_ENH_SGLIST(ha) &&
- !pci_set_dma_mask(ha->pcidev, 0xffffffffffffffffULL)) {
+ !pci_set_dma_mask(ha->pcidev, DMA_BIT_MASK(64))) {
(ha)->flags |= IPS_HA_ENH_SG;
} else {
- if (pci_set_dma_mask(ha->pcidev, 0xffffffffULL) != 0) {
+ if (pci_set_dma_mask(ha->pcidev, DMA_BIT_MASK(32)) != 0) {
printk(KERN_WARNING "Unable to set DMA Mask\n");
return ips_abort_init(ha, index);
}
}
/* Install the interrupt handler */
- if (request_irq(ha->irq, do_ipsintr, SA_SHIRQ, ips_name, ha)) {
+ if (request_irq(ha->pcidev->irq, do_ipsintr, IRQF_SHARED, ips_name, ha)) {
IPS_PRINTK(KERN_WARNING, ha->pcidev,
"Unable to install interrupt handler\n");
return ips_abort_init(ha, index);
if (!ips_allocatescbs(ha)) {
IPS_PRINTK(KERN_WARNING, ha->pcidev,
"Unable to allocate a CCB\n");
- free_irq(ha->irq, ha);
+ free_irq(ha->pcidev->irq, ha);
return ips_abort_init(ha, index);
}
if (!ips_hainit(ha)) {
IPS_PRINTK(KERN_WARNING, ha->pcidev,
"Unable to initialize controller\n");
- free_irq(ha->irq, ha);
+ free_irq(ha->pcidev->irq, ha);
return ips_abort_init(ha, index);
}
/* Free the temporary SCB */
if (!ips_allocatescbs(ha)) {
IPS_PRINTK(KERN_WARNING, ha->pcidev,
"Unable to allocate CCBs\n");
- free_irq(ha->irq, ha);
+ free_irq(ha->pcidev->irq, ha);
return ips_abort_init(ha, index);
}
return SUCCESS;
}
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,9)
MODULE_LICENSE("GPL");
-#endif
-
MODULE_DESCRIPTION("IBM ServeRAID Adapter Driver " IPS_VER_STRING);
-
-#ifdef MODULE_VERSION
MODULE_VERSION(IPS_VER_STRING);
-#endif
/*