文章详情

  • 游戏榜单
  • 软件榜单
关闭导航
热搜榜
热门下载
热门标签
php爱好者> php文档>linux 1.0 内核注解 linux/kernel/ioport.c

linux 1.0 内核注解 linux/kernel/ioport.c

时间:2009-03-09  来源:taozhijiangscu

/********************************************
 *Created By: 陶治江
 *Date:       2009-3-7
 ********************************************/
#include <linux/sched.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/types.h>
#include <linux/ioport.h>
static unsigned long ioport_registrar[IO_BITMAP_SIZE] = {0, /* ... */}; #define _IODEBUG #ifdef IODEBUG //将l实际的位图数字转换为字符串形式
static char * ios(unsigned long l)
{
 static char str[33] = { '\0' };
 int i;
 unsigned long mask;
 for (i = 0, mask = 0x80000000; i < 32; ++i, mask >>= 1)
  str[i] = (l & mask) ? '1' : '0';
 return str;
}
//显示当前进程的IO位图
static void dump_io_bitmap(void)
{
 int i, j;
 //unsigned long io_bitmap[IO_BITMAP_SIZE+1];
 //IO_BITMAP_SIZE=32
 
 int numl = sizeof(current->tss.io_bitmap) >> 2;
 for (i = j = 0; j < numl; ++i)
 {
  printk("%4d [%3x]: ", 64*i, 64*i);  //64位一显示
  printk("%s ", ios(current->tss.io_bitmap[j++]));
  if (j < numl)
   printk("%s", ios(current->tss.io_bitmap[j++]));
  printk("\n");
 }
}
#endif
asmlinkage void set_bitmap(unsigned long *bitmap,
         short base, short extent, int new_value)
{
 int mask;
 unsigned long *bitmap_base = bitmap + (base >> 5); 
   //>>5就是*8变成比特,*4变成long类型
 unsigned short low_index = base & 0x1f;  //就是获得long对其后的低位
 int length = low_index + extent;
 if (low_index != 0) {
  mask = (~0 << low_index);   //将低位的32位转换为位图模式
  if (length < 32)
    mask &= ~(~0 << length);
    
  if (new_value)  //1表示设置,0表示取消
   *bitmap_base++ |= mask;
  else
   *bitmap_base++ &= ~mask;
  length -= 32;
 }
 //呃,下面都是32为单位操作了
 
 mask = (new_value ? ~0 : 0);
 while (length >= 32) {
  *bitmap_base++ = mask;
  length -= 32;
 }
 if (length > 0) {
  mask = ~(~0 << length);  //剩下的零碎的位
  if (new_value)
   *bitmap_base++ |= mask;
  else
   *bitmap_base++ &= ~mask;
 }
}
//呃,基本的操作的原理是同上面相类似的,检测的范围只要有
//置位就返回1,否则如果全部复位就返回0
asmlinkage int check_bitmap(unsigned long *bitmap, short base, short extent)
{
 int mask;
 unsigned long *bitmap_base = bitmap + (base >> 5);
 unsigned short low_index = base & 0x1f;
 int length = low_index + extent;
 if (low_index != 0) {
  mask = (~0 << low_index);
  if (length < 32)
    mask &= ~(~0 << length);
  if (*bitmap_base++ & mask)
   return 1;
  length -= 32;
 }
 while (length >= 32) {
  if (*bitmap_base++ != 0)
   return 1;
  length -= 32;
 }
 if (length > 0) {
  mask = ~(~0 << length);
  if (*bitmap_base++ & mask)
   return 1;
 }
 return 0;
}
//从from开始设置连续num个端口的状态,内核的手册上说
//使用fork是不会继承端口设置的,但是使用execv是会继承的
asmlinkage int sys_ioperm(unsigned long from, unsigned long num, int turn_on)
{
 if (from + num <= from)
  return -EINVAL;
 if (from + num > IO_BITMAP_SIZE*32)  //只能对0x3ff以下的端口进行设置
  return -EINVAL;
 if (!suser())
  return -EPERM;
#ifdef IODEBUG
 printk("io: from=%d num=%d %s\n", from, num, (turn_on ? "on" : "off"));
#endif
 set_bitmap((unsigned long *)current->tss.io_bitmap, from, num, !turn_on);
 return 0;
}
unsigned int *stack; //这个是通过系统调用设置eflags的io特权级来设置的
//设置当前进程的io特权级到level指定的值
//如果使得CPL<=IOPL成立就不用检查IO位图了,同时这对于
//0x3ff以上的65536全端口是唯一的控制了
asmlinkage int sys_iopl(long ebx,long ecx,long edx,
      long esi, long edi, long ebp, long eax, long ds,
      long es, long fs, long gs, long orig_eax,
      long eip,long cs,long eflags,long esp,long ss)
{
 unsigned int level = ebx;
 if (level > 3)
  return -EINVAL;
 if (!suser())
  return -EPERM;
 *(&eflags) = (eflags & 0xffffcfff) | (level << 12);
 return 0;
}
//实际的被外部调用的函数
void snarf_region(unsigned int from, unsigned int num)
{
 if (from > IO_BITMAP_SIZE*32)
  return;
 if (from + num > IO_BITMAP_SIZE*32)
  num = IO_BITMAP_SIZE*32 - from;
 set_bitmap(ioport_registrar, from, num, 1);
 return;
}
int check_region(unsigned int from, unsigned int num)
{
 if (from > IO_BITMAP_SIZE*32)
  return 0;
 if (from + num > IO_BITMAP_SIZE*32)
  num = IO_BITMAP_SIZE*32 - from;
 return check_bitmap(ioport_registrar, from, num);
}
// Called from init/main.c to reserve IO ports. 设置保留的IO端口
void reserve_setup(char *str, int *ints)
{
 int i;
 for (i = 1; i < ints[0]; i += 2)
  snarf_region(ints[i], ints[i+1]);
}
  文档地址:http://blogimg.chinaunix.net/blog/upfile2/090309215536.pdf
相关阅读 更多 +
排行榜 更多 +
几何飞行内购修改版

几何飞行内购修改版

飞行射击 下载
别踩白块内购修改版

别踩白块内购修改版

休闲益智 下载
乐涂数字填色游戏

乐涂数字填色游戏

休闲益智 下载