- 1、本文档共3页,可阅读全部内容。
- 2、有哪些信誉好的足球投注网站(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。
- 3、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载。
- 4、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
- 5、该文档为VIP文档,如果想要下载,成为VIP会员后,下载免费。
- 6、成为VIP后,下载本文档将扣除1次下载权益。下载后,不支持退款、换文档。如有疑问请联系我们。
- 7、成为VIP后,您将拥有八大权益,权益包括:VIP文档下载权益、阅读免打扰、文档格式转换、高级专利检索、专属身份标志、高级客服、多端互通、版权登记。
- 8、VIP文档为合作方或网友上传,每下载1次, 网站将根据用户上传文档的质量评分、类型等,对文档贡献者给予高额补贴、流量扶持。如果你也想贡献VIP文档。上传文档
查看更多
10.4. 中断共享
10.4. 中断共享
10.4. 中断共享
中断冲突的概念⼏乎是 PC 体系的同义词. 过去, 在 PC 上的 IRQ 线不能服务多于⼀个
设备, 并 它们从不⾜够. 结果, 失望的⽤户花费⼤量时间开着它们的计算机, 尽⼒找到
⼀个⽅法来使它们所有的外设⼀起⼯作.
现代的硬件, 当然, 已经设计来允许中断共享; PCI 总线要求它. 因此, Linux 内核⽀持在
所有总线上中断共享, 甚⾄是那些(例如 ISA 总线)传统上不被⽀持的. 2.6 内核的设备驱
动应当编写来使⽤共享中断, 如果⽬标硬件能够⽀持这个操作模式. 幸运的是, 使⽤共
享中断在⼤部分时间是容易的.
10.4.1. 安装⼀个共享的处理者
共享中断通过 request_irq 来安装就像不共享的⼀样, 但是有 2 个不同:
SA_SHIRQ 位必须在 fla s 参数中指定, 当请求中断时.
dev_id 参数必须是独特的. 任何模块地址空间的指针都⾏, 但是 dev_id 明确地不
能设置为 NULL .
内核保持着⼀个与中断相关联的共享处理者列表, 并 dev_id 可认为是区别它们的签
名. 如果 2 个驱动要在同⼀个中断上注册 NULL 作为它们的签名, 在卸载时事情可能就
乱了, 在中断到的时候引发内核 oops. 由于这个理由, 如果在注册共享中断时传给了⼀
个 NULL dev_id , 现代内核会⼤声抱怨. 当请求⼀个共享的中断, request_irq 成功, 如果
下列之⼀是真:
中断线空闲.
所有这条线的已经注册的处理者也指定共享这个 IRQ .
⽆论何时 2 个或多个驱动在共享中断线, 并 硬件中断在这条线上中断处理器, 内核为
这个中断调⽤每个注册的处理者, 传递它的 dev_id 给每个. 因此, ⼀个共享的处理者必
须能够识别它⾃⼰的中断并 应当快速退出当它⾃⼰的设备没有被中断时. 确认返回
IRQ_NONE ⽆论何时你的处理者被调⽤并 发现设备没被中断.
如果你需要探测你的设备, 在请求 IRQ 线之前, 内核⽆法帮你. 没有探测函数可给共享
处理者使⽤. 标准的探测机制有效如果使⽤的线是空闲的, 但是如果这条线已经被另⼀
个有共享能⼒的驱动持有, 探测失败, 即便你的驱动已正常⼯作. 幸运的是, ⼤部分设计
为中断共享的硬件能够告知处理器它在使⽤哪个中断, 因此减少明显的探测的需要.
释放处理者以正常⽅式进⾏, 使⽤ free_irq . 这⾥ dev_id 参数⽤来从这个中断的共享处
理者列表中选择正确的处理者来释放. 这就是为什么 dev_id 指针必须是独特的.
⼀个使⽤共享处理者的驱动需要⼩⼼多⼀件事: 它不能使⽤ enable_irq 或者 disable_irq .
如果它⽤了, 对其他共享这条线的设备就乱了; 禁⽌另⼀个设备的中断即便短时间也可
能产⽣延时, 这对这个设备和它的⽤户是有问题的. 通常, 程序员必须记住, 他的驱动不
拥有这个 IRQ, 并 它的⾏为应当⽐它拥有这个中断线更加社会性.
10.4.2. 运⾏处理者
如同前⾯建议的, 当内核收到⼀个中断, 所有的注册的处理者被调⽤. ⼀个共享的处理
者必须能够在它需要的处理的中断和其他设备产⽣的中断之间区分.
使⽤ shared= 1 选项来加载 short 安装了下列处理者来代替缺省的:
irqreturn_t short_sh_interrupt(int irq, void *dev_id, struct pt_re
{
int value, written;
struct timeval tv;
/* If it wasnt short, return immediatel */
value = inb(short_base);
if (!(value 0x80))
return IRQ_NONE;
/* clear the interrupting bit */
outb(value 0x7F, short_base);
/* the rest is unchanged */
do_gettimeofda (tv);
written = sprintf((char *)short_
文档评论(0)