summaryrefslogtreecommitdiffstats
path: root/arch/sparc64/kernel/ioport.c
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>1997-04-29 21:13:14 +0000
committer <ralf@linux-mips.org>1997-04-29 21:13:14 +0000
commit19c9bba94152148523ba0f7ef7cffe3d45656b11 (patch)
tree40b1cb534496a7f1ca0f5c314a523c69f1fee464 /arch/sparc64/kernel/ioport.c
parent7206675c40394c78a90e74812bbdbf8cf3cca1be (diff)
Import of Linux/MIPS 2.1.36
Diffstat (limited to 'arch/sparc64/kernel/ioport.c')
-rw-r--r--arch/sparc64/kernel/ioport.c139
1 files changed, 139 insertions, 0 deletions
diff --git a/arch/sparc64/kernel/ioport.c b/arch/sparc64/kernel/ioport.c
new file mode 100644
index 000000000..2f94e9102
--- /dev/null
+++ b/arch/sparc64/kernel/ioport.c
@@ -0,0 +1,139 @@
+/* $Id: ioport.c,v 1.7 1997/04/10 05:13:01 davem Exp $
+ * ioport.c: Simple io mapping allocator.
+ *
+ * Copyright (C) 1995,1996 David S. Miller (davem@caip.rutgers.edu)
+ * Copyright (C) 1995 Miguel de Icaza (miguel@nuclecu.unam.mx)
+ */
+
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/types.h>
+#include <linux/ioport.h>
+#include <linux/mm.h>
+
+#include <asm/io.h>
+#include <asm/vaddrs.h>
+#include <asm/oplib.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+
+/* This points to the next to use virtual memory for io mappings */
+static unsigned long dvma_next_free = DVMA_VADDR;
+unsigned long sparc_iobase_vaddr = IOBASE_VADDR;
+
+extern void mmu_map_dma_area(unsigned long addr, int len, __u32 *dvma_addr);
+
+/*
+ * sparc_alloc_io:
+ * Map and allocates an obio device.
+ * Implements a simple linear allocator, you can force the function
+ * to use your own mapping, but in practice this should not be used.
+ *
+ * Input:
+ * address: Physical address to map
+ * virtual: if non zero, specifies a fixed virtual address where
+ * the mapping should take place.
+ * len: the length of the mapping
+ * bus_type: Optional high word of physical address.
+ *
+ * Returns:
+ * The virtual address where the mapping actually took place.
+ */
+
+void *sparc_alloc_io (u32 address, void *virtual, int len, char *name,
+ u32 bus_type, int rdonly)
+{
+ unsigned long vaddr, base_address;
+ unsigned long addr = ((unsigned long) address) + (((unsigned long) bus_type) << 32);
+ unsigned long offset = (addr & (~PAGE_MASK));
+
+ if (virtual) {
+ vaddr = (unsigned long) virtual;
+
+ len += offset;
+ if(((unsigned long) virtual + len) > (IOBASE_VADDR + IOBASE_LEN)) {
+ prom_printf("alloc_io: Mapping outside IOBASE area\n");
+ prom_halt();
+ }
+ if(check_region ((vaddr | offset), len)) {
+ prom_printf("alloc_io: 0x%lx is already in use\n", vaddr);
+ prom_halt();
+ }
+
+ /* Tell Linux resource manager about the mapping */
+ request_region ((vaddr | offset), len, name);
+ } else {
+ vaddr = occupy_region(sparc_iobase_vaddr, IOBASE_END,
+ (offset + len + PAGE_SIZE-1) & PAGE_MASK, PAGE_SIZE, name);
+ if (vaddr == 0) {
+ /* Usually we cannot see printks in this case. */
+ prom_printf("alloc_io: cannot occupy %d region\n", len);
+ prom_halt();
+ }
+ }
+
+ base_address = vaddr;
+ /* Do the actual mapping */
+ for (; len > 0; len -= PAGE_SIZE) {
+ mapioaddr(addr, vaddr, bus_type, rdonly);
+ vaddr += PAGE_SIZE;
+ addr += PAGE_SIZE;
+ }
+
+ return (void *) (base_address | offset);
+}
+
+void sparc_free_io (void *virtual, int len)
+{
+ unsigned long vaddr = (unsigned long) virtual & PAGE_MASK;
+ unsigned long plen = (((unsigned long)virtual & ~PAGE_MASK) + len + PAGE_SIZE-1) & PAGE_MASK;
+
+ release_region(vaddr, plen);
+
+ for (; plen != 0;) {
+ plen -= PAGE_SIZE;
+ unmapioaddr(vaddr + plen);
+ }
+}
+
+/* Does DVMA allocations with PAGE_SIZE granularity. How this basically
+ * works is that the ESP chip can do DVMA transfers at ANY address with
+ * certain size and boundary restrictions. But other devices that are
+ * attached to it and would like to do DVMA have to set things up in
+ * a special way, if the DVMA sees a device attached to it transfer data
+ * at addresses above DVMA_VADDR it will grab them, this way it does not
+ * now have to know the peculiarities of where to read the Lance data
+ * from. (for example)
+ *
+ * Returns CPU visible address for the buffer returned, dvma_addr is
+ * set to the DVMA visible address.
+ */
+void *sparc_dvma_malloc (int len, char *name, __u32 *dvma_addr)
+{
+ unsigned long vaddr, base_address;
+
+ vaddr = dvma_next_free;
+ if(check_region (vaddr, len)) {
+ prom_printf("alloc_dma: 0x%lx is already in use\n", vaddr);
+ prom_halt();
+ }
+ if(vaddr + len > (DVMA_VADDR + DVMA_LEN)) {
+ prom_printf("alloc_dvma: out of dvma memory\n");
+ prom_halt();
+ }
+
+ /* Basically these can be mapped just like any old
+ * IO pages, cacheable bit off, etc. The physical
+ * pages are now mapped dynamically to save space.
+ */
+ base_address = vaddr;
+ mmu_map_dma_area(base_address, len, dvma_addr);
+
+ /* Assign the memory area. */
+ dvma_next_free = PAGE_ALIGN(dvma_next_free+len);
+
+ request_region(base_address, len, name);
+
+ return (void *) base_address;
+}