/** Allocate a block of memory to be used by the buffer pool. @param Pool The buffer pool to allocate memory for. @param Pages How many pages to allocate. @return The allocated memory block or NULL if failed. **/ USBHC_MEM_BLOCK * UsbHcAllocMemBlock ( IN USBHC_MEM_POOL *Pool, IN UINTN Pages ) { USBHC_MEM_BLOCK *Block; EFI_PCI_IO_PROTOCOL *PciIo; VOID *BufHost; VOID *Mapping; EFI_PHYSICAL_ADDRESS MappedAddr; UINTN Bytes; EFI_STATUS Status; PciIo = Pool->PciIo; Block = AllocateZeroPool (sizeof (USBHC_MEM_BLOCK)); if (Block == NULL) { return NULL; } // // each bit in the bit array represents USBHC_MEM_UNIT // bytes of memory in the memory block. // ASSERT (USBHC_MEM_UNIT * 8 <= EFI_PAGE_SIZE); Block->BufLen = EFI_PAGES_TO_SIZE (Pages); Block->BitsLen = Block->BufLen / (USBHC_MEM_UNIT * 8); Block->Bits = AllocateZeroPool (Block->BitsLen); if (Block->Bits == NULL) { gBS->FreePool (Block); return NULL; } // // Allocate the number of Pages of memory, then map it for // bus master read and write. // Status = PciIo->AllocateBuffer ( PciIo, AllocateAnyPages, EfiBootServicesData, Pages, &BufHost, 0 ); if (EFI_ERROR (Status)) { goto FREE_BITARRAY; } Bytes = EFI_PAGES_TO_SIZE (Pages); Status = PciIo->Map ( PciIo, EfiPciIoOperationBusMasterCommonBuffer, BufHost, &Bytes, &MappedAddr, &Mapping ); if (EFI_ERROR (Status) || (Bytes != EFI_PAGES_TO_SIZE (Pages))) { goto FREE_BUFFER; } // // Check whether the data structure used by the host controller // should be restricted into the same 4G // if (Pool->Check4G && (Pool->Which4G != USB_HC_HIGH_32BIT (MappedAddr))) { PciIo->Unmap (PciIo, Mapping); goto FREE_BUFFER; } Block->BufHost = BufHost; Block->Buf = (UINT8 *) ((UINTN) MappedAddr); Block->Mapping = Mapping; return Block; FREE_BUFFER: PciIo->FreeBuffer (PciIo, Pages, BufHost); FREE_BITARRAY: gBS->FreePool (Block->Bits); gBS->FreePool (Block); return NULL; }
/** Allocate a block of memory to be used by the buffer pool. Use Redirect memory services to allocate memmory so that USB DMA transfers do not cause IMR violations on Quark. @param Pool The buffer pool to allocate memory for. @param Pages How many pages to allocate. @return The allocated memory block or NULL if failed. **/ USBHC_MEM_BLOCK * UsbHcAllocMemBlock ( IN USBHC_MEM_POOL *Pool, IN UINTN Pages ) { USBHC_MEM_BLOCK *Block; VOID *BufHost; VOID *Mapping; EFI_PHYSICAL_ADDRESS MappedAddr; EFI_STATUS Status; UINTN PageNumber; EFI_PHYSICAL_ADDRESS TempPtr; Mapping = NULL; PageNumber = sizeof(USBHC_MEM_BLOCK)/PAGESIZE +1; Status = PeiServicesAllocatePages ( EfiBootServicesCode, PageNumber, &TempPtr ); if (EFI_ERROR (Status)) { return NULL; } ZeroMem ((VOID *)(UINTN)TempPtr, PageNumber*EFI_PAGE_SIZE); // // each bit in the bit array represents USBHC_MEM_UNIT // bytes of memory in the memory block. // ASSERT (USBHC_MEM_UNIT * 8 <= EFI_PAGE_SIZE); Block = (USBHC_MEM_BLOCK*)(UINTN)TempPtr; Block->BufLen = EFI_PAGES_TO_SIZE (Pages); Block->BitsLen = Block->BufLen / (USBHC_MEM_UNIT * 8); PageNumber = (Block->BitsLen)/PAGESIZE +1; Status = PeiServicesAllocatePages ( EfiBootServicesCode, PageNumber, &TempPtr ); if (EFI_ERROR (Status)) { return NULL; } ZeroMem ((VOID *)(UINTN)TempPtr, PageNumber*EFI_PAGE_SIZE); Block->Bits = (UINT8 *)(UINTN)TempPtr; Status = PeiServicesAllocatePages ( EfiBootServicesCode, Pages, &TempPtr ); ZeroMem ((VOID *)(UINTN)TempPtr, Pages*EFI_PAGE_SIZE); BufHost = (VOID *)(UINTN)TempPtr; MappedAddr = (EFI_PHYSICAL_ADDRESS) (UINTN) BufHost; // // Check whether the data structure used by the host controller // should be restricted into the same 4G // if (Pool->Check4G && (Pool->Which4G != USB_HC_HIGH_32BIT (MappedAddr))) { return NULL; } Block->BufHost = BufHost; Block->Buf = (UINT8 *) ((UINTN) MappedAddr); Block->Mapping = Mapping; Block->Next = NULL; return Block; }