/** Reset the input device and optionally run diagnostics There are 2 types of reset for USB keyboard. For non-exhaustive reset, only keyboard buffer is cleared. For exhaustive reset, in addition to clearance of keyboard buffer, the hardware status is also re-initialized. @param This Protocol instance pointer. @param ExtendedVerification Driver may perform diagnostics on reset. @retval EFI_SUCCESS The device was reset. @retval EFI_DEVICE_ERROR The device is not functioning properly and could not be reset. **/ EFI_STATUS EFIAPI USBKeyboardReset ( IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This, IN BOOLEAN ExtendedVerification ) { EFI_STATUS Status; USB_KB_DEV *UsbKeyboardDevice; UsbKeyboardDevice = USB_KB_DEV_FROM_THIS (This); REPORT_STATUS_CODE_WITH_DEVICE_PATH ( EFI_PROGRESS_CODE, (EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_RESET), UsbKeyboardDevice->DevicePath ); // // Non-exhaustive reset: // only reset private data structures. // if (!ExtendedVerification) { REPORT_STATUS_CODE_WITH_DEVICE_PATH ( EFI_PROGRESS_CODE, (EFI_PERIPHERAL_KEYBOARD | EFI_P_KEYBOARD_PC_CLEAR_BUFFER), UsbKeyboardDevice->DevicePath ); // // Clear the key buffer of this USB keyboard // InitQueue (&UsbKeyboardDevice->UsbKeyQueue, sizeof (USB_KEY)); InitQueue (&UsbKeyboardDevice->EfiKeyQueue, sizeof (EFI_KEY_DATA)); InitQueue (&UsbKeyboardDevice->EfiKeyQueueForNotify, sizeof (EFI_KEY_DATA)); return EFI_SUCCESS; } // // Exhaustive reset // Status = InitUSBKeyboard (UsbKeyboardDevice); if (EFI_ERROR (Status)) { return EFI_DEVICE_ERROR; } return EFI_SUCCESS; }
/** Resets the SCSI Bus that the SCSI Controller is attached to. @param This Protocol instance pointer. @retval EFI_SUCCESS The SCSI bus is reset successfully. @retval EFI_DEVICE_ERROR Errors encountered when resetting the SCSI bus. @retval EFI_UNSUPPORTED The bus reset operation is not supported by the SCSI Host Controller. @retval EFI_TIMEOUT A timeout occurred while attempting to reset the SCSI bus. **/ EFI_STATUS EFIAPI ScsiResetBus ( IN EFI_SCSI_IO_PROTOCOL *This ) { SCSI_IO_DEV *ScsiIoDevice; ScsiIoDevice = SCSI_IO_DEV_FROM_THIS (This); // // Report Status Code to indicate reset happens // REPORT_STATUS_CODE_WITH_DEVICE_PATH ( EFI_PROGRESS_CODE, (EFI_IO_BUS_ATA_ATAPI | EFI_IOB_PC_RESET), ScsiIoDevice->ScsiBusDeviceData->DevicePath ); if (ScsiIoDevice->ExtScsiSupport){ return ScsiIoDevice->ExtScsiPassThru->ResetChannel (ScsiIoDevice->ExtScsiPassThru); } else { return ScsiIoDevice->ScsiPassThru->ResetChannel (ScsiIoDevice->ScsiPassThru); } }
/** Resets the pointer device hardware. @param This A pointer to the EFI_SIMPLE_POINTER_PROTOCOL instance. @param ExtendedVerification Indicates that the driver may perform a more exhaustive verification operation of the device during reset. @retval EFI_SUCCESS The device was reset. @retval EFI_DEVICE_ERROR The device is not functioning correctly and could not be reset. **/ EFI_STATUS EFIAPI UsbMouseReset ( IN EFI_SIMPLE_POINTER_PROTOCOL *This, IN BOOLEAN ExtendedVerification ) { USB_MOUSE_DEV *UsbMouseDevice; UsbMouseDevice = USB_MOUSE_DEV_FROM_MOUSE_PROTOCOL (This); REPORT_STATUS_CODE_WITH_DEVICE_PATH ( EFI_PROGRESS_CODE, (EFI_PERIPHERAL_MOUSE | EFI_P_PC_RESET), UsbMouseDevice->DevicePath ); // // Clear mouse state. // ZeroMem ( &UsbMouseDevice->State, sizeof (EFI_SIMPLE_POINTER_STATE) ); UsbMouseDevice->StateChanged = FALSE; return EFI_SUCCESS; }
/** Implements EFI_SIMPLE_TEXT_INPUT_PROTOCOL.Reset(). This driver only perform dependent serial device reset regardless of the value of ExtendeVerification @param This Indicates the calling context. @param ExtendedVerification Skip by this driver. @retval EFI_SUCCESS The reset operation succeeds. @retval EFI_DEVICE_ERROR The dependent serial port reset fails. **/ EFI_STATUS EFIAPI TerminalConInReset ( IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This, IN BOOLEAN ExtendedVerification ) { EFI_STATUS Status; TERMINAL_DEV *TerminalDevice; TerminalDevice = TERMINAL_CON_IN_DEV_FROM_THIS (This); // // Report progress code here // REPORT_STATUS_CODE_WITH_DEVICE_PATH ( EFI_PROGRESS_CODE, (EFI_PERIPHERAL_REMOTE_CONSOLE | EFI_P_PC_RESET), TerminalDevice->DevicePath ); Status = TerminalDevice->SerialIo->Reset (TerminalDevice->SerialIo); // // Make all the internal buffer empty for keys // TerminalDevice->RawFiFo->Head = TerminalDevice->RawFiFo->Tail; TerminalDevice->UnicodeFiFo->Head = TerminalDevice->UnicodeFiFo->Tail; TerminalDevice->EfiKeyFiFo->Head = TerminalDevice->EfiKeyFiFo->Tail; if (EFI_ERROR (Status)) { REPORT_STATUS_CODE_WITH_DEVICE_PATH ( EFI_ERROR_CODE | EFI_ERROR_MINOR, (EFI_PERIPHERAL_REMOTE_CONSOLE | EFI_P_EC_CONTROLLER_ERROR), TerminalDevice->DevicePath ); } return Status; }
/** Common report status code interface. @param This Pointer of FDC_BLK_IO_DEV instance @param Read Read or write operation when error occurrs **/ VOID FddReportStatus ( IN EFI_BLOCK_IO_PROTOCOL *This, IN BOOLEAN Read ) { FDC_BLK_IO_DEV *FdcDev; FdcDev = FDD_BLK_IO_FROM_THIS (This); REPORT_STATUS_CODE_WITH_DEVICE_PATH ( EFI_ERROR_CODE, ((Read) ? EFI_P_EC_INPUT_ERROR : EFI_P_EC_OUTPUT_ERROR) | EFI_PERIPHERAL_REMOVABLE_MEDIA, FdcDev->DevicePath ); }
/** Reset the Block Device. @param This Indicates a pointer to the calling context. @param ExtendedVerification Driver may perform diagnostics on reset. @retval EFI_SUCCESS The device was reset. @retval EFI_DEVICE_ERROR The device is not functioning properly and could not be reset. **/ EFI_STATUS EFIAPI FdcReset ( IN EFI_BLOCK_IO_PROTOCOL *This, IN BOOLEAN ExtendedVerification ) { FDC_BLK_IO_DEV *FdcDev; // // Reset the Floppy Disk Controller // FdcDev = FDD_BLK_IO_FROM_THIS (This); REPORT_STATUS_CODE_WITH_DEVICE_PATH ( EFI_PROGRESS_CODE, EFI_P_PC_RESET | EFI_PERIPHERAL_REMOVABLE_MEDIA, FdcDev->DevicePath ); return FddReset (FdcDev); }
/** Resets the SCSI Controller that the device handle specifies. @param This Protocol instance pointer. @retval EFI_SUCCESS Reset the SCSI controller successfully. @retval EFI_DEVICE_ERROR Errors are encountered when resetting the SCSI Controller. @retval EFI_UNSUPPORTED The SCSI bus does not support a device reset operation. @retval EFI_TIMEOUT A timeout occurred while attempting to reset the SCSI Controller. **/ EFI_STATUS EFIAPI ScsiResetDevice ( IN EFI_SCSI_IO_PROTOCOL *This ) { SCSI_IO_DEV *ScsiIoDevice; UINT8 Target[TARGET_MAX_BYTES]; ScsiIoDevice = SCSI_IO_DEV_FROM_THIS (This); // // Report Status Code to indicate reset happens // REPORT_STATUS_CODE_WITH_DEVICE_PATH ( EFI_PROGRESS_CODE, (EFI_IO_BUS_ATA_ATAPI | EFI_IOB_PC_RESET), ScsiIoDevice->ScsiBusDeviceData->DevicePath ); CopyMem (Target,&ScsiIoDevice->Pun, TARGET_MAX_BYTES); if (ScsiIoDevice->ExtScsiSupport) { return ScsiIoDevice->ExtScsiPassThru->ResetTargetLun ( ScsiIoDevice->ExtScsiPassThru, Target, ScsiIoDevice->Lun ); } else { return ScsiIoDevice->ScsiPassThru->ResetTarget ( ScsiIoDevice->ScsiPassThru, ScsiIoDevice->Pun.ScsiId.Scsi, ScsiIoDevice->Lun ); } }
/** Starts a device controller or a bus controller. The Start() function is designed to be invoked from the EFI boot service ConnectController(). As a result, much of the error checking on the parameters to Start() has been moved into this common boot service. It is legal to call Start() from other locations, but the following calling restrictions must be followed or the system behavior will not be deterministic. 1. ControllerHandle must be a valid EFI_HANDLE. 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned EFI_DEVICE_PATH_PROTOCOL. 3. Prior to calling Start(), the Supported() function for the driver specified by This must have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS. @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. @param[in] ControllerHandle The handle of the controller to start. This handle must support a protocol interface that supplies an I/O abstraction to the driver. @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This parameter is ignored by device drivers, and is optional for bus drivers. For a bus driver, if this parameter is NULL, then handles for all the children of Controller are created by this driver. If this parameter is not NULL and the first Device Path Node is not the End of Device Path Node, then only the handle for the child device specified by the first Device Path Node of RemainingDevicePath is created by this driver. If the first Device Path Node of RemainingDevicePath is the End of Device Path Node, no child handle is created by this driver. @retval EFI_SUCCESS The device was started. @retval EFI_DEVICE_ERROR The device could not be started due to a device error. @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. @retval Others The driver failded to start the device. **/ EFI_STATUS EFIAPI SioBusDriverBindingStart ( IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE Controller, IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath ) { EFI_STATUS Status; EFI_PCI_IO_PROTOCOL *PciIo; EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath; UINT64 Supports; UINT64 OriginalAttributes; UINT64 Attributes; BOOLEAN Enabled; SIO_BUS_DRIVER_PRIVATE_DATA *Private; UINT32 ChildDeviceNumber; Enabled = FALSE; Supports = 0; OriginalAttributes = 0; Private = NULL; // // Open the PCI I/O Protocol Interface // PciIo = NULL; Status = gBS->OpenProtocol ( Controller, &gEfiPciIoProtocolGuid, (VOID**) &PciIo, This->DriverBindingHandle, Controller, EFI_OPEN_PROTOCOL_BY_DRIVER ); if (EFI_ERROR (Status)) { return Status; } // // Open Device Path Protocol // Status = gBS->OpenProtocol ( Controller, &gEfiDevicePathProtocolGuid, (VOID **) &ParentDevicePath, This->DriverBindingHandle, Controller, EFI_OPEN_PROTOCOL_BY_DRIVER ); if (EFI_ERROR (Status)) { gBS->CloseProtocol ( Controller, &gEfiPciIoProtocolGuid, This->DriverBindingHandle, Controller ); return Status; } // // Get supported PCI attributes // Status = PciIo->Attributes ( PciIo, EfiPciIoAttributeOperationSupported, 0, &Supports ); if (EFI_ERROR (Status)) { goto Done; } Supports &= (UINT64) (EFI_PCI_IO_ATTRIBUTE_ISA_IO | EFI_PCI_IO_ATTRIBUTE_ISA_IO_16); if (Supports == 0 || Supports == (EFI_PCI_IO_ATTRIBUTE_ISA_IO | EFI_PCI_IO_ATTRIBUTE_ISA_IO_16)) { Status = EFI_UNSUPPORTED; goto Done; } Status = PciIo->Attributes ( PciIo, EfiPciIoAttributeOperationGet, 0, &OriginalAttributes ); if (EFI_ERROR (Status)) { goto Done; } Attributes = EFI_PCI_DEVICE_ENABLE | Supports | EFI_PCI_IO_ATTRIBUTE_ISA_MOTHERBOARD_IO; Status = PciIo->Attributes ( PciIo, EfiPciIoAttributeOperationEnable, Attributes, NULL ); if (EFI_ERROR (Status)) { goto Done; } Enabled = TRUE; // // Store the OriginalAttributes for the restore in BindingStop() // Private = AllocateZeroPool (sizeof (SIO_BUS_DRIVER_PRIVATE_DATA)); if (Private == NULL) { Status = EFI_OUT_OF_RESOURCES; goto Done; } Private->PciIo = PciIo; Private->OriginalAttributes = OriginalAttributes; Status = gBS->InstallProtocolInterface ( &Controller, &gEfiCallerIdGuid, EFI_NATIVE_INTERFACE, Private ); if (EFI_ERROR (Status)) { goto Done; } // // Report status code for the start of general controller initialization // REPORT_STATUS_CODE_WITH_DEVICE_PATH ( EFI_PROGRESS_CODE, (EFI_IO_BUS_LPC | EFI_IOB_PC_INIT), ParentDevicePath ); // // Report status code for the start of enabling devices on the bus // REPORT_STATUS_CODE_WITH_DEVICE_PATH ( EFI_PROGRESS_CODE, (EFI_IO_BUS_LPC | EFI_IOB_PC_ENABLE), ParentDevicePath ); // // Create all the children upon the first entrance // ChildDeviceNumber = SioCreateAllChildDevices ( This, Controller, PciIo, ParentDevicePath ); if (ChildDeviceNumber == 0) { Status = EFI_DEVICE_ERROR; } Done: if (EFI_ERROR (Status)) { if (PciIo != NULL && Enabled) { PciIo->Attributes ( PciIo, EfiPciIoAttributeOperationSet, OriginalAttributes, NULL ); } gBS->CloseProtocol ( Controller, &gEfiDevicePathProtocolGuid, This->DriverBindingHandle, Controller ); gBS->CloseProtocol ( Controller, &gEfiPciIoProtocolGuid, This->DriverBindingHandle, Controller ); if (Private != NULL) { gBS->UninstallMultipleProtocolInterfaces ( Controller, &gEfiCallerIdGuid, Private, NULL ); FreePool (Private); } return Status; } return EFI_SUCCESS; }
/** Perform 8042 controller and keyboard initialization which implement SIMPLE_TEXT_IN.Reset() @param This Pointer to instance of EFI_SIMPLE_TEXT_INPUT_PROTOCOL @param ExtendedVerification Indicate that the driver may perform a more exhaustive verification operation of the device during reset, now this par is ignored in this driver **/ EFI_STATUS EFIAPI KeyboardEfiReset ( IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This, IN BOOLEAN ExtendedVerification ) { EFI_STATUS Status; KEYBOARD_CONSOLE_IN_DEV *ConsoleIn; EFI_TPL OldTpl; ConsoleIn = KEYBOARD_CONSOLE_IN_DEV_FROM_THIS (This); if (ConsoleIn->KeyboardErr) { return EFI_DEVICE_ERROR; } REPORT_STATUS_CODE_WITH_DEVICE_PATH ( EFI_PROGRESS_CODE, EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_RESET, ConsoleIn->DevicePath ); // // Enter critical section // OldTpl = gBS->RaiseTPL (TPL_NOTIFY); // // Call InitKeyboard to initialize the keyboard // Status = InitKeyboard (ConsoleIn, ExtendedVerification); if (EFI_ERROR (Status)) { // // Leave critical section and return // gBS->RestoreTPL (OldTpl); return EFI_DEVICE_ERROR; } // // Clear the status of ConsoleIn.Key // ConsoleIn->Key.ScanCode = SCAN_NULL; ConsoleIn->Key.UnicodeChar = 0x0000; // // Leave critical section and return // gBS->RestoreTPL (OldTpl); // // Report the status If a stuck key was detected // if (KeyReadStatusRegister (ConsoleIn) & 0x01) { REPORT_STATUS_CODE_WITH_DEVICE_PATH ( EFI_ERROR_CODE | EFI_ERROR_MINOR, EFI_PERIPHERAL_KEYBOARD | EFI_P_KEYBOARD_EC_STUCK_KEY, ConsoleIn->DevicePath ); } // // Report the status If keyboard is locked // if ((KeyReadStatusRegister (ConsoleIn) & 0x10) == 0) { REPORT_STATUS_CODE_WITH_DEVICE_PATH ( EFI_ERROR_CODE | EFI_ERROR_MINOR, EFI_PERIPHERAL_KEYBOARD | EFI_P_KEYBOARD_EC_LOCKED, ConsoleIn->DevicePath ); } return EFI_SUCCESS; }
/** Stop the USB mouse device handled by this driver. @param This The USB mouse driver binding protocol. @param Controller The controller to release. @param NumberOfChildren The number of handles in ChildHandleBuffer. @param ChildHandleBuffer The array of child handle. @retval EFI_SUCCESS The device was stopped. @retval EFI_UNSUPPORTED Simple Pointer Protocol is not installed on Controller. @retval Others Fail to uninstall protocols attached on the device. **/ EFI_STATUS EFIAPI USBMouseDriverBindingStop ( IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE Controller, IN UINTN NumberOfChildren, IN EFI_HANDLE *ChildHandleBuffer ) { EFI_STATUS Status; USB_MOUSE_DEV *UsbMouseDevice; EFI_SIMPLE_POINTER_PROTOCOL *SimplePointerProtocol; EFI_USB_IO_PROTOCOL *UsbIo; Status = gBS->OpenProtocol ( Controller, &gEfiSimplePointerProtocolGuid, (VOID **) &SimplePointerProtocol, This->DriverBindingHandle, Controller, EFI_OPEN_PROTOCOL_GET_PROTOCOL ); if (EFI_ERROR (Status)) { return EFI_UNSUPPORTED; } UsbMouseDevice = USB_MOUSE_DEV_FROM_MOUSE_PROTOCOL (SimplePointerProtocol); UsbIo = UsbMouseDevice->UsbIo; // // The key data input from this device will be disabled. // REPORT_STATUS_CODE_WITH_DEVICE_PATH ( EFI_PROGRESS_CODE, (EFI_PERIPHERAL_MOUSE | EFI_P_PC_DISABLE), UsbMouseDevice->DevicePath ); // // Delete the Asynchronous Interrupt Transfer from this device // UsbIo->UsbAsyncInterruptTransfer ( UsbIo, UsbMouseDevice->IntEndpointDescriptor.EndpointAddress, FALSE, UsbMouseDevice->IntEndpointDescriptor.Interval, 0, NULL, NULL ); Status = gBS->UninstallProtocolInterface ( Controller, &gEfiSimplePointerProtocolGuid, &UsbMouseDevice->SimplePointerProtocol ); if (EFI_ERROR (Status)) { return Status; } gBS->CloseProtocol ( Controller, &gEfiUsbIoProtocolGuid, This->DriverBindingHandle, Controller ); // // Free all resources. // gBS->CloseEvent (UsbMouseDevice->SimplePointerProtocol.WaitForInput); if (UsbMouseDevice->DelayedRecoveryEvent != NULL) { gBS->CloseEvent (UsbMouseDevice->DelayedRecoveryEvent); UsbMouseDevice->DelayedRecoveryEvent = NULL; } if (UsbMouseDevice->ControllerNameTable != NULL) { FreeUnicodeStringTable (UsbMouseDevice->ControllerNameTable); } FreePool (UsbMouseDevice); return EFI_SUCCESS; }
/** Handler function for USB mouse's asynchronous interrupt transfer. This function is the handler function for USB mouse's asynchronous interrupt transfer to manage the mouse. It parses data returned from asynchronous interrupt transfer, and get button and movement state. @param Data A pointer to a buffer that is filled with key data which is retrieved via asynchronous interrupt transfer. @param DataLength Indicates the size of the data buffer. @param Context Pointing to USB_KB_DEV instance. @param Result Indicates the result of the asynchronous interrupt transfer. @retval EFI_SUCCESS Asynchronous interrupt transfer is handled successfully. @retval EFI_DEVICE_ERROR Hardware error occurs. **/ EFI_STATUS EFIAPI OnMouseInterruptComplete ( IN VOID *Data, IN UINTN DataLength, IN VOID *Context, IN UINT32 Result ) { USB_MOUSE_DEV *UsbMouseDevice; EFI_USB_IO_PROTOCOL *UsbIo; UINT8 EndpointAddr; UINT32 UsbResult; UsbMouseDevice = (USB_MOUSE_DEV *) Context; UsbIo = UsbMouseDevice->UsbIo; if (Result != EFI_USB_NOERROR) { // // Some errors happen during the process // REPORT_STATUS_CODE_WITH_DEVICE_PATH ( EFI_ERROR_CODE | EFI_ERROR_MINOR, (EFI_PERIPHERAL_MOUSE | EFI_P_EC_INPUT_ERROR), UsbMouseDevice->DevicePath ); if ((Result & EFI_USB_ERR_STALL) == EFI_USB_ERR_STALL) { EndpointAddr = UsbMouseDevice->IntEndpointDescriptor.EndpointAddress; UsbClearEndpointHalt ( UsbIo, EndpointAddr, &UsbResult ); } // // Delete & Submit this interrupt again // Handler of DelayedRecoveryEvent triggered by timer will re-submit the interrupt. // UsbIo->UsbAsyncInterruptTransfer ( UsbIo, UsbMouseDevice->IntEndpointDescriptor.EndpointAddress, FALSE, 0, 0, NULL, NULL ); // // EFI_USB_INTERRUPT_DELAY is defined in USB standard for error handling. // gBS->SetTimer ( UsbMouseDevice->DelayedRecoveryEvent, TimerRelative, EFI_USB_INTERRUPT_DELAY ); return EFI_DEVICE_ERROR; } // // If no error and no data, just return EFI_SUCCESS. // if (DataLength == 0 || Data == NULL) { return EFI_SUCCESS; } UsbMouseDevice->StateChanged = TRUE; // // Check mouse Data // USB HID Specification specifies following data format: // Byte Bits Description // 0 0 Button 1 // 1 Button 2 // 2 Button 3 // 4 to 7 Device-specific // 1 0 to 7 X displacement // 2 0 to 7 Y displacement // 3 to n 0 to 7 Device specific (optional) // UsbMouseDevice->State.LeftButton = (BOOLEAN) ((*(UINT8 *) Data & BIT0) != 0); UsbMouseDevice->State.RightButton = (BOOLEAN) ((*(UINT8 *) Data & BIT1) != 0); UsbMouseDevice->State.RelativeMovementX += *((INT8 *) Data + 1); UsbMouseDevice->State.RelativeMovementY += *((INT8 *) Data + 2); if (DataLength > 3) { UsbMouseDevice->State.RelativeMovementZ += *((INT8 *) Data + 3); } return EFI_SUCCESS; }
/** Timer handler to poll the key from serial. @param Event Indicates the event that invoke this function. @param Context Indicates the calling context. **/ VOID EFIAPI TerminalConInTimerHandler ( IN EFI_EVENT Event, IN VOID *Context ) { EFI_STATUS Status; TERMINAL_DEV *TerminalDevice; UINT32 Control; UINT8 Input; EFI_SERIAL_IO_MODE *Mode; EFI_SERIAL_IO_PROTOCOL *SerialIo; UINTN SerialInTimeOut; TerminalDevice = (TERMINAL_DEV *) Context; SerialIo = TerminalDevice->SerialIo; if (SerialIo == NULL) { return ; } // // if current timeout value for serial device is not identical with // the value saved in TERMINAL_DEV structure, then recalculate the // timeout value again and set serial attribute according to this value. // Mode = SerialIo->Mode; if (Mode->Timeout != TerminalDevice->SerialInTimeOut) { SerialInTimeOut = 0; if (Mode->BaudRate != 0) { // // According to BAUD rate to calculate the timeout value. // SerialInTimeOut = (1 + Mode->DataBits + Mode->StopBits) * 2 * 1000000 / (UINTN) Mode->BaudRate; } Status = SerialIo->SetAttributes ( SerialIo, Mode->BaudRate, Mode->ReceiveFifoDepth, (UINT32) SerialInTimeOut, (EFI_PARITY_TYPE) (Mode->Parity), (UINT8) Mode->DataBits, (EFI_STOP_BITS_TYPE) (Mode->StopBits) ); if (EFI_ERROR (Status)) { TerminalDevice->SerialInTimeOut = 0; } else { TerminalDevice->SerialInTimeOut = SerialInTimeOut; } } // // Check whether serial buffer is empty. // Status = SerialIo->GetControl (SerialIo, &Control); if ((Control & EFI_SERIAL_INPUT_BUFFER_EMPTY) == 0) { // // Fetch all the keys in the serial buffer, // and insert the byte stream into RawFIFO. // while (!IsRawFiFoFull (TerminalDevice)) { Status = GetOneKeyFromSerial (TerminalDevice->SerialIo, &Input); if (EFI_ERROR (Status)) { if (Status == EFI_DEVICE_ERROR) { REPORT_STATUS_CODE_WITH_DEVICE_PATH ( EFI_ERROR_CODE | EFI_ERROR_MINOR, (EFI_PERIPHERAL_REMOTE_CONSOLE | EFI_P_EC_INPUT_ERROR), TerminalDevice->DevicePath ); } break; } RawFiFoInsertOneKey (TerminalDevice, Input); } } // // Translate all the raw data in RawFIFO into EFI Key, // according to different terminal type supported. // TranslateRawDataToEfiKey (TerminalDevice); }
/** Starts the mouse device with this driver. This function consumes USB I/O Portocol, intializes USB mouse device, installs Simple Pointer Protocol, and submits Asynchronous Interrupt Transfer to manage the USB mouse device. @param This The USB mouse driver binding instance. @param Controller Handle of device to bind driver to. @param RemainingDevicePath Optional parameter use to pick a specific child device to start. @retval EFI_SUCCESS This driver supports this device. @retval EFI_UNSUPPORTED This driver does not support this device. @retval EFI_DEVICE_ERROR This driver cannot be started due to device Error. @retval EFI_OUT_OF_RESOURCES Can't allocate memory resources. @retval EFI_ALREADY_STARTED This driver has been started. **/ EFI_STATUS EFIAPI USBMouseDriverBindingStart ( IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE Controller, IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath ) { EFI_STATUS Status; EFI_USB_IO_PROTOCOL *UsbIo; USB_MOUSE_DEV *UsbMouseDevice; UINT8 EndpointNumber; EFI_USB_ENDPOINT_DESCRIPTOR EndpointDescriptor; UINT8 Index; UINT8 EndpointAddr; UINT8 PollingInterval; UINT8 PacketSize; BOOLEAN Found; EFI_TPL OldTpl; OldTpl = gBS->RaiseTPL (TPL_CALLBACK); // // Open USB I/O Protocol // Status = gBS->OpenProtocol ( Controller, &gEfiUsbIoProtocolGuid, (VOID **) &UsbIo, This->DriverBindingHandle, Controller, EFI_OPEN_PROTOCOL_BY_DRIVER ); if (EFI_ERROR (Status)) { goto ErrorExit1; } UsbMouseDevice = AllocateZeroPool (sizeof (USB_MOUSE_DEV)); ASSERT (UsbMouseDevice != NULL); UsbMouseDevice->UsbIo = UsbIo; UsbMouseDevice->Signature = USB_MOUSE_DEV_SIGNATURE; // // Get the Device Path Protocol on Controller's handle // Status = gBS->OpenProtocol ( Controller, &gEfiDevicePathProtocolGuid, (VOID **) &UsbMouseDevice->DevicePath, This->DriverBindingHandle, Controller, EFI_OPEN_PROTOCOL_GET_PROTOCOL ); if (EFI_ERROR (Status)) { goto ErrorExit; } // // Report Status Code here since USB mouse will be detected next. // REPORT_STATUS_CODE_WITH_DEVICE_PATH ( EFI_PROGRESS_CODE, (EFI_PERIPHERAL_MOUSE | EFI_P_PC_PRESENCE_DETECT), UsbMouseDevice->DevicePath ); // // Get interface & endpoint descriptor // UsbIo->UsbGetInterfaceDescriptor ( UsbIo, &UsbMouseDevice->InterfaceDescriptor ); EndpointNumber = UsbMouseDevice->InterfaceDescriptor.NumEndpoints; // // Traverse endpoints to find interrupt endpoint // Found = FALSE; for (Index = 0; Index < EndpointNumber; Index++) { UsbIo->UsbGetEndpointDescriptor ( UsbIo, Index, &EndpointDescriptor ); if ((EndpointDescriptor.Attributes & (BIT0 | BIT1)) == USB_ENDPOINT_INTERRUPT) { // // We only care interrupt endpoint here // CopyMem(&UsbMouseDevice->IntEndpointDescriptor, &EndpointDescriptor, sizeof(EndpointDescriptor)); Found = TRUE; break; } } if (!Found) { // // Report Status Code to indicate that there is no USB mouse // REPORT_STATUS_CODE ( EFI_ERROR_CODE | EFI_ERROR_MINOR, (EFI_PERIPHERAL_MOUSE | EFI_P_EC_NOT_DETECTED) ); // // No interrupt endpoint found, then return unsupported. // Status = EFI_UNSUPPORTED; goto ErrorExit; } // // Report Status Code here since USB mouse has be detected. // REPORT_STATUS_CODE_WITH_DEVICE_PATH ( EFI_PROGRESS_CODE, (EFI_PERIPHERAL_MOUSE | EFI_P_PC_DETECTED), UsbMouseDevice->DevicePath ); Status = InitializeUsbMouseDevice (UsbMouseDevice); if (EFI_ERROR (Status)) { // // Fail to initialize USB mouse device. // REPORT_STATUS_CODE_WITH_DEVICE_PATH ( EFI_ERROR_CODE | EFI_ERROR_MINOR, (EFI_PERIPHERAL_MOUSE | EFI_P_EC_INTERFACE_ERROR), UsbMouseDevice->DevicePath ); goto ErrorExit; } // // Initialize and install EFI Simple Pointer Protocol. // UsbMouseDevice->SimplePointerProtocol.GetState = GetMouseState; UsbMouseDevice->SimplePointerProtocol.Reset = UsbMouseReset; UsbMouseDevice->SimplePointerProtocol.Mode = &UsbMouseDevice->Mode; Status = gBS->CreateEvent ( EVT_NOTIFY_WAIT, TPL_NOTIFY, UsbMouseWaitForInput, UsbMouseDevice, &((UsbMouseDevice->SimplePointerProtocol).WaitForInput) ); if (EFI_ERROR (Status)) { goto ErrorExit; } Status = gBS->InstallProtocolInterface ( &Controller, &gEfiSimplePointerProtocolGuid, EFI_NATIVE_INTERFACE, &UsbMouseDevice->SimplePointerProtocol ); if (EFI_ERROR (Status)) { goto ErrorExit; } // // The next step would be submitting Asynchronous Interrupt Transfer on this mouse device. // After that we will be able to get key data from it. Thus this is deemed as // the enable action of the mouse, so report status code accordingly. // REPORT_STATUS_CODE_WITH_DEVICE_PATH ( EFI_PROGRESS_CODE, (EFI_PERIPHERAL_MOUSE | EFI_P_PC_ENABLE), UsbMouseDevice->DevicePath ); // // Submit Asynchronous Interrupt Transfer to manage this device. // EndpointAddr = UsbMouseDevice->IntEndpointDescriptor.EndpointAddress; PollingInterval = UsbMouseDevice->IntEndpointDescriptor.Interval; PacketSize = (UINT8) (UsbMouseDevice->IntEndpointDescriptor.MaxPacketSize); Status = UsbIo->UsbAsyncInterruptTransfer ( UsbIo, EndpointAddr, TRUE, PollingInterval, PacketSize, OnMouseInterruptComplete, UsbMouseDevice ); if (EFI_ERROR (Status)) { // // If submit error, uninstall that interface // gBS->UninstallProtocolInterface ( Controller, &gEfiSimplePointerProtocolGuid, &UsbMouseDevice->SimplePointerProtocol ); goto ErrorExit; } UsbMouseDevice->ControllerNameTable = NULL; AddUnicodeString2 ( "eng", gUsbMouseComponentName.SupportedLanguages, &UsbMouseDevice->ControllerNameTable, L"Generic Usb Mouse", TRUE ); AddUnicodeString2 ( "en", gUsbMouseComponentName2.SupportedLanguages, &UsbMouseDevice->ControllerNameTable, L"Generic Usb Mouse", FALSE ); gBS->RestoreTPL (OldTpl); return EFI_SUCCESS; // // Error handler // ErrorExit: if (EFI_ERROR (Status)) { gBS->CloseProtocol ( Controller, &gEfiUsbIoProtocolGuid, This->DriverBindingHandle, Controller ); if (UsbMouseDevice != NULL) { if ((UsbMouseDevice->SimplePointerProtocol).WaitForInput != NULL) { gBS->CloseEvent ((UsbMouseDevice->SimplePointerProtocol).WaitForInput); } FreePool (UsbMouseDevice); UsbMouseDevice = NULL; } } ErrorExit1: gBS->RestoreTPL (OldTpl); return Status; }
/** Create KEYBOARD_CONSOLE_IN_DEV instance on controller. @param This Pointer of EFI_DRIVER_BINDING_PROTOCOL @param Controller driver controller handle @param RemainingDevicePath Children's device path @retval whether success to create floppy control instance. **/ EFI_STATUS EFIAPI KbdControllerDriverStart ( IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE Controller, IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath ) { EFI_STATUS Status; EFI_STATUS Status1; EFI_ISA_IO_PROTOCOL *IsaIo; KEYBOARD_CONSOLE_IN_DEV *ConsoleIn; UINT8 Data; EFI_STATUS_CODE_VALUE StatusCode; EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath; StatusCode = 0; Status = gBS->OpenProtocol ( Controller, &gEfiDevicePathProtocolGuid, (VOID **) &ParentDevicePath, This->DriverBindingHandle, Controller, EFI_OPEN_PROTOCOL_BY_DRIVER ); if (EFI_ERROR (Status)) { return Status; } // // Report that the keyboard is being enabled // REPORT_STATUS_CODE_WITH_DEVICE_PATH ( EFI_PROGRESS_CODE, EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_ENABLE, ParentDevicePath ); // // Get the ISA I/O Protocol on Controller's handle // Status = gBS->OpenProtocol ( Controller, &gEfiIsaIoProtocolGuid, (VOID **) &IsaIo, This->DriverBindingHandle, Controller, EFI_OPEN_PROTOCOL_BY_DRIVER ); if (EFI_ERROR (Status)) { gBS->CloseProtocol ( Controller, &gEfiDevicePathProtocolGuid, This->DriverBindingHandle, Controller ); return EFI_INVALID_PARAMETER; } // // Allocate private data // ConsoleIn = AllocateZeroPool (sizeof (KEYBOARD_CONSOLE_IN_DEV)); if (ConsoleIn == NULL) { Status = EFI_OUT_OF_RESOURCES; StatusCode = EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_CONTROLLER_ERROR; goto ErrorExit; } // // Setup the device instance // ConsoleIn->Signature = KEYBOARD_CONSOLE_IN_DEV_SIGNATURE; ConsoleIn->Handle = Controller; (ConsoleIn->ConIn).Reset = KeyboardEfiReset; (ConsoleIn->ConIn).ReadKeyStroke = KeyboardReadKeyStroke; ConsoleIn->DataRegisterAddress = KEYBOARD_8042_DATA_REGISTER; ConsoleIn->StatusRegisterAddress = KEYBOARD_8042_STATUS_REGISTER; ConsoleIn->CommandRegisterAddress = KEYBOARD_8042_COMMAND_REGISTER; ConsoleIn->IsaIo = IsaIo; ConsoleIn->DevicePath = ParentDevicePath; ConsoleIn->ConInEx.Reset = KeyboardEfiResetEx; ConsoleIn->ConInEx.ReadKeyStrokeEx = KeyboardReadKeyStrokeEx; ConsoleIn->ConInEx.SetState = KeyboardSetState; ConsoleIn->ConInEx.RegisterKeyNotify = KeyboardRegisterKeyNotify; ConsoleIn->ConInEx.UnregisterKeyNotify = KeyboardUnregisterKeyNotify; InitializeListHead (&ConsoleIn->NotifyList); // // Fix for random hangs in System waiting for the Key if no KBC is present in BIOS. // When KBC decode (IO port 0x60/0x64 decode) is not enabled, // KeyboardRead will read back as 0xFF and return status is EFI_SUCCESS. // So instead we read status register to detect after read if KBC decode is enabled. // // // Return code is ignored on purpose. // if (!PcdGetBool (PcdFastPS2Detection)) { KeyboardRead (ConsoleIn, &Data); if ((KeyReadStatusRegister (ConsoleIn) & (KBC_PARE | KBC_TIM)) == (KBC_PARE | KBC_TIM)) { // // If nobody decodes KBC I/O port, it will read back as 0xFF. // Check the Time-Out and Parity bit to see if it has an active KBC in system // Status = EFI_DEVICE_ERROR; StatusCode = EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_NOT_DETECTED; goto ErrorExit; } } // // Setup the WaitForKey event // Status = gBS->CreateEvent ( EVT_NOTIFY_WAIT, TPL_NOTIFY, KeyboardWaitForKey, ConsoleIn, &((ConsoleIn->ConIn).WaitForKey) ); if (EFI_ERROR (Status)) { Status = EFI_OUT_OF_RESOURCES; StatusCode = EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_CONTROLLER_ERROR; goto ErrorExit; } // // Setup the WaitForKeyEx event // Status = gBS->CreateEvent ( EVT_NOTIFY_WAIT, TPL_NOTIFY, KeyboardWaitForKeyEx, ConsoleIn, &(ConsoleIn->ConInEx.WaitForKeyEx) ); if (EFI_ERROR (Status)) { Status = EFI_OUT_OF_RESOURCES; StatusCode = EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_CONTROLLER_ERROR; goto ErrorExit; } // Setup a periodic timer, used for reading keystrokes at a fixed interval // Status = gBS->CreateEvent ( EVT_TIMER | EVT_NOTIFY_SIGNAL, TPL_NOTIFY, KeyboardTimerHandler, ConsoleIn, &ConsoleIn->TimerEvent ); if (EFI_ERROR (Status)) { Status = EFI_OUT_OF_RESOURCES; StatusCode = EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_CONTROLLER_ERROR; goto ErrorExit; } Status = gBS->SetTimer ( ConsoleIn->TimerEvent, TimerPeriodic, KEYBOARD_TIMER_INTERVAL ); if (EFI_ERROR (Status)) { Status = EFI_OUT_OF_RESOURCES; StatusCode = EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_CONTROLLER_ERROR; goto ErrorExit; } REPORT_STATUS_CODE_WITH_DEVICE_PATH ( EFI_PROGRESS_CODE, EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_PRESENCE_DETECT, ParentDevicePath ); // // Reset the keyboard device // Status = ConsoleIn->ConInEx.Reset (&ConsoleIn->ConInEx, FeaturePcdGet (PcdPs2KbdExtendedVerification)); if (EFI_ERROR (Status)) { Status = EFI_DEVICE_ERROR; StatusCode = EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_NOT_DETECTED; goto ErrorExit; } REPORT_STATUS_CODE_WITH_DEVICE_PATH ( EFI_PROGRESS_CODE, EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_DETECTED, ParentDevicePath ); ConsoleIn->ControllerNameTable = NULL; AddUnicodeString2 ( "eng", gPs2KeyboardComponentName.SupportedLanguages, &ConsoleIn->ControllerNameTable, L"PS/2 Keyboard Device", TRUE ); AddUnicodeString2 ( "en", gPs2KeyboardComponentName2.SupportedLanguages, &ConsoleIn->ControllerNameTable, L"PS/2 Keyboard Device", FALSE ); // // Install protocol interfaces for the keyboard device. // Status = gBS->InstallMultipleProtocolInterfaces ( &Controller, &gEfiSimpleTextInProtocolGuid, &ConsoleIn->ConIn, &gEfiSimpleTextInputExProtocolGuid, &ConsoleIn->ConInEx, NULL ); if (EFI_ERROR (Status)) { StatusCode = EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_CONTROLLER_ERROR; goto ErrorExit; } return Status; ErrorExit: // // Report error code // if (StatusCode != 0) { REPORT_STATUS_CODE_WITH_DEVICE_PATH ( EFI_ERROR_CODE | EFI_ERROR_MINOR, StatusCode, ParentDevicePath ); } if ((ConsoleIn != NULL) && (ConsoleIn->ConIn.WaitForKey != NULL)) { gBS->CloseEvent (ConsoleIn->ConIn.WaitForKey); } if ((ConsoleIn != NULL) && (ConsoleIn->TimerEvent != NULL)) { gBS->CloseEvent (ConsoleIn->TimerEvent); } if ((ConsoleIn != NULL) && (ConsoleIn->ConInEx.WaitForKeyEx != NULL)) { gBS->CloseEvent (ConsoleIn->ConInEx.WaitForKeyEx); } KbdFreeNotifyList (&ConsoleIn->NotifyList); if ((ConsoleIn != NULL) && (ConsoleIn->ControllerNameTable != NULL)) { FreeUnicodeStringTable (ConsoleIn->ControllerNameTable); } // // Since there will be no timer handler for keyboard input any more, // exhaust input data just in case there is still keyboard data left // if (ConsoleIn != NULL) { Status1 = EFI_SUCCESS; while (!EFI_ERROR (Status1) && (Status != EFI_DEVICE_ERROR)) { Status1 = KeyboardRead (ConsoleIn, &Data);; } } if (ConsoleIn != NULL) { gBS->FreePool (ConsoleIn); } gBS->CloseProtocol ( Controller, &gEfiDevicePathProtocolGuid, This->DriverBindingHandle, Controller ); gBS->CloseProtocol ( Controller, &gEfiIsaIoProtocolGuid, This->DriverBindingHandle, Controller ); return Status; }
/** Stop the USB keyboard device handled by this driver. @param This The USB keyboard driver binding protocol. @param Controller The controller to release. @param NumberOfChildren The number of handles in ChildHandleBuffer. @param ChildHandleBuffer The array of child handle. @retval EFI_SUCCESS The device was stopped. @retval EFI_UNSUPPORTED Simple Text In Protocol or Simple Text In Ex Protocol is not installed on Controller. @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error. @retval Others Fail to uninstall protocols attached on the device. **/ EFI_STATUS EFIAPI USBKeyboardDriverBindingStop ( IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE Controller, IN UINTN NumberOfChildren, IN EFI_HANDLE *ChildHandleBuffer ) { EFI_STATUS Status; EFI_SIMPLE_TEXT_INPUT_PROTOCOL *SimpleInput; USB_KB_DEV *UsbKeyboardDevice; Status = gBS->OpenProtocol ( Controller, &gEfiSimpleTextInProtocolGuid, (VOID **) &SimpleInput, This->DriverBindingHandle, Controller, EFI_OPEN_PROTOCOL_GET_PROTOCOL ); if (EFI_ERROR (Status)) { return EFI_UNSUPPORTED; } Status = gBS->OpenProtocol ( Controller, &gEfiSimpleTextInputExProtocolGuid, NULL, This->DriverBindingHandle, Controller, EFI_OPEN_PROTOCOL_TEST_PROTOCOL ); if (EFI_ERROR (Status)) { return EFI_UNSUPPORTED; } UsbKeyboardDevice = USB_KB_DEV_FROM_THIS (SimpleInput); // // The key data input from this device will be disabled. // REPORT_STATUS_CODE_WITH_DEVICE_PATH ( EFI_PROGRESS_CODE, (EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_DISABLE), UsbKeyboardDevice->DevicePath ); // // Delete the Asynchronous Interrupt Transfer from this device // UsbKeyboardDevice->UsbIo->UsbAsyncInterruptTransfer ( UsbKeyboardDevice->UsbIo, UsbKeyboardDevice->IntEndpointDescriptor.EndpointAddress, FALSE, UsbKeyboardDevice->IntEndpointDescriptor.Interval, 0, NULL, NULL ); gBS->CloseProtocol ( Controller, &gEfiUsbIoProtocolGuid, This->DriverBindingHandle, Controller ); Status = gBS->UninstallMultipleProtocolInterfaces ( Controller, &gEfiSimpleTextInProtocolGuid, &UsbKeyboardDevice->SimpleInput, &gEfiSimpleTextInputExProtocolGuid, &UsbKeyboardDevice->SimpleInputEx, NULL ); // // Free all resources. // gBS->CloseEvent (UsbKeyboardDevice->TimerEvent); gBS->CloseEvent (UsbKeyboardDevice->RepeatTimer); gBS->CloseEvent (UsbKeyboardDevice->DelayedRecoveryEvent); gBS->CloseEvent (UsbKeyboardDevice->SimpleInput.WaitForKey); gBS->CloseEvent (UsbKeyboardDevice->SimpleInputEx.WaitForKeyEx); KbdFreeNotifyList (&UsbKeyboardDevice->NotifyList); ReleaseKeyboardLayoutResources (UsbKeyboardDevice); gBS->CloseEvent (UsbKeyboardDevice->KeyboardLayoutEvent); if (UsbKeyboardDevice->ControllerNameTable != NULL) { FreeUnicodeStringTable (UsbKeyboardDevice->ControllerNameTable); } DestroyQueue (&UsbKeyboardDevice->UsbKeyQueue); DestroyQueue (&UsbKeyboardDevice->EfiKeyQueue); FreePool (UsbKeyboardDevice); return Status; }
/** Start function of Driver binding protocol which start this driver on Controller by detecting all disks and installing BlockIo protocol on them. @param This Protocol instance pointer. @param Controller Handle of device to bind driver to. @param RemainingDevicePath produce all possible children. @retval EFI_SUCCESS This driver is added to ControllerHandle. @retval EFI_ALREADY_STARTED This driver is already running on ControllerHandle. @retval other This driver does not support this device. **/ EFI_STATUS EFIAPI IDEBusDriverBindingStart ( IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE Controller, IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath ) { EFI_STATUS Status; EFI_STATUS SavedStatus; EFI_PCI_IO_PROTOCOL *PciIo; EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath; EFI_DEV_PATH *Node; UINT8 IdeChannel; UINT8 BeginningIdeChannel; UINT8 EndIdeChannel; UINT8 IdeDevice; UINT8 BeginningIdeDevice; UINT8 EndIdeDevice; IDE_BLK_IO_DEV *IdeBlkIoDevice[IdeMaxChannel][IdeMaxDevice]; IDE_BLK_IO_DEV *IdeBlkIoDevicePtr; IDE_REGISTERS_BASE_ADDR IdeRegsBaseAddr[IdeMaxChannel]; ATA_TRANSFER_MODE TransferMode; ATA_DRIVE_PARMS DriveParameters; EFI_DEV_PATH NewNode; UINT8 ConfigurationOptions; UINT16 CommandBlockBaseAddr; UINT16 ControlBlockBaseAddr; UINTN DataSize; IDE_BUS_DRIVER_PRIVATE_DATA *IdeBusDriverPrivateData; UINT64 Supports; // // Local variables declaration for IdeControllerInit support // EFI_IDE_CONTROLLER_INIT_PROTOCOL *IdeInit; BOOLEAN EnumAll; BOOLEAN ChannelEnabled; UINT8 MaxDevices; EFI_IDENTIFY_DATA IdentifyData; EFI_ATA_COLLECTIVE_MODE *SupportedModes; IdeBusDriverPrivateData = NULL; SupportedModes = NULL; // // Perform IdeBus initialization // Status = gBS->OpenProtocol ( Controller, &gEfiDevicePathProtocolGuid, (VOID **) &ParentDevicePath, This->DriverBindingHandle, Controller, EFI_OPEN_PROTOCOL_BY_DRIVER ); if ((EFI_ERROR (Status)) && (Status != EFI_ALREADY_STARTED)) { return Status; } // // Now open the IDE_CONTROLLER_INIT protocol. Step7.1 // Status = gBS->OpenProtocol ( Controller, &gEfiIdeControllerInitProtocolGuid, (VOID **) &IdeInit, This->DriverBindingHandle, Controller, EFI_OPEN_PROTOCOL_BY_DRIVER ); // // The following OpenProtocol function with _GET_PROTOCOL attribute and // will not return EFI_ALREADY_STARTED, so save it for now // SavedStatus = Status; if ((EFI_ERROR (Status)) && (Status != EFI_ALREADY_STARTED)) { DEBUG ((EFI_D_ERROR, "Open Init, Status=%x", Status)); // // open protocol is not SUCCESS or not ALREADY_STARTED, error exit // goto ErrorExit; } // // Save Enumall. Step7.2 // EnumAll = IdeInit->EnumAll; // // Consume PCI I/O protocol. Note that the OpenProtocol with _GET_PROTOCOL // attribute will not return EFI_ALREADY_STARTED // Status = gBS->OpenProtocol ( Controller, &gEfiPciIoProtocolGuid, (VOID **) &PciIo, This->DriverBindingHandle, Controller, EFI_OPEN_PROTOCOL_GET_PROTOCOL ); if (EFI_ERROR (Status)) { DEBUG ((EFI_D_ERROR, "Open PciIo, Status=%x", Status)); goto ErrorExit; } // // We must check EFI_ALREADY_STARTED because many ATAPI devices are removable // if (SavedStatus != EFI_ALREADY_STARTED) { IdeBusDriverPrivateData = AllocatePool (sizeof (IDE_BUS_DRIVER_PRIVATE_DATA)); if (IdeBusDriverPrivateData == NULL) { Status = EFI_OUT_OF_RESOURCES; goto ErrorExit; } ZeroMem (IdeBusDriverPrivateData, sizeof (IDE_BUS_DRIVER_PRIVATE_DATA)); Status = gBS->InstallMultipleProtocolInterfaces ( &Controller, &gEfiCallerIdGuid, IdeBusDriverPrivateData, NULL ); if (EFI_ERROR (Status)) { goto ErrorExit; } } else { Status = gBS->OpenProtocol ( Controller, &gEfiCallerIdGuid, (VOID **) &IdeBusDriverPrivateData, This->DriverBindingHandle, Controller, EFI_OPEN_PROTOCOL_GET_PROTOCOL ); if (EFI_ERROR (Status)) { IdeBusDriverPrivateData = NULL; goto ErrorExit; } } Status = PciIo->Attributes ( PciIo, EfiPciIoAttributeOperationSupported, 0, &Supports ); if (!EFI_ERROR (Status)) { Supports &= (UINT64)EFI_PCI_DEVICE_ENABLE; Status = PciIo->Attributes ( PciIo, EfiPciIoAttributeOperationEnable, Supports, NULL ); } if (EFI_ERROR (Status)) { goto ErrorExit; } // // Read the environment variable that contains the IDEBus Driver's // Config options that were set by the Driver Configuration Protocol // DataSize = sizeof (ConfigurationOptions); Status = gRT->GetVariable ( (CHAR16 *) L"Configuration", &gEfiCallerIdGuid, NULL, &DataSize, &ConfigurationOptions ); if (EFI_ERROR (Status)) { ConfigurationOptions = 0x0f; } if (EnumAll || RemainingDevicePath == NULL) { // // If IdeInit->EnumAll is TRUE or RemainingDevicePath is NULL, // must enumerate all IDE devices anyway // BeginningIdeChannel = IdePrimary; EndIdeChannel = IdeSecondary; BeginningIdeDevice = IdeMaster; EndIdeDevice = IdeSlave; } else if (!IsDevicePathEnd (RemainingDevicePath)) { // // If RemainingDevicePath isn't the End of Device Path Node, // only scan the specified device by RemainingDevicePath // Node = (EFI_DEV_PATH *) RemainingDevicePath; BeginningIdeChannel = Node->Atapi.PrimarySecondary; EndIdeChannel = BeginningIdeChannel; BeginningIdeDevice = Node->Atapi.SlaveMaster; EndIdeDevice = BeginningIdeDevice; if (BeginningIdeChannel >= IdeMaxChannel || EndIdeChannel >= IdeMaxChannel) { Status = EFI_INVALID_PARAMETER; goto ErrorExit; } if (BeginningIdeDevice >= IdeMaxDevice|| EndIdeDevice >= IdeMaxDevice) { Status = EFI_INVALID_PARAMETER; goto ErrorExit; } } else { // // If RemainingDevicePath is the End of Device Path Node, // skip enumerate any device and return EFI_SUCESSS // BeginningIdeChannel = IdeMaxChannel; EndIdeChannel = IdeMaxChannel - 1; BeginningIdeDevice = IdeMaxDevice; EndIdeDevice = IdeMaxDevice - 1; } // // Obtain IDE IO port registers' base addresses // Status = GetIdeRegistersBaseAddr (PciIo, IdeRegsBaseAddr); if (EFI_ERROR (Status)) { goto ErrorExit; } // // Report status code: begin IdeBus initialization // REPORT_STATUS_CODE_WITH_DEVICE_PATH ( EFI_PROGRESS_CODE, (EFI_IO_BUS_ATA_ATAPI | EFI_IOB_PC_RESET), ParentDevicePath ); // // Strictly follow the enumeration based on IDE_CONTROLLER_INIT protocol // for (IdeChannel = BeginningIdeChannel; IdeChannel <= EndIdeChannel; IdeChannel++) { IdeInit->NotifyPhase (IdeInit, EfiIdeBeforeChannelEnumeration, IdeChannel); // // now obtain channel information fron IdeControllerInit protocol. Step9 // Status = IdeInit->GetChannelInfo ( IdeInit, IdeChannel, &ChannelEnabled, &MaxDevices ); if (EFI_ERROR (Status)) { DEBUG ((EFI_D_ERROR, "[GetChannel, Status=%x]", Status)); continue; } if (!ChannelEnabled) { continue; } EndIdeDevice = (UINT8) MIN ((MaxDevices - 1), EndIdeDevice); ASSERT (EndIdeDevice < IdeMaxDevice); // // Now inform the IDE Controller Init Module. Sept10 // IdeInit->NotifyPhase (IdeInit, EfiIdeBeforeChannelReset, IdeChannel); // // No reset channel function implemented. Sept11 // IdeInit->NotifyPhase (IdeInit, EfiIdeAfterChannelReset, IdeChannel); // // Step13 // IdeInit->NotifyPhase ( IdeInit, EfiIdeBusBeforeDevicePresenceDetection, IdeChannel ); // // Prepare to detect IDE device of this channel // InitializeIDEChannelData (); // // -- 1st inner loop --- Master/Slave ------------ Step14 // for (IdeDevice = BeginningIdeDevice; IdeDevice <= EndIdeDevice; IdeDevice++) { // // Check whether the configuration options allow this device // if ((ConfigurationOptions & (1 << (IdeChannel * 2 + IdeDevice))) == 0) { continue; } // // The device has been scanned in another Start(), No need to scan it again // for perf optimization. // if (IdeBusDriverPrivateData->HaveScannedDevice[IdeChannel * 2 + IdeDevice]) { continue; } // // create child handle for the detected device. // IdeBlkIoDevice[IdeChannel][IdeDevice] = AllocatePool (sizeof (IDE_BLK_IO_DEV)); if (IdeBlkIoDevice[IdeChannel][IdeDevice] == NULL) { continue; } IdeBlkIoDevicePtr = IdeBlkIoDevice[IdeChannel][IdeDevice]; ZeroMem (IdeBlkIoDevicePtr, sizeof (IDE_BLK_IO_DEV)); IdeBlkIoDevicePtr->Signature = IDE_BLK_IO_DEV_SIGNATURE; IdeBlkIoDevicePtr->Channel = (EFI_IDE_CHANNEL) IdeChannel; IdeBlkIoDevicePtr->Device = (EFI_IDE_DEVICE) IdeDevice; // // initialize Block IO interface's Media pointer // IdeBlkIoDevicePtr->BlkIo.Media = &IdeBlkIoDevicePtr->BlkMedia; // // Initialize IDE IO port addresses, including Command Block registers // and Control Block registers // IdeBlkIoDevicePtr->IoPort = AllocatePool (sizeof (IDE_BASE_REGISTERS)); if (IdeBlkIoDevicePtr->IoPort == NULL) { continue; } ZeroMem (IdeBlkIoDevicePtr->IoPort, sizeof (IDE_BASE_REGISTERS)); CommandBlockBaseAddr = IdeRegsBaseAddr[IdeChannel].CommandBlockBaseAddr; ControlBlockBaseAddr = IdeRegsBaseAddr[IdeChannel].ControlBlockBaseAddr; IdeBlkIoDevicePtr->IoPort->Data = CommandBlockBaseAddr; (*(UINT16 *) &IdeBlkIoDevicePtr->IoPort->Reg1) = (UINT16) (CommandBlockBaseAddr + 0x01); IdeBlkIoDevicePtr->IoPort->SectorCount = (UINT16) (CommandBlockBaseAddr + 0x02); IdeBlkIoDevicePtr->IoPort->SectorNumber = (UINT16) (CommandBlockBaseAddr + 0x03); IdeBlkIoDevicePtr->IoPort->CylinderLsb = (UINT16) (CommandBlockBaseAddr + 0x04); IdeBlkIoDevicePtr->IoPort->CylinderMsb = (UINT16) (CommandBlockBaseAddr + 0x05); IdeBlkIoDevicePtr->IoPort->Head = (UINT16) (CommandBlockBaseAddr + 0x06); (*(UINT16 *) &IdeBlkIoDevicePtr->IoPort->Reg) = (UINT16) (CommandBlockBaseAddr + 0x07); (*(UINT16 *) &IdeBlkIoDevicePtr->IoPort->Alt) = ControlBlockBaseAddr; IdeBlkIoDevicePtr->IoPort->DriveAddress = (UINT16) (ControlBlockBaseAddr + 0x01); IdeBlkIoDevicePtr->IoPort->MasterSlave = (UINT16) ((IdeDevice == IdeMaster) ? 1 : 0); IdeBlkIoDevicePtr->PciIo = PciIo; IdeBlkIoDevicePtr->IdeBusDriverPrivateData = IdeBusDriverPrivateData; IdeBlkIoDevicePtr->IoPort->BusMasterBaseAddr = IdeRegsBaseAddr[IdeChannel].BusMasterBaseAddr; // // Report Status code: is about to detect IDE drive // REPORT_STATUS_CODE_EX ( EFI_PROGRESS_CODE, (EFI_IO_BUS_ATA_ATAPI | EFI_P_PC_PRESENCE_DETECT), 0, &gEfiCallerIdGuid, NULL, NULL, 0 ); // // Discover device, now! // PERF_START (NULL, "DiscoverIdeDevice", "IDE", 0); Status = DiscoverIdeDevice (IdeBlkIoDevicePtr); PERF_END (NULL, "DiscoverIdeDevice", "IDE", 0); IdeBusDriverPrivateData->HaveScannedDevice[IdeChannel * 2 + IdeDevice] = TRUE; IdeBusDriverPrivateData->DeviceProcessed[IdeChannel * 2 + IdeDevice] = FALSE; if (!EFI_ERROR (Status)) { // // Set Device Path // ZeroMem (&NewNode, sizeof (NewNode)); NewNode.DevPath.Type = MESSAGING_DEVICE_PATH; NewNode.DevPath.SubType = MSG_ATAPI_DP; SetDevicePathNodeLength (&NewNode.DevPath, sizeof (ATAPI_DEVICE_PATH)); NewNode.Atapi.PrimarySecondary = (UINT8) IdeBlkIoDevicePtr->Channel; NewNode.Atapi.SlaveMaster = (UINT8) IdeBlkIoDevicePtr->Device; NewNode.Atapi.Lun = IdeBlkIoDevicePtr->Lun; IdeBlkIoDevicePtr->DevicePath = AppendDevicePathNode ( ParentDevicePath, &NewNode.DevPath ); if (IdeBlkIoDevicePtr->DevicePath == NULL) { ReleaseIdeResources (IdeBlkIoDevicePtr); continue; } // // Submit identify data to IDE controller init driver // CopyMem (&IdentifyData, IdeBlkIoDevicePtr->IdData, sizeof (IdentifyData)); IdeBusDriverPrivateData->DeviceFound[IdeChannel * 2 + IdeDevice] = TRUE; IdeInit->SubmitData (IdeInit, IdeChannel, IdeDevice, &IdentifyData); } else { // // Device detection failed // IdeBusDriverPrivateData->DeviceFound[IdeChannel * 2 + IdeDevice] = FALSE; IdeInit->SubmitData (IdeInit, IdeChannel, IdeDevice, NULL); ReleaseIdeResources (IdeBlkIoDevicePtr); IdeBlkIoDevicePtr = NULL; } // // end of 1st inner loop --- // } // // end of 1st outer loop ========= // } // // = 2nd outer loop == Primary/Secondary ================= // for (IdeChannel = BeginningIdeChannel; IdeChannel <= EndIdeChannel; IdeChannel++) { // // -- 2nd inner loop --- Master/Slave -------- // for (IdeDevice = BeginningIdeDevice; IdeDevice <= EndIdeDevice; IdeDevice++) { ASSERT (IdeChannel * 2 + IdeDevice < MAX_IDE_DEVICE); if (IdeBusDriverPrivateData->DeviceProcessed[IdeChannel * 2 + IdeDevice]) { continue; } if (!IdeBusDriverPrivateData->DeviceFound[IdeChannel * 2 + IdeDevice]) { continue; } Status = IdeInit->CalculateMode ( IdeInit, IdeChannel, IdeDevice, &SupportedModes ); if (EFI_ERROR (Status)) { DEBUG ((EFI_D_ERROR, "[bStStp20S=%x]", Status)); continue; } ASSERT (IdeChannel < IdeMaxChannel && IdeDevice < IdeMaxDevice); IdeBlkIoDevicePtr = IdeBlkIoDevice[IdeChannel][IdeDevice]; // // Set best supported PIO mode on this IDE device // if (SupportedModes->PioMode.Mode <= AtaPioMode2) { TransferMode.ModeCategory = ATA_MODE_CATEGORY_DEFAULT_PIO; } else { TransferMode.ModeCategory = ATA_MODE_CATEGORY_FLOW_PIO; } TransferMode.ModeNumber = (UINT8) (SupportedModes->PioMode.Mode); if (SupportedModes->ExtModeCount == 0){ Status = SetDeviceTransferMode (IdeBlkIoDevicePtr, &TransferMode); if (EFI_ERROR (Status)) { IdeBusDriverPrivateData->DeviceFound[IdeChannel * 2 + IdeDevice] = FALSE; ReleaseIdeResources (IdeBlkIoDevicePtr); IdeBlkIoDevicePtr = NULL; continue; } } // // Set supported DMA mode on this IDE device. Note that UDMA & MDMA cann't // be set together. Only one DMA mode can be set to a device. If setting // DMA mode operation fails, we can continue moving on because we only use // PIO mode at boot time. DMA modes are used by certain kind of OS booting // if (SupportedModes->UdmaMode.Valid) { TransferMode.ModeCategory = ATA_MODE_CATEGORY_UDMA; TransferMode.ModeNumber = (UINT8) (SupportedModes->UdmaMode.Mode); Status = SetDeviceTransferMode (IdeBlkIoDevicePtr, &TransferMode); if (EFI_ERROR (Status)) { IdeBusDriverPrivateData->DeviceFound[IdeChannel * 2 + IdeDevice] = FALSE; ReleaseIdeResources (IdeBlkIoDevicePtr); IdeBlkIoDevicePtr = NULL; continue; } // // Record Udma Mode // IdeBlkIoDevicePtr->UdmaMode.Valid = TRUE; IdeBlkIoDevicePtr->UdmaMode.Mode = SupportedModes->UdmaMode.Mode; EnableInterrupt (IdeBlkIoDevicePtr); } else if (SupportedModes->MultiWordDmaMode.Valid) { TransferMode.ModeCategory = ATA_MODE_CATEGORY_MDMA; TransferMode.ModeNumber = (UINT8) SupportedModes->MultiWordDmaMode.Mode; Status = SetDeviceTransferMode (IdeBlkIoDevicePtr, &TransferMode); if (EFI_ERROR (Status)) { IdeBusDriverPrivateData->DeviceFound[IdeChannel * 2 + IdeDevice] = FALSE; ReleaseIdeResources (IdeBlkIoDevicePtr); IdeBlkIoDevicePtr = NULL; continue; } EnableInterrupt (IdeBlkIoDevicePtr); } // // Init driver parameters // DriveParameters.Sector = (UINT8) ((ATA5_IDENTIFY_DATA *) IdeBlkIoDevicePtr->IdData)->sectors_per_track; DriveParameters.Heads = (UINT8) (((ATA5_IDENTIFY_DATA *) IdeBlkIoDevicePtr->IdData)->heads - 1); DriveParameters.MultipleSector = (UINT8) IdeBlkIoDevicePtr->IdData->AtaData.multi_sector_cmd_max_sct_cnt; // // Set Parameters for the device: // 1) Init // 2) Establish the block count for READ/WRITE MULTIPLE (EXT) command // if ((IdeBlkIoDevicePtr->Type == IdeHardDisk) || (IdeBlkIoDevicePtr->Type == Ide48bitAddressingHardDisk)) { Status = SetDriveParameters (IdeBlkIoDevicePtr, &DriveParameters); } // // Record PIO mode used in private data // IdeBlkIoDevicePtr->PioMode = (ATA_PIO_MODE) SupportedModes->PioMode.Mode; // // Set IDE controller Timing Blocks in the PCI Configuration Space // IdeInit->SetTiming (IdeInit, IdeChannel, IdeDevice, SupportedModes); // // Add Component Name for the IDE/ATAPI device that was discovered. // IdeBlkIoDevicePtr->ControllerNameTable = NULL; ADD_IDE_ATAPI_NAME (IdeBlkIoDevicePtr); Status = gBS->InstallMultipleProtocolInterfaces ( &IdeBlkIoDevicePtr->Handle, &gEfiDevicePathProtocolGuid, IdeBlkIoDevicePtr->DevicePath, &gEfiBlockIoProtocolGuid, &IdeBlkIoDevicePtr->BlkIo, &gEfiDiskInfoProtocolGuid, &IdeBlkIoDevicePtr->DiskInfo, NULL ); if (EFI_ERROR (Status)) { ReleaseIdeResources (IdeBlkIoDevicePtr); } gBS->OpenProtocol ( Controller, &gEfiPciIoProtocolGuid, (VOID **) &PciIo, This->DriverBindingHandle, IdeBlkIoDevicePtr->Handle, EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER ); IdeBusDriverPrivateData->DeviceProcessed[IdeChannel * 2 + IdeDevice] = TRUE; // // Report status code: device eanbled! // REPORT_STATUS_CODE_WITH_DEVICE_PATH ( EFI_PROGRESS_CODE, (EFI_IO_BUS_ATA_ATAPI | EFI_P_PC_ENABLE), IdeBlkIoDevicePtr->DevicePath ); // // Create event to clear pending IDE interrupt // Status = gBS->CreateEventEx ( EVT_NOTIFY_SIGNAL, TPL_NOTIFY, ClearInterrupt, IdeBlkIoDevicePtr, &gEfiEventExitBootServicesGuid, &IdeBlkIoDevicePtr->ExitBootServiceEvent ); // // end of 2nd inner loop ---- // } // // end of 2nd outer loop ========== // } // // All configurations done! Notify IdeController to do post initialization // work such as saving IDE controller PCI settings for S3 resume // IdeInit->NotifyPhase (IdeInit, EfiIdeBusPhaseMaximum, 0); if (SupportedModes != NULL) { FreePool (SupportedModes); } PERF_START (NULL, "Finish IDE detection", "IDE", 1); PERF_END (NULL, "Finish IDE detection", "IDE", 0); return EFI_SUCCESS; ErrorExit: // // Report error code: controller error // REPORT_STATUS_CODE_WITH_DEVICE_PATH ( EFI_ERROR_CODE | EFI_ERROR_MINOR, (EFI_IO_BUS_ATA_ATAPI | EFI_IOB_EC_CONTROLLER_ERROR), ParentDevicePath ); gBS->CloseProtocol ( Controller, &gEfiIdeControllerInitProtocolGuid, This->DriverBindingHandle, Controller ); gBS->UninstallMultipleProtocolInterfaces ( Controller, &gEfiCallerIdGuid, IdeBusDriverPrivateData, NULL ); if (IdeBusDriverPrivateData != NULL) { gBS->FreePool (IdeBusDriverPrivateData); } if (SupportedModes != NULL) { gBS->FreePool (SupportedModes); } gBS->CloseProtocol ( Controller, &gEfiPciIoProtocolGuid, This->DriverBindingHandle, Controller ); gBS->CloseProtocol ( Controller, &gEfiDevicePathProtocolGuid, This->DriverBindingHandle, Controller ); return Status; }
/** Stop this driver on ControllerHandle. Support stoping any child handles created by this driver. @param This Protocol instance pointer. @param ControllerHandle Handle of device to stop driver on @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number of children is zero stop the entire bus driver. @param ChildHandleBuffer List of Child Handles to Stop. @retval EFI_SUCCESS This driver is removed ControllerHandle @retval other This driver was not removed from this device **/ EFI_STATUS EFIAPI PS2MouseAbsolutePointerDriverStop ( IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE Controller, IN UINTN NumberOfChildren, IN EFI_HANDLE *ChildHandleBuffer ) { EFI_STATUS Status; EFI_ABSOLUTE_POINTER_PROTOCOL *AbsolutePointerProtocol; PS2_MOUSE_ABSOLUTE_POINTER_DEV *MouseAbsolutePointerDev; UINT8 Data; Status = gBS->OpenProtocol ( Controller, &gEfiAbsolutePointerProtocolGuid, (VOID **) &AbsolutePointerProtocol, This->DriverBindingHandle, Controller, EFI_OPEN_PROTOCOL_GET_PROTOCOL ); if (EFI_ERROR (Status)) { return EFI_SUCCESS; } MouseAbsolutePointerDev = PS2_MOUSE_ABSOLUTE_POINTER_DEV_FROM_THIS (AbsolutePointerProtocol); // // Report that the keyboard is being disabled // REPORT_STATUS_CODE_WITH_DEVICE_PATH ( EFI_PROGRESS_CODE, EFI_PERIPHERAL_MOUSE | EFI_P_PC_DISABLE, MouseAbsolutePointerDev->DevicePath ); Status = gBS->UninstallProtocolInterface ( Controller, &gEfiAbsolutePointerProtocolGuid, &MouseAbsolutePointerDev->AbsolutePointerProtocol ); if (EFI_ERROR (Status)) { return Status; } // // Cancel mouse data polling timer, close timer event // gBS->SetTimer (MouseAbsolutePointerDev->TimerEvent, TimerCancel, 0); gBS->CloseEvent (MouseAbsolutePointerDev->TimerEvent); // // Since there will be no timer handler for mouse input any more, // exhaust input data just in case there is still mouse data left // Status = EFI_SUCCESS; while (!EFI_ERROR (Status)) { Status = In8042Data (MouseAbsolutePointerDev->IsaIo, &Data); } gBS->CloseEvent (MouseAbsolutePointerDev->AbsolutePointerProtocol.WaitForInput); FreeUnicodeStringTable (MouseAbsolutePointerDev->ControllerNameTable); FreePool (MouseAbsolutePointerDev); gBS->CloseProtocol ( Controller, &gEfiDevicePathProtocolGuid, This->DriverBindingHandle, Controller ); gBS->CloseProtocol ( Controller, &gEfiIsaIoProtocolGuid, This->DriverBindingHandle, Controller ); return EFI_SUCCESS; }
/** Start this driver on ControllerHandle. This service is called by the EFI boot service ConnectController(). In order to make drivers as small as possible, there are a few calling restrictions for this service. ConnectController() must follow these calling restrictions. If any other agent wishes to call Start() it must also follow these calling restrictions. @param This Protocol instance pointer. @param ControllerHandle Handle of device to bind driver to @param RemainingDevicePath Optional parameter use to pick a specific child device to start. @retval EFI_SUCCESS This driver is added to ControllerHandle @retval EFI_ALREADY_STARTED This driver is already running on ControllerHandle @retval other This driver does not support this device **/ EFI_STATUS EFIAPI SCSIBusDriverBindingStart ( IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE Controller, IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath ) { UINT64 Lun; UINT8 *TargetId; BOOLEAN ScanOtherPuns; BOOLEAN FromFirstTarget; BOOLEAN ExtScsiSupport; EFI_STATUS Status; EFI_STATUS DevicePathStatus; EFI_STATUS PassThruStatus; SCSI_BUS_DEVICE *ScsiBusDev; SCSI_TARGET_ID ScsiTargetId; EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath; EFI_SCSI_PASS_THRU_PROTOCOL *ScsiInterface; EFI_EXT_SCSI_PASS_THRU_PROTOCOL *ExtScsiInterface; EFI_SCSI_BUS_PROTOCOL *BusIdentify; TargetId = NULL; ScanOtherPuns = TRUE; FromFirstTarget = FALSE; ExtScsiSupport = FALSE; PassThruStatus = EFI_SUCCESS; TargetId = &ScsiTargetId.ScsiId.ExtScsi[0]; SetMem (TargetId, TARGET_MAX_BYTES, 0xFF); DevicePathStatus = gBS->OpenProtocol ( Controller, &gEfiDevicePathProtocolGuid, (VOID **) &ParentDevicePath, This->DriverBindingHandle, Controller, EFI_OPEN_PROTOCOL_BY_DRIVER ); if (EFI_ERROR (DevicePathStatus) && (DevicePathStatus != EFI_ALREADY_STARTED)) { return DevicePathStatus; } // // Report Status Code to indicate SCSI bus starts // REPORT_STATUS_CODE_WITH_DEVICE_PATH ( EFI_PROGRESS_CODE, (EFI_IO_BUS_SCSI | EFI_IOB_PC_INIT), ParentDevicePath ); // // To keep backward compatibility, UEFI ExtPassThru Protocol is supported as well as // EFI PassThru Protocol. From priority perspective, ExtPassThru Protocol is firstly // tried to open on host controller handle. If fails, then PassThru Protocol is tried instead. // Status = gBS->OpenProtocol ( Controller, &gEfiExtScsiPassThruProtocolGuid, (VOID **) &ExtScsiInterface, This->DriverBindingHandle, Controller, EFI_OPEN_PROTOCOL_BY_DRIVER ); // // Fail to open UEFI ExtendPassThru Protocol, then try to open EFI PassThru Protocol instead. // if (EFI_ERROR(Status) && (Status != EFI_ALREADY_STARTED)) { Status = gBS->OpenProtocol ( Controller, &gEfiScsiPassThruProtocolGuid, (VOID **) &ScsiInterface, This->DriverBindingHandle, Controller, EFI_OPEN_PROTOCOL_BY_DRIVER ); // // Fail to open EFI PassThru Protocol, Close the DevicePathProtocol if it is opened by this time. // if (EFI_ERROR (Status) && (Status != EFI_ALREADY_STARTED)) { if (!EFI_ERROR(DevicePathStatus)) { gBS->CloseProtocol ( Controller, &gEfiDevicePathProtocolGuid, This->DriverBindingHandle, Controller ); } return Status; } } else { // // Succeed to open ExtPassThru Protocol, and meanwhile open PassThru Protocol // with BY_DRIVER if it is also present on the handle. The intent is to prevent // another SCSI Bus Driver to work on the same host handle. // ExtScsiSupport = TRUE; PassThruStatus = gBS->OpenProtocol ( Controller, &gEfiScsiPassThruProtocolGuid, (VOID **) &ScsiInterface, This->DriverBindingHandle, Controller, EFI_OPEN_PROTOCOL_BY_DRIVER ); } if (Status != EFI_ALREADY_STARTED) { // // Go through here means either ExtPassThru or PassThru Protocol is successfully opened // on this handle for this time. Then construct Host controller private data. // ScsiBusDev = NULL; ScsiBusDev = AllocateZeroPool(sizeof(SCSI_BUS_DEVICE)); if (ScsiBusDev == NULL) { Status = EFI_OUT_OF_RESOURCES; goto ErrorExit; } ScsiBusDev->Signature = SCSI_BUS_DEVICE_SIGNATURE; ScsiBusDev->ExtScsiSupport = ExtScsiSupport; ScsiBusDev->DevicePath = ParentDevicePath; if (ScsiBusDev->ExtScsiSupport) { ScsiBusDev->ExtScsiInterface = ExtScsiInterface; } else { ScsiBusDev->ScsiInterface = ScsiInterface; } // // Install EFI_SCSI_BUS_PROTOCOL to the controller handle, So ScsiBusDev could be // retrieved on this controller handle. With ScsiBusDev, we can know which PassThru // Protocol is present on the handle, UEFI ExtPassThru Protocol or EFI PassThru Protocol. // Status = gBS->InstallProtocolInterface ( &Controller, &gEfiCallerIdGuid, EFI_NATIVE_INTERFACE, &ScsiBusDev->BusIdentify ); if (EFI_ERROR (Status)) { goto ErrorExit; } } else { // // Go through here means Start() is re-invoked again, nothing special is required to do except // picking up Host controller private information. // Status = gBS->OpenProtocol ( Controller, &gEfiCallerIdGuid, (VOID **) &BusIdentify, This->DriverBindingHandle, Controller, EFI_OPEN_PROTOCOL_GET_PROTOCOL ); if (EFI_ERROR (Status)) { return Status; } ScsiBusDev = SCSI_BUS_CONTROLLER_DEVICE_FROM_THIS (BusIdentify); } // // Report Status Code to indicate detecting devices on bus // REPORT_STATUS_CODE_WITH_DEVICE_PATH ( EFI_PROGRESS_CODE, (EFI_IO_BUS_SCSI | EFI_IOB_PC_DETECT), ParentDevicePath ); Lun = 0; if (RemainingDevicePath == NULL) { // // If RemainingDevicePath is NULL, // must enumerate all SCSI devices anyway // FromFirstTarget = TRUE; } else if (!IsDevicePathEnd (RemainingDevicePath)) { // // If RemainingDevicePath isn't the End of Device Path Node, // only scan the specified device by RemainingDevicePath // if (ScsiBusDev->ExtScsiSupport) { Status = ScsiBusDev->ExtScsiInterface->GetTargetLun (ScsiBusDev->ExtScsiInterface, RemainingDevicePath, &TargetId, &Lun); } else { Status = ScsiBusDev->ScsiInterface->GetTargetLun (ScsiBusDev->ScsiInterface, RemainingDevicePath, &ScsiTargetId.ScsiId.Scsi, &Lun); } if (EFI_ERROR (Status)) { return Status; } } else { // // If RemainingDevicePath is the End of Device Path Node, // skip enumerate any device and return EFI_SUCESSS // ScanOtherPuns = FALSE; } while(ScanOtherPuns) { if (FromFirstTarget) { // // Remaining Device Path is NULL, scan all the possible Puns in the // SCSI Channel. // if (ScsiBusDev->ExtScsiSupport) { Status = ScsiBusDev->ExtScsiInterface->GetNextTargetLun (ScsiBusDev->ExtScsiInterface, &TargetId, &Lun); } else { Status = ScsiBusDev->ScsiInterface->GetNextDevice (ScsiBusDev->ScsiInterface, &ScsiTargetId.ScsiId.Scsi, &Lun); } if (EFI_ERROR (Status)) { // // no legal Pun and Lun found any more // break; } } else { ScanOtherPuns = FALSE; } // // Avoid creating handle for the host adapter. // if (ScsiBusDev->ExtScsiSupport) { if ((ScsiTargetId.ScsiId.Scsi) == ScsiBusDev->ExtScsiInterface->Mode->AdapterId) { continue; } } else { if ((ScsiTargetId.ScsiId.Scsi) == ScsiBusDev->ScsiInterface->Mode->AdapterId) { continue; } } // // Scan for the scsi device, if it attaches to the scsi bus, // then create handle and install scsi i/o protocol. // Status = ScsiScanCreateDevice (This, Controller, &ScsiTargetId, Lun, ScsiBusDev); } return EFI_SUCCESS; ErrorExit: if (ScsiBusDev != NULL) { FreePool (ScsiBusDev); } if (ExtScsiSupport) { gBS->CloseProtocol ( Controller, &gEfiExtScsiPassThruProtocolGuid, This->DriverBindingHandle, Controller ); if (!EFI_ERROR (PassThruStatus)) { gBS->CloseProtocol ( Controller, &gEfiScsiPassThruProtocolGuid, This->DriverBindingHandle, Controller ); } } else { gBS->CloseProtocol ( Controller, &gEfiScsiPassThruProtocolGuid, This->DriverBindingHandle, Controller ); } return Status; }
/** Scan SCSI Bus to discover the device, and attach ScsiIoProtocol to it. @param This Protocol instance pointer @param Controller Controller handle @param TargetId Tartget to be scanned @param Lun The Lun of the SCSI device on the SCSI channel. @param ScsiBusDev The pointer of SCSI_BUS_DEVICE @retval EFI_SUCCESS Successfully to discover the device and attach ScsiIoProtocol to it. @retval EFI_OUT_OF_RESOURCES Fail to discover the device. **/ EFI_STATUS EFIAPI ScsiScanCreateDevice ( IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE Controller, IN SCSI_TARGET_ID *TargetId, IN UINT64 Lun, IN OUT SCSI_BUS_DEVICE *ScsiBusDev ) { EFI_STATUS Status; SCSI_IO_DEV *ScsiIoDevice; EFI_DEVICE_PATH_PROTOCOL *ScsiDevicePath; EFI_DEVICE_PATH_PROTOCOL *DevicePath; EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath; EFI_HANDLE DeviceHandle; DevicePath = NULL; RemainingDevicePath = NULL; ScsiDevicePath = NULL; ScsiIoDevice = NULL; // // Build Device Path // if (ScsiBusDev->ExtScsiSupport){ Status = ScsiBusDev->ExtScsiInterface->BuildDevicePath ( ScsiBusDev->ExtScsiInterface, &TargetId->ScsiId.ExtScsi[0], Lun, &ScsiDevicePath ); } else { Status = ScsiBusDev->ScsiInterface->BuildDevicePath ( ScsiBusDev->ScsiInterface, TargetId->ScsiId.Scsi, Lun, &ScsiDevicePath ); } if (EFI_ERROR(Status)) { return Status; } DevicePath = AppendDevicePathNode ( ScsiBusDev->DevicePath, ScsiDevicePath ); if (DevicePath == NULL) { Status = EFI_OUT_OF_RESOURCES; goto ErrorExit; } DeviceHandle = NULL; RemainingDevicePath = DevicePath; Status = gBS->LocateDevicePath (&gEfiDevicePathProtocolGuid, &RemainingDevicePath, &DeviceHandle); if (!EFI_ERROR (Status) && (DeviceHandle != NULL) && IsDevicePathEnd(RemainingDevicePath)) { // // The device has been started, directly return to fast boot. // Status = EFI_ALREADY_STARTED; goto ErrorExit; } ScsiIoDevice = AllocateZeroPool (sizeof (SCSI_IO_DEV)); if (ScsiIoDevice == NULL) { Status = EFI_OUT_OF_RESOURCES; goto ErrorExit; } ScsiIoDevice->Signature = SCSI_IO_DEV_SIGNATURE; ScsiIoDevice->ScsiBusDeviceData = ScsiBusDev; CopyMem(&ScsiIoDevice->Pun, TargetId, TARGET_MAX_BYTES); ScsiIoDevice->Lun = Lun; if (ScsiBusDev->ExtScsiSupport) { ScsiIoDevice->ExtScsiPassThru = ScsiBusDev->ExtScsiInterface; ScsiIoDevice->ExtScsiSupport = TRUE; ScsiIoDevice->ScsiIo.IoAlign = ScsiIoDevice->ExtScsiPassThru->Mode->IoAlign; } else { ScsiIoDevice->ScsiPassThru = ScsiBusDev->ScsiInterface; ScsiIoDevice->ExtScsiSupport = FALSE; ScsiIoDevice->ScsiIo.IoAlign = ScsiIoDevice->ScsiPassThru->Mode->IoAlign; } ScsiIoDevice->ScsiIo.GetDeviceType = ScsiGetDeviceType; ScsiIoDevice->ScsiIo.GetDeviceLocation = ScsiGetDeviceLocation; ScsiIoDevice->ScsiIo.ResetBus = ScsiResetBus; ScsiIoDevice->ScsiIo.ResetDevice = ScsiResetDevice; ScsiIoDevice->ScsiIo.ExecuteScsiCommand = ScsiExecuteSCSICommand; // // Report Status Code here since the new SCSI device will be discovered // REPORT_STATUS_CODE_WITH_DEVICE_PATH ( EFI_PROGRESS_CODE, (EFI_IO_BUS_SCSI | EFI_IOB_PC_ENABLE), ScsiBusDev->DevicePath ); if (!DiscoverScsiDevice (ScsiIoDevice)) { Status = EFI_OUT_OF_RESOURCES; goto ErrorExit; } ScsiIoDevice->DevicePath = DevicePath; Status = gBS->InstallMultipleProtocolInterfaces ( &ScsiIoDevice->Handle, &gEfiDevicePathProtocolGuid, ScsiIoDevice->DevicePath, &gEfiScsiIoProtocolGuid, &ScsiIoDevice->ScsiIo, NULL ); if (EFI_ERROR (Status)) { goto ErrorExit; } else { if (ScsiBusDev->ExtScsiSupport) { gBS->OpenProtocol ( Controller, &gEfiExtScsiPassThruProtocolGuid, (VOID **) &(ScsiBusDev->ExtScsiInterface), This->DriverBindingHandle, ScsiIoDevice->Handle, EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER ); } else { gBS->OpenProtocol ( Controller, &gEfiScsiPassThruProtocolGuid, (VOID **) &(ScsiBusDev->ScsiInterface), This->DriverBindingHandle, ScsiIoDevice->Handle, EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER ); } } return EFI_SUCCESS; ErrorExit: // // The memory space for ScsiDevicePath is allocated in // ScsiPassThru->BuildDevicePath() function; It is no longer used // after AppendDevicePathNode,so free the memory it occupies. // FreePool (ScsiDevicePath); if (DevicePath != NULL) { FreePool (DevicePath); } if (ScsiIoDevice != NULL) { FreePool (ScsiIoDevice); } return Status; }
/** Deregister an IDE device and free resources @param This Protocol instance pointer. @param Controller Ide device handle @param Handle Handle of device to deregister driver on @retval EFI_SUCCESS Deregiter a specific IDE device successfully **/ EFI_STATUS DeRegisterIdeDevice ( IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE Controller, IN EFI_HANDLE Handle ) { EFI_STATUS Status; EFI_BLOCK_IO_PROTOCOL *BlkIo; IDE_BLK_IO_DEV *IdeBlkIoDevice; EFI_PCI_IO_PROTOCOL *PciIo; UINTN Index; Status = gBS->OpenProtocol ( Handle, &gEfiBlockIoProtocolGuid, (VOID **) &BlkIo, This->DriverBindingHandle, Controller, EFI_OPEN_PROTOCOL_GET_PROTOCOL ); if (EFI_ERROR (Status)) { return Status; } IdeBlkIoDevice = IDE_BLOCK_IO_DEV_FROM_THIS (BlkIo); // // Report Status code: Device disabled // REPORT_STATUS_CODE_WITH_DEVICE_PATH ( EFI_PROGRESS_CODE, (EFI_IO_BUS_ATA_ATAPI | EFI_P_PC_DISABLE), IdeBlkIoDevice->DevicePath ); // // Close the child handle // Status = gBS->CloseProtocol ( Controller, &gEfiPciIoProtocolGuid, This->DriverBindingHandle, Handle ); Status = gBS->UninstallMultipleProtocolInterfaces ( Handle, &gEfiDevicePathProtocolGuid, IdeBlkIoDevice->DevicePath, &gEfiBlockIoProtocolGuid, &IdeBlkIoDevice->BlkIo, &gEfiDiskInfoProtocolGuid, &IdeBlkIoDevice->DiskInfo, NULL ); if (EFI_ERROR (Status)) { gBS->OpenProtocol ( Controller, &gEfiPciIoProtocolGuid, (VOID **) &PciIo, This->DriverBindingHandle, Handle, EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER ); return Status; } // // Release allocated resources // Index = IdeBlkIoDevice->Channel * 2 + IdeBlkIoDevice->Device; if (Index < MAX_IDE_DEVICE) { IdeBlkIoDevice->IdeBusDriverPrivateData->HaveScannedDevice[Index] = FALSE; } ReleaseIdeResources (IdeBlkIoDevice); return EFI_SUCCESS; }
/** Reset the Floppy Logic Drive. @param FdcDev FDC_BLK_IO_DEV * : A pointer to the FDC_BLK_IO_DEV @retval EFI_SUCCESS: The Floppy Logic Drive is reset @retval EFI_DEVICE_ERROR: The Floppy Logic Drive is not functioning correctly and can not be reset **/ EFI_STATUS FddReset ( IN FDC_BLK_IO_DEV *FdcDev ) { UINT8 Data; UINT8 StatusRegister0; UINT8 PresentCylinderNumber; UINTN Index; // // Report reset progress code // REPORT_STATUS_CODE_WITH_DEVICE_PATH ( EFI_PROGRESS_CODE, EFI_PERIPHERAL_REMOVABLE_MEDIA | EFI_P_PC_RESET, FdcDev->DevicePath ); // // Reset specified Floppy Logic Drive according to FdcDev -> Disk // Set Digital Output Register(DOR) to do reset work // bit0 & bit1 of DOR : Drive Select // bit2 : Reset bit // bit3 : DMA and Int bit // Reset : a "0" written to bit2 resets the FDC, this reset will remain // active until // a "1" is written to this bit. // Reset step 1: // use bit0 & bit1 to select the logic drive // write "0" to bit2 // Data = 0x0; Data = (UINT8) (Data | (SELECT_DRV & FdcDev->Disk)); FdcWritePort (FdcDev, FDC_REGISTER_DOR, Data); // // wait some time,at least 120us // MicroSecondDelay (500); // // Reset step 2: // write "1" to bit2 // write "1" to bit3 : enable DMA // Data |= 0x0C; FdcWritePort (FdcDev, FDC_REGISTER_DOR, Data); // // Experience value // MicroSecondDelay (2000); // // wait specified floppy logic drive is not busy // if (EFI_ERROR (FddWaitForBSYClear (FdcDev, 1))) { return EFI_DEVICE_ERROR; } // // Set the Transfer Data Rate // FdcWritePort (FdcDev, FDC_REGISTER_CCR, 0x0); // // Experience value // MicroSecondDelay (100); // // Issue Sense interrupt command for each drive (total 4 drives) // for (Index = 0; Index < 4; Index++) { if (EFI_ERROR (SenseIntStatus (FdcDev, &StatusRegister0, &PresentCylinderNumber))) { return EFI_DEVICE_ERROR; } } // // issue Specify command // if (EFI_ERROR (Specify (FdcDev))) { return EFI_DEVICE_ERROR; } return EFI_SUCCESS; }
/** Start this driver on ControllerHandle by opening a Sio protocol, creating PS2_MOUSE_DEV device and install gEfiSimplePointerProtocolGuid finally. @param This Protocol instance pointer. @param ControllerHandle Handle of device to bind driver to @param RemainingDevicePath Optional parameter use to pick a specific child device to start. @retval EFI_SUCCESS This driver is added to ControllerHandle @retval EFI_ALREADY_STARTED This driver is already running on ControllerHandle @retval other This driver does not support this device **/ EFI_STATUS EFIAPI PS2MouseDriverStart ( IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE Controller, IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath ) { EFI_STATUS Status; EFI_STATUS EmptyStatus; EFI_SIO_PROTOCOL *Sio; PS2_MOUSE_DEV *MouseDev; UINT8 Data; EFI_TPL OldTpl; EFI_STATUS_CODE_VALUE StatusCode; EFI_DEVICE_PATH_PROTOCOL *DevicePath; StatusCode = 0; // // Open the device path protocol // Status = gBS->OpenProtocol ( Controller, &gEfiDevicePathProtocolGuid, (VOID **) &DevicePath, This->DriverBindingHandle, Controller, EFI_OPEN_PROTOCOL_GET_PROTOCOL ); if (EFI_ERROR (Status)) { return Status; } // // Report that the keyboard is being enabled // REPORT_STATUS_CODE_WITH_DEVICE_PATH ( EFI_PROGRESS_CODE, EFI_PERIPHERAL_MOUSE | EFI_P_PC_ENABLE, DevicePath ); // // Get the ISA I/O Protocol on Controller's handle // Status = gBS->OpenProtocol ( Controller, &gEfiSioProtocolGuid, (VOID **) &Sio, This->DriverBindingHandle, Controller, EFI_OPEN_PROTOCOL_BY_DRIVER ); if (EFI_ERROR (Status)) { return Status; } // // Raise TPL to avoid keyboard operation impact // OldTpl = gBS->RaiseTPL (TPL_NOTIFY); // // Allocate private data // MouseDev = AllocateZeroPool (sizeof (PS2_MOUSE_DEV)); if (MouseDev == NULL) { Status = EFI_OUT_OF_RESOURCES; goto ErrorExit; } // // Setup the device instance // MouseDev->Signature = PS2_MOUSE_DEV_SIGNATURE; MouseDev->Handle = Controller; MouseDev->SampleRate = SampleRate20; MouseDev->Resolution = MouseResolution4; MouseDev->Scaling = Scaling1; MouseDev->DataPackageSize = 3; MouseDev->DevicePath = DevicePath; // // Resolution = 4 counts/mm // MouseDev->Mode.ResolutionX = 4; MouseDev->Mode.ResolutionY = 4; MouseDev->Mode.LeftButton = TRUE; MouseDev->Mode.RightButton = TRUE; MouseDev->SimplePointerProtocol.Reset = MouseReset; MouseDev->SimplePointerProtocol.GetState = MouseGetState; MouseDev->SimplePointerProtocol.Mode = &(MouseDev->Mode); // // Initialize keyboard controller if necessary // REPORT_STATUS_CODE_WITH_DEVICE_PATH ( EFI_PROGRESS_CODE, EFI_PERIPHERAL_MOUSE | EFI_P_MOUSE_PC_SELF_TEST, DevicePath ); Data = IoRead8 (KBC_CMD_STS_PORT); // // Fix for random hangs in System waiting for the Key if no KBC is present in BIOS. // if ((Data & (KBC_PARE | KBC_TIM)) == (KBC_PARE | KBC_TIM)) { // // If nobody decodes KBC I/O port, it will read back as 0xFF. // Check the Time-Out and Parity bit to see if it has an active KBC in system // Status = EFI_DEVICE_ERROR; StatusCode = EFI_PERIPHERAL_MOUSE | EFI_P_EC_NOT_DETECTED; goto ErrorExit; } if ((Data & KBC_SYSF) != KBC_SYSF) { Status = KbcSelfTest (); if (EFI_ERROR (Status)) { StatusCode = EFI_PERIPHERAL_MOUSE | EFI_P_EC_CONTROLLER_ERROR; goto ErrorExit; } } KbcEnableAux (); REPORT_STATUS_CODE_WITH_DEVICE_PATH ( EFI_PROGRESS_CODE, EFI_PERIPHERAL_MOUSE | EFI_P_PC_PRESENCE_DETECT, DevicePath ); // // Reset the mouse // Status = MouseDev->SimplePointerProtocol.Reset ( &MouseDev->SimplePointerProtocol, FeaturePcdGet (PcdPs2MouseExtendedVerification) ); if (EFI_ERROR (Status)) { // // mouse not connected // Status = EFI_SUCCESS; StatusCode = EFI_PERIPHERAL_MOUSE | EFI_P_EC_NOT_DETECTED; goto ErrorExit; } REPORT_STATUS_CODE_WITH_DEVICE_PATH ( EFI_PROGRESS_CODE, EFI_PERIPHERAL_MOUSE | EFI_P_PC_DETECTED, DevicePath ); // // Setup the WaitForKey event // Status = gBS->CreateEvent ( EVT_NOTIFY_WAIT, TPL_NOTIFY, MouseWaitForInput, MouseDev, &((MouseDev->SimplePointerProtocol).WaitForInput) ); if (EFI_ERROR (Status)) { Status = EFI_OUT_OF_RESOURCES; goto ErrorExit; } // // Setup a periodic timer, used to poll mouse state // Status = gBS->CreateEvent ( EVT_TIMER | EVT_NOTIFY_SIGNAL, TPL_NOTIFY, PollMouse, MouseDev, &MouseDev->TimerEvent ); if (EFI_ERROR (Status)) { Status = EFI_OUT_OF_RESOURCES; goto ErrorExit; } // // Start timer to poll mouse (100 samples per second) // Status = gBS->SetTimer (MouseDev->TimerEvent, TimerPeriodic, 100000); if (EFI_ERROR (Status)) { Status = EFI_OUT_OF_RESOURCES; goto ErrorExit; } MouseDev->ControllerNameTable = NULL; AddUnicodeString2 ( "eng", gPs2MouseComponentName.SupportedLanguages, &MouseDev->ControllerNameTable, L"PS/2 Mouse Device", TRUE ); AddUnicodeString2 ( "en", gPs2MouseComponentName2.SupportedLanguages, &MouseDev->ControllerNameTable, L"PS/2 Mouse Device", FALSE ); // // Install protocol interfaces for the mouse device. // Status = gBS->InstallMultipleProtocolInterfaces ( &Controller, &gEfiSimplePointerProtocolGuid, &MouseDev->SimplePointerProtocol, NULL ); if (EFI_ERROR (Status)) { goto ErrorExit; } gBS->RestoreTPL (OldTpl); return Status; ErrorExit: if (Status != EFI_DEVICE_ERROR) { KbcDisableAux (); } if (StatusCode != 0) { REPORT_STATUS_CODE_WITH_DEVICE_PATH ( EFI_ERROR_CODE | EFI_ERROR_MINOR, StatusCode, DevicePath ); } if ((MouseDev != NULL) && (MouseDev->SimplePointerProtocol.WaitForInput != NULL)) { gBS->CloseEvent (MouseDev->SimplePointerProtocol.WaitForInput); } if ((MouseDev != NULL) && (MouseDev->TimerEvent != NULL)) { gBS->CloseEvent (MouseDev->TimerEvent); } if ((MouseDev != NULL) && (MouseDev->ControllerNameTable != NULL)) { FreeUnicodeStringTable (MouseDev->ControllerNameTable); } if (Status != EFI_DEVICE_ERROR) { // // Since there will be no timer handler for mouse input any more, // exhaust input data just in case there is still mouse data left // EmptyStatus = EFI_SUCCESS; while (!EFI_ERROR (EmptyStatus)) { EmptyStatus = In8042Data (&Data); } } if (MouseDev != NULL) { FreePool (MouseDev); } gBS->CloseProtocol ( Controller, &gEfiDevicePathProtocolGuid, This->DriverBindingHandle, Controller ); gBS->CloseProtocol ( Controller, &gEfiSioProtocolGuid, This->DriverBindingHandle, Controller ); gBS->RestoreTPL (OldTpl); return Status; }
/** Starts the keyboard device with this driver. This function produces Simple Text Input Protocol and Simple Text Input Ex Protocol, initializes the keyboard device, and submit Asynchronous Interrupt Transfer to manage this keyboard device. @param This The USB keyboard driver binding instance. @param Controller Handle of device to bind driver to. @param RemainingDevicePath Optional parameter use to pick a specific child device to start. @retval EFI_SUCCESS The controller is controlled by the usb keyboard driver. @retval EFI_UNSUPPORTED No interrupt endpoint can be found. @retval Other This controller cannot be started. **/ EFI_STATUS EFIAPI USBKeyboardDriverBindingStart ( IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE Controller, IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath ) { EFI_STATUS Status; EFI_USB_IO_PROTOCOL *UsbIo; USB_KB_DEV *UsbKeyboardDevice; UINT8 EndpointNumber; EFI_USB_ENDPOINT_DESCRIPTOR EndpointDescriptor; UINT8 Index; UINT8 EndpointAddr; UINT8 PollingInterval; UINT8 PacketSize; BOOLEAN Found; EFI_TPL OldTpl; OldTpl = gBS->RaiseTPL (TPL_CALLBACK); // // Open USB I/O Protocol // Status = gBS->OpenProtocol ( Controller, &gEfiUsbIoProtocolGuid, (VOID **) &UsbIo, This->DriverBindingHandle, Controller, EFI_OPEN_PROTOCOL_BY_DRIVER ); if (EFI_ERROR (Status)) { goto ErrorExit1; } UsbKeyboardDevice = AllocateZeroPool (sizeof (USB_KB_DEV)); ASSERT (UsbKeyboardDevice != NULL); // // Get the Device Path Protocol on Controller's handle // Status = gBS->OpenProtocol ( Controller, &gEfiDevicePathProtocolGuid, (VOID **) &UsbKeyboardDevice->DevicePath, This->DriverBindingHandle, Controller, EFI_OPEN_PROTOCOL_GET_PROTOCOL ); if (EFI_ERROR (Status)) { goto ErrorExit; } // // Report that the USB keyboard is being enabled // REPORT_STATUS_CODE_WITH_DEVICE_PATH ( EFI_PROGRESS_CODE, (EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_ENABLE), UsbKeyboardDevice->DevicePath ); // // This is pretty close to keyboard detection, so log progress // REPORT_STATUS_CODE_WITH_DEVICE_PATH ( EFI_PROGRESS_CODE, (EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_PRESENCE_DETECT), UsbKeyboardDevice->DevicePath ); UsbKeyboardDevice->UsbIo = UsbIo; // // Get interface & endpoint descriptor // UsbIo->UsbGetInterfaceDescriptor ( UsbIo, &UsbKeyboardDevice->InterfaceDescriptor ); EndpointNumber = UsbKeyboardDevice->InterfaceDescriptor.NumEndpoints; // // Traverse endpoints to find interrupt endpoint // Found = FALSE; for (Index = 0; Index < EndpointNumber; Index++) { UsbIo->UsbGetEndpointDescriptor ( UsbIo, Index, &EndpointDescriptor ); if ((EndpointDescriptor.Attributes & (BIT0 | BIT1)) == USB_ENDPOINT_INTERRUPT) { // // We only care interrupt endpoint here // CopyMem(&UsbKeyboardDevice->IntEndpointDescriptor, &EndpointDescriptor, sizeof(EndpointDescriptor)); Found = TRUE; break; } } if (!Found) { // // No interrupt endpoint found, then return unsupported. // Status = EFI_UNSUPPORTED; goto ErrorExit; } UsbKeyboardDevice->Signature = USB_KB_DEV_SIGNATURE; UsbKeyboardDevice->SimpleInput.Reset = USBKeyboardReset; UsbKeyboardDevice->SimpleInput.ReadKeyStroke = USBKeyboardReadKeyStroke; UsbKeyboardDevice->SimpleInputEx.Reset = USBKeyboardResetEx; UsbKeyboardDevice->SimpleInputEx.ReadKeyStrokeEx = USBKeyboardReadKeyStrokeEx; UsbKeyboardDevice->SimpleInputEx.SetState = USBKeyboardSetState; UsbKeyboardDevice->SimpleInputEx.RegisterKeyNotify = USBKeyboardRegisterKeyNotify; UsbKeyboardDevice->SimpleInputEx.UnregisterKeyNotify = USBKeyboardUnregisterKeyNotify; InitializeListHead (&UsbKeyboardDevice->NotifyList); Status = gBS->CreateEvent ( EVT_TIMER | EVT_NOTIFY_SIGNAL, TPL_NOTIFY, USBKeyboardTimerHandler, UsbKeyboardDevice, &UsbKeyboardDevice->TimerEvent ); if (!EFI_ERROR (Status)) { Status = gBS->SetTimer (UsbKeyboardDevice->TimerEvent, TimerPeriodic, KEYBOARD_TIMER_INTERVAL); } if (EFI_ERROR (Status)) { goto ErrorExit; } Status = gBS->CreateEvent ( EVT_NOTIFY_WAIT, TPL_NOTIFY, USBKeyboardWaitForKey, UsbKeyboardDevice, &(UsbKeyboardDevice->SimpleInputEx.WaitForKeyEx) ); if (EFI_ERROR (Status)) { goto ErrorExit; } Status = gBS->CreateEvent ( EVT_NOTIFY_WAIT, TPL_NOTIFY, USBKeyboardWaitForKey, UsbKeyboardDevice, &(UsbKeyboardDevice->SimpleInput.WaitForKey) ); if (EFI_ERROR (Status)) { goto ErrorExit; } // // Install Simple Text Input Protocol and Simple Text Input Ex Protocol // for the USB keyboard device. // USB keyboard is a hot plug device, and expected to work immediately // when plugging into system, other conventional console devices could // distinguish it by its device path. // Status = gBS->InstallMultipleProtocolInterfaces ( &Controller, &gEfiSimpleTextInProtocolGuid, &UsbKeyboardDevice->SimpleInput, &gEfiSimpleTextInputExProtocolGuid, &UsbKeyboardDevice->SimpleInputEx, NULL ); if (EFI_ERROR (Status)) { goto ErrorExit; } UsbKeyboardDevice->ControllerHandle = Controller; Status = InitKeyboardLayout (UsbKeyboardDevice); if (EFI_ERROR (Status)) { gBS->UninstallMultipleProtocolInterfaces ( Controller, &gEfiSimpleTextInProtocolGuid, &UsbKeyboardDevice->SimpleInput, &gEfiSimpleTextInputExProtocolGuid, &UsbKeyboardDevice->SimpleInputEx, NULL ); goto ErrorExit; } // // Reset USB Keyboard Device exhaustively. // Status = UsbKeyboardDevice->SimpleInputEx.Reset ( &UsbKeyboardDevice->SimpleInputEx, TRUE ); if (EFI_ERROR (Status)) { gBS->UninstallMultipleProtocolInterfaces ( Controller, &gEfiSimpleTextInProtocolGuid, &UsbKeyboardDevice->SimpleInput, &gEfiSimpleTextInputExProtocolGuid, &UsbKeyboardDevice->SimpleInputEx, NULL ); goto ErrorExit; } // // Submit Asynchronous Interrupt Transfer to manage this device. // EndpointAddr = UsbKeyboardDevice->IntEndpointDescriptor.EndpointAddress; PollingInterval = UsbKeyboardDevice->IntEndpointDescriptor.Interval; PacketSize = (UINT8) (UsbKeyboardDevice->IntEndpointDescriptor.MaxPacketSize); Status = UsbIo->UsbAsyncInterruptTransfer ( UsbIo, EndpointAddr, TRUE, PollingInterval, PacketSize, KeyboardHandler, UsbKeyboardDevice ); if (EFI_ERROR (Status)) { gBS->UninstallMultipleProtocolInterfaces ( Controller, &gEfiSimpleTextInProtocolGuid, &UsbKeyboardDevice->SimpleInput, &gEfiSimpleTextInputExProtocolGuid, &UsbKeyboardDevice->SimpleInputEx, NULL ); goto ErrorExit; } UsbKeyboardDevice->ControllerNameTable = NULL; AddUnicodeString2 ( "eng", gUsbKeyboardComponentName.SupportedLanguages, &UsbKeyboardDevice->ControllerNameTable, L"Generic Usb Keyboard", TRUE ); AddUnicodeString2 ( "en", gUsbKeyboardComponentName2.SupportedLanguages, &UsbKeyboardDevice->ControllerNameTable, L"Generic Usb Keyboard", FALSE ); gBS->RestoreTPL (OldTpl); return EFI_SUCCESS; // // Error handler // ErrorExit: if (UsbKeyboardDevice != NULL) { if (UsbKeyboardDevice->TimerEvent != NULL) { gBS->CloseEvent (UsbKeyboardDevice->TimerEvent); } if (UsbKeyboardDevice->SimpleInput.WaitForKey != NULL) { gBS->CloseEvent (UsbKeyboardDevice->SimpleInput.WaitForKey); } if (UsbKeyboardDevice->SimpleInputEx.WaitForKeyEx != NULL) { gBS->CloseEvent (UsbKeyboardDevice->SimpleInputEx.WaitForKeyEx); } if (UsbKeyboardDevice->KeyboardLayoutEvent != NULL) { ReleaseKeyboardLayoutResources (UsbKeyboardDevice); gBS->CloseEvent (UsbKeyboardDevice->KeyboardLayoutEvent); } FreePool (UsbKeyboardDevice); UsbKeyboardDevice = NULL; } gBS->CloseProtocol ( Controller, &gEfiUsbIoProtocolGuid, This->DriverBindingHandle, Controller ); ErrorExit1: gBS->RestoreTPL (OldTpl); return Status; }
/** Enumerate and configure the new device on the port of this HUB interface. @param HubIf The HUB that has the device connected. @param Port The port index of the hub (started with zero). @retval EFI_SUCCESS The device is enumerated (added or removed). @retval EFI_OUT_OF_RESOURCES Failed to allocate resource for the device. @retval Others Failed to enumerate the device. **/ EFI_STATUS UsbEnumerateNewDev ( IN USB_INTERFACE *HubIf, IN UINT8 Port ) { USB_BUS *Bus; USB_HUB_API *HubApi; USB_DEVICE *Child; USB_DEVICE *Parent; EFI_USB_PORT_STATUS PortState; UINTN Address; UINT8 Config; EFI_STATUS Status; Parent = HubIf->Device; Bus = Parent->Bus; HubApi = HubIf->HubApi; Address = Bus->MaxDevices; DBG("USB_WAIT_PORT_STABLE_STALL\n"); gBS->Stall (USB_WAIT_PORT_STABLE_STALL); //100ms // // Hub resets the device for at least 10 milliseconds. // Host learns device speed. If device is of low/full speed // and the hub is a EHCI root hub, ResetPort will release // the device to its companion UHCI and return an error. // Status = HubApi->ResetPort (HubIf, Port); if (EFI_ERROR (Status)) { // DEBUG ((EFI_D_ERROR, "UsbEnumerateNewDev: failed to reset port %d - %r\n", Port, Status)); return Status; } // DEBUG (( EFI_D_INFO, "UsbEnumerateNewDev: hub port %d is reset\n", Port)); Child = UsbCreateDevice (HubIf, Port); if (Child == NULL) { return EFI_OUT_OF_RESOURCES; } // // OK, now identify the device speed. After reset, hub // fully knows the actual device speed. // DBG("GetPortStatus\n"); Status = HubApi->GetPortStatus (HubIf, Port, &PortState); if (EFI_ERROR (Status)) { // DEBUG ((EFI_D_ERROR, "UsbEnumerateNewDev: failed to get speed of port %d\n", Port)); goto ON_ERROR; } if (!USB_BIT_IS_SET (PortState.PortStatus, USB_PORT_STAT_CONNECTION)) { // DEBUG ((EFI_D_ERROR, "UsbEnumerateNewDev: No device presented at port %d\n", Port)); goto ON_ERROR; } else if (USB_BIT_IS_SET (PortState.PortStatus, USB_PORT_STAT_SUPER_SPEED)){ Child->Speed = EFI_USB_SPEED_SUPER; Child->MaxPacket0 = 512; } else if (USB_BIT_IS_SET (PortState.PortStatus, USB_PORT_STAT_HIGH_SPEED)) { Child->Speed = EFI_USB_SPEED_HIGH; Child->MaxPacket0 = 64; } else if (USB_BIT_IS_SET (PortState.PortStatus, USB_PORT_STAT_LOW_SPEED)) { Child->Speed = EFI_USB_SPEED_LOW; Child->MaxPacket0 = 8; } else { Child->Speed = EFI_USB_SPEED_FULL; Child->MaxPacket0 = 8; } // DEBUG (( EFI_D_INFO, "UsbEnumerateNewDev: device is of %d speed\n", Child->Speed)); DBG("UsbEnumerateNewDev: device is of %d speed\n", Child->Speed); if (((Child->Speed == EFI_USB_SPEED_LOW) || (Child->Speed == EFI_USB_SPEED_FULL)) && (Parent->Speed == EFI_USB_SPEED_HIGH)) { // // If the child is a low or full speed device, it is necessary to // set the transaction translator. Port TT is 1-based. // This is quite simple: // 1. if parent is of high speed, then parent is our translator // 2. otherwise use parent's translator. // Child->Translator.TranslatorHubAddress = Parent->Address; Child->Translator.TranslatorPortNumber = (UINT8) (Port + 1); } else { Child->Translator = Parent->Translator; } // DEBUG (( EFI_D_INFO, "UsbEnumerateNewDev: device uses translator (%d, %d)\n", // Child->Translator.TranslatorHubAddress, // Child->Translator.TranslatorPortNumber)); DBG("UsbEnumerateNewDev: device uses translator (%d, %d)\n", Child->Translator.TranslatorHubAddress, Child->Translator.TranslatorPortNumber); // // After port is reset, hub establishes a signal path between // the device and host (DEFALUT state). Device's registers are // reset, use default address 0 (host enumerates one device at // a time) , and ready to respond to control transfer at EP 0. // // // Host assigns an address to the device. Device completes the // status stage with default address, then switches to new address. // ADDRESS state. Address zero is reserved for root hub. // // ASSERT (Bus->MaxDevices <= 256); for (Address = 1; Address < Bus->MaxDevices; Address++) { if (Bus->Devices[Address] == NULL) { break; } } if (Address >= Bus->MaxDevices) { // DEBUG ((EFI_D_ERROR, "UsbEnumerateNewDev: address pool is full for port %d\n", Port)); DBG("UsbEnumerateNewDev: address pool is full for port %d\n", Port); Status = EFI_ACCESS_DENIED; goto ON_ERROR; } Status = UsbSetAddress (Child, (UINT8)Address); Child->Address = (UINT8)Address; Bus->Devices[Address] = Child; if (EFI_ERROR (Status)) { // DEBUG ((EFI_D_ERROR, "UsbEnumerateNewDev: failed to set device address - %r\n", Status)); goto ON_ERROR; } gBS->Stall (USB_SET_DEVICE_ADDRESS_STALL); // DEBUG ((EFI_D_INFO, "UsbEnumerateNewDev: device is now ADDRESSED at %d\n", Address)); DBG("UsbEnumerateNewDev: device is now ADDRESSED at %d\n", Address); // // Host sends a Get_Descriptor request to learn the max packet // size of default pipe (only part of the device's descriptor). // Status = UsbGetMaxPacketSize0 (Child); if (EFI_ERROR (Status)) { // DEBUG ((EFI_D_ERROR, "UsbEnumerateNewDev: failed to get max packet for EP 0 - %r\n", Status)); DBG("UsbEnumerateNewDev: failed to get max packet for EP 0 - %r\n", Status); goto ON_ERROR; } // DEBUG (( EFI_D_INFO, "UsbEnumerateNewDev: max packet size for EP 0 is %d\n", Child->MaxPacket0)); // // Host learns about the device's abilities by requesting device's // entire descriptions. // Status = UsbBuildDescTable (Child); if (EFI_ERROR (Status)) { // DEBUG ((EFI_D_ERROR, "UsbEnumerateNewDev: failed to build descriptor table - %r\n", Status)); DBG("UsbEnumerateNewDev: failed to build descriptor table - %r\n", Status); goto ON_ERROR; } // // Select a default configuration: UEFI must set the configuration // before the driver can connect to the device. // Config = Child->DevDesc->Configs[0]->Desc.ConfigurationValue; Status = UsbSetConfig (Child, Config); if (EFI_ERROR (Status)) { // DEBUG ((EFI_D_ERROR, "UsbEnumerateNewDev: failed to set configure %d - %r\n", Config, Status)); DBG("UsbEnumerateNewDev: failed to set configure %d - %r\n", Config, Status); goto ON_ERROR; } // DEBUG (( EFI_D_INFO, "UsbEnumerateNewDev: device %d is now in CONFIGED state\n", Address)); DBG("UsbEnumerateNewDev: device %d is now in CONFIGED state\n", Address); // // Host assigns and loads a device driver. // Status = UsbSelectConfig (Child, Config); if (EFI_ERROR (Status)) { // DEBUG ((EFI_D_ERROR, "UsbEnumerateNewDev: failed to create interfaces - %r\n", Status)); DBG("UsbEnumerateNewDev: failed to create interfaces - %r\n", Status); goto ON_ERROR; } // // Report Status Code to indicate USB device has been detected by hotplug // REPORT_STATUS_CODE_WITH_DEVICE_PATH ( EFI_PROGRESS_CODE, (EFI_IO_BUS_USB | EFI_IOB_PC_HOTPLUG), Bus->DevicePath ); return EFI_SUCCESS; ON_ERROR: // // If reach here, it means the enumeration process on a given port is interrupted due to error. // The s/w resources, including the assigned address(Address) and the allocated usb device data // structure(Bus->Devices[Address]), will NOT be freed here. These resources will be freed when // the device is unplugged from the port or DriverBindingStop() is invoked. // // This way is used to co-work with the lower layer EDKII UHCI/EHCI/XHCI host controller driver. // It's mainly because to keep UEFI spec unchanged EDKII XHCI driver have to maintain a state machine // to keep track of the mapping between actual address and request address. If the request address // (Address) is freed here, the Address value will be used by next enumerated device. Then EDKII XHCI // host controller driver will have wrong information, which will cause further transaction error. // // EDKII UHCI/EHCI doesn't get impacted as it's make sense to reserve s/w resource till it gets unplugged. // /* if (Address != Bus->MaxDevices) { Bus->Devices[Address] = NULL; } if (Child != NULL) { UsbFreeDevice (Child); } */ return Status; }
/** Start this driver on ControllerHandle by opening a IsaIo protocol, creating PS2_MOUSE_ABSOLUTE_POINTER_DEV device and install gEfiAbsolutePointerProtocolGuid finally. @param This Protocol instance pointer. @param ControllerHandle Handle of device to bind driver to @param RemainingDevicePath Optional parameter use to pick a specific child device to start. @retval EFI_SUCCESS This driver is added to ControllerHandle @retval EFI_ALREADY_STARTED This driver is already running on ControllerHandle @retval other This driver does not support this device **/ EFI_STATUS EFIAPI PS2MouseAbsolutePointerDriverStart ( IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE Controller, IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath ) { EFI_STATUS Status; EFI_STATUS EmptyStatus; EFI_ISA_IO_PROTOCOL *IsaIo; PS2_MOUSE_ABSOLUTE_POINTER_DEV *MouseAbsolutePointerDev; UINT8 Data; EFI_TPL OldTpl; EFI_STATUS_CODE_VALUE StatusCode; EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath; StatusCode = 0; MouseAbsolutePointerDev = NULL; IsaIo = NULL; // // Open the device path protocol // Status = gBS->OpenProtocol ( Controller, &gEfiDevicePathProtocolGuid, (VOID **) &ParentDevicePath, This->DriverBindingHandle, Controller, EFI_OPEN_PROTOCOL_BY_DRIVER ); if (EFI_ERROR (Status)) { return Status; } // // Report that the keyboard is being enabled // REPORT_STATUS_CODE_WITH_DEVICE_PATH ( EFI_PROGRESS_CODE, EFI_PERIPHERAL_MOUSE | EFI_P_PC_ENABLE, ParentDevicePath ); // // Get the ISA I/O Protocol on Controller's handle // Status = gBS->OpenProtocol ( Controller, &gEfiIsaIoProtocolGuid, (VOID **) &IsaIo, This->DriverBindingHandle, Controller, EFI_OPEN_PROTOCOL_BY_DRIVER ); if (EFI_ERROR (Status)) { gBS->CloseProtocol ( Controller, &gEfiDevicePathProtocolGuid, This->DriverBindingHandle, Controller ); return EFI_INVALID_PARAMETER; } // // Raise TPL to avoid keyboard operation impact // OldTpl = gBS->RaiseTPL (TPL_NOTIFY); // // Allocate private data // MouseAbsolutePointerDev = AllocateZeroPool (sizeof (PS2_MOUSE_ABSOLUTE_POINTER_DEV)); if (MouseAbsolutePointerDev == NULL) { Status = EFI_OUT_OF_RESOURCES; goto ErrorExit; } // // Setup the device instance // MouseAbsolutePointerDev->Signature = PS2_MOUSE_ABSOLUTE_POINTER_DEV_SIGNATURE; MouseAbsolutePointerDev->Handle = Controller; MouseAbsolutePointerDev->SampleRate = SampleRate20; MouseAbsolutePointerDev->Resolution = MouseResolution4; MouseAbsolutePointerDev->Scaling = Scaling1; MouseAbsolutePointerDev->DataPackageSize = 3; MouseAbsolutePointerDev->IsaIo = IsaIo; MouseAbsolutePointerDev->DevicePath = ParentDevicePath; // // Resolution = 4 counts/mm // MouseAbsolutePointerDev->Mode.AbsoluteMaxX = 1024; MouseAbsolutePointerDev->Mode.AbsoluteMinX = 0; MouseAbsolutePointerDev->Mode.AbsoluteMaxY = 798; MouseAbsolutePointerDev->Mode.AbsoluteMinY = 0; MouseAbsolutePointerDev->Mode.AbsoluteMaxZ = 0; MouseAbsolutePointerDev->Mode.AbsoluteMinZ = 0; MouseAbsolutePointerDev->Mode.Attributes = 0x03; MouseAbsolutePointerDev->AbsolutePointerProtocol.Reset = MouseAbsolutePointerReset; MouseAbsolutePointerDev->AbsolutePointerProtocol.GetState = MouseAbsolutePointerGetState; MouseAbsolutePointerDev->AbsolutePointerProtocol.Mode = &(MouseAbsolutePointerDev->Mode); // // Initialize keyboard controller if necessary // REPORT_STATUS_CODE_WITH_DEVICE_PATH ( EFI_PROGRESS_CODE, EFI_PERIPHERAL_MOUSE | EFI_P_MOUSE_PC_SELF_TEST, ParentDevicePath ); IsaIo->Io.Read (IsaIo, EfiIsaIoWidthUint8, KBC_CMD_STS_PORT, 1, &Data); if ((Data & KBC_SYSF) != KBC_SYSF) { Status = KbcSelfTest (IsaIo); if (EFI_ERROR (Status)) { StatusCode = EFI_PERIPHERAL_MOUSE | EFI_P_EC_CONTROLLER_ERROR; goto ErrorExit; } } KbcEnableAux (IsaIo); REPORT_STATUS_CODE_WITH_DEVICE_PATH ( EFI_PROGRESS_CODE, EFI_PERIPHERAL_MOUSE | EFI_P_PC_PRESENCE_DETECT, ParentDevicePath ); // // Reset the mouse // Status = MouseAbsolutePointerDev->AbsolutePointerProtocol.Reset ( &MouseAbsolutePointerDev->AbsolutePointerProtocol, FeaturePcdGet (PcdPs2MouseExtendedVerification) ); if (EFI_ERROR (Status)) { // // mouse not connected // Status = EFI_SUCCESS; StatusCode = EFI_PERIPHERAL_MOUSE | EFI_P_EC_NOT_DETECTED; goto ErrorExit; } REPORT_STATUS_CODE_WITH_DEVICE_PATH ( EFI_PROGRESS_CODE, EFI_PERIPHERAL_MOUSE | EFI_P_PC_DETECTED, ParentDevicePath ); // // Setup the WaitForKey event // Status = gBS->CreateEvent ( EVT_NOTIFY_WAIT, TPL_NOTIFY, MouseAbsolutePointerWaitForInput, MouseAbsolutePointerDev, &((MouseAbsolutePointerDev->AbsolutePointerProtocol).WaitForInput) ); if (EFI_ERROR (Status)) { Status = EFI_OUT_OF_RESOURCES; goto ErrorExit; } // // Setup a periodic timer, used to poll mouse state // Status = gBS->CreateEvent ( EVT_TIMER | EVT_NOTIFY_SIGNAL, TPL_NOTIFY, PollMouseAbsolutePointer, MouseAbsolutePointerDev, &MouseAbsolutePointerDev->TimerEvent ); if (EFI_ERROR (Status)) { Status = EFI_OUT_OF_RESOURCES; goto ErrorExit; } // // Start timer to poll mouse (100 samples per second) // Status = gBS->SetTimer (MouseAbsolutePointerDev->TimerEvent, TimerPeriodic, 100000); if (EFI_ERROR (Status)) { Status = EFI_OUT_OF_RESOURCES; goto ErrorExit; } MouseAbsolutePointerDev->ControllerNameTable = NULL; AddUnicodeString2 ( "eng", gPs2MouseAbsolutePointerComponentName.SupportedLanguages, &MouseAbsolutePointerDev->ControllerNameTable, L"Faked PS/2 Touchpad Device", TRUE ); AddUnicodeString2 ( "en", gPs2MouseAbsolutePointerComponentName2.SupportedLanguages, &MouseAbsolutePointerDev->ControllerNameTable, L"Faked PS/2 Touchpad Device", FALSE ); // // Install protocol interfaces for the mouse device. // Status = gBS->InstallMultipleProtocolInterfaces ( &Controller, &gEfiAbsolutePointerProtocolGuid, &MouseAbsolutePointerDev->AbsolutePointerProtocol, NULL ); if (EFI_ERROR (Status)) { goto ErrorExit; } gBS->RestoreTPL (OldTpl); return Status; ErrorExit: KbcDisableAux (IsaIo); if (StatusCode != 0) { REPORT_STATUS_CODE_WITH_DEVICE_PATH ( EFI_ERROR_CODE | EFI_ERROR_MINOR, StatusCode, ParentDevicePath ); } if ((MouseAbsolutePointerDev != NULL) && (MouseAbsolutePointerDev->AbsolutePointerProtocol.WaitForInput != NULL)) { gBS->CloseEvent (MouseAbsolutePointerDev->AbsolutePointerProtocol.WaitForInput); } if ((MouseAbsolutePointerDev != NULL) && (MouseAbsolutePointerDev->TimerEvent != NULL)) { gBS->CloseEvent (MouseAbsolutePointerDev->TimerEvent); } if ((MouseAbsolutePointerDev != NULL) && (MouseAbsolutePointerDev->ControllerNameTable != NULL)) { FreeUnicodeStringTable (MouseAbsolutePointerDev->ControllerNameTable); } // // Since there will be no timer handler for mouse input any more, // exhaust input data just in case there is still mouse data left // EmptyStatus = EFI_SUCCESS; while (!EFI_ERROR (EmptyStatus)) { EmptyStatus = In8042Data (IsaIo, &Data); } if (MouseAbsolutePointerDev != NULL) { FreePool (MouseAbsolutePointerDev); } gBS->CloseProtocol ( Controller, &gEfiDevicePathProtocolGuid, This->DriverBindingHandle, Controller ); gBS->CloseProtocol ( Controller, &gEfiIsaIoProtocolGuid, This->DriverBindingHandle, Controller ); gBS->RestoreTPL (OldTpl); return Status; }
/** Start this driver on ControllerHandle and enumerate Pci bus and start all device under PCI bus. @param This Protocol instance pointer. @param Controller Handle of device to bind driver to. @param RemainingDevicePath Optional parameter use to pick a specific child device to start. @retval EFI_SUCCESS This driver is added to ControllerHandle. @retval EFI_ALREADY_STARTED This driver is already running on ControllerHandle. @retval other This driver does not support this device. **/ EFI_STATUS EFIAPI PciBusDriverBindingStart ( IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE Controller, IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath ) { EFI_STATUS Status; EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath; EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo; // // Initialize PciRootBridgeIo to suppress incorrect compiler warning. // PciRootBridgeIo = NULL; // // Check RemainingDevicePath validation // if (RemainingDevicePath != NULL) { // // Check if RemainingDevicePath is the End of Device Path Node, // if yes, return EFI_SUCCESS // if (IsDevicePathEnd (RemainingDevicePath)) { return EFI_SUCCESS; } } gBS->LocateProtocol ( &gEfiIncompatiblePciDeviceSupportProtocolGuid, NULL, (VOID **) &gIncompatiblePciDeviceSupport ); // // If PCI Platform protocol is available, get it now. // If the platform implements this, it must be installed before BDS phase // gPciPlatformProtocol = NULL; gBS->LocateProtocol ( &gEfiPciPlatformProtocolGuid, NULL, (VOID **) &gPciPlatformProtocol ); // // If PCI Platform protocol doesn't exist, try to Pci Override Protocol. // if (gPciPlatformProtocol == NULL) { gPciOverrideProtocol = NULL; gBS->LocateProtocol ( &gEfiPciOverrideProtocolGuid, NULL, (VOID **) &gPciOverrideProtocol ); } if (mIoMmuProtocol == NULL) { gBS->LocateProtocol ( &gEdkiiIoMmuProtocolGuid, NULL, (VOID **) &mIoMmuProtocol ); } if (PcdGetBool (PcdPciDisableBusEnumeration)) { gFullEnumeration = FALSE; } else { gFullEnumeration = (BOOLEAN) ((SearchHostBridgeHandle (Controller) ? FALSE : TRUE)); } // // Open Device Path Protocol for PCI root bridge // Status = gBS->OpenProtocol ( Controller, &gEfiDevicePathProtocolGuid, (VOID **) &ParentDevicePath, This->DriverBindingHandle, Controller, EFI_OPEN_PROTOCOL_GET_PROTOCOL ); ASSERT_EFI_ERROR (Status); // // Report Status Code to indicate PCI bus starts // REPORT_STATUS_CODE_WITH_DEVICE_PATH ( EFI_PROGRESS_CODE, (EFI_IO_BUS_PCI | EFI_IOB_PC_INIT), ParentDevicePath ); Status = EFI_SUCCESS; // // Enumerate the entire host bridge // After enumeration, a database that records all the device information will be created // // if (gFullEnumeration) { // // Get the rootbridge Io protocol to find the host bridge handle // Status = gBS->OpenProtocol ( Controller, &gEfiPciRootBridgeIoProtocolGuid, (VOID **) &PciRootBridgeIo, gPciBusDriverBinding.DriverBindingHandle, Controller, EFI_OPEN_PROTOCOL_GET_PROTOCOL ); if (!EFI_ERROR (Status)) { Status = PciEnumerator (Controller, PciRootBridgeIo->ParentHandle); } } else { // // If PCI bus has already done the full enumeration, never do it again // Status = PciEnumeratorLight (Controller); } if (EFI_ERROR (Status)) { return Status; } // // Start all the devices under the entire host bridge. // StartPciDevices (Controller); if (gFullEnumeration) { gFullEnumeration = FALSE; Status = gBS->InstallProtocolInterface ( &PciRootBridgeIo->ParentHandle, &gEfiPciEnumerationCompleteProtocolGuid, EFI_NATIVE_INTERFACE, NULL ); ASSERT_EFI_ERROR (Status); } return Status; }
/** Reset the Mouse and do BAT test for it, if ExtendedVerification isTRUE and there is a mouse device connectted to system. @param This - Pointer of simple pointer Protocol. @param ExtendedVerification - Whether configure mouse parameters. True: do; FALSE: skip. @retval EFI_SUCCESS - The command byte is written successfully. @retval EFI_DEVICE_ERROR - Errors occurred during reseting keyboard. **/ EFI_STATUS EFIAPI MouseAbsolutePointerReset ( IN EFI_ABSOLUTE_POINTER_PROTOCOL *This, IN BOOLEAN ExtendedVerification ) { EFI_STATUS Status; PS2_MOUSE_ABSOLUTE_POINTER_DEV *MouseAbsolutePointerDev; EFI_TPL OldTpl; BOOLEAN KeyboardEnable; UINT8 Data; MouseAbsolutePointerDev = PS2_MOUSE_ABSOLUTE_POINTER_DEV_FROM_THIS (This); // // Report reset progress code // REPORT_STATUS_CODE_WITH_DEVICE_PATH ( EFI_PROGRESS_CODE, EFI_PERIPHERAL_MOUSE | EFI_P_PC_RESET, MouseAbsolutePointerDev->DevicePath ); KeyboardEnable = FALSE; // // Raise TPL to avoid keyboard operation impact // OldTpl = gBS->RaiseTPL (TPL_NOTIFY); ZeroMem (&MouseAbsolutePointerDev->State, sizeof (EFI_ABSOLUTE_POINTER_STATE)); MouseAbsolutePointerDev->StateChanged = FALSE; // // Exhaust input data // Status = EFI_SUCCESS; while (!EFI_ERROR (Status)) { Status = In8042Data (MouseAbsolutePointerDev->IsaIo, &Data); } CheckKbStatus (MouseAbsolutePointerDev->IsaIo, &KeyboardEnable); KbcDisableKb (MouseAbsolutePointerDev->IsaIo); MouseAbsolutePointerDev->IsaIo->Io.Read (MouseAbsolutePointerDev->IsaIo, EfiIsaIoWidthUint8, KBC_CMD_STS_PORT, 1, &Data); // // if there's data block on KBC data port, read it out // if ((Data & KBC_OUTB) == KBC_OUTB) { MouseAbsolutePointerDev->IsaIo->Io.Read (MouseAbsolutePointerDev->IsaIo, EfiIsaIoWidthUint8, KBC_DATA_PORT, 1, &Data); } Status = EFI_SUCCESS; // // The PS2 mouse driver reset behavior is always successfully return no matter wheater or not there is mouse connected to system. // This behavior is needed by performance speed. The following mouse command only succeessfully finish when mouse device is // connected to system, so if PS2 mouse device not connect to system or user not ask for, we skip the mouse configuration and enabling // if (ExtendedVerification && CheckMouseAbsolutePointerConnect (MouseAbsolutePointerDev)) { // // Send mouse reset command and set mouse default configure // Status = PS2MouseReset (MouseAbsolutePointerDev->IsaIo); if (EFI_ERROR (Status)) { Status = EFI_DEVICE_ERROR; goto Exit; } Status = PS2MouseSetSampleRate (MouseAbsolutePointerDev->IsaIo, MouseAbsolutePointerDev->SampleRate); if (EFI_ERROR (Status)) { Status = EFI_DEVICE_ERROR; goto Exit; } Status = PS2MouseSetResolution (MouseAbsolutePointerDev->IsaIo, MouseAbsolutePointerDev->Resolution); if (EFI_ERROR (Status)) { Status = EFI_DEVICE_ERROR; goto Exit; } Status = PS2MouseSetScaling (MouseAbsolutePointerDev->IsaIo, MouseAbsolutePointerDev->Scaling); if (EFI_ERROR (Status)) { Status = EFI_DEVICE_ERROR; goto Exit; } Status = PS2MouseEnable (MouseAbsolutePointerDev->IsaIo); if (EFI_ERROR (Status)) { Status = EFI_DEVICE_ERROR; goto Exit; } } Exit: gBS->RestoreTPL (OldTpl); if (KeyboardEnable) { KbcEnableKb (MouseAbsolutePointerDev->IsaIo); } return Status; }
/** Start this driver on Controller. @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. @param[in] ControllerHandle The handle of the controller to start. This handle must support a protocol interface that supplies an I/O abstraction to the driver. @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This parameter is ignored by device drivers, and is optional for bus drivers. @retval EFI_SUCCESS The device was started. @retval EFI_DEVICE_ERROR The device could not be started due to a device error. Currently not implemented. @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. @retval Others The driver failded to start the device. **/ EFI_STATUS EFIAPI FdcControllerDriverStart ( IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE Controller, IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath ) { EFI_STATUS Status; FDC_BLK_IO_DEV *FdcDev; EFI_ISA_IO_PROTOCOL *IsaIo; UINTN Index; LIST_ENTRY *List; BOOLEAN Found; EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath; FdcDev = NULL; IsaIo = NULL; // // Open the device path protocol // Status = gBS->OpenProtocol ( Controller, &gEfiDevicePathProtocolGuid, (VOID **) &ParentDevicePath, This->DriverBindingHandle, Controller, EFI_OPEN_PROTOCOL_BY_DRIVER ); if (EFI_ERROR (Status)) { return Status; } // // Report enable progress code // REPORT_STATUS_CODE_WITH_DEVICE_PATH ( EFI_PROGRESS_CODE, EFI_PERIPHERAL_REMOVABLE_MEDIA | EFI_P_PC_ENABLE, ParentDevicePath ); // // Open the ISA I/O Protocol // Status = gBS->OpenProtocol ( Controller, &gEfiIsaIoProtocolGuid, (VOID **) &IsaIo, This->DriverBindingHandle, Controller, EFI_OPEN_PROTOCOL_BY_DRIVER ); if (EFI_ERROR (Status)) { goto Done; } // // Allocate the floppy device's Device structure // FdcDev = AllocateZeroPool (sizeof (FDC_BLK_IO_DEV)); if (FdcDev == NULL) { goto Done; } // // Initialize the floppy device's device structure // FdcDev->Signature = FDC_BLK_IO_DEV_SIGNATURE; FdcDev->Handle = Controller; FdcDev->IsaIo = IsaIo; FdcDev->Disk = (EFI_FDC_DISK) IsaIo->ResourceList->Device.UID; FdcDev->Cache = NULL; FdcDev->Event = NULL; FdcDev->ControllerState = NULL; FdcDev->DevicePath = ParentDevicePath; FdcDev->ControllerNameTable = NULL; AddName (FdcDev); // // Look up the base address of the Floppy Disk Controller which controls this floppy device // for (Index = 0; FdcDev->IsaIo->ResourceList->ResourceItem[Index].Type != EfiIsaAcpiResourceEndOfList; Index++) { if (FdcDev->IsaIo->ResourceList->ResourceItem[Index].Type == EfiIsaAcpiResourceIo) { FdcDev->BaseAddress = (UINT16) FdcDev->IsaIo->ResourceList->ResourceItem[Index].StartRange; } } // // Maintain the list of floppy disk controllers // Found = FALSE; List = mControllerHead.ForwardLink; while (List != &mControllerHead) { FdcDev->ControllerState = FLOPPY_CONTROLLER_FROM_LIST_ENTRY (List); if (FdcDev->BaseAddress == FdcDev->ControllerState->BaseAddress) { Found = TRUE; break; } List = List->ForwardLink; } if (!Found) { // // A new floppy disk controller controlling this floppy disk drive is found // FdcDev->ControllerState = AllocatePool (sizeof (FLOPPY_CONTROLLER_CONTEXT)); if (FdcDev->ControllerState == NULL) { goto Done; } FdcDev->ControllerState->Signature = FLOPPY_CONTROLLER_CONTEXT_SIGNATURE; FdcDev->ControllerState->FddResetPerformed = FALSE; FdcDev->ControllerState->NeedRecalibrate = FALSE; FdcDev->ControllerState->BaseAddress = FdcDev->BaseAddress; FdcDev->ControllerState->NumberOfDrive = 0; InsertTailList (&mControllerHead, &FdcDev->ControllerState->Link); } // // Create a timer event for each floppy disk drive device. // This timer event is used to control the motor on and off // Status = gBS->CreateEvent ( EVT_TIMER | EVT_NOTIFY_SIGNAL, TPL_NOTIFY, FddTimerProc, FdcDev, &FdcDev->Event ); if (EFI_ERROR (Status)) { goto Done; } // // Reset the Floppy Disk Controller // if (!FdcDev->ControllerState->FddResetPerformed) { FdcDev->ControllerState->FddResetPerformed = TRUE; FdcDev->ControllerState->FddResetStatus = FddReset (FdcDev); } if (EFI_ERROR (FdcDev->ControllerState->FddResetStatus)) { Status = EFI_DEVICE_ERROR; goto Done; } REPORT_STATUS_CODE_WITH_DEVICE_PATH ( EFI_PROGRESS_CODE, EFI_PERIPHERAL_REMOVABLE_MEDIA | EFI_P_PC_PRESENCE_DETECT, ParentDevicePath ); // // Discover the Floppy Drive // Status = DiscoverFddDevice (FdcDev); if (EFI_ERROR (Status)) { Status = EFI_DEVICE_ERROR; goto Done; } // // Install protocol interfaces for the serial device. // Status = gBS->InstallMultipleProtocolInterfaces ( &Controller, &gEfiBlockIoProtocolGuid, &FdcDev->BlkIo, NULL ); if (!EFI_ERROR (Status)) { FdcDev->ControllerState->NumberOfDrive++; } Done: if (EFI_ERROR (Status)) { REPORT_STATUS_CODE_WITH_DEVICE_PATH ( EFI_ERROR_CODE | EFI_ERROR_MINOR, EFI_PERIPHERAL_REMOVABLE_MEDIA | EFI_P_EC_CONTROLLER_ERROR, ParentDevicePath ); // // If a floppy drive device structure was allocated, then free it // if (FdcDev != NULL) { if (FdcDev->Event != NULL) { // // Close the event for turning the motor off // gBS->CloseEvent (FdcDev->Event); } FreeUnicodeStringTable (FdcDev->ControllerNameTable); FreePool (FdcDev); } // // Close the ISA I/O Protocol // if (IsaIo != NULL) { gBS->CloseProtocol ( Controller, &gEfiIsaIoProtocolGuid, This->DriverBindingHandle, Controller ); } // // Close the device path protocol // gBS->CloseProtocol ( Controller, &gEfiDevicePathProtocolGuid, This->DriverBindingHandle, Controller ); } return Status; }
/** Stop this driver on ControllerHandle. Support stoping any child handles created by this driver. @param This Protocol instance pointer. @param ControllerHandle Handle of device to stop driver on @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number of children is zero stop the entire bus driver. @param ChildHandleBuffer List of Child Handles to Stop. @retval EFI_SUCCESS This driver is removed ControllerHandle @retval other This driver was not removed from this device **/ EFI_STATUS EFIAPI KbdControllerDriverStop ( IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE Controller, IN UINTN NumberOfChildren, IN EFI_HANDLE *ChildHandleBuffer ) { EFI_STATUS Status; EFI_SIMPLE_TEXT_INPUT_PROTOCOL *ConIn; KEYBOARD_CONSOLE_IN_DEV *ConsoleIn; UINT8 Data; // // Disable Keyboard // Status = gBS->OpenProtocol ( Controller, &gEfiSimpleTextInProtocolGuid, (VOID **) &ConIn, This->DriverBindingHandle, Controller, EFI_OPEN_PROTOCOL_GET_PROTOCOL ); if (EFI_ERROR (Status)) { return Status; } Status = gBS->OpenProtocol ( Controller, &gEfiSimpleTextInputExProtocolGuid, NULL, This->DriverBindingHandle, Controller, EFI_OPEN_PROTOCOL_TEST_PROTOCOL ); if (EFI_ERROR (Status)) { return Status; } ConsoleIn = KEYBOARD_CONSOLE_IN_DEV_FROM_THIS (ConIn); // // Report that the keyboard is being disabled // REPORT_STATUS_CODE_WITH_DEVICE_PATH ( EFI_PROGRESS_CODE, EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_DISABLE, ConsoleIn->DevicePath ); if (ConsoleIn->TimerEvent != NULL) { gBS->CloseEvent (ConsoleIn->TimerEvent); ConsoleIn->TimerEvent = NULL; } // // Since there will be no timer handler for keyboard input any more, // exhaust input data just in case there is still keyboard data left // Status = EFI_SUCCESS; while (!EFI_ERROR (Status)) { Status = KeyboardRead (ConsoleIn, &Data);; } // // Uninstall the SimpleTextIn and SimpleTextInEx protocols // Status = gBS->UninstallMultipleProtocolInterfaces ( Controller, &gEfiSimpleTextInProtocolGuid, &ConsoleIn->ConIn, &gEfiSimpleTextInputExProtocolGuid, &ConsoleIn->ConInEx, NULL ); if (EFI_ERROR (Status)) { return Status; } gBS->CloseProtocol ( Controller, &gEfiDevicePathProtocolGuid, This->DriverBindingHandle, Controller ); gBS->CloseProtocol ( Controller, &gEfiIsaIoProtocolGuid, This->DriverBindingHandle, Controller ); // // Free other resources // if ((ConsoleIn->ConIn).WaitForKey != NULL) { gBS->CloseEvent ((ConsoleIn->ConIn).WaitForKey); (ConsoleIn->ConIn).WaitForKey = NULL; } if (ConsoleIn->ConInEx.WaitForKeyEx != NULL) { gBS->CloseEvent (ConsoleIn->ConInEx.WaitForKeyEx); ConsoleIn->ConInEx.WaitForKeyEx = NULL; } KbdFreeNotifyList (&ConsoleIn->NotifyList); FreeUnicodeStringTable (ConsoleIn->ControllerNameTable); gBS->FreePool (ConsoleIn); return EFI_SUCCESS; }
/** Stop this driver on ControllerHandle. @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. @param[in] ControllerHandle A handle to the device being stopped. The handle must support a bus specific I/O protocol for the driver to use to stop the device. @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer. @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL if NumberOfChildren is 0. @retval EFI_SUCCESS The device was stopped. @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error. **/ EFI_STATUS EFIAPI FdcControllerDriverStop ( IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE Controller, IN UINTN NumberOfChildren, IN EFI_HANDLE *ChildHandleBuffer ) { EFI_STATUS Status; EFI_BLOCK_IO_PROTOCOL *BlkIo; FDC_BLK_IO_DEV *FdcDev; // // Ignore NumberOfChildren since this is a device driver // // // Get the Block I/O Protocol on Controller // Status = gBS->OpenProtocol ( Controller, &gEfiBlockIoProtocolGuid, (VOID **) &BlkIo, This->DriverBindingHandle, Controller, EFI_OPEN_PROTOCOL_GET_PROTOCOL ); if (EFI_ERROR (Status)) { return Status; } // // Get the floppy drive device's Device structure // FdcDev = FDD_BLK_IO_FROM_THIS (BlkIo); // // Report disable progress code // REPORT_STATUS_CODE_WITH_DEVICE_PATH ( EFI_PROGRESS_CODE, EFI_PERIPHERAL_REMOVABLE_MEDIA | EFI_P_PC_DISABLE, FdcDev->DevicePath ); // // Uninstall the Block I/O Protocol // Status = gBS->UninstallProtocolInterface ( Controller, &gEfiBlockIoProtocolGuid, &FdcDev->BlkIo ); if (EFI_ERROR (Status)) { return Status; } // // Close the event for turning the motor off // gBS->CloseEvent (FdcDev->Event); // // Turn the motor off on the floppy drive device // FddTimerProc (FdcDev->Event, FdcDev); // // Close the device path protocol // gBS->CloseProtocol ( Controller, &gEfiDevicePathProtocolGuid, This->DriverBindingHandle, Controller ); // // Close the ISA I/O Protocol // gBS->CloseProtocol ( Controller, &gEfiIsaIoProtocolGuid, This->DriverBindingHandle, Controller ); // // Free the controller list if needed // FdcDev->ControllerState->NumberOfDrive--; // // Free the cache if one was allocated // FdcFreeCache (FdcDev); // // Free the floppy drive device's device structure // FreeUnicodeStringTable (FdcDev->ControllerNameTable); FreePool (FdcDev); return EFI_SUCCESS; }