IOBufferMemoryDescriptor* MemoryDmaAlloc(UInt32 buf_size, dma_addr_t *phys_add, void *virt_add) { IOBufferMemoryDescriptor *memBuffer; void *virt_address; dma_addr_t phys_address; IOMemoryMap *memMap; memBuffer = IOBufferMemoryDescriptor::inTaskWithOptions(kernel_task, kIODirectionOutIn | kIOMemoryPhysicallyContiguous | \ kIOMemoryAutoPrepare | kIOMapInhibitCache, buf_size, \ PAGE_SIZE); if (memBuffer == NULL) { //IOLog("Memory Allocation failed - RLC"); return NULL; } memMap = memBuffer->map(); if (memMap == NULL) { //IOLog("mapping failed\n"); memBuffer->release(); memBuffer = NULL; return NULL; } phys_address = memMap->getPhysicalAddress(); virt_address = (void *)memMap->getVirtualAddress(); if (virt_address == NULL || phys_address == NULL) { memMap->release(); memBuffer->release(); memBuffer = NULL; return NULL; } *phys_add = phys_address; *(IOVirtualAddress*)virt_add = (IOVirtualAddress)virt_address; memMap->release(); return memBuffer; }
bool AppleSamsungSerialDeviceSync::start(IOService *provider) { IOMemoryMap* memoryMap; uint32_t uartBase; if(!provider) { panic("provider should not be null"); } memoryMap = provider->mapDeviceMemoryWithIndex(0); if(!memoryMap) { panic("failed to get physical device memory map"); } uartBase = memoryMap->getPhysicalAddress(); SERIAL_LOG("Detected uart at PA:0x%08x\n", uartBase); memoryMap->release(); registerService(); return true; }
// ---------------------------------------------------------------------------------------------------- IODBDMAChannelRegisters * PlatformInterfaceDBDMA_Mapped::GetOutputChannelRegistersVirtualAddress ( IOService * dbdmaProvider ) { IOMemoryMap * map; IOService * parentOfParent; debugIOLog (3, "+ PlatformInterfaceDBDMA_Mapped::GetOutputChannelRegistersVirtualAddress ( %p )", dbdmaProvider ); FailIf ( NULL == dbdmaProvider, Exit ); debugIOLog (3, " i2s-x name is %s", dbdmaProvider->getName() ); parentOfParent = (IOService*)dbdmaProvider->getParentEntry ( gIODTPlane ); FailIf ( NULL == parentOfParent, Exit ); debugIOLog (3, " parent of %s is %s", dbdmaProvider->getName(), parentOfParent->getName() ); map = parentOfParent->mapDeviceMemoryWithIndex ( AppleDBDMAAudio::kDBDMAOutputIndex ); FailIf ( NULL == map, Exit ); mIOBaseDMAOutput = (IODBDMAChannelRegisters *) map->getVirtualAddress(); debugIOLog (3, " mIOBaseDMAOutput virtual address %p is at physical address %p", mIOBaseDMAOutput, (void*)map->getPhysicalAddress() ); if ( NULL == mIOBaseDMAOutput ) { debugIOLog (1, " PlatformInterfaceDBDMA_Mapped::GetOutputChannelRegistersVirtualAddress IODBDMAChannelRegisters NOT IN VIRTUAL SPACE" ); } Exit: debugIOLog (3, "- PlatformInterfaceDBDMA_Mapped::GetOutputChannelRegistersVirtualAddress ( %p ) returns %p", dbdmaProvider, mIOBaseDMAOutput ); return mIOBaseDMAOutput; }
// ---------------------------------------------------------------------------------------------------- bool PlatformInterfaceDBDMA_Mapped::init ( IOService* device, AppleOnboardAudio* provider, UInt32 inDBDMADeviceIndex ) { bool result = FALSE; IOService* theService; IORegistryEntry *macio; IORegistryEntry *gpio; IORegistryEntry *i2s; IORegistryEntry *i2sParent; IOMemoryMap *map; debugIOLog ( 3, "+ PlatformInterfaceDBDMA_Mapped::init ( %p, %p, %d )", device, provider, inDBDMADeviceIndex ); FailIf ( NULL == provider, Exit ); FailIf ( NULL == device, Exit ); result = super::init ( device, provider, inDBDMADeviceIndex ); if ( result ) { mKeyLargoService = IOService::waitForService ( IOService::serviceMatching ( "KeyLargo" ) ); debugIOLog ( 3, " sound's name is %s", ( (IORegistryEntry*)device)->getName () ); i2s = ( ( IORegistryEntry*)device)->getParentEntry ( gIODTPlane ); FailWithAction ( 0 == i2s, result = false, Exit ); debugIOLog ( 3, " parent name is '%s'", i2s->getName () ); if ( 0 == strcmp ( "i2s-a", i2s->getName () ) ) { mI2SInterfaceNumber = kUseI2SCell0; } else if ( 0 == strcmp ( "i2s-b", i2s->getName () ) ) { mI2SInterfaceNumber = kUseI2SCell1; } else if ( 0 == strcmp ( "i2s-c", i2s->getName () ) ) { mI2SInterfaceNumber = kUseI2SCell2; } else if ( 0 == strcmp ( "i2s-d", i2s->getName () ) ) { mI2SInterfaceNumber = kUseI2SCell3; } else if ( 0 == strcmp ( "i2s-e", i2s->getName () ) ) { mI2SInterfaceNumber = kUseI2SCell4; } else if ( 0 == strcmp ( "i2s-f", i2s->getName () ) ) { mI2SInterfaceNumber = kUseI2SCell5; } else if ( 0 == strcmp ( "i2s-g", i2s->getName () ) ) { mI2SInterfaceNumber = kUseI2SCell6; } else if ( 0 == strcmp ( "i2s-h", i2s->getName () ) ) { mI2SInterfaceNumber = kUseI2SCell7; } debugIOLog ( 5, " mI2SInterfaceNumber = %d", mI2SInterfaceNumber ); i2sParent = i2s->getParentEntry ( gIODTPlane ); FailWithAction ( 0 == i2sParent, result = false, Exit ); debugIOLog ( 3, " parent name of '%s' is %s", i2s->getName (), i2sParent->getName () ); macio = i2sParent->getParentEntry ( gIODTPlane ); FailWithAction ( 0 == macio, result = false, Exit ); debugIOLog ( 3, " macio name is %s", macio->getName () ); gpio = macio->childFromPath ( kGPIODTEntry, gIODTPlane); FailWithAction ( !gpio, result = false, Exit); debugIOLog ( 3, " gpio name is %s", gpio->getName () ); theService = ( OSDynamicCast ( IOService, i2s ) ); FailWithAction ( !theService, result = false, Exit ); map = theService->mapDeviceMemoryWithIndex ( inDBDMADeviceIndex ); FailWithAction ( 0 == map, result = false, Exit ); // cache the config space mSoundConfigSpace = (UInt8 *)map->getPhysicalAddress(); // sets the clock base address figuring out which I2S cell we're on if ((((UInt32)mSoundConfigSpace ^ kI2S0BaseOffset) & 0x0001FFFF) == 0) { // [3060321] ioBaseAddress is required by this object in order to enable the target // I2S I/O Module for which this object is to service. The I2S I/O Module // enable occurs through the configuration registers which reside in the // first block of ioBase. rbm 2 Oct 2002 mIOBaseAddress = (void *)((UInt32)mSoundConfigSpace - kI2S0BaseOffset); mIOBaseAddressMemory = IODeviceMemory::withRange ((IOPhysicalAddress)((UInt8 *)mSoundConfigSpace - kI2S0BaseOffset), 256); mI2SInterfaceNumber = kUseI2SCell0; } else if ((((UInt32)mSoundConfigSpace ^ kI2S1BaseOffset) & 0x0001FFFF) == 0) { // [3060321] ioBaseAddress is required by this object in order to enable the target // I2S I/O Module for which this object is to service. The I2S I/O Module // enable occurs through the configuration registers which reside in the // first block of ioBase. rbm 2 Oct 2002 mIOBaseAddress = (void *)((UInt32)mSoundConfigSpace - kI2S1BaseOffset); mIOBaseAddressMemory = IODeviceMemory::withRange ((IOPhysicalAddress)((UInt8 *)mSoundConfigSpace - kI2S1BaseOffset), 256); mI2SInterfaceNumber = kUseI2SCell1; } else { debugIOLog (3, " AudioI2SControl::init ERROR: unable to setup ioBaseAddress and i2SInterfaceNumber"); } FailIf (NULL == mIOBaseAddressMemory, Exit); // [3060321] ioConfigurationBaseAddress is required by this object in order to enable the target // I2S I/O Module for which this object is to service. The I2S I/O Module // enable occurs through the configuration registers which reside in the // first block of ioBase. rbm 2 Oct 2002 mIOConfigurationBaseAddress = (void *)mIOBaseAddressMemory->map()->getVirtualAddress(); FailIf ( NULL == mIOConfigurationBaseAddress, Exit ); // // There are three sections of memory mapped I/O that are directly accessed by the Apple02Audio. These // include the GPIOs, I2S DMA Channel Registers and I2S control registers. They fall within the memory map // as follows: // ~ ~ // |______________________________| // | | // | I2S Control | // |______________________________| <- soundConfigSpace = ioBase + i2s0BaseOffset ...OR... ioBase + i2s1BaseOffset // | | // ~ ~ // ~ ~ // |______________________________| // | | // | I2S DMA Channel | // |______________________________| <- i2sDMA = ioBase + i2s0_DMA ...OR... ioBase + i2s1_DMA // | | // ~ ~ // ~ ~ // |______________________________| // | FCRs | // | GPIO | <- gpio = ioBase + gpioOffsetAddress // | ExtIntGPIO | <- fcr = ioBase + fcrOffsetAddress // |______________________________| <- ioConfigurationBaseAddress // | | // ~ ~ // // The I2S DMA Channel is mapped in by the Apple02DBDMAAudioDMAEngine. Only the I2S control registers are // mapped in by the AudioI2SControl. The Apple I/O Configuration Space (i.e. FCRs, GPIOs and ExtIntGPIOs) // are mapped in by the subclass of Apple02Audio. The FCRs must also be mapped in by the AudioI2SControl // object as the init method must enable the I2S I/O Module for which the AudioI2SControl object is // being instantiated for. // // The physical addresses for memory mapped I/O within the KeyLargo system I/O controller are as follows: // // // // ______________________________ // /| | // / | | // / |______________________________| // ______________________________ / | | // | | | I2S 1 ('i2s-b') | // | | |______________________________|....0xnnn11000 [0x80011000] // | | | | // | | | I2S 0 ('i2s-a') | // | | |______________________________|....0xnnn10000 [0x80001000] // | Device Registers | / // | | / // | | / ______________________________ // | |/ /| | // |______________________________|__/ | | // | | |______________________________| // | | | | // | | | I2S 1 Rx DMA ('i2s-b') | // | | |______________________________|....0xnnn08300 [0x80008300] // | DMA Channel Registers | | | // | | | I2S 1 Tx DMA ('i2s-b') | // | | |______________________________|....0xnnn08200 [0x80008200] // | | | | // |______________________________| | I2S 0 Rx DMA ('i2s-a') | // | |\ |______________________________|....0xnnn08100 [0x80008100] // | | \ | | // | Reserved: read "0" | \ | I2S 0 Tx DMA ('i2s-a') | // | | \|______________________________|....0xnnn08000 [0x80008000] // |______________________________| // | | // | | // | Apple I/O Configuration | // | | // |______________________________|....0xnnn00000 [0x80011000] // // Map the I2S configuration registers mIOI2SBaseAddressMemory = IODeviceMemory::withRange ((IOPhysicalAddress)((UInt8 *)mSoundConfigSpace), kI2S_IO_CONFIGURATION_SIZE); FailIf ( NULL == mIOI2SBaseAddressMemory, Exit ); mI2SBaseAddress = (void *)mIOI2SBaseAddressMemory->map()->getVirtualAddress(); FailIf (NULL == mI2SBaseAddress, Exit); debugIOLog (3, " mI2SInterfaceNumber = %d", mI2SInterfaceNumber); debugIOLog (3, " mIOI2SBaseAddressMemory = %p", mIOI2SBaseAddressMemory); debugIOLog (3, " mI2SBaseAddress = %p", mI2SBaseAddress); debugIOLog (3, " mIOBaseAddressMemory = %p", mIOBaseAddressMemory); debugIOLog (3, " mIOConfigurationBaseAddress = %p", mIOConfigurationBaseAddress); } Exit: debugIOLog ( 3, "- PlatformInterfaceDBDMA_Mapped::init ( %p, %p, %d ) returns %lX", device, provider, inDBDMADeviceIndex, result ); return result; }
// -------------------------------------------------------------------------- bool AudioI2SControl::init(AudioI2SInfo *theInfo) { UInt32 tempFcr1; debugIOLog (3, "+ AudioI2SControl::init"); if(!super::init()) return(false); if ( NULL == theInfo ) { return ( false ); } // [3060321] rbm 1 Oct 2002 IOMemoryMap *map = theInfo->map ; switch ( theInfo->i2sSerialFormat ) { // [3060321] rbm 2 Oct 2002 begin { case kSerialFormatSony: // fall through to kSerialFormatSiliLabs case kSerialFormat64x: // fall through to kSerialFormatSiliLabs case kSerialFormat32x: // fall through to kSerialFormatSiliLabs case kSerialFormatDAV: // fall through to kSerialFormatSiliLabs case kSerialFormatSiliLabs: serialFormat = theInfo->i2sSerialFormat; // set the format as requested break; default: debugIOLog (3, "### WRONG I2S Serial Format" ); serialFormat = kSerialFormatSony; // force a legal value here... break; } // [3060321] rbm 1 Oct 2002 } end // cache the config space soundConfigSpace = (UInt8 *)map->getPhysicalAddress(); // sets the clock base address figuring out which I2S cell we're on if ((((UInt32)soundConfigSpace ^ kI2S0BaseOffset) & 0x0001FFFF) == 0) { // [3060321] ioBaseAddress is required by this object in order to enable the target // I2S I/O Module for which this object is to service. The I2S I/O Module // enable occurs through the configuration registers which reside in the // first block of ioBase. rbm 2 Oct 2002 ioBaseAddress = (void *)((UInt32)soundConfigSpace - kI2S0BaseOffset); ioBaseAddressMemory = IODeviceMemory::withRange ((IOPhysicalAddress)((UInt8 *)soundConfigSpace - kI2S0BaseOffset), 256); i2SInterfaceNumber = kUseI2SCell0; } else if ((((UInt32)soundConfigSpace ^ kI2S1BaseOffset) & 0x0001FFFF) == 0) { // [3060321] ioBaseAddress is required by this object in order to enable the target // I2S I/O Module for which this object is to service. The I2S I/O Module // enable occurs through the configuration registers which reside in the // first block of ioBase. rbm 2 Oct 2002 ioBaseAddress = (void *)((UInt32)soundConfigSpace - kI2S1BaseOffset); ioBaseAddressMemory = IODeviceMemory::withRange ((IOPhysicalAddress)((UInt8 *)soundConfigSpace - kI2S1BaseOffset), 256); i2SInterfaceNumber = kUseI2SCell1; } else { debugIOLog (3, "AudioI2SControl::init ERROR: unable to setup ioBaseAddress and i2SInterfaceNumber"); } // // There are three sections of memory mapped I/O that are directly accessed by the Apple02Audio. These // include the GPIOs, I2S DMA Channel Registers and I2S control registers. They fall within the memory map // as follows: // ~ ~ // |______________________________| // | | // | I2S Control | // |______________________________| <- soundConfigSpace = ioBase + i2s0BaseOffset ...OR... ioBase + i2s1BaseOffset // | | // ~ ~ // ~ ~ // |______________________________| // | | // | I2S DMA Channel | // |______________________________| <- i2sDMA = ioBase + i2s0_DMA ...OR... ioBase + i2s1_DMA // | | // ~ ~ // ~ ~ // |______________________________| // | FCRs | // | GPIO | <- gpio = ioBase + gpioOffsetAddress // | ExtIntGPIO | <- fcr = ioBase + fcrOffsetAddress // |______________________________| <- ioConfigurationBaseAddress // | | // ~ ~ // // The I2S DMA Channel is mapped in by the Apple02DBDMAAudioDMAEngine. Only the I2S control registers are // mapped in by the AudioI2SControl. The Apple I/O Configuration Space (i.e. FCRs, GPIOs and ExtIntGPIOs) // are mapped in by the subclass of Apple02Audio. The FCRs must also be mapped in by the AudioI2SControl // object as the init method must enable the I2S I/O Module for which the AudioI2SControl object is // being instantiated for. // // Map the I2S configuration registers if (kUseI2SCell0 == i2SInterfaceNumber) { ioI2SBaseAddressMemory = IODeviceMemory::withRange ((IOPhysicalAddress)((UInt8 *)soundConfigSpace), kI2S_IO_CONFIGURATION_SIZE); } else { ioI2SBaseAddressMemory = IODeviceMemory::withRange ((IOPhysicalAddress)((UInt8 *)soundConfigSpace), kI2S_IO_CONFIGURATION_SIZE); } if (NULL != ioI2SBaseAddressMemory) { i2sBaseAddress = (void *)ioI2SBaseAddressMemory->map()->getVirtualAddress(); } else { return false; } // Enable the I2S interface by setting the enable bit in the feature // control register. This one action requires knowledge of the address // of I/O configuration address space. [3060321] rbm 2 Oct 2002 tempFcr1 = KLGetRegister ( kFCR1Offset ); if ( kUseI2SCell0 == i2SInterfaceNumber ) { tempFcr1 &= ~( 1 << kI2S0SwReset ); KLSetRegister ( kFCR1Offset, tempFcr1 ); KLSetRegister ( kFCR1Offset, tempFcr1 | kI2S0InterfaceEnable ); } else { tempFcr1 &= ~( 1 << kI2S1SwReset ); KLSetRegister ( kFCR1Offset, tempFcr1 ); KLSetRegister ( kFCR1Offset, tempFcr1 | kI2S1InterfaceEnable ); } debugIOLog (3, "- AudioI2SControl::init"); return(true); }
bool AppleSamplePCI::start( IOService * provider ) { IOMemoryDescriptor * mem; IOMemoryMap * map; IOLog("AppleSamplePCI::start\n"); if( !super::start( provider )) return( false ); /* * Our provider class is specified in the driver property table * as IOPCIDevice, so the provider must be of that class. * The assert is just to make absolutely sure for debugging. */ assert( OSDynamicCast( IOPCIDevice, provider )); fPCIDevice = (IOPCIDevice *) provider; /* * Enable memory response from the card */ fPCIDevice->setMemoryEnable( true ); /* * Log some info about the device */ /* print all the device's memory ranges */ for( UInt32 index = 0; index < fPCIDevice->getDeviceMemoryCount(); index++ ) { mem = fPCIDevice->getDeviceMemoryWithIndex( index ); assert( mem ); IOLog("Range[%ld] %08lx:%08lx\n", index, mem->getPhysicalAddress(), mem->getLength()); } /* look up a range based on its config space base address register */ mem = fPCIDevice->getDeviceMemoryWithRegister( kIOPCIConfigBaseAddress0 ); if( mem ) IOLog("Range@0x%x %08lx:%08lx\n", kIOPCIConfigBaseAddress0, mem->getPhysicalAddress(), mem->getLength()); /* map a range based on its config space base address register, * this is how the driver gets access to its memory mapped registers * the getVirtualAddress() method returns a kernel virtual address * for the register mapping */ map = fPCIDevice->mapDeviceMemoryWithRegister( kIOPCIConfigBaseAddress0 ); if( map ) { IOLog("Range@0x%x (%08lx) mapped to kernel virtual address %08x\n", kIOPCIConfigBaseAddress0, map->getPhysicalAddress(), map->getVirtualAddress()); /* release the map object, and the mapping itself */ map->release(); } /* read a config space register */ IOLog("Config register@0x%x = %08lx\n", kIOPCIConfigCommand, fPCIDevice->configRead32(kIOPCIConfigCommand) ); // construct a memory descriptor for a buffer below the 4Gb line & // so addressable by 32 bit DMA. This could be used for a // DMA program buffer for example IOBufferMemoryDescriptor * bmd = IOBufferMemoryDescriptor::inTaskWithPhysicalMask( // task to hold the memory kernel_task, // options kIOMemoryPhysicallyContiguous, // size 64*1024, // physicalMask - 32 bit addressable and page aligned 0x00000000FFFFF000ULL); if (bmd) { generateDMAAddresses(bmd); } else { IOLog("IOBufferMemoryDescriptor::inTaskWithPhysicalMask failed\n"); } fLowMemory = bmd; /* publish ourselves so clients can find us */ registerService(); return( true ); }