Tải bản đầy đủ (.pdf) (8 trang)

Các cổng và các thanh ghi (ports and registers )

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (90.45 KB, 8 trang )

Các cổng và các thanh ghi (Ports and Registers )

Các cổng và các thanh ghi
(Ports and Registers )
Bởi:
Khoa CNTT ĐHSP KT Hưng Yên
Windows XP sử dụng mô hình máy tính trừu tượng như được mô tả trong hình 7.4 để
cung cấp một giao diện driver hợp nhất như trong kiến trúc của CPU. Trong chế độ này,
một CPU có thể có bộ nhớ riêng biệt và các không gian địa chỉ. Để truy cập vào bộ nhớ
thiết bị, CPU sẽ giao công việc cho một dạng bộ nhớ khác như là một bộ nhớ load hay
lưu truy cập trực tiếp đến một địa chỉ ảo. CPU dịch địa chỉ ảo đó ra thành địa chỉ vật lý
bằng cách thiết lập các bảng trang. Để truy cập vào một thiết bị vào ra đã được sơ đồ
hoá, bằng một cách khác, CPU cầu cứu tới một hệ thống đặc biệt là x86 với lời chỉ dẫn
vào và ra.

Hình 7.4. Truy cập vào các cổng và các thanh ghi.

1/8


Các cổng và các thanh ghi (Ports and Registers )

Các thiết bị phải có đường Bus là các cách thức cụ thể để có thể giải mã bọ nhớ và các
địa chỉ vào/ra. Trong trường hợp bus PCI, một cầu nối chính (host) để vẽ ra đường đi
(nối) giữa địa chỉ bộ nhớ vật lý của CPU và các điạ chỉ vào/ra tới không gian địa chỉ cái
mà có thể truy cập trực tiếp tới các thiết bị. Bít cờ trong không gian cấu hình của thiết bị
sẽ quyết định cầu nối này có vẽ được đường đi (nối từ) từ các thanh ghi của thiết bị tới
bộ nhớ hoặc địa chỉ vào/ra trên CPU thong qua cả hai không gian địa chỉ.
Rộng hơn khi bạn di chuyển có điều kiện một loạt code được biên dịch trong trình điều
khiển của bạn cho tất cả các thể hiện có thể, các nhà thiết kế Windows Nt đã sáng tạo
ra một lớp các phần cứng trừu tượng (Hal), cái mà tôi đã ám chỉ một vài lần trong cuốn


sách này. Hal cung cấp các hàm cái mà bạn sử dụng để truy xuất tới các tài nguyên bộ
nhớ và các cổng.
Hãy nhìn bảng 7.3. Với bảng tóm lược này, bạn có thể đọc/ghi hoặc là UCHAR/
USHORT/ULONG hoặc là một mảng các kiểu này đến hay từ (đến và đi) một
Cổng//Thanh ghi. điều này tạo nên 24 hàm hal tất cả mà bạn sử dụng để truy cập các
thiết bị. Từ trình điều khiển WDM không trực tiếp dựa vào Hal cho tất cả mọi thứ, bạn
có thể nghĩ về 24 hàm này tốt như là việc công khai toàn bộ, nguyên vẹn …… hal.
Bảng 7.3. Các hàm Hal cho việc truy cập các cổng và các thanh ghi bộ nhớ.
Table 7-3.
HAL
Functions
for
Accessing
Ports and
Memory
Registers
Access
Width

Functions for Port Access

Functions for Memory Access

8 bits

READ_PORT_UCHAR
WRITE_PORT_UCHAR

READ_REGISTER_UCHAR
WRITE_REGISTER_UCHAR


16 bits

READ_PORT_USHORT
WRITE_PORT_USHORT

READ_REGISTER_USHORT
WRITE_REGISTER_USHORT

32 bits

READ_PORT_ULONG
WRITE_PORT_ULONG

READ_REGISTER_ULONG
WRITE_REGISTER_ULONG

String of
8-bit bytes

READ_PORT_BUFFER_UCHAR
WRITE_PORT_BUFFER_UCHAR

READ_REGISTER_BUFFER_UCHAR
WRITE_REGISTER_BUFFER_UCHAR

2/8


Các cổng và các thanh ghi (Ports and Registers )


String of
READ_PORT_BUFFER_USHORT READ_REGISTER_BUFFER_USHORT
16-bit words WRITE_PORT_BUFFER_USHORT WRITE_REGISTER_BUFFER_USHORT
String of
READ_PORT_BUFFER_ULONG
32-bit WRITE_PORT_BUFFER_ULONG
doublewords

READ_REGISTER_BUFFER_ULONG
WRITE_REGISTER_BUFFER_ULONG

Những gì diễn ra bên trong của các hàm truy cập này là phục thuộc vào hệ
nền(Platform). Ví dụ, phiên bản Intel x86 của READ_PORT_CHAR thực hiện một cấu
trúc IN để đọc một byte từ cổng vào /ra đã được chỉ định. Bản bổ sung Microsoft
Windows 98/ME tiến xa hơn ….. lưu trữ tràn lời gọi của trình điều khiển với một lời
gọi IN hiện tại trong một số trường hợp. The Alpha version of this routine performs
a memory fetch. Phiên bản intel x86 của Read_Register_uchar cũng thực hiện một lộ
trình bộ nhớ. …. Theo cách khác, phiên bản định vùng đệm của hàm này (Read-registẻunchar) thực hiện thêm một số công việc trong môi trường x86 để chắc chắn rằngtất cả
các bộ nhớ cache được xoá (làm sạch) một cách hợp lý khi mà hoạt động này kết thúc.
Tài nguyên cổng (Port)
Các thiết bị vào ra được mô hình hoá (IO-Mapped) phơi bày ra các thanh ghi phần cứng
cái mà trên một số kiến trúc CPU (bao gồm cả Intel x86) được định địa chỉ thong qua
phần mềm sử dụng một không gian địa chỉ vào ra đặc biệt. Trên một số kiến trúc CPU
khác, không tồn tại không gian địa chỉ riêng biệt, và các thanh ghi này được định địa
chỉ thong qua việc sử dụng một bộ nhớ chính thức khác. May mắn thay, bạn không cần
phải hiểu rõ về sự phức tạp của các địa chỉ này. Nếu bạn yêu cầu thiết bị một cổng tài
nguyên, một vòng lặp của bạn lặp qua các kí hiệu tài nguyên được dịch sẽ tìm kiếm một
kí hiệu CmResourceTypePort, và bạn sẽ lưu thông tin ở 3 nơi.
typedef struct _DEVICE_EXTENSION {


PUCHAR portbase;
ULONG nports;
BOOLEAN mappedport;

} DEVICE_EXTENSION, *PDEVICE_EXTENSION;

3/8


Các cổng và các thanh ghi (Ports and Registers )

PHYSICAL_ADDRESS portbase;

// base address of range

for (ULONG i = 0; i < nres; ++i, ++resource)
{
switch (resource->Type)
{
case CmResourceTypePort:

portbase = resource->u.Port.Start;
pdx->nports = resource->u.Port.Length;

pdx->mappedport =
(resource->Flags & CM_RESOURCE_PORT_IO) == 0;
break;

}


if (pdx->mappedport)
{

pdx->portbase = (PUCHAR) MmMapIoSpace(portbase,

4/8


Các cổng và các thanh ghi (Ports and Registers )

pdx->nports, MmNonCached);
if (!pdx->portbase)
return STATUS_NO_MEMORY;
}
else

pdx->portbase = (PUCHAR) portbase.QuadPart;
1. Kí hiệu nguồn chứa đựng một tập hợp được đặt tên là u cái mà có các cấu trúc
hạ tầng cho mỗi kiểu trong số các kiểu nguồn chuẩn. u.Port có các thong tin về
một tài nguyên cổng. u.Port.Start là địa chỉ bắt đầu của một vùng liên tiếp các
cổng vào ra, và u.Port.Length là số lượng các cổng trong vùng (phạm vi) đó.
Địa chỉ bắt đầu là một giá trị địa chỉ vật lý 64 bit.
2. Thành phần Flags của kí hiệu nguồn cho một cổng tài nguyên có cờ CMRESOURCE-PORT-TO được thiết lập nếu như kiến trúc của CPU có không
gian địa chỉ vào ra riêng bệt để chứa các địa chỉ cổng thuộc về nó.
3. Nếu cờ CM_resource_Port_IO bị xoá, khi mà nó là một hệ nền của Alpha hoặc
một hang khác như RISC, bạn cần phải gọi MnMapIoSpace để đạt được nhân
của nó ở chế độ địa chỉ ảo bằng cổng có thể được truy cập. Việc truy cập này sẽ
giao cho một bộ nhớ khác, nhưng bạn vẫn gọi cổng …. của các công việc
thường nhật của Hal (read_Port_unchar và cứ thế) từ trình điều khiển.

4. Nếu cờ CM_RESOURCE_PORT_IO được thiết lập, đó là trong hệ nền x86, thì
bạn không cần vẽ sơ đồ (định sơ đồ) địa chỉ cổng. Bạn sẽ gọi PORT flavor of
HAL routines từ trình điều khiển của bạn khi bạn muốn truy xuất vào một cổng
trong số các cổng của bạn. Các công việc thường nhật của HAL (Hal routimes)
đòi hỏi một đối số địa chỉ cổng Puchar, đólà lý do tại sao chúng ta loại được
các đại chỉ cơ sở với kiểu này. Theo cách này thì một phần khác QuadPart dẫn
đến (tạo ra) con trỏ 32 bit hoặc 64 bít, thích hợp với hệ nền cho cái mà bạn
đang biên dịch.
- Nhờ StoptDevice của bạn sẽ giải phóng được tài nguyên thực hiện nếu bạn phải tiến
hành sơ đồ hoá các tài nguyên cổng của bạn.
VOID StopDevice(...)
{

5/8


Các cổng và các thanh ghi (Ports and Registers )

if (pdx->portbase && pdx->mappedport)
MmUnmapIoSpace(pdx->portbase, pdx->nports);
pdx->portbase = NULL;

}
Tài nguyên bộ nhớ (Memory Resources):
Các thiết bị mà bộ nhớ được mô hình hoá chỉ ra các thanh ghi, cái mà phần mềm truy
cập sử dụng câu lệnh nạp và lưu trữ. Giá trị tài nguyên được dịch này bạn lấy từ trình
quản lý PnP là một địa chỉ vật lý, và bạn cần phải dự phòng các địa chỉ ảo để có thể chứa
(bao bọc) bộ nhớ vật lý. Sau đó, bạn sẽ phải gọi các thủ tục của Hal, những cái mà sẽ
lien kết với các thanh ghi bộ nhớ như là Read_Register_Unchar , write_register_unchar,
và hơn thế nữa. Phần code cấu hình cũng như chú thích của bạn sẽ tương tự như những

gì được trình bày dưới đây.
typedef struct _DEVICE_EXTENSION {

PUCHAR membase;
ULONG nbytes;

} DEVICE_EXTENSION, *PDEVICE_EXTENSION;
PHYSICAL_ADDRESS membase;

// base address of range

for (ULONG i = 0; i < nres; ++i, ++resource)
{
6/8


Các cổng và các thanh ghi (Ports and Registers )

switch (resource->Type)
{
case CmResourceTypeMemory:

membase = resource->u.Memory.Start;
pdx->nbytes = resource->u.Memory.Length;
break;

}

pdx->membase = (PUCHAR) MmMapIoSpace(membase, pdx->nbytes,
MmNonCached);

if (!pdx->membase)
return STATUS_NO_MEMORY;
1. Trong suốt phần nguồn ở trên (code), u.memory có các thong tin vềtài nguyên
bộ nhớ. U.memory.Start là địa chỉ bắt đầu của một khoảng (phạm vi) liên tiếp
các vùng của bộ nhớ, và u.memory.length là số byte của cả phạm vi đó. Địa chỉ
bắt đầu là một giá trị địa chỉ vật lý 64 bits. Không phải ngẫu nhiên mà u.port và
u.memory là gống nhau- đó là một việc làm có mục đích và bạ có thể kiểm tra
lại để thấy điều này đúng nếu bạn muốn
2. Bạn phải gogị hàm MnMapÍopace để đạt được nhân chế độ địa chỉ ảo thong
qua phạm vi bộ nhớ có thể được truy xuất.
Hàm StopDevice của bạn vạch ra vô điều kiện các tài nguyên bộ nhớ của bạn
VOID StopDevice(...)

7/8


Các cổng và các thanh ghi (Ports and Registers )

{

if (pdx->membase)
MmUnmapIoSpace(pdx->membase, pdx->nbytes);
pdx->membase = NULL;

}

8/8




×