Nhân của Windows XP sử dụng một cấu trúc dữ liệu được biết đến như là đối tượng điềuhợp để mô tả các đặc tính DMA của thiết bị và để điều khiển truy cập đến các nguồnđược chia sẻ, như là
Trang 1Truy nhập bộ nhớ trực tiếp (Direct Memory Access )
Bởi:
Khoa CNTT ĐHSP KT Hưng Yên
Windows XP hỗ trợ việc truy cập trực tiếp bộ nhớ thong qua một mô hình máy tính trừutượng được mô tả ở hình 7.6 Trong hình này, máy tính được coi như là có một tập hợp
sơ đồ các thanh ghi cái mà được chuyển đổi giữa địa chỉ vật lý của CPU và địa chỉ bus.Mỗi sơ đồ địa chỉ thanh ghi này lưu giữ địa chỉ của một trang vật lý nào đó Phần cứngtruy cập bộ nhớ để đọc hay ghi bằng cách chỉ ra địa chỉ bus hay địa chỉ logic Sơ đồ cácthanh ghi này thực hiện cùng một vai trò khi tiếp nhận bảng trang cho phần mềm bằngcách cho phép phần cứng sử dụng các giá trị số khác nhau cho các địa chỉ của nó hơn là
để cho CPU hiểu
Hình 7-6 Mô hình máy tính trừu tượng của bộ chuyển MDA.
Một số CUP như Alpha chẳng hạn thì có sơ đồ thanh ghi phần cứng thực tế Một trongcác bước khởi đầu cho bộ chuyển DMA dự trữ một số thanh ghi cho quá trình sử dụngcủa bạn- tôi sẽ thảo luận vấn đề này trong phần sơ đồ chuyển Một số loại CPU khác,
Trang 2tự như họ làm Sơ đồ chuyển thực hiện từng bước có thể dảo ngược từ dưới lên củacác vùng đệm bộ nhớ vật lý, cái mà phụ thuộc vào hệ thống Trong một số trường hợpthì hoạt động của DMA sẽ được xử lý sử dụng vùng đệm đảo ngược Rõ rang là một
số người đã copy dữ liệu đến hoặc từ vùng đệm DMA trước hoặc sau khi dịch Trongtrường hợp cụ thể, ví dụ như là khi chúng ta lien hệ một đường bus của thiết bị chủ, cái
mà là noi tụ họp của các cáp- các giai đoạn của sơ đồ chuyển có thể không làm gì trongcấu trúc mà không có sơ đồ thanh ghi
Nhân của Windows XP sử dụng một cấu trúc dữ liệu được biết đến như là đối tượng điềuhợp để mô tả các đặc tính DMA của thiết bị và để điều khiển truy cập đến các nguồnđược chia sẻ, như là hệ thống các kênh DMA và sơ đồ các thanh ghi Bạn sẽ lấy mộtcon trỏ trỏ tới đối tượng điều hợp bởi lời gọi IOGetDmAAdapter trong suốt quá trìnhStartDevice của bạn Đối tượng điều hợp sẽ có một con trỏ để trỏ tới một cấu trúc đượcgọi là DmaOperations cái mà khi nó bật thì chứa các con trỏ để trỏ tới các hàm mà bạnmuốn gọi Hãy xem bảng 7.4 Các hàm này chỉ ra vị trí đích của hàm (ví dụ như … ) cái
mà bạn phải sử dụng phiên bản trước của Windown NT Thực tế, tên đích này có trongcác Macro các mà được khai báo trong hàm DmaOperations
Table 7-4 DmaOperations Function Pointers for
DMA Helper Routines
DmaOperations Function Pointer Description
GetDmaAlignment Gets address alignment requiredfor adapter
Trang 3GetScatterGatherList Reserves adapter and constructsscatter/gather list
Chiến lược chuyển đổi (Transfer Strategies):
Cách bạn thựchiện chuyển đổi DMa phụ thuộc vào nmột số nhân tố sau:
1 Nếu thiết bị của bạn có Bus-Mastering capability, tất nhiên là nó cần có điện đểtruy cập vào bộ nhớ chính nếu như bạn yêu cầu nó một số chức năng có bản.như là nơi bắt đầu, bao nhiêu đơn vị dữ liệu được chuyển, bạn đang thực hiệnviệc vào hay ra dữ liệu và nhiều điều khác Bạn sẽ phải hội ý với những ngườithiết kế ra phần cứng của bạn để lọc ra được các chi tiết này hoặc là bạn sẽ phảilàm việc với bảng hướng dẫn để biết được bạn cần phải làm gì với các mứcphần cứng này
2 Một thiết bị với khả năng tập hợp/trải ra có thể chuyển các khối lớn dữ liệu đếnhoặc đi các vùng không cấu hình của bộ nhớ vật lý Sử dụng scatter/gather làmột lợi thể của phần mềmbởi vì nó giới hạn yêu cầu về với các khối dữ liệu lớncủa các trang Frame cấu hình CÁc trang này có thể đơn giản là bị khoá khi màchúng được tìm thấy trong bộ nhớ vật lý và thiết bị có thể bị mô tả bởi chúng
3 Nếu thiết bị của bạn không có Bus chủ, bạn sẽ sử dụng hệ thống điều khiểnDMa trên bo mạch chủ của máy tính Kiểu của DMA đó đôi khi được gọi làDMA nô lệ (Slave) Hệ thống điều khiển DMA lien kết với các bus ISA có một
số giới hạn về bộ nhớ nào nó được truy cập và độ rộng của một bộ chuyển nó
có thể thực hiện mà không có chương trình định trước Trình điều khiển này cí
dụ như là IESA thiếu các giới hạn này Ít nhất là trong Windows XP, bạn sẽkhông cần phải biết kiểu bus phần cứng cảu bạn cắm vào bởi vì hệ thống có thểlấy ra các hạn chế này một cách tự động
4 Thông thường, hệ thống DMA bao gồm chương trình sơ đồ các thanh ghi phầncứng hoặc bản copy dữ liệu trước hay sau của hệ thống nếu thiết bịcủa bạn cầnđọc hay ghi dữ liệu lien tục, bạn không cần phải thực hiện các bước này vớimỗi yêu cầu vào.ra, nó có thể làm chậm đi quá trình được chấp nhận trongtrường hợp cụ thể rất nhiều Vì vậy bạn có thể chỉ định cái nào được biết như làvùng đệm chung, nơi mà các thiết bị và các trình điều khiển của bạn có thểđông thời truy cập tại nhiều thời điểm
Tuy nhiên trong thực tế nhiều chi tiết này sẽ bị phụ thuộc khác nhau vào cách mà 4 tácnhân này ảnh hưởng lẫn nhau, các bước mà bạn thực hiện sẽ có những đặc tính chung.Hình 7.7 đã minh hoạc qua tổ chức của một chuyển đổi Bạn bắt đầu chuyển đổi từ côngviệc StartIo bằng cách yêu cầu quyền sở hữu của chính đối tượng điều hợp.Quyền sởhữu này chỉ có giá trị khi bạn chia sẻ một kênh DMA hệ thống với một thiết bị khác,
Trang 4này Khi trình quản lý vào/ra có thể cung cấp cho bạn quyền này, nó sẽ chỉ định cho bạnmột số sơ đồ các thanh ghi cho quá trình sử dụng tạm thời cảu bạnvà gọi lại hành độngđiều khiển bộ điều hợp bạn cung cấp TRong hành động điều khiển bộ điều hợp của bạn,bạn thực hiện một sơ đồ chuyển đổi từng bước đế sắp xếp phạm vi chuyển đổi đầu tiên(cũng có thể là chỉ có một) Một số phạm vi có thể cần thiết nếu khả năng sơ đồ cácthanh ghi là không thể Thiết bị của bạn phải có thể cản trở và điều khiển những điều cóthể xáy ra giữa các phạm vi.
Figure 7-7 Flow of ownership during DMA.
Một thủ tục điều khiển bộ điều hợp của bạn có thể khởi tạo sơ đồ các thanh ghi chophạm vi đầu tiên, bạn báo hiệu cho thiết bị của mình băt đầu hoạt động Thiết bị của bạn
sẽ thúc đẩy một ngắt khi mà quá trình chuyển đổi ban đầu được hoàn tất VÀ sau đó thìbạn sẽ liệt kê được một DPC Thủ tục của DPC sẽ khởi đầu một phạm vi chuyển đổikhácnếu cần thiết hoặc nếu không thì nó sẽ hoàn thành yêu cầu
Đôi khi theo cách này, bạn sẽ giải phóng sơ đồ các thanh ghi và đối tượng điều hợp
Sự tính toán thời gian của hai sự kiện này là một trong số các chi tiết khác cái mà phụcthuộc vào các tác nhân tôi đã nêu ra ở đầu của phần này
Thực hiện chuyển đổi DM (Performing DMA Transfers):
Bây giờ tôi sẽ đi vào chi tiết về những cái máy cơ học cái mà vẫn được gọi là một gói cơ
sở DMA chuyển đổi, ở khía cạnh nào đó bạn chuyển đổi một số dữ liệu riêng biệt bằngcách sử dụng vùng đệm dữ liệu cái mà đi cùng với gói yêu cầu vào/ra Hãy bắt đầu mộtcách đơn giản và giả sử rằng bạn đối diện với một trường hợp rất chung ngày nay: Thiết
bị của bạn là một bus PCI master nhưng không có khả năng phân giải/ tụ tập
Trang 5Khi bạn tạo ra đối tượng thiết bị của mình, để bắt đầu bạn thong thường sẽ biểu thịđiều bạn muốn để sử dụng phương thức truy cập trực tiếp vùng đệm dữ liệu bằngviệc thiết lập cờ DO_DIRECT_IO Bạn chọn phương thức trực tiếp bởi vì bạn thậmchí sẽ phải thong qua địa chỉ của một kí hiệu bộ nhớ lập danh sách khi một trong
số các tham số hàm MapTransfẻ bạn sẽ gọi Sự lựa chọn này sẽ đưa ra một số vấn
đề đáng quan tâm về sự sắp hang của vùng đệm Trừ phi mà ứng dụng sử dụng cờFILE_FLAG_NO_BUFFERING trong lời gọi của nó tới hàm CreatFile, trình quản lývào ra sẽ không bắt buộc yêu cầu xếp hang của đối tượng thiết bị trên các vùng đệm
dữ liệu ở chế độ người dùng (nó không bắt buộc các yêu cầu cho nhân ở chế độ lời gọitrong ……) Nếu Hal hoặc thiết bị của bạn yêu cầu các vùng đệm DMA để bắt đầu trongmột ranh giới cụ thể, vì thế bạn có thể copy từ duới lên một phần nhỏ của dữ liệu ngườidùng tới hang chính xác bên trong vùng đệm để có được một hang đợi yêu cầu- hoặc làđiều đó hoặc nguyên nhân để làm sai và yêu cầu điều đó có một vùng đệm không sắphàng
TRong hàm StartDevice, bạn tạo một đối tượng điềuhợp bằng cách sử dụng đoạn codenhư sau:
Trang 6sẽ cần phải lưu ý rằng tôi đã lưu trữ hai trường trong thiết bị mở rộng để nhận lấy hai dữliệu ra từ hàm này.
Để khởi đầu cho hoạt động vào/ra, thủ tục StartIo đầu tiên cần phải dự trữ một đốitượng bằng lời gọi thủ tục AllocateAdapterChannel của đối tượng Một trong các tham
số truyền tới hàm AllocateAdapterChannel là địa chỉ của một thủ tục điều khiển điềuhợp, cái mà trình quản lý vào ra sẽ gọi khi sự lưu trữ xong xuôi Đây là đoạn code mẫu
mà bạn sử dụng để chuẩn bị và thực hiện lời gọi tới AllocateAdapterChannel:
typedef struct _DEVICE_EXTENSION {
PADAPTER_OBJECT AdapterObject; // device's adapter object
ULONG nMapRegisters; // max # map registers
ULONG nMapRegistersAllocated; // # allocated for this xfer
ULONG numxfer; // # bytes transferred so far
ULONG xfer; // # bytes to transfer during this stage
ULONG nbytes; // # bytes remaining to transfer
PVOID vaddr; // virtual address for current stage
PVOID regbase; // map register base for this stage
Trang 7NTSTATUS status = (*pdx->AdapterObject->DmaOperations
->AllocateAdapterChannel)(pdx->AdapterObject, fdo, nregs,
Trang 8kê khai vùng đệm có thể kéo dài qua ranh giới của một trang Tuy nhiên con số
mà chúng ta đi ngược từ dưới lên với khả năng có thể vượt qua số lớn nhất màchúng ta được cho phépbởi lời gọi thong thường tới hàm IoGetDmAAdapter.TRong trường hợp này chúng ta cần thực hiện một chuyển đổi trong nhiềuphạm vi Do vậy chúng ta đảo ngược tỉlệ của trang đầu tiên để chỉ sử dụng con
số chấp nhận được của sơ đồ các thanh ghi Chúng ta cũng cấn phải nhớ có baonhiêu sơ đồ các thanh ghi mà chúng ta đang cho phép để chúng ta có thể huỷchính xác con số này về sau
4 TRong lời gọi tới hàm AllocateAdapterChannel, chúng ta chỉ ra địa chỉ của đ ốitượng Adapter, địa chỉ của đối tượng thiết bị của chúng ta, số lượng đã đượctính toán của sơ đồ các thanh ghi, và địa chỉ của thủ tục điều khiển điều hợ củachúng ta Tham số cuối cùng pdx là tham số ngữ cảnh cho thủ tục điều khiểnđiều hợp của chúng ta
Thông thường thì một vài thiết bị có thể chia sẻ chung một đối tượng điều hợp đơn, đốitượng điều hợp đang chia sẻ trong cuộc sống thực tế chỉ khi bạn tin tưởng vào hệ thốngđiều khiển DMA Các thiết bị Bus-Master tận dụng các đối tượng điều hợp thuộc quyền
sở hữu.Nhưng bởi vì bạn không cần phải biết về hệ thống các thiết bị khi bạn tạo ra cácđối tượng điều hợp, nên bạn cũng không cần phải đưa ra bất cứ chứng minhnào vềnó.Khi đó thong thường đối tượng điều hợp của chúng ta sẽ rất bận rộn khi bạn gọi tớiAllocateAdapterChannel, và yêu cầu của bạn vì thế có thể bị đặt vào trong một hang đợicho tới khi đối tượng điềuhợp trở nên có thể xử lý (rảnh rỗi) Tất cả khoảng trễ này xảy
ra bên trong của AllocateAdapterChannel cái mà sẽ gọi thủ tục điều khiển điều hợp củabạn khi đối tượng điều hợp và tất cả sơ đồ các thanh ghi mà bạn yêu cầu rảng rỗi
Nhiệm vụ tiếp theo của bạn là thực hiện những gì mà thiết bị phụ thuộc của bạn yêu cầu
để nói cho thiết bị của bạn biết về địa chỉ vật lý để bắt đầu hoạt động trong phần cứngcủa bạn
IO_ALLOCATION_ACTION AdapterControl(PDEVICE_OBJECT fdo,
Trang 9PIRP junk, PVOID regbase, PDEVICE_EXTENSION pdx)
{
PIRP Irp = GetCurrentIrp(&pdx->dqReadWrite);
PMDL mdl = Irp->MdlAddress;
PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp);
BOOLEAN isread = stack->MajorFunction == IRP_MJ_READ;
Trang 101 Tham số thứ 2 cái mà tôi đặt tên là junk to AdapterControl is whatever(bất cứkhi nào) was in the CurrentIrp field of the device object khi mà bạn gọi hàmAllocateAdapterChannel Khi bạn sử dụng DEVQUEUE cho hang đợi IRP, bạncần phải yêu cầu đối tượng DEVQUEUE cái mà là IRP hiện tại Nếu bạn sửdụng hang đợi các thủ tục của Microsoft IoStartPacker & IoStartNextPacket đểquảnlý hang đợi của bạn thì junk sẽ đúng là một IRP Trong trường hợp này tôi
sẽ gọi tên Irp để thay thế
2 Có một số điều khác biệt giữa đoạn code điều khiển hoạt động vào và ra sửdụng DMA, vì thế nó rất thuận tiện cho việc điều khiển cả hai hoạt động nàytrong thủ tục con đơn Dòng code này kiểm tra code cho hàm chính cho Irp đểquyết định khi nào thì hành động đọc hoặc ghĩe xảy ra
3 Tham số regbase tới hàm này là một điều khiển không rõ ràngtrong việc chỉđịnh tập hợp của các thanh ghi sẽ được lưu trữ trong suốt quá trình sử dụng củabạn Sau này bạn sẽ cần tới giá trị này, vì thế bạn cần lưu trữ nó trong thiết bị
mở rộng của mình
4 KeFlushIoBuffers chắc chắn rằng nội dung của toàn bộ các xửlý trong các bộnhớ Cache cho vùng đệm bộ nhớ bạn đang sử dụng được làm sạch bộ nhớ.Tham số thứ 3 (TRUE)chỉ ra rằng bạn đã làm sạch bộ nhớ Cache chuẩn bị chohoạt động của DMA Kiểu kiến trúc của CPU có thể yêu cầu bước này, bởi vìthong thường thì hoạt động của DMA hướng trực tiếp đến hoặc đi từ bộ nhớ màkhông nhất thiết phải kéo theo các bộ nhớ Cache
5 Thủ tục Map Transfer thực hiện phần cứng của DMA cho một phạm vi củachuyển đổi và trả về địa chỉ vật lý khi mà việc chuyển đổi bắt đầu Chú ý rằngbạn cung cấp địa chỉ của một MDL như là tham số thứ hai của hàm này Bởi vìbạn cần một MDL tại điểm này, nên thong thường thì bạn cần phải lựa chọnphương thức DO_DIRECT_IOkhi lần đầu tiên bạn tạo đối tượng thiết bị củamình, và trình quản lý vào ra vì thế sẽ tự động tạo một MDL cho bạn Bạn cũngcần thong qua cùng với sơ đồ thanh ghi địa chỉ cơ sở (regbase) Bạn chỉ ra phầnnào của MDL bị dính líu đến phạm vi của hoạt động này bằng cách cung cấpmột địa chỉ ảo (pxd→vaddr) và một bute đếm (pxd→xfer) Sơ đồ chuyển đổi sẽ
sử dụng tham số địa chỉ ảo để tính toán điạ chỉ offset của vùng đệm Từ đó nó
có thể xác định các trang vật lý đang chứa đựng dữ liệu của bạn
6 Đó là một điểm mà tại đó bạn lập trình phần cứng của mình trong thiết bị theomột cách đặc biệt là được yêu cầu Ví dụ như là bạn có thể sử dụng một trong
số các thủ tục của WRITE_Xxx Hal để gửi địa chỉ vật lý và các giá trị của byteđếm đến các thanh ghi ở trong card của bạn, và từ đó về sau thì bạn có thể điềukhiển thanh ghi nhấp nháy để bắt đầu chuyển đổi dữ liệu
7 Chúng ta trả ra một hằng số DeAllocateKeepObjectRegister để chỉ ra rằngchúng ta đã không sử dụng đối tượng điều hợp nhưng chúng ta vẫn sử dụng sơ
đồ các thanh ghi Trong m\ví dụ cụ thể (bus chủ PCI), ở đây không bao giờ có
sự ganh đua với đối tượng điều hợp tại vị trí đầu tiên vì khó khăn của nó là vấn
đề chúng ta giải phóng đối tượng điều hợp đó Trong một số trường hợp busđang làm chủ khác (bus-mastering) chúng ta có thể chia sẻ điều khiển DMA
Trang 11với các thiết bị khác Việc giải phóng đối tượng điều hợp này cho phép cácthiết bị khác bắt đầu được thực hiện chuyển đổi bằng việc sử dụng các phần tậphợp rời nhau của sơ đồ thanh ghi từ một khối liền mà chúng ta vẫn đang sửdụng.
Một ngắt thường xuất hiện rất nhanh sau khi mà chúng ta bắt đầu chuyển đổi.Và thủ tụcngắt dịch vụ luôn luôn yêu cầu một DPC để liên hệ với sự hoàn thành của phạm vi đầutiên của chuyển đổi Thủ tục DPC của bạncó thể tương tự như sau:
VOID DpcForIsr(PKDPC Dpc, PDEVICE_OBJECT fdo,
PIRP junk, PDEVICE_EXTENSION pdx)
Trang 12if (pdx->nbytes && NT_SUCCESS(status))
Trang 13ULONG numxfer = pdx->numxfer;
3 Ở đây chúng ta cập nhật số dư và số dữ liệu còn lại sau khi mà phạm vi chuyển đổi đãhoàn tất
4 Tại vị trí này, bạn xác định phạm vi hiện thời của chuyển đổi đã được hoàn tất thànhcông hoặc có lỗi xảy ra Ví dụ như là bạn có thể đọc trạng thái của cổng hay là xemxét kỹ kết quả của một hoạt động tương tự được thực hiện bởi thủ tục ngắt của bạn Ởtrong ví dụ này, tôi thiết lập thuộc tính variable cho trạng thái thành công (STATUS-SUCCESS) với sự mong đợi rằng bạn đã thay đổi nó nếu tìm ra lỗi ở đây
5 Nếu chuyển đổi này không dừng lại, bạn cần phải lập trình cho một phạm vi khác.Bước đầu tiên trong tiến trình này là tính toán địa chỉ ảo của vị trí tiếp theo của bộ đệm
ở chế độ người dùng Theo tôi thì việc tính toán này đơn thuần chỉ là làm việc với mộtsố- thực tế chúng ta chưa cố gắng để truy cập vào bộ nhớ bằng cách sử dụng địa chỉ ảonày Tất nhiên, truy cập bộ nhớ có thể là một ý kiến tồi bởi vì chúng ta đang thực hiệnmột luồng ngữ cảnh tuỳ biến