在汇编的代码里,已经进行了串口初始化,在这里更进一步初始化串口,它是通过调用下面的代码实现的:
#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);
}
经历上面很多寄存器的初始化,才把南桥的功能设置完成。
查看本文来源