1 /* $Id: ioport.c,v 1.12 1995/11/25 00:58:07 davem Exp $
2 * ioport.c: Simple io mapping allocator.
3 *
4 * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
5 * Copyright (C) 1995 Miguel de Icaza (miguel@nuclecu.unam.mx)
6 *
7 * The routines in this file should be changed for a memory allocator
8 * that would be setup just like NetBSD does : you create regions that
9 * are administered by a general purpose allocator, and then you call
10 * that allocator with your handle and the block size instead of this
11 * weak stuff.
12 *
13 * XXX No joke, this needs to be rewritten badly. XXX
14 */
15
16 #include <linux/sched.h>
17 #include <linux/kernel.h>
18 #include <linux/errno.h>
19 #include <linux/types.h>
20 #include <linux/ioport.h>
21 #include <linux/mm.h>
22
23 #include <asm/io.h>
24 #include <asm/vaddrs.h>
25 #include <asm/oplib.h>
26 #include <asm/page.h>
27 #include <asm/pgtable.h>
28
29 /* This points to the next to use virtual memory for io mappings */
30 static long next_free_region = IOBASE_VADDR;
31 static long dvma_next_free = DVMA_VADDR;
32
33 /*
34 * sparc_alloc_dev:
35 * Map and allocates an obio device.
36 * Implements a simple linear allocator, you can force the function
37 * to use your own mapping, but in practice this should not be used.
38 *
39 * Input:
40 * address: the obio address to map
41 * virtual: if non zero, specifies a fixed virtual address where
42 * the mapping should take place.
43 * len: the length of the mapping
44 * bus_type: The bus on which this io area sits.
45 *
46 * Returns:
47 * The virtual address where the mapping actually took place.
48 */
49
50 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)
*/
51 int bus_type, int rdonly)
52 {
53 unsigned long vaddr, base_address;
54 unsigned long addr = (unsigned long) address;
55 unsigned long offset = (addr & (~PAGE_MASK));
56
57 if (virtual){
58 vaddr = (unsigned long) virtual;
59 } else {
60 vaddr = next_free_region;
61 }
62
63 len += offset;
64 if (((unsigned long) virtual + len) > (IOBASE_VADDR + IOBASE_LEN)){
65 printk ("alloc_io: Mapping ouside IOBASE area\n");
66 prom_halt ();
67 }
68 if (check_region ((vaddr | offset), len)){
69 printk ("alloc_io: 0x%lx is already in use\n", vaddr);
70 prom_halt ();
71 }
72
73 /* Tell Linux resource manager about the mapping */
74 request_region ((vaddr | offset), len, name);
75
76 base_address = vaddr;
77 /* Do the actual mapping */
78 for (; len > 0; len -= PAGE_SIZE){
79 mapioaddr (addr, vaddr, bus_type, rdonly);
80 vaddr += PAGE_SIZE;
81 addr += PAGE_SIZE;
82 if (!virtual)
83 next_free_region += PAGE_SIZE;
84 }
85 return (void *) (base_address | offset);
86 }
87
88 /* Does DVMA allocations with PAGE_SIZE granulatity. How this basically
89 * works is that the ESP chip can do DVMA transfers at ANY address with
90 * certain size and boundry restrictions. But other devices that are
91 * attached to it and would like to do DVMA have to set things up in
92 * a special way, if the DVMA see's a device attached to it transfer data
93 * at addresses above DVMA_VADDR it will grab them, this way it does not
94 * now have to know the peculiarities of where to read the Lance data
95 * from. (for example)
96 */
97 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)
*/
98 {
99 unsigned long vaddr, base_address;
100
101 vaddr = dvma_next_free;
102 if (check_region (vaddr, len)){
103 printk ("alloc_dma: 0x%lx is already in use\n", vaddr);
104 prom_halt ();
105 }
106 if (vaddr + len > (DVMA_VADDR + DVMA_LEN)){
107 printk ("alloc_dvma: out of dvma memory\n");
108 prom_halt ();
109 }
110
111 /* Basically these can be mapped just like any old
112 * IO pages, cacheable bit off, etc. The physical
113 * pages are pre-mapped in paging_init()
114 */
115 base_address = vaddr;
116 /* Assign the memory area. */
117 dvma_next_free = PAGE_ALIGN(dvma_next_free+len);
118
119 request_region(base_address, len, name);
120
121 return (void *) base_address;
122 }