]> git.saurik.com Git - apple/xnu.git/blame - iokit/Kernel/IOMapper.cpp
xnu-792.13.8.tar.gz
[apple/xnu.git] / iokit / Kernel / IOMapper.cpp
CommitLineData
55e303ae 1/*
91447636 2 * Copyright (c) 1998-2004 Apple Computer, Inc. All rights reserved.
55e303ae 3 *
8ad349bb 4 * @APPLE_LICENSE_OSREFERENCE_HEADER_START@
55e303ae 5 *
8ad349bb
A
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
14 * agreement.
15 *
16 * Please obtain a copy of the License at
17 * http://www.opensource.apple.com/apsl/ and read it before using this
18 * file.
19 *
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.
27 *
28 * @APPLE_LICENSE_OSREFERENCE_HEADER_END@
55e303ae
A
29 */
30#include <IOKit/IOLib.h>
31#include <IOKit/IOMapper.h>
32#include <libkern/c++/OSData.h>
33
5d5c5d0d
A
34#include "IOCopyMapper.h"
35
36__BEGIN_DECLS
37extern ppnum_t pmap_find_phys(pmap_t pmap, addr64_t va);
38__END_DECLS
39
55e303ae
A
40#define super IOService
41OSDefineMetaClassAndAbstractStructors(IOMapper, IOService);
42
5d5c5d0d 43OSMetaClassDefineReservedUsed(IOMapper, 0);
55e303ae
A
44OSMetaClassDefineReservedUnused(IOMapper, 1);
45OSMetaClassDefineReservedUnused(IOMapper, 2);
46OSMetaClassDefineReservedUnused(IOMapper, 3);
47OSMetaClassDefineReservedUnused(IOMapper, 4);
48OSMetaClassDefineReservedUnused(IOMapper, 5);
49OSMetaClassDefineReservedUnused(IOMapper, 6);
50OSMetaClassDefineReservedUnused(IOMapper, 7);
51OSMetaClassDefineReservedUnused(IOMapper, 8);
52OSMetaClassDefineReservedUnused(IOMapper, 9);
53OSMetaClassDefineReservedUnused(IOMapper, 10);
54OSMetaClassDefineReservedUnused(IOMapper, 11);
55OSMetaClassDefineReservedUnused(IOMapper, 12);
56OSMetaClassDefineReservedUnused(IOMapper, 13);
57OSMetaClassDefineReservedUnused(IOMapper, 14);
58OSMetaClassDefineReservedUnused(IOMapper, 15);
59
60IOMapper * IOMapper::gSystem = (IOMapper *) IOMapper::kUnknown;
61
62class IOMapperLock {
63 IOLock *fWaitLock;
64public:
65 IOMapperLock() { fWaitLock = IOLockAlloc(); };
66 ~IOMapperLock() { IOLockFree(fWaitLock); };
67
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); };
72};
73
74static IOMapperLock sMapperLock;
75
76bool IOMapper::start(IOService *provider)
77{
78 if (!super::start(provider))
79 return false;
80
81 if (!initHardware(provider))
82 return false;
83
84 if (fIsSystem) {
85 sMapperLock.lock();
86 IOMapper::gSystem = this;
87 sMapperLock.wakeup(&IOMapper::gSystem);
88 sMapperLock.unlock();
89 }
90
91 return true;
92}
93
94bool IOMapper::allocTable(IOByteCount size)
95{
96 assert(!fTable);
97
98 fTableSize = size;
99 fTableHandle = NewARTTable(size, &fTable, &fTablePhys);
100 return fTableHandle != 0;
101}
102
103void IOMapper::free()
104{
105 if (fTableHandle) {
106 FreeARTTable(fTableHandle, fTableSize);
107 fTableHandle = 0;
108 }
109
110 super::free();
111}
112
113void IOMapper::setMapperRequired(bool hasMapper)
114{
115 if (hasMapper)
116 IOMapper::gSystem = (IOMapper *) kHasMapper;
117 else {
118 sMapperLock.lock();
119 IOMapper::gSystem = (IOMapper *) kNoMapper;
120 sMapperLock.unlock();
121 sMapperLock.wakeup(&IOMapper::gSystem);
122 }
123}
124
125void IOMapper::waitForSystemMapper()
126{
127 sMapperLock.lock();
128 while ((vm_address_t) IOMapper::gSystem & kWaitMask)
129 sMapperLock.sleep(&IOMapper::gSystem);
130 sMapperLock.unlock();
131}
132
133void IOMapper::iovmInsert(ppnum_t addr, IOItemCount offset,
134 ppnum_t *pageList, IOItemCount pageCount)
135{
136 while (pageCount--)
137 iovmInsert(addr, offset++, *pageList++);
138}
139
140void IOMapper::iovmInsert(ppnum_t addr, IOItemCount offset,
141 upl_page_info_t *pageList, IOItemCount pageCount)
142{
143 for (IOItemCount i = 0; i < pageCount; i++)
144 iovmInsert(addr, offset + i, pageList[i].phys_addr);
145}
146
5d5c5d0d
A
147OSData * IOMapper::
148NewARTTable(IOByteCount size, void ** virtAddrP, ppnum_t *physAddrP)
8ad349bb 149{
5d5c5d0d
A
150 if (!virtAddrP || !physAddrP)
151 return 0;
152
55e303ae 153 kern_return_t kr;
5d5c5d0d 154 vm_address_t address;
55e303ae 155
55e303ae 156 size = round_page_32(size);
5d5c5d0d
A
157 kr = kmem_alloc_contig(kernel_map, &address, size, PAGE_MASK, 0);
158 if (kr)
55e303ae
A
159 return 0;
160
5d5c5d0d
A
161 ppnum_t pagenum = pmap_find_phys(kernel_pmap, (addr64_t) address);
162 if (pagenum)
163 *physAddrP = pagenum;
164 else {
165 FreeARTTable((OSData *) address, size);
166 address = 0;
167 }
55e303ae 168
5d5c5d0d 169 *virtAddrP = (void *) address;
55e303ae 170
5d5c5d0d 171 return (OSData *) address;
55e303ae
A
172}
173
174void IOMapper::FreeARTTable(OSData *artHandle, IOByteCount size)
175{
5d5c5d0d 176 vm_address_t address = (vm_address_t) artHandle;
55e303ae 177
5d5c5d0d
A
178 size = round_page_32(size);
179 kmem_free(kernel_map, address, size); // Just panic if address is 0
180}
8ad349bb 181
5d5c5d0d
A
182bool IOMapper::getBypassMask(addr64_t *maskP) const
183{
184 return false;
55e303ae
A
185}
186
187__BEGIN_DECLS
188
189// These are C accessors to the system mapper for non-IOKit clients
190ppnum_t IOMapperIOVMAlloc(unsigned pages)
191{
192 IOMapper::checkForSystemMapper();
193
194 if (IOMapper::gSystem)
195 return IOMapper::gSystem->iovmAlloc((IOItemCount) pages);
196 else
197 return 0;
198}
199
200void IOMapperIOVMFree(ppnum_t addr, unsigned pages)
201{
202 if (IOMapper::gSystem)
203 IOMapper::gSystem->iovmFree(addr, (IOItemCount) pages);
204}
205
206ppnum_t IOMapperInsertPage(ppnum_t addr, unsigned offset, ppnum_t page)
207{
208 if (IOMapper::gSystem) {
209 IOMapper::gSystem->iovmInsert(addr, (IOItemCount) offset, page);
210 return addr + offset;
211 }
212 else
213 return page;
214}
215
216void IOMapperInsertPPNPages(ppnum_t addr, unsigned offset,
217 ppnum_t *pageList, unsigned pageCount)
218{
219 if (!IOMapper::gSystem)
220 panic("IOMapperInsertPPNPages no system mapper");
221 else
222 assert(!((vm_address_t) IOMapper::gSystem & 3));
223
224 IOMapper::gSystem->
225 iovmInsert(addr, (IOItemCount) offset, pageList, pageCount);
226}
227
228void IOMapperInsertUPLPages(ppnum_t addr, unsigned offset,
229 upl_page_info_t *pageList, unsigned pageCount)
230{
231 if (!IOMapper::gSystem)
232 panic("IOMapperInsertUPLPages no system mapper");
233 else
234 assert(!((vm_address_t) IOMapper::gSystem & 3));
235
236 IOMapper::gSystem->iovmInsert(addr,
237 (IOItemCount) offset,
238 pageList,
239 (IOItemCount) pageCount);
240}
241
242/////////////////////////////////////////////////////////////////////////////
243//
244//
245// IOLib.h APIs
246//
247//
248/////////////////////////////////////////////////////////////////////////////
249
250#include <machine/machine_routines.h>
251
252UInt8 IOMappedRead8(IOPhysicalAddress address)
253{
254 IOMapper::checkForSystemMapper();
255
256 if (IOMapper::gSystem) {
257 addr64_t addr = IOMapper::gSystem->mapAddr(address);
258 return (UInt8) ml_phys_read_byte_64(addr);
259 }
260 else
261 return (UInt8) ml_phys_read_byte((vm_offset_t) address);
262}
263
264UInt16 IOMappedRead16(IOPhysicalAddress address)
265{
266 IOMapper::checkForSystemMapper();
267
268 if (IOMapper::gSystem) {
269 addr64_t addr = IOMapper::gSystem->mapAddr(address);
270 return (UInt16) ml_phys_read_half_64(addr);
271 }
272 else
273 return (UInt16) ml_phys_read_half((vm_offset_t) address);
274}
275
276UInt32 IOMappedRead32(IOPhysicalAddress address)
277{
278 IOMapper::checkForSystemMapper();
279
280 if (IOMapper::gSystem) {
281 addr64_t addr = IOMapper::gSystem->mapAddr(address);
282 return (UInt32) ml_phys_read_word_64(addr);
283 }
284 else
285 return (UInt32) ml_phys_read_word((vm_offset_t) address);
286}
287
288UInt64 IOMappedRead64(IOPhysicalAddress address)
289{
290 IOMapper::checkForSystemMapper();
291
292 if (IOMapper::gSystem) {
293 addr64_t addr = IOMapper::gSystem->mapAddr(address);
294 return (UInt64) ml_phys_read_double_64(addr);
295 }
296 else
297 return (UInt64) ml_phys_read_double((vm_offset_t) address);
298}
299
300void IOMappedWrite8(IOPhysicalAddress address, UInt8 value)
301{
302 IOMapper::checkForSystemMapper();
303
304 if (IOMapper::gSystem) {
305 addr64_t addr = IOMapper::gSystem->mapAddr(address);
306 ml_phys_write_byte_64(addr, value);
307 }
308 else
309 ml_phys_write_byte((vm_offset_t) address, value);
310}
311
312void IOMappedWrite16(IOPhysicalAddress address, UInt16 value)
313{
314 IOMapper::checkForSystemMapper();
315
316 if (IOMapper::gSystem) {
317 addr64_t addr = IOMapper::gSystem->mapAddr(address);
318 ml_phys_write_half_64(addr, value);
319 }
320 else
321 ml_phys_write_half((vm_offset_t) address, value);
322}
323
324void IOMappedWrite32(IOPhysicalAddress address, UInt32 value)
325{
326 IOMapper::checkForSystemMapper();
327
328 if (IOMapper::gSystem) {
329 addr64_t addr = IOMapper::gSystem->mapAddr(address);
330 ml_phys_write_word_64(addr, value);
331 }
332 else
333 ml_phys_write_word((vm_offset_t) address, value);
334}
335
336void IOMappedWrite64(IOPhysicalAddress address, UInt64 value)
337{
338 IOMapper::checkForSystemMapper();
339
340 if (IOMapper::gSystem) {
341 addr64_t addr = IOMapper::gSystem->mapAddr(address);
342 ml_phys_write_double_64(addr, value);
343 }
344 else
345 ml_phys_write_double((vm_offset_t) address, value);
346}
347
5d5c5d0d
A
348mach_vm_address_t IOMallocPhysical(mach_vm_size_t size, mach_vm_address_t mask)
349{
350 mach_vm_address_t address = 0;
351 if (gIOCopyMapper)
352 {
353 address = ptoa_64(gIOCopyMapper->iovmAlloc(atop_64(round_page(size))));
354 }
355
356 return (address);
357}
358
359void IOFreePhysical(mach_vm_address_t address, mach_vm_size_t size)
360{
361 if (gIOCopyMapper)
362 {
363 gIOCopyMapper->iovmFree(atop_64(address), atop_64(round_page(size)));
364 }
365}
366
367
55e303ae 368__END_DECLS