Cấu hình thiết bị của bạn (Configuring Your Device )
Trong chương trước, tôi đã thảo luận với bạn về IRP-MJ-PNP cho thiết bị cắm và chạy (Plug and Play). IRP_MN_START_DEVICE là một phương tiện để cung cấp cho bạn các thông tin về các nguồn vào/ra cái mà đã được chỉ định bởi PnP Manager bạn sử dụng. Tôi đã ...
Trong chương trước, tôi đã thảo luận với bạn về IRP-MJ-PNP cho thiết bị cắm và chạy (Plug and Play). IRP_MN_START_DEVICE là một phương tiện để cung cấp cho bạn các thông tin về các nguồn vào/ra cái mà đã được chỉ định bởi PnP Manager bạn sử dụng. Tôi đã chỉ cho bạn cách để đạt được đồng thời list các cách thức đơn giản (chưa tinh tế) và cách để dịch các mô tả nguồn và làm sao để có thể gọi trợ giúp hàm StartDevice mà bạn có thể thấy nguyên mẫu như sau:
NTSTATUS StartDevice(PDEVICE_OBJECT fdo,
PCM_PARTIAL_RESOURCE_LIST raw,
PCM_PARTIAL_RESOURCE_LIST translated)
{

}
Các cấu trúc CM_PARTIAL_RESOURCE_lIST chứa đựng một số đếm và một mảng các cấu trúc CM_PARTIAL_RESOURCE_DESCRIPTOR, như là minh hoạ ở hình 7.1. Mỗi một kí hiệu nguồn ở trong mảng này có một thành phần là Type để biểu thị kiểu của nguồn được mô tả và một số các thành phần thêm vào cái mà cung cấp các thể hiện cụ thể về nguồn được chỉ định. Bạn sẽ không bị làm cho ngạc nhiên (bất ngờ) bằng việc hãy tìm trong mảng này và theo cách: Nếu thiết bị của bạn sử dụng IRQ và vùng các cổng vào ra, bạn sẽ nhận được hai kí hiệu nguồn từ trong mảng này. Một trong hai kí hiệu là dành cho IRQ của bạn và kí hiệu còn lại sẽ dành cho phần cổng vào/ra. Thật không may, bạn không thể dự đoán trước được thứ tự mà các kí hiệu sẽ xuất hiện trong mảng này. Chính vì vậy, hàm giúp đỡ StartDevice sẽ phải bắt đầu với một vòng lặp đó là “trải mỏng” mảng này bằng cách trích ra các giá trị nguồn vào một tập hợp các biến cục bộ. Bạn có thể sử dụng các biến cục bộ này sau để liên kết với các nguồn chỉ định tại các vị trí mmà bạn cần (nó sẽ khác với những gì lý thuyết nói, có thể khác một chút với các thứ tự mà trong đó PnP Manager chọn lựa để hiển thị cho bạn)
Hình 7-1. Structure of a partial resource list.
Với bản phác thảo này, hàm StartDevice sẽ có dạng:
NTSTATUS StartDevice(PDEVICE_OBJECT fdo,
PCM_PARTIAL_RESOURCE_LIST raw,
PCM_PARTIAL_RESOURCE_LIST translated)
{
PDEVICE_EXTENSION pdx =
(PDEVICE_EXTENSION) fdo->DeviceExtension;

PCM_PARTIAL_RESOURCE_DESCRIPTOR resource =
translated->PartialDescriptors;

ULONG nres = translated->Count;

<local variable declarations>
for (ULONG i = 0; i < nres; ++i, ++resource)
{

switch (resource->Type)
{
case CmResourceTypePort:
<save port info in local variables>
break;
case CmResourceTypeInterrupt:
<save interrupt info in local variables>
break;
case CmResourceTypeMemory:
<save memory info in local variables>
break;
case CmResourceTypeDma:
<save DMA info in local variables>
break;
}
}

<use local variables to configure driver & hardware> return STATUS_SUCCESS;
}
- Tôi sẽ sử dụng con trỏ trong đoạn code này để chỉ ra kí hiệu nguồn hiện tại với độ dài khác nhau của mảng.
- Thành phần Count cuả danh sách nguồn sẽ chỉ ra rằng có bao nhiêu kí hiệu nguồn ở trong mảng PartialDescriptor.
- Bạn nên khai báo các biến cục bộ thích hợp với mỗi nguồn vào/ra mà bạn muốn nhận được. Tôi sẽ cụ thể hoá những điều này sau khi mà tôi thảo luận về cách làm thế nào để liên kết (liên hệ) các nguồn vào ra chuẩn.
- Các kí hiệu nguồn trong suốt vòng lặp, bạn hãy sử dụng cấu trúc lệnh Switch để lưu các thông tin mô tả nguồn vào các biến cục bộ tương ứng. Trong đoạn text này, tôi ấn định một thiết bị cái mà cần sử dụng một cổng vào/ra và một ngắt, và thiết bị đó sẽ đòi hỏi phải tìm ra các kiểu dữ liệu nguồn CmResourceTypePort và CmResourceTypeInterup. Tôi đang chỉ cho bạn một cách kĩ lưỡng về hai kiểu dữ liệu nguồn chuẩn CmResourceTypeMemory và CmResourceTypeDma.
- Một vòng lặp bên ngoài, các biến cục bộ mà bạn khởi tạo trong các nhãn khác nhau sẽ giữ các thông tin nguồn bạn cần.
Nếu bạn có nhiều hơn một nguồn có kiểu riêng biệt (cụ thể), bạn cần phải tạo ra một cách thức nào đó để thông báo cho thành phần các kí hiệu nguồn. Để đưa ra một ví dụ cụ thể (nhưng chỉ là tưởng tượng), giả sử rằng thiết bị của bạn sử dụng 4 KB của vùng nhớ cho mục đích điều khiển và 16 KB vùng nhớ để dành cho việc thu thập dữ liệu. Bạn mong rằng sẽ nhận được hai nguồn CmResourceTypeMemory từ Manager PnP. Điều khiển bộ nhớ là một khối có dung lượng 4 KB, và bộ nhớ dữ liệu là một khối có dung lượng 16 KB. Nếu code (nguồn) của thiết bị của bạn có sự phân biệt kí tự như là kích cỡ khác nhau như trong ví dụ, bạn có thể nói rõ nó là cái gì trong phần nguồn (code).
Bảng 7.1 thể hiện cái nhìn tổng quát về mỗi kiểu dữ liệu nguồn.
Table 7-1. Overview of Processing Steps for I/O Resources | |
Resource Type | Overview |
Port | Possibly map port range; save base port address in device extension |
Memory | Map memory range; save base address in device extension |
Dma | Call IoGetDmaAdapter to create an adapter object |
Interrupt | Call IoConnectInterrupt to create an interrupt object that points to your interrupt service routine (ISR) |