## 12.2. 回顾: ISA
设计上 ISA 总线非常老了, 并且是非常地低能, 但是它仍然持有一块挺大的控制设备的市场. 如果速度不重要并且你想支持老式主板, 一个 ISA 实现要优于 PCI. 这个老标准的另外一个好处是如果你是一个电子爱好者, 你可轻易建立你自己的 ISA 设备, 显然对 PCI 是不可能的.
另一方面, ISA 的许多缺点是它紧密绑定在 PC 体系上; 这个接口总线有所有的 80286 处理器的限制并且给系统程序员带来无穷的痛苦. ISA 设计(从原始的 IBM PC 继承下来的)的另一个大问题是地理式寻址的缺乏, 它已导致许多问题和长时间的拔下-重置跳线-插上-测试 循环来添加新设备. 有趣的是要注意甚至是最老的 Aplle II 计算机都已经采用了地理式寻址, 并且它们特有无跳线扩展板.
不管它的大的缺点, ISA 仍然在几个意想不到的地方使用. 例如, 用在几个掌上电脑的 VR41xx 系列的 MIPS 处理器特有一个 ISA 兼容的扩展总线, 就象它看起来那么奇怪. 在 ISA 的这些意想不到的用法之后的理由是一些老式设备的相当低的成本, 例如基于 8390 的以太网卡, 因此一个带有 ISA 电路信号的 CPU 可轻易采用这个糟糕的, 但是便宜的 PC 设备.
### 12.2.1. 硬件资源
一个 ISA 设备可配备有 I/O 端口, 内存区, 和中断线.
尽管 x86 处理器支持 64 KB I/O 端口内存(即, 处理器有 16 条地址线), 一些老 PC 硬件仅解码最低的 10 位地址线. 这限制可用的地址空间为 1024 个端口, 因为任何在 1 KB 到64 KB 范围内的地址都被只解码低地址的任何设备错当成一个低地址. 一些外设解决这个限制通过映射一个端口到低 KB 并且使用高地址线来选择不同的设备寄存器. 例如, 一个映射在 0x340 的设备可安全地使用端口 0x740, 0x840, 等等.
如果 I/O 端口的可用性被限制, 内存存取更加麻烦. 一个 ISA 设备可只使用 640KB 到1 MB 之间的内存范围和 15 MB 和 16MB 之间的范围给 I/O 寄存器和设备控制. 640-KB 到 1-MB 范围被 PC BIOS , VAG-兼容的视频卡, 和各种其他设备使用, 给新设备留下了很少空间. 另一方面, 在 15MB 的内存, 不被 Linux 直接支持, 并且改造内核来支持它是浪费时间.
对 ISA 设备板第 3 个可用资源是中断线. 一个有限数目的中断线被连接到 ISA 总线, 并且它们由所有接口板共享. 结果是, 如果设备不被正确配置, 它们可能发现它们自己在使用同一个中断线.
尽管原始的 ISA 规范不允许在设备间共享, 大部分设备板允许这样. [[44](#)]在软件层次的共享在"中断共享"一节中描述, 在第 10 章.
### 12.2.2. ISA 编程
对于编程, 内核中没有特别的帮助来易于存取 ISA 设备(象对 PCI 那样有, 例如). 你可使用的唯一工具是 I/O 端口和 IRQ 线的注册, 在 10 章的"安装一个中断处理"一节.
在本书第一部分所展示的编程技术适用于 ISA 设备; 驱动可探测 I/O 端口, 并且中断线必须被自动探测, 使用在 10 章的"自动探测 IRQ 号"一节的一个技术.
帮忙函数 isa_readb 和 它的朋友已经在"使用 I/O 内存" 9 章中简单介绍了, 并且对它们没有更多要说的.
### 12.2.3. 即插即用规范
一些新 ISA 设备板遵循特殊的设计规范并且需要一个特别的初始化顺序, 对增加接口板的简单安装和配置的扩展. 这些板的设计规范称为即插即用, 由一个麻烦的规则集组成, 来建立和配置无跳线的 ISA 设备. PnP 设备实现可重分配的 I/O 区; PC 的 BIOS 负责重新分配 -- 回想 PCI
简短来说, PnP 的目标是获得同样的灵活性, 在 PCI 设备中有的, 而不必关闭底层的电路接口(ISA 总线). 为此, 这个规范定义了一套设备独立的配置寄存器和一个地理式寻址接口板的方法, 尽管物理总线没有每块板子相连(地理上)--每个 ISA 信号线连接到每个可用的槽位.
地理式寻址通过分配一个小的整数, 称为卡选择号(CSN), 给计算机中的每个 PnP 外设. 每个 PnP 设备特有一个唯一的系列标识符, 64-位宽, 这硬连线到外设板. CSN 分配使用唯一的序列号来标识 PnP 设备. 但是 CSN 可被分配只在启动时, 它要求 BISO 是知道 PnP 的. 由于这个理由, 老式计算机要求用户来获得并插入一个特别的配置磁盘, 即便这个设备是 PnP 的.
遵循 PnP 的接口板在硬件级别上是复杂的. 它们比 PCI 板更加精细并且需要复杂的软件. 安装这些设备有困难是常有的, 并且即便安装顺利, 你仍然面对性能限制和 ISA 总线的受限的 I/O 空间. 最好在任何可能时安装 PCI 设备, 并且享受新技术.
如果你对 PnP 配置软件感兴趣, 你可浏览 drivers/net/3c509.c, 它的探测函数处理 PnP 设备. 2.6 内核有许多工作在 PnP 设备支持领域, 因此许多灵活的接口和之前的内核发行相比被清理了.
[[44](#)] 中断共享的问题是一个电子工程的问题: 如果一个设备驱动信号线非激活 -- 通过给一个低阻电平 -- 中断无法被共享. 如果, 另一方面, 设备使用一个上拉电阻来去激活逻辑电平, 共享是可能的. 现在这是正常的. 但是, 仍然有潜在的丢失中断事件的危险, 因为 ISA 中断是沿触发的而不是电平触发的. 沿触发中断易于在硬件中实现, 但是没有使它们可安全共享.
- Linux设备驱动第三版
- 第 1 章 设备驱动简介
- 1.1. 驱动程序的角色
- 1.2. 划分内核
- 1.3. 设备和模块的分类
- 1.4. 安全问题
- 1.5. 版本编号
- 1.6. 版权条款
- 1.7. 加入内核开发社团
- 1.8. 本书的内容
- 第 2 章 建立和运行模块
- 2.1. 设置你的测试系统
- 2.2. Hello World 模块
- 2.3. 内核模块相比于应用程序
- 2.4. 编译和加载
- 2.5. 内核符号表
- 2.6. 预备知识
- 2.7. 初始化和关停
- 2.8. 模块参数
- 2.9. 在用户空间做
- 2.10. 快速参考
- 第 3 章 字符驱动
- 3.1. scull 的设计
- 3.2. 主次编号
- 3.3. 一些重要数据结构
- 3.4. 字符设备注册
- 3.5. open 和 release
- 3.6. scull 的内存使用
- 3.7. 读和写
- 3.8. 使用新设备
- 3.9. 快速参考
- 第 4 章 调试技术
- 4.1. 内核中的调试支持
- 4.2. 用打印调试
- 4.3. 用查询来调试
- 4.4. 使用观察来调试
- 4.5. 调试系统故障
- 4.6. 调试器和相关工具
- 第 5 章 并发和竞争情况
- 5.1. scull 中的缺陷
- 5.2. 并发和它的管理
- 5.3. 旗标和互斥体
- 5.4. Completions 机制
- 5.5. 自旋锁
- 5.6. 锁陷阱
- 5.7. 加锁的各种选择
- 5.8. 快速参考
- 第 6 章 高级字符驱动操作
- 6.1. ioctl 接口
- 6.2. 阻塞 I/O
- 6.3. poll 和 select
- 6.4. 异步通知
- 6.5. 移位一个设备
- 6.6. 在一个设备文件上的存取控制
- 6.7. 快速参考
- 第 7 章 时间, 延时, 和延后工作
- 7.1. 测量时间流失
- 7.2. 获知当前时间
- 7.3. 延后执行
- 7.4. 内核定时器
- 7.5. Tasklets 机制
- 7.6. 工作队列
- 7.7. 快速参考
- 第 8 章 分配内存
- 8.1. kmalloc 的真实故事
- 8.2. 后备缓存
- 8.3. get_free_page 和其友
- 8.4. 每-CPU 的变量
- 8.5. 获得大量缓冲
- 8.6. 快速参考
- 第 9 章 与硬件通讯
- 9.1. I/O 端口和 I/O 内存
- 9.2. 使用 I/O 端口
- 9.3. 一个 I/O 端口例子
- 9.4. 使用 I/O 内存
- 9.5. 快速参考
- 第 10 章 中断处理
- 10.1. 准备并口
- 10.2. 安装一个中断处理
- 10.3. 前和后半部
- 10.4. 中断共享
- 10.5. 中断驱动 I/O
- 10.6. 快速参考
- 第 11 章 内核中的数据类型
- 11.1. 标准 C 类型的使用
- 11.2. 安排一个明确大小给数据项
- 11.3. 接口特定的类型
- 11.4. 其他移植性问题
- 11.5. 链表
- 11.6. 快速参考
- 第 12 章 PCI 驱动
- 12.1. PCI 接口
- 12.2. 回顾: ISA
- 12.3. PC/104 和 PC/104+
- 12.4. 其他的 PC 总线
- 12.5. SBus
- 12.6. NuBus 总线
- 12.7. 外部总线
- 12.8. 快速参考
- 第 13 章 USB 驱动
- 13.1. USB 设备基础知识
- 13.2. USB 和 sysfs
- 13.3. USB 的 Urbs
- 13.4. 编写一个 USB 驱动
- 13.5. 无 urb 的 USB 传送
- 13.6. 快速参考
- 第 14 章 Linux 设备模型
- 14.1. Kobjects, Ksets 和 Subsystems
- 14.2. 低级 sysfs 操作
- 14.3. 热插拔事件产生
- 14.4. 总线, 设备, 和驱动
- 14.5. 类
- 14.6. 集成起来
- 14.7. 热插拔
- 14.8. 处理固件
- 14.9. 快速参考
- 第 15 章 内存映射和 DMA
- 15.1. Linux 中的内存管理
- 15.2. mmap 设备操作
- 15.3. 进行直接 I/O
- 15.4. 直接内存存取
- 15.5. 快速参考
- 第 16 章 块驱动
- 16.1. 注册
- 16.2. 块设备操作
- 16.3. 请求处理
- 16.4. 一些其他的细节
- 16.5. 快速参考
- 第 17 章 网络驱动
- 17.1. snull 是如何设计的
- 17.2. 连接到内核
- 17.3. net_device 结构的详情
- 17.4. 打开与关闭
- 17.5. 报文传送
- 17.6. 报文接收
- 17.7. 中断处理
- 17.8. 接收中断缓解
- 17.9. 连接状态的改变
- 17.10. Socket 缓存
- 17.11. MAC 地址解析
- 17.12. 定制 ioctl 命令
- 17.13. 统计信息
- 17.14. 多播
- 17.15. 几个其他细节
- 17.16. 快速参考
- 第 18 章 TTY 驱动
- 18.1. 一个小 TTY 驱动
- 18.2. tty_driver 函数指针
- 18.3. TTY 线路设置
- 18.4. ioctls 函数
- 18.5. TTY 设备的 proc 和 sysfs 处理
- 18.6. tty_driver 结构的细节
- 18.7. tty_operaions 结构的细节
- 18.8. tty_struct 结构的细节
- 18.9. 快速参考