2011年4月24日 星期日

Hot Plug Events

在以前, System Firmware在pre-boot的階段並沒有Hot Plug Events的需求. 然而, 例如像USB這種高階的Bus, 使用者會經常的插拔裝置. 要確保在EFI Driver Model內能夠描述這些Bus的種類是很重要的. Bus的Bus Driver要能夠支援這些Hot Plag Events. 對於這種類型的Bus, 有一些Platform的管理必須要轉成這種Bus Driver. 例如, 當一個鍵盤要插入USB Bus, 使用者會希望鍵盤是可以動的. USB Bus Driver要能夠偵測Add的Event發生, 並且建立一個Child Handle給Keyboard device.
然而, 因為Driver無法連接到Controller(除非呼叫ConnectController()), 所以鍵盤無法啟動. 當Add的Event發生, 要讓鍵盤啟動就必須仰賴USB Bus Driver去呼叫ConnectController(). 此外, 當Remove的Event發生時, USB Bus Driver也要能夠呼叫DisconnectController().

Hot Plug Events也會影響Device Driver. 例如USB, 在沒有任何通知下可以移除Device. 這代表USB Device Driver的Stop() function必須要和系統中不再存在的Device關掉Drver. 所以任何不能完成的I/O請求必須在不能接觸Hardware的情況下被清除.

一般而言, 增加支援Hot Plug Events的功能會大大地增加Bus Driver與Device Driver之間的複雜性.

下面有兩個例子, 第一個例子會去察看Controller Handle, 第二個例子會去測試Device Path.

extern EFI_GUID gEfiDriverBindingProtocolGuid;
EFI_HANDLE gMyImageHandle;
EFI_HANDLE DriverImageHandle;
EFI_HANDLE ControllerHandle;
EFI_DRIVER_BINDING_PROTOCOL *DriverBinding;
EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath;

//
// Use the DriverImageHandle to get the Driver Binding Protocol
// instance
//

//
// 透過DriverImageHandle取得Driver Binding Protocol的指標, 並放到DriverBinding內.
//

Status = gBS->OpenProtocol (
                             DriverImageHandle,
                             &gEfiDriverBindingProtocolGuid,
                             &DriverBinding,
                             gMyImageHandle,
                             NULL,
                             EFI_OPEN_PROTOCOL_HANDLE_PROTOCOL);

if (EFI_ERROR (Status)) {
  return Status;
}

//
// EXAMPLE #1
//
// Use the Driver Binding Protocol instance to test to see if
// the driver specified by DriverImageHandle supports the
// controller specified by ControllerHandle
//

//
// 取得Driver Binding Protocol的instance後,
// 就可以透過DriverBinding去測試, DriverImageHandle的Driver是否
// 有支援ControllerHandle的Controller.
//
Status = DriverBinding->Supported (
                                             DriverBinding,
                                             ControllerHandle,
                                             NULL);

//
// 如果成功的話, 表示Driver支援Controller, 執行Start() function.
//

if (!EFI_ERROR (Status)) {
  Status = DriverBinding->Start (
                                              DriverBinding,
                                              ControllerHandle,
                                              NULL);
}
return Status;

//
// EXAMPLE #2
//
// The RemainingDevicePath parameter can be used to initialize
// only the minimum devices required to boot. For example,
// maybe we only want to initialize 1 hard disk on a SCSI
// channel. If DriverImageHandle is a SCSI Bus Driver, and
// ControllerHandle is a SCSI Controller, and we only want to
// create a child handle for PUN=3 and LUN=0, then the
// RemainingDevicePath would be SCSI(3,0)/END. The following
// example would return EFI_SUCCESS if the SCSI driver supports
// creating the child handle for PUN=3, LUN=0. Otherwise it
// would return an error.
//

//
// RemainingDevicePath參數可以用來初始化最少Device Boot的需求.
// 例如, 我們可能只需要初始化SCSI上的一個HDD. 如果DriverImageHandle是
// 一個SCSI Bus Driver, 而ControllerHandle是一個SCSI Controller的話, 那麼
// 我們就只需要去建立一個PUN = 3以及LUN = 0的Child Handle. 它的
// RemainingDevicePath就可以寫成SCSI(3,0)/END. 下面的例子, 如果
// SCSI Driver支援PUN = 3以及LUN = 0的Child Handle的話, 那麼就會返回
// EFI_SUCCESS, 否則返回error.
//

Status = DriverBinding->Supported (
                                             DriverBinding,
                                             ControllerHandle,
                                             RemainingDevicePath);
if (!EFI_ERROR (Status)) {
  Status = DriverBinding->Start (
  DriverBinding,
  ControllerHandle,
  RemainingDevicePath);
}
return Status;

沒有留言:

張貼留言