📄 pci.c
字号:
#include <dos.h>
#include "pci.h"
#define I_VENDOR_ID 0x00
#define PCI_DEVICE_ID 0x02
#define PCI_CMD_REG 0x04
#define PCI_STATUS_REG 0x06
#define PCI_REV_ID 0x08 /* including the class code */
#define PCI_CACHE_LINE_SIZE 0x0C
#define PCI_LATENCY_TIMER 0x0D
#define PCI_HEAD_TYPE 0x0E
#define PCI_BIST 0x0F
#define PCI_BASE_ADDR_0 0x10
#define PCI_BASE_ADDR_1 0x14
#define PCI_BASE_ADDR_2 0x18
#define PCI_BASE_ADDR_3 0x1C
#define PCI_BASE_ADDR_4 0x20
#define PCI_BASE_ADDR_5 0x24
#define PCI_CIS_POINTER 0x28
#define PCI_SUB_VENDOR_ID 0x2C
#define PCI_SUB_SYSTEM_ID 0x2E
#define PCI_EXP_ROM_BASE 0x30
#define PCI_INTR_LINE 0x3C
#define PCI_INTR_PIN 0x3D
#define PCI_MIN_GNT 0x3E
#define PCI_MAX_LAT 0x3F
#define OFFSET_TO_DW_INDEX(x) ((x) & ~0x3)
#define OFFSET_TO_BYTE_INDEX(x) ((x) & 0x3)
/*---------------------------------------------------------------------*/
/* Ports and the bit patterns used by the Configuration Mechanism One */
/*---------------------------------------------------------------------*/
#define CFG_ADDR_REG 0x0CF8
#define CFG_DATA_REG 0x0CFC
#define CFG_SPACE_ENA 0x80000000
/*---------------------------------------------------------------------*/
/* Ports and the bit patterns used by the Configuration Mechanism Two */
/*---------------------------------------------------------------------*/
#define CFG_ENABLE_REG 0x0CF8
#define CFG_FORWARD_REG 0x0CFA
#define CFG_BASE_REG 0xC000
#define CFG_SPACE_KEY 0xF0
#define SPE_CYC_ENA 0x01
#define MULTI_FUNC_BIT 0x80
#define MAX_PCI_DEVICES 16
#define MAX_BUS_NUM 16 /* the maximum value is 256 */
#define MAX_DEV_NUM 32
#define MAX_FUNC_NUM 8
#define PCI_CFG_MECHANISM_1 1
#define PCI_CFG_MECHANISM_2 2
#define PCI_NO_DEVICE_ID 0xffffffff
#define USHORT unsigned short
#define ULONG unsigned long
#define UCHAR unsigned char
typedef struct pci_cfg_info
{
struct pci_cfg_info *next;
USHORT vendor_id;
USHORT dev_id;
USHORT pci_bus_num;
USHORT pci_dev_num;
USHORT pci_func_num;
USHORT rev_id;
USHORT base_class;
USHORT sub_class;
ULONG class_code;
USHORT subsys_vendor_id;
USHORT subsys_id;
ULONG cfg_addr;
} PCI_CFG_INFO;
static PCI_CFG_INFO pci_cfg_info[MAX_PCI_DEVICES];
unsigned long g_bridge_setting_IO;
USHORT pci_cfg_rd_w(ULONG addr, ULONG offset);
UCHAR pci_cfg_rd_b(ULONG addr, ULONG offset);
ULONG pci_cfg_rd_l(ULONG addr, ULONG offset);
static ULONG inpd(int portnum)
{
static ULONG value ;
asm mov dx,portnum ;
asm lea bx,value ;
__emit__(0x66,0x50, // push EAX
0x66,0xED, // in EAX,DX
0x66,0x89,0x07, // mov [BX],EAX
0x66,0x58) ; // pop EAX
return value ;
}
static void outpd(int portnum, ULONG val)
{
static ULONG value = 0 ;
value = val ;
asm mov dx,portnum ;
asm lea bx,value ;
__emit__(0x66,0x50, // push EAX
0x66,0x8B,0x07, // mov EAX,[BX]
0x66,0xEF, // out DX,EAX
0x66,0x58) ; // pop EAX
return ;
}
PCI_CFG_INFO * get_pci_cfg_info_tbl()
{
PCI_CFG_INFO *pinfo;
ULONG dnum, fnum, bus_num;
ULONG addr, addr_f;
ULONG tmpl;
ULONG tmps;
ULONG pci_found;
pinfo = &pci_cfg_info[0];
pci_found = 0;
for(bus_num=0; bus_num < MAX_BUS_NUM; bus_num++)
{
for(dnum=0; dnum < MAX_DEV_NUM; dnum++)
{
addr = (bus_num << 16) | (dnum << 11);
for(fnum=0; fnum < MAX_FUNC_NUM; fnum++)
{
/*---------------------------------------------------------*/
/* read vendor and device IDs and check them */
/*---------------------------------------------------------*/
addr_f = addr | (fnum << 8);
tmpl = pci_cfg_rd_l(addr_f, 0);
if(tmpl == PCI_NO_DEVICE_ID)
break;
pinfo->vendor_id = tmpl & 0xFFFF;
pinfo->dev_id = (tmpl >> 16) & 0xFFFF;
pinfo->pci_bus_num = bus_num;
pinfo->pci_dev_num = dnum;
pinfo->pci_func_num = fnum;
pinfo->subsys_id = pci_cfg_rd_w(addr_f,
PCI_SUB_VENDOR_ID);
pinfo->subsys_vendor_id = pci_cfg_rd_w(addr_f,
PCI_SUB_SYSTEM_ID);
tmpl = pci_cfg_rd_l(addr_f, PCI_REV_ID);
pinfo->rev_id = tmpl & 0xf;
pinfo->class_code = (tmpl >> 8) & 0xffffff;
pinfo->base_class = (tmpl >> 24) & 0xff;
pinfo->sub_class = (tmpl >> 16) & 0xff;
pinfo->cfg_addr = addr_f;
pci_found++;
if(pci_found >= MAX_PCI_DEVICES)
break;
pinfo->next = &pci_cfg_info[pci_found];
pinfo = pinfo->next;
tmpl = pci_cfg_rd_b(addr| (fnum << 8), PCI_HEAD_TYPE);
if(!(tmpl & MULTI_FUNC_BIT))
break;
}
}
}
pinfo->next = 0;
return &pci_cfg_info[0];
} /* get_pci_cfg_info_tbl() */
ULONG pci_cfg_read(ULONG dev_idx, ULONG offset, ULONG bytes)
{
ULONG addr;
addr = pci_cfg_info[dev_idx].cfg_addr;
if(bytes == 1)
return pci_cfg_rd_b(addr, offset);
else if(bytes == 2)
return pci_cfg_rd_w(addr, offset);
else
return pci_cfg_rd_l(addr, offset);
}
USHORT pci_cfg_rd_w(ULONG addr, ULONG offset)
{
USHORT wtmp;
addr |= CFG_SPACE_ENA;
outpd(CFG_ADDR_REG, addr | OFFSET_TO_DW_INDEX(offset));
wtmp = inport(CFG_DATA_REG | OFFSET_TO_BYTE_INDEX(offset));
outpd(CFG_ADDR_REG, 0);
return wtmp;
} /* pci_cfg_rd_w() */
UCHAR pci_cfg_rd_b(ULONG addr, ULONG offset)
{
UCHAR btmp;
addr |= CFG_SPACE_ENA;
outpd(CFG_ADDR_REG, addr | OFFSET_TO_DW_INDEX(offset));
btmp = inportb(CFG_DATA_REG | OFFSET_TO_BYTE_INDEX(offset));
outpd(CFG_ADDR_REG, 0);
return btmp;
} /* pci_cfg_rd_b() */
ULONG pci_cfg_rd_l(ULONG addr, ULONG offset)
{
ULONG ltmp;
addr |= CFG_SPACE_ENA;
outpd(CFG_ADDR_REG, addr | OFFSET_TO_DW_INDEX(offset));
ltmp = inpd(CFG_DATA_REG);
outpd(CFG_ADDR_REG, 0);
return ltmp;
} /* pci_cfg_rd_l() */
ULONG findPCIdev(ULONG classcode, ULONG *puBaseAddress, ULONG *puIntLevel)
{
PCI_CFG_INFO *pci_tblp;
ULONG dev_idx;
ULONG uHostType;
ULONG uRetVal;
ULONG uData;
dev_idx = 0;
pci_tblp = get_pci_cfg_info_tbl();
/*************************************/
/* No PCI device found in the system */
/*************************************/
if(pci_tblp->vendor_id == 0xffff && pci_tblp->dev_id == 0xffff) {
return 0;
}
/*************************************/
/* Search for USB host controllers */
/*************************************/
while (pci_tblp) {
/* Is it the end of pSOS PCI device table? */
if (pci_tblp->vendor_id == 0xffff && pci_tblp->dev_id == 0xffff)
break;
/* Is it a USB host controller? */
if (pci_tblp->class_code == classcode) {
*puBaseAddress = pci_cfg_read(dev_idx, PCI_BASE_ADDR_2, 4UL) & 0xFFFFFFF0;
g_bridge_setting_IO = pci_cfg_read(dev_idx, PCI_BASE_ADDR_1, 4UL) & 0xFFFFFFF0;
*puIntLevel = pci_cfg_read(dev_idx, PCI_INTR_LINE, 1UL);
return 1;
} /* if */
dev_idx++;
pci_tblp = pci_tblp->next;
} /* while */
return 0;
} /* findPCIdev() */
void set_pci_bridge( void )
{
unsigned long wait_cycle=3L;
unsigned long tmp;
tmp = inpd (g_bridge_setting_IO + 0x18);
tmp &= ~0x0000003C; // mask register[5..2]
tmp |= wait_cycle << 2;
outpd(g_bridge_setting_IO + 0x18, tmp);
outpd( g_bridge_setting_IO + 0x68, 0x00000900 );
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -