summaryrefslogtreecommitdiffstats
path: root/drivers/scsi/pci2000.c
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2000-04-28 01:09:25 +0000
committerRalf Baechle <ralf@linux-mips.org>2000-04-28 01:09:25 +0000
commitb9ba7aeb165cffecdffb60aec8c3fa8d590d9ca9 (patch)
tree42d07b0c7246ae2536a702e7c5de9e2732341116 /drivers/scsi/pci2000.c
parent7406b0a326f2d70ade2671c37d1beef62249db97 (diff)
Merge with 2.3.99-pre6.
Diffstat (limited to 'drivers/scsi/pci2000.c')
-rw-r--r--drivers/scsi/pci2000.c197
1 files changed, 116 insertions, 81 deletions
diff --git a/drivers/scsi/pci2000.c b/drivers/scsi/pci2000.c
index d111eba9d..94007c5a8 100644
--- a/drivers/scsi/pci2000.c
+++ b/drivers/scsi/pci2000.c
@@ -29,8 +29,11 @@
* Revisions 1.12 Mar-26-1999
* - Fixed spinlock and PCI configuration.
*
+ * Revisions 1.20 Mar-27-2000
+ * - Added support for dynamic DMA
+ *
****************************************************************************/
-#define PCI2000_VERSION "1.12"
+#define PCI2000_VERSION "1.20"
#include <linux/module.h>
@@ -67,32 +70,37 @@
typedef struct
{
- ULONG address;
- ULONG length;
+ unsigned int address;
+ unsigned int length;
} SCATGATH, *PSCATGATH;
typedef struct
{
- Scsi_Cmnd *SCpnt;
- SCATGATH scatGath[16];
- UCHAR tag;
+ Scsi_Cmnd *SCpnt;
+ PSCATGATH scatGath;
+ dma_addr_t scatGathDma;
+ UCHAR *cdb;
+ dma_addr_t cdbDma;
+ UCHAR tag;
} DEV2000, *PDEV2000;
typedef struct
{
- USHORT basePort;
- USHORT mb0;
- USHORT mb1;
- USHORT mb2;
- USHORT mb3;
- USHORT mb4;
- USHORT cmd;
- USHORT tag;
- ULONG irqOwned;
- DEV2000 dev[MAX_BUS][MAX_UNITS];
+ ULONG basePort;
+ ULONG mb0;
+ ULONG mb1;
+ ULONG mb2;
+ ULONG mb3;
+ ULONG mb4;
+ ULONG cmd;
+ ULONG tag;
+ ULONG irqOwned;
+ struct pci_dev *pdev;
+ DEV2000 dev[MAX_BUS][MAX_UNITS];
} ADAPTER2000, *PADAPTER2000;
#define HOSTDATA(host) ((PADAPTER2000)&host->hostdata)
+#define consistentLen (MAX_BUS * MAX_UNITS * (16 * sizeof (SCATGATH) + MAX_COMMAND_SIZE))
static struct Scsi_Host *PsiHost[MAXADAPTER] = {NULL,}; // One for each adapter
@@ -193,20 +201,31 @@ static UCHAR Command (PADAPTER2000 padapter, UCHAR cmd)
****************************************************************/
static int BuildSgList (Scsi_Cmnd *SCpnt, PADAPTER2000 padapter, PDEV2000 pdev)
{
- int z;
+ int z;
+ int zc;
+ struct scatterlist *sg;
if ( SCpnt->use_sg )
{
- for ( z = 0; z < SCpnt->use_sg; z++ )
+ sg = (struct scatterlist *)SCpnt->request_buffer;
+ zc = pci_map_sg (padapter->pdev, sg, SCpnt->use_sg, scsi_to_pci_dma_dir (SCpnt->sc_data_direction));
+ for ( z = 0; z < zc; z++ )
{
- pdev->scatGath[z].address = virt_to_bus (((struct scatterlist *)SCpnt->request_buffer)[z].address);
- pdev->scatGath[z].length = ((struct scatterlist *)SCpnt->request_buffer)[z].length;
+ pdev->scatGath[z].address = cpu_to_le32 (sg_dma_address (sg));
+ pdev->scatGath[z].length = cpu_to_le32 (sg_dma_len (sg++));
}
- outl (virt_to_bus (pdev->scatGath), padapter->mb2);
- outl ((SCpnt->use_sg << 24) | SCpnt->request_bufflen, padapter->mb3);
+ outl (pdev->scatGathDma, padapter->mb2);
+ outl ((zc << 24) | SCpnt->request_bufflen, padapter->mb3);
return FALSE;
}
- outl (virt_to_bus (SCpnt->request_buffer), padapter->mb2);
+ if ( !SCpnt->request_bufflen)
+ {
+ outl (0, padapter->mb2);
+ outl (0, padapter->mb3);
+ return TRUE;
+ }
+ SCpnt->SCp.have_data_in = pci_map_single (padapter->pdev, SCpnt->request_buffer, SCpnt->request_bufflen, scsi_to_pci_dma_dir (SCpnt->sc_data_direction));
+ outl (SCpnt->SCp.have_data_in, padapter->mb2);
outl (SCpnt->request_bufflen, padapter->mb3);
return TRUE;
}
@@ -254,23 +273,13 @@ static void Irq_Handler (int irq, void *dev_id, struct pt_regs *regs)
int pun;
int bus;
int z;
-#if LINUX_VERSION_CODE < LINUXVERSION(2,1,95)
- int flags;
-#else /* version >= v2.1.95 */
unsigned long flags;
-#endif /* version >= v2.1.95 */
-#if LINUX_VERSION_CODE < LINUXVERSION(2,1,95)
- /* Disable interrupts, if they aren't already disabled. */
- save_flags (flags);
- cli ();
-#else /* version >= v2.1.95 */
/*
* Disable interrupts, if they aren't already disabled and acquire
* the I/O spinlock.
*/
spin_lock_irqsave (&io_request_lock, flags);
-#endif /* version >= v2.1.95 */
DEB(printk ("\npci2000 recieved interrupt "));
for ( z = 0; z < NumAdapters; z++ ) // scan for interrupt to process
@@ -306,14 +315,39 @@ static void Irq_Handler (int irq, void *dev_id, struct pt_regs *regs)
{
pdev->tag = 0;
SCpnt = pdev->SCpnt;
- goto irqProceed;
+ goto unmapProceed;
}
}
}
outb_p (0xFF, padapter->tag); // clear the op interrupt
outb_p (CMD_DONE, padapter->cmd); // complete the op
- goto irq_return;; // done, but, with what?
+ goto irq_return;; // done, but, with what?
+
+unmapProceed:;
+ if ( !bus )
+ {
+ switch ( SCpnt->cmnd[0] )
+ {
+ case SCSIOP_TEST_UNIT_READY:
+ pci_unmap_single (padapter->pdev, SCpnt->SCp.have_data_in, sizeof (SCpnt->sense_buffer), PCI_DMA_FROMDEVICE);
+ goto irqProceed;
+ case SCSIOP_READ_CAPACITY:
+ pci_unmap_single (padapter->pdev, SCpnt->SCp.have_data_in, 8, PCI_DMA_FROMDEVICE);
+ goto irqProceed;
+ case SCSIOP_VERIFY:
+ case SCSIOP_START_STOP_UNIT:
+ case SCSIOP_MEDIUM_REMOVAL:
+ goto irqProceed;
+ }
+ }
+ if ( SCpnt->SCp.have_data_in )
+ pci_unmap_single (padapter->pdev, SCpnt->SCp.have_data_in, SCpnt->request_bufflen, scsi_to_pci_dma_dir(SCpnt->sc_data_direction));
+ else
+ {
+ if ( SCpnt->use_sg )
+ pci_unmap_sg (padapter->pdev, (struct scatterlist *)SCpnt->request_buffer, SCpnt->use_sg, scsi_to_pci_dma_dir(SCpnt->sc_data_direction));
+ }
irqProceed:;
if ( tag & ERR08_TAGGED ) // is there an error here?
@@ -359,20 +393,12 @@ irqProceed:;
OpDone (SCpnt, DID_OK << 16);
irq_return:;
-#if LINUX_VERSION_CODE < LINUXVERSION(2,1,95)
- /*
- * Restore the original flags which will enable interrupts
- * if and only if they were enabled on entry.
- */
- restore_flags (flags);
-#else /* version >= v2.1.95 */
/*
* Release the I/O spinlock and restore the original flags
* which will enable interrupts if and only if they were
* enabled on entry.
*/
spin_unlock_irqrestore (&io_request_lock, flags);
-#endif /* version >= v2.1.95 */
}
/****************************************************************
* Name: Pci2000_QueueCommand
@@ -403,6 +429,7 @@ int Pci2000_QueueCommand (Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
}
SCpnt->scsi_done = done;
+ SCpnt->SCp.have_data_in = 0;
pdev->SCpnt = SCpnt; // Save this command data
if ( WaitReady (padapter) )
@@ -428,7 +455,9 @@ int Pci2000_QueueCommand (Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
outw_p (pun | (lun << 8), padapter->mb0);
outw_p (SCpnt->cmd_len << 8, padapter->mb0 + 2);
- outl (virt_to_bus (cdb), padapter->mb1);
+ memcpy (pdev->cdb, cdb, MAX_COMMAND_SIZE);
+
+ outl (pdev->cdbDma, padapter->mb1);
if ( BuildSgList (SCpnt, padapter, pdev) )
cmd = CMD_SCSI_THRU;
else
@@ -469,7 +498,11 @@ int Pci2000_QueueCommand (Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
goto finished;
}
else
- outl (virt_to_bus (SCpnt->request_buffer), padapter->mb2);
+ {
+ SCpnt->SCp.have_data_in = pci_map_single (padapter->pdev, SCpnt->request_buffer, SCpnt->request_bufflen,
+ scsi_to_pci_dma_dir(SCpnt->sc_data_direction));
+ outl (SCpnt->SCp.have_data_in, padapter->mb2);
+ }
outl (cdb[5], padapter->mb0);
outl (cdb[3], padapter->mb3);
cmd = CMD_DASD_RAID_RQ;
@@ -480,31 +513,35 @@ int Pci2000_QueueCommand (Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
if ( SCpnt->use_sg )
{
- outl (virt_to_bus (((struct scatterlist *)(SCpnt->request_buffer))->address), padapter->mb2);
+ SCpnt->SCp.have_data_in = pci_map_single (padapter->pdev, ((struct scatterlist *)SCpnt->request_buffer)->address,
+ SCpnt->request_bufflen, scsi_to_pci_dma_dir (SCpnt->sc_data_direction));
}
else
{
- outl (virt_to_bus (SCpnt->request_buffer), padapter->mb2);
+ SCpnt->SCp.have_data_in = pci_map_single (padapter->pdev, SCpnt->request_buffer,
+ SCpnt->request_bufflen, scsi_to_pci_dma_dir (SCpnt->sc_data_direction));
}
+ outl (SCpnt->SCp.have_data_in, padapter->mb2);
outl (SCpnt->request_bufflen, padapter->mb3);
cmd = CMD_DASD_SCSI_INQ;
break;
case SCSIOP_TEST_UNIT_READY: // test unit ready CDB
- outl (virt_to_bus (SCpnt->sense_buffer), padapter->mb2);
+ SCpnt->SCp.have_data_in = pci_map_single (padapter->pdev, SCpnt->sense_buffer, sizeof (SCpnt->sense_buffer), PCI_DMA_FROMDEVICE);
+ outl (SCpnt->SCp.have_data_in, padapter->mb2);
outl (sizeof (SCpnt->sense_buffer), padapter->mb3);
cmd = CMD_TEST_READY;
break;
- case SCSIOP_READ_CAPACITY: // read capctiy CDB
+ case SCSIOP_READ_CAPACITY: // read capacity CDB
if ( SCpnt->use_sg )
{
- outl (virt_to_bus (((struct scatterlist *)(SCpnt->request_buffer))->address), padapter->mb2);
+ SCpnt->SCp.have_data_in = pci_map_single (padapter->pdev, ((struct scatterlist *)(SCpnt->request_buffer))->address,
+ 8, PCI_DMA_FROMDEVICE);
}
else
- {
- outl (virt_to_bus (SCpnt->request_buffer), padapter->mb2);
- }
+ SCpnt->SCp.have_data_in = pci_map_single (padapter->pdev, SCpnt->request_buffer, 8, PCI_DMA_FROMDEVICE);
+ outl (SCpnt->SCp.have_data_in, padapter->mb2);
outl (8, padapter->mb3);
cmd = CMD_DASD_CAP;
break;
@@ -629,37 +666,23 @@ int Pci2000_Detect (Scsi_Host_Template *tpnt)
PADAPTER2000 padapter;
int z, zz;
int setirq;
-#if LINUX_VERSION_CODE > LINUXVERSION(2,1,92)
struct pci_dev *pdev = NULL;
-#else
- UCHAR pci_bus, pci_device_fn;
-#endif
+ UCHAR *consistent;
+ dma_addr_t consistentDma;
+
-#if LINUX_VERSION_CODE > LINUXVERSION(2,1,92)
if ( !pci_present () )
-#else
- if ( !pcibios_present () )
-#endif
{
printk ("pci2000: PCI BIOS not present\n");
return 0;
}
-#if LINUX_VERSION_CODE > LINUXVERSION(2,1,92)
while ( (pdev = pci_find_device (VENDOR_PSI, DEVICE_ROY_1, pdev)) != NULL )
-#else
- while ( !pcibios_find_device (VENDOR_PSI, DEVICE_ROY_1, found, &pci_bus, &pci_device_fn) )
-#endif
{
pshost = scsi_register (tpnt, sizeof(ADAPTER2000));
padapter = HOSTDATA(pshost);
-#if LINUX_VERSION_CODE > LINUXVERSION(2,1,92)
- padapter->basePort = pci_resource_start (pdev, 1);
-#else
- pcibios_read_config_word (pci_bus, pci_device_fn, PCI_BASE_ADDRESS_1, &padapter->basePort);
- padapter->basePort &= 0xFFFE;
-#endif
+ padapter->basePort = pdev->resource[1].start & PCI_BASE_ADDRESS_IO_MASK;
DEB (printk ("\nBase Regs = %#04X", padapter->basePort)); // get the base I/O port address
padapter->mb0 = padapter->basePort + RTR_MAILBOX; // get the 32 bit mail boxes
padapter->mb1 = padapter->basePort + RTR_MAILBOX + 4;
@@ -668,6 +691,7 @@ int Pci2000_Detect (Scsi_Host_Template *tpnt)
padapter->mb4 = padapter->basePort + RTR_MAILBOX + 16;
padapter->cmd = padapter->basePort + RTR_LOCAL_DOORBELL; // command register
padapter->tag = padapter->basePort + RTR_PCI_DOORBELL; // tag/response register
+ padapter->pdev = pdev;
if ( WaitReady (padapter) )
goto unregister;
@@ -676,11 +700,14 @@ int Pci2000_Detect (Scsi_Host_Template *tpnt)
if ( WaitReady (padapter) )
goto unregister;
-#if LINUX_VERSION_CODE > LINUXVERSION(2,1,92)
+ consistent = pci_alloc_consistent (pdev, consistentLen, &consistentDma);
+ if ( !consistent )
+ {
+ printk ("Unable to allocate DMA memory for PCI-2000 controller.\n");
+ goto unregister;
+ }
+
pshost->irq = pdev->irq;
-#else
- pcibios_read_config_byte (pci_bus, pci_device_fn, PCI_INTERRUPT_LINE, &pshost->irq);
-#endif
setirq = 1;
padapter->irqOwned = 0;
for ( z = 0; z < installed; z++ ) // scan for shared interrupts
@@ -695,6 +722,7 @@ int Pci2000_Detect (Scsi_Host_Template *tpnt)
if ( request_irq (pshost->irq, Irq_Handler, SA_INTERRUPT | SA_SHIRQ, "pci2000", padapter) < 0 )
{
printk ("Unable to allocate IRQ for PCI-2000 controller.\n");
+ pci_free_consistent (pdev, consistentLen, consistent, consistentDma);
goto unregister;
}
}
@@ -710,9 +738,19 @@ int Pci2000_Detect (Scsi_Host_Template *tpnt)
for ( zz = 0; zz < MAX_BUS; zz++ )
for ( z = 0; z < MAX_UNITS; z++ )
+ {
padapter->dev[zz][z].tag = 0;
+ padapter->dev[zz][z].scatGath = (PSCATGATH)consistent;
+ padapter->dev[zz][z].scatGathDma = consistentDma;
+ consistent += 16 * sizeof (SCATGATH);
+ consistentDma += 16 * sizeof (SCATGATH);
+ padapter->dev[zz][z].cdb = (UCHAR *)consistent;
+ padapter->dev[zz][z].cdbDma = consistentDma;
+ consistent += MAX_COMMAND_SIZE;
+ consistentDma += MAX_COMMAND_SIZE;
+ }
- printk("\nPSI-2000 Intelligent Storage SCSI CONTROLLER: at I/O = %X IRQ = %d\n", padapter->basePort, pshost->irq);
+ printk("\nPSI-2000 Intelligent Storage SCSI CONTROLLER: at I/O = %lX IRQ = %d\n", padapter->basePort, pshost->irq);
printk("Version %s, Compiled %s %s\n\n", PCI2000_VERSION, __DATE__, __TIME__);
found++;
if ( ++installed < MAXADAPTER )
@@ -774,12 +812,9 @@ int Pci2000_Release (struct Scsi_Host *pshost)
PADAPTER2000 padapter = HOSTDATA (pshost);
if ( padapter->irqOwned )
-#if LINUX_VERSION_CODE < LINUXVERSION(1,3,70)
- free_irq (pshost->irq);
-#else /* version >= v1.3.70 */
free_irq (pshost->irq, padapter);
-#endif /* version >= v1.3.70 */
- release_region (pshost->io_port, pshost->n_io_port);
+ pci_free_consistent (padapter->pdev, consistentLen, padapter->dev[0][0].scatGath, padapter->dev[0][0].scatGathDma);
+ release_region (pshost->io_port, pshost->n_io_port);
scsi_unregister(pshost);
return 0;
}