|
|
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.