/* * Copyright (c) 2003 Apple Computer, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * * Copyright (c) 1998-2003 Apple Computer, Inc. All Rights Reserved. * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. * * @APPLE_LICENSE_HEADER_END@ */ #include #include "AppleUSBOHCIMemoryBlocks.h" #define super OSObject OSDefineMetaClassAndStructors(AppleUSBOHCIedMemoryBlock, OSObject); AppleUSBOHCIedMemoryBlock* AppleUSBOHCIedMemoryBlock::NewMemoryBlock(void) { AppleUSBOHCIedMemoryBlock *me = new AppleUSBOHCIedMemoryBlock; IOByteCount len; IODMACommand *dmaCommand = NULL; UInt64 offset = 0; IODMACommand::Segment32 segments; UInt32 numSegments = 1; IOReturn status = kIOReturnSuccess; if (me) { // Use IODMACommand to get the physical address dmaCommand = IODMACommand::withSpecification(kIODMACommandOutputHost32, 32, PAGE_SIZE, (IODMACommand::MappingOptions)(IODMACommand::kMapped | IODMACommand::kIterateOnly)); if (!dmaCommand) { USBError(1, "AppleUSBOHCIedMemoryBlock::NewMemoryBlock - could not create IODMACommand"); return NULL; } USBLog(6, "AppleUSBOHCIedMemoryBlock::NewMemoryBlock - got IODMACommand %p", dmaCommand); // allocate one page on a page boundary below the 4GB line me->_buffer = IOBufferMemoryDescriptor::inTaskWithPhysicalMask(kernel_task, kIOMemoryUnshared | kIODirectionInOut, kOHCIPageSize, kOHCIStructureAllocationPhysicalMask); // allocate exactly one physical page if (me->_buffer) { status = me->_buffer->prepare(); if (status) { USBError(1, "AppleUSBOHCIedMemoryBlock::NewMemoryBlock - could not prepare buffer"); me->_buffer->release(); me->release(); dmaCommand->release(); return NULL; } me->_sharedLogical = (OHCIEndpointDescriptorSharedPtr)me->_buffer->getBytesNoCopy(); bzero(me->_sharedLogical, kOHCIPageSize); status = dmaCommand->setMemoryDescriptor(me->_buffer); if (status) { USBError(1, "AppleUSBOHCIedMemoryBlock::NewMemoryBlock - could not set memory descriptor"); me->_buffer->complete(); me->_buffer->release(); me->release(); dmaCommand->release(); return NULL; } status = dmaCommand->gen32IOVMSegments(&offset, &segments, &numSegments); dmaCommand->clearMemoryDescriptor(); dmaCommand->release(); if (status || (numSegments != 1) || (segments.fLength != kOHCIPageSize)) { USBError(1, "AppleUSBOHCIedMemoryBlock::NewMemoryBlock - could not get physical segment"); me->_buffer->complete(); me->_buffer->release(); me->release(); return NULL; } me->_sharedPhysical = segments.fIOVMAddr; } else { USBError(1, "AppleUSBOHCIedMemoryBlock::NewMemoryBlock, could not allocate buffer!"); me->release(); me = NULL; } } else { USBError(1, "AppleUSBOHCIedMemoryBlock::NewMemoryBlock, constructor failed!"); } return me; } UInt32 AppleUSBOHCIedMemoryBlock::NumEDs(void) { return EDsPerBlock; } IOPhysicalAddress AppleUSBOHCIedMemoryBlock::GetSharedPhysicalPtr(UInt32 index) { IOPhysicalAddress ret = NULL; if (index < EDsPerBlock) ret = _sharedPhysical + (index * sizeof(OHCIEndpointDescriptorShared)); return ret; } OHCIEndpointDescriptorSharedPtr AppleUSBOHCIedMemoryBlock::GetSharedLogicalPtr(UInt32 index) { OHCIEndpointDescriptorSharedPtr ret = NULL; if (index < EDsPerBlock) ret = &_sharedLogical[index]; return ret; } AppleOHCIEndpointDescriptorPtr AppleUSBOHCIedMemoryBlock::GetED(UInt32 index) { AppleOHCIEndpointDescriptorPtr ret = NULL; if (index < EDsPerBlock) ret = &_eds[index]; return ret; } AppleUSBOHCIedMemoryBlock* AppleUSBOHCIedMemoryBlock::GetNextBlock(void) { return _nextBlock; } void AppleUSBOHCIedMemoryBlock::SetNextBlock(AppleUSBOHCIedMemoryBlock* next) { _nextBlock = next; } void AppleUSBOHCIedMemoryBlock::free() { // IOKit calls this when we are going away if (_buffer) _buffer->complete(); // we need to unmap our buffer super::free(); } OSDefineMetaClassAndStructors(AppleUSBOHCIgtdMemoryBlock, OSObject); AppleUSBOHCIgtdMemoryBlock* AppleUSBOHCIgtdMemoryBlock::NewMemoryBlock(void) { AppleUSBOHCIgtdMemoryBlock *me = new AppleUSBOHCIgtdMemoryBlock; IOByteCount len; IODMACommand *dmaCommand = NULL; UInt64 offset = 0; IODMACommand::Segment32 segments; UInt32 numSegments = 1; IOReturn status = kIOReturnSuccess; UInt32 *block0; if (me) { // Use IODMACommand to get the physical address dmaCommand = IODMACommand::withSpecification(kIODMACommandOutputHost32, 32, PAGE_SIZE, (IODMACommand::MappingOptions)(IODMACommand::kMapped | IODMACommand::kIterateOnly)); if (!dmaCommand) { USBError(1, "AppleUSBOHCIedMemoryBlock::NewMemoryBlock - could not create IODMACommand"); return NULL; } USBLog(6, "AppleUSBOHCIedMemoryBlock::NewMemoryBlock - got IODMACommand %p", dmaCommand); // allocate one page on a page boundary below the 4GB line me->_buffer = IOBufferMemoryDescriptor::inTaskWithPhysicalMask(kernel_task, kIOMemoryUnshared | kIODirectionInOut, kOHCIPageSize, kOHCIStructureAllocationPhysicalMask); // allocate exactly one physical page if (me->_buffer) { status = me->_buffer->prepare(); if (status) { USBError(1, "AppleUSBOHCIedMemoryBlock::NewMemoryBlock - could not prepare buffer"); me->_buffer->release(); me->release(); dmaCommand->release(); return NULL; } me->_sharedLogical = (OHCIGeneralTransferDescriptorSharedPtr)me->_buffer->getBytesNoCopy(); bzero(me->_sharedLogical, kOHCIPageSize); status = dmaCommand->setMemoryDescriptor(me->_buffer); if (status) { USBError(1, "AppleUSBOHCIedMemoryBlock::NewMemoryBlock - could not set memory descriptor"); me->_buffer->complete(); me->_buffer->release(); me->release(); dmaCommand->release(); return NULL; } status = dmaCommand->gen32IOVMSegments(&offset, &segments, &numSegments); dmaCommand->clearMemoryDescriptor(); dmaCommand->release(); if (status || (numSegments != 1) || (segments.fLength != kOHCIPageSize)) { USBError(1, "AppleUSBOHCIedMemoryBlock::NewMemoryBlock - could not get physical segment"); me->_buffer->complete(); me->_buffer->release(); me->release(); return NULL; } me->_sharedPhysical = segments.fIOVMAddr; block0 = (UInt32*) me->_sharedLogical; *block0++ = (UInt32)me; *block0 = kAppleUSBOHCIMemBlockGTD; } else { USBError(1, "AppleUSBOHCIedMemoryBlock::NewMemoryBlock, could not allocate buffer!"); me->release(); me = NULL; } } else { USBError(1, "AppleUSBOHCIedMemoryBlock::NewMemoryBlock, constructor failed!"); } return me; } UInt32 AppleUSBOHCIgtdMemoryBlock::NumGTDs(void) { return GTDsPerBlock; } IOPhysicalAddress AppleUSBOHCIgtdMemoryBlock::GetSharedPhysicalPtr(UInt32 index) { IOPhysicalAddress ret = NULL; if (index < GTDsPerBlock) ret = _sharedPhysical + ((index+1) * sizeof(OHCIGeneralTransferDescriptorShared)); return ret; } OHCIGeneralTransferDescriptorSharedPtr AppleUSBOHCIgtdMemoryBlock::GetSharedLogicalPtr(UInt32 index) { OHCIGeneralTransferDescriptorSharedPtr ret = NULL; if (index < GTDsPerBlock) ret = &_sharedLogical[index+1]; return ret; } AppleOHCIGeneralTransferDescriptorPtr AppleUSBOHCIgtdMemoryBlock::GetGTD(UInt32 index) { AppleOHCIGeneralTransferDescriptorPtr ret = NULL; if (index < GTDsPerBlock) ret = &_gtds[index]; return ret; } AppleOHCIGeneralTransferDescriptorPtr AppleUSBOHCIgtdMemoryBlock::GetGTDFromPhysical(IOPhysicalAddress addr, UInt32 blockType) { // NOTE: Don't use any USBLogs here, as this is called at primary interrupt time // IOPhysicalAddress blockStart; AppleUSBOHCIgtdMemoryBlock *me; UInt32 index; if (!addr) return NULL; blockStart = addr & ~(kOHCIPageSize-1); if (!blockType) blockType = IOMappedRead32(blockStart + 4); if (blockType == kAppleUSBOHCIMemBlockGTD) { me = (AppleUSBOHCIgtdMemoryBlock*)IOMappedRead32(blockStart); index = ((addr & (kOHCIPageSize-1)) / sizeof(OHCIGeneralTransferDescriptorShared))-1; return &me->_gtds[index]; } else if (blockType == kAppleUSBOHCIMemBlockITD) { return (AppleOHCIGeneralTransferDescriptorPtr)AppleUSBOHCIitdMemoryBlock::GetITDFromPhysical(addr, blockType); } else { return NULL; } } AppleUSBOHCIgtdMemoryBlock* AppleUSBOHCIgtdMemoryBlock::GetNextBlock(void) { return _nextBlock; } void AppleUSBOHCIgtdMemoryBlock::SetNextBlock(AppleUSBOHCIgtdMemoryBlock* next) { _nextBlock = next; } void AppleUSBOHCIgtdMemoryBlock::free() { // IOKit calls this when we are going away if (_buffer) _buffer->complete(); // we need to unmap our buffer super::free(); } OSDefineMetaClassAndStructors(AppleUSBOHCIitdMemoryBlock, OSObject); AppleUSBOHCIitdMemoryBlock* AppleUSBOHCIitdMemoryBlock::NewMemoryBlock(void) { AppleUSBOHCIitdMemoryBlock *me = new AppleUSBOHCIitdMemoryBlock; IOByteCount len; IODMACommand *dmaCommand = NULL; UInt64 offset = 0; IODMACommand::Segment32 segments; UInt32 numSegments = 1; IOReturn status = kIOReturnSuccess; UInt32 *block0; if (me) { // Use IODMACommand to get the physical address dmaCommand = IODMACommand::withSpecification(kIODMACommandOutputHost32, 32, PAGE_SIZE, (IODMACommand::MappingOptions)(IODMACommand::kMapped | IODMACommand::kIterateOnly)); if (!dmaCommand) { USBError(1, "AppleUSBOHCIitdMemoryBlock::NewMemoryBlock - could not create IODMACommand"); return NULL; } USBLog(6, "AppleUSBOHCIitdMemoryBlock::NewMemoryBlock - got IODMACommand %p", dmaCommand); // allocate one page on a page boundary below the 4GB line me->_buffer = IOBufferMemoryDescriptor::inTaskWithPhysicalMask(kernel_task, kIOMemoryUnshared | kIODirectionInOut, kOHCIPageSize, kOHCIStructureAllocationPhysicalMask); // allocate exactly one physical page if (me->_buffer) { status = me->_buffer->prepare(); if (status) { USBError(1, "AppleUSBOHCIitdMemoryBlock::NewMemoryBlock - could not prepare buffer"); me->_buffer->release(); me->release(); dmaCommand->release(); return NULL; } me->_sharedLogical = (OHCIIsochTransferDescriptorSharedPtr)me->_buffer->getBytesNoCopy(); bzero(me->_sharedLogical, kOHCIPageSize); status = dmaCommand->setMemoryDescriptor(me->_buffer); if (status) { USBError(1, "AppleUSBOHCIitdMemoryBlock::NewMemoryBlock - could not set memory descriptor"); me->_buffer->complete(); me->_buffer->release(); me->release(); dmaCommand->release(); return NULL; } status = dmaCommand->gen32IOVMSegments(&offset, &segments, &numSegments); dmaCommand->clearMemoryDescriptor(); dmaCommand->release(); if (status || (numSegments != 1) || (segments.fLength != kOHCIPageSize)) { USBError(1, "AppleUSBOHCIitdMemoryBlock::NewMemoryBlock - could not get physical segment"); me->_buffer->complete(); me->_buffer->release(); me->release(); return NULL; } me->_sharedPhysical = segments.fIOVMAddr; block0 = (UInt32*) me->_sharedLogical; *block0++ = (UInt32)me; *block0 = kAppleUSBOHCIMemBlockITD; } else { USBError(1, "AppleUSBOHCIitdMemoryBlock::NewMemoryBlock, could not allocate buffer!"); me->release(); me = NULL; } } else { USBError(1, "AppleUSBOHCIitdMemoryBlock::NewMemoryBlock, constructor failed!"); } return me; } UInt32 AppleUSBOHCIitdMemoryBlock::NumITDs(void) { return ITDsPerBlock; } IOPhysicalAddress AppleUSBOHCIitdMemoryBlock::GetSharedPhysicalPtr(UInt32 index) { IOPhysicalAddress ret = NULL; if (index < ITDsPerBlock) ret = _sharedPhysical + ((index+1) * sizeof(OHCIIsochTransferDescriptorShared)); return ret; } OHCIIsochTransferDescriptorSharedPtr AppleUSBOHCIitdMemoryBlock::GetSharedLogicalPtr(UInt32 index) { OHCIIsochTransferDescriptorSharedPtr ret = NULL; if (index < ITDsPerBlock) ret = &_sharedLogical[index+1]; return ret; } AppleOHCIIsochTransferDescriptorPtr AppleUSBOHCIitdMemoryBlock::GetITD(UInt32 index) { AppleOHCIIsochTransferDescriptorPtr ret = NULL; if (index < ITDsPerBlock) ret = &_itds[index]; return ret; } AppleOHCIIsochTransferDescriptorPtr AppleUSBOHCIitdMemoryBlock::GetITDFromPhysical(IOPhysicalAddress addr, UInt32 blockType) { IOPhysicalAddress blockStart; AppleUSBOHCIitdMemoryBlock *me; UInt32 index; if (!addr) return NULL; blockStart = addr & ~(kOHCIPageSize-1); if (!blockType) blockType = IOMappedRead32(blockStart + 4); if (blockType == kAppleUSBOHCIMemBlockITD) { me = (AppleUSBOHCIitdMemoryBlock*)IOMappedRead32(blockStart); index = ((addr & (kOHCIPageSize-1)) / sizeof(OHCIIsochTransferDescriptorShared))-1; return &me->_itds[index]; } else if (blockType == kAppleUSBOHCIMemBlockGTD) { return (AppleOHCIIsochTransferDescriptorPtr)AppleUSBOHCIgtdMemoryBlock::GetGTDFromPhysical(addr, blockType); } else { return NULL; } } AppleUSBOHCIitdMemoryBlock* AppleUSBOHCIitdMemoryBlock::GetNextBlock(void) { return _nextBlock; } void AppleUSBOHCIitdMemoryBlock::SetNextBlock(AppleUSBOHCIitdMemoryBlock* next) { _nextBlock = next; } void AppleUSBOHCIitdMemoryBlock::free() { // IOKit calls this when we are going away if (_buffer) _buffer->complete(); // we need to unmap our buffer super::free(); }