Windows95的裝置驅動程式的編寫 (轉)

worldblog發表於2007-12-04
Windows95的裝置驅動程式的編寫 (轉)[@more@]95的裝置的編寫 錄入/江湖小子 1999.08.07

1 ? 為 什 麼 需 要 設 備 驅 動 程 序

從 Windows 3.1 開 始 , 對 於 硬 件 設 備 的 訪 問 便 採 取 了 一 種 設 備 驅 動 程 序 的 方 法 , 客 戶 通 過 設 備 驅 動 程 序 來 獲 得 硬 件 的 參 數 或 者 設 置 , 但 是 由 於 16 位 的 操 作 系 統 基 於 原 來 的 D, 所 以 客 戶 程 序 仍 然 可 以 通 過 一 些 或 者 DOS 的 DPMI 中 斷 調 用 來 實 現 對 硬 件 的 操 作 。

32 位 的 操 作 系 統 如 Windows 95 & NT 不 再 基 於 16 位 DOS , 所 以 用 戶 如 果 需 要 實 現 對 硬 件 中 斷 、 DMA 、 I/O 或 者 是 絕 對 存 儲 訪 問 , 都 不 可 避 免 地 必 須 通 過 設 備 驅 動 程 序 。 Windows 95 操 作 系 統 能 夠 實 現 多 線 程 、 多 進 程 的 應 用 , 系 統 通 過 一 個 虛 擬 機 管 理 器 VMM 32 、 VXD(Virtual machine manager) , 通 過 它 和 其 他 的 設 備 驅 動 程 序 合 作 , 來 實 現 多 個 進 程 間 的 協 調 工 作 , 防 止 一 個 進 程 的 運 行 導 致 另 一 個 進 程 的 崩 潰 。

2 ? 什 麼 是 設 備 驅 動 程 序

設 備 驅 動 程 序 被 用 來 管 理 系 統 資 源 ( 硬 件 或 者 軟 件 ) 的 可 執 行 二 進 制 代 碼 , 通 過 設 備 驅 動 程 序 , 多 個 進 程 可 以 同 時 使 用 這 些 資 源 , 從 而 可 以 實 現 多 進 程 並 行 運 行 。 設 備 驅 動 程 序 一 般 是 以 “ VxD ” 為 後 綴 名 , 其 意 思 是 虛 擬 化 某 些 設 備 (Virtual ″ something ″ Device) 。 在 一 般 概 念 上 , 設 備 驅 動 程 序 和 虛 擬 設 備 是 同 義 的 , 我 們 下 面 就 將 兩 者 混 用 。

386 以 上 的 微 處 理 器 有 4 個 優 先 級 別 : 0 級 、 1 級 、 2 級 、 3 級 , 一 般 操 作 系 統 運 行 於 優 先 級 0 級 上 , 而 用 戶 程 序 運 行 在 3 級 上 。 VxD 運 行 於 0 級 上 , 其 在 內 存 中 的 位 置 也 是 處 在 操 作 系 統 保 護 的 空 間 之 內 的 。

Windows 95 是 繼 承 Windows 3.x 而 來 , 所 以 兩 者 的 設 備 驅 動 程 序 採 取 的 是 同 一 種 模 式 , 也 就 是 說 , 一 般 為 Windows 3.x 寫 的 設 備 驅 動 程 序 , 可 以 不 加 改 動 地 運 行 於 Windows 95 下 ; 但 是 也 有 一 些 區 別 : 一 般 Windows 95 下 面 的 驅 動 程 序 是 以 “ VxD ” 為 後 綴 名 , 而 Windows 3.x 是 以 “ 386 ” 為 後 綴 名 ; Windows 3.x 的 設 備 驅 動 程 序 必 須 在 Windows 啟 動 時 靜 態 載 入 , 而 Windows 95 的 設 備 驅 動 程 序 可 以 在 程 序 運 行 過 程 中 動 態 載 入 。

採 用 的 一 種 完 全 不 同 的 模 式 , 所 以 Windows 95 & 3.x 下 的 設 備 驅 動 程 序 是 不 能 和 Windows NT 的 設 備 驅 動 程 序 兼 容 的 。

另 外 , Windows 還 提 供 一 些 運 行 在 優 先 級 3 上 的 驅 動 程 序 , 主 要 是 串列埠 的 通 信 程 序 和 並 口 的 打 印 機 程 序 , 這 些 程 序 以 “ DRV ” 為 後 綴名 。 但 是 一 般 說 來 , 運 行 於 優 先 級 別 3 上 面 的 I/O 比 運 行 於 0 級 的 慢。

3 ? 設 備 驅 動 程 序 編 寫 簡 介

設 備 驅 動 程 序 的 編 寫 有 一 定 規 範 , 需 要 對 於 32 位 的 匯 編 和 C 語 言 比較 熟 悉 ; 一 般 完 全 由 匯 編 語 言 編 寫 , 但 是 也 可 以 用 C 與 匯 編 的 混 合語 言 實 現 ; 首 先 需 要 有 DDK(Device Kit) , 一 般 工 具 是MASM6 ? 11 和 VC2 ? 0 以 上 版 本 。

通 常 設 備 驅 動 程 序 由 五 個 段 組 成 , 它 們 分 別 是 : VxD - CODE 、 VxD- DATA 、 VxD - ICODE 、 VxD - IDATA 和 VxD - REAL - INIT 。 VxD -CODE 是 保 護 模 式 下 的 代 碼 段 , 一 般 這 個 段 包 括 設 備 驅 動 程 序 的 控制 程 序 、 回 收 函 數 、 服 務 程 序 和 接 口 函 數 , 這 個 段 也 命 名 為 -LTEXT ; VxD - DATA 是 保 護 模 式 下 的 數 據 段 , 一 般 包 括 設 備 驅 動 程式 的 描 述 表 , 以 及 一 些 全 局 變 量 , 這 個 段 也 命 名 為 - LDATA ; VxD- ICODE 是 保 護 模 式 下 的 初 始 化 代 碼 段 , 包 括 一 些 初 始 化 時 使 用 的服 務 程 序 , 虛 擬 機 管 理 器 (VMM) 在 初 始 化 結 束 之 後 就 將 這 個 段 取 消, 這 個 段 也 命 名 為 - ITEXT ; VxD - IDATA 是 保 護 模 式 下 的 初 始 化 資料 段 , 包 括 一 些 初 始 化 時 使 用 的 數 據 , 虛 擬 機 管 理 器 (VMM) 在 初 始化 結 束 之 後 就 將 這 個 段 取 消 , 這 個 段 也 命 名 為 - IDATA ; VxD -REAL - INIT 包 括 實 模 式 下 的 初 始 化 數 據 和 代 碼 段 , 虛 擬 機 管 理 器(VMM) 最 先 就 是 裝 入 這 個 代 碼 段 , 在 進 程 返 回 之 後 這 個 段 取 消 , 再裝 入 其 他 代 碼 段 , 這 個 段 又 命 名 為 - RTEXT 。

需 要 注 意 的 是 , 除 了 實 模 式 下 的 初 始 化 數 據 和 代 碼 段 外 , 其 他 四個 段 都 是 32 位 保 護 模 式 下 平 板 模 式 (flat model) 的 段 。

每 個 設 備 驅 動 程 序 必 須 首 先 聲 明 一 個 虛 擬 機 的 名 字 、 版 本 號 、 初始 化 過 程 、 虛 擬 機 控 制 程 序 ( 相 當 於 程 序 入 口 ) ; 有 些 設 備 驅 動 程式 還 可 以 聲 明 設 備 標 志 號 和 接 口 函 數 () 。 虛 擬 機 一 般 用 Declare -Virtual - Device 宏 來 聲 明 , 例 如 下 例 :

Declare - Virtual - Device VSAMPLED,4,0,VSAMPLED - Control,

VSAMPLED - Device - ID,VSAMPLED - Init - Order,

VSAMPLED - V86 - API - Handler,VSAMPLED - PM - API - Handler

意 思 是 樣 例 虛 擬 機 , 名 字 叫 做 VSAMPLED , 版 本 是 4 ? 0 , 控 制 程 序是 VSAMPLED - Control , VSAMPLED - Device - ID 申 明 了 虛 擬 機 的 標 志符 , VSAMPLED - Init - Order 說 明 初 始 化 的 過 程 , 另 外 後 面 兩 項 說 明中 支 持 V86 模 式 和 保 護 模 式 下 的 兩 種 接 口 函 數 。 通 過 這 些 聲 明 , 我們 就 可 以 確 定 一 個 唯 一 的 虛 擬 機 , 系 統 就 可 以 將 它 和 別 的 虛 擬 機區 別 。

每 個 虛 擬 機 需 要 一 個 虛 擬 機 控 制 程 序 。 虛 擬 機 管 理 器 (VMM) 通 過 這個 程 序 來 向 該 虛 擬 機 傳 遞 控 制 信 息 , 系 統 通 過 控 制 消 息 來 控 制 虛擬 機 的 執 行 , 例 如 初 始 化 虛 擬 機 、 虛 擬 機 狀 態 的 改 變 等 工 作 。

一 個 虛 擬 機 需 要 提 供 一 些 服 務 功 能 , 這 些 功 能 可 以 被 虛 擬 機 管 理器 (VMM) 或 者 其 他 的 虛 擬 機 來 使 用 。 但 是 , 虛 擬 機 不 像 Windows DLLs一 樣 提 供 出 口 函 數 (export functions) , 虛 擬 機 管 理 器 (VMM) 通 過 0x20 號中 斷 來 實 現 與 虛 擬 機 的 連 接 , 中 斷 的 句 柄 通 過 一 個 服 務 號 來 決 定到 底 哪 個 虛 擬 機 支 持 這 個 服 務 功 能 。

一 個 虛 擬 機 通 過 BeginProc 和 EndProc 兩 個 宏 來 定 義 它 的 服 務 功 能 , 很像 匯 編 語 言 。 例 如 下 例 :

BeginProc VSMAPLED - Service - Routine,Service

main body of the service......

EndProc VSAMPLED - Service - Routine

一 般 BeginProc 的 名 字 後 面 有 一 個 參 數 : Service 或 者 Async - Service , 後者 是 說 明 這 個 服 務 程 序 可 以 被 異 步 地 調 用 , 多 用 在 中 斷 服 務 程 序一 類 中 , 異 步 服 務 程 序 必 須 是 可 以 重 入 的 , 所 以 它 不 能 調 用 不 能重 入 的 服 務 程 序 。

二 、 圖 像 採 集 卡 設 備 驅 動 程 序

由 於 實 際 工 作 的 需 要 , 我 們 設 計 一 塊 圖 像 採 集 卡 來 實 現 圖 像 的 實時 採 集 , 由 於 圖 像 數 據 傳 輸 量 大 , 實 時 性 要 求 強 , 所 以 我 們 採 用PCI 總 線 ; 軟 件 的 平 臺 採 用 Windows 95 。

1 ? 系 統 硬 件 簡 介

系 統 採 用 Philips 公 司 的 SAA7110 作 為 前 端 圖 像 採 集 量 化 器 , 而 PCI 介面 芯 片 採 用 以 色 列 ZORAN 公 司 的 ZR36120 作 為 接 口 工 芯 片 , 兩 個 都 是 可 編 程 的 芯 片 。

ZR36120 是 為 多 媒 體 應 用 設 計 的 一 個 控 制 器 , 它 既 具 有 PCI 總 線 操 作的 功 能 , 又 具 有 多 媒 體 控 制 功 能 , 比 如 圖 像 數 據 的 濾 波 , 是 一 個多 媒 體 控 制 器 (Multimedia Controller for PCI Bus) 。 它 具 有 兩 組 寄 存 器 , 一組 是 符 合 PCI 2 ? 0 的 配 置 寄 存 器 (Configuration Registers) ; 另 外 一 組 是 基於 用 戶 應 用 的 寄 存 器 , 命 名 為 ASR(Application - specific Registers) , 這 組寄 存 器 主 要 是 面 向 用 戶 實 際 應 用 的 , 包 括 一 些 圖 像 數 據 格 式 、 濾波 器 的 選 擇 、 中 斷 方 式 的 設 置 、 DMA 通 道 的 選 擇 及 地 址 等 等 內 容的 寄 存 器 , ASR 的 訪 問 是 採 用 存 儲 器 映 射 方 式 的 。

2 ? 軟 件 設 計

系 統 需 要 對 硬 件 進 行 操 作 , 其 中 包 括 :

(1)DMA 內 存 的 分 配 。 圖 像 的 數 據 是 通 過 DMA 方 式 傳 送 到 主 機 的 ,所 以 必 須 根 據 圖 像 尺 寸 大 小 來 分 配 內 存 給 DMA 通 道 。 將 DMA 內 存地 址 通 知 PCI 接 口 芯 片 和 客 戶 程 序 , PCI 接 口 芯 片 所 需 要 的 地 址 是絕 對 物 理 地 址 , 客 戶 程 序 使 用 的 地 址 是 虛 擬 地 址 ( 平 板 模 式 的 32 位下 就 是 線 性 地 址 ) , 如 何 將 兩 者 對 應 起 來 ?

(2) 接 口 芯 片 ZR36120 和 圖 像 採 集 芯 片 SAA7110 的 初 始 化 。 需 要 對ZR36120 的 配 置 寄 存 器 讀 寫 , 使 用 I/O 方 式 或 者 是 BIOS 中 斷 方 式 ; 另外 ZR36120 的 ASR 採 用 存 儲 器 映 射 方 式 來 實 現 讀 寫 。

所 有 這 些 問 題 的 解 決 都 不 可 回 避 地 必 須 採 用 設 備 驅 動 程 序 來 實 現對 硬 件 的 操 作 , 在 優 先 級 3 上 運 行 的 用 戶 程 序 是 無 法 實 現 這 些 功 能的 。

? DMA 內 存 的 分 配

首 先 必 須 在 Windows 95 的 System.ini 文 件 中 加 入 DMABUFFERSIZE=2048K( 這兒 是 2M , 大 小 根 據 DMA 操 作 的 實 際 大 小 決 定 ) 。 系 統 就 會 在 啟 動 時留 下 相 應 大 小 的 內 存 以 供 用 戶 以 後 DMA 操 作 使 用 。

用 戶 在 自 己 程 序 中 分 配 一 段 內 存 , 現 在 問 題 是 如 何 將 這 段 內 存 與系 統 的 DMA 內 存 聯 系 起 來 。 Microsoft DDK 的 內 核 提 供 了 VDMAD -Request - Buffer 這 個 系 統 調 用 , 向 系 統 申 請 一 定 大 小 的 DMA 內 存 ,DMA 緩 衝 區 的 線 性 地 址 通 過 ESI 傳 入 , 緩 衝 區 的 大 小 通 過 ECX 傳 入

。 得 到 的 DMA 區 域 的 物 理 地 址 通 過 EDX 傳 出 , 而 標 志 號 由 EBX 傳 出

。 申 請 DMA 區 域 後 , 我 們 必 須 用 VDMAD - Lock - DMA - REGION 將該 區 域 鎖 定 , 以 便 我 們 後 面 使 用 。

分 配 好 DFMA 內 存 後 , 還 必 須 能 夠 實 現 DMA 內 存 與 用 戶 空 間 數 據 的交 換 。 DDK 提 供 VDMAD - Copy - From - Buffer 這 個 系 統 調 用 來 實 現數 據 由 DMA 區 域 傳 到 用 戶 數 據 區 中 。 其 中 傳 入 的 參 數 中 : ESI 存 放用 戶 數 據 區 域 性 地 址 , ECX 存 放 數 據 區 大 小 , EBX 中 存 放 標 志 號 ,EDI 中 存 放 偏 移 量 。 如 果 操 作 成 功 , CF 位 復 位 ; 失 敗 的 話 , CF 位置 位 。 另 外 提 供 VDMAD - Copy - To - Buffer 實 現 將 用 戶 區 數 據 拷 貝到 DMA 緩 衝 區 中 , 其 輸 入 輸 出 參 數 與 前 者 一 模 一 樣 。

? 存 儲 器 映 射 方 式

ZR36120 的 ASR 必 須 採 用 存 儲 器 映 射 的 方 式 來 實 現 讀 寫 。 所 謂 存 儲器 映 射 , 就 是 一 些 芯 片 將 自 己 的 一 些 寄 存 器 映 射 在 某 段 內 存 上 ,系 統 可 以 象 平 時 訪 問 內 存 一 樣 取 訪 問 它 們 ; 但 是 這 段 內 存 映 射 的必 須 是 主 機 上 一 段 空 白 的 內 存 段 , 不 得 和 已 存 的 內 存 相 衝 突 , 比如 0xF00000000 ; 而 映 射 的 這 段 地 址 是 物 理 地 址 , 客 戶 程 序 中 讀 寫 的是 線 性 地 址 , 我 們 必 須 將 這 段 物 理 地 址 轉 化 為 線 性 地 址 。

DDK 中 提 供 - MapPhysToLinear 這 個 調 用 來 實 現 將 物 理 地 址 映 射 為 線 性地 址 , 但 是 這 個 調 用 只 能 是 用 於 將 外 設 的 物 理 地 址 轉 化 為 線 性 地址 , 而 不 是 計 算 機 本 身 的 內 存 空 間 ; 傳 入 的 參 數 是 三 個 , 第 一 個參 數 是 物 理 地 址 的 起 始 地 址 , 第 二 個 參 數 是 長 度 , 第 三 個 是 標 志位 , 一 般 為 0 ; 返 回 的 參 數 是 優 先 級 0 下 面 的 線 性 地 址 。 例 如 :

VMMcall - MapPhysToLinear,<0f0000000h,1000h,0>

就 是 將 起 臺 物 理 地 址 為 0xF0000000 的 長 度 為 0x1000 的 一 段 寄 存 器 映 射到 內 存 上 面 。

? 端 口 操 作

Windows 95 沒 有 將 端 口 保 護 起 來 , 這 可 能 主 要 是 為 串 口 通 信 設 備 和並 口 打 印 設 備 的 需 要 而 考 慮 的 。 所 以 應 用 程 序 可 以 通 過 調 用 系 統函 數 或 者 是 直 接 用 匯 編 語 言 來 實 現 對 端 口 的 操 作 。 例 如 中 就 有- outp, - outpw, - outpd, - inp, - inpw, - inpd 等 函 數 分 別 實 現 端 口 的 輸入 輸 出 。 但 是 由 於 在 優 先 級 0 級 上 的 速 度 快 , 另 外 可 以 多 進 程 操 作, 一 般 硬 件 的 端 口 操 作 最 好 還 是 在 設 備 驅 動 程 序 中 完 成 。根 據 PCI 總 線 2 ? 0 的 標 準 , PCI 總 線 的 配 置 寄 存 器 (configuraiotn registers)包 括 256 個 字 節 , 其 中 前 64 比 特 構 成 配 置 寄 存 器 頭 (configuraiotn header), 主 要 包 括 主 機 (Host) 與 客 戶 (Client) 的 一 些 接 口 信 息 , 如 器 件 號 , 廠商 號 , 所 用 的 中 斷 號 , 口 地 址 的 範 圍 (I/O 方 式 ) , 存 儲 器 的 地 址 ( 器 映 射 方 式 ) … … 。 對 於 PCI 配 置 寄 存 器 (configuration registers) 的 讀 寫, 有 兩 種 方 式 : 第 一 種 , 通 過 BIOS 中 斷 0x1A 的 子 功 能 號 0xB1 完 成 ,這 是 為 兼 容 以 前 的 系 統 所 設 計 。 第 二 種 , 通 過 對 兩 個 口 地 址0xcf8 和 0xcfc 進 行 雙 字 的 讀 寫 來 實 現 對 配 置 寄 存 器 讀 寫 , 這 種 方 法 是為 了 同 未 來 的 系 統 兼 容 設 計 的 , 特 點 是 簡 單 明 了 。我 們 這 兒 詳 細 介 紹 第 二 種 方 法 : 口 地 址 0xcf8 是 配 置 寄 存 器 的 地 址寄 存 器 , 它 的 32 位 操 作 的 每 一 位 的 意 義 如 下 : bus number 、 functionnumber 和 device number 都 是 在 計 算 機 啟 動 時 由 系 統 分 配 , register number就 是 我 們 所 需 要 進 行 讀 寫 的 寄 存 器 號 , 最 低 兩 位 為 0 , 8 比 特 剛 好構 成 256 個 字 節 的 配 置 寄 存 器 地 址 空 間 。 口 地 址 0xcfc 就 是 數 據 寄 存器 , 寫 完 地 址 寄 存 後 , 對 該 口 進 行 雙 字 讀 就 得 到 配 置 寄 存 器 裡 面的 值 , 寫 入 一 個 雙 字 就 完 成 對 相 應 配 置 寄 存 器 的 寫 操 作 。明 白 各 操 作 位 的 意 義 後 , 我 們 就 可 以 利 用 兩 條 匯 編 指 令 IN 和 OUT來 實 現 我 們 的 目 的 , 注 意 的 是 這 兒 的 操 作 必 須 是 雙 字 操 作 , 例 如必 須 是 : IN EAX , DX 或 者 OUT DX , EAX 一 類 的 指 令 , 而 不 能 將 一個 雙 字 操 作 轉 化 為 兩 次 字 的 操 作 或 者 四 次 字 節 操 作 。

? 客 戶 程 序 對 設 備 驅 動 程 序 的 調 用

以 上 介 紹 的 是 設 備 驅 動 程 序 的 編 寫 , 下 面 我 們 詳 細 分 析 一 下 客 戶程 序 ( 一 般 的 用 戶 程 序 , 最 常 見 是 用 C 和 C + + 編 寫 ) 如 何 調 用 設 備驅 動 程 序 的 。

如 果 開 發 的 是 標 準 的 API 函 數 的 話 , 客 戶 程 序 可 以 通 過 調 用 系 統 標準 的 函 數 庫 來 進 行 操 作 。 但 是 如 果 定 義 的 不 是 系 統 提 供 的 標 準 的 話 , 接 口 函 數 就 是 用 戶 面 向 自 己 的 硬 件 或 者 軟 件 開 發 , 那 麼一 般 不 會 採 用 標 準 的 接 口 函 數 , 這 就 無 法 從 標 準 的 函 數 庫 中 得 到調 用 , 但 是 這 也 是 最 常 出 現 的 情 形 , 下 面 我 們 就 C 語 言 中 的 調 用 情況 加 以 詳 細 說 明 。

把 一 個 硬 件 設 備 虛 擬 化 後 , 這 個 硬 件 設 備 就 是 作 為 一 個 文 件 系 統而 被 系 統 調 用 ; 採 用 這 樣 的 方 式 , 現 在 Windows 95 & NT 也 是 採用 這 樣 的 方 式 。 32 位 的 系 統 調 用 中 提 供 一 個 CreateFile 來 打 開 或 者 建立 “ 文 件 ” , 其 中 可 以 打 開 的 “ 文 件 ” 的 類 型 有 : 文 件 、 管 道 、通 信 設 備 、 磁 盤 設 備 、 控 件 、 目 錄 … … ; 我 們 這 兒 不 妨 假 設 我 們的 驅 動 程 序 名 字 叫 做 Pclvice.Vxd 。

正 如 前 面 所 述 , 我 們 先 要 使 用 CreateFile 系 統 函 數 打 開 這 個 設 備 文 件, 得 到 一 個 句 柄 , 如 下 例 所 示 :

hCVxd=CreateFile( ″ PciDevice.Vxd ″ ,0,0,0,CREATE - NEW,FILE - FLAG -DELETE - ON - CLOSE,0) ;

打 開 這 個 設 備 後 , 我 們 就 可 以 和 它 進 行 數 據 的 交 換 了 。 比 如 圖 像數 據 採 集 卡 已 將 數 據 通 過 DMA 方 式 傳 入 內 存 之 中 , 我 們 需 要 通 過設 備 驅 動 程 序 將 數 據 轉 入 我 們 程 序 的 內 存 中 , 我 們 的 設 備 驅 動 程式 中 已 有 子 例 程 VXD - COPY - OUT - OF - DMA - BUFFER , 它 輸 入是 兩 個 參 數 , 一 個 是 應 用 程 序 緩 衝 區 的 地 址 , 第 二 個 是 緩 衝 區 長度 ; 輸 出 是 一 個 參 數 , 代 表 操 作 成 功 或 者 失 敗 。 調 用 DeviceIoControl就 可 完 成 此 項 任 務 , 如 下 例 :

DeviceIoControl

(hCVxD,VXD - COPY - OUT - OF - DMA -

BUFFER,(LPVOID)InInfo,sizeof(InInfo),(LPVOID)RetInfo,sizeof(RetInfo), &

cbBytesReturned,NULL);

其 中 第 一 個 參 數 是 我 們 前 面 所 打 開 的 設 備 的 句 柄 , 第 二 個 是 我 們所 要 進 行 的 操 作 的 代 碼 , 第 三 個 參 數 和 第 四 個 參 數 分 別 是 傳 入 的參 數 和 大 小 ( 一 般 用 多 少 比 特 表 示 ) , 比 如 我 們 的 例 子 中 兩 個 參 數都 是 長 整 形 的 話 , 那 麼 第 四 個 參 數 就 是 8 ; 第 二 、 第 六 和 第 七 個 引數 分 別 是 返 回 參 數 及 其 大 小 ; 第 八 個 參 數 是 用 於 異 步 方 式 的 設 備驅 動 程 序 , 例 如 中 斷 服 務 程 序 。

三 、 程 序 參 考

下 面 一 些 程 序 是 我 的 圖 像 採 集 卡 的 設 備 驅 動 程 序 的 一 些 關 鍵 子 程式 , 但 是 沒 有 將 與 硬 件 設 備 相 關 的 例 程 列 出 , 為 了 敘 述 方 便 , 我將 有 些 變 量 用 全 局 變 量 代 替 , 以 下 程 序 用 VC5 ? 0 、 MASM6 ? 11 和DDK 混 合 編 譯 通 過 。

.386p
.xlist
include vmm.inc
include vdmad.inc
include configmg.inc
.list
extern - lineadr:D
extern - bufsize:DWORD
extern - physadr:DWORD
extern - buffid:DWORD
VxD - LOCKED - CODE - SEG

線 性 地 址 在 返 回 的 EAX 中 , 高 級 語 言 就 可 以 像 調 用 一 般 程 序 一 樣得 到 線 性 地 址 public Phys2Linear

Phys2Linear PROC

VMMCall - MapPhysToLinear,<080000000h,1000h,0>

得 到 起 始 物 理 地 址 為 0x80000000 長 度 為 0x1000 一 段 內 存 的 線 性 地 址

ret

Phys2Linear ENDP

; 分 配 和 鎖 存 一 段 DMA 內 存 區 域

phblic Alloc - Lick - DMA - Region

alloc - Lock - DMA - Region PROC

mov esi, - lineadr; 線 性 地 址

    mov ecx, - bufsize ; DMA 區 域 長 度

    VxDcall VDMAD - Request - Buffer

    mov - physadr,edx; 返 回 起 始 物 理 地 址 在 edx 中

    mov - buffid,ebx ; 標 志 號 在 ebx 中

    mov esi, - lineadr

    mov ecx, - bufsize

    mov d1,1

    VxDcall VDMAD - Lock - DMA - REGION

    ret

alloc - Lock - DMA - Region ENDP

; 從 DMA 區 域 中 將 數 據 拷 貝 到 用 戶 的 內 存 中

public Copy - From - DMA - Buffer

Copy - From - DMA - Buffer PROC

    mov ebx, - buffid; 標 志 號

    mov esi, - lineadr; 用 戶 的 線 性 地 址

    xor edi,edi;DMA 緩 衝 區 相 對 起 始 地 址

    mov ecx, - bufsize ; 需 要 傳 輸 的 長 度

    VxDcall VDMAD - Copy - From - Buffer

copy - From - DMA - Buffer ENDP

; 將 DMA 內 存 釋 放

public Free - DMA - Region

Free - DMA - Region PROC

    mov esi, - lineadr

    mov ecx, - bufsize

    VxDcall VDMAD - Unlock - DMA - REGION

    mov ebx, - buffid

    VxDcall VDMAD - Release - Buffer

    ret

Free - DMA - Region ENDP


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10752043/viewspace-987977/,如需轉載,請註明出處,否則將追究法律責任。

相關文章