File: ioport.c

package info (click to toggle)
kernel-source-2.0.32 2.0.32-5
  • links: PTS
  • area: main
  • in suites: hamm
  • size: 29,648 kB
  • ctags: 86,850
  • sloc: ansic: 542,141; asm: 26,201; makefile: 3,423; sh: 1,195; perl: 727; tcl: 408; cpp: 277; lisp: 211; awk: 134
file content (121 lines) | stat: -rw-r--r-- 3,723 bytes parent folder | download | duplicates (7)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
/* $Id: ioport.c,v 1.18 1996/04/25 06:08:44 davem Exp $
 * ioport.c:  Simple io mapping allocator.
 *
 * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
 * Copyright (C) 1995 Miguel de Icaza (miguel@nuclecu.unam.mx)
 *
 * The routines in this file should be changed for a memory allocator
 * that would be setup just like NetBSD does : you create regions that
 * are administered by a general purpose allocator, and then you call
 * that allocator with your handle and the block size instead of this
 * weak stuff.
 *
 * XXX No joke, this needs to be rewritten badly. XXX
 */

#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 long next_free_region = IOBASE_VADDR;
static long dvma_next_free   = DVMA_VADDR;

/*
 * 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: the obio 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: The bus on which this io area sits.
 *
 * Returns:
 *  The virtual address where the mapping actually took place.
 */

void *sparc_alloc_io (void *address, void *virtual, int len, char *name,
		      int bus_type, int rdonly)
{
	unsigned long vaddr, base_address;
	unsigned long addr = (unsigned long) address;
	unsigned long offset = (addr & (~PAGE_MASK));

	if (virtual)
		vaddr = (unsigned long) virtual;
	else
		vaddr = next_free_region;
		
	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);

	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;
		if (!virtual)
			next_free_region += PAGE_SIZE;
	}
	return (void *) (base_address | offset);
}

/* 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)
 */
void *sparc_dvma_malloc (int len, char *name)
{
	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 pre-mapped in paging_init()
	 */
	base_address = vaddr;
	/* Assign the memory area. */
	dvma_next_free = PAGE_ALIGN(dvma_next_free+len);

	request_region(base_address, len, name);

	return (void *) base_address;
}