|
|
1.1 root 1: /*
2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
6: * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7: * Reserved. This file contains Original Code and/or Modifications of
8: * Original Code as defined in and that are subject to the Apple Public
9: * Source License Version 1.1 (the "License"). You may not use this file
10: * except in compliance with the License. Please obtain a copy of the
11: * License at http://www.apple.com/publicsource and read it before using
12: * this file.
13: *
14: * The Original Code and all software distributed under the License are
15: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
19: * License for the specific language governing rights and limitations
20: * under the License.
21: *
22: * @APPLE_LICENSE_HEADER_END@
23: */
24:
25: /*
26: * Copyright (c) 1994 NeXT Computer, Inc.
27: *
28: * Kernel Bus Generic Memory Resource Object(s).
29: *
30: * HISTORY
31: *
32: * 15 Mar 1994 ? at NeXT
33: * Created.
34: */
35:
36: #import <mach/mach_types.h>
37: #import <vm/vm_kern.h>
38:
39: #import <driverkit/KernBusMemory.h>
40:
41: @implementation KernBusMemoryRange
42:
43: - mapToAddress: (vm_offset_t)destAddr
44: inTarget: (task_t)task
45: cache: (IOCache)cache
46: {
47: Range subRange = [self range];
48:
49: subRange.base = 0;
50:
51: return [[KernBusMemoryRangeMapping alloc]
52: initWithRange:self
53: subRange:subRange
54: atAddress:destAddr
55: inTarget:task
56: cache:cache];
57: }
58:
59: - mapInTarget: (task_t)task
60: cache: (IOCache)cache
61: {
62: Range subRange = [self range];
63:
64: subRange.base = 0;
65:
66: return [[KernBusMemoryRangeMapping alloc]
67: initWithRange:self
68: subRange:subRange
69: inTarget:task
70: cache:cache];
71: }
72:
73: @end
74:
75: #if ppc
76: #include <machdep/ppc/proc_reg.h>
77: #endif
78:
79: @implementation KernBusMemoryRangeMapping
80:
81: - initWithRange: range
82: subRange: (Range)subRange
83: atAddress: (vm_offset_t)address
84: inTarget: (task_t)task
85: cache: (IOCache)cache
86: {
87: Range mappedRange;
88:
89: if (task == TASK_NULL)
90: return [self free];
91:
92: if ([super initWithRange:range subRange:subRange] == nil)
93: return nil;
94:
95: mappedRange = [self mappedRange]; // absolute physical range
96:
97: #if ppc
98:
99: if( (task->map->pmap == kernel_pmap)
100: && (IO_CacheOff == cache)
101: && (address == PEMapSegment( mappedRange.base, mappedRange.length)) ) {
102:
103: _address = address;
104: _task = TASK_NULL;
105: return self;
106:
107: } else {
108:
109: vm_offset_t spa, epa;
110:
111: spa = mappedRange.base & 0xfffff000;
112: epa = (mappedRange.base + mappedRange.length + 0xfff) & 0xfffff000;
113: // non fatal - it may overlap another range
114: pmap_add_physical_memory( spa, epa, FALSE, PTE_WIMG_IO);
115: }
116:
117: #endif
118:
119: if (_KernBusMemoryCreateMapping(
120: mappedRange.base,
121: mappedRange.length, // will not work if == 0
122: &address,
123: task,
124: NO,
125: cache) != KERN_SUCCESS)
126: return [self free];
127:
128: _task = task;
129: _address = address;
130:
131: return self;
132: }
133:
134: - initWithRange: range
135: subRange: (Range)subRange
136: inTarget: (task_t)task
137: cache: (IOCache)cache
138: {
139: Range mappedRange;
140:
141: if (task == TASK_NULL)
142: return [self free];
143:
144: if ([super initWithRange:range subRange:subRange] == nil)
145: return nil;
146:
147: mappedRange = [self mappedRange]; // absolute physical range
148:
149: #if ppc
150:
151: if( (task->map->pmap == kernel_pmap)
152: && (IO_CacheOff == cache)
153: && (_address = PEMapSegment( mappedRange.base, mappedRange.length)) ) {
154:
155: _task = TASK_NULL;
156: return self;
157:
158: } else {
159:
160: vm_offset_t spa, epa;
161:
162: spa = mappedRange.base & 0xfffff000;
163: epa = (mappedRange.base + mappedRange.length + 0xfff) & 0xfffff000;
164: // non fatal - it may overlap another range
165: pmap_add_physical_memory( spa, epa, FALSE, PTE_WIMG_IO);
166: }
167:
168: #endif
169:
170: if (_KernBusMemoryCreateMapping(
171: mappedRange.base,
172: mappedRange.length, // will not work if == 0
173: &_address,
174: task,
175: YES,
176: cache) != KERN_SUCCESS)
177: return [self free];
178:
179: _task = task;
180:
181: return self;
182: }
183:
184: - free
185: {
186: Range mappedRange = [self mappedRange];
187:
188: if (_task != TASK_NULL)
189: (void) vm_deallocate(_task->map, _address, mappedRange.length);
190:
191: return [super free];
192: }
193:
194: - (task_t)task
195: {
196: return _task;
197: }
198:
199: - (vm_offset_t)address
200: {
201: return _address;
202: }
203:
204: @end
205:
206: kern_return_t
207: _KernBusMemoryCreateMapping(
208: vm_offset_t physAddr,
209: vm_size_t length,
210: vm_offset_t *destAddr,
211: task_t task,
212: BOOL findSpace,
213: IOCache cache
214: )
215: {
216: kern_return_t result;
217: vm_map_t map = task->map;
218: vm_offset_t virtAddr;
219: cache_spec_t caching;
220:
221: vm_map_reference(map);
222:
223: if (findSpace)
224: *destAddr = vm_map_min(map);
225: else
226: *destAddr = trunc_page(*destAddr);
227:
228: length = round_page(length);
229:
230: result = vm_map_find(
231: map,
232: VM_OBJECT_NULL, (vm_offset_t) 0,
233: destAddr, length,
234: findSpace);
235:
236: if (result != KERN_SUCCESS) {
237: vm_map_deallocate(map);
238: return result;
239: }
240:
241: virtAddr = trunc_page(*destAddr);
242:
243: (void) vm_map_inherit(
244: map,
245: virtAddr, virtAddr + length,
246: VM_INHERIT_NONE);
247:
248: physAddr = trunc_page(physAddr);
249:
250: switch (cache) {
251:
252: case IO_CacheOff:
253: caching = cache_disable;
254: break;
255:
256: case IO_WriteThrough:
257: caching = cache_writethrough;
258: break;
259:
260: default:
261: caching = cache_default;
262: break;
263: }
264:
265: while (length > 0) {
266: pmap_enter_cache_spec(
267: vm_map_pmap(map),
268: virtAddr,
269: physAddr,
270: VM_PROT_READ | VM_PROT_WRITE,
271: TRUE,
272: caching);
273:
274: virtAddr += PAGE_SIZE; length -= PAGE_SIZE; physAddr += PAGE_SIZE;
275: }
276:
277: vm_map_deallocate(map);
278:
279: return KERN_SUCCESS;
280: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.