#include <scsi/scsicam.h>
#include "scsi.h"
-#include "hosts.h"
+#include <scsi/scsi_host.h>
#include "megaraid.h"
return 0;
}
+/**
+ * mega_runpendq()
+ * @adapter - pointer to our soft state
+ *
+ * Runs through the list of pending requests.
+ */
+static inline void
+mega_runpendq(adapter_t *adapter)
+{
+ if(!list_empty(&adapter->pending_list))
+ __mega_runpendq(adapter);
+}
/*
* megaraid_queue()
return busy;
}
+/**
+ * mega_allocate_scb()
+ * @adapter - pointer to our soft state
+ * @cmd - scsi command from the mid-layer
+ *
+ * Allocate a SCB structure. This is the central structure for controller
+ * commands.
+ */
+static inline scb_t *
+mega_allocate_scb(adapter_t *adapter, Scsi_Cmnd *cmd)
+{
+ struct list_head *head = &adapter->free_list;
+ scb_t *scb;
+
+ /* Unlink command from Free List */
+ if( !list_empty(head) ) {
+
+ scb = list_entry(head->next, scb_t, list);
+
+ list_del_init(head->next);
+
+ scb->state = SCB_ACTIVE;
+ scb->cmd = cmd;
+ scb->dma_type = MEGA_DMA_TYPE_NONE;
+
+ return scb;
+ }
+
+ return NULL;
+}
+
+/**
+ * mega_get_ldrv_num()
+ * @adapter - pointer to our soft state
+ * @cmd - scsi mid layer command
+ * @channel - channel on the controller
+ *
+ * Calculate the logical drive number based on the information in scsi command
+ * and the channel number.
+ */
+static inline int
+mega_get_ldrv_num(adapter_t *adapter, Scsi_Cmnd *cmd, int channel)
+{
+ int tgt;
+ int ldrv_num;
+
+ tgt = cmd->device->id;
+
+ if ( tgt > adapter->this_id )
+ tgt--; /* we do not get inquires for initiator id */
+
+ ldrv_num = (channel * 15) + tgt;
+
+
+ /*
+ * If we have a logical drive with boot enabled, project it first
+ */
+ if( adapter->boot_ldrv_enabled ) {
+ if( ldrv_num == 0 ) {
+ ldrv_num = adapter->boot_ldrv;
+ }
+ else {
+ if( ldrv_num <= adapter->boot_ldrv ) {
+ ldrv_num--;
+ }
+ }
+ }
+
+ /*
+ * If "delete logical drive" feature is enabled on this controller.
+ * Do only if at least one delete logical drive operation was done.
+ *
+ * Also, after logical drive deletion, instead of logical drive number,
+ * the value returned should be 0x80+logical drive id.
+ *
+ * These is valid only for IO commands.
+ */
+
+ if (adapter->support_random_del && adapter->read_ldidmap )
+ switch (cmd->cmnd[0]) {
+ case READ_6: /* fall through */
+ case WRITE_6: /* fall through */
+ case READ_10: /* fall through */
+ case WRITE_10:
+ ldrv_num += 0x80;
+ }
+
+ return ldrv_num;
+}
/**
* mega_build_cmd()
return epthru;
}
-
-/**
- * mega_allocate_scb()
- * @adapter - pointer to our soft state
- * @cmd - scsi command from the mid-layer
- *
- * Allocate a SCB structure. This is the central structure for controller
- * commands.
- */
-static inline scb_t *
-mega_allocate_scb(adapter_t *adapter, Scsi_Cmnd *cmd)
-{
- struct list_head *head = &adapter->free_list;
- scb_t *scb;
-
- /* Unlink command from Free List */
- if( !list_empty(head) ) {
-
- scb = list_entry(head->next, scb_t, list);
-
- list_del_init(head->next);
-
- scb->state = SCB_ACTIVE;
- scb->cmd = cmd;
- scb->dma_type = MEGA_DMA_TYPE_NONE;
-
- return scb;
- }
-
- return NULL;
-}
-
-
-/**
- * mega_runpendq()
- * @adapter - pointer to our soft state
- *
- * Runs through the list of pending requests.
- */
-static inline void
-mega_runpendq(adapter_t *adapter)
-{
- if(!list_empty(&adapter->pending_list))
- __mega_runpendq(adapter);
-}
-
static void
__mega_runpendq(adapter_t *adapter)
{
* busy. We also take the scb from the pending list if the mailbox is
* available.
*/
-static inline int
+static int
issue_scb(adapter_t *adapter, scb_t *scb)
{
volatile mbox64_t *mbox64 = adapter->mbox64;
return 0;
}
+/*
+ * Wait until the controller's mailbox is available
+ */
+static inline int
+mega_busywait_mbox (adapter_t *adapter)
+{
+ if (adapter->mbox->m_in.busy)
+ return __mega_busywait_mbox(adapter);
+ return 0;
+}
/**
* issue_scb_block()
*
* Complete the comamnds and call the scsi mid-layer callback hooks.
*/
-static inline void
+static void
mega_cmd_done(adapter_t *adapter, u8 completed[], int nstatus, int status)
{
mega_ext_passthru *epthru = NULL;
}
-/*
- * Wait until the controller's mailbox is available
- */
-static inline int
-mega_busywait_mbox (adapter_t *adapter)
-{
- if (adapter->mbox->m_in.busy)
- return __mega_busywait_mbox(adapter);
- return 0;
-}
-
static int
__mega_busywait_mbox (adapter_t *adapter)
{
return FALSE;
}
+static inline int
+make_local_pdev(adapter_t *adapter, struct pci_dev **pdev)
+{
+ *pdev = kmalloc(sizeof(struct pci_dev), GFP_KERNEL);
+
+ if( *pdev == NULL ) return -1;
+
+ memcpy(*pdev, adapter->dev, sizeof(struct pci_dev));
+
+ if( pci_set_dma_mask(*pdev, 0xffffffff) != 0 ) {
+ kfree(*pdev);
+ return -1;
+ }
+
+ return 0;
+}
+
+static inline void
+free_local_pdev(struct pci_dev *pdev)
+{
+ kfree(pdev);
+}
+
+/**
+ * mega_allocate_inquiry()
+ * @dma_handle - handle returned for dma address
+ * @pdev - handle to pci device
+ *
+ * allocates memory for inquiry structure
+ */
+static inline void *
+mega_allocate_inquiry(dma_addr_t *dma_handle, struct pci_dev *pdev)
+{
+ return pci_alloc_consistent(pdev, sizeof(mega_inquiry3), dma_handle);
+}
+
+
+static inline void
+mega_free_inquiry(void *inquiry, dma_addr_t dma_handle, struct pci_dev *pdev)
+{
+ pci_free_consistent(pdev, sizeof(mega_inquiry3), inquiry, dma_handle);
+}
+
#ifdef CONFIG_PROC_FS
/* Following code handles /proc fs */
nitioctl_t uioc;
int adapno;
int rval;
- mega_passthru *upthru; /* user address for passthru */
+ mega_passthru __user *upthru; /* user address for passthru */
mega_passthru *pthru; /* copy user passthru here */
dma_addr_t pthru_dma_hndl;
void *data = NULL; /* data to be transferred */
dma_addr_t data_dma_hndl; /* dma handle for data xfer area */
megacmd_t mc;
- megastat_t *ustats;
+ megastat_t __user *ustats;
int num_ldrv;
u32 uxferaddr = 0;
struct pci_dev *pdev;
* addresses.
*/
memset(&uioc, 0, sizeof(nitioctl_t));
- if( (rval = mega_m_to_n( (void *)arg, &uioc)) != 0 )
+ if( (rval = mega_m_to_n( (void __user *)arg, &uioc)) != 0 )
return rval;
switch( uioc.opcode ) {
case GET_DRIVER_VER:
- if( put_user(driver_ver, (u32 *)uioc.uioc_uaddr) )
+ if( put_user(driver_ver, (u32 __user *)uioc.uioc_uaddr) )
return (-EFAULT);
break;
case GET_N_ADAP:
- if( put_user(hba_count, (u32 *)uioc.uioc_uaddr) )
+ if( put_user(hba_count, (u32 __user *)uioc.uioc_uaddr) )
return (-EFAULT);
/*
adapter = hba_soft_state[adapno];
- ustats = (megastat_t *)uioc.uioc_uaddr;
+ ustats = uioc.uioc_uaddr;
if( copy_from_user(&num_ldrv, &ustats->num_ldrv, sizeof(int)) )
return (-EFAULT);
mc.status = rval;
- rval = mega_n_to_m((void *)arg, &mc);
+ rval = mega_n_to_m((void __user *)arg, &mc);
}
return rval;
/*
* The user passthru structure
*/
- upthru = (mega_passthru *)MBOX(uioc)->xferaddr;
+ upthru = (mega_passthru __user *)MBOX(uioc)->xferaddr;
/*
* Copy in the user passthru here.
*/
- if( copy_from_user(pthru, (char *)upthru,
+ if( copy_from_user(pthru, upthru,
sizeof(mega_passthru)) ) {
pci_free_consistent(pdev,
/*
* Get the user data
*/
- if( copy_from_user(data, (char *)uxferaddr,
+ if( copy_from_user(data, (char __user *)uxferaddr,
pthru->dataxferlen) ) {
rval = (-EFAULT);
goto freemem_and_return;
*/
mega_internal_command(adapter, LOCK_INT, &mc, pthru);
- rval = mega_n_to_m((void *)arg, &mc);
+ rval = mega_n_to_m((void __user *)arg, &mc);
if( rval ) goto freemem_and_return;
* Is data going up-stream
*/
if( pthru->dataxferlen && (uioc.flags & UIOC_RD) ) {
- if( copy_to_user((char *)uxferaddr, data,
+ if( copy_to_user((char __user *)uxferaddr, data,
pthru->dataxferlen) ) {
rval = (-EFAULT);
}
/*
* Get the user data
*/
- if( copy_from_user(data, (char *)uxferaddr,
+ if( copy_from_user(data, (char __user *)uxferaddr,
uioc.xferlen) ) {
pci_free_consistent(pdev,
*/
mega_internal_command(adapter, LOCK_INT, &mc, NULL);
- rval = mega_n_to_m((void *)arg, &mc);
+ rval = mega_n_to_m((void __user *)arg, &mc);
if( rval ) {
if( uioc.xferlen ) {
* Is data going up-stream
*/
if( uioc.xferlen && (uioc.flags & UIOC_RD) ) {
- if( copy_to_user((char *)uxferaddr, data,
+ if( copy_to_user((char __user *)uxferaddr, data,
uioc.xferlen) ) {
rval = (-EFAULT);
* Converts the older mimd ioctl structure to newer NIT structure
*/
static int
-mega_m_to_n(void *arg, nitioctl_t *uioc)
+mega_m_to_n(void __user *arg, nitioctl_t *uioc)
{
struct uioctl_t uioc_mimd;
char signature[8] = {0};
* begining of the structure.
*/
- if( copy_from_user(signature, (char *)arg, 7) )
+ if( copy_from_user(signature, arg, 7) )
return (-EFAULT);
if( memcmp(signature, "MEGANIT", 7) == 0 ) {
*/
return -EINVAL;
#if 0
- if( copy_from_user(uioc, (char *)arg, sizeof(nitioctl_t)) )
+ if( copy_from_user(uioc, arg, sizeof(nitioctl_t)) )
return (-EFAULT);
return 0;
#endif
*
* Get the user ioctl structure
*/
- if( copy_from_user(&uioc_mimd, (char *)arg, sizeof(struct uioctl_t)) )
+ if( copy_from_user(&uioc_mimd, arg, sizeof(struct uioctl_t)) )
return (-EFAULT);
* conforms to older mimd ioctl interface or newer NIT ioctl interface
*/
static int
-mega_n_to_m(void *arg, megacmd_t *mc)
+mega_n_to_m(void __user *arg, megacmd_t *mc)
{
- nitioctl_t *uiocp;
- megacmd_t *umc;
- mega_passthru *upthru;
- struct uioctl_t *uioc_mimd;
+ nitioctl_t __user *uiocp;
+ megacmd_t __user *umc;
+ mega_passthru __user *upthru;
+ struct uioctl_t __user *uioc_mimd;
char signature[8] = {0};
/*
* check is the application conforms to NIT.
*/
- if( copy_from_user(signature, (char *)arg, 7) )
+ if( copy_from_user(signature, arg, 7) )
return -EFAULT;
if( memcmp(signature, "MEGANIT", 7) == 0 ) {
- uiocp = (nitioctl_t *)arg;
+ uiocp = arg;
- if( put_user(mc->status, (u8 *)&MBOX_P(uiocp)->status) )
+ if( put_user(mc->status, (u8 __user *)&MBOX_P(uiocp)->status) )
return (-EFAULT);
if( mc->cmd == MEGA_MBOXCMD_PASSTHRU ) {
umc = MBOX_P(uiocp);
- upthru = (mega_passthru *)umc->xferaddr;
+ if (get_user(upthru, (mega_passthru __user * __user *)&umc->xferaddr))
+ return -EFAULT;
- if( put_user(mc->status, (u8 *)&upthru->scsistatus) )
+ if( put_user(mc->status, (u8 __user *)&upthru->scsistatus))
return (-EFAULT);
}
}
else {
- uioc_mimd = (struct uioctl_t *)arg;
+ uioc_mimd = arg;
- if( put_user(mc->status, (u8 *)&uioc_mimd->mbox[17]) )
+ if( put_user(mc->status, (u8 __user *)&uioc_mimd->mbox[17]) )
return (-EFAULT);
if( mc->cmd == MEGA_MBOXCMD_PASSTHRU ) {
- umc = (megacmd_t *)uioc_mimd->mbox;
+ umc = (megacmd_t __user *)uioc_mimd->mbox;
- upthru = (mega_passthru *)umc->xferaddr;
+ if (get_user(upthru, (mega_passthru __user * __user *)&umc->xferaddr))
+ return (-EFAULT);
- if( put_user(mc->status, (u8 *)&upthru->scsistatus) )
+ if( put_user(mc->status, (u8 __user *)&upthru->scsistatus) )
return (-EFAULT);
}
}
static int
mega_del_logdrv(adapter_t *adapter, int logdrv)
{
- DECLARE_WAIT_QUEUE_HEAD(wq);
unsigned long flags;
scb_t *scb;
int rval;
* Wait till all the issued commands are complete and there are no
* commands in the pending queue
*/
- while( atomic_read(&adapter->pend_cmds) > 0 ||
- !list_empty(&adapter->pending_list) ) {
-
- sleep_on_timeout( &wq, 1*HZ ); /* sleep for 1s */
- }
+ while (atomic_read(&adapter->pend_cmds) > 0 ||
+ !list_empty(&adapter->pending_list))
+ msleep(1000); /* sleep for 1s */
rval = mega_do_del_logdrv(adapter, logdrv);
}
-
-/**
- * mega_get_ldrv_num()
- * @adapter - pointer to our soft state
- * @cmd - scsi mid layer command
- * @channel - channel on the controller
- *
- * Calculate the logical drive number based on the information in scsi command
- * and the channel number.
- */
-static inline int
-mega_get_ldrv_num(adapter_t *adapter, Scsi_Cmnd *cmd, int channel)
-{
- int tgt;
- int ldrv_num;
-
- tgt = cmd->device->id;
-
- if ( tgt > adapter->this_id )
- tgt--; /* we do not get inquires for initiator id */
-
- ldrv_num = (channel * 15) + tgt;
-
-
- /*
- * If we have a logical drive with boot enabled, project it first
- */
- if( adapter->boot_ldrv_enabled ) {
- if( ldrv_num == 0 ) {
- ldrv_num = adapter->boot_ldrv;
- }
- else {
- if( ldrv_num <= adapter->boot_ldrv ) {
- ldrv_num--;
- }
- }
- }
-
- /*
- * If "delete logical drive" feature is enabled on this controller.
- * Do only if at least one delete logical drive operation was done.
- *
- * Also, after logical drive deletion, instead of logical drive number,
- * the value returned should be 0x80+logical drive id.
- *
- * These is valid only for IO commands.
- */
-
- if (adapter->support_random_del && adapter->read_ldidmap )
- switch (cmd->cmnd[0]) {
- case READ_6: /* fall through */
- case WRITE_6: /* fall through */
- case READ_10: /* fall through */
- case WRITE_10:
- ldrv_num += 0x80;
- }
-
- return ldrv_num;
-}
-
-
/**
* mega_adapinq()
* @adapter - pointer to our soft state
}
-/**
- * mega_allocate_inquiry()
- * @dma_handle - handle returned for dma address
- * @pdev - handle to pci device
- *
- * allocates memory for inquiry structure
- */
-static inline caddr_t
-mega_allocate_inquiry(dma_addr_t *dma_handle, struct pci_dev *pdev)
-{
- return pci_alloc_consistent(pdev, sizeof(mega_inquiry3), dma_handle);
-}
-
-
-static inline void
-mega_free_inquiry(caddr_t inquiry, dma_addr_t dma_handle, struct pci_dev *pdev)
-{
- pci_free_consistent(pdev, sizeof(mega_inquiry3), inquiry, dma_handle);
-}
-
-
/** mega_internal_dev_inquiry()
* @adapter - pointer to our soft state
* @ch - channel for this device
}
-static inline int
-make_local_pdev(adapter_t *adapter, struct pci_dev **pdev)
-{
- *pdev = kmalloc(sizeof(struct pci_dev), GFP_KERNEL);
-
- if( *pdev == NULL ) return -1;
-
- memcpy(*pdev, adapter->dev, sizeof(struct pci_dev));
-
- if( pci_set_dma_mask(*pdev, 0xffffffff) != 0 ) {
- kfree(*pdev);
- return -1;
- }
-
- return 0;
-}
-
-static inline void
-free_local_pdev(struct pci_dev *pdev)
-{
- kfree(pdev);
-}
-
static struct scsi_host_template megaraid_template = {
.module = THIS_MODULE,
.name = "MegaRAID",
pci_bus = pdev->bus->number;
pci_dev_func = pdev->devfn;
+ /*
+ * The megaraid3 stuff reports the ID of the Intel part which is not
+ * remotely specific to the megaraid
+ */
+ if (pdev->vendor == PCI_VENDOR_ID_INTEL) {
+ u16 magic;
+ /*
+ * Don't fall over the Compaq management cards using the same
+ * PCI identifier
+ */
+ if (pdev->subsystem_vendor == PCI_VENDOR_ID_COMPAQ &&
+ pdev->subsystem_device == 0xC000)
+ return -ENODEV;
+ /* Now check the magic signature byte */
+ pci_read_config_word(pdev, PCI_CONF_AMISIG, &magic);
+ if (magic != HBA_SIGNATURE_471 && magic != HBA_SIGNATURE)
+ return -ENODEV;
+ /* Ok it is probably a megaraid */
+ }
+
/*
* For these vendor and device ids, signature offsets are not
* valid and 64 bit is implicit