FreeBSD 系统结构手册
上一页 | 第10章 　ISA设备驱动程序 | 下一页

# 10.5 资源

用户写入到内核配置文件中的信息被作为配置资源处理，并传递到内核。 总线配置代码解析这部分信息并将其转换为结构device_t的值和与之 关联的总线资源。对于复杂情况下的配置，驱动程序可以直接使用 `resource_*` 函数访问配置资源。 然而， 通常既不需要也不推荐这样做， 因此这儿不再进一步讨论这个问题。

总线资源与每个设备相关联。通过类型和类型中的数字标识它们。 对于ISA总线，定义了下面的类型：

- SYS_RES_IRQ - 中断号

- SYS_RES_DRQ - ISA DMA通道号

- SYS_RES_MEMORY - 映射到系统内存空间 的设备内存的范围

- SYS_RES_IOPORT - 设备I/O寄存器的范围

类型内的枚举从0开始，因此如果设备有两个内存区域，它的 `SYS_RES_MEMORY` 类型的资源编号为0和1。 资源类型与C语言的类型无关， 所有资源值具有C语言 `unsigned long` 类型，并且必要时必须进行类型强制转换 (cast)。资源号不必连续， 尽管对于ISA它们一般是连续的。ISA设备允许的资源编号为：

              IRQ: 0-1
              DRQ: 0-1
              MEMORY: 0-3
              IOPORT: 0-7

所有资源被表示为带有起始值和计数的范围。对于IRQ和DRQ资源， 计数一般等于1。内存的值引用物理地址。

对资源能够执行三种类型的动作：

- set/get

- allocate/release

- activate/deactivate

Set设置资源使用的范围。Allocation保留出请求的范围，使得 其它设备不能再占用（并检查此范围没有被其它设备占用）。 Activation执行必要的动作使得驱动程序可以访问资源（例如，对于 内存，它将被映射到内核的虚拟地址空间）。

操作资源的函数有：

- `int bus_set_resource(device_t dev, int type, int rid, u_long start, u_long count)`

  为资源设置范围。成功则返回0，否则返回错误码。 一般此函数只有在`type`， `rid`，`start`或 `count`之一的值超出了允许的范围才会 返回错误。

  - dev - 驱动程序的设备

  - type - 资源类型，SYS_RES_*

  - rid - 类型内部的资源号（ID）

  - start, count - 资源范围

- `int bus_get_resource(device_t dev, int type, int rid, u_long *startp, u_long *countp)`

  取得资源范围。成功则返回0，如果资源尚未定义则返回错误码。

- `u_long bus_get_resource_start(device_t dev, int type, int rid) u_long bus_get_resource_count (device_t dev, int type, int rid)`

  便捷函数，只用来获取start或count。出错的情况下返回0， 因此如果0是资源的start合法值之一，将无法区分返回 的0是否指示错误。幸运的是，对于附加驱动程序，没有ISA资源的 start值从0开始。

- `void bus_delete_resource(device_t dev, int type, int rid)`

  删除资源，令其未定义。

- `struct resource * bus_alloc_resource(device_t dev, int type, int *rid, u_long start, u_long end, u_long count, u_int flags)`

  在start和end之间没有被其它设备占用的地方按count值 的范围分配一个资源。不过，不支持对齐。如果资源尚未被设置， 则自动创建它。start为0，end为~0（全1）的这对特殊值 意味着必须使用以前通过 `bus_set_resource()`设置的固定值： start和count就是它们自己，end=(start+count)，这种情况下， 如果以前资源没有定义，则返回错误。尽管rid通过引用传递， 但它并不被ISA总线的资源分配代码设置（其它总线可能使用不同的 方法并可能修改它）。

旗标是一个位映射，调用者感兴趣的有：

- RF_ACTIVE - 使得资源分配后 被自动激活。

- RF_SHAREABLE - 资源可以同时 被多个驱动程序共享。

- RF_TIMESHARE - 资源可以被多个驱动 程序分时共享，也就是说，被多个驱动程序同时分配，但任何 给定时间只能被其中一个激活。

- 出错返回0。被分配的值可以使用 `rhand_*()`从返回的句柄获得。

- `int bus_release_resource(device_t dev, int type, int rid, struct resource *r)`

- 释放资源，r为`bus_alloc_resource()` 返回的句柄。成功则返回0，否则返回错误码。

- `int bus_activate_resource(device_t dev, int type, int rid, struct resource *r)` `int bus_deactivate_resource(device_t dev, int type, int rid, struct resource *r)`

- 激活或禁用资源。成功则返回0，否则返回错误码。如果 资源被分时共享且当前被另一驱动程序激活，则返回 `EBUSY`。

- `int bus_setup_intr(device_t dev, struct resource *r, int flags, driver_intr_t *handler, void *arg, void **cookiep)` `int bus_teardown_intr(device_t dev, struct resource *r, void *cookie)`

- 关联/分离中断处理程序与设备。成功则返回0，否则 返回错误码。

- r - 被激活的描述IRQ的资源句柄。

  flags - 中断优先级，如下之一：

  - `INTR_TYPE_TTY` - 终端和其它 类似的字符类型设备。使用 `spltty()`屏蔽它们。

  - `(INTR_TYPE_TTY | INTR_TYPE_FAST)` - 输入缓冲较小的终端类型 设备，而且输入上的数据丢失很关键（例如老式串口）。 使用`spltty()`屏蔽它们。

  - `INTR_TYPE_BIO` - 块类型设备， 不包括CAM控制器上的。使用 `splbio()`屏蔽它们。

  - `INTR_TYPE_CAM` - CAM （通用访问 方法Common Access Method）总线控制器。使用 `splcam()`屏蔽它们。

  - `INTR_TYPE_NET` - 网络接口 控制器。使用 `splimp()`屏蔽它们。

  - `INTR_TYPE_MISC` - 各种其它设备。除了通过 `splhigh()`没有其它方法屏蔽它们。 `splhigh()`屏蔽所有中断。

当中断处理程序执行时，匹配其优先级的所有其它中断都被屏蔽， 唯一的例外是MISC级别，它不会屏蔽其它中断，也不会被其它中断 屏蔽。

- handler - 指向处理程序的指针， 类型driver_intr_t被定义为`void driver_intr_t(void *)`

- arg - 传递给处理程序的参量，标识 特定设备。由处理程序将它从void*转换为任何实际类型。ISA 中断处理程序的旧约定是使用单元号作为参量，新约定（推荐） 使用指向设备softc结构的指针。

- cookie[p] - 从 `setup()`接收的值，当传递给 `teardown()` 时用于标识处理程序。

定义了若干方法来操作资源句柄(struct resource *)。设备驱动 程序编写者感兴趣的有：

- `u_long rman_get_start(r) u_long rman_get_end(r)` 取得被分配的资源范围的起始和结束。

- `void *rman_get_virtual(r)` 取得 被激活的内存资源的虚地址。

上一页 | 起始页 | 下一页
配置文件与自动配置期间识别和探测的顺序 | 上一级 | 总线内存映射

本文档和其它文档可从这里下载：ftp://ftp.FreeBSD.org/pub/FreeBSD/doc/.

如果对于FreeBSD有问题，请先阅读文档，如不能解决再联系<questions@FreeBSD.org>.
关于本文档的问题请发信联系 <doc@FreeBSD.org>.