分类: 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);/*返回有多少个槽上有可用设备*/
}