ASPI编程概述
1. ASPI与OS/2 2.x
1.1 设备驱动架构
OS/2 2.x的设备驱动架构分为几个基本层。设备管理器驱动(DMDs)接收来自文件系统和其他设备驱动的请求,这些请求会传递给适配器设备驱动(ADD),ADD再向主机适配器发送相应命令。
1.2 ASPI在OS/2 2.x中的实现
ASPI在OS/2 2.x中是一个转换层,实现为设备驱动(os2aspi.dmd)。应用程序可以向任何安装了ADD的SCSI适配器发送SCSI请求块(SRB)。不过,由于OS2ASPI无法直接控制主机适配器,所以不能设置主机适配器参数。
1.3 目标分配
在OS/2 2.x中,由ADD控制的目标必须分配给单个DMD。例如,系统启动时,os2dasd.dmd通常是第一个加载的设备管理器,它会自动搜索所有可用的硬盘并永久分配给文件系统使用。其他DMD通常也会对它们认为应由自己控制的目标进行类似操作。
防止DMD分配特定目标的标准方法是在处理该设备的ADD上使用命令行开关。以下是具体示例:
- 如果你正在为一个在查询数据中返回设备类型0(DASD)的磁光驱动器(AHA - 1540上的目标6)编写ASPI应用程序,必须确保阻止OS2DASD访问它:
BASEDEV=AHA154X.ADD /A:0 /!DM:6
- 如果你正在为一个也可能由设备驱动通过os2scsi.dmd控制的设备(AHA - 1540上的目标6)编写ASPI应用程序,可以阻止OS2SCSI访问它:
BASEDEV=AHA154X.ADD /A:0 /!SM:6
目前,只有os2dasd.dmd和os2scsi.dmd可以通过这种方式控制,因为它们是IBM的ADD规范中提到的仅有的DMD。要了解OS/2 2.1附带的ADD支持的命令行开关的完整说明,请参考SCSI的在线帮助。
1.4 目标分配规则
当前的ASPI规范没有提供分配目标的方法,os2aspi.dmd也没有可与当前ADD一起使用的命令行开关。每个SRB的目标将在命令基础上进行分配和释放,直到发送第一个执行I/O SRB。此时,目标将永久分配给os2aspi.dmd,其他DMD将不再有权访问该目标。
2. OS/2 2.x示例代码
2.1 ASPIAPP
ASPIAPP是一个简单的程序,用于扫描SCSI总线并显示系统中适配器上找到的任何目标的信息。这是一个单线程、基于字符的应用程序,旨在展示如何使用ASPI。
2.2 ASPIDRV
ASPIDRV是一个简单的设备驱动,它将ASPIAPP的请求传递给os2aspi.dmd,在传递之前会将任何虚拟地址转换为物理地址。该驱动用于处理不需要散列收集列表的单线程小请求。如果你要传输大块数据,可能需要将缓冲区的虚拟地址转换为可作为散列收集列表使用的页表。
3. SCSI请求块(SRB)
3.1 SRB结构
SCSI请求块(SRB)包含要由ASPI管理器执行的命令,供驱动程序和应用程序使用。SRB由SRB头和依赖于命令代码的附加字段组成,所有请求块都有一个8字节的头,具体结构如下表所示:
| Offset | # Bytes | Description | R/W |
| ---- | ---- | ---- | ---- |
| 00h (00) | 01h (01) | Command Code | W |
| 01h (01) | 01h (01) | Status | R |
| 02h (02) | 01h (01) | Host Adapter Number | W |
| 03h (03) | 01h (01) | SCSI Request Flags | W |
| 04h (04) | 04h (04) | Reserved for Expansion = 0 | — |
3.2 SRB头各字段说明
-
Command Code
:用于指示正在访问的ASPI服务,有效ASPI命令代码如下表所示:
| Command Code | Description |
| ---- | ---- |
| 00h | Host Adapter Inquiry |
| 01h | Get Device Type |
| 02h | Execute SCSI I/O Command |
| 03h | Abort SCSI I/O Command |
| 04h | Reset SCSI Device |
| 05h | Set Host Adapter Parameters |
| 06h - 7Fh | Reserved for Future Expansion |
| 80h - FFh | Reserved for Vendor Unique | -
Status
:用于发布命令的状态,ASPI状态字节如下表所示:
| Status Byte | Description |
| ---- | ---- |
| 00h | SCSI Request In Progress |
| 01h | SCSI Request Completed Without Error |
| 02h | SCSI Request Aborted By Host |
| 04h | SCSI Request Completed With Error |
| 80h | Invalid SCSI Request |
| 81h | Invalid Host Adapter Number |
| 82h | SCSI Device Not Installed | - Host Adapter Number :指定请求所针对的已安装主机适配器,主机适配器编号从0开始由SCSI管理器层分配。
- SCSI Request Flags :该字段的定义因命令代码而异。
- Reserved for Expansion :头的最后4个字节保留,必须为0。
4. 各ASPI命令代码详解
4.1 ASPI Command Code = 0: Host Adapter Inquiry
此命令用于获取已安装主机适配器硬件的信息,包括已安装的主机适配器数量。可以指定主机适配器0来获取主机适配器的数量,如果需要更多信息,可以为每个单独的主机适配器发出此命令。状态字节总是返回非零状态,状态为SCSI Request Completed Without Error (01h)表示其余字段有效,状态为Invalid Host Adapter Number (81h)表示指定的主机适配器未安装。具体结构如下表所示:
| Offset | # Bytes | Description | R/W |
| ---- | ---- | ---- | ---- |
| 00h (00) | 01h (01) | Command Code = 0 | W |
| 01h (01) | 01h (01) | Status | R |
| 02h (02) | 01h (01) | Host Adapter Number | W |
| 03h (03) | 01h (01) | SCSI Request Flags | W |
| 04h (04) | 04h (04) | Reserved for Expansion = 0 | — |
| 08h (08) | 01h (01) | Number of Host Adapters | R |
| 09h (09) | 01h (01) | Target ID of Host Adapter | R |
| 0Ah (10) | 10h (16) | SCSI Manager ID | R |
| 1Ah (26) | 10h (16) | Host Adapter ID | R |
| 2Ah (42) | 10h (16) | Host Adapter Unique Parameters | R |
4.2 ASPI Command Code = 1: Get Device Type
此命令总是返回非零状态。状态为SCSI Request Completed Without Error (01h)表示指定的设备已安装且外围设备类型字段有效,状态为SCSI Device Not Installed Error (82h)表示外围设备类型字段无效。该命令供各种驱动在初始化期间识别它们需要支持的目标。例如,CD - ROM驱动可以扫描每个已安装主机适配器上的每个目标/LUN,查找与CD - ROM设备对应的设备类型。具体结构如下表所示:
| Offset | # Bytes | Description | R/W |
| ---- | ---- | ---- | ---- |
| 00h (00) | 01h (01) | Command Code = 1 | W |
| 01h (01) | 01h (01) | Status | R |
| 02h (02) | 01h (01) | Host Adapter Number | W |
| 03h (03) | 01h (01) | SCSI Request Flags | W |
| 04h (04) | 04h (04) | Reserved for Expansion = 0 | — |
| 08h (08) | 01h (01) | Target ID | W |
| 09h (09) | 01h (01) | LUN | W |
| 0Ah (10) | 01h (01) | Peripheral Device Type of Target/LUN | R |
4.3 ASPI Command Code = 2: Execute SCSI I/O Command
此命令通常返回状态为0,表示请求已成功排队。可以通过轮询非零状态或使用ASPI命令发布部分中的Post Routine Address字段来确定命令是否完成。要注意,如果使用轮询,必须启用中断。具体结构如下表所示:
| Offset | # Bytes | Description | R/W |
| ---- | ---- | ---- | ---- |
| 00h (00) | 01h (01) | Command Code = 2 | W |
| 01h (01) | 01h (01) | Status | R |
| 02h (02) | 01h (01) | Host Adapter Number | W |
| 03h (03) | 01h (01) | SCSI Request Flags | W |
| 04h (04) | 02h (02) | Length of Scatter/Gather List | W |
| 06h (06) | 02h (02) | Reserved for Expansion = 0 | — |
| 08h (08) | 01h (01) | Target ID | W |
| 09h (09) | 01h (01) | LUN | W |
| 0Ah (10) | 04h (04) | Data Allocation Length | W |
| 0Eh (14) | 01h (01) | Sense Allocation Length (N) | W |
| 0Fh (15) | 04h (04) | Data Buffer Pointer | W |
| 13h (19) | 04h (04) | SRB Link Pointer | W |
| 17h (23) | 01h (01) | SCSI CDB Length (M) | W |
| 18h (24) | 01h (01) | Host Adapter Status | R |
| 19h (25) | 01h (01) | Target Status | R |
| 1Ah (26) | 02h (02) | Real Mode Post Routine Offset
| W |
| 1Ch (28) | 02h (02) | Real Mode Post Routine CS
| W |
| 1Eh (30) | 02h (02) | Real Mode Post Routine DS* | W |
| 20h (32) | 02h (02) | Protected Mode Post Routine Offset | W |
| 22h (34) | 02h (02) | Protected Mode Post Routine CS | W |
| 24h (36) | 02h (02) | Protected Mode Post Routine DS | W |
| 26h (38) | 04h (04) | Physical Address of SRB | W |
| 2Ah (42) | 16h (22) | Reserved for ASPI Workspace | — |
| 40h (64) | M | SCSI Command Descriptor Block (CDB) | W |
| 40h + M | N | Sense Allocation Area | R |
注:*仅用于OS/2 1.x,在OS/2 2.x下不使用这些字段。
4.4 SCSI请求标志字节定义
SCSI请求标志字节的定义如下:
| 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
| ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- |
| Rsvd | Rsvd | SGE | Direction Bit | Rsvd | Link | Post |
- Post :指定是否启用发布(位0 = 1启用,位0 = 0禁用)。
- Link :指定是否启用链接(位1 = 1启用,位1 = 0禁用)。
- Direction Bits :指定传输方向:
- 00:传输方向由SCSI命令确定,不检查长度。
- 01:从SCSI目标传输到主机,检查长度。
- 10:从主机传输到SCSI目标,检查长度。
- 11:无数据传输。
- Scatter/Gather Enable (SGE) :指定是否启用散列收集(位5 = 1启用,位5 = 0禁用)。
4.5 其他字段说明
- Target ID和LUN :用于指定I/O涉及的外围设备。
- Data Allocation Length :指示要传输的字节数。如果要执行的SCSI命令不传输数据(如倒带、启动单元等),则数据分配长度必须设置为0。
- Length of Scatter/Gather List :仅当标志中的散列收集启用位设置时有效,包含Data Buffer Pointer字段指向的数组中的描述符数量。
- Sense Allocation Length :以字节为单位指示为感应数据在SRB末尾分配的字节数。如果在SCSI命令结束时出现检查条件,将自动生成请求感应。
- Data Buffer Pointer :是I/O数据缓冲区的指针。当启用散列收集时,该字段是散列收集列表的物理指针。散列收集列表由一个或多个以下格式的描述符组成:
DWORD Buffer Pointer
DWORD Buffer Size
- SRB Link Pointer :是链中下一个SRB的指针。
- SCSI CDB Length :确定SCSI命令描述符块(CDB)的长度(以字节为单位)。
- Host Adapter Status :用于报告主机适配器状态:
- 00h:主机适配器未检测到任何错误
- 11h:选择超时
- 12h:数据溢出/不足
- 13h:意外总线空闲
- 14h:目标总线相位序列失败
- Target Status :用于报告目标的SCSI状态,包括:
- 00h:无目标状态
- 02h:检查状态(感应数据在感应分配区域中)
- 08h:指定的目标/LUN繁忙
- 18h:保留冲突
注:主机适配器状态和目标状态仅在状态字节为2或4时有效。
4.6 SCSI命令链接
ASPI提供了使用SCSI链接来保证多个命令顺序执行的能力。但使用此功能要求涉及的目标支持SCSI链接。
使用SCSI链接时,需要使用SRB链接指针构建一个SRB链,除链中的最后一个SRB外,所有SRB的SCSI请求标志字节中的链接位都应设置。当SCSI目标返回表示链接命令完成时,将立即处理下一个SRB并发送相应的CDB。使用SCSI链接时,要确保SCSI CDB中的链接标志与SCSI请求标志中的链接位一致,不一致可能导致不可预测的结果。例如,设置CDB进行链接但未设置链接位可能会导致使用随机地址作为下一个SRB指针。
任何来自目标的链接命令错误都会中断链。如果使用无标签的链接(如SCSI中定义的那样),在链完成之前,链中的任何元素可能都不会进行发布。如果在每个SRB的SCSI请求标志字节中设置了发布位,则每个SRB的发布例程将被调用。不过,强烈建议不要使用SCSI链接,因为许多SCSI目标和SCSI主机适配器不支持SCSI链接,可能无法与你的ASPI模块一起工作。
4.7 ASPI命令发布
发布是指SCSI管理器根据SRB中指定的内容对发布例程进行远调用。驱动程序可以像使用硬件中断一样使用发布。发布例程在OS/2中具有与硬件中断服务例程相同的权限和限制。发布是可选的,但在OS/2中几乎总是应该使用。要使用发布,必须在SCSI请求标志中设置发布位。发布例程在请求的I/O完成时被调用,完成的特定SRB由堆栈上的4字节SRB指针指示,SRB中指定的发布例程的DS也会传递到堆栈。
发布例程将在启用中断的情况下被调用,假设发布例程会保留所有寄存器。以下是一个发布例程的示例代码:
ASPI_Post proc far
push bp ;Use bp as a reference
mov bp,sp
pusha ;Save all registers
push es ;Save ES
mov bx,[bp+6] ;Load DS of POST routine
mov ax,[bp+10] ;Physical address of SRB—>AX:BX
mov ax,[bp+8]
...
pop es ;Restore registers
popa
pop ds
pop bp
retf
ASPI_Post endp
当首次进入发布例程时,堆栈如下所示:
Top of Stack [SP+0] —> Return Address (Offset)
[SP+2] —> Return Address (Segment)
[SP+4] —> SRB Pointer (Offset)
[SP+6] —> SRB Pointer (Segment)
...
...
...
在发布例程中可以发出除中止命令之外的任何ASPI命令,发布例程应尽快完成操作。
4.8 ASPI Command Code = 3: Abort SCSI I/O Request
此命令用于请求中止一个SRB。如果驱动程序希望对未完成的I/O请求进行超时处理,应发出此命令。但中止命令的成功与否无法保证。具体结构如下表所示:
| Offset | # Bytes | Description | R/W |
| ---- | ---- | ---- | ---- |
| 00h (00) | 01h (01) | Command Code = 3 | W |
| 01h (01) | 01h (01) | Status | R |
| 02h (02) | 01h (01) | Host Adapter Number | W |
| 03h (03) | 01h (01) | SCSI Request Flags | W |
| 04h (04) | 04h (04) | Reserved for Expansion = 0 | — |
| 08h (08) | 04h (04) | Physical SRB Pointer | W |
此命令总是返回SCSI Request Completed Without Error,但中止操作的实际失败或成功由指定SRB最终返回的状态指示。SCSI请求标志字段目前对此命令未定义,应置零。SRB Pointer to Abort字段包含要中止的SRB的指针。注意,不应在发布例程中发出中止命令。
4.9 ASPI Command Code = 4: Reset SCSI Device
此命令用于重置特定的SCSI目标。传递的结构与执行SCSI I/O SRB几乎相同,但有些字段未使用。具体的结构如下表所示:
| Offset | # Bytes | Description | R/W |
| ---- | ---- | ---- | ---- |
| 00h (00) | 01h (01) | Command Code = 4 | W |
| 01h (01) | 01h (01) | Status | R |
| 02h (02) | 01h (01) | Host Adapter Number | W |
| 03h (03) | 01h (01) | SCSI Request Flags | W |
| 04h (04) | 04h (04) | Reserved for Expansion = 0 | — |
| 08h (08) | 01h (01) | Target ID | W |
| 09h (09) | 01h (01) | LUN | W |
| 0Ah (10) | 0Eh (14) | Reserved | — |
| 18h (24) | 01h (01) | Host Adapter Status | R |
| 19h (25) | 01h (01) | Target Status | R |
| 1Ah (26) | 02h (02) | Real Mode Post Routine Offset
| W |
| 1Ch (28) | 02h (02) | Real Mode Post Routine CS
| W |
| 1Eh (30) | 02h (02) | Real Mode Post Routine DS* | W |
| 20h (32) | 02h (02) | Protected Mode Post Routine Offset | W |
| 22h (34) | 02h (02) | Protected Mode Post Routine CS | W |
| 24h (36) | 02h (02) | Protected Mode Post Routine DS | W |
| 26h (38) | 16h (22) | Reserved for ASPI Workspace | — |
注:*仅用于OS/2 1.x,在OS/2 2.x下不使用这些字段。
综上所述,本文详细介绍了ASPI编程在OS/2 2.x环境下的相关内容,包括设备驱动架构、目标分配、示例代码、SCSI请求块结构以及各种ASPI命令代码的使用和相关注意事项。通过这些内容,开发者可以更好地理解和运用ASPI进行SCSI设备的编程开发。
4.10 各ASPI命令代码总结
为了更清晰地了解各个ASPI命令代码的功能和使用场景,下面对前面介绍的命令代码进行总结:
| Command Code | 功能描述 | 使用场景 |
| ---- | ---- | ---- |
| 00h | 获取已安装主机适配器硬件的信息,包括数量、ID等 | 初始化时获取系统中主机适配器的基本信息 |
| 01h | 获取指定目标的外围设备类型 | 驱动初始化时识别需要支持的目标设备类型 |
| 02h | 执行SCSI I/O命令 | 进行数据传输、设备操作等I/O任务 |
| 03h | 中止一个SRB | 对未完成的I/O请求进行超时处理 |
| 04h | 重置特定的SCSI目标 | 当设备出现异常时进行重置操作 |
| 05h | 设置主机适配器参数 | 目前在OS/2 2.x中无法使用 |
| 06h - 7Fh | 保留用于未来扩展 | - |
| 80h - FFh | 保留用于厂商特定用途 | - |
4.11 ASPI编程流程总结
下面通过一个mermaid流程图来展示ASPI编程的基本流程:
graph LR
classDef startend fill:#F5EBFF,stroke:#BE8FED,stroke-width:2px
classDef process fill:#E5F6FF,stroke:#73A6FF,stroke-width:2px
classDef decision fill:#FFF6CC,stroke:#FFBC52,stroke-width:2px
A([开始]):::startend --> B(初始化):::process
B --> C{选择命令代码}:::decision
C -->|00h| D(主机适配器查询):::process
C -->|01h| E(获取设备类型):::process
C -->|02h| F(执行SCSI I/O命令):::process
C -->|03h| G(中止SCSI I/O请求):::process
C -->|04h| H(重置SCSI设备):::process
D --> I(处理结果):::process
E --> I
F --> I
G --> I
H --> I
I --> J{是否继续}:::decision
J -->|是| C
J -->|否| K([结束]):::startend
这个流程图展示了ASPI编程的基本步骤:
1. 开始编程后,首先进行初始化操作。
2. 选择合适的ASPI命令代码。
3. 根据选择的命令代码执行相应的操作。
4. 处理操作结果。
5. 判断是否需要继续执行其他命令,如果是则回到选择命令代码的步骤,否则结束编程。
5. 注意事项
5.1 目标分配注意事项
- 在使用ASPI控制可能被DMD分配的设备时,要通过ADD的命令行开关来防止DMD访问特定目标。例如,对于磁光驱动器和可能由os2scsi.dmd控制的设备,分别使用相应的命令行开关来阻止os2dasd.dmd和os2scsi.dmd访问。
- 目前只有os2dasd.dmd和os2scsi.dmd可以通过这种方式控制,因为它们是IBM的ADD规范中提到的仅有的DMD。
5.2 SCSI链接注意事项
- 使用SCSI链接要求涉及的目标支持SCSI链接,许多SCSI目标和主机适配器不支持该功能,因此强烈建议不要使用。
- 使用SCSI链接时,要确保SCSI CDB中的链接标志与SCSI请求标志中的链接位一致,否则可能导致不可预测的结果。
5.3 发布例程注意事项
- 在发布例程中可以发出除中止命令之外的任何ASPI命令,发布例程应尽快完成操作,以避免影响系统性能。
- 发布例程会在启用中断的情况下被调用,并且假设发布例程会保留所有寄存器。
5.4 中止命令注意事项
- 中止命令的成功与否无法保证,并且不应在发布例程中发出中止命令。
6. 总结
本文全面介绍了ASPI编程在OS/2 2.x环境下的相关知识,包括ASPI与OS/2 2.x的设备驱动架构、目标分配规则、示例代码、SCSI请求块结构以及各种ASPI命令代码的功能和使用方法。通过详细的表格和代码示例,帮助开发者更好地理解和运用ASPI进行SCSI设备的编程开发。
在实际应用中,开发者需要根据具体的需求选择合适的ASPI命令代码,并注意目标分配、SCSI链接、发布例程和中止命令等方面的注意事项,以确保程序的稳定性和可靠性。同时,参考提供的示例代码和流程图,可以更高效地完成ASPI编程任务。
希望本文对从事ASPI编程的开发者有所帮助,能够在实际项目中顺利运用这些知识进行SCSI设备的开发和调试。
超级会员免费看
28

被折叠的 条评论
为什么被折叠?



