/** Reset the port and re-configure the usb device. @param PeiServices General-purpose services that are available to every PEIM. @param This Indicates the PEI_USB_IO_PPI instance. @retval EFI_SUCCESS Usb device is reset and configured successfully. @retval Others Other failure occurs. **/ EFI_STATUS EFIAPI PeiUsbPortReset ( IN EFI_PEI_SERVICES **PeiServices, IN PEI_USB_IO_PPI *This ) { PEI_USB_DEVICE *PeiUsbDev; EFI_STATUS Status; UINT8 Address; PeiUsbDev = PEI_USB_DEVICE_FROM_THIS (This); ResetRootPort ( PeiServices, PeiUsbDev->UsbHcPpi, PeiUsbDev->Usb2HcPpi, PeiUsbDev->DeviceAddress, 0 ); // // Set address // Address = PeiUsbDev->DeviceAddress; PeiUsbDev->DeviceAddress = 0; Status = PeiUsbSetDeviceAddress ( PeiServices, This, Address ); if (EFI_ERROR (Status)) { return Status; } PeiUsbDev->DeviceAddress = Address; // // Set default configuration // Status = PeiUsbSetConfiguration ( PeiServices, This ); return Status; }
/** The enumeration routine to detect device change. @param PeiServices Describes the list of possible PEI Services. @param UsbHcPpi The pointer of PEI_USB_HOST_CONTROLLER_PPI instance. @param Usb2HcPpi The pointer of PEI_USB2_HOST_CONTROLLER_PPI instance. @retval EFI_SUCCESS The usb is enumerated successfully. @retval EFI_OUT_OF_RESOURCES Can't allocate memory resource. @retval Others Other failure occurs. **/ EFI_STATUS PeiUsbEnumeration ( IN EFI_PEI_SERVICES **PeiServices, IN PEI_USB_HOST_CONTROLLER_PPI *UsbHcPpi, IN PEI_USB2_HOST_CONTROLLER_PPI *Usb2HcPpi ) { UINT8 NumOfRootPort; EFI_STATUS Status; UINT8 Index; EFI_USB_PORT_STATUS PortStatus; PEI_USB_DEVICE *PeiUsbDevice; UINTN MemPages; EFI_PHYSICAL_ADDRESS AllocateAddress; UINT8 CurrentAddress; UINTN InterfaceIndex; UINTN EndpointIndex; CurrentAddress = 0; if (Usb2HcPpi != NULL) { Usb2HcPpi->GetRootHubPortNumber ( PeiServices, Usb2HcPpi, (UINT8 *) &NumOfRootPort ); } else if (UsbHcPpi != NULL) { UsbHcPpi->GetRootHubPortNumber ( PeiServices, UsbHcPpi, (UINT8 *) &NumOfRootPort ); } else { ASSERT (FALSE); return EFI_INVALID_PARAMETER; } DEBUG ((EFI_D_INFO, "PeiUsbEnumeration: NumOfRootPort: %x\n", NumOfRootPort)); for (Index = 0; Index < NumOfRootPort; Index++) { // // First get root port status to detect changes happen // if (Usb2HcPpi != NULL) { Usb2HcPpi->GetRootHubPortStatus ( PeiServices, Usb2HcPpi, (UINT8) Index, &PortStatus ); } else { UsbHcPpi->GetRootHubPortStatus ( PeiServices, UsbHcPpi, (UINT8) Index, &PortStatus ); } DEBUG ((EFI_D_INFO, "USB Status --- Port: %x ConnectChange[%04x] Status[%04x]\n", Index, PortStatus.PortChangeStatus, PortStatus.PortStatus)); // // Only handle connection/enable/overcurrent/reset change. // if ((PortStatus.PortChangeStatus & (USB_PORT_STAT_C_CONNECTION | USB_PORT_STAT_C_ENABLE | USB_PORT_STAT_C_OVERCURRENT | USB_PORT_STAT_C_RESET)) == 0) { continue; } else { if (IsPortConnect (PortStatus.PortStatus)) { MemPages = sizeof (PEI_USB_DEVICE) / EFI_PAGE_SIZE + 1; Status = PeiServicesAllocatePages ( EfiBootServicesCode, MemPages, &AllocateAddress ); if (EFI_ERROR (Status)) { return EFI_OUT_OF_RESOURCES; } PeiUsbDevice = (PEI_USB_DEVICE *) ((UINTN) AllocateAddress); ZeroMem (PeiUsbDevice, sizeof (PEI_USB_DEVICE)); PeiUsbDevice->Signature = PEI_USB_DEVICE_SIGNATURE; PeiUsbDevice->DeviceAddress = 0; PeiUsbDevice->MaxPacketSize0 = 8; PeiUsbDevice->DataToggle = 0; CopyMem ( &(PeiUsbDevice->UsbIoPpi), &mUsbIoPpi, sizeof (PEI_USB_IO_PPI) ); CopyMem ( &(PeiUsbDevice->UsbIoPpiList), &mUsbIoPpiList, sizeof (EFI_PEI_PPI_DESCRIPTOR) ); PeiUsbDevice->UsbIoPpiList.Ppi = &PeiUsbDevice->UsbIoPpi; PeiUsbDevice->AllocateAddress = (UINTN) AllocateAddress; PeiUsbDevice->UsbHcPpi = UsbHcPpi; PeiUsbDevice->Usb2HcPpi = Usb2HcPpi; PeiUsbDevice->IsHub = 0x0; PeiUsbDevice->DownStreamPortNo = 0x0; if (((PortStatus.PortChangeStatus & USB_PORT_STAT_C_RESET) == 0) || ((PortStatus.PortStatus & (USB_PORT_STAT_CONNECTION | USB_PORT_STAT_ENABLE)) == 0)) { // // If the port already has reset change flag and is connected and enabled, skip the port reset logic. // ResetRootPort ( PeiServices, PeiUsbDevice->UsbHcPpi, PeiUsbDevice->Usb2HcPpi, Index, 0 ); if (Usb2HcPpi != NULL) { Usb2HcPpi->GetRootHubPortStatus ( PeiServices, Usb2HcPpi, (UINT8) Index, &PortStatus ); } else { UsbHcPpi->GetRootHubPortStatus ( PeiServices, UsbHcPpi, (UINT8) Index, &PortStatus ); } } else { if (Usb2HcPpi != NULL) { Usb2HcPpi->ClearRootHubPortFeature ( PeiServices, Usb2HcPpi, (UINT8) Index, EfiUsbPortResetChange ); } else { UsbHcPpi->ClearRootHubPortFeature ( PeiServices, UsbHcPpi, (UINT8) Index, EfiUsbPortResetChange ); } } PeiUsbDevice->DeviceSpeed = (UINT8) PeiUsbGetDeviceSpeed (PortStatus.PortStatus); DEBUG ((EFI_D_INFO, "Device Speed =%d\n", PeiUsbDevice->DeviceSpeed)); if (USB_BIT_IS_SET (PortStatus.PortStatus, USB_PORT_STAT_SUPER_SPEED)){ PeiUsbDevice->MaxPacketSize0 = 512; } else if (USB_BIT_IS_SET (PortStatus.PortStatus, USB_PORT_STAT_HIGH_SPEED)) { PeiUsbDevice->MaxPacketSize0 = 64; } else if (USB_BIT_IS_SET (PortStatus.PortStatus, USB_PORT_STAT_LOW_SPEED)) { PeiUsbDevice->MaxPacketSize0 = 8; } else { PeiUsbDevice->MaxPacketSize0 = 8; } // // Configure that Usb Device // Status = PeiConfigureUsbDevice ( PeiServices, PeiUsbDevice, Index, &CurrentAddress ); if (EFI_ERROR (Status)) { continue; } DEBUG ((EFI_D_INFO, "PeiUsbEnumeration: PeiConfigureUsbDevice Success\n")); Status = PeiServicesInstallPpi (&PeiUsbDevice->UsbIoPpiList); if (PeiUsbDevice->InterfaceDesc->InterfaceClass == 0x09) { PeiUsbDevice->IsHub = 0x1; Status = PeiDoHubConfig (PeiServices, PeiUsbDevice); if (EFI_ERROR (Status)) { return Status; } PeiHubEnumeration (PeiServices, PeiUsbDevice, &CurrentAddress); } for (InterfaceIndex = 1; InterfaceIndex < PeiUsbDevice->ConfigDesc->NumInterfaces; InterfaceIndex++) { // // Begin to deal with the new device // MemPages = sizeof (PEI_USB_DEVICE) / EFI_PAGE_SIZE + 1; Status = PeiServicesAllocatePages ( EfiBootServicesCode, MemPages, &AllocateAddress ); if (EFI_ERROR (Status)) { return EFI_OUT_OF_RESOURCES; } CopyMem ((VOID *)(UINTN)AllocateAddress, PeiUsbDevice, sizeof (PEI_USB_DEVICE)); PeiUsbDevice = (PEI_USB_DEVICE *) ((UINTN) AllocateAddress); PeiUsbDevice->AllocateAddress = (UINTN) AllocateAddress; PeiUsbDevice->UsbIoPpiList.Ppi = &PeiUsbDevice->UsbIoPpi; PeiUsbDevice->InterfaceDesc = PeiUsbDevice->InterfaceDescList[InterfaceIndex]; for (EndpointIndex = 0; EndpointIndex < PeiUsbDevice->InterfaceDesc->NumEndpoints; EndpointIndex++) { PeiUsbDevice->EndpointDesc[EndpointIndex] = PeiUsbDevice->EndpointDescList[InterfaceIndex][EndpointIndex]; } Status = PeiServicesInstallPpi (&PeiUsbDevice->UsbIoPpiList); if (PeiUsbDevice->InterfaceDesc->InterfaceClass == 0x09) { PeiUsbDevice->IsHub = 0x1; Status = PeiDoHubConfig (PeiServices, PeiUsbDevice); if (EFI_ERROR (Status)) { return Status; } PeiHubEnumeration (PeiServices, PeiUsbDevice, &CurrentAddress); } } } else { // // Disconnect change happen, currently we don't support // } } } return EFI_SUCCESS; }