/** 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; }
EFI_STATUS EFIAPI FdcControllerDriverStart ( IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE Controller, IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath ) /*++ Routine Description: Arguments: Returns: --*/ // GC_TODO: This - add argument and description to function comment // GC_TODO: Controller - add argument and description to function comment // GC_TODO: RemainingDevicePath - add argument and description to function comment { EFI_STATUS Status; FDC_BLK_IO_DEV *FdcDev; EFI_INTERFACE_DEFINITION_FOR_ISA_IO *IsaIo; UINTN Index; EFI_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 // ReportStatusCodeWithDevicePath ( EFI_PROGRESS_CODE, EFI_PERIPHERAL_REMOVABLE_MEDIA | EFI_P_PC_ENABLE, 0, &gEfiCallerIdGuid, ParentDevicePath ); // // Open the ISA I/O Protocol // Status = gBS->OpenProtocol ( Controller, EFI_ISA_IO_PROTOCOL_VERSION, (VOID **) &IsaIo, This->DriverBindingHandle, Controller, EFI_OPEN_PROTOCOL_BY_DRIVER ); if (EFI_ERROR (Status)) { goto Done; } // // Allocate the Floppy Disk Controller's Device structure // FdcDev = EfiLibAllocateZeroPool (sizeof (FDC_BLK_IO_DEV)); if (FdcDev == NULL) { goto Done; } // // Initialize the Floppy Disk Controller's Device structure // FdcDev->Signature = FDC_BLK_IO_DEV_SIGNATURE; FdcDev->Handle = Controller; FdcDev->IsaIo = IsaIo; FdcDev->Disk = IsaIo->ResourceList->Device.UID; FdcDev->Cache = NULL; FdcDev->Event = NULL; FdcDev->ControllerState = NULL; FdcDev->DevicePath = ParentDevicePath; ADD_FLOPPY_NAME (FdcDev); // // Look up the base address of the Floppy Disk Controller // 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 controller list // Found = FALSE; List = gControllerHead.ForwardLink; while (List != &gControllerHead) { FdcDev->ControllerState = FLOPPY_CONTROLLER_FROM_LIST_ENTRY (List); if (FdcDev->BaseAddress == FdcDev->ControllerState->BaseAddress) { Found = TRUE; break; } List = List->ForwardLink; } if (!Found) { // // The Controller is new // FdcDev->ControllerState = EfiLibAllocatePool (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 (&gControllerHead, &FdcDev->ControllerState->Link); } // // Create a timer event for each Floppd Disk Controller. // This timer event is used to control the motor on and off // Status = gBS->CreateEvent ( EFI_EVENT_TIMER | EFI_EVENT_NOTIFY_SIGNAL, EFI_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; } ReportStatusCodeWithDevicePath ( EFI_PROGRESS_CODE, EFI_PERIPHERAL_REMOVABLE_MEDIA | EFI_P_PC_PRESENCE_DETECT, 0, &gEfiCallerIdGuid, 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 ); FdcDev->ControllerState->NumberOfDrive++; Done: if (EFI_ERROR (Status)) { ReportStatusCodeWithDevicePath ( EFI_ERROR_CODE | EFI_ERROR_MINOR, EFI_PERIPHERAL_REMOVABLE_MEDIA | EFI_P_EC_CONTROLLER_ERROR, 0, &gEfiCallerIdGuid, ParentDevicePath ); // // Close the device path protocol // gBS->CloseProtocol ( Controller, &gEfiDevicePathProtocolGuid, This->DriverBindingHandle, Controller ); // // Close the ISA I/O Protocol // if (IsaIo != NULL) { gBS->CloseProtocol ( Controller, EFI_ISA_IO_PROTOCOL_VERSION, This->DriverBindingHandle, Controller ); } // // If a Floppy Disk Controller 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); } EfiLibFreeUnicodeStringTable (FdcDev->ControllerNameTable); gBS->FreePool (FdcDev); } } return Status; }