第 1 部分针对 Oracle Solaris 平台设计设备驱动程序
9. 直接内存访问 (Direct Memory Access, DMA)
14. 分层驱动程序接口 (Layered Driver Interface, LDI)
全存储排序 (Total Store Ordering, TSO)
某些平台具有 PROM 监视器,支持在没有操作系统的情况下调试设备。本节介绍如何使用 SPARC 计算机上的 PROM 来映射设备寄存器,以便可对其进行访问。通常,可以使用 PROM 命令对设备进行充分测试,以确定设备是否正常工作。
有关 x86 引导子系统的说明,请参见 boot(1M) 手册页。
PROM 具有多种用途,包括:
通过打开电源或硬重置 PROM reset 命令初启计算机
提供交互工具来检查和设置内存、设备寄存器以及内存映射
引导 Solaris 系统。
仅打开计算机电源并尝试使用其 PROM 来检查设备寄存器会失败。虽然可能正确安装了设备,但是这些映射特定于 Solaris OS,并且直到 Solaris 内核引导后才会变为活动状态。打开电源之后,PROM 仅映射基本系统设备,如键盘。
使用 sync 命令执行系统故障转储
有关 Open Boot PROM 的完整文档,请参见《Open Boot PROM Toolkit User's Guide》和 monitor(1M) 手册页。本节中的示例引用的是 Sun4U 体系结构。其他体系结构可能要求不同的命令来执行操作。
注 - Open Boot PROM 当前在具有 S 总线或 UPA/PCI 的 Oracle 计算机上使用。Open Boot PROM 使用 "ok" 提示符。在早期计算机上,可能必须键入 `n' 才能获取 "ok" 提示符。
如果 PROM 处于安全模式(security-mode 参数并未设置为无),则可能需要 PROM 口令(在 security-password 参数中设置)。
printenv 命令用于显示所有参数及其值。
使用 help 命令可以获取帮助信息。
可以使用 EMACS 样式的命令行历史记录。使用 Ctrl-N (下一步)和 Ctrl-P (上一步)可以遍历历史记录列表。
Open Boot PROM 使用 Forth 编程语言。Forth 是一种基于栈的语言。必须将参数推送到栈上,然后再运行正确的命令(称为字),并且结果将留在栈上。
要对栈进行编号,请键入其值。
ok 57 ok 68
要在栈上添加两个顶部值,请使用 + 运算符。
ok +
结果会保留在栈上。栈显示有单词 .s。
ok .s bf
缺省基值为十六进制。可以使用单词 hex 和 decimal 来切换基值。
ok decimal ok .s 191
有关更多信息,请参见《Forth User's Guide》。
pwd、cd 和 ls 命令将遍历 PROM 设备树以查找设备。必须首先使用 cd 命令在树中建立一个位置,然后pwd 才能运行。本示例为在 S 总线上带有 cgsix 帧缓存器的 Ultra 1 工作站。
ok cd /
要查看连接到树中的当前节点的设备,请使用 ls 命令。
ok ls f006a064 SUNW,UltraSPARC@0,0 f00598b0 sbus@1f,0 f00592dc counter-timer@1f,3c00 f004eec8 virtual-memory f004e8e8 memory@0,0 f002ca28 aliases f002c9b8 options f002c880 openprom f002c814 chosen f002c7a4 packages
可以使用全节点名称:
ok cd sbus@1f,0 ok ls f006a4e4 cgsix@2,0 f0068194 SUNW,bpp@e,c800000 f0065370 ledma@e,8400010 f006120c espdma@e,8400000 f005a448 SUNW,pll@f,1304000 f005a394 sc@f,1300000 f005a24c zs@f,1000000 f005a174 zs@f,1100000 f005a0c0 eeprom@f,1200000 f0059f8c SUNW,fdtwo@f,1400000 f0059ec4 flashprom@f,0 f0059e34 auxio@f,1900000 f0059d28 SUNW,CS4231@d,c000000
如果不使用前一个示例中的全节点名称,则还可以使用缩写。缩写命令行项类似于以下示例:
ok cd sbus
对于 S 总线设备,名称实际为 device@slot,offset。cgsix 设备位于插槽 2 中,并在偏移 0 处开始。如果该树中显示了 S 总线设备,则表明 PROM 已经识别了此设备。
.properties 命令用于显示设备的 PROM 属性。通过检查这些属性可以确定设备导出的属性。以后可以使用此信息来确保驱动程序查找的是正确的硬件属性。这些属性与可以使用 ddi_getprop(9F) 检索的属性相同。
ok cd cgsix ok .properties character-set ISO8859-1 intr 00000005 00000000 interrupts 00000005 reg 00000002 00000000 01000000 dblbuf 00 00 00 00 vmsize 00 00 00 01 ...
reg 属性用于定义包含以下字段的寄存器说明结构的数组:
uint_t bustype; /* cookie for related bus type*/ uint_t addr; /* address of reg relative to bus */ uint_t size; /* size of this register set */
对于 cgsix 示例,地址为 0。
必须将设备映射到内存中才能进行测试。然后,可以使用 PROM 来验证设备是否正确操作,方法是使用数据传送命令来传送字节、字以及长字。如果可以通过 PROM 操作设备(即使使用受限的方法),则驱动程序也应该可以操作设备。
要设置设备以进行初始测试,请执行以下步骤:
确定设备所在的 S 总线插槽编号。
在本示例中,cgsix 设备位于插槽 2 中。
确定设备使用的物理地址空间中的偏移。
所使用的偏移特定于设备。在 cgsix 示例中,视频内存恰好在偏移 0x800000 处开始。
使用 select-dev 字可选择 S 总线设备以及在其中映射此设备的 map-in 字。
字 select-dev 采用设备路径的字符串作为其参数。map-in 单词接受偏移、插槽编号以及大小作为映射的参数。与偏移一样,字节传送的大小也特定于设备。在 cgsix 示例中,大小设置为 0x100000 字节。
在以下代码示例中,S 总线路径显示为单词 select-dev 的参数,帧缓存器的偏移、插槽编号以及大小值显示为单词 map-in 的参数。请注意 select-dev 参数中起始引号和 / 之间的空格。要使用的虚拟地址保留在栈的顶部。栈通过使用字 .s 进行显示。通过 constant 操作可为该栈分配一个名称。
ok " sbus@1f,0" select-dev ok 800000 2 100000 map-in ok .s ffe98000 ok constant fb
PROM 提供了许多 8 位、16 位以及 32 位操作。通常,c(字符)前缀表示 8 位(一字节)操作;w(字)前缀表示 16 位(二字节)操作;L(长字)前缀表示 32 位(四字节)操作。
后缀 ! 表示写入操作。写入操作用于从栈中取出前两项。第一项是地址,第二项是值。
ok 55 ffe98000 c!
后缀 @ 表示读取操作。读取操作用于从栈中取出地址。
ok ffe98000 c@ ok .s 55
后缀 ? 用于显示值,并且不会影响栈。
ok ffe98000 c? 55
尝试查询设备时,请务必谨慎。如果未正确设置映射,则尝试读取或写入可能会导致错误。为处理这些情况,提供了特殊字。例如,cprobe、wprobe 和 lprobe 会从给定地址进行读取,但是如果此位置不响应,则会返回零;如果此位置响应,则返回非零值。
ok fffa4000 c@ Data Access Error ok fffa4000 cprobe ok .s0 ok ffe98000 cprobe ok .s 0 ffffffffffffffff
使用字 dump 可以显示内存的区域。这会采用 address 和 length,并以字节为单位显示内存区域的内容。
在以下示例中,字 fill 用于使用某种模式填充视频内存。fill 会采用地址、要填充的字节数以及要使用的字节。对于字和长字,请分别使用 wfill 和 Lfill。此填充示例会导致 cgsix 基于传递的字节显示简单模式。
ok " /sbus" select-dev ok 800000 2 100000 map-in ok constant fb ok fb 10000 ff fill ok fb 20000 0 fill ok fb 18000 55 fill ok fb 15000 3 fill ok fb 10000 5 fillok fb 5000 f9 fill