/*

*  该文件实现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

参考《linux内核完全注释》和网上相关文章

转载于:https://www.cnblogs.com/xuqiang/archive/2010/02/01/1953773.html

linux 0.11 内核学习 -- rs_io.s,串口汇编代码相关推荐

  1. linux内核态串口读写程序,linux 0.11 内核学习 -- rs_io.s,串口汇编代码

    /* *  该文件实现rs232 串行通信中断处理 */ /* *  linux/kernel/rs_io.s * *  (C) 1991  Linus Torvalds */ /* *rs_io.s ...

  2. linux 0.11 内核学习 -- bootsect.s, 万里长征第一步

    呵呵,终于将linux 0.11 下面的boot文件夹下的三个文件读完,下面是相关注释,没有汇编基础的人也是可以读的.废话少说,下面就是linux的源码了. 参考资料 Linux内核完全注释.pdf ...

  3. linux 0.11 内核学习路线

    转载至 http://tieba.baidu.com/p/4871637101 当初一开始拿到赵炯的书时是兴奋的,代码几乎每行都有注释,心想这不手到擒来的吗.但是代码看到十几行就看不下去了,没错就是十 ...

  4. linux 0.11 内核学习 -- console.c,控制台

    参考<linux内核完全注释>和网上相关文章 /* * 控制台显示操作 */ /* *  linux/kernel/console.c * *  (C) 1991  Linus Torva ...

  5. Linux 0.11内核分析04:多进程视图

    目录 1 进程概念的引入 1.1 使用CPU的直观想法 1.2 直观用法的缺点 1.3 直观用法的改进 1.4 进程的概念 1.4.1 保存程序执行状态 1.4.2 进程与PCB 1.5 Linux ...

  6. Linux 0.11内核分析01:概述

    目录 1. 什么是操作系统 1.1 计算机硬件组成 1.2 操作系统基本结构 2. 操作系统核心视图 2.1 多进程视图 2.1.1 操作系统的相关演变 2.1.2 核心思想 2.2 文件视图 2.2 ...

  7. 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 ...

  8. LINUX 0.11内核完全剖析学习笔记-第三章内核编程语言和环境

    一.编译器 linux 0.11 集成了两种汇编器.一种是能产生16位代码的as86汇编器,使用配套的ld86链接器:另一种是GUN汇编器gas,使用GNU ld链接器俩链接产生的目标文件. 1.1 ...

  9. Linux 0.11 内核解析:中断相关(1)asm.s文件中断处理分析

    0 源代码 有两个版本的,一个是带中文注释,Intel格式的:一个是不带注释是AT&T格式的. Linux 0.11 中文注释版 Linux 0.11 源码,基于<Linux内核完全注释 ...

最新文章

  1. 语言中knitr_R语言软件包的批量引用
  2. JavaScript: 代码简洁之道
  3. 如何保护 SpringBoot 配置文件中的敏感信息
  4. CowNew开源-sql解析引擎和cownewsql阶段成果汇报
  5. iframe如何发送请求_插件分享 | 如何半天玩转一个“ES未授权利用”插件
  6. 如今全球超级计算机运算速度排名,截至2019年(或2018年),全球超级计算机运算速度排名第一的是?...
  7. 人名和成绩一起排序_#excel中怎么让人名和他的成绩一起排序#excle排序 怎么弄同名次...
  8. SharePoint文档上传管理
  9. windows环境 wildfly-10.1.0.Final 安装、配置、部署
  10. [转载] java给对象中的包装类设置默认值
  11. 前序表达式 中序表达式 后序表达式
  12. php 获取文件给用户下载,让PHP更快的为用户提供文件下载_PHP教程
  13. c语言程序结课编程报告,C语言程序分析报告课程标准.doc
  14. 什么是类Unix系统?
  15. Linux之Shell编程详解
  16. 关于ColorPicker颜色拾取器的使用方法
  17. 元宇宙持续引发关注,微软计划明年发布相关产品 | 产业区块链发展周报
  18. SwiftUI中微信认证成功但App回调方法未被调用的解决
  19. 遥感影像反差增强、直方图均衡化
  20. 23考研| 你来了,准硕士!!!

热门文章

  1. Android用户界面设计学习之旅-第二站
  2. 在asp中怎么调用带输出参数的存储过程
  3. 硕士:论文提交和考试
  4. WHERE WILL BUSINESS PHD GO?
  5. 命令前面加一个!的意思如!python
  6. 【转】dijkstra算法
  7. Windows Vista 交互式服务编程
  8. 在Linux操作系统下使用虚拟光驱的方法
  9. Keepalived+Nginx 实现双机热备
  10. 红外热成像拥抱无人机 迸发安防救援新活力