1 /* ioport.c: Simple io mapping allocator.
2 *
3 * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
4 * Copyright (C) 1995 Miguel de Icaza (miguel@nuclecu.unam.mx)
5 *
6 * The routines in this file should be changed for a memory allocator
7 * that would be setup just like NetBSD does : you create regions that
8 * are administered by a general purpose allocator, and then you call
9 * that allocator with your handle and the block size instead of this
10 * weak stuff.
11 *
12 * XXX No joke, this needs to be rewritten badly. XXX
13 */
14
15 #include <linux/sched.h>
16 #include <linux/kernel.h>
17 #include <linux/errno.h>
18 #include <linux/types.h>
19 #include <linux/ioport.h>
20
21 #include <asm/io.h>
22 #include <asm/vaddrs.h>
23 #include <asm/oplib.h>
24
25 /* This points to the next to use virtual memory for io mappings */
26 static long next_free_region = IOBASE_VADDR;
27 static long dvma_next_free = DVMA_VADDR;
28
29 /*
30 * sparc_alloc_dev:
31 * Map and allocates an obio device.
32 * Implements a simple linear allocator, you can force the function
33 * to use your own mapping, but in practice this should not be used.
34 *
35 * Input:
36 * address: the obio address to map
37 * virtual: if non zero, specifies a fixed virtual address where
38 * the mapping should take place.
39 * len: the length of the mapping
40 * bus_type: The bus on which this io area sits.
41 *
42 * Returns:
43 * The virtual address where the mapping actually took place.
44 */
45
46 void *sparc_alloc_io (void *address, void *virtual, int len, char *name,
/* ![[previous]](../icons/n_left.png)
![[next]](../icons/right.png)
![[first]](../icons/n_first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
47 int bus_type, int rdonly)
48 {
49 unsigned long vaddr, base_address;
50 unsigned long addr = (unsigned long) address;
51
52
53 if (virtual){
54 vaddr = (unsigned long) virtual;
55 } else {
56 vaddr = next_free_region;
57 }
58
59 if (((unsigned long) virtual + len) > (IOBASE_VADDR + IOBASE_LEN)){
60 printk ("alloc_io: Mapping ouside IOBASE area\n");
61 prom_halt ();
62 }
63 if (check_region (vaddr, len)){
64 printk ("alloc_io: 0x%lx is already in use\n", vaddr);
65 prom_halt ();
66 }
67
68 /* Tell Linux resource manager about the mapping */
69 request_region (vaddr, len, name);
70
71 base_address = vaddr;
72 /* Do the actual mapping */
73 for (; len > 0; len -= PAGE_SIZE){
74 mapioaddr (addr, vaddr, bus_type, rdonly);
75 vaddr += PAGE_SIZE;
76 addr += PAGE_SIZE;
77 if (!virtual)
78 next_free_region += PAGE_SIZE;
79 }
80 return (void *) base_address;
81 }
82
83 /* Does DVMA allocations with PAGE_SIZE granulatity */
84 void *sparc_dvma_malloc (int len, char *name)
/* ![[previous]](../icons/left.png)
![[next]](../icons/n_right.png)
![[first]](../icons/first.png)
![[last]](../icons/n_last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
85 {
86 unsigned long vaddr, base_address;
87
88 vaddr = dvma_next_free;
89 if (check_region (vaddr, len)){
90 printk ("alloc_dma: 0x%lx is already in use\n", vaddr);
91 prom_halt ();
92 }
93 if (vaddr + len > (DVMA_VADDR + DVMA_LEN)){
94 printk ("alloc_dvma: out of dvma memory\n");
95 prom_halt ();
96 }
97
98 /* Tell Linux resource manager about the mapping */
99 request_region (vaddr, len, name);
100
101 base_address = vaddr;
102 /* Assign the memory area and remove the cache bit */
103 /* XXX EWWWWEE!! Sun4c specific, fix now! XXX */
104 for (; len > 0; len -= PAGE_SIZE){
105 printk ("Len=%d\n", len);
106 put_pte (vaddr, get_pte (vaddr) | PTE_NC);
107 vaddr += PAGE_SIZE;
108 dvma_next_free += PAGE_SIZE;
109 }
110 return (void *) base_address;
111 }