Chinaunix首页 | 论坛 | 博客
  • 博客访问: 199229
  • 博文数量: 29
  • 博客积分: 1280
  • 博客等级: 中尉
  • 技术积分: 320
  • 用 户 组: 普通用户
  • 注册时间: 2005-02-22 16:23
文章分类

全部博文(29)

文章存档

2009年(3)

2008年(1)

2007年(1)

2006年(3)

2005年(21)

我的朋友

分类: BSD

2006-05-09 13:55:43

#include
__FBSDID("$FreeBSD: src/sys/i386/bios/mca_machdep.c,v 1.9 2004/08/31 21:51:51 mdodd Exp $");

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include

#include
#include

/* 全局微通道总线标志,0代表没有微通道,1代表有*/
int MCA_system = 0;

/* 由BIOS的15号C0字功能调用后返回的系统配置结构 */
struct sys_config {
 u_int16_t count;
 u_int8_t model;
 u_int8_t submodel;
 u_int8_t bios_rev;
 u_int8_t feature;
#define FEATURE_MCAISA 0x01 /* 含有微通道和ISA总线*/
#define FEATURE_MCABUS 0x02 /* 含有微通道  */
#define FEATURE_EBDA 0x04 /* 扩充的BIOS数据区被分配*/
#define FEATURE_WAITEV 0x08 /* 支持扩充事件等待*/
#define FEATURE_KBDINT 0x10 /* INT 09H 中断为键盘*/
#define FEATURE_RTC 0x20 /* 实时钟存在*/
#define FEATURE_IC2 0x40 /* 第二中断芯片存在*/
#define FEATURE_DMA3 0x80 /* DMA 通道 3 由磁盘BIOS使用*/
 u_int8_t pad[3];
} __packed;

/* 函数原形 */
static void bios_mcabus_present (void *);
SYSINIT(mca_present, SI_SUB_CPU, SI_ORDER_ANY, bios_mcabus_present, NULL);

/* Functions */
static void
bios_mcabus_present(void * dummy)
{
 struct vm86frame vmf; /*CPU的寄存器结构,可以32位,16位,8位表示法.见/sys/i386/include/vm86.h*/
 struct sys_config * scp;
 vm_offset_t  paddr;

 bzero(&vmf, sizeof(struct vm86frame));/*分配一段内存(按字节方式,因为寄存器可描述到字节,即8位,如AH,AL等)*/

 vmf.vmf_ah = 0xc0;/*准备BIOS中断调用,准备调用的AH寄存器对应结构成员放入C0,*/
 if (vm86_intcall(0x15, &vmf)) {/*BIOS中断调用INT 15,我的中断大全丢了,没查到,看下文估计是PS/2鼠标?*/
  /* bootverbose参数在init_main.c主程序中申明.意思是在启动时候是否打印出一些问题细节.文件的申明如下:
  int bootverbose;
  SYSCTL_INT(_debug, OID_AUTO, bootverbose, CTLFLAG_RW, &bootverbose, 0, "");
  该变量位于debug节点下.可以用sysctl debug.bootverbose来显示,由于读写标记为CTLFLAG_RW,说明它可以设置的.
  */
  if (bootverbose) {
   printf("BIOS SDT: INT call failed.\n");
  }
  return;
 }

 if ((vmf.vmf_ah != 0) && (vmf.vmf_flags & 0x01)) {/*AH寄存器返回值为非0并且标志位的第一位置位,有错误*/
  if (bootverbose) {
   printf("BIOS SDT: Not supported.  Not PS/2?\n");
   printf("BIOS SDT: AH 0x%02x, Flags 0x%04x\n",
    vmf.vmf_ah, vmf.vmf_flags);
  }
  return;
 }

 paddr = vmf.vmf_es;/*中断调用后返回数据在ES:BX中*/
 paddr = (paddr << 4) + vmf.vmf_bx;
 scp = (struct sys_config *)BIOS_PADDRTOVADDR(paddr);/*强制paddr指向的是一sys_config结构*/
 /*在/sys/i386/include/pc/bios.h中对宏的申明#define BIOS_PADDRTOVADDR(x) ((x) + KERNBASE)
 关于KERNBASE宏可以在vmparam.h中找到.不过关于KERNBASE核心基地址涉及到几个头文件.如PMAP等等
 */

 if (bootverbose) {
  printf("BIOS SDT: model 0x%02x, submodel 0x%02x, bios_rev 0x%02x\n",
   scp->model, scp->submodel, scp->bios_rev);
  printf("BIOS SDT: features 0x%b\n", scp->feature,
   "\20"
   "\01MCA+ISA"
   "\02MCA"
   "\03EBDA"
   "\04WAITEV"
   "\05KBDINT"
   "\06RTC"
   "\07IC2"
   "\08DMA3"
   "\n");
 }

 MCA_system = ((scp->feature & FEATURE_MCABUS) ? 1 : 0);/*是微通道总线吗?*/

 if (MCA_system)
  printf("MicroChannel Architecture System detected.\n");

 return;
}

int
mca_bus_nmi (void)
/*
在/sys/i386/isa/nmi.c中对其调用.用于微通道总线不可屏蔽的中断处理程序的一支撑函数
该程序的被调用有个前提,MAC_system=1即机器有微通道总线.
*/
{
 int slot;
 int retval = 0;
 int pos5 = 0;

 /* 关闭主板设置寄存器. mca_busreg.h(74)定义了I/O口:#define MCA_MB_SETUP_REG 0x94 */
 outb(MCA_MB_SETUP_REG, MCA_MB_SETUP_DIS);

 /* 搜寻每个槽位 */
 for (slot = 0; slot < MCA_MAX_SLOTS; slot++) {/*每总线的最大槽数为8个*/

  /* Select the slot */
  outb(MCA_ADAP_SETUP_REG, slot | MCA_ADAP_SET); /*MCA_ADAP_SETUP_REG是适配器设置寄存器*/
  pos5 = inb(MCA_POS_REG(MCA_POS5));

  /* If Adapter Check is low */
  if ((pos5 & MCA_POS5_CHCK) == 0) {/*如果pos5的第8位置位(代表有设备)*/
   retval++;/*设备数加1*/

  
   if ((pos5 & MCA_POS5_CHCK_STAT) == 0) {/*如果pos5的第7位置位(代表设备状态是可用的)*/
    printf("MCA NMI: slot %d, POS6=0x%02x, POS7=0x%02x\n",
     slot+1,
     inb( MCA_POS_REG(MCA_POS6) ),
     inb( MCA_POS_REG(MCA_POS7) ));
   } else {
    printf("MCA NMI: slot %d\n", slot+1);
   }
  }
  /* 暂时关闭适配器的设置,在mca_bus.c中(微通道驱动)会进一步配置 */
  outb(MCA_ADAP_SETUP_REG, MCA_ADAP_SETUP_DIS);
 }

 return (retval);/*返回有多少个槽上有可用设备*/
}

阅读(2704) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~