patch-2.4.4 linux/arch/ia64/sn/io/pci_dma.c

Next file: linux/arch/ia64/sn/io/pciba.c
Previous file: linux/arch/ia64/sn/io/pci_bus_cvlink.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.4.3/linux/arch/ia64/sn/io/pci_dma.c linux/arch/ia64/sn/io/pci_dma.c
@@ -21,9 +21,6 @@
 #ifndef _LANGUAGE_C
 #define _LANGUAGE_C 99
 #endif
-#ifndef CONFIG_IA64_SGI_IO
-#define CONFIG_IA64_SGI_IO 99
-#endif
 
 #include <asm/io.h>
 #include <asm/sn/sgi.h>
@@ -32,9 +29,9 @@
 #include <asm/sn/pci/pcibr.h>
 #include <asm/sn/pci/pcibr_private.h>
 #include <asm/sn/iobus.h>
-#include <asm/sn/pci/pci_bus_cvlink.h>
 #include <asm/sn/types.h>
 #include <asm/sn/alenlist.h>
+#include <asm/sn/pci/pci_bus_cvlink.h>
 
 /*
  * this is REALLY ugly, blame it on gcc's lame inlining that we
@@ -43,13 +40,69 @@
 #if LANGUAGE_C == 99
 #undef LANGUAGE_C
 #endif
-#if _LANGUAGE_C == 99
-#undef _LANGUAGE_C
-#endif
 #if CONFIG_IA64_SGI_IO == 99
 #undef CONFIG_IA64_SGI_IO
 #endif
 
+pciio_dmamap_t get_free_pciio_dmamap(devfs_handle_t);
+struct sn1_dma_maps_s *find_sn1_dma_map(dma_addr_t, unsigned char);
+extern devfs_handle_t busnum_to_pcibr_vhdl[];
+extern nasid_t busnum_to_nid[];
+extern void * busnum_to_atedmamaps[];
+
+/*
+ * Get a free pciio_dmamap_t entry.
+ */
+pciio_dmamap_t
+get_free_pciio_dmamap(devfs_handle_t pci_bus)
+{
+	int i;
+	struct sn1_dma_maps_s *sn1_dma_map = NULL;
+
+	/*
+	 * Darn, we need to get the maps allocated for this bus.
+	 */
+	for (i=0; i<512; i++) {
+		if (busnum_to_pcibr_vhdl[i] == pci_bus) {
+			sn1_dma_map = busnum_to_atedmamaps[i];
+		}
+	}
+
+	/*
+	 * Now get a free dmamap entry from this list.
+	 */
+	for (i=0; i<512; i++, sn1_dma_map++) {
+		if (!sn1_dma_map->dma_addr) {
+			sn1_dma_map->dma_addr = -1;
+			return( (pciio_dmamap_t) sn1_dma_map );
+		}
+	}
+
+printk("get_pciio_dmamap: Unable to find a free dmamap\n");
+	return(NULL);
+
+}
+
+struct sn1_dma_maps_s *
+find_sn1_dma_map(dma_addr_t dma_addr, unsigned char busnum)
+{
+
+	struct sn1_dma_maps_s *sn1_dma_map = NULL;
+	int i;
+
+	sn1_dma_map = busnum_to_atedmamaps[busnum];
+
+	for (i=0; i<512; i++, sn1_dma_map++) {
+		if (sn1_dma_map->dma_addr == dma_addr) {
+			return( sn1_dma_map );
+		}
+	}
+
+printk("find_pciio_dmamap: Unable find the corresponding dma map\n");
+	return(NULL);
+
+}
+
 /*
  * sn1 platform specific pci_alloc_consistent()
  *
@@ -74,7 +127,7 @@
 	device_sysdata = (struct sn1_device_sysdata *) hwdev->sysdata;
 	vhdl = device_sysdata->vhdl;
 
-        if ( ret = (void *)__get_free_pages(gfp, get_order(size)) ) {
+        if ( (ret = (void *)__get_free_pages(gfp, get_order(size))) ) {
 		memset(ret, 0, size);
 	} else {
 		return(NULL);
@@ -142,6 +195,8 @@
 	dma_addr_t dma_addr;
 	paddr_t temp_ptr;
 	struct sn1_device_sysdata *device_sysdata;
+	pciio_dmamap_t dma_map;
+
 
 
 	if (direction == PCI_DMA_NONE)
@@ -153,7 +208,7 @@
 	device_sysdata = (struct sn1_device_sysdata *) hwdev->sysdata;
 	vhdl = device_sysdata->vhdl;
 	for (i = 0; i < nents; i++, sg++) {
-		sg->orig_address = sg->address;
+		sg->orig_address = (char *)NULL;
 		dma_addr = 0;
 		temp_ptr = (paddr_t) __pa(sg->address);
 
@@ -166,7 +221,6 @@
 				PCIBR_BARRIER | PCIIO_BYTE_STREAM |
 				PCIIO_DMA_CMD | PCIIO_DMA_A64 );
 			sg->address = (char *)dma_addr;
-/* printk("pci_map_sg: 64Bits hwdev %p DMA Address 0x%p alt_address 0x%p orig_address 0x%p length 0x%x\n", hwdev, sg->address, sg->alt_address, sg->orig_address, sg->length); */
 			continue;
 		}
 
@@ -180,17 +234,28 @@
 				PCIIO_DMA_CMD);
 			if (dma_addr) {
 				sg->address = (char *)dma_addr;
-/* printk("pci_map_single: 32Bit direct pciio_dmatrans_addr pcidev %p returns dma_addr 0x%lx\n", hwdev, dma_addr); */
 				continue;
-			} else {
-				/*
-				 * We need to map this request by using ATEs.
-				 */
-				printk("pci_map_single: 32Bits DMA Page Map support not available yet!");
-				BUG();
-
 			}
+
 		}
+
+		/*
+		 * It is a 32bit card and we cannot do Direct mapping.
+		 * Let's 32Bit Page map the request.
+		 */
+		dma_map = NULL;
+		dma_map = pciio_dmamap_alloc(vhdl, NULL, sg->length, 
+				PCIBR_BARRIER | PCIIO_BYTE_STREAM |
+				PCIIO_DMA_CMD);
+		if (!dma_map) {
+			printk("pci_map_sg: Unable to allocate anymore 32Bits Page Map entries.\n");
+			BUG();
+		}
+		dma_addr = (dma_addr_t)pciio_dmamap_addr(dma_map, temp_ptr, sg->length);
+		/* printk("pci_map_sg: dma_map 0x%p Phys Addr 0x%p dma_addr 0x%p\n", dma_map, temp_ptr, dma_addr); */
+		sg->address = (char *)dma_addr;
+		sg->orig_address = (char *)dma_map;
+		
 	}
 
 	return nents;
@@ -206,13 +271,25 @@
 sn1_pci_unmap_sg (struct pci_dev *hwdev, struct scatterlist *sg, int nelems, int direction)
 {
 	int i;
+	struct sn1_dma_maps_s *sn1_dma_map;
+
 
 	if (direction == PCI_DMA_NONE)
 		BUG();
+
 	for (i = 0; i < nelems; i++, sg++)
-		if (sg->orig_address != sg->address) {
+		if (sg->orig_address) {
+			/*
+			 * We maintain the DMA Map pointer in sg->orig_address if 
+			 * it is ever allocated.
+			 */
 			/* phys_to_virt((dma_addr_t)sg->address | ~0x80000000); */
-			sg->address = sg->orig_address;
+			/* sg->address = sg->orig_address; */
+			sg->address = (char *)-1;
+			sn1_dma_map = (struct sn1_dma_maps_s *)sg->orig_address;
+			pciio_dmamap_done((pciio_dmamap_t)sn1_dma_map);
+			pciio_dmamap_free((pciio_dmamap_t)sn1_dma_map);
+			sn1_dma_map->dma_addr = 0;
 			sg->orig_address = 0;
 		}
 }
@@ -234,24 +311,20 @@
 	dma_addr_t dma_addr;
 	paddr_t temp_ptr;
 	struct sn1_device_sysdata *device_sysdata;
+	pciio_dmamap_t dma_map = NULL;
+	struct sn1_dma_maps_s *sn1_dma_map;
 
 
 	if (direction == PCI_DMA_NONE)
 		BUG();
 
-	if (IS_PCI32L(hwdev)) {
-		/*
-		 * SNIA64 cannot support DMA Addresses smaller than 32 bits.
-		 */
-		return ((dma_addr_t) NULL);
-	}
 
 	/*
 	 * find vertex for the device
 	 */
 	device_sysdata = (struct sn1_device_sysdata *)hwdev->sysdata;
 	vhdl = device_sysdata->vhdl;
-/* printk("pci_map_single: Called vhdl = 0x%p ptr = 0x%p size = %d\n", vhdl, ptr, size); */
+
 	/*
 	 * Call our dmamap interface
 	 */
@@ -266,7 +339,6 @@
 			temp_ptr, size,
 			PCIBR_BARRIER | PCIIO_BYTE_STREAM | PCIIO_DMA_CMD
 			| PCIIO_DMA_A64 );
-/* printk("pci_map_single: 64Bit pciio_dmatrans_addr pcidev %p returns dma_addr 0x%lx\n", hwdev, dma_addr); */
 		return (dma_addr);
 	}
 
@@ -281,14 +353,7 @@
 			temp_ptr, size,
 			PCIBR_BARRIER | PCIIO_BYTE_STREAM | PCIIO_DMA_CMD);
 		if (dma_addr) {
-/* printk("pci_map_single: 32Bit direct pciio_dmatrans_addr pcidev %p returns dma_addr 0x%lx\n", hwdev, dma_addr); */
 			return (dma_addr);
-		} else {
-			/*
-			 * We need to map this request by using ATEs.
-			 */
-			printk("pci_map_single: 32Bits DMA Page Map support not available yet!");
-			BUG();
 		}
 	}
 
@@ -297,23 +362,56 @@
 		 * SNIA64 cannot support DMA Addresses smaller than 32 bits.
 		 */
 		return ((dma_addr_t) NULL);
+        }
+
+	/*
+	 * It is a 32bit card and we cannot do Direct mapping.
+	 * Let's 32Bit Page map the request.
+	 */
+	dma_map = NULL;
+	dma_map = pciio_dmamap_alloc(vhdl, NULL, size, PCIBR_BARRIER | 
+			PCIIO_BYTE_STREAM | PCIIO_DMA_CMD);
+	if (!dma_map) {
+		printk("pci_map_single: Unable to allocate anymore 32Bits Page Map entries.\n");
+		BUG();
 	}
 
-	return ((dma_addr_t) NULL);
+	dma_addr = (dma_addr_t) pciio_dmamap_addr(dma_map, temp_ptr, size);
+	/* printk("pci_map_single: dma_map 0x%p Phys Addr 0x%p dma_addr 0x%p\n", dma_map, 
+		temp_ptr, dma_addr); */
+	sn1_dma_map = (struct sn1_dma_maps_s *)dma_map;
+	sn1_dma_map->dma_addr = dma_addr;
 
+	return ((dma_addr_t)dma_addr);
 }
 
 void
 sn1_pci_unmap_single (struct pci_dev *hwdev, dma_addr_t dma_addr, size_t size, int direction)
 {
+
+	struct sn1_dma_maps_s *sn1_dma_map = NULL;
+
         if (direction == PCI_DMA_NONE)
-                BUG();
-        /* Nothing to do */
+		BUG();
+
+	/*
+	 * Get the sn1_dma_map entry.
+	 */
+	if (IS_PCI32_MAPPED(dma_addr))
+		sn1_dma_map = find_sn1_dma_map(dma_addr, hwdev->bus->number);
+
+	if (sn1_dma_map) {
+		pciio_dmamap_done((pciio_dmamap_t)sn1_dma_map);
+		pciio_dmamap_free((pciio_dmamap_t)sn1_dma_map);
+		sn1_dma_map->dma_addr = (dma_addr_t)NULL;
+	}
+
 }
 
 void
 sn1_pci_dma_sync_single (struct pci_dev *hwdev, dma_addr_t dma_handle, size_t size, int direction)
 {
+	
         if (direction == PCI_DMA_NONE)
                 BUG();
         /* Nothing to do */
@@ -330,5 +428,5 @@
 unsigned long
 sn1_dma_address (struct scatterlist *sg)
 {
-	return (sg->address);
+	return ((unsigned long)sg->address);
 }

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