The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/iokit/Kernel/IOMapper.cpp

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

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

Cache object: aa903e28d1c618d76dc7c9db4802807c


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.