SPB I/O 请求

系统提供的 CTL_CODE 宏(如 定义 I/O 控制代码中所述)用于在 Spb.h 中定义IOCTL_SPB_* 控制代码。

IOCTL_SPB_EXECUTE_SEQUENCE控制代码

IOCTL_SPB_EXECUTE_SEQUENCE I/O 控制代码允许客户端 (SPB 控制器驱动程序的外围驱动程序) 执行一系列传输, (读取和写入) 作为一个 I/O 请求的原子操作。 总线上的指定设备是序列中所有传输的目标。

通过将固定长度传输序列指定为单个原子操作,IOCTL_SPB_EXECUTE_SEQUENCE I/O 控制请求使控制器驱动程序能够优化 I/O 传输并提高性能。

客户端将此 I/O 控制请求发送到目标设备的文件对象。

SPB 控制器驱动程序注册 EvtSpbControllerIoSequence 回调函数,以执行 I/O 传输序列的总线传输。 SPB 框架扩展 (SpbCx) 调用此函数,将IOCTL_SPB_EXECUTE_SEQUENCE请求传递给 SPB 控制器驱动程序进行处理。

IOCTL_SPB_EXECUTE_SEQUENCE输入缓冲区

输入缓冲区是一个SPB_TRANSFER_LIST结构,其中包含指向客户端数据缓冲区的指针列表。 此列表包含 I/O 传输序列中每个传输 (读取或写入) 的数据缓冲区。

IOCTL_SPB_EXECUTE_SEQUENCE输入缓冲区长度

SPB_TRANSFER_LIST 结构的大小。

IOCTL_SPB_EXECUTE_SEQUENCE状态块

如果操作成功,控制器驱动程序会将 Status 成员设置为 STATUS_SUCCESS,并将 Information 成员设置为序列期间传输的总字节数。

此操作可能会因各种原因而失败,包括资源不足、客户端输入无效和设备故障。

如果控制器驱动程序开始处理 I/O 请求,但在序列 (的某个传输期间发生错误,例如,目标设备向 NACK 发出信号以拒绝传输) ,则控制器驱动程序将中止序列中的剩余传输。 然后,驱动程序将完成状态设置为STATUS_SUCCESS,将 Information 成员设置为错误发生前成功传输的字节数,并完成请求。

IOCTL_SPB_FULL_DUPLEX控制代码

客户端 (外围驱动程序) 使用IOCTL_SPB_FULL_DUPLEX控制代码来请求全双工 I/O 操作。 可以同时读取和写入数据的总线(例如 SPI)的控制器支持全双工 I/O 操作。 系统提供的 CTL_CODE 宏(如 定义 I/O 控制代码中所述)用于定义IOCTL_SPB_FULL_DUPLEX,如下所示。

总线上设备的用户模式驱动程序或内核模式驱动程序将此 I/O 控制请求发送到目标设备的文件对象。

此 IOCTL 仅受可以同时读取和写入数据的总线(如 SPI)的 SPB 控制器驱动程序支持。

全双工传输的写入和读取缓冲区由 SPB_TRANSFER_LIST 结构描述。 此结构必须使用以下格式:

  • SPB_TRANSFER_LIST_ENTRY 结构的数组正好包含两个元素。 第一个元素描述方向 = SpbTransferDirectionToDevice) (写入缓冲区。 第二个元素描述读取缓冲区 (Direction = SpbTransferDirectionFromDevice) 。

  • 两个SPB_TRANSFER_LIST_ENTRY结构的 DelayInUs 成员必须为零。 写入缓冲区和读取缓冲区的缓冲区格式可以是以下任意一种:

    • SpbTransferBufferFormatSimple
    • SpbTransferBufferFormatList
    • SpbTransferBufferFormatSimpleNonPaged
    • SpbTransferBufferFormatMdl

    前面列表中的最后两种格式只能由内核模式客户端使用。 写入缓冲区和读取缓冲区的格式不需要相同。 有关这些缓冲区格式的详细信息,请参阅 SPB_TRANSFER_BUFFER_FORMAT。

成功的操作可能会将 Information 成员设置为小于写入缓冲区和读取缓冲区大小之和的值,如果取消请求,或者操作无法将写入缓冲区的全部内容写入设备,或者使用从设备读取的数据完全填充读取缓冲区,则可能会发生这种情况。

写入和读取缓冲区大小不需要相同。 如果写入缓冲区大于读取缓冲区,则操作在读取缓冲区已满后继续从写入缓冲区写入数据。 如果读取缓冲区大于写入缓冲区,则操作在清空写入缓冲区后继续填充读取缓冲区。

如果 SPB 控制器驱动程序注册 EvtSpbControllerIoOther 回调函数,SPB 框架扩展 (SpbCx) 调用此函数以将IOCTL_SPB_FULL_DUPLEX请求传递给 SPB 控制器驱动程序进行处理。 SpbCx 不对IOCTL_SPB_FULL_DUPLEX请求执行任何参数检查、传输列表验证或其他处理。

有关 SPB 控制器驱动程序如何实现对此 IOCTL 的支持的详细信息,请参阅处理IOCTL_SPB_FULL_DUPLEX请求。

IOCTL_SPB_FULL_DUPLEX输入缓冲区

指向SPB_TRANSFER_LIST 结构的指针,该结构包含指向客户端输入和输出数据缓冲区的指针。 此结构包含正好包含两个元素的 Transfers 数组。 第一个元素描述包含要写入设备的数据的缓冲区。 第二个元素描述用于保存从设备读取的数据的缓冲区。 有关 SPB 控制器驱动程序如何 (IOCTL) 使用 SPB_TRANSFER_LIST 结构描述缓冲区的请求实现自定义 I/O 控件的详细信息,请参阅使用自定义 IOCTL 的SPB_TRANSFER_LIST结构。

IOCTL_SPB_FULL_DUPLEX输入缓冲区长度

SPB_TRANSFER_LIST 结构的大小。

IOCTL_SPB_FULL_DUPLEX状态块

如果操作成功,控制器驱动程序会将 Status 成员设置为 STATUS_SUCCESS,并将 Information 成员设置为在全双工操作期间读取 (字节加上写入) 字节的字节总数。

此操作可能会因各种原因而失败,包括资源不足、客户端输入无效和设备故障。

IOCTL_SPB_LOCK_CONNECTION控制代码

IOCTL_SPB_LOCK_CONNECTION控制代码由客户端 (外围驱动程序) 用于获取与另一个客户端共享的 SPB 连接的目标设备上的连接锁。 当客户端持有连接锁时,此客户端对设备具有独占访问权限。 系统提供的 CTL_CODE 宏(如 定义 I/O 控制代码中所述)用于定义IOCTL_SPB_LOCK_CONNECTION,如下所示。

IOCTL_SPB_LOCK_CONNECTION和IOCTL_SPB_UNLOCK_CONNECTION请求获取并释放连接到简单外围总线的目标设备上的连接锁。 大多数客户端不使用这些 I/O 控制请求。 仅当两个客户端共享对同一目标设备的访问权限时,才使用这些请求。 有关详细信息,请参阅 SPB 连接锁。

两个客户端可以打开与同一目标设备的单独逻辑连接,并在任一客户端需要对设备进行独占访问时使用连接锁。 当一个客户端持有锁时,第二个客户端对设备的 I/O 请求将自动推迟,直到第一个客户端释放锁定。

客户端可以同时在目标设备上保留连接锁,在 SPB 控制器上同时保留控制器锁。 IOCTL_SPB_LOCK_CONTROLLER和IOCTL_SPB_UNLOCK_CONTROLLER请求获取并释放控制器锁。 客户端必须在获取控制器锁之前获取连接锁,并且必须在释放连接锁之前释放控制器锁。 客户端使用控制器锁执行一组有序的总线传输, (读取和写入操作) 作为单个原子总线操作。 有关详细信息,请参阅 I/O 传输序列。

如果在设备上锁定连接时将IRP_MJ_CLEANUP请求发送到目标设备,则连接锁会自动终止。 当客户端关闭对设备的文件句柄时,会将清理请求发送到目标设备。

IOCTL_SPB_LOCK_CONNECTION状态块

如果操作成功,则 Status 成员设置为STATUS_SUCCESS。

如果操作失败,则 Status 成员将设置为相应的错误状态代码。

如果客户端已持有目标设备上的连接锁或 SPB 控制器上的控制器锁,此操作将失败,状态 = STATUS_INVALID_DEVICE_REQUEST。 此操作可能会由于其他原因而失败,包括资源不足、客户端输入无效和设备故障。

IOCTL_SPB_LOCK_CONTROLLER控制代码

客户端 (外围驱动程序) 使用IOCTL_SPB_LOCK_CONTROLLER控制代码来锁定 SPB 控制器。 锁定控制器时,客户端以独占方式使用总线来访问锁的指定目标设备。 系统提供的CTL_CODE宏(如 定义 I/O 控制代码中所述)用于定义IOCTL_SPB_LOCK_CONTROLLER,如下所示。

为了获得专用的总线来访问目标设备,客户端 (外围驱动程序) 将此 IOCTL 发送到目标的文件对象。 完成此 IOCTL 后,控制器将锁定,所有 I/O 传输 (总线上的读取或写入) 访问指定目标。 在传输之间,控制器保持目标设备处于选中状态,但停止时钟。

在客户端发送解锁控制器IOCTL_SPB_UNLOCK_CONTROLLER请求之前,控制器一直处于锁定状态。 当客户端与目标设备的传输序列完成时,客户端必须解锁控制器,以便控制器可以处理总线上其他目标的 I/O 请求。

如果在目标设备上锁定控制器时将IRP_MJ_CLEANUP请求发送到目标设备,则锁会自动终止。 当客户端关闭目标句柄时,会将清理请求发送到目标。

SPB 控制器不需要支持IOCTL_SPB_LOCK_CONTROLLER和IOCTL_SPB_UNLOCK_CONTROLLER请求,并且外围设备驱动程序不应假定它们受支持。

如果 SPB 控制器驱动程序注册 EvtSpbControllerLock 回调函数,SPB 框架扩展 (SpbCx) 调用此函数以将IOCTL_SPB_LOCK_CONTROLLER请求传递给 SPB 控制器驱动程序进行处理。

IOCTL_SPB_LOCK_CONTROLLER状态块

如果操作成功,则 Status 成员设置为STATUS_SUCCESS。 此 IOCTL 可能出于多种原因返回错误状态,包括无法将控制器配置为在独占访问模式下运行。 在此模式下,控制器会选择目标设备,以便它是总线上所有 I/O 传输的独占目标。 控制器将一直处于此模式,直到解锁为止。

IOCTL_SPB_UNLOCK_CONNECTION控制代码

IOCTL_SPB_UNLOCK_CONNECTION I/O 控制代码由客户端 (外围驱动程序) 用于释放与另一个客户端共享的 SPB 连接的目标设备上的连接锁。 客户端之前发送了IOCTL_SPB_LOCK_CONNECTION请求来获取对设备的独占访问权限。

IOCTL_SPB_LOCK_CONNECTION和IOCTL_SPB_UNLOCK_CONNECTION请求获取并释放连接到简单外围总线的目标设备上的连接锁。 大多数客户端不使用这些 I/O 控制请求。 仅当两个客户端共享对同一目标设备的访问权限时,才使用这些请求。 有关详细信息,请参阅 SPB 连接锁。

在客户端 (外围驱动程序) 向总线上的目标设备发送IOCTL_SPB_LOCK_CONNECTION请求并成功完成请求后,连接将保持锁定状态,直到客户端发送IOCTL_SPB_UNLOCK_CONNECTION请求来解锁连接。

当客户端不再需要对设备进行独占访问时,客户端发送IOCTL_SPB_UNLOCK_CONNECTION请求以释放目标设备的连接锁。 必须解锁连接,以便其他客户端可以访问设备。

IOCTL_SPB_UNLOCK_CONNECTION状态块

如果操作成功,则 Status 成员设置为STATUS_SUCCESS。

如果操作失败,则 Status 成员将设置为相应的错误状态代码。 如果客户端未在目标设备上保留连接锁,或者客户端仍持有 SPB 控制器上的连接锁,则此操作将失败,状态 = STATUS_INVALID_DEVICE_REQUEST。 此操作可能会由于其他原因而失败,包括资源不足、客户端输入无效和设备故障。

IOCTL_SPB_UNLOCK_CONTROLLER控制代码

IOCTL_SPB_UNLOCK_CONTROLLER I/O 控制代码由客户端 (外围驱动程序) 用于解锁 SPB 控制器。 客户端之前锁定了控制器,以独占使用总线来访问总线上的目标设备。

客户端 (外围驱动程序) 将IOCTL_SPB_LOCK_CONTROLLER I/O 控制请求发送到总线上的目标设备后,控制器将保持锁定状态,直到客户端发送IOCTL_SPB_UNLOCK_CONTROLLER I/O 控制请求来解锁控制器。 客户端将这些 I/O 控制请求发送到目标设备的文件对象。

客户端在总线上完成一系列传输并希望释放目标设备时,会发送IOCTL_SPB_UNLOCK_CONTROLLER请求。 控制器必须解锁,以便它可以处理总线上其他目标的 I/O 请求。

SPB 控制器不需要支持IOCTL_SPB_LOCK_CONTROLLER和IOCTL_SPB_UNLOCK_CONTROLLER请求,并且外围设备驱动程序不应假定它们受支持。

SPB 框架扩展 (SpbCx) 调用 SPB 控制器驱动程序的可选 EvtSpbControllerUnlock 回调函数,以将IOCTL_SPB_LOCK_CONTROLLER请求传递给 SPB 控制器驱动程序进行处理。

IOCTL_SPB_UNLOCK_CONTROLLER状态块

如果操作成功,则 Status 成员设置为STATUS_SUCCESS。

仅当此 IOCTL 由未锁定控制器以独占访问指定目标的客户端发送时,此 IOCTL 才会失败。