📄 pcicfg.cpp
字号:
...
char* -> next vendor or 0
WORD vendor ID
ASCIZ vendor name
.....
*/
/************************************************************************/
/* Helper Functions */
/************************************************************************/
static void get_exe_directory(const char *argv0)
{
char *pathname = (char*)malloc(strlen(argv0)+2) ;
strcpy(pathname,argv0) ;
// strip off any existing extension
char *slash = strrchr(pathname,'/') ;
char *backslash = strrchr(pathname,'\\') ;
if (backslash && (!slash || backslash > slash))
slash = backslash ;
if (slash)
*slash = '\0' ;
else
strcpy(pathname,".") ;
exe_directory = pathname ;
}
//----------------------------------------------------------------------
static const char *skip_whitespace(const char *line)
{
while (*line && isspace(*line))
line++ ;
return line ;
}
//----------------------------------------------------------------------
inline char *skip_whitespace(char *line)
{
return (char*)skip_whitespace((const char *)line) ;
}
//----------------------------------------------------------------------
static int is_comment_line(const char *line,int pcicfg_format = 0)
{
// if in Craig Hart's format, we want to skip the subsystem-vendor-ID
// lines (those starting with two tab characters) because PCICFG doesn't
// support them
if (!pcicfg_format && line[0] == '\t' && line[1] == '\t')
return TRUE ;
line = skip_whitespace(line) ;
// blank lines and lines whose first nonwhite character is a semicolon
// can be skipped as comments
if (*line == '\0' || *line == '\n' || *line == ';')
return TRUE ;
else
return FALSE ;
}
//----------------------------------------------------------------------
static int read_nonblank_line(char *buf, int size, FILE *fp, int pcicfg_format)
{
do {
buf[0] = '\0' ;
if (!fgets(buf,size,fp) || feof(fp))
return FALSE ;
} while (is_comment_line(buf,pcicfg_format)) ;
return TRUE ;
}
//----------------------------------------------------------------------
static WORD hextoint(const char *&digits)
{
WORD hex = 0 ;
while (isxdigit(*digits))
{
int digit = toupper(*digits++) - '0' ;
if (digit > 9)
digit -= ('A'-'0'-10) ;
hex = 16*hex + digit ;
}
return hex ;
}
//----------------------------------------------------------------------
static FILE *open_PCICFG_DAT(const char *fopen_mode)
{
int dir_len = strlen(exe_directory) ;
char *datafile = (char*)malloc(dir_len+15) ;
if (!datafile)
{
fprintf(stderr,"Insufficient memory for PCICFG.DAT pathname\n") ;
return FALSE ;
}
sprintf(datafile,"%s/PCICFG.DAT",exe_directory) ;
FILE *fp = fopen(datafile,fopen_mode) ;
free(datafile) ;
if (!fp)
fprintf(stderr,"Unable to open PCICFG.DAT in mode \"%s\"\n",fopen_mode) ;
return fp ;
}
//----------------------------------------------------------------------
static int backup_PCICFG_DAT()
{
int dir_len = strlen(exe_directory) ;
char *datafile = (char*)malloc(dir_len+15) ;
if (!datafile)
{
fprintf(stderr,"Insufficient memory for PCICFG.DAT pathname\n") ;
return FALSE ;
}
sprintf(datafile,"%s/PCICFG.DAT",exe_directory) ;
FILE *fp = fopen(datafile,"r") ;
if (!fp)
{
free(datafile) ;
return FALSE ;
}
strcpy(datafile+strlen(datafile)-4,".BAK") ;
FILE *backup = fopen(datafile,"w") ;
if (!backup)
{
free(datafile) ;
return FALSE ;
}
char buffer[BUFSIZ] ;
int count ;
int success = TRUE ;
while ((count = fread(buffer,sizeof(char),sizeof(buffer),fp)) > 0)
{
if (fwrite(buffer,sizeof(char),count,backup) < count)
success = FALSE ;
}
fclose(fp) ;
fclose(backup) ;
if (!success)
{
fprintf(stderr,"Backup of PCICFG.DAT failed!\n") ;
unlink(datafile) ;
}
free(datafile) ;
return success ;
}
/************************************************************************/
/************************************************************************/
#if defined(__WATCOMC__) && defined(__386__)
extern DWORD inpd(int portnum) ;
#pragma aux inpd = \
"in eax,dx" \
parm [edx] \
value [eax] \
modify exact [eax] ;
#else
static DWORD inpd(int portnum)
{
static DWORD value ;
asm mov dx,portnum ;
asm lea bx,value ;
#if defined(__BORLANDC__)
__emit__(0x66,0x50, // push EAX
0x66,0xED, // in EAX,DX
0x66,0x89,0x07, // mov [BX],EAX
0x66,0x58) ; // pop EAX
#else
asm push eax
asm in eax,dx ;
asm mov [bx],eax ;
asm pop eax
#endif
return value ;
}
#endif /* __WATCOMC__ */
//----------------------------------------------------------------------
#if defined(__WATCOMC__) && defined(__386__)
extern void outpd(int portnum, DWORD value) ;
#pragma aux outpd = \
"out dx,eax" \
parm [edx][eax] \
modify exact [] ;
#else
static void outpd(int portnum, DWORD val)
{
static DWORD value = 0 ;
value = val ;
asm mov dx,portnum ;
asm lea bx,value ;
#if defined(__BORLANDC__)
__emit__(0x66,0x50, // push EAX
0x66,0x8B,0x07, // mov EAX,[BX]
0x66,0xEF, // out DX,EAX
0x66,0x58) ; // pop EAX
#else
asm push eax
asm mov eax,[bx] ;
asm out dx,eax ;
asm pop eax
#endif
return ;
}
#endif /* __WATCOMC__ */
//----------------------------------------------------------------------
#if defined(__WATCOMC__)
extern void outp(short portnumber, BYTE value) ;
#pragma aux outp = \
"out dx,al" \
parm [dx][al] \
modify exact [] ;
extern BYTE inp(short portnumber) ;
#pragma aux inp = \
"in al,dx" \
parm [dx] \
value [al] \
modify exact [al] ;
#endif /* __WATCOMC__ */
/************************************************************************/
/************************************************************************/
static int check_PCI_BIOS()
{
union REGS regs ;
#if defined(__WATCOMC__) && defined(__386__)
regs.w.ax = 0xB101 ;
int386(0x1A,®s,®s) ;
#else
regs.x.ax = 0xB101 ;
int86(0x1A,®s,®s) ;
#endif /* __WATCOMC__ && __386__ */
if (regs.h.ah == 0x00)
return regs.h.cl ; // last PCI bus in system
else
return -1 ; // no PCI BIOS detected
}
//----------------------------------------------------------------------
static void determine_cfg_mech()
{
union REGS regs ;
#if defined(__WATCOMC__) && defined(__386__)
regs.w.ax = 0xB101 ;
int386(0x1A,®s,®s) ;
#else
regs.x.ax = 0xB101 ;
int86(0x1A,®s,®s) ;
#endif /* __WATCOMC__ && __386__ */
if (regs.h.ah == 0x00)
{
// we have a PCI BIOS, so check which configuration mechanism(s) it
// supports
int mechs = regs.h.al & 0x03 ;
if (mechs & 0x01)
cfg_mech = 1 ;
else if (mechs & 0x02)
cfg_mech = 2 ;
else
cfg_mech = 1 ; // default is to assume mechanism #1
}
return ;
}
//----------------------------------------------------------------------
static int read_DWORD_register(int bus, int device, int func, int reg,
WORD *lo, WORD *hi)
{
if (bypass_BIOS)
{
DWORD value ;
if (cfg_mech == 1)
{
DWORD addr = 0x80000000L | (((DWORD)(bus & 0xFF)) << 16) |
((((unsigned)device) & 0x1F) << 11) |
((((unsigned)func) & 0x07) << 8) | (reg & 0xFC) ;
DWORD orig = inp(0xCF8) ; // get current state
outpd(0xCF8,addr) ; // set up addressing to config data
value = inpd(0xCFC) ; // get requested DWORD of config data
outpd(0xCF8,orig) ; // restore configuration control
}
else // cfg_mech == 2
{
if (device > 0x0F) // mech#2 only supports 16 devices
{ // per bus
*lo = 0xFFFF ;
*hi = 0xFFFF ;
return FALSE ;
}
BYTE oldenable = inp(0xCF8) ; // store current state of config space
BYTE oldbus = inp(0xCFA) ;
outp(0xCFA,bus) ;
outp(0xCF8,0x80) ; // enable configuration space
WORD addr = 0xC000 | ((device & 0x0F) << 8) | (reg & 0xFF) ;
value = inpd(addr) ;
outp(0xCFA,oldbus) ; // restore configuration space
outp(0xCF8,oldenable) ;
}
*hi = (WORD)(value >> 16) ;
*lo = (WORD)(value & 0xFFFF) ;
return TRUE ;
}
else // use BIOS
{
union REGS regs, outregs ;
regs.h.bh = bus ;
regs.h.bl = (device<<3) | (func & 0x07) ;
#if defined(__WATCOMC__) && defined(__386__)
regs.w.ax = 0xB109 ;
regs.w.di = reg ;
int386(0x1A,®s,&outregs) ;
if (outregs.x.cflag != 0)
return FALSE ;
*lo = outregs.w.cx ;
regs.w.di += 2 ;
int386(0x1A,®s,&outregs) ;
if (outregs.x.cflag != 0)
return FALSE ;
*hi = outregs.w.cx ;
#else
regs.x.ax = 0xB109 ;
regs.x.di = reg ;
int86(0x1A,®s,&outregs) ;
if (outregs.x.cflag != 0)
return FALSE ;
*lo = outregs.x.cx ;
regs.x.di += 2 ;
int86(0x1A,®s,&outregs) ;
if (outregs.x.cflag != 0)
return FALSE ;
*hi = outregs.x.cx ;
#endif /* __WATCOMC__ && __386__ */
}
return TRUE ;
}
//----------------------------------------------------------------------
static void write_DWORD_register(int bus,int device,int func,
int reg, WORD lo, WORD hi)
{
if (bypass_BIOS)
{
DWORD value = ((DWORD)hi << 16) | lo ;
if (cfg_mech == 1)
{
DWORD addr = 0x80000000L | ((DWORD)(bus & 0xFF) << 16) |
((device & 0x1F) << 11) | ((func & 0x07) << 8) |
(reg & 0xFC) ;
DWORD orig = inpd(0xCF8) ;
outpd(0xCF8,addr) ;
outpd(0xCFC,value) ;
outpd(0xCF8,orig) ;
}
else
{
if (device > 0x0F)
return ;
BYTE oldenable = inp(0xCF8) ;
BYTE oldbus = inp(0xCFA) ;
outp(0xCFA,bus) ;
outp(0xCF8,0x80) ; // enable configuration space
WORD addr = 0xC000 | ((device & 0x0F) << 8) | reg ;
outpd(addr,value) ;
outp(0xCFA,oldbus) ;
outp(0xCF8,oldenable) ;
}
}
else
{
union REGS regs, outregs ;
regs.h.bh = bus ;
regs.h.bl = (device<<3) | (func & 0x07) ;
#if defined(__WATCOMC__) && defined(__386__)
regs.w.ax = 0xB10D ; // write configuration DWORD
regs.w.di = reg ;
regs.x.ecx = ((long)hi) << 16 | ((unsigned)lo) ;
int386(0x1A,®s,&outregs) ;
#else
regs.x.ax = 0xB10C ; // write configuration word
regs.x.di = reg ;
regs.x.cx = lo ;
int86(0x1A,®s,&outregs) ;
regs.x.di += 2 ;
regs.x.cx = hi ;
int86(0x1A,®s,&outregs) ;
#endif /* __WATCOMC__ && __386__ */
}
return ;
}
//----------------------------------------------------------------------
static PCIcfg *read_PCI_config(int bus, int device, int func)
{
static PCIcfg cfg ;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -