2 * Copyright (c) 1998-2004 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_OSREFERENCE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the
10 * License may not be used to create, or enable the creation or
11 * redistribution of, unlawful or unlicensed copies of an Apple operating
12 * system, or to circumvent, violate, or enable the circumvention or
13 * violation of, any terms of an Apple operating system software license
16 * Please obtain a copy of the License at
17 * http://www.opensource.apple.com/apsl/ and read it before using this
20 * The Original Code and all software distributed under the License are
21 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
22 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
23 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
24 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
25 * Please see the License for the specific language governing rights and
26 * limitations under the License.
28 * @APPLE_LICENSE_OSREFERENCE_HEADER_END@
30 #include <IOKit/IOLib.h>
31 #include <IOKit/IOMapper.h>
32 #include <libkern/c++/OSData.h>
34 #include "IOCopyMapper.h"
37 extern ppnum_t
pmap_find_phys(pmap_t pmap
, addr64_t va
);
40 #define super IOService
41 OSDefineMetaClassAndAbstractStructors(IOMapper
, IOService
);
43 OSMetaClassDefineReservedUsed(IOMapper
, 0);
44 OSMetaClassDefineReservedUnused(IOMapper
, 1);
45 OSMetaClassDefineReservedUnused(IOMapper
, 2);
46 OSMetaClassDefineReservedUnused(IOMapper
, 3);
47 OSMetaClassDefineReservedUnused(IOMapper
, 4);
48 OSMetaClassDefineReservedUnused(IOMapper
, 5);
49 OSMetaClassDefineReservedUnused(IOMapper
, 6);
50 OSMetaClassDefineReservedUnused(IOMapper
, 7);
51 OSMetaClassDefineReservedUnused(IOMapper
, 8);
52 OSMetaClassDefineReservedUnused(IOMapper
, 9);
53 OSMetaClassDefineReservedUnused(IOMapper
, 10);
54 OSMetaClassDefineReservedUnused(IOMapper
, 11);
55 OSMetaClassDefineReservedUnused(IOMapper
, 12);
56 OSMetaClassDefineReservedUnused(IOMapper
, 13);
57 OSMetaClassDefineReservedUnused(IOMapper
, 14);
58 OSMetaClassDefineReservedUnused(IOMapper
, 15);
60 IOMapper
* IOMapper::gSystem
= (IOMapper
*) IOMapper::kUnknown
;
65 IOMapperLock() { fWaitLock
= IOLockAlloc(); };
66 ~IOMapperLock() { IOLockFree(fWaitLock
); };
68 void lock() { IOLockLock(fWaitLock
); };
69 void unlock() { IOLockUnlock(fWaitLock
); };
70 void sleep(void *event
) { IOLockSleep(fWaitLock
, event
, THREAD_UNINT
); };
71 void wakeup(void *event
) { IOLockWakeup(fWaitLock
, event
, false); };
74 static IOMapperLock sMapperLock
;
76 bool IOMapper::start(IOService
*provider
)
78 if (!super::start(provider
))
81 if (!initHardware(provider
))
86 IOMapper::gSystem
= this;
87 sMapperLock
.wakeup(&IOMapper::gSystem
);
94 bool IOMapper::allocTable(IOByteCount size
)
99 fTableHandle
= NewARTTable(size
, &fTable
, &fTablePhys
);
100 return fTableHandle
!= 0;
103 void IOMapper::free()
106 FreeARTTable(fTableHandle
, fTableSize
);
113 void IOMapper::setMapperRequired(bool hasMapper
)
116 IOMapper::gSystem
= (IOMapper
*) kHasMapper
;
119 IOMapper::gSystem
= (IOMapper
*) kNoMapper
;
120 sMapperLock
.unlock();
121 sMapperLock
.wakeup(&IOMapper::gSystem
);
125 void IOMapper::waitForSystemMapper()
128 while ((vm_address_t
) IOMapper::gSystem
& kWaitMask
)
129 sMapperLock
.sleep(&IOMapper::gSystem
);
130 sMapperLock
.unlock();
133 void IOMapper::iovmInsert(ppnum_t addr
, IOItemCount offset
,
134 ppnum_t
*pageList
, IOItemCount pageCount
)
137 iovmInsert(addr
, offset
++, *pageList
++);
140 void IOMapper::iovmInsert(ppnum_t addr
, IOItemCount offset
,
141 upl_page_info_t
*pageList
, IOItemCount pageCount
)
143 for (IOItemCount i
= 0; i
< pageCount
; i
++)
144 iovmInsert(addr
, offset
+ i
, pageList
[i
].phys_addr
);
148 NewARTTable(IOByteCount size
, void ** virtAddrP
, ppnum_t
*physAddrP
)
150 if (!virtAddrP
|| !physAddrP
)
154 vm_address_t address
;
156 size
= round_page_32(size
);
157 kr
= kmem_alloc_contig(kernel_map
, &address
, size
, PAGE_MASK
, 0);
161 ppnum_t pagenum
= pmap_find_phys(kernel_pmap
, (addr64_t
) address
);
163 *physAddrP
= pagenum
;
165 FreeARTTable((OSData
*) address
, size
);
169 *virtAddrP
= (void *) address
;
171 return (OSData
*) address
;
174 void IOMapper::FreeARTTable(OSData
*artHandle
, IOByteCount size
)
176 vm_address_t address
= (vm_address_t
) artHandle
;
178 size
= round_page_32(size
);
179 kmem_free(kernel_map
, address
, size
); // Just panic if address is 0
182 bool IOMapper::getBypassMask(addr64_t
*maskP
) const
189 // These are C accessors to the system mapper for non-IOKit clients
190 ppnum_t
IOMapperIOVMAlloc(unsigned pages
)
192 IOMapper::checkForSystemMapper();
194 if (IOMapper::gSystem
)
195 return IOMapper::gSystem
->iovmAlloc((IOItemCount
) pages
);
200 void IOMapperIOVMFree(ppnum_t addr
, unsigned pages
)
202 if (IOMapper::gSystem
)
203 IOMapper::gSystem
->iovmFree(addr
, (IOItemCount
) pages
);
206 ppnum_t
IOMapperInsertPage(ppnum_t addr
, unsigned offset
, ppnum_t page
)
208 if (IOMapper::gSystem
) {
209 IOMapper::gSystem
->iovmInsert(addr
, (IOItemCount
) offset
, page
);
210 return addr
+ offset
;
216 void IOMapperInsertPPNPages(ppnum_t addr
, unsigned offset
,
217 ppnum_t
*pageList
, unsigned pageCount
)
219 if (!IOMapper::gSystem
)
220 panic("IOMapperInsertPPNPages no system mapper");
222 assert(!((vm_address_t
) IOMapper::gSystem
& 3));
225 iovmInsert(addr
, (IOItemCount
) offset
, pageList
, pageCount
);
228 void IOMapperInsertUPLPages(ppnum_t addr
, unsigned offset
,
229 upl_page_info_t
*pageList
, unsigned pageCount
)
231 if (!IOMapper::gSystem
)
232 panic("IOMapperInsertUPLPages no system mapper");
234 assert(!((vm_address_t
) IOMapper::gSystem
& 3));
236 IOMapper::gSystem
->iovmInsert(addr
,
237 (IOItemCount
) offset
,
239 (IOItemCount
) pageCount
);
242 /////////////////////////////////////////////////////////////////////////////
248 /////////////////////////////////////////////////////////////////////////////
250 #include <machine/machine_routines.h>
252 UInt8
IOMappedRead8(IOPhysicalAddress address
)
254 IOMapper::checkForSystemMapper();
256 if (IOMapper::gSystem
) {
257 addr64_t addr
= IOMapper::gSystem
->mapAddr(address
);
258 return (UInt8
) ml_phys_read_byte_64(addr
);
261 return (UInt8
) ml_phys_read_byte((vm_offset_t
) address
);
264 UInt16
IOMappedRead16(IOPhysicalAddress address
)
266 IOMapper::checkForSystemMapper();
268 if (IOMapper::gSystem
) {
269 addr64_t addr
= IOMapper::gSystem
->mapAddr(address
);
270 return (UInt16
) ml_phys_read_half_64(addr
);
273 return (UInt16
) ml_phys_read_half((vm_offset_t
) address
);
276 UInt32
IOMappedRead32(IOPhysicalAddress address
)
278 IOMapper::checkForSystemMapper();
280 if (IOMapper::gSystem
) {
281 addr64_t addr
= IOMapper::gSystem
->mapAddr(address
);
282 return (UInt32
) ml_phys_read_word_64(addr
);
285 return (UInt32
) ml_phys_read_word((vm_offset_t
) address
);
288 UInt64
IOMappedRead64(IOPhysicalAddress address
)
290 IOMapper::checkForSystemMapper();
292 if (IOMapper::gSystem
) {
293 addr64_t addr
= IOMapper::gSystem
->mapAddr(address
);
294 return (UInt64
) ml_phys_read_double_64(addr
);
297 return (UInt64
) ml_phys_read_double((vm_offset_t
) address
);
300 void IOMappedWrite8(IOPhysicalAddress address
, UInt8 value
)
302 IOMapper::checkForSystemMapper();
304 if (IOMapper::gSystem
) {
305 addr64_t addr
= IOMapper::gSystem
->mapAddr(address
);
306 ml_phys_write_byte_64(addr
, value
);
309 ml_phys_write_byte((vm_offset_t
) address
, value
);
312 void IOMappedWrite16(IOPhysicalAddress address
, UInt16 value
)
314 IOMapper::checkForSystemMapper();
316 if (IOMapper::gSystem
) {
317 addr64_t addr
= IOMapper::gSystem
->mapAddr(address
);
318 ml_phys_write_half_64(addr
, value
);
321 ml_phys_write_half((vm_offset_t
) address
, value
);
324 void IOMappedWrite32(IOPhysicalAddress address
, UInt32 value
)
326 IOMapper::checkForSystemMapper();
328 if (IOMapper::gSystem
) {
329 addr64_t addr
= IOMapper::gSystem
->mapAddr(address
);
330 ml_phys_write_word_64(addr
, value
);
333 ml_phys_write_word((vm_offset_t
) address
, value
);
336 void IOMappedWrite64(IOPhysicalAddress address
, UInt64 value
)
338 IOMapper::checkForSystemMapper();
340 if (IOMapper::gSystem
) {
341 addr64_t addr
= IOMapper::gSystem
->mapAddr(address
);
342 ml_phys_write_double_64(addr
, value
);
345 ml_phys_write_double((vm_offset_t
) address
, value
);
348 mach_vm_address_t
IOMallocPhysical(mach_vm_size_t size
, mach_vm_address_t mask
)
350 mach_vm_address_t address
= 0;
353 address
= ptoa_64(gIOCopyMapper
->iovmAlloc(atop_64(round_page(size
))));
359 void IOFreePhysical(mach_vm_address_t address
, mach_vm_size_t size
)
363 gIOCopyMapper
->iovmFree(atop_64(address
), atop_64(round_page(size
)));