patch-2.4.21 linux-2.4.21/drivers/scsi/megaraid.c
Next file: linux-2.4.21/drivers/scsi/megaraid.h
Previous file: linux-2.4.21/drivers/scsi/mac_scsi.h
Back to the patch index
Back to the overall index
- Lines: 1015
- Date:
2003-06-13 07:51:36.000000000 -0700
- Orig file:
linux-2.4.20/drivers/scsi/megaraid.c
- Orig date:
2002-11-28 15:53:14.000000000 -0800
diff -urN linux-2.4.20/drivers/scsi/megaraid.c linux-2.4.21/drivers/scsi/megaraid.c
@@ -2,14 +2,14 @@
*
* Linux MegaRAID device driver
*
- * Copyright 2001 American Megatrends Inc.
+ * Copyright 2001 LSI Logic Corporation.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*
- * Version : v1.18 (Oct 11, 2001)
+ * Version : v1.18f (Dec 10, 2002)
*
* Description: Linux device driver for LSI Logic MegaRAID controller
*
@@ -459,6 +459,58 @@
*
* References to AMI have been changed to LSI Logic.
*
+ * Version 1.18a
+ * Mon Mar 11 11:38:38 EST 2002 - Atul Mukker <Atul.Mukker@lsil.com>
+ *
+ * RAID On MotherBoard (ROMB) - boot from logical or physical drives
+ *
+ * Support added for discovery(ROMB) vendor and device ids.
+ *
+ * Data transfer length for passthru commands must be valid even if the
+ * command has an associated scatter-gather list.
+ *
+ *
+ * Version 1.18b
+ * Tue Apr 23 11:01:58 EDT 2002 - Atul Mukker <Atul.Mukker@lsil.com>
+ *
+ * typo corrected for scsi condition CHECK_CONDITION in mega_cmd_done()
+ *
+ * Support added for PCI_VENDOR_ID_LSI_LOGIC with device id
+ * PCI_DEVICE_ID_AMI_MEGARAID3.
+ *
+ *
+ * Version 1.18c
+ * Thu May 16 10:27:55 EDT 2002 - Atul Mukker <Atul.Mukker@lsil.com>
+ *
+ * Retrun valid return status for mega passthru commands resulting in
+ * contingent allegiance condition. Check for 64-bit passthru commands also.
+ *
+ * Do not check_region() anymore and check for return value of
+ * request_region()
+ *
+ * Send valid sense data to appliations using the private ioctl interface.
+ *
+ *
+ * Version 1.18d
+ * Wed Aug 7 18:51:51 EDT 2002 - Atul Mukker <atul.mukker@lsil.com>
+ *
+ * Added support for yellowstone and verde controller
+ *
+ * Version 1.18e
+ * Mon Nov 18 12:11:02 EST 2002 - Atul Mukker <atul.mukker@lsil.com>
+ *
+ * Don't use virt_to_bus in mega_register_mailbox when you've got the DMA
+ * address already. Submitted by Jens Axboe and is included in SuSE Linux
+ * Enterprise Server 7.
+ *
+ * s/pcibios_read_config/pci_read_config - Matt Domsch <mdomsch@dell.com>
+ *
+ * remove an unsed variable
+ *
+ * Version 1.18f
+ * Tue Dec 10 09:54:39 EST 2002 - Atul Mukker <atul.mukker@lsil.com>
+ *
+ * remove GFP_DMA flag for ioctl. This was causing overrun of DMA buffers.
*
* BUGS:
* Some older 2.1 kernels (eg. 2.1.90) have a bug in pci.c that
@@ -772,7 +824,7 @@
static struct mcontroller mcontroller[MAX_CONTROLLERS];
/* The current driver version */
-static u32 driver_ver = 114;
+static u32 driver_ver = 0x118C;
/* major number used by the device for character interface */
static int major;
@@ -795,8 +847,7 @@
extern struct proc_dir_entry proc_root;
#endif
-static char mega_ch_class; /* channels are raid or scsi */
-#define IS_RAID_CH(ch) ( (mega_ch_class >> (ch)) & 0x01 )
+#define IS_RAID_CH(this, ch) ( (this->mega_ch_class >> (ch)) & 0x01 )
#if SERDEBUG
static char strbuf[MAX_SERBUF + 1];
@@ -1076,11 +1127,14 @@
panic(KERN_ERR "megaraid:Problem...!\n");
}
+#if 0
islogical = ( (SCpnt->channel >= megaCfg->productInfo.SCSIChanPresent) &&
(SCpnt->channel <= megaCfg->host->max_channel) );
+#endif
#if 0
islogical = (SCpnt->channel == megaCfg->host->max_channel);
#endif
+ islogical = megaCfg->logdrv_chan[SCpnt->channel];
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
/* Special Case to handle PassThrough->XferAddrress > 4GB */
@@ -1117,7 +1171,7 @@
status = 0xF0;
}
#endif
- if( IS_RAID_CH(SCpnt->channel) && ((c & 0x1F ) == TYPE_DISK) ) {
+ if(IS_RAID_CH(megaCfg, SCpnt->channel) && ((c & 0x1F) == TYPE_DISK)) {
status = 0xF0;
}
}
@@ -1126,7 +1180,7 @@
/* clear result; otherwise, success returns corrupt value */
SCpnt->result = 0;
- if ((SCpnt->cmnd[0] & M_RD_IOCTL_CMD)) { /* i.e. ioctl cmd such as M_RD_IOCTL_CMD, M_RD_IOCTL_CMD_NEW of megamgr */
+ if ( 0 && SCpnt->cmnd[0] & M_RD_IOCTL_CMD ) { /* i.e. ioctl cmd such as M_RD_IOCTL_CMD, M_RD_IOCTL_CMD_NEW of megamgr */
switch (status) {
case 2:
case 0xF0:
@@ -1146,18 +1200,21 @@
case 0x02: /* ERROR_ABORTED, i.e. SCSI_STATUS_CHECK_CONDITION */
/*set sense_buffer and result fields */
- if (mbox->cmd == MEGA_MBOXCMD_PASSTHRU) {
+ if (mbox->cmd == MEGA_MBOXCMD_PASSTHRU || mbox->cmd ==
+ MEGA_MBOXCMD_PASSTHRU64 ) {
+
memcpy (SCpnt->sense_buffer, pthru->reqsensearea, 14);
+
+ SCpnt->result = (DRIVER_SENSE << 24) | (DID_OK << 16) |
+ (CHECK_CONDITION << 1);
+
} else if (mbox->cmd == MEGA_MBOXCMD_EXTPASSTHRU) {
- SCpnt->result = (DRIVER_SENSE << 24) | (DID_OK << 16) | (CHECK_CONDITION << 1);
- memcpy(
- SCpnt->sense_buffer,
- epthru->reqsensearea, 14
- );
- SCpnt->result = (DRIVER_SENSE << 24) | (DID_OK << 16) | (CHECK_CONDITION << 1);
- /*SCpnt->result =
- (DRIVER_SENSE << 24) |
- (DID_ERROR << 16) | status;*/
+
+ memcpy( SCpnt->sense_buffer, epthru->reqsensearea, 14);
+
+ SCpnt->result = (DRIVER_SENSE << 24) | (DID_OK << 16) |
+ (CHECK_CONDITION << 1);
+
} else {
SCpnt->sense_buffer[0] = 0x70;
SCpnt->sense_buffer[2] = ABORTED_COMMAND;
@@ -1204,8 +1261,10 @@
mega_ext_passthru *epthru;
long seg;
char islogical;
- int lun = SCpnt->lun;
- int max_lun;
+ int max_ldrv_num;
+ int channel = 0;
+ int target = 0;
+ int ldrv_num = 0; /* logical drive number */
if ((SCpnt->cmnd[0] == MEGADEVIOC))
return megadev_doioctl (megaCfg, SCpnt);
@@ -1222,15 +1281,61 @@
}
#endif
+#if 0
islogical = ( (SCpnt->channel >= megaCfg->productInfo.SCSIChanPresent) &&
(SCpnt->channel <= megaCfg->host->max_channel) );
+#endif
#if 0
islogical = (IS_RAID_CH(SCpnt->channel) && /* virtual ch is raid - AM */
(SCpnt->channel == megaCfg->host->max_channel));
#endif
+ /*
+ * We know on what channels are our logical drives - mega_findCard()
+ */
+ islogical = megaCfg->logdrv_chan[SCpnt->channel];
+
+ /*
+ * The theory: If physical drive is chosen for boot, all the physical
+ * devices are exported before the logical drives, otherwise physical
+ * devices are pushed after logical drives, in which case - Kernel sees
+ * the physical devices on virtual channel which is obviously converted
+ * to actual channel on the HBA.
+ */
+ if( megaCfg->boot_pdrv_enabled ) {
+ if( islogical ) {
+ /* logical channel */
+ channel = SCpnt->channel - megaCfg->productInfo.SCSIChanPresent;
+ }
+ else {
+ channel = SCpnt->channel; /* this is physical channel */
+ target = SCpnt->target;
+
+ /*
+ * boot from a physical disk, that disk needs to be exposed first
+ * IF both the channels are SCSI, then booting from the second
+ * channel is not allowed.
+ */
+ if( target == 0 ) {
+ target = megaCfg->boot_pdrv_tgt;
+ }
+ else if( target == megaCfg->boot_pdrv_tgt ) {
+ target = 0;
+ }
+ }
+ }
+ else {
+ if( islogical ) {
+ channel = SCpnt->channel; /* this is the logical channel */
+ }
+ else {
+ channel = SCpnt->channel - NVIRT_CHAN; /* physical channel */
+ target = SCpnt->target;
+ }
+ }
+
if ( ! megaCfg->support_ext_cdb ) {
- if (!islogical && lun != 0) {
+ if (!islogical && SCpnt->lun != 0) {
SCpnt->result = (DID_BAD_TARGET << 16);
callDone (SCpnt);
return NULL;
@@ -1252,39 +1357,26 @@
return NULL;
}
- lun = mega_get_lun(megaCfg, SCpnt);
+ ldrv_num = mega_get_ldrv_num(megaCfg, SCpnt, channel);
- max_lun = (megaCfg->flag & BOARD_40LD) ?
+ max_ldrv_num = (megaCfg->flag & BOARD_40LD) ?
FC_MAX_LOGICAL_DRIVES : MAX_LOGICAL_DRIVES;
/*
- * max_lun increases by 0x80 if some logical drive was deleted.
+ * max_ldrv_num increases by 0x80 if some logical drive was deleted.
*/
if(megaCfg->read_ldidmap) {
- max_lun += 0x80;
+ max_ldrv_num += 0x80;
}
- if( lun > max_lun ) {
+ if( ldrv_num > max_ldrv_num ) {
SCpnt->result = (DID_BAD_TARGET << 16);
callDone (SCpnt);
return NULL;
}
- /*
- * If we have a logical drive with boot enabled, project it first
- */
- if( megaCfg->boot_ldrv_enabled ) {
- if( lun == 0 ) {
- lun = megaCfg->boot_ldrv;
- }
- else {
- if( lun <= megaCfg->boot_ldrv ) {
- lun--;
- }
- }
- }
} else {
- if ( lun > 7) {
+ if ( SCpnt->lun > 7) {
/* Do not support lun >7 for physically accessed devices */
SCpnt->result = (DID_BAD_TARGET << 16);
callDone (SCpnt);
@@ -1312,6 +1404,14 @@
case READ_CAPACITY:
case INQUIRY:
+ if(!(megaCfg->flag & (1L << SCpnt->channel))) {
+ printk(KERN_NOTICE
+ "scsi%d: scanning virtual channel %d for logical drives.\n",
+ megaCfg->host->host_no, channel);
+
+ megaCfg->flag |= (1L << SCpnt->channel);
+ }
+
/* Allocate a SCB and initialize passthru */
if ((pScb = mega_allocateSCB (megaCfg, SCpnt)) == NULL) {
SCpnt->result = (DID_ERROR << 16);
@@ -1331,7 +1431,7 @@
pthru->ars = 1;
pthru->reqsenselen = 14;
pthru->islogical = 1;
- pthru->logdrv = lun;
+ pthru->logdrv = ldrv_num;
pthru->cdblen = SCpnt->cmd_len;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
@@ -1386,7 +1486,7 @@
mbox = (mega_mailbox *) & pScb->mboxData;
memset (mbox, 0, sizeof (pScb->mboxData));
- mbox->logdrv = lun;
+ mbox->logdrv = ldrv_num;
if (megaCfg->flag & BOARD_64BIT) {
mbox->cmd = (*SCpnt->cmnd == READ_6
@@ -1410,12 +1510,12 @@
mbox->lba &= 0x1FFFFF;
if (*SCpnt->cmnd == READ_6) {
- megaCfg->nReads[(int) lun]++;
- megaCfg->nReadBlocks[(int) lun] +=
+ megaCfg->nReads[(int)ldrv_num]++;
+ megaCfg->nReadBlocks[(int)ldrv_num] +=
mbox->numsectors;
} else {
- megaCfg->nWrites[(int) lun]++;
- megaCfg->nWriteBlocks[(int) lun] +=
+ megaCfg->nWrites[(int)ldrv_num]++;
+ megaCfg->nWriteBlocks[(int)ldrv_num] +=
mbox->numsectors;
}
}
@@ -1432,12 +1532,12 @@
(u32) SCpnt->cmnd[5];
if (*SCpnt->cmnd == READ_10) {
- megaCfg->nReads[(int) lun]++;
- megaCfg->nReadBlocks[(int) lun] +=
+ megaCfg->nReads[(int)ldrv_num]++;
+ megaCfg->nReadBlocks[(int)ldrv_num] +=
mbox->numsectors;
} else {
- megaCfg->nWrites[(int) lun]++;
- megaCfg->nWriteBlocks[(int) lun] +=
+ megaCfg->nWrites[(int)ldrv_num]++;
+ megaCfg->nWriteBlocks[(int)ldrv_num] +=
mbox->numsectors;
}
}
@@ -1457,12 +1557,12 @@
(u32) SCpnt->cmnd[9];
if (*SCpnt->cmnd == READ_12) {
- megaCfg->nReads[(int) lun]++;
- megaCfg->nReadBlocks[(int) lun] +=
+ megaCfg->nReads[(int)ldrv_num]++;
+ megaCfg->nReadBlocks[(int)ldrv_num] +=
mbox->numsectors;
} else {
- megaCfg->nWrites[(int) lun]++;
- megaCfg->nWriteBlocks[(int) lun] +=
+ megaCfg->nWrites[(int)ldrv_num]++;
+ megaCfg->nWriteBlocks[(int)ldrv_num] +=
mbox->numsectors;
}
}
@@ -1516,7 +1616,8 @@
memset (mbox, 0, sizeof (pScb->mboxData));
if ( megaCfg->support_ext_cdb && SCpnt->cmd_len > 10 ) {
- epthru = mega_prepare_extpassthru(megaCfg, pScb, SCpnt);
+ epthru = mega_prepare_extpassthru(megaCfg, pScb, SCpnt, channel,
+ target);
mbox->cmd = MEGA_MBOXCMD_EXTPASSTHRU;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
mbox->xferaddr = pScb->dma_ext_passthruhandle64;
@@ -1531,7 +1632,8 @@
#endif
}
else {
- pthru = mega_prepare_passthru(megaCfg, pScb, SCpnt);
+ pthru = mega_prepare_passthru(megaCfg, pScb, SCpnt, channel,
+ target);
/* Initialize mailbox */
mbox->cmd = MEGA_MBOXCMD_PASSTHRU;
@@ -1553,18 +1655,30 @@
}
static int
-mega_get_lun(mega_host_config *this_hba, Scsi_Cmnd *sc)
+mega_get_ldrv_num(mega_host_config *this_hba, Scsi_Cmnd *sc, int channel)
{
int tgt;
- int lun;
- int virt_chan;
+ int ldrv_num;
tgt = sc->target;
if ( tgt > 7 ) tgt--; /* we do not get inquires for tgt 7 */
- virt_chan = sc->channel - this_hba->productInfo.SCSIChanPresent;
- lun = (virt_chan * 15) + tgt;
+ ldrv_num = (channel * 15) + tgt; /* 14 targets per channel */
+
+ /*
+ * If we have a logical drive with boot enabled, project it first
+ */
+ if( this_hba->boot_ldrv_enabled ) {
+ if( ldrv_num == 0 ) {
+ ldrv_num = this_hba->boot_ldrv;
+ }
+ else {
+ if( ldrv_num <= this_hba->boot_ldrv ) {
+ ldrv_num--;
+ }
+ }
+ }
/*
* If "delete logical drive" feature is enabled on this controller.
@@ -1582,16 +1696,17 @@
case WRITE_6: /* fall through */
case READ_10: /* fall through */
case WRITE_10:
- lun += 0x80;
+ ldrv_num += 0x80;
}
}
- return lun;
+ return ldrv_num;
}
static mega_passthru *
-mega_prepare_passthru(mega_host_config *megacfg, mega_scb *scb, Scsi_Cmnd *sc)
+mega_prepare_passthru(mega_host_config *megacfg, mega_scb *scb, Scsi_Cmnd *sc,
+ int channel, int target)
{
mega_passthru *pthru;
@@ -1608,9 +1723,9 @@
pthru->ars = 1;
pthru->reqsenselen = 14;
pthru->islogical = 0;
- pthru->channel = (megacfg->flag & BOARD_40LD) ? 0 : sc->channel;
+ pthru->channel = (megacfg->flag & BOARD_40LD) ? 0 : channel;
pthru->target = (megacfg->flag & BOARD_40LD) ?
- (sc->channel << 4) | sc->target : sc->target;
+ (channel << 4) | target : target;
pthru->cdblen = sc->cmd_len;
pthru->logdrv = sc->lun;
@@ -1624,6 +1739,15 @@
switch (sc->cmnd[0]) {
case INQUIRY:
case READ_CAPACITY:
+
+ if(!(megacfg->flag & (1L << sc->channel))) {
+ printk(KERN_NOTICE
+ "scsi%d: scanning physical channel %d for devices.\n",
+ megacfg->host->host_no, channel);
+
+ megacfg->flag |= (1L << sc->channel);
+ }
+
pthru->numsgelements = 0;
pthru->dataxferaddr = scb->dma_bounce_buffer;
pthru->dataxferlen = sc->request_bufflen;
@@ -1647,7 +1771,8 @@
}
static mega_ext_passthru *
-mega_prepare_extpassthru(mega_host_config *megacfg, mega_scb *scb, Scsi_Cmnd *sc)
+mega_prepare_extpassthru(mega_host_config *megacfg, mega_scb *scb,
+ Scsi_Cmnd *sc, int channel, int target)
{
mega_ext_passthru *epthru;
@@ -1664,9 +1789,9 @@
epthru->ars = 1;
epthru->reqsenselen = 14;
epthru->islogical = 0;
- epthru->channel = (megacfg->flag & BOARD_40LD) ? 0 : sc->channel;
+ epthru->channel = (megacfg->flag & BOARD_40LD) ? 0 : channel;
epthru->target = (megacfg->flag & BOARD_40LD) ?
- (sc->channel << 4) | sc->target : sc->target;
+ (channel << 4) | target : target;
epthru->cdblen = sc->cmd_len;
epthru->logdrv = sc->lun;
@@ -1680,6 +1805,14 @@
switch (sc->cmnd[0]) {
case INQUIRY:
case READ_CAPACITY:
+ if(!(megacfg->flag & (1L << sc->channel))) {
+ printk(KERN_NOTICE
+ "scsi%d: scanning physical channel %d for devices.\n",
+ megacfg->host->host_no, channel);
+
+ megacfg->flag |= (1L << sc->channel);
+ }
+
epthru->numsgelements = 0;
epthru->dataxferaddr = scb->dma_bounce_buffer;
epthru->dataxferlen = sc->request_bufflen;
@@ -2240,7 +2373,6 @@
return 0;
}
udelay (100);
- barrier ();
}
return -1; /* give up after 1 second */
}
@@ -2439,7 +2571,7 @@
scb->sg64List[0].address = scb->dma_h_bulkdata;
scb->sg64List[0].length = scb->SCpnt->request_bufflen;
*buffer = scb->dma_sghandle64;
- *length = 0;
+ *length = (u32)scb->SCpnt->request_bufflen;
scb->sglist_count = 1;
return 1;
} else {
@@ -2520,7 +2652,15 @@
#else
*buffer = virt_to_bus (scb->sgList);
#endif
+
+#if 0
*length = 0;
+#endif
+ /*
+ * For passthru command, dataxferlen must be set, even for commands with a
+ * sg list
+ */
+ *length = (u32)scb->SCpnt->request_bufflen;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
/* Return count of SG requests */
@@ -2743,12 +2883,7 @@
megaCfg->productInfo.SCSIChanPresent + NVIRT_CHAN -1;
megaCfg->host->max_id = 16; /* max targets per channel */
- /*(megaCfg->flag & BOARD_40LD)?FC_MAX_TARGETS_PER_CHANNEL:MAX_TARGET+1; */
-#if 0
- megaCfg->host->max_lun = /* max lun */
- (megaCfg->flag & BOARD_40LD) ?
- FC_MAX_LOGICAL_DRIVES : MAX_LOGICAL_DRIVES;
-#endif
+
megaCfg->host->max_lun = 7; /* Upto 7 luns for non disk devices */
megaCfg->host->cmd_per_lun = MAX_CMD_PER_LUN;
@@ -2760,12 +2895,6 @@
megaCfg->host->can_queue = megaCfg->max_cmds - 1;
-#if 0
- if (megaCfg->host->can_queue >= MAX_COMMANDS) {
- megaCfg->host->can_queue = MAX_COMMANDS - 16;
- }
-#endif
-
/* use HP firmware and bios version encoding */
if (megaCfg->productInfo.subSystemVendorID == HP_SUBSYS_ID) {
sprintf (megaCfg->fwVer, "%c%d%d.%d%d",
@@ -2833,7 +2962,7 @@
u32 magic64;
#endif
- int i;
+ int i, j;
#if BITS_PER_LONG==64
u64 megaBase;
@@ -2863,20 +2992,27 @@
pciDevFun = pdev->devfn;
#endif
if ((flag & BOARD_QUARTZ) && (skip_id == -1)) {
- pcibios_read_config_word (pciBus, pciDevFun,
- PCI_CONF_AMISIG, &magic);
- if ((magic != AMI_SIGNATURE)
- && (magic != AMI_SIGNATURE_471)) {
- pciIdx++;
- continue; /* not an AMI board */
- }
+ if( (pciVendor == PCI_VENDOR_ID_PERC4_DI_YSTONE &&
+ pciDev == PCI_DEVICE_ID_PERC4_DI_YSTONE) ||
+ (pciVendor == PCI_VENDOR_ID_PERC4_QC_VERDE &&
+ pciDev == PCI_DEVICE_ID_PERC4_QC_VERDE) ) {
+
+ flag |= BOARD_64BIT;
+ }
+ else {
+ pci_read_config_word (pdev, PCI_CONF_AMISIG, &magic);
+ if ((magic != AMI_SIGNATURE)
+ && (magic != AMI_SIGNATURE_471)) {
+ pciIdx++;
+ continue; /* not an AMI board */
+ }
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
- pcibios_read_config_dword (pciBus, pciDevFun,
- PCI_CONF_AMISIG64, &magic64);
+ pci_read_config_dword (pdev, PCI_CONF_AMISIG64, &magic64);
- if (magic64 == AMI_64BIT_SIGNATURE)
- flag |= BOARD_64BIT;
+ if (magic64 == AMI_64BIT_SIGNATURE)
+ flag |= BOARD_64BIT;
#endif
+ }
}
/* Hmmm...Should we not make this more modularized so that in future we dont add
@@ -2898,24 +3034,15 @@
PCI_SUBSYSTEM_ID, &subsysid);
#endif
-#if 0
/*
- * This routine is called with well know values and we
- * should not be getting what we have not asked.
- * Also, the check is not right. It should have been for
- * pci_vendor_id not subsysvid - AM
- */
-
- /* If we dont detect this valid subsystem vendor id's
- we refuse to load the driver
- PART of PC200X compliance
+ * If we do not find the valid subsys vendor id, refuse to load
+ * the driver. This is part of PCI200X compliance
*/
+ if( (subsysvid != AMI_SUBSYS_ID) &&
+ (subsysvid != DELL_SUBSYS_ID) &&
+ (subsysvid != LSI_SUBSYS_ID) &&
+ (subsysvid != HP_SUBSYS_ID) ) continue;
- if ((subsysvid != AMI_SUBSYS_ID)
- && (subsysvid != DELL_SUBSYS_ID)
- && (subsysvid != HP_SUBSYS_ID))
- continue;
-#endif
}
printk (KERN_NOTICE
@@ -3004,11 +3131,10 @@
megaCtlrs[numCtlrs] = megaCfg;
if (!(flag & BOARD_QUARTZ)) {
+
/* Request our IO Range */
- if (!request_region(megaBase, 16, "megaraid")) {
- printk(KERN_WARNING "megaraid: Couldn't register I/O range!\n");
+ if( !request_region(megaBase, 16, "megaraid") )
goto err_unregister;
- }
}
/* Request our IRQ */
@@ -3031,9 +3157,7 @@
sizeof (mega_mailbox64),
&(megaCfg->dma_handle64));
- mega_register_mailbox (megaCfg,
- virt_to_bus ((void *) megaCfg->
- mailbox64ptr));
+ mega_register_mailbox (megaCfg,megaCfg->dma_handle64);
#else
mega_register_mailbox (megaCfg,
virt_to_bus ((void *) &megaCfg->
@@ -3097,18 +3221,35 @@
* Find out which channel is raid and which is scsi
*/
mega_enum_raid_scsi(megaCfg);
- for( i = 0; i < megaCfg->productInfo.SCSIChanPresent; i++ ) {
- if(IS_RAID_CH(i))
- printk(KERN_NOTICE"megaraid: channel[%d] is raid.\n", i+1);
- else
- printk(KERN_NOTICE"megaraid: channel[%d] is scsi.\n", i+1);
- }
/*
* Find out if a logical drive is set as the boot drive. If there is
* one, will make that as the first logical drive.
+ * ROMB: Do we have to boot from a physical drive. Then all the
+ * physical drives would appear before the logical disks. Else, all
+ * the physical drives would be exported to the mid layer after
+ * logical disks.
*/
- mega_get_boot_ldrv(megaCfg);
+ mega_get_boot_drv(megaCfg);
+
+ if( ! megaCfg->boot_pdrv_enabled ) {
+ for( i = 0; i < NVIRT_CHAN; i++ )
+ megaCfg->logdrv_chan[i] = 1;
+
+ for( i = NVIRT_CHAN; i < MAX_CHANNEL + NVIRT_CHAN; i++ )
+ megaCfg->logdrv_chan[i] = 0;
+
+ megaCfg->mega_ch_class <<= NVIRT_CHAN;
+ }
+ else {
+ j = megaCfg->productInfo.SCSIChanPresent;
+ for( i = 0; i < j; i++ )
+ megaCfg->logdrv_chan[i] = 0;
+
+ for( i = j; i < NVIRT_CHAN + j; i++ )
+ megaCfg->logdrv_chan[i] = 1;
+ }
+
mega_hbas[numCtlrs].hostdata_addr = megaCfg;
@@ -3208,6 +3349,12 @@
memset (mega_hbas, 0, sizeof (mega_hbas));
+ /* Detect ROMBs first */
+ count += mega_findCard (pHostTmpl, PCI_VENDOR_ID_DISCOVERY,
+ PCI_DEVICE_ID_DISCOVERY, BOARD_QUARTZ);
+ count += mega_findCard (pHostTmpl, PCI_VENDOR_ID_PERC4_DI_YSTONE,
+ PCI_DEVICE_ID_PERC4_DI_YSTONE, BOARD_QUARTZ);
+ /* Then detect cards based on date they were produced, oldest first */
count += mega_findCard (pHostTmpl, PCI_VENDOR_ID_AMI,
PCI_DEVICE_ID_AMI_MEGARAID, 0);
count += mega_findCard (pHostTmpl, PCI_VENDOR_ID_AMI,
@@ -3216,6 +3363,10 @@
PCI_DEVICE_ID_AMI_MEGARAID3, BOARD_QUARTZ);
count += mega_findCard (pHostTmpl, PCI_VENDOR_ID_AMI,
PCI_DEVICE_ID_AMI_MEGARAID3, BOARD_QUARTZ);
+ count += mega_findCard (pHostTmpl, PCI_VENDOR_ID_LSI_LOGIC,
+ PCI_DEVICE_ID_AMI_MEGARAID3, BOARD_QUARTZ);
+ count += mega_findCard (pHostTmpl, PCI_VENDOR_ID_PERC4_QC_VERDE,
+ PCI_DEVICE_ID_PERC4_QC_VERDE, BOARD_QUARTZ);
mega_reorder_hosts ();
@@ -3366,7 +3517,7 @@
/*
* Find out what channels are RAID/SCSI
*/
-void
+static void
mega_enum_raid_scsi(mega_host_config *megacfg)
{
mega_mailbox *mboxp;
@@ -3401,16 +3552,16 @@
* Non-ROMB firware fail this command, so all channels
* must be shown RAID
*/
+ megacfg->mega_ch_class = 0xFF;
if( megaIssueCmd(megacfg, mbox, NULL, 0) == 0 ) {
- mega_ch_class = *((char *)megacfg->mega_buffer);
-
- for( i = 0; i < NVIRT_CHAN; i++ ) {
- /* logical drives channel is RAID */
- mega_ch_class |= (0x01 << (megacfg->productInfo.SCSIChanPresent+i));
- }
+ megacfg->mega_ch_class = *((char *)megacfg->mega_buffer);
}
- else {
- mega_ch_class = 0xFF;
+
+ for( i = 0; i < megacfg->productInfo.SCSIChanPresent; i++ ) {
+ if( (megacfg->mega_ch_class >> i) & 0x01 )
+ printk(KERN_NOTICE"megaraid: channel[%d] is raid.\n", i+1);
+ else
+ printk(KERN_NOTICE"megaraid: channel[%d] is scsi.\n", i+1);
}
@@ -3426,13 +3577,14 @@
* get the boot logical drive number if enabled
*/
void
-mega_get_boot_ldrv(mega_host_config *megacfg)
+mega_get_boot_drv(mega_host_config *megacfg)
{
mega_mailbox *mboxp;
unsigned char mbox[16];
struct private_bios_data *prv_bios_data;
u16 cksum = 0;
- char *cksum_p;
+ u8 *cksum_p;
+ u8 boot_pdrv;
int i;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
@@ -3459,19 +3611,35 @@
megacfg->boot_ldrv_enabled = 0;
megacfg->boot_ldrv = 0;
- if( megaIssueCmd(megacfg, mbox, NULL, 0) == 0 ) {
+ megacfg->boot_pdrv_enabled = 0;
+ megacfg->boot_pdrv_ch = 0;
+ megacfg->boot_pdrv_tgt = 0;
+
+ if( megaIssueCmd(megacfg, mbox, NULL, 0) == 0 ) {
prv_bios_data = (struct private_bios_data *)megacfg->mega_buffer;
cksum = 0;
- cksum_p = (char *)prv_bios_data;
+ cksum_p = (u8 *)prv_bios_data;
for( i = 0; i < 14; i++ ) {
- cksum += (u16)(*cksum_p++);
+ cksum += *cksum_p++;
}
if( prv_bios_data->cksum == (u16)(0-cksum) ) {
- megacfg->boot_ldrv_enabled = 1;
- megacfg->boot_ldrv = prv_bios_data->boot_ldrv;
+
+ /*
+ * If MSB is set, a physical drive is set as boot device
+ */
+ if( prv_bios_data->boot_drv & 0x80 ) {
+ megacfg->boot_pdrv_enabled = 1;
+ boot_pdrv = prv_bios_data->boot_drv & 0x7F;
+ megacfg->boot_pdrv_ch = boot_pdrv / 16;
+ megacfg->boot_pdrv_tgt = boot_pdrv % 16;
+ }
+ else {
+ megacfg->boot_ldrv_enabled = 1;
+ megacfg->boot_ldrv = prv_bios_data->boot_drv;
+ }
}
}
@@ -3681,7 +3849,7 @@
sprintf (buffer,
"LSI Logic MegaRAID %s %d commands %d targs %d chans %d luns",
megaCfg->fwVer, megaCfg->productInfo.MaxConcCmds,
- megaCfg->host->max_id, megaCfg->host->max_channel,
+ megaCfg->host->max_id-1, megaCfg->host->max_channel,
megaCfg->host->max_lun);
return buffer;
}
@@ -3710,6 +3878,7 @@
megaCfg = (mega_host_config *) SCpnt->host->hostdata;
DRIVER_LOCK (megaCfg);
+#if 0
if (!(megaCfg->flag & (1L << SCpnt->channel))) {
if (SCpnt->channel < megaCfg->productInfo.SCSIChanPresent)
printk ( KERN_NOTICE
@@ -3723,6 +3892,7 @@
megaCfg->flag |= (1L << SCpnt->channel);
}
+#endif
SCpnt->scsi_done = pktComp;
@@ -4232,7 +4402,7 @@
/* Get pointer to host config structure */
megaCfg = (mega_host_config *) disk->device->host->hostdata;
- if( IS_RAID_CH(disk->device->channel)) {
+ if( IS_RAID_CH(megaCfg, disk->device->channel)) {
/* Default heads (64) & sectors (32) */
heads = 64;
sectors = 32;
@@ -4297,7 +4467,15 @@
int heads, cyls, sectors;
int capacity = disk->capacity;
- if(!(bh = bread(MKDEV(MAJOR(dev), MINOR(dev)&~0xf), 0, block_size(dev))))
+ int ma = MAJOR(dev);
+ int mi = (MINOR(dev) & ~0xf);
+
+ int block = 1024;
+
+ if(blksize_size[ma])
+ block = blksize_size[ma][mi];
+
+ if(!(bh = bread(MKDEV(ma,mi), 0, block)))
return -1;
if( *(unsigned short *)(bh->b_data + 510) == 0xAA55 ) {
@@ -4626,9 +4804,10 @@
/*
* Copy struct mcontroller to user area
*/
- copy_to_user (ioc.data,
+ if (copy_to_user (ioc.data,
mcontroller + adapno,
- sizeof (struct mcontroller));
+ sizeof (struct mcontroller)))
+ return -EFAULT;
return 0;
default:
@@ -4694,7 +4873,7 @@
if(shpnt == NULL) return -ENODEV;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
- scsicmd = (Scsi_Cmnd *)kmalloc(sizeof(Scsi_Cmnd), GFP_KERNEL|GFP_DMA);
+ scsicmd = (Scsi_Cmnd *)kmalloc(sizeof(Scsi_Cmnd), GFP_KERNEL);
#else
scsicmd = (Scsi_Cmnd *)scsi_init_malloc(sizeof(Scsi_Cmnd),
GFP_ATOMIC | GFP_DMA);
@@ -4716,19 +4895,18 @@
if( kvaddr == NULL ) {
printk(KERN_WARNING "megaraid:allocation failed\n");
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) /*0x20400 */
- kfree(scsicmd);
-#else
- scsi_init_free((char *)scsicmd, sizeof(Scsi_Cmnd));
-#endif
- return -ENOMEM;
+ ret = -ENOMEM;
+ goto out;
}
ioc.ui.fcs.buffer = kvaddr;
if (inlen) {
/* copyin the user data */
- copy_from_user(kvaddr, (char *)uaddr, length );
+ if (copy_from_user(kvaddr, (char *)uaddr, length )) {
+ ret = -EFAULT;
+ goto out;
+ }
}
}
@@ -4745,7 +4923,9 @@
down(&mimd_ioctl_sem);
if( !scsicmd->result && outlen ) {
- copy_to_user(uaddr, kvaddr, length);
+ if (copy_to_user(uaddr, kvaddr, length))
+ ret = -EFAULT;
+ goto out;
}
/*
@@ -4755,12 +4935,16 @@
if( ioc.mbox[0] == MEGA_MBOXCMD_PASSTHRU ) {
put_user( scsicmd->result, &uioc->pthru.scsistatus );
+ if (copy_to_user( uioc->pthru.reqsensearea, scsicmd->sense_buffer,
+ MAX_REQ_SENSE_LEN ))
+ ret= -EFAULT;
} else {
put_user(1, &uioc->mbox[16]); /* numstatus */
/* status */
put_user (scsicmd->result, &uioc->mbox[17]);
}
+out:
if (kvaddr) {
dma_free_consistent(pdevp, length, kvaddr, dma_addr);
}
@@ -4836,7 +5020,7 @@
}
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
- scsicmd = (Scsi_Cmnd *)kmalloc(sizeof(Scsi_Cmnd), GFP_KERNEL|GFP_DMA);
+ scsicmd = (Scsi_Cmnd *)kmalloc(sizeof(Scsi_Cmnd), GFP_KERNEL);
#else
scsicmd = (Scsi_Cmnd *)scsi_init_malloc(sizeof(Scsi_Cmnd),
GFP_ATOMIC | GFP_DMA);
@@ -4894,9 +5078,11 @@
if (!scsicmd->result && outlen) {
if (ioc.mbox[0] == MEGA_MBOXCMD_PASSTHRU) {
- copy_to_user (uaddr, kvaddr, ioc.pthru.dataxferlen);
+ if (copy_to_user (uaddr, kvaddr, ioc.pthru.dataxferlen))
+ ret = -EFAULT;
} else {
- copy_to_user (uaddr, kvaddr, outlen);
+ if (copy_to_user (uaddr, kvaddr, outlen))
+ ret = -EFAULT;
}
}
@@ -4907,6 +5093,15 @@
if (ioc.mbox[0] == MEGA_MBOXCMD_PASSTHRU) {
put_user (scsicmd->result, &uioc->pthru.scsistatus);
+
+ /*
+ * If scsicmd->result is 0x02 (CHECK CONDITION) then copy the
+ * SCSI sense data into user area
+ */
+ if (copy_to_user( uioc->pthru.reqsensearea, scsicmd->sense_buffer,
+ MAX_REQ_SENSE_LEN ))
+ ret = -EFAULT;
+
} else {
put_user (1, &uioc->mbox[16]); /* numstatus */
put_user (scsicmd->result, &uioc->mbox[17]); /* status */
@@ -4995,7 +5190,7 @@
scb->sg64List[0].length = 4096; // TODO: Check this
pthru->dataxferaddr = scb->dma_sghandle64;
pthru->numsgelements = 1;
- mboxpthru->cmd = 0xC3;
+ mboxpthru->cmd = MEGA_MBOXCMD_PASSTHRU64;
} else {
mboxpthru->dataxferaddr = scb->dma_passthruhandle64;
pthru->dataxferaddr =
@@ -5189,8 +5384,6 @@
return rval;
}
- printk("megaraid: logical drive %d deleted.\n", logdrv);
-
/*
* After deleting first logical drive, the logical drives must be
* addressed by adding 0x80 to the logical drive id.
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)