编写 s390 通道设备驱动程序

作者:

Cornelia Huck

简介

本文档描述了用于驱动基于 s390 的通道连接 I/O 设备的设备驱动程序可用的接口。这包括与硬件交互的接口以及与通用驱动程序核心交互的接口。这些接口由 s390 通用 I/O 层提供。

本文档假设读者熟悉与 s390 通道 I/O 架构相关的技术术语。有关此架构的描述,请参阅 “z/Architecture: Principles of Operation”,IBM 出版物编号 SA22-7832。

虽然 s390 系统上的大多数 I/O 设备通常通过此处描述的通道 I/O 机制驱动,但还有其他各种方法(如 diag 接口)。这些不在本文档的范围之内。

s390 通用 I/O 层还提供对一些不被严格认为是 I/O 设备的设备的访问。它们也在这里考虑,尽管它们不是本文档的重点。

在内核源代码中的 S/390 驱动程序模型接口 下也可以找到一些其他信息。

css 总线

css 总线包含系统上可用的子通道。它们分为以下几个类别

  • 标准 I/O 子通道,供系统使用。它们在 ccw 总线上有一个子设备,如下所述。

  • 绑定到 vfio-ccw 驱动程序的 I/O 子通道。请参阅 vfio-ccw: 基本基础设施

  • 消息子通道。目前不存在 Linux 驱动程序。

  • CHSC 子通道(最多一个)。chsc 子通道驱动程序可用于发送异步 chsc 命令。

  • eADM 子通道。用于与存储级内存通信。

ccw 总线

ccw 总线通常包含 s390 系统可用的大部分设备。ccw 总线以用于寻址其设备的基本命令结构通道命令字 (ccw) 命名,包含所谓的通道连接设备。它们通过在 css 总线上可见的 I/O 子通道寻址。但是,通道连接设备的设备驱动程序永远不会直接与子通道交互,而只能通过 ccw 总线上的 I/O 设备(ccw 设备)进行交互。

通道连接设备的 I/O 功能

一些硬件结构已被转换为 C 结构,供通用 I/O 层和设备驱动程序使用。有关此处表示的硬件结构的更多信息,请查阅《操作原理》。

struct ccw1

通道命令字

定义:

struct ccw1 {
    __u8 cmd_code;
    __u8 flags;
    __u16 count;
    dma32_t cda;
};

成员

cmd_code

命令代码

flags

标志,如 IDA 寻址等。

count

字节计数

cda

数据地址

描述

ccw 是构建通道程序的基本结构,这些通道程序执行与设备或控制单元的操作。仅支持格式 1 通道命令字。

struct ccw0

通道命令字

定义:

struct ccw0 {
    __u8 cmd_code;
    __u32 cda : 24;
    __u8 flags;
    __u8 reserved;
    __u16 count;
};

成员

cmd_code

命令代码

cda

数据地址

flags

标志,如 IDA 寻址等。

保留

将被忽略

count

字节计数

描述

格式 0 ccw 结构。

struct erw

扩展报告字

定义:

struct erw {
    __u32 res0  : 3;
    __u32 auth  : 1;
    __u32 pvrf  : 1;
    __u32 cpt   : 1;
    __u32 fsavf : 1;
    __u32 cons  : 1;
    __u32 scavf : 1;
    __u32 fsaf  : 1;
    __u32 scnt  : 6;
    __u32 res16 : 16;
};

成员

res0

保留

auth

授权检查

pvrf

需要路径验证标志

cpt

通道路径超时

fsavf

失败存储地址有效性标志

cons

并发感测

scavf

辅助 ccw 地址有效性标志

fsaf

失败存储地址格式

scnt

如果 cons == 1,则为感测计数

res16

保留

struct erw_eadm

EADM 子通道扩展报告字

定义:

struct erw_eadm {
    __u32 : 16;
    __u32 b : 1;
    __u32 r : 1;
    __u32 : 14;
};

成员

b

aob 错误

r

arsb 错误

struct sublog

子通道注销区域

定义:

struct sublog {
    __u32 res0  : 1;
    __u32 esf   : 7;
    __u32 lpum  : 8;
    __u32 arep  : 1;
    __u32 fvf   : 5;
    __u32 sacc  : 2;
    __u32 termc : 2;
    __u32 devsc : 1;
    __u32 serr  : 1;
    __u32 ioerr : 1;
    __u32 seqc  : 3;
};

成员

res0

保留

esf

扩展状态标志

lpum

上次使用的路径掩码

arep

辅助报告

fvf

字段有效性标志

sacc

存储访问代码

termc

终止代码

devsc

设备状态检查

serr

辅助错误

ioerr

I/O 错误警报

seqc

序列代码

struct esw0

格式 0 扩展状态字 (ESW)

定义:

struct esw0 {
    struct sublog sublog;
    struct erw erw;
    dma32_t faddr[2];
    dma32_t saddr;
};

成员

sublog

子通道注销

erw

扩展报告字

faddr

失败存储地址

saddr

辅助 ccw 地址

struct esw1

格式 1 扩展状态字 (ESW)

定义:

struct esw1 {
    __u8 zero0;
    __u8 lpum;
    __u16 zero16;
    struct erw erw;
    __u32 zeros[3];
};

成员

zero0

保留的零

lpum

上次使用的路径掩码

zero16

保留的零

erw

扩展报告字

三个全字的零

struct esw2

格式 2 扩展状态字 (ESW)

定义:

struct esw2 {
    __u8 zero0;
    __u8 lpum;
    __u16 dcti;
    struct erw erw;
    __u32 zeros[3];
};

成员

zero0

保留的零

lpum

上次使用的路径掩码

dcti

设备连接时间间隔

erw

扩展报告字

三个全字的零

struct esw3

格式 3 扩展状态字 (ESW)

定义:

struct esw3 {
    __u8 zero0;
    __u8 lpum;
    __u16 res;
    struct erw erw;
    __u32 zeros[3];
};

成员

zero0

保留的零

lpum

上次使用的路径掩码

res

保留

erw

扩展报告字

三个全字的零

struct esw_eadm

EADM 子通道扩展状态字 (ESW)

定义:

struct esw_eadm {
    __u32 sublog;
    struct erw_eadm erw;
    __u32 : 32;
    __u32 : 32;
    __u32 : 32;
};

成员

sublog

子通道注销

erw

扩展报告字

struct irb

中断响应块

定义:

struct irb {
    union scsw scsw;
    union {
        struct esw0 esw0;
        struct esw1 esw1;
        struct esw2 esw2;
        struct esw3 esw3;
        struct esw_eadm eadm;
    } esw;
    __u8 ecw[32];
};

成员

scsw

子通道状态字

esw

扩展状态字

ecw

扩展控制字

描述

当发生中断时传递给设备驱动程序的 irb。对于请求的中断,通用 I/O 层已经执行了检查,以确定字段是否有效;无效的字段始终以 0 传递。如果发生单元检查,则 ecw 可能包含感测数据;如果设备不支持并发感测,则此数据由通用 I/O 层本身检索(以便设备驱动程序永远不需要执行基本感测本身)。对于未经请求的中断,irb 将按原样传递(适用时,感测数据除外)。

struct ciw

命令信息字 (CIW) 布局

定义:

struct ciw {
    __u32 et       :  2;
    __u32 reserved :  2;
    __u32 ct       :  4;
    __u32 cmd      :  8;
    __u32 count    : 16;
};

成员

et

条目类型

保留

保留位

ct

命令类型

cmd

命令代码

count

命令计数

struct ccw_dev_id

ccw 设备的唯一标识符

定义:

struct ccw_dev_id {
    u8 ssid;
    u16 devno;
};

成员

ssid

子通道集 id

devno

设备号

描述

此结构不是直接基于任何硬件结构。硬件通过其设备号和子通道来标识设备,子通道又通过其 id 来标识。为了获得跨子通道集的 ccw 设备的唯一标识符,引入了 struct ccw_dev_id。

int ccw_dev_id_is_equal(struct ccw_dev_id *dev_id1, struct ccw_dev_id *dev_id2)

比较两个 ccw_dev_id。

参数

struct ccw_dev_id *dev_id1

一个 ccw_dev_id。

struct ccw_dev_id *dev_id2

另一个 ccw_dev_id。

返回值

如果两个结构体逐字段相等,则返回 1;否则返回 0

上下文

任意

u8 pathmask_to_pos(u8 mask)

查找路径掩码中最左侧的位的位置。

参数

u8 mask

至少设置了一位的路径掩码。

ccw 设备

想要启动通道 I/O 的设备需要连接到 ccw 总线。与驱动程序核心的交互通过通用 I/O 层完成,该层提供了 ccw 设备和 ccw 设备驱动程序的抽象概念。

启动或终止通道 I/O 的函数都作用于 ccw 设备结构。设备驱动程序不得绕过这些函数,否则可能会发生奇怪的副作用。

struct ccw_device

通道连接的设备

定义:

struct ccw_device {
    spinlock_t *ccwlock;
    struct ccw_device_id id;
    struct ccw_driver *drv;
    struct device dev;
    int online;
    void (*handler) (struct ccw_device *, unsigned long, struct irb *);
};

成员

ccwlock

指向设备锁的指针

id

此设备的 ID

drv

此设备的 ccw 驱动程序

dev

嵌入的设备结构

online

设备的在线状态

handler

中断处理程序

描述

handler 是设备而不是驱动程序的成员,因为驱动程序可以为不同的 ccw 设备(多子通道驱动程序)使用不同的中断处理程序。

struct ccw_driver

通道连接设备的设备驱动程序

定义:

struct ccw_driver {
    struct ccw_device_id *ids;
    int (*probe) (struct ccw_device *);
    void (*remove) (struct ccw_device *);
    int (*set_online) (struct ccw_device *);
    int (*set_offline) (struct ccw_device *);
    int (*notify) (struct ccw_device *, int);
    void (*path_event) (struct ccw_device *, int *);
    void (*shutdown) (struct ccw_device *);
    enum uc_todo (*uc_handler) (struct ccw_device *, struct irb *);
    struct device_driver driver;
    enum interruption_class int_class;
};

成员

ids

此驱动程序支持的 ID

probe

在探测时调用的函数

remove

在移除时调用的函数

set_online

在设置设备在线时调用

set_offline

在设置设备离线时调用

notify

通知驱动程序设备状态更改

path_event

通知驱动程序通道路径事件

shutdown

在设备关闭时调用

uc_handler

单元检查处理程序的回调

driver

嵌入的设备驱动程序结构

int_class

用于计算中断的中断类

int ccw_device_set_offline(struct ccw_device *cdev)

禁用 ccw 设备进行 I/O 操作。

参数

struct ccw_device *cdev

目标 ccw 设备

描述

此函数如果存在,则为 cdev 调用驱动程序的 set_offline() 函数,然后禁用 cdev

返回值

成功返回 0,失败返回负错误值。

上下文

已启用,未持有 ccw 设备锁。

int ccw_device_set_online(struct ccw_device *cdev)

启用 ccw 设备进行 I/O 操作。

参数

struct ccw_device *cdev

目标 ccw 设备

描述

此函数首先启用 cdev,然后如果存在,则为 cdev 调用驱动程序的 set_online() 函数。如果 set_online() 返回错误,则再次禁用 cdev

返回值

成功返回 0,失败返回负错误值。

上下文

已启用,未持有 ccw 设备锁。

struct ccw_device *get_ccwdev_by_dev_id(struct ccw_dev_id *dev_id)

从 ccw 设备 ID 获取设备。

参数

struct ccw_dev_id *dev_id

要搜索的设备的 ID

描述

此函数搜索连接到 ccw 总线的所有设备,以查找与 dev_id 匹配的设备。

返回值

如果找到设备,则其引用计数会增加并返回;否则返回 NULL

struct ccw_device *get_ccwdev_by_busid(struct ccw_driver *cdrv, const char *bus_id)

从总线 ID 获取设备。

参数

struct ccw_driver *cdrv

设备所属的驱动程序。

const char *bus_id

要搜索的设备的总线 ID。

描述

此函数搜索由 cdrv 拥有的所有设备,以查找总线 ID 与 bus_id 匹配的设备。

返回值

如果找到匹配项,则会增加找到的设备的引用计数并返回;否则返回 NULL

int ccw_driver_register(struct ccw_driver *cdriver)

注册 ccw 驱动程序。

参数

struct ccw_driver *cdriver

要注册的驱动程序

描述

此函数主要是在 driver_register() 周围的包装器。

返回值

成功返回 0,失败返回负错误值。

void ccw_driver_unregister(struct ccw_driver *cdriver)

取消注册 ccw 驱动程序。

参数

struct ccw_driver *cdriver

要取消注册的驱动程序

描述

此函数主要是在 driver_unregister() 周围的包装器。

int ccw_device_siosl(struct ccw_device *cdev)

启动日志记录。

参数

struct ccw_device *cdev

ccw 设备

描述

此函数用于在通道子系统内调用特定于模型的日志记录。

int ccw_device_set_options_mask(struct ccw_device *cdev, unsigned long flags)

设置某些选项并取消设置其余选项。

参数

struct ccw_device *cdev

要设置选项的设备

unsigned long flags

要设置的选项

描述

flags 中指定的所有标志位都会被设置,flags 中未指定的所有标志位都会被清除。

返回值

成功时返回 0,如果标志位组合无效则返回 -EINVAL

int ccw_device_set_options(struct ccw_device *cdev, unsigned long flags)

设置一些选项

参数

struct ccw_device *cdev

要设置选项的设备

unsigned long flags

要设置的选项

描述

flags 中指定的所有标志位都会被设置,其余标志位保持不变。

返回值

成功时返回 0,如果会导致无效的标志位组合则返回 -EINVAL

void ccw_device_clear_options(struct ccw_device *cdev, unsigned long flags)

清除一些选项

参数

struct ccw_device *cdev

要清除选项的设备

unsigned long flags

要清除的选项

描述

flags 中指定的所有标志位都会被清除,其余标志位保持不变。

int ccw_device_is_pathgroup(struct ccw_device *cdev)

确定此设备的路径是否分组

参数

struct ccw_device *cdev

ccw 设备

描述

如果存在路径组则返回非零值,否则返回零。

int ccw_device_is_multipath(struct ccw_device *cdev)

确定设备是否以多路径模式运行

参数

struct ccw_device *cdev

ccw 设备

描述

如果设备以多路径模式运行则返回非零值,否则返回零。

int ccw_device_clear(struct ccw_device *cdev, unsigned long intparm)

终止 I/O 请求处理

参数

struct ccw_device *cdev

目标 ccw 设备

unsigned long intparm

csch 结束时要返回的中断参数

描述

ccw_device_clear()cdev 的子通道上调用 csch。

返回值

成功时返回 0,如果设备未运行则返回 -ENODEV,如果设备状态无效则返回 -EINVAL

上下文

禁用中断,持有 ccw 设备锁

int ccw_device_start_timeout_key(struct ccw_device *cdev, struct ccw1 *cpa, unsigned long intparm, __u8 lpm, __u8 key, unsigned long flags, int expires)

启动带有超时和密钥的 s390 通道程序

参数

struct ccw_device *cdev

目标 ccw 设备

struct ccw1 *cpa

通道程序的逻辑起始地址

unsigned long intparm

用户特定的中断参数;将会返回给 cdev 的中断处理程序。允许设备驱动程序将中断与特定的 I/O 请求关联起来。

__u8 lpm

定义要用于特定 I/O 请求的通道路径。值为 0 将使 cio 使用 opm。

__u8 key

用于 I/O 的存储密钥

unsigned long flags

附加标志;定义 I/O 处理要执行的操作。

int expires

超时值(以 jiffies 为单位)

描述

启动 S/390 通道程序。当中断到达时,会立即调用 IRQ 处理程序,延迟调用(缺少 dev-end 或需要感应),或永不调用(未注册 IRQ 处理程序)。如果通道程序在 expires 指定的时间内未完成,此函数会通知设备驱动程序。如果发生超时,通道程序将通过 xsch、hsch 或 csch 终止,并且设备的 中断处理程序将被调用,并带有一个包含 ERR_PTR(-ETIMEDOUT) 的 irb。中断处理程序将回显此处指定的 intparm,除非通过后续调用 ccw_device_halt()ccw_device_clear() 指定了另一个中断参数。

返回值

如果操作成功则返回 0;如果设备繁忙或状态挂起则返回 -EBUSY;如果 lpm 中未指定可操作的路径则返回 -EACCES;如果设备未运行则返回 -ENODEV

上下文

禁用中断,持有 ccw 设备锁

int ccw_device_start_key(struct ccw_device *cdev, struct ccw1 *cpa, unsigned long intparm, __u8 lpm, __u8 key, unsigned long flags)

启动带有密钥的 s390 通道程序

参数

struct ccw_device *cdev

目标 ccw 设备

struct ccw1 *cpa

通道程序的逻辑起始地址

unsigned long intparm

用户特定的中断参数;将会返回给 cdev 的中断处理程序。允许设备驱动程序将中断与特定的 I/O 请求关联起来。

__u8 lpm

定义要用于特定 I/O 请求的通道路径。值为 0 将使 cio 使用 opm。

__u8 key

用于 I/O 的存储密钥

unsigned long flags

附加标志;定义 I/O 处理要执行的操作。

描述

启动 S/390 通道程序。当中断到达时,会立即调用 IRQ 处理程序,延迟调用(缺少 dev-end 或需要感应),或永不调用(未注册 IRQ 处理程序)。中断处理程序将回显此处指定的 intparm,除非通过后续调用 ccw_device_halt()ccw_device_clear() 指定了另一个中断参数。

返回值

如果操作成功则返回 0;如果设备繁忙或状态挂起则返回 -EBUSY;如果 lpm 中未指定可操作的路径则返回 -EACCES;如果设备未运行则返回 -ENODEV

上下文

禁用中断,持有 ccw 设备锁

int ccw_device_start(struct ccw_device *cdev, struct ccw1 *cpa, unsigned long intparm, __u8 lpm, unsigned long flags)

启动 s390 通道程序

参数

struct ccw_device *cdev

目标 ccw 设备

struct ccw1 *cpa

通道程序的逻辑起始地址

unsigned long intparm

用户特定的中断参数;将会返回给 cdev 的中断处理程序。允许设备驱动程序将中断与特定的 I/O 请求关联起来。

__u8 lpm

定义要用于特定 I/O 请求的通道路径。值为 0 将使 cio 使用 opm。

unsigned long flags

附加标志;定义 I/O 处理要执行的操作。

描述

启动 S/390 通道程序。当中断到达时,会立即调用 IRQ 处理程序,延迟调用(缺少 dev-end 或需要感应),或永不调用(未注册 IRQ 处理程序)。中断处理程序将回显此处指定的 intparm,除非通过后续调用 ccw_device_halt()ccw_device_clear() 指定了另一个中断参数。

返回值

如果操作成功则返回 0;如果设备繁忙或状态挂起则返回 -EBUSY;如果 lpm 中未指定可操作的路径则返回 -EACCES;如果设备未运行则返回 -ENODEV

上下文

禁用中断,持有 ccw 设备锁

int ccw_device_start_timeout(struct ccw_device *cdev, struct ccw1 *cpa, unsigned long intparm, __u8 lpm, unsigned long flags, int expires)

启动带有超时功能的 s390 通道程序

参数

struct ccw_device *cdev

目标 ccw 设备

struct ccw1 *cpa

通道程序的逻辑起始地址

unsigned long intparm

用户特定的中断参数;将会返回给 cdev 的中断处理程序。允许设备驱动程序将中断与特定的 I/O 请求关联起来。

__u8 lpm

定义要用于特定 I/O 请求的通道路径。值为 0 将使 cio 使用 opm。

unsigned long flags

附加标志;定义 I/O 处理要执行的操作。

int expires

超时值(以 jiffies 为单位)

描述

启动 S/390 通道程序。当中断到达时,会立即调用 IRQ 处理程序,延迟调用(缺少 dev-end 或需要感应),或永不调用(未注册 IRQ 处理程序)。如果通道程序在 expires 指定的时间内未完成,此函数会通知设备驱动程序。如果发生超时,通道程序将通过 xsch、hsch 或 csch 终止,并且设备的 中断处理程序将被调用,并带有一个包含 ERR_PTR(-ETIMEDOUT) 的 irb。中断处理程序将回显此处指定的 intparm,除非通过后续调用 ccw_device_halt()ccw_device_clear() 指定了另一个中断参数。

返回值

如果操作成功则返回 0;如果设备繁忙或状态挂起则返回 -EBUSY;如果 lpm 中未指定可操作的路径则返回 -EACCES;如果设备未运行则返回 -ENODEV

上下文

禁用中断,持有 ccw 设备锁

int ccw_device_halt(struct ccw_device *cdev, unsigned long intparm)

暂停 I/O 请求处理

参数

struct ccw_device *cdev

目标 ccw 设备

unsigned long intparm

中断参数将在 hsch 结束后返回

描述

ccw_device_halt()cdev 的子通道上调用 hsch。除非通过后续调用 ccw_device_clear() 指定了另一个中断参数,否则中断处理程序将回显此处指定的 intparm

返回值

成功时返回 0,设备未运行时返回 -ENODEV,设备状态无效时返回 -EINVAL,设备繁忙或中断挂起时返回 -EBUSY

上下文

禁用中断,持有 ccw 设备锁

int ccw_device_resume(struct ccw_device *cdev)

恢复通道程序的执行

参数

struct ccw_device *cdev

目标 ccw 设备

描述

ccw_device_resume()cdev 的子通道上调用 rsch。

返回值

成功时返回 0,设备未运行时返回 -ENODEV,设备状态无效时返回 -EINVAL,设备繁忙或中断挂起时返回 -EBUSY

上下文

禁用中断,持有 ccw 设备锁

struct ciw *ccw_device_get_ciw(struct ccw_device *cdev, __u32 ct)

在扩展感测数据中搜索 CIW 命令。

参数

struct ccw_device *cdev

要检查的 ccw 设备

__u32 ct

要查找的命令类型

描述

在 SenseID 期间,描述设备可用的特殊命令的命令信息字 (CIW) 可能已存储在扩展感测数据中。此函数在扩展感测数据中搜索指定命令类型的 CIW。

返回值

如果未存储扩展感测数据,或者找不到指定命令类型的 CIW,则返回 NULL,否则返回指向指定命令类型的 CIW 的指针。

__u8 ccw_device_get_path_mask(struct ccw_device *cdev)

获取当前可用的路径

参数

struct ccw_device *cdev

要查询的 ccw 设备

返回值

如果该设备没有可用的子通道,则返回 0,否则返回 ccw 设备子通道的当前可用路径的掩码。

struct channel_path_desc_fmt0 *ccw_device_get_chp_desc(struct ccw_device *cdev, int chp_idx)

返回新分配的通道路径描述符

参数

struct ccw_device *cdev

要获取描述符的设备

int chp_idx

通道路径的索引

描述

成功时返回与给定通道路径关联的通道路径描述数据的新分配的副本。如果出错,则返回 NULL

u8 *ccw_device_get_util_str(struct ccw_device *cdev, int chp_idx)

返回新分配的实用程序字符串

参数

struct ccw_device *cdev

要获取实用程序字符串的设备

int chp_idx

通道路径的索引

描述

成功时返回与给定通道路径关联的实用程序字符串的新分配的副本。如果出错,则返回 NULL

void ccw_device_get_id(struct ccw_device *cdev, struct ccw_dev_id *dev_id)

获取 ccw 设备 ID

参数

struct ccw_device *cdev

要获取 ID 的设备

struct ccw_dev_id *dev_id

在哪里填充值

int ccw_device_tm_start_timeout_key(struct ccw_device *cdev, struct tcw *tcw, unsigned long intparm, u8 lpm, u8 key, int expires)

执行启动功能

参数

struct ccw_device *cdev

在其上执行启动功能的 ccw 设备

struct tcw *tcw

要启动的传输命令字

unsigned long intparm

要传递给中断处理程序的用户定义参数

u8 lpm

要使用的路径的掩码

u8 key

用于存储访问的存储密钥

int expires

在中止请求之前的时间跨度(以 jiffies 为单位)

描述

在给定的 ccw 设备上启动 tcw。成功时返回零,否则返回非零值。

int ccw_device_tm_start_key(struct ccw_device *cdev, struct tcw *tcw, unsigned long intparm, u8 lpm, u8 key)

执行启动功能

参数

struct ccw_device *cdev

在其上执行启动功能的 ccw 设备

struct tcw *tcw

要启动的传输命令字

unsigned long intparm

要传递给中断处理程序的用户定义参数

u8 lpm

要使用的路径的掩码

u8 key

用于存储访问的存储密钥

描述

在给定的 ccw 设备上启动 tcw。成功时返回零,否则返回非零值。

int ccw_device_tm_start(struct ccw_device *cdev, struct tcw *tcw, unsigned long intparm, u8 lpm)

执行启动功能

参数

struct ccw_device *cdev

在其上执行启动功能的 ccw 设备

struct tcw *tcw

要启动的传输命令字

unsigned long intparm

要传递给中断处理程序的用户定义参数

u8 lpm

要使用的路径的掩码

描述

在给定的 ccw 设备上启动 tcw。成功时返回零,否则返回非零值。

int ccw_device_tm_start_timeout(struct ccw_device *cdev, struct tcw *tcw, unsigned long intparm, u8 lpm, int expires)

执行启动功能

参数

struct ccw_device *cdev

在其上执行启动功能的 ccw 设备

struct tcw *tcw

要启动的传输命令字

unsigned long intparm

要传递给中断处理程序的用户定义参数

u8 lpm

要使用的路径的掩码

int expires

在中止请求之前的时间跨度(以 jiffies 为单位)

描述

在给定的 ccw 设备上启动 tcw。成功时返回零,否则返回非零值。

int ccw_device_get_mdc(struct ccw_device *cdev, u8 mask)

累积最大数据计数

参数

struct ccw_device *cdev

累积最大数据计数的 ccw 设备

u8 mask

要使用的路径的掩码

描述

返回所有路径至少支持的传输命令的 64KB 块的数量。 返回值 0 表示失败。

int ccw_device_tm_intrg(struct ccw_device *cdev)

执行询问功能

参数

struct ccw_device *cdev

要在其上执行询问功能的 ccw 设备

描述

在给定的 ccw 设备上执行询问功能。成功返回零,否则返回非零值。

void ccw_device_get_schid(struct ccw_device *cdev, struct subchannel_id *schid)

获取子通道 ID

参数

struct ccw_device *cdev

要获取 ID 的设备

struct subchannel_id *schid

在哪里填充值

int ccw_device_pnso(struct ccw_device *cdev, struct chsc_pnso_area *pnso_area, u8 oc, struct chsc_pnso_resume_token resume_token, int cnc)

执行网络子通道操作

参数

struct ccw_device *cdev

在其上执行 PNSO 的设备

struct chsc_pnso_area *pnso_area

操作的请求和响应块

u8 oc

操作码

struct chsc_pnso_resume_token resume_token

多块响应的恢复令牌

int cnc

布尔更改通知控制

描述

pnso_area 必须由调用者使用 get_zeroed_page(GFP_KERNEL) 分配

成功时返回 0。

int ccw_device_get_cssid(struct ccw_device *cdev, u8 *cssid)

获取通道子系统 ID

参数

struct ccw_device *cdev

获取 CSSID 的设备

u8 *cssid

结果通道子系统 ID

int ccw_device_get_iid(struct ccw_device *cdev, u8 *iid)

获取 MIF 镜像 ID

参数

struct ccw_device *cdev

获取 MIF 镜像 ID 的设备

u8 *iid

结果 MIF 镜像 ID

int ccw_device_get_chpid(struct ccw_device *cdev, int chp_idx, u8 *chpid)

获取通道路径 ID

参数

struct ccw_device *cdev

获取通道路径 ID 的设备

int chp_idx

通道路径的索引

u8 *chpid

结果通道路径 ID

int ccw_device_get_chid(struct ccw_device *cdev, int chp_idx, u16 *chid)

获取与指定 CHPID 关联的通道 ID

参数

struct ccw_device *cdev

获取通道 ID 的设备

int chp_idx

通道路径的索引

u16 *chid

结果通道 ID

通道测量工具

通道测量工具提供了一种收集测量数据的方法,该数据由通道子系统为每个连接的通道设备提供。

struct cmbdata

用户空间的通道测量块数据

定义:

struct cmbdata {
    __u64 size;
    __u64 elapsed_time;
    __u64 ssch_rsch_count;
    __u64 sample_count;
    __u64 device_connect_time;
    __u64 function_pending_time;
    __u64 device_disconnect_time;
    __u64 control_unit_queuing_time;
    __u64 device_active_only_time;
    __u64 device_busy_time;
    __u64 initial_command_response_time;
};

成员

大小

存储数据的大小

elapsed_time

自上次采样以来的时间

ssch_rsch_count

ssch 和 rsch 的数量

sample_count

采样数量

device_connect_time

设备连接时间

function_pending_time

函数挂起的时间

device_disconnect_time

设备断开连接时间

control_unit_queuing_time

控制单元排队的时间

device_active_only_time

仅设备活动的时间

device_busy_time

设备繁忙时间(扩展格式)

initial_command_response_time

初始命令响应时间(扩展格式)

描述

为了简单起见,所有值都存储为 64 位,尤其是在 32 位仿真模式下。所有时间值都标准化为纳秒。目前,已知两种格式,它们的区别在于此结构的大小,即仅当激活扩展通道测量工具(首次在 z990 机器中发布)时才设置最后两个成员。可能会添加更多字段,这将导致新的 ioctl 编号。

int enable_cmf(struct ccw_device *cdev)

为特定设备打开通道测量

参数

struct ccw_device *cdev

要启用的 ccw 设备

cdev 启用通道测量。如果在已经启用通道测量的设备上调用此函数,则会触发测量数据的重置。

返回值

成功返回 0 或负错误值。

上下文

非原子操作

int disable_cmf(struct ccw_device *cdev)

为特定设备关闭通道测量

参数

struct ccw_device *cdev

要禁用的 ccw 设备

返回值

成功返回 0 或负错误值。

上下文

非原子操作

u64 cmf_read(struct ccw_device *cdev, int index)

从当前通道测量块读取一个值

参数

struct ccw_device *cdev

要读取的通道

int index

要读取的值的索引

返回值

读取的值,如果无法读取该值,则返回 0

上下文

任意

int cmf_readall(struct ccw_device *cdev, struct cmbdata *data)

读取当前通道测量块

参数

struct ccw_device *cdev

要读取的通道

struct cmbdata *data

指向将填充的数据块的指针

返回值

成功返回 0,否则返回负错误值。

上下文

任意

ccwgroup 总线

ccwgroup 总线仅包含用户创建的人工设备。许多网络设备(例如 qeth)实际上由多个 ccw 设备(例如 qeth 的读取、写入和数据通道)组成。ccwgroup 总线提供了一种机制来创建包含这些 ccw 设备作为从属设备的元设备,并且可以将其与网络设备关联。

ccw 组设备

struct ccwgroup_device

ccw 组设备

定义:

struct ccwgroup_device {
    enum {
        CCWGROUP_OFFLINE,
        CCWGROUP_ONLINE,
    } state;
    unsigned int count;
    struct device   dev;
    struct work_struct ungroup_work;
    struct ccw_device *cdev[];
};

成员

状态

在线/离线状态

count

附加的从属设备数量

dev

嵌入的设备结构

ungroup_work

用于取消分组 ccwgroup 设备

cdev

可变数量的从属设备,根据需要分配

struct ccwgroup_driver

ccw 组设备的驱动程序

定义:

struct ccwgroup_driver {
    int (*setup) (struct ccwgroup_device *);
    void (*remove) (struct ccwgroup_device *);
    int (*set_online) (struct ccwgroup_device *);
    int (*set_offline) (struct ccwgroup_device *);
    void (*shutdown)(struct ccwgroup_device *);
    struct device_driver driver;
    struct ccw_driver *ccw_driver;
};

成员

setup

在设备创建期间调用以设置设备的函数

remove

在移除时调用的函数

set_online

在设备设置为在线时调用的函数

set_offline

在设备设置为离线时调用的函数

shutdown

在设备关闭时调用的函数

driver

嵌入式驱动程序结构

ccw_driver

支持的 ccw_driver (可选)

int ccwgroup_set_online(struct ccwgroup_device *gdev)

启用 ccwgroup 设备

参数

struct ccwgroup_device *gdev

目标 ccwgroup 设备

描述

此函数尝试将 ccwgroup 设备设置为在线状态。

返回值

成功返回 0,失败返回负错误值。

int ccwgroup_set_offline(struct ccwgroup_device *gdev, bool call_gdrv)

禁用 ccwgroup 设备

参数

struct ccwgroup_device *gdev

目标 ccwgroup 设备

bool call_gdrv

调用已注册的 gdrv set_offline 函数

描述

此函数尝试将 ccwgroup 设备设置为离线状态。

返回值

成功返回 0,失败返回负错误值。

int ccwgroup_create_dev(struct device *parent, struct ccwgroup_driver *gdrv, int num_devices, const char *buf)

创建并注册 ccw 组设备

参数

struct device *parent

新设备的父设备

struct ccwgroup_driver *gdrv

新组设备的驱动程序

int num_devices

从属设备的数量

const char *buf

包含以逗号分隔的从属设备总线 ID 的缓冲区

描述

创建并注册一个新的 ccw 组设备,作为 parent 的子设备。从 buf 中给出的总线 ID 列表获取从属设备。

返回值

成功时返回 0,失败时返回错误代码。

上下文

非原子操作

int ccwgroup_driver_register(struct ccwgroup_driver *cdriver)

注册 ccw 组驱动程序

参数

struct ccwgroup_driver *cdriver

要注册的驱动程序

描述

此函数主要是在 driver_register() 周围的包装器。

void ccwgroup_driver_unregister(struct ccwgroup_driver *cdriver)

注销 ccw 组驱动程序

参数

struct ccwgroup_driver *cdriver

要取消注册的驱动程序

描述

此函数主要是在 driver_unregister() 周围的包装器。

int ccwgroup_probe_ccwdev(struct ccw_device *cdev)

从属设备的探测函数

参数

struct ccw_device *cdev

要探测的 ccw 设备

描述

这是一个 ccw 设备的虚拟探测函数,这些 ccw 设备是 ccw 组设备中的从属设备。

返回值

始终为 0

void ccwgroup_remove_ccwdev(struct ccw_device *cdev)

从属设备的删除函数

参数

struct ccw_device *cdev

要删除的 ccw 设备

描述

这是一个 ccw 设备的删除函数,这些 ccw 设备是 ccw 组设备中的从属设备。它将 ccw 设备设置为离线,并注销嵌入的 ccw 组设备。

通用接口

以下部分包含的接口不仅由处理 ccw 设备的驱动程序使用,还由各种其他 s390 硬件的驱动程序使用。

适配器中断

公共 I/O 层提供用于处理适配器中断和中断向量的辅助函数。

int register_adapter_interrupt(struct airq_struct *airq)

注册适配器中断处理程序

参数

struct airq_struct *airq

指向适配器中断描述符的指针

描述

成功时返回 0,否则返回 -EINVAL。

void unregister_adapter_interrupt(struct airq_struct *airq)

注销适配器中断处理程序

参数

struct airq_struct *airq

指向适配器中断描述符的指针

struct airq_iv *airq_iv_create(unsigned long bits, unsigned long flags, unsigned long *vec)

创建中断向量

参数

unsigned long bits

中断向量中的位数

unsigned long flags

分配标志

unsigned long *vec

如果为 AIRQ_IV_GUESTVEC,则指向已固定客户内存的指针

描述

返回指向中断向量结构的指针

void airq_iv_release(struct airq_iv *iv)

释放中断向量

参数

struct airq_iv *iv

指向中断向量结构的指针

unsigned long airq_iv_alloc(struct airq_iv *iv, unsigned long num)

从中断向量分配 irq 位

参数

struct airq_iv *iv

指向中断向量结构的指针

unsigned long num

要分配的连续 irq 位的数量

描述

返回分配的 irq 块中第一个 irq 的位号,如果没有任何位可用或未指定 AIRQ_IV_ALLOC 标志,则返回 -1UL

void airq_iv_free(struct airq_iv *iv, unsigned long bit, unsigned long num)

释放中断向量的 irq 位

参数

struct airq_iv *iv

指向中断向量结构的指针

unsigned long bit

要释放的第一个 irq 位的编号

unsigned long num

要释放的连续 irq 位的数量

unsigned long airq_iv_scan(struct airq_iv *iv, unsigned long start, unsigned long end)

扫描中断向量以查找非零位

参数

struct airq_iv *iv

指向中断向量结构的指针

unsigned long start

搜索起始的位号

unsigned long end

搜索结束的位号

描述

返回下一个非零中断位的位号,如果在扫描完成时未找到任何非零位,则返回 -1UL。