void *pci_alloc_consistent(void *pdev, size_t size, dma_addr_t *dma_handle) { IOBufferMemoryDescriptor *memDesc; IOVirtualAddress virt_address; IOPhysicalAddress phys_address; // construct a memory descriptor for a buffer below the 4Gb line, // addressable by 32 bit DMA and page aligned. memDesc = IOBufferMemoryDescriptor::inTaskWithOptions(kernel_task, kIOMemoryPhysicallyContiguous, size, PAGE_SIZE); if (memDesc) { IOByteCount offset = 0; IOByteCount length; memDesc->prepare(); virt_address = (IOVirtualAddress)memDesc->getBytesNoCopy(); phys_address = memDesc->getPhysicalSegment(offset, &length); g_bcm_dma_info->setObject(memDesc); } else { virt_address = NULL; phys_address = NULL; IOLog("pci_alloc_consistent:IOBufferMemoryDescriptor::inTaskWithOptions failed\n"); } //IOLog("pci_alloc_consistent paddr(0x%X), size(0x%X)\n", (unsigned int)phys_address, size); *dma_handle = phys_address; return (void*)virt_address; }
IOBufferMemoryDescriptor *kXAudioEngine::my_alloc_contiguous(mach_vm_size_t size, void **addr, dword *phys) { if(size<PAGE_SIZE) size=PAGE_SIZE; #ifdef DEBUGGING size += 2 * PAGE_SIZE; #endif //void *addr=IOMallocContiguous(size+PAGE_SIZE+PAGE_SIZE,alignment,phys); mach_vm_address_t mask = 0x000000007FFFFFFFULL & ~(PAGE_SIZE - 1); IOBufferMemoryDescriptor *desc = IOBufferMemoryDescriptor::inTaskWithPhysicalMask( kernel_task, kIODirectionInOut | kIOMemoryPhysicallyContiguous, size, mask); if(desc) { desc->prepare(); IOPhysicalAddress pa = desc->getPhysicalAddress(); if (pa & ~mask) debug("kXAudioEngine[%p]::my_alloc_contiguous() - memory misaligned or beyond 2GB limit (%p)\n", this, (void *)pa); *phys = (dword)pa; *addr = desc->getBytesNoCopy(); #ifdef DEBUGGING memset(addr,0x11,PAGE_SIZE); memset((UInt8 *)addr+PAGE_SIZE+size,0x22,PAGE_SIZE); *((UInt8 *)addr) += PAGE_SIZE; *phys += PAGE_SIZE; #endif } else debug("kXAudioEngine[%p]::my_alloc_contiguous() - allocation failed\n",this); return desc; }
IOReturn IOUSBController::CheckForDisjointDescriptor(IOUSBCommand *command, UInt16 maxPacketSize) { IOMemoryDescriptor *buf = command->GetBuffer(); IOBufferMemoryDescriptor *newBuf = NULL; IOByteCount length = command->GetReqCount(); IODMACommand *dmaCommand = command->GetDMACommand(); IOByteCount segLength = 0; IOByteCount offset = 0; IOReturn err; UInt64 offset64; IODMACommand::Segment64 segment64; UInt32 numSegments; // USBTrace_Start( kUSBTController, kTPControllerCheckForDisjointDescriptor, (uintptr_t)this ); // Zero length buffers are valid, but they are surely not disjoint, so just return success. // if ( length == 0 ) return kIOReturnSuccess; if (!dmaCommand) { USBLog(1, "%s[%p]::CheckForDisjointDescriptor - no dmaCommand", getName(), this); USBTrace( kUSBTController, kTPControllerCheckForDisjointDescriptor, (uintptr_t)this, kIOReturnBadArgument, 0, 1 ); return kIOReturnBadArgument; } if (dmaCommand->getMemoryDescriptor() != buf) { USBLog(1, "%s[%p]::CheckForDisjointDescriptor - mismatched memory descriptor (%p) and dmaCommand memory descriptor (%p)", getName(), this, buf, dmaCommand->getMemoryDescriptor()); USBTrace( kUSBTController, kTPControllerCheckForDisjointDescriptor, kIOReturnBadArgument, (uintptr_t)buf, (uintptr_t)dmaCommand->getMemoryDescriptor(), 2 ); return kIOReturnBadArgument; } while (length) { offset64 = offset; numSegments = 1; err = dmaCommand->gen64IOVMSegments(&offset64, &segment64, &numSegments); if (err || (numSegments != 1)) { USBLog(1, "%s[%p]::CheckForDisjointDescriptor - err (%p) trying to generate segments at offset (%qd), length (%d), segLength (%d), total length (%d), buf (%p), numSegments (%d)", getName(), this, (void*)err, offset64, (int)length, (int)segLength, (int)command->GetReqCount(), buf, (int)numSegments); USBTrace( kUSBTController, kTPControllerCheckForDisjointDescriptor, offset64, length, segLength, 3 ); USBTrace( kUSBTController, kTPControllerCheckForDisjointDescriptor, segLength, command->GetReqCount(), numSegments, 4 ); return kIOReturnBadArgument; } // 3036056 since length might be less than the length of the descriptor, we are OK if the physical // segment is longer than we need if (segment64.fLength >= length) return kIOReturnSuccess; // this is the last segment, so we are OK // since length is a 32 bit quantity, then we know from the above statement that if we are here we are 32 bit only segLength = (IOByteCount)segment64.fLength; // so the segment is less than the rest of the length - we need to check against maxPacketSize if (segLength % maxPacketSize) { // this is the error case. I need to copy the descriptor to a new descriptor and remember that I did it USBLog(6, "%s[%p]::CheckForDisjointDescriptor - found a disjoint segment of length (%d) MPS (%d)", getName(), this, (int)segLength, maxPacketSize); length = command->GetReqCount(); // we will not return to the while loop, so don't worry about changing the value of length // allocate a new descriptor which is the same total length as the old one newBuf = IOBufferMemoryDescriptor::withOptions((command->GetDirection() == kUSBIn) ? kIODirectionIn : kIODirectionOut, length); if (!newBuf) { USBLog(1, "%s[%p]::CheckForDisjointDescriptor - could not allocate new buffer", getName(), this); USBTrace( kUSBTController, kTPControllerCheckForDisjointDescriptor, (uintptr_t)this, kIOReturnNoMemory, 0, 5 ); return kIOReturnNoMemory; } USBLog(7, "%s[%p]::CheckForDisjointDescriptor, obtained buffer %p of length %d", getName(), this, newBuf, (int)length); // first close out (and complete) the original dma command descriptor USBLog(7, "%s[%p]::CheckForDisjointDescriptor, clearing memDec (%p) from dmaCommand (%p)", getName(), this, dmaCommand->getMemoryDescriptor(), dmaCommand); dmaCommand->clearMemoryDescriptor(); // copy the bytes to the buffer if necessary if (command->GetDirection() == kUSBOut) { USBLog(7, "%s[%p]::CheckForDisjointDescriptor, copying %d bytes from desc %p to buffer %p", getName(), this, (int)length, buf, newBuf->getBytesNoCopy()); if (buf->readBytes(0, newBuf->getBytesNoCopy(), length) != length) { USBLog(1, "%s[%p]::CheckForDisjointDescriptor - bad copy on a write", getName(), this); USBTrace( kUSBTController, kTPControllerCheckForDisjointDescriptor, (uintptr_t)this, 0, 0, 6 ); newBuf->release(); return kIOReturnNoMemory; } } err = newBuf->prepare(); if (err) { USBLog(1, "%s[%p]::CheckForDisjointDescriptor - err 0x%x in prepare", getName(), this, err); USBTrace( kUSBTController, kTPControllerCheckForDisjointDescriptor, (uintptr_t)this, err, 0, 7 ); newBuf->release(); return err; } err = dmaCommand->setMemoryDescriptor(newBuf); if (err) { USBLog(1, "%s[%p]::CheckForDisjointDescriptor - err 0x%x in setMemoryDescriptor", getName(), this, err); USBTrace( kUSBTController, kTPControllerCheckForDisjointDescriptor, (uintptr_t)this, err, 0, 8 ); newBuf->complete(); newBuf->release(); return err; } command->SetOrigBuffer(command->GetBuffer()); command->SetDisjointCompletion(command->GetClientCompletion()); USBLog(7, "%s[%p]::CheckForDisjointDescriptor - changing buffer from (%p) to (%p) and putting new buffer in dmaCommand (%p)", getName(), this, command->GetBuffer(), newBuf, dmaCommand); command->SetBuffer(newBuf); IOUSBCompletion completion; completion.target = this; completion.action = (IOUSBCompletionAction)DisjointCompletion; completion.parameter = command; command->SetClientCompletion(completion); command->SetDblBufLength(length); // for the IOFree - the other buffer may change size return kIOReturnSuccess; } length -= segLength; // adjust our master length pointer offset += segLength; } USBLog(5, "%s[%p]::CheckForDisjointDescriptor - returning kIOReturnBadArgument(0x%x)", getName(), this, kIOReturnBadArgument); // USBTrace_End( kUSBTController, kTPControllerCheckForDisjointDescriptor, (uintptr_t)this, kIOReturnBadArgument); return kIOReturnBadArgument; }