S/390 驱动模型接口

1. CCW 设备

所有可以通过 CCW 寻址的设备都被称为“CCW 设备” - 即使它们实际上不是由 CCW 驱动的。

所有 CCW 设备都通过子通道访问,这反映在 devices/ 下的结构中。

devices/
   - system/
   - css0/
         - 0.0.0000/0.0.0815/
         - 0.0.0001/0.0.4711/
         - 0.0.0002/
         - 0.1.0000/0.1.1234/
         ...
         - defunct/

在此示例中,设备 0815 通过子通道集 0 中的子通道 0 访问,设备 4711 通过子通道集 0 中的子通道 1 访问,子通道 2 是非 I/O 子通道。设备 1234 通过子通道集 1 中的子通道 0 访问。

名为“defunct”的子通道不代表系统上的任何真实子通道;它是一个伪子通道,如果断开连接的 CCW 设备被另一个在其先前子通道上运行的 CCW 设备取代,则会将其移动到该伪子通道。如果 CCW 设备再次在该子通道上运行,它们将被再次移动到适当的子通道。

您应该通过其总线 ID(例如 0.0.4711)寻址 CCW 设备;该设备可以在 bus/ccw/devices/ 下找到。

所有 CCW 设备都通过 sysfs 导出一些数据。

cutype

控制单元类型/型号。

devtype

设备类型/型号(如果适用)。

availability

可以是“good”或“boxed”;对于断开连接的设备,可以是“no path”或“no device”。

online

一个用于设置设备上线和下线的接口。在设备断开连接的特殊情况下(参见 1.2 下的 notify 函数),将 0 管道到 online 将强制删除该设备。

设备驱动程序可以添加条目以导出每个设备的数据和接口。

还有一些数据以每个子通道为基础导出(参见 bus/css/devices/ 下)。

chpids

设备通过哪些 chpids 连接。

pimpampom

已安装路径、可用路径和可操作路径的掩码。

可能还有其他数据,例如块设备的数据。

1.1 启动 CCW 设备

这分为几个步骤完成。

  1. 每个驱动程序可以提供一个或多个参数接口,可以在其中指定参数。这些接口也由驱动程序负责。

  2. 如有必要,在执行 a. 之后,最终通过“online”接口启动设备。

1.2 为 CCW 设备编写驱动程序

基本的 struct ccw_devicestruct ccw_driver 数据结构可以在 include/asm/ccwdev.h 下找到

struct ccw_device {
      spinlock_t *ccwlock;
      struct ccw_device_private *private;
      struct ccw_device_id id;

      struct ccw_driver *drv;
      struct device dev;
      int online;

      void (*handler) (struct ccw_device *dev, unsigned long intparm,
                       struct irb *irb);
};

struct ccw_driver {
      struct module *owner;
      struct ccw_device_id *ids;
      int (*probe) (struct ccw_device *);
      int (*remove) (struct ccw_device *);
      int (*set_online) (struct ccw_device *);
      int (*set_offline) (struct ccw_device *);
      int (*notify) (struct ccw_device *, int);
      struct device_driver driver;
      char *name;
};

“private”字段包含仅用于内部 I/O 操作的数据,并且设备驱动程序不可用。

每个驱动程序都应该在 MODULE_DEVICE_TABLE 中声明它感兴趣的 CU 类型/型号和/或设备类型/型号。此信息稍后可以在 struct ccw_device_id 字段中找到

struct ccw_device_id {
      __u16   match_flags;

      __u16   cu_type;
      __u16   dev_type;
      __u8    cu_model;
      __u8    dev_model;

      unsigned long driver_info;
};

ccw_driver 中的函数应以下列方式使用

probe

设备层会为驱动程序感兴趣的每个设备调用此函数。驱动程序应仅分配私有结构以放入 dev->driver_data 并创建属性(如果需要)。此外,应在此处设置中断处理程序(见下文)。

int (*probe) (struct ccw_device *cdev);
参数
cdev
  • 要探测的设备。

remove

驱动程序层在删除驱动程序、设备或模块时会调用此函数。驱动程序应在此处执行清理。

int (*remove) (struct ccw_device *cdev);
参数
cdev
  • 要删除的设备。

set_online

当设备通过“online”属性激活时,公共 I/O 层会调用此函数。驱动程序应在此处最终设置并激活设备。

int (*set_online) (struct ccw_device *);
参数
cdev
  • 要激活的设备。公共层已验证该设备尚未上线。

set_offline:当设备

通过“online”属性停用时,公共 I/O 层会调用此函数。驱动程序应关闭设备,但不要取消分配其私有数据。

int (*set_offline) (struct ccw_device *);
参数
cdev
  • 要停用的设备。公共层

    已验证该设备已上线。

notify

公共 I/O 层会为设备的某些状态更改调用此函数。

发送到驱动程序的信号是

  • 在在线状态下,设备已分离 (CIO_GONE) 或最后一个路径已消失 (CIO_NO_PATH)。驱动程序必须返回 !0 以保留该设备;对于返回代码 0,设备将像往常一样被删除(即使未注册任何 notify 函数)。如果驱动程序想要保留该设备,则会将其移动到断开连接状态。

  • 在断开连接状态下,设备再次运行 (CIO_OPER)。公共 I/O 层对设备编号和设备/CU 执行一些健全性检查,以合理确定它是否仍然是同一设备。如果不是,则删除旧设备并注册一个新设备。通过 notify 函数的返回代码,设备驱动程序发出信号,表明它是否希望将设备取回:!0 表示保留,0 表示使设备被删除并重新注册。

int (*notify) (struct ccw_device *, int);
参数
cdev
  • 其状态已更改的设备。

event
  • 发生的事件。这可以是 CIO_GONE、CIO_NO_PATH 或 CIO_OPER 之一。

struct ccw_device 的 handler 字段旨在设置为设备的中断处理程序。为了适应使用多个不同处理程序的驱动程序(例如多子通道设备),这是 ccw_device 的成员,而不是 ccw_driver 的成员。该处理程序在驱动程序被调用之前,在 set_online() 处理期间向公共层注册,并在驱动程序被调用之后,在 set_offline() 期间注销。此外,在注册/注销之前,会执行路径分组或解散路径组(如果适用)。

void (*handler) (struct ccw_device *dev, unsigned long intparm, struct irb *irb);
参数:dev - 调用处理程序的设备
intparm - intparm 允许设备驱动程序识别

中断与之关联的 i/o,或将中断识别为未经请求的。

irb - 中断响应块,其中包含累积的

状态。

设备驱动程序从公共 ccw_device 层调用,并且可以从 irb 参数中检索有关中断的信息。

1.3 ccwgroup 设备

ccwgroup 机制旨在处理由多个 ccw 设备组成的设备,如 qeth 或 ctc。

ccw 驱动程序提供了一个“group”属性。将 ccw 设备的总线 ID 管道到此属性会创建一个由这些 ccw 设备组成的 ccwgroup 设备(如果可能)。此 ccwgroup 设备可以像普通 ccw 设备一样设置为上线或下线。

每个 ccwgroup 设备还提供一个“ungroup”属性,用于再次销毁该设备(仅在离线时)。这是一个通用的 ccwgroup 机制(驱动程序不需要实现任何超出正常删除例程的内容)。

作为 ccwgroup 设备成员的 ccw 设备在其设备结构的 driver_data 中携带一个指向 ccwgroup 设备的指针。驱动程序不得触及此字段 - 它应该使用 ccwgroup 设备的 driver_data 作为其私有数据。

要实现 ccwgroup 驱动程序,请参阅 include/asm/ccwgroup.h。请记住,大多数驱动程序都需要同时实现 ccwgroup 和 ccw 驱动程序。

2. 通道路径

通道路径像子通道一样出现在通道子系统根目录 (css0) 下,称为“chp0.<chpid>”。它们没有驱动程序,也不属于任何总线。请注意,与 2.4 中的 /proc/chpids 不同,通道路径对象仅反映逻辑状态,而不反映物理状态,因为由于缺少机器支持,我们无法始终如一地跟踪后者(无论如何我们不需要了解它)。

status
  • 可以是“online”或“offline”。管道“on”或“off”将 chpid 逻辑上设置为上线/下线。将“on”管道到在线 chpid 会触发 chpid 连接到的所有设备的路径重新探测。这可用于强制内核重新使用用户知道在线的通道路径,但机器尚未为其创建机器检查。

type
  • 通道路径的物理类型。

shared
  • 通道路径是否共享。

cmg
  • 通道测量组。

3. 系统设备

3.1 xpram

xpram 显示在 devices/system/ 下,作为“xpram”。

3.2 cpus

对于每个 cpu,会在 devices/system/cpu/ 下创建一个目录。每个 cpu 都有一个属性“online”,可以是 0 或 1。

4. 其他设备

4.1 Netiucv

netiucv 驱动程序在 bus/iucv/drivers/netiucv 下创建一个属性“connection”。管道到此属性会创建一个到指定主机的新的 netiucv 连接。

Netiucv 连接显示在 devices/iucv/ 下,作为“netiucv<ifnum>”。接口编号按顺序分配给通过“connection”属性定义的连接。

user
  • 显示连接伙伴。

buffer
  • 最大缓冲区大小。管道到它可以更改缓冲区大小。