网络安全参考 | UNIX参考 | GPS参考 | 无线参考 | 在线手册 | OSBUG.ORG | SUNNY-NETWORK.COM
天线制作 GPS 地标
网站地图 RSS订阅
高级搜索 收藏本站
Home | 业界动态 | Open source | GNU | Linux | BSD | Solaris | AIX | HP-UX | IRIX | Mac OS X | Minix | Tru64 | SCO UNIX | Network | Security | X-Window | Database | 应用服务 | Programming | 经典著作 | 永远的纪念 | 杂项
 当前位置: Home > Linux > 设备驱动 > 文章  
Linux设备驱动编程之内存与I/O操作
文章来源: 天极开发 文章作者: 宋宝华 发布时间: 2006-10-27   字体: [ ]  
 

  这两个函数都是实现在mm/ioremap.c文件中。

  在将I/O内存资源的物理地址映射成核心虚地址后,理论上讲我们就可以象读写RAM那样直接读写I/O内存资源了。为了保证驱动程序的跨平台的可移植性,我们应该使用Linux中特定的函数来访问I/O内存资源,而不应该通过指向核心虚地址的指针来访问。如在x86平台上,读写I/O的函数如下所示:

#define readb(addr) (*(volatile unsigned char *) __io_virt(addr))
#define readw(addr) (*(volatile unsigned short *) __io_virt(addr))
#define readl(addr) (*(volatile unsigned int *) __io_virt(addr))

#define writeb(b,addr) (*(volatile unsigned char *) __io_virt(addr) = (b))
#define writew(b,addr) (*(volatile unsigned short *) __io_virt(addr) = (b))
#define writel(b,addr) (*(volatile unsigned int *) __io_virt(addr) = (b))

#define memset_io(a,b,c) memset(__io_virt(a),(b),(c))
#define memcpy_fromio(a,b,c) memcpy((a),__io_virt(b),(c))
#define memcpy_toio(a,b,c) memcpy(__io_virt(a),(b),(c))

  最后,我们要特别强调驱动程序中mmap函数的实现方法。用mmap映射一个设备,意味着使用户空间的一段地址关联到设备内存上,这使得只要程序在分配的地址范围内进行读取或者写入,实际上就是对设备的访问。

  笔者在Linux源代码中进行包含"ioremap"文本的搜索,发现真正出现的ioremap的地方相当少。所以笔者追根索源地寻找I/O操作的物理地址转换到虚拟地址的真实所在,发现Linux有替代ioremap的语句,但是这个转换过程却是不可或缺的。

  譬如我们再次摘取S3C2410这个ARM芯片RTC(实时钟)驱动中的一小段:

static void get_rtc_time(int alm, struct rtc_time *rtc_tm)
{
 spin_lock_irq(&rtc_lock);
 if (alm == 1) {
  rtc_tm->tm_year = (unsigned char)ALMYEAR & Msk_RTCYEAR;
  rtc_tm->tm_mon = (unsigned char)ALMMON & Msk_RTCMON;
  rtc_tm->tm_mday = (unsigned char)ALMDAY & Msk_RTCDAY;
  rtc_tm->tm_hour = (unsigned char)ALMHOUR & Msk_RTCHOUR;
  rtc_tm->tm_min = (unsigned char)ALMMIN & Msk_RTCMIN;
  rtc_tm->tm_sec = (unsigned char)ALMSEC & Msk_RTCSEC;
 }
 else {
  read_rtc_bcd_time:
  rtc_tm->tm_year = (unsigned char)BCDYEAR & Msk_RTCYEAR;
  rtc_tm->tm_mon = (unsigned char)BCDMON & Msk_RTCMON;
  rtc_tm->tm_mday = (unsigned char)BCDDAY & Msk_RTCDAY;
  rtc_tm->tm_hour = (unsigned char)BCDHOUR & Msk_RTCHOUR;
  rtc_tm->tm_min = (unsigned char)BCDMIN & Msk_RTCMIN;
  rtc_tm->tm_sec = (unsigned char)BCDSEC & Msk_RTCSEC;

  if (rtc_tm->tm_sec == 0) {
   /* Re-read all BCD registers in case of BCDSEC is 0.
   See RTC section at the manual for more info. */
   goto read_rtc_bcd_time;
  }
 }
 spin_unlock_irq(&rtc_lock);

 BCD_TO_BIN(rtc_tm->tm_year);
 BCD_TO_BIN(rtc_tm->tm_mon);
 BCD_TO_BIN(rtc_tm->tm_mday);
 BCD_TO_BIN(rtc_tm->tm_hour);
 BCD_TO_BIN(rtc_tm->tm_min);
 BCD_TO_BIN(rtc_tm->tm_sec);

 /* The epoch of tm_year is 1900 */
 rtc_tm->tm_year += RTC_LEAP_YEAR - 1900;

 /* tm_mon starts at 0, but rtc month starts at 1 */
 rtc_tm->tm_mon--;
}

  I/O操作似乎就是对ALMYEAR、ALMMON、ALMDAY定义的寄存器进行操作,那这些宏究竟定义为什么呢?

 
推荐文章
·让arm-linux支持普通USB摄像头
·Linux设备驱动编程之结构化设备
·Linux设备驱动编程之复杂设备驱
·深入浅出Linux设备驱动之并发控
·深入浅出Linux设备驱动之字符设
·深入浅出Linux设备驱动编程之内
·深入浅出Linux设备驱动编程之引
·Linux设备驱动编程之定时器
·Linux设备驱动编程之中断处理
·Linux设备驱动编程之异步通知
·Linux设备驱动编程之阻塞与非阻
·摄像头(WebCam)在Linux操作系
·中星微芯片(301,302)USB 摄像头
·Linux的I2C驱动架构
 

 
↑返回顶部   打印本页   关闭窗口↓  

Google
 
Web oldhand.org unixreference.net meshmea.org
相关分类
热点文章
·摄像头(WebCam)在Linu
·在Linux中使用中星微301
·中星微芯片(301,302)USB
·深入浅出Linux设备驱动
·Linux培训园地:Linux下
·Linux的I2C驱动架构
·让arm-linux支持普通USB
·Linux设备驱动编程之复
相关文章
·Linux设备驱动编程之阻
·Linux设备驱动编程之异
·Linux设备驱动编程之中
·ARM的嵌入式Linux移植体
·Linux设备驱动编程之定
·深入浅出Linux设备驱动
·深入浅出Linux设备驱动
·深入浅出Linux设备驱动
更多...
 
 

Copyright(c) 2001-2009 OLDHAND ORGANIZATION, All Rights reserved.
Power by DedeCms 织梦内容管理系统