patch-2.3.99-pre6 linux/drivers/scsi/pci2000.c

Next file: linux/drivers/scsi/pci2220i.c
Previous file: linux/drivers/scsi/ncr53c8xx.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.3.99-pre5/linux/drivers/scsi/pci2000.c linux/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 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 @@
 	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 @@
 				{
 				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 @@
 	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 @@
 		}
 
 	SCpnt->scsi_done = done;
+	SCpnt->SCp.have_data_in = 0;
 	pdev->SCpnt = SCpnt;  									// Save this command data
 
 	if ( WaitReady (padapter) )
@@ -428,7 +455,9 @@
 
 		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 @@
 							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 @@
 			
 			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 @@
 	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 @@
 		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 @@
 		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 @@
 				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 @@
 
 		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 @@
     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;
 	}

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)