PCI2000 & 2.3.47

From: Jakub Jelinek (jakub@redhat.com)
Date: Mon Feb 21 2000 - 04:30:53 EST


Hi!

PCI2000 in 2.3.47 does not compile at all. This patch moves it into compile
land and includes an attempt to use dynamic DMA and solve some 64bit issues,
but as I don't have such card, I cannot test it much.
So, I'd like anyone with PCI2000 if he could test this and tell me how it
went.

--- linux/drivers/scsi/pci2000.h.jj Mon Feb 21 08:24:26 2000
+++ linux/drivers/scsi/pci2000.h Mon Feb 21 09:55:09 2000
@@ -202,56 +202,86 @@ int Pci2000_BiosParam (Disk *disk, kdev
 
 extern struct proc_dir_entry Proc_Scsi_Pci2000;
 
-#if LINUX_VERSION_CODE >= LINUXVERSION(2,1,75)
-#define PCI2000 { \
- next: NULL, \
- module: NULL, \
- proc_dir: &Proc_Scsi_Pci2000, \
+#if LINUX_VERSION_CODE >= LINUXVERSION(2,3,28)
+#define PCI2000 { \
+ next: NULL, \
+ module: NULL, \
+ proc_name: "pci2000", \
                 proc_info: NULL, /* let's not bloat the kernel */ \
- name: "PCI-2000 SCSI Intelligent Disk Controller",\
- detect: Pci2000_Detect, \
- release: Pci2000_Release, \
+ name: "PCI-2000 SCSI Intelligent Disk Controller", \
+ detect: Pci2000_Detect, \
+ release: Pci2000_Release, \
                 info: NULL, /* let's not bloat the kernel */ \
- command: Pci2000_Command, \
- queuecommand: Pci2000_QueueCommand, \
- eh_strategy_handler: NULL, \
- eh_abort_handler: NULL, \
- eh_device_reset_handler: NULL, \
- eh_bus_reset_handler: NULL, \
- eh_host_reset_handler: NULL, \
- abort: Pci2000_Abort, \
- reset: Pci2000_Reset, \
- slave_attach: NULL, \
- bios_param: Pci2000_BiosParam, \
- can_queue: 16, \
- this_id: -1, \
- sg_tablesize: 16, \
- cmd_per_lun: 1, \
- present: 0, \
- unchecked_isa_dma: 0, \
- use_clustering: DISABLE_CLUSTERING, \
- use_new_eh_code: 0 \
+ command: Pci2000_Command, \
+ queuecommand: Pci2000_QueueCommand, \
+ eh_strategy_handler: NULL, \
+ eh_abort_handler: NULL, \
+ eh_device_reset_handler: NULL, \
+ eh_bus_reset_handler: NULL, \
+ eh_host_reset_handler: NULL, \
+ abort: Pci2000_Abort, \
+ reset: Pci2000_Reset, \
+ slave_attach: NULL, \
+ bios_param: Pci2000_BiosParam, \
+ can_queue: 16, \
+ this_id: -1, \
+ sg_tablesize: 16, \
+ cmd_per_lun: 1, \
+ present: 0, \
+ unchecked_isa_dma: 0, \
+ use_clustering: DISABLE_CLUSTERING, \
+ use_new_eh_code: 0 \
+ }
+#elif LINUX_VERSION_CODE >= LINUXVERSION(2,1,75)
+#define PCI2000 { \
+ next: NULL, \
+ module: NULL, \
+ proc_dir: &Proc_Scsi_Pci2000, \
+ proc_info: NULL, /* let's not bloat the kernel */ \
+ name: "PCI-2000 SCSI Intelligent Disk Controller", \
+ detect: Pci2000_Detect, \
+ release: Pci2000_Release, \
+ info: NULL, /* let's not bloat the kernel */ \
+ command: Pci2000_Command, \
+ queuecommand: Pci2000_QueueCommand, \
+ eh_strategy_handler: NULL, \
+ eh_abort_handler: NULL, \
+ eh_device_reset_handler: NULL, \
+ eh_bus_reset_handler: NULL, \
+ eh_host_reset_handler: NULL, \
+ abort: Pci2000_Abort, \
+ reset: Pci2000_Reset, \
+ slave_attach: NULL, \
+ bios_param: Pci2000_BiosParam, \
+ can_queue: 16, \
+ this_id: -1, \
+ sg_tablesize: 16, \
+ cmd_per_lun: 1, \
+ present: 0, \
+ unchecked_isa_dma: 0, \
+ use_clustering: DISABLE_CLUSTERING, \
+ use_new_eh_code: 0 \
                 }
 #else
 #define PCI2000 { NULL, NULL, \
- &Proc_Scsi_Pci2000,/* proc_dir_entry */ \
- NULL, \
- "PCI-2000 SCSI Intelligent Disk Controller",\
- Pci2000_Detect, \
- Pci2000_Release, \
- NULL, \
- Pci2000_Command, \
- Pci2000_QueueCommand, \
- Pci2000_Abort, \
- Pci2000_Reset, \
- NULL, \
+ &Proc_Scsi_Pci2000,/* proc_dir_entry */ \
+ NULL, \
+ "PCI-2000 SCSI Intelligent Disk Controller", \
+ Pci2000_Detect, \
+ Pci2000_Release, \
+ NULL, \
+ Pci2000_Command, \
+ Pci2000_QueueCommand, \
+ Pci2000_Abort, \
+ Pci2000_Reset, \
+ NULL, \
                         Pci2000_BiosParam, \
- 16, \
- -1, \
- 16, \
- 1, \
- 0, \
- 0, \
+ 16, \
+ -1, \
+ 16, \
+ 1, \
+ 0, \
+ 0, \
                         DISABLE_CLUSTERING }
 #endif
 
--- linux/drivers/scsi/pci2000.c.jj Mon Feb 21 09:25:37 2000
+++ linux/drivers/scsi/pci2000.c Mon Feb 21 10:05:26 2000
@@ -53,15 +53,19 @@
 #include "pci2000.h"
 #include "psi_roy.h"
 
-#if LINUX_VERSION_CODE >= LINUXVERSION(2,1,95)
+#if LINUX_VERSION_CODE >= LINUXVERSION(2,3,18)
+#include <linux/spinlock.h>
+#elif LINUX_VERSION_CODE >= LINUXVERSION(2,1,95)
 #include <asm/spinlock.h>
 #endif
 #if LINUX_VERSION_CODE < LINUXVERSION(2,1,93)
 #include <linux/bios32.h>
 #endif
 
+#if LINUX_VERSION_CODE < LINUXVERSION(2,3,28)
 struct proc_dir_entry Proc_Scsi_Pci2000 =
         { PROC_SCSI_PCI2000, 7, "pci2000", S_IFDIR | S_IRUGO | S_IXUGO, 2 };
+#endif
 
 //#define DEBUG 1
 
@@ -73,30 +77,55 @@ struct proc_dir_entry Proc_Scsi_Pci2000
 #define STOP_HERE
 #endif
 
+#if LINUX_VERSION_CODE < LINUXVERSION(2,3,47)
+typedef u32 dma_addr_t;
+
+#define pci_alloc_consistent(cookie, size, dma_handle) \
+({ void *virt_ptr = kmalloc((size), GFP_KERNEL); \
+ *(dma_handle) = virt_to_bus(virt_ptr); \
+ virt_ptr; \
+})
+#define pci_free_consistent(cookie, size, ptr, dma_ptr) kfree(ptr)
+#define pci_map_single(cookie, address, size, dir) virt_to_bus(address)
+#define pci_unmap_single(cookie, address, size, dir)
+#define pci_map_sg(cookie, sg, nents, dir)
+#define pci_unmap_sg(cookie, sg, nents, dir)
+#define scsi_to_pci_dma_dir(dir) 0
+#define sg_dma_address(sg) virt_to_bus((sg)->address)
+#define sg_dma_len(sg) ((sg)->length)
+#endif
+
+
 typedef struct
         {
- ULONG address;
- ULONG length;
+ unsigned int address;
+ unsigned int length;
         } SCATGATH, *PSCATGATH;
 
 typedef struct
         {
         Scsi_Cmnd *SCpnt;
- SCATGATH scatGath[16];
+ 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 basePort;
+ ULONG mb0;
+ ULONG mb1;
+ ULONG mb2;
+ ULONG mb3;
+ ULONG mb4;
+ ULONG cmd;
+ ULONG tag;
         ULONG irqOwned;
+#if LINUX_VERSION_CODE >= LINUXVERSION(2,3,47)
+ struct pci_dev *pdev;
+#endif
         DEV2000 dev[MAX_BUS][MAX_UNITS];
         } ADAPTER2000, *PADAPTER2000;
 
@@ -201,20 +230,30 @@ static UCHAR Command (PADAPTER2000 padap
  ****************************************************************/
 static int BuildSgList (Scsi_Cmnd *SCpnt, PADAPTER2000 padapter, PDEV2000 pdev)
         {
- int z;
+ int z, n;
+ struct scatterlist *sg;
 
         if ( SCpnt->use_sg )
                 {
- for ( z = 0; z < SCpnt->use_sg; z++ )
+ sg = (struct scatterlist *)SCpnt->request_buffer;
+ n = pci_map_sg (padapter->pdev, sg, SCpnt->use_sg, scsi_to_pci_dma_dir (SCpnt->sc_data_direction));
+ for ( z = 0; z < n; 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 ((n << 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;
         }
@@ -314,7 +353,7 @@ static void Irq_Handler (int irq, void *
                                 {
                                 pdev->tag = 0;
                                 SCpnt = pdev->SCpnt;
- goto irqProceed;
+ goto unmapProceed;
                             }
                         }
             }
@@ -323,6 +362,25 @@ static void Irq_Handler (int irq, void *
         outb_p (CMD_DONE, padapter->cmd); // complete the op
         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?
                 {
@@ -411,6 +469,7 @@ int Pci2000_QueueCommand (Scsi_Cmnd *SCp
                 }
 
         SCpnt->scsi_done = done;
+ SCpnt->SCp.have_data_in = 0;
         pdev->SCpnt = SCpnt; // Save this command data
 
         if ( WaitReady (padapter) )
@@ -436,7 +495,8 @@ int Pci2000_QueueCommand (Scsi_Cmnd *SCp
 
                 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
@@ -476,8 +536,10 @@ int Pci2000_QueueCommand (Scsi_Cmnd *SCp
                                                         rc = DID_ERROR;
                                                         goto finished;
                                                         }
- else
- outl (virt_to_bus (SCpnt->request_buffer), padapter->mb2);
+ else {
+ 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;
@@ -487,32 +549,26 @@ int Pci2000_QueueCommand (Scsi_Cmnd *SCp
                                 }
                         
                         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 (8, padapter->mb3);
                         cmd = CMD_DASD_CAP;
                         break;
@@ -642,6 +698,9 @@ int Pci2000_Detect (Scsi_Host_Template *
 #else
         UCHAR pci_bus, pci_device_fn;
 #endif
+ UCHAR *consistent;
+ dma_addr_t consistentDma;
+#define consistentLen (MAX_BUS * MAX_UNITS * (16 * sizeof (SCATGATH) + MAX_COMMAND_SIZE))
 
 #if LINUX_VERSION_CODE > LINUXVERSION(2,1,92)
         if ( !pci_present () )
@@ -662,7 +721,9 @@ int Pci2000_Detect (Scsi_Host_Template *
                 pshost = scsi_register (tpnt, sizeof(ADAPTER2000));
                 padapter = HOSTDATA(pshost);
 
-#if LINUX_VERSION_CODE > LINUXVERSION(2,1,92)
+#if LINUX_VERSION_CODE > LINUXVERSION(2,3,12)
+ padapter->basePort = pdev->resource[1].start & PCI_BASE_ADDRESS_IO_MASK;
+#elif LINUX_VERSION_CODE > LINUXVERSION(2,1,92)
                 padapter->basePort = pdev->base_address[1] & 0xFFFE;
 #else
                 pcibios_read_config_word (pci_bus, pci_device_fn, PCI_BASE_ADDRESS_1, &padapter->basePort);
@@ -676,6 +737,9 @@ int Pci2000_Detect (Scsi_Host_Template *
                 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
+#if LINUX_VERSION_CODE >= LINUXVERSION(2,3,47)
+ padapter->pdev = pdev;
+#endif
 
                 if ( WaitReady (padapter) )
                         goto unregister;
@@ -684,6 +748,13 @@ int Pci2000_Detect (Scsi_Host_Template *
                 if ( WaitReady (padapter) )
                         goto unregister;
 
+ consistent = pci_alloc_consistent (pdev, consistentLen, &consistentDma);
+ if ( !consistent )
+ {
+ printk ("Unable to allocate DMA memory for PCI-2000 controller.\n");
+ goto unregister;
+ }
+
 #if LINUX_VERSION_CODE > LINUXVERSION(2,1,92)
                 pshost->irq = pdev->irq;
 #else
@@ -703,6 +774,7 @@ int Pci2000_Detect (Scsi_Host_Template *
                                 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;
                                         }
                                 }
@@ -718,9 +790,19 @@ int Pci2000_Detect (Scsi_Host_Template *
 
                 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 )
@@ -787,6 +869,9 @@ int Pci2000_Release (struct Scsi_Host *p
 #else /* version >= v1.3.70 */
                 free_irq (pshost->irq, padapter);
 #endif /* version >= v1.3.70 */
+ 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;

Cheers,
    Jakub
___________________________________________________________________
Jakub Jelinek | jakub@redhat.com | http://sunsite.mff.cuni.cz/~jj
Linux version 2.3.47 on a sparc64 machine (1343.49 BogoMips)
___________________________________________________________________

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/



This archive was generated by hypermail 2b29 : Wed Feb 23 2000 - 21:00:27 EST