用户写入到内核配置文件中的信息被作为配置资源处理,并传递到内核。
总线配置代码解析这部分信息并将其转换为结构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和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>.