2 * Copyright (c) 1998-2004 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
20 * @APPLE_LICENSE_HEADER_END@
22 #include <IOKit/IOLib.h>
23 #include <IOKit/IOMapper.h>
24 #include <libkern/c++/OSData.h>
26 #include "IOCopyMapper.h"
29 extern ppnum_t
pmap_find_phys(pmap_t pmap
, addr64_t va
);
32 #define super IOService
33 OSDefineMetaClassAndAbstractStructors(IOMapper
, IOService
);
35 OSMetaClassDefineReservedUsed(IOMapper
, 0);
36 OSMetaClassDefineReservedUnused(IOMapper
, 1);
37 OSMetaClassDefineReservedUnused(IOMapper
, 2);
38 OSMetaClassDefineReservedUnused(IOMapper
, 3);
39 OSMetaClassDefineReservedUnused(IOMapper
, 4);
40 OSMetaClassDefineReservedUnused(IOMapper
, 5);
41 OSMetaClassDefineReservedUnused(IOMapper
, 6);
42 OSMetaClassDefineReservedUnused(IOMapper
, 7);
43 OSMetaClassDefineReservedUnused(IOMapper
, 8);
44 OSMetaClassDefineReservedUnused(IOMapper
, 9);
45 OSMetaClassDefineReservedUnused(IOMapper
, 10);
46 OSMetaClassDefineReservedUnused(IOMapper
, 11);
47 OSMetaClassDefineReservedUnused(IOMapper
, 12);
48 OSMetaClassDefineReservedUnused(IOMapper
, 13);
49 OSMetaClassDefineReservedUnused(IOMapper
, 14);
50 OSMetaClassDefineReservedUnused(IOMapper
, 15);
52 IOMapper
* IOMapper::gSystem
= (IOMapper
*) IOMapper::kUnknown
;
57 IOMapperLock() { fWaitLock
= IOLockAlloc(); };
58 ~IOMapperLock() { IOLockFree(fWaitLock
); };
60 void lock() { IOLockLock(fWaitLock
); };
61 void unlock() { IOLockUnlock(fWaitLock
); };
62 void sleep(void *event
) { IOLockSleep(fWaitLock
, event
, THREAD_UNINT
); };
63 void wakeup(void *event
) { IOLockWakeup(fWaitLock
, event
, false); };
66 static IOMapperLock sMapperLock
;
68 bool IOMapper::start(IOService
*provider
)
70 if (!super::start(provider
))
73 if (!initHardware(provider
))
78 IOMapper::gSystem
= this;
79 sMapperLock
.wakeup(&IOMapper::gSystem
);
86 bool IOMapper::allocTable(IOByteCount size
)
91 fTableHandle
= NewARTTable(size
, &fTable
, &fTablePhys
);
92 return fTableHandle
!= 0;
98 FreeARTTable(fTableHandle
, fTableSize
);
105 void IOMapper::setMapperRequired(bool hasMapper
)
108 IOMapper::gSystem
= (IOMapper
*) kHasMapper
;
111 IOMapper::gSystem
= (IOMapper
*) kNoMapper
;
112 sMapperLock
.unlock();
113 sMapperLock
.wakeup(&IOMapper::gSystem
);
117 void IOMapper::waitForSystemMapper()
120 while ((vm_address_t
) IOMapper::gSystem
& kWaitMask
)
121 sMapperLock
.sleep(&IOMapper::gSystem
);
122 sMapperLock
.unlock();
125 void IOMapper::iovmInsert(ppnum_t addr
, IOItemCount offset
,
126 ppnum_t
*pageList
, IOItemCount pageCount
)
129 iovmInsert(addr
, offset
++, *pageList
++);
132 void IOMapper::iovmInsert(ppnum_t addr
, IOItemCount offset
,
133 upl_page_info_t
*pageList
, IOItemCount pageCount
)
135 for (IOItemCount i
= 0; i
< pageCount
; i
++)
136 iovmInsert(addr
, offset
+ i
, pageList
[i
].phys_addr
);
140 NewARTTable(IOByteCount size
, void ** virtAddrP
, ppnum_t
*physAddrP
)
142 if (!virtAddrP
|| !physAddrP
)
146 vm_address_t address
;
148 size
= round_page_32(size
);
149 kr
= kmem_alloc_contig(kernel_map
, &address
, size
, PAGE_MASK
, 0);
153 ppnum_t pagenum
= pmap_find_phys(kernel_pmap
, (addr64_t
) address
);
155 *physAddrP
= pagenum
;
157 FreeARTTable((OSData
*) address
, size
);
161 *virtAddrP
= (void *) address
;
163 return (OSData
*) address
;
166 void IOMapper::FreeARTTable(OSData
*artHandle
, IOByteCount size
)
168 vm_address_t address
= (vm_address_t
) artHandle
;
170 size
= round_page_32(size
);
171 kmem_free(kernel_map
, address
, size
); // Just panic if address is 0
174 bool IOMapper::getBypassMask(addr64_t
*maskP
) const
181 // These are C accessors to the system mapper for non-IOKit clients
182 ppnum_t
IOMapperIOVMAlloc(unsigned pages
)
184 IOMapper::checkForSystemMapper();
186 if (IOMapper::gSystem
)
187 return IOMapper::gSystem
->iovmAlloc((IOItemCount
) pages
);
192 void IOMapperIOVMFree(ppnum_t addr
, unsigned pages
)
194 if (IOMapper::gSystem
)
195 IOMapper::gSystem
->iovmFree(addr
, (IOItemCount
) pages
);
198 ppnum_t
IOMapperInsertPage(ppnum_t addr
, unsigned offset
, ppnum_t page
)
200 if (IOMapper::gSystem
) {
201 IOMapper::gSystem
->iovmInsert(addr
, (IOItemCount
) offset
, page
);
202 return addr
+ offset
;
208 void IOMapperInsertPPNPages(ppnum_t addr
, unsigned offset
,
209 ppnum_t
*pageList
, unsigned pageCount
)
211 if (!IOMapper::gSystem
)
212 panic("IOMapperInsertPPNPages no system mapper");
214 assert(!((vm_address_t
) IOMapper::gSystem
& 3));
217 iovmInsert(addr
, (IOItemCount
) offset
, pageList
, pageCount
);
220 void IOMapperInsertUPLPages(ppnum_t addr
, unsigned offset
,
221 upl_page_info_t
*pageList
, unsigned pageCount
)
223 if (!IOMapper::gSystem
)
224 panic("IOMapperInsertUPLPages no system mapper");
226 assert(!((vm_address_t
) IOMapper::gSystem
& 3));
228 IOMapper::gSystem
->iovmInsert(addr
,
229 (IOItemCount
) offset
,
231 (IOItemCount
) pageCount
);
234 /////////////////////////////////////////////////////////////////////////////
240 /////////////////////////////////////////////////////////////////////////////
242 #include <machine/machine_routines.h>
244 UInt8
IOMappedRead8(IOPhysicalAddress address
)
246 IOMapper::checkForSystemMapper();
248 if (IOMapper::gSystem
) {
249 addr64_t addr
= IOMapper::gSystem
->mapAddr(address
);
250 return (UInt8
) ml_phys_read_byte_64(addr
);
253 return (UInt8
) ml_phys_read_byte((vm_offset_t
) address
);
256 UInt16
IOMappedRead16(IOPhysicalAddress address
)
258 IOMapper::checkForSystemMapper();
260 if (IOMapper::gSystem
) {
261 addr64_t addr
= IOMapper::gSystem
->mapAddr(address
);
262 return (UInt16
) ml_phys_read_half_64(addr
);
265 return (UInt16
) ml_phys_read_half((vm_offset_t
) address
);
268 UInt32
IOMappedRead32(IOPhysicalAddress address
)
270 IOMapper::checkForSystemMapper();
272 if (IOMapper::gSystem
) {
273 addr64_t addr
= IOMapper::gSystem
->mapAddr(address
);
274 return (UInt32
) ml_phys_read_word_64(addr
);
277 return (UInt32
) ml_phys_read_word((vm_offset_t
) address
);
280 UInt64
IOMappedRead64(IOPhysicalAddress address
)
282 IOMapper::checkForSystemMapper();
284 if (IOMapper::gSystem
) {
285 addr64_t addr
= IOMapper::gSystem
->mapAddr(address
);
286 return (UInt64
) ml_phys_read_double_64(addr
);
289 return (UInt64
) ml_phys_read_double((vm_offset_t
) address
);
292 void IOMappedWrite8(IOPhysicalAddress address
, UInt8 value
)
294 IOMapper::checkForSystemMapper();
296 if (IOMapper::gSystem
) {
297 addr64_t addr
= IOMapper::gSystem
->mapAddr(address
);
298 ml_phys_write_byte_64(addr
, value
);
301 ml_phys_write_byte((vm_offset_t
) address
, value
);
304 void IOMappedWrite16(IOPhysicalAddress address
, UInt16 value
)
306 IOMapper::checkForSystemMapper();
308 if (IOMapper::gSystem
) {
309 addr64_t addr
= IOMapper::gSystem
->mapAddr(address
);
310 ml_phys_write_half_64(addr
, value
);
313 ml_phys_write_half((vm_offset_t
) address
, value
);
316 void IOMappedWrite32(IOPhysicalAddress address
, UInt32 value
)
318 IOMapper::checkForSystemMapper();
320 if (IOMapper::gSystem
) {
321 addr64_t addr
= IOMapper::gSystem
->mapAddr(address
);
322 ml_phys_write_word_64(addr
, value
);
325 ml_phys_write_word((vm_offset_t
) address
, value
);
328 void IOMappedWrite64(IOPhysicalAddress address
, UInt64 value
)
330 IOMapper::checkForSystemMapper();
332 if (IOMapper::gSystem
) {
333 addr64_t addr
= IOMapper::gSystem
->mapAddr(address
);
334 ml_phys_write_double_64(addr
, value
);
337 ml_phys_write_double((vm_offset_t
) address
, value
);
340 mach_vm_address_t
IOMallocPhysical(mach_vm_size_t size
, mach_vm_address_t mask
)
342 mach_vm_address_t address
= 0;
345 address
= ptoa_64(gIOCopyMapper
->iovmAlloc(atop_64(round_page(size
))));
351 void IOFreePhysical(mach_vm_address_t address
, mach_vm_size_t size
)
355 gIOCopyMapper
->iovmFree(atop_64(address
), atop_64(round_page(size
)));