Windows95的设备驱动程序的编写
Windows95的设备驱动程序的编写 |
录入/江湖小子 |
1999.08.07 |
1 ?? 为 什 么 需 要 设 备 驱 动 程 序
从 Windows 3.1 开 始 , 对 于 硬 件 设 备 的 访 问 便 采 取 了 一 种 设 备 驱 动 程 序 的 方 法 , 客 户 通 过 设 备 驱 动 程 序 来 获 得 硬 件 的 参 数 或 者 设 置 , 但 是 由 于 16 位 的 操 作 系 统 基 于 原 来 的 DOS , 所 以 客 户 程 序 仍 然 可 以 通 过 一 些 BIOS 或 者 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 NT 采 用 的 一 种 完 全 不 同 的 模 式 , 所 以 Windows 95 & 3.x 下 的 设 备 驱 动 程 序 是 不 能 和 Windows NT 的 设 备 驱 动 程 序 兼 容 的 。
另 外 , Windows 还 提 供 一 些 运 行 在 优 先 级 3 上 的 驱 动 程 序 , 主 要 是 串口 的 通 信 程 序 和 并 口 的 打 印 机 程 序 , 这 些 程 序 以 “ DRV ” 为 后 缀名 。 但 是 一 般 说 来 , 运 行 于 优 先 级 别 3 上 面 的 I/O 比 运 行 于 0 级 的 慢。
3 ?? 设 备 驱 动 程 序 编 写 简 介
设 备 驱 动 程 序 的 编 写 有 一 定 规 范 , 需 要 对 于 32 位 的 汇 编 和 C 语 言 比较 熟 悉 ; 一 般 完 全 由 汇 编 语 言 编 写 , 但 是 也 可 以 用 C 与 汇 编 的 混 合语 言 实 现 ; 首 先 需 要 有 Microsoft DDK(Device Driver 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) 的 段 。
每 个 设 备 驱 动 程 序 必 须 首 先 声 明 一 个 虚 拟 机 的 名 字 、 版 本 号 、 初始 化 过 程 、 虚 拟 机 控 制 程 序 ( 相 当 于 程 序 入 口 ) ; 有 些 设 备 驱 动 程序 还 可 以 声 明 设 备 标 志 号 和 接 口 函 数 (API) 。 虚 拟 机 一 般 用 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 没 有 将 端 口 保 护 起 来 , 这 可 能 主 要 是 为 串 口 通 信 设 备 和并 口 打 印 设 备 的 需 要 而 考 虑 的 。 所 以 应 用 程 序 可 以 通 过 调 用 系 统函 数 或 者 是 直 接 用 汇 编 语 言 来 实 现 对 端 口 的 操 作 。 例 如 VC 中 就 有- 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 完 成 ,这 是 Intel 为 兼 容 以 前 的 系 统 所 设 计 。 第 二 种 , 通 过 对 两 个 口 地 址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 语 言 中 的 调 用 情况 加 以 详 细 说 明 。
把 一 个 硬 件 设 备 虚 拟 化 后 , 这 个 硬 件 设 备 就 是 作 为 一 个 文 件 系 统而 被 系 统 调 用 ; UNIX 采 用 这 样 的 方 式 , 现 在 Windows 95 & NT 也 是 采用 这 样 的 方 式 。 32 位 的 系 统 调 用 中 提 供 一 个 CreateFile 来 打 开 或 者 创建 “ 文 件 ” , 其 中 可 以 打 开 的 “ 文 件 ” 的 类 型 有 : 文 件 、 管 道 、通 信 设 备 、 磁 盘 设 备 、 控 件 、 目 录 … … ; 我 们 这 儿 不 妨 假 设 我 们的 驱 动 程 序 名 字 叫 做 PcliDevice.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:DWORD
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