在汇编的代码里,已经进行了串口初始化,在这里更进一步初始化串口,它是通过调用下面的代码实现的:
#define
SUPERIO_CFG_REG 0x85
上面定义南桥里串口寄存器地址。
static
void initSerial(void)
{
pcitag_t tag;
char confval,val;
/*
使能串口
*
这个需要在汇编代码serialinit中设置
* */
#define
E2_EPP 2
#define
E2_S1 (1<<2)
#define
E2_S2 (1<<3)
#define
E2_FLOPPY (1<<4)
/*
配置super io*/
tag=_pci_make_tag(VTSB_BUS,VTSB_DEV, VTSB_ISA_FUNC);
confval=_pci_conf_readn(tag,SUPERIO_CFG_REG,1);
_pci_conf_writen(tag,SUPERIO_CFG_REG,confval|2,1);
上面根据
VT82C686B
来操作,主要是设置
SUPER IO
能配置,也就是设置
0x85
寄存器的第二位为
1
时为开始配置。根据
VT82C686B
的操作流程如下:
第一步,设置
0x85
寄存器的第二位的为
1
时可以配置。
第二步,写一个要操作的索引到
0x3F0
,然后写配置的数据到
0x3F1
。当要配置多端口时,可以重复地写不同的索引和配置。
第三步,设置
0x85
寄存器的第二位的为
0
时结束配置。
#ifdef
HIGH_SPEED_SERIAL
linux_outb(0xee,0x3f0);
val=linux_inb(0x3f1);
linux_outb(val|0xc0,0x3f1); /* both ports on high speed*/
#endif
#if
0
outb(PCI_IO_SPACE_BASE+0x3f0,0xe7);
outb(PCI_IO_SPACE_BASE+0x3f1,(COM1_BASE_ADDR-PCI_IO_SPACE_BASE)>>2); /* com1 serial base address*/
outb(PCI_IO_SPACE_BASE+0x3f0,0xe8);
outb(PCI_IO_SPACE_BASE+0x3f1,(COM2_BASE_ADDR-PCI_IO_SPACE_BASE)>>2); /* com2 serial base address*/
#endif
linux_outb(0xe2,0x3f0);
val=linux_inb(0x3f1);
linux_outb(val|E2_S2|E2_S1,0x3f1);
_pci_conf_writen(tag,SUPERIO_CFG_REG,confval,1);
上面操作索引为
0xE2
,设置的配置值的意思是打开并口为
EPP
模式,串口
1
和串口
2
打开,并且软驱打开。
printf("0x3f8=%x/n",linux_inb(0x3f0));
上面显示
0x3F0
的值。
}
接着来看初始化键盘,
static
void init_keyboard(void)
{
pcitag_t tag;
tag=_pci_make_tag(VTSB_BUS,VTSB_DEV, VTSB_ISA_FUNC);
_pci_conf_writen(tag,0x5a,0xff,1);
}
上面是打开键盘和
RTC
的功能,打开声音功能,打开
SD
数据线
4—7
的信号为
1
。
接着下来,就是初始化
IDE
端口的功能了,在龙芯里
IDE
主要接硬盘和光驱。它的代码如下:
#define
IDE_CHIPEN_REG 0x40
#define
IDE_CFG_REG 0x41
static
void initIDE(void)
{
pcitag_t tag;
char val;
/*
南桥外设默认都是非使能状态,我们这里将其一一使能*/
/*
硬盘使能*/
#if
1
/* IDE controller enable */
tag=_pci_make_tag(VTSB_BUS,VTSB_DEV, VTSB_ISA_FUNC);
val=_pci_conf_readn(tag,0x48,1);
val=val & ~2;
_pci_conf_writen(tag,0x48,val,1);
上面打开
IDE
功能,由于南桥里定义
0
为使用,所以上面置第二位的值为
0
。
/* IDE IRQ Route */
val=_pci_conf_readn(tag,0x4a,1);
val=(val&0xf0)|0x4;
_pci_conf_writen(tag,0x4a,val,1);
上面设置第一个
IDE
使用
14
号中断源,第二个
IDE
使用
15
号中断源。
#endif
tag=_pci_make_tag(VTSB_BUS,VTSB_DEV, VTSB_IDE_FUNC);
/* enable IO space */
_pci_conf_writen(tag,0x04,7,1);
上面使用
IO
空间,使用内存空间并设置为总线主设备。
/* set to compatible mode */
_pci_conf_writen(tag,0x09,0x8A,1);
上面全部设置为固定模式。也就是主
IDE
的命令寄存器是
0x1F0—0x1F7
,从
IDE
的命令寄存器是
0x170—0x177
。
/* latency */
_pci_conf_writen(tag,0x0d,0xd0,1);
上面设置
RTC
时钟使用
VBAT
电压。
/* set to legacy interrupt */
_pci_conf_writen(tag,0x3d,0x00,1);
上面设置中断方式为一般方式。
/* enable primary/secondary channel */
_pci_conf_writen(tag,0x40,0xb,0x1);
上面打开
IDE
第一和第二通道。
/* disable prefetch buffer & post write buffer */
_pci_conf_writen(tag,0x41,0x2,0x1);
_pci_conf_writen(tag,0x43,0xa,0x1);
上面关闭所有
IDE
缓冲区,配置
FIFO
的最大值为一半。
/* set zero wait state for master read/write
* to make ict nb happy
*/
_pci_conf_writen(tag,0x44,0x0,1);
上面设置读写等待信号为
0
电平。
/* disable memory read multiple/memory write and invalidate
*/
_pci_conf_writen(tag,0x45,0x0,1);
上面关闭内存读写多个命令。
#if
1
_pci_conf_writen(tag, 0x10, 0x1f1,4);
上面设置第一个
IDE
的命令基地址为
0x1F1.
_pci_conf_writen(tag, 0x14, 0x3f5,4);
上面设置第一个
IDE
的控制和状态寄存器的基地址为
0x3F5
。
_pci_conf_writen(tag, 0x18, 0x171,4);
_pci_conf_writen(tag, 0x1c, 0x375,4);
上面设置第二个
IDE
的命令和状态基地址。
_pci_conf_writen(tag, 0x20, 0xcc1,4);
上面设置总线控制的基地址。
#endif
}
接着初始化中断控制,代码如下:
#define
IRQ_ROUTE_REG1 0x51
#define
IRQ_ROUTE_REG2 0x52
#define
IRQ_ROUTE_REG4 0x55
#define
IRQ_ROUTE_REG5 0x56
#define
IRQ_ROUTE_REG6 0x57
#define
PCI_IRQ_TYPE_REG 0x54
#define
IRQ(x) x
#define
PARALLEL_IRQ (IRQ(7)<<4)
#define
FLOPPY_IRQ (IRQ(6))
#define
COM1_IRQ (IRQ(4))
#define
COM2_IRQ (IRQ(3)<<4)
#define
PCIA_IRQ (IRQ(10)<<4)
#define
PCIB_IRQ (IRQ(11))
#define
PCIC_IRQ (IRQ(12)<<4)
#define
PCID_IRQ (IRQ(13)<<4)
static
void initIRQ(void)
{
pcitag_t tag;
char val;
tag=_pci_make_tag(VTSB_BUS,VTSB_DEV, VTSB_ISA_FUNC);
_pci_conf_writen(tag,IRQ_ROUTE_REG1,PARALLEL_IRQ|FLOPPY_IRQ,1);
上面启用并口和软盘中断。
_pci_conf_writen(tag,IRQ_ROUTE_REG2,COM2_IRQ|COM1_IRQ,1);
上面启用串口
1
和串口
2
中断。
val=_pci_conf_readn(tag,IRQ_ROUTE_REG4,1);
val &=0xf;
val |=PCIA_IRQ;
_pci_conf_writen(tag,IRQ_ROUTE_REG4,val,1);
上面配置
PCI
的
A
插槽的中断为
10
号。
_pci_conf_writen(tag,IRQ_ROUTE_REG5,PCIC_IRQ|PCIB_IRQ,1);
上面设置
B,C
的中断号
11
,
12
。
val=_pci_conf_readn(tag,IRQ_ROUTE_REG6,1);
val &=0xf0;
val |=PCID_IRQ;
_pci_conf_writen(tag,IRQ_ROUTE_REG6,val,1);
上面设置
D
的中断为
13
。
val=_pci_conf_readn(tag,PCI_IRQ_TYPE_REG,1);
val &= 0xf0;
_pci_conf_writen(tag,PCI_IRQ_TYPE_REG,PARALLEL_IRQ|FLOPPY_IRQ,1);
上面设置为低电平中断模式。
}
这样就初始化中断源了。接着就启用
IO
的功能,如下:
static
void enable_io_decode(void)
{
pcitag_t tag;
char val;
tag=_pci_make_tag(VTSB_BUS,VTSB_DEV, VTSB_ISA_FUNC);
/*enable on-board io*/
val=_pci_conf_readn(tag,0x81,1);
_pci_conf_writen(tag,0x81,val|0x80,1);
/*enable com1 and com2*/
_pci_conf_writen(tag,0x83,0x80|0x1| 0x8,1);
}
经历上面很多寄存器的初始化,才把南桥的功能设置完成。