linux 0.11 内核学习 -- rs_io.s,串口汇编代码
/*
* 该文件实现rs232 串行通信中断处理
*/
/*
* linux/kernel/rs_io.s
*
* (C) 1991 Linus Torvalds
*/
/*
* rs_io.s
*
* This module implements the rs232 io interrupts.
*/
.text
.globl _rs1_interrupt,_rs2_interrupt
/* 读写队列缓冲区的长度 */
size = 1024 /* must be power of two !
and must match the value
in tty_io.c!!! */
/* these are the offsets into the read/write buffer structures */
/* 读写缓冲结构中的偏移量tty_queue */
rs_addr = 0
head = 4
tail = 8
proc_list = 12
buf = 16
/* 当写队列里还剩256 个字符空间(WAKEUP_CHARS)时,我们就可以写 */
startup = 256 /* chars left in write queue when we restart it */
/*
* These are the actual interrupt routines. They look where
* the interrupt is coming from, and take appropriate action.
*/
.align 2
/* 串行端口1 中断处理程序入口点 */
_rs1_interrupt:
// tty 表中对应串口1 的读写缓冲指针的地址入栈
pushl $_table_list+8 // table_list定义在文件tty_io.c文件中
jmp rs_int
/* 串行端口2 中断处理程序入口点 */
.align 2
_rs2_interrupt:
pushl $_table_list+16 // 同上
rs_int:
pushl %edx
pushl %ecx
pushl %ebx
pushl %eax
push %es
push %ds /* as this is an interrupt, we cannot */
/* 让ds、es 指向内核数据段 */
pushl $0x10 /* know that bs is ok. Load it */
pop %ds
pushl $0x10
pop %es
movl 24(%esp),%edx // 将缓冲队列指针地址存入edx 寄存器
movl (%edx),%edx // 取读队列指针(地址)?-> edx
movl rs_addr(%edx),%edx // 取串口1 的端口号?-> edx
/* edx 指向中断标识寄存器 */
addl $2,%edx /* interrupt ident. reg */
rep_int:
xorl %eax,%eax // eax = 0
inb %dx,%al // 取中断标识字节,用以判断中断来源
testb $1,%al // 有无待处理的中断?
jne end // 没有,则跳转至退出处理处end
cmpb $6,%al /* this shouldn't happen, but ... */
ja end // al 值>6? 是则跳转至end
movl 24(%esp),%ecx // 再取缓冲队列指针地址?-> ecx
pushl %edx // 将端口号0x3fa(0x2fa)入栈
subl $2,%edx // 0x3f8(0x2f8)
/* jmp_table在下面定义 */
call jmp_table(,%eax,2) /* NOTE! not *4, bit0 is 0 already */
popl %edx // 弹出中断标识寄存器端口号0x3fa(或0x2fa)
jmp rep_int // 继续处理
/* 向中断控制器发送结束中断指令EOI */
end: movb $0x20,%al
outb %al,$0x20 /* EOI */
pop %ds
pop %es
popl %eax
popl %ebx
popl %ecx
popl %edx
/* 丢弃缓冲队列指针地址 */
addl $4,%esp # jump over _table_list entry
iret
/* 各中断类型处理程序地址跳转表 */
/* modem 状态变化中断,写字符中断,读字符中断,线路状态有问题中断 */
jmp_table:
.long modem_status,write_char,read_char,line_status
.align 2
/* 通过读modem 状态寄存器进行复位(0x3fe) */
modem_status:
addl $6,%edx /* clear intr by reading modem status reg */
inb %dx,%al
ret
.align 2
/* 通过读线路状态寄存器进行复位(0x3fd) */
line_status:
addl $5,%edx /* clear intr by reading line status reg. */
inb %dx,%al
ret
.align 2
/*
* read_char实现的是从CPU读取,将结果存储到缓冲队列中
*/
read_char:
inb %dx,%al // 读取字符?-> al
movl %ecx,%edx // 当前串口缓冲队列指针地址?-> edx
subl $_table_list,%edx // 当前串口队列指针地址?-> edx
shrl $3,%edx
movl (%ecx),%ecx # read-queue
// 取读队列中缓冲头指针?-> ebx
movl head(%ecx),%ebx
// 将字符放在缓冲区中头指针所指的位置
movb %al,buf(%ecx,%ebx)
incl %ebx // 将头指针前移一字节
andl $size-1,%ebx // 缓冲区头指针进行模操作
cmpl tail(%ecx),%ebx // 缓冲区头指针与尾指针比较
je 1f // 若相等,表示缓冲区满,跳转到标号1 处
movl %ebx,head(%ecx) // 保存修改过的头指针
1: pushl %edx // 将串口号压入堆栈
call _do_tty_interrupt // 调用tty 中断处理C 函数
addl $4,%esp // 丢弃入栈参数,并返回
ret
.align 2
/*
* write_char函数是将收到的数据传送给CPU
*/
write_char:
// 取写缓冲队列结构地址?-> ecx
movl 4(%ecx),%ecx # write-queue
movl head(%ecx),%ebx // 取写队列头指针?-> ebx
subl tail(%ecx),%ebx // 头指针 - 尾指针 = 队列中字符数
andl $size-1,%ebx # nr chars in queue
je write_buffer_empty // 如果头指针 = 尾指针,说明写队列无字符,跳转处理
cmpl $startup,%ebx // 队列中字符数超过256 个?
ja 1f // 超过,则跳转处理
// 取等待该队列的进程的指针,并判断是否为空
movl proc_list(%ecx),%ebx # wake up sleeping process
testl %ebx,%ebx # is there any?
je 1f // 是空的,则向前跳转到标号1 处
movl $0,(%ebx) // 否则将进程置为可运行状态(唤醒进程)
/*
* 缓冲区的长度是1024,但是在缓冲区中含有256个字符时,就开始
* 进行写操作。下面的饿代码首先将超过256的字节的后一个字节
* 写入端口中,然后该段代码从尾部读取一个字符,然后继续rep_int
* ,程序继续判断是那种的处理情况
*
* tail(low address) ---------------------> head(high address)
*/
1: movl tail(%ecx),%ebx // 取尾指针
movb buf(%ecx,%ebx),%al // 从缓冲中尾指针处取一字符?-> al
outb %al,%dx // 将端口0x3f8(0x2f8)送出保存到寄存器中
incl %ebx // 尾指针前移
andl $size-1,%ebx // 尾指针若到缓冲区末端,则折回
movl %ebx,tail(%ecx) // // 保存已修改过的尾指针
cmpl head(%ecx),%ebx // 尾指针与头指针比较
// 注意队列数据结构
je write_buffer_empty // // 若相等,表示队列已空,则跳转
ret
.align 2
/*
* 唤醒进程,改写端口寄存器值
*/
write_buffer_empty:
// 唤醒等待的进程
movl proc_list(%ecx),%ebx # wake up sleeping process
// 有等待的进程吗?
testl %ebx,%ebx # is there any?
je 1f // 无,则向前跳转到标号1 处
movl $0,(%ebx) // 唤醒进程
1: incl %edx // 指向端口0x3f9(0x2f9)
inb %dx,%al // 读取中断允许寄存器
jmp 1f // 延迟
1: jmp 1f
/* disable transmit interrupt */
1: andb $0xd,%al
outb %al,%dx
ret
转载于:https://www.cnblogs.com/xuqiang/archive/2010/02/01/1953773.html
linux 0.11 内核学习 -- rs_io.s,串口汇编代码相关推荐
- linux内核态串口读写程序,linux 0.11 内核学习 -- rs_io.s,串口汇编代码
/* * 该文件实现rs232 串行通信中断处理 */ /* * linux/kernel/rs_io.s * * (C) 1991 Linus Torvalds */ /* *rs_io.s ...
- linux 0.11 内核学习 -- bootsect.s, 万里长征第一步
呵呵,终于将linux 0.11 下面的boot文件夹下的三个文件读完,下面是相关注释,没有汇编基础的人也是可以读的.废话少说,下面就是linux的源码了. 参考资料 Linux内核完全注释.pdf ...
- linux 0.11 内核学习路线
转载至 http://tieba.baidu.com/p/4871637101 当初一开始拿到赵炯的书时是兴奋的,代码几乎每行都有注释,心想这不手到擒来的吗.但是代码看到十几行就看不下去了,没错就是十 ...
- linux 0.11 内核学习 -- console.c,控制台
参考<linux内核完全注释>和网上相关文章 /* * 控制台显示操作 */ /* * linux/kernel/console.c * * (C) 1991 Linus Torva ...
- Linux 0.11内核分析04:多进程视图
目录 1 进程概念的引入 1.1 使用CPU的直观想法 1.2 直观用法的缺点 1.3 直观用法的改进 1.4 进程的概念 1.4.1 保存程序执行状态 1.4.2 进程与PCB 1.5 Linux ...
- Linux 0.11内核分析01:概述
目录 1. 什么是操作系统 1.1 计算机硬件组成 1.2 操作系统基本结构 2. 操作系统核心视图 2.1 多进程视图 2.1.1 操作系统的相关演变 2.1.2 核心思想 2.2 文件视图 2.2 ...
- Linux 0.11内核分析02:系统启动
目录 1. 内核镜像的构建 1.1 内核源码结构 1.1.1 boot 1.1.2 fs 1.1.3 include 1.1.4 init 1.1.5 kernel 1.1.6 lib 1.1.7 m ...
- LINUX 0.11内核完全剖析学习笔记-第三章内核编程语言和环境
一.编译器 linux 0.11 集成了两种汇编器.一种是能产生16位代码的as86汇编器,使用配套的ld86链接器:另一种是GUN汇编器gas,使用GNU ld链接器俩链接产生的目标文件. 1.1 ...
- Linux 0.11 内核解析:中断相关(1)asm.s文件中断处理分析
0 源代码 有两个版本的,一个是带中文注释,Intel格式的:一个是不带注释是AT&T格式的. Linux 0.11 中文注释版 Linux 0.11 源码,基于<Linux内核完全注释 ...
最新文章
- 语言中knitr_R语言软件包的批量引用
- JavaScript: 代码简洁之道
- 如何保护 SpringBoot 配置文件中的敏感信息
- CowNew开源-sql解析引擎和cownewsql阶段成果汇报
- iframe如何发送请求_插件分享 | 如何半天玩转一个“ES未授权利用”插件
- 如今全球超级计算机运算速度排名,截至2019年(或2018年),全球超级计算机运算速度排名第一的是?...
- 人名和成绩一起排序_#excel中怎么让人名和他的成绩一起排序#excle排序 怎么弄同名次...
- SharePoint文档上传管理
- windows环境 wildfly-10.1.0.Final 安装、配置、部署
- [转载] java给对象中的包装类设置默认值
- 前序表达式 中序表达式 后序表达式
- php 获取文件给用户下载,让PHP更快的为用户提供文件下载_PHP教程
- c语言程序结课编程报告,C语言程序分析报告课程标准.doc
- 什么是类Unix系统?
- Linux之Shell编程详解
- 关于ColorPicker颜色拾取器的使用方法
- 元宇宙持续引发关注,微软计划明年发布相关产品 | 产业区块链发展周报
- SwiftUI中微信认证成功但App回调方法未被调用的解决
- 遥感影像反差增强、直方图均衡化
- 23考研| 你来了,准硕士!!!