📄 pcicfg.cpp
字号:
for (int i = 0 ; i < sizeof(cfg)/sizeof(DWORD) ; i++)
{
WORD hi, lo ;
if (!read_DWORD_register(bus,device,func,i*sizeof(DWORD),&lo,&hi))
return 0 ;
((WORD*)&cfg)[2*i] = lo ;
((WORD*)&cfg)[2*i+1] = hi ;
}
return &cfg ;
}
//----------------------------------------------------------------------
static const char *get_subclass_name(int classcode, int subclass)
{
if (classcode < 0 || classcode >= lengthof(subclass_data) ||
subclass_data[classcode] == 0)
return "???" ;
const subclass_info *subinfo = subclass_data[classcode] ;
while (subinfo->subclass_code != -1)
{
if (subinfo->subclass_code == subclass)
return subinfo->subclass_name ;
subinfo++ ;
}
return "???" ;
}
//----------------------------------------------------------------------
static const char *get_vendor_name(WORD vendorID)
{
if (vendorID == 0x0000 || vendorID == 0xFFFF)
return "Not Present" ;
char *next ;
for (char *data = device_ID_data ; data ; data = next)
{
next = *((char**)data) ;
data += sizeof(char*) ;
data += sizeof(WORD) ; // skip the length field
WORD ID = *((WORD*)data) ;
data += sizeof(WORD) ;
if (ID == vendorID)
return data ;
}
// if we get here, there was no matching ID in the file,
return "???" ;
}
//----------------------------------------------------------------------
static const char *get_device_name(WORD vendorID, WORD deviceID)
{
if (vendorID == 0x0000 || vendorID == 0xFFFF || deviceID == 0xFFFF)
return "Not Present" ;
char *data = device_ID_data ;
while (data)
{
char *next = *((char**)data) ;
data += sizeof(char*) ;
WORD length = *((WORD*)data) ;
data += sizeof(WORD) ;
char *end = data + length ;
WORD ID = *((WORD*)data) ;
data += sizeof(WORD) ;
if (ID == vendorID)
{
// OK, we've found the vendor, now scan for the device
// 1. skip the vendor name
while (*data)
data++ ;
if (data < end) // skip the NUL
data++ ;
// 2. check each device ID in turn
while (data < end)
{
ID = *((WORD*)data) ;
data += sizeof(WORD) ;
if (ID == deviceID)
return data ;
while (*data)
data++ ;
data++ ; // skip the NUL
}
// if we get here, there was no match for the device ID
break ;
}
data = next ;
}
// if we get here, there was no matching ID in the file,
return "???" ;
}
//----------------------------------------------------------------------
static int load_device_info(FILE *fp, char * &format_string,
char const * &enum_list)
{
if (!fp)
return FALSE ;
long int filesize = lseek(fileno(fp),0L,SEEK_END) ;
fseek(fp,0L,SEEK_SET) ; // back to beginning of file
char line[MAX_LINE] ;
// read until we find the actual beginning of the device definition
do {
line[0] = '\0' ; // catch EOF or read error
fgets(line,sizeof(line),fp) ;
} while (!feof(fp) && strncmp(line,"!begin",6) != 0) ;
int datasize = (int)(filesize - ftell(fp)) ;
char *buffer = (char*)malloc(datasize+3) ;
int readsize ;
char *newline ;
if (buffer && (readsize = fread(buffer,sizeof(char),datasize,fp)) > 0)
{
buffer[readsize] = '\0' ; // ensure proper string termination
format_string = buffer ;
enum_list = format_string ;
if (*enum_list == '\n')
enum_list++ ;
// look forward to end of format string, then chop into two strings
do {
newline = strchr(enum_list,'\n') ;
if (newline && strncmp(newline+1,"!end",4) == 0)
{
newline[1] = '\0' ;
newline = strchr(newline+2,'\n') ;
if (newline)
enum_list = newline ;
else
enum_list = newline+2 ;
break ;
}
if (newline)
enum_list = newline+1 ;
} while (newline) ;
}
else
return FALSE ;
// scan until we find the actual beginning of the 'enum' definition
char *result = (char*)enum_list ;
newline = (char*)enum_list ;
do {
newline = strchr(newline,'\n') ;
if (newline)
{
newline++ ;
if (strncmp(newline,"!enum",5) == 0)
break ;
}
} while (newline) ;
if (newline)
{
newline++ ;
// format of the enum:
// !enum enum_name
// enumvalue0
// enumvalue1
// ...
// enumvalueN
// !end
do {
// extract the enum's name
//assert(strcmp(newline,"!enum",5) == 0) ;
newline = skip_whitespace(newline+5) ;
const char *end = strchr(newline,'\n') ;
if (!end)
break ;
memcpy(result,newline,end-newline+1) ;
result += (end-newline+1) ;
newline = (char*)end+1 ;
while (*newline && strncmp(newline,"!end",4) != 0)
{
newline = skip_whitespace(newline) ;
char *end = strchr(newline,'\n') ;
if (!end)
end = strchr(newline,'\0') ;
char *next = *end ? end+1 : end ;
while (end > newline && isspace(end[-1]))
end-- ;
memcpy(result,newline,end-newline) ;
result[end-newline] = '\n' ;
result += (end-newline+1) ;
newline = next ;
}
*result++ = '\0' ;
// one enum is done, so scan for the next (if any)
while ((newline = strchr(newline,'\n')) != 0)
{
newline++ ;
if (strncmp(newline,"!enum",5) == 0)
break ;
}
} while (newline && *newline) ;
}
*result++ = '\0' ;
return TRUE ;
}
//----------------------------------------------------------------------
static int know_device(WORD vendor, WORD device,
char * &format_string, char const * &enum_list)
{
if (vendor == 0x0000 || vendor == 0xFFFF || device == 0xFFFF)
return FALSE ;
// see if there's a data file for this device
int dir_len = strlen(exe_directory) ;
char *device_file = (char*)malloc(dir_len+14) ;
if (device_file)
{
sprintf(device_file,"%s/%4.04X%4.04X.PCI",exe_directory,vendor,device) ;
device_file[dir_len+13] = '\0' ;
FILE *fp = fopen(device_file,"r") ;
free(device_file) ;
if (fp)
{
int success = load_device_info(fp,format_string,enum_list) ;
fclose(fp) ;
return success ;
}
}
return FALSE ;
}
//----------------------------------------------------------------------
static void write_bits(WORD bitflags, const char *const *flagnames, int numbits)
{
for (int i = 0 ; i < numbits ; i++)
{
if ((bitflags & (1 << i)) != 0 && flagnames[i])
printf(" %s",flagnames[i]) ;
}
}
#define WRITE_CMD_BITS(x) write_bits((x),command_bits,lengthof(command_bits))
#define WRITE_STAT_BITS(x) write_bits((x),status_bits,lengthof(status_bits))
#define WRITE_BCTRL_BITS(x) write_bits((x),bctrl_bits,lengthof(bctrl_bits))
//----------------------------------------------------------------------
static DWORD extract_field(const char *&s, const char *cfg)
{
DWORD value = 0 ;
int addr = 0 ;
while (*s == '[' || *s == '|')
{
s++ ;
int lowbit = 0 ;
int highbit = 7 ;
while (*s && isxdigit(*s))
{
int digit = *s - '0' ;
if (digit > 9)
digit -= ('A'-10-'0') ;
addr = 16*addr + digit ;
s++ ;
}
addr &= 0x00FF ;
if (*s == ':')
{
s++ ;
while (*s && isdigit(*s))
{
lowbit = 10*lowbit + (*s-'0') ;
s++ ;
}
if (*s == '-')
{
highbit = 0 ;
s++ ;
while (*s && isdigit(*s))
{
highbit = 10*highbit + (*s-'0') ;
s++ ;
}
}
else
highbit = lowbit ;
if (highbit < lowbit)
{
int tmp = lowbit ;
lowbit = highbit ;
highbit = tmp ;
}
if (highbit > 31)
{
if (highbit - lowbit >= 32)
highbit = 31 ;
}
if (lowbit/8)
{
int adj = lowbit/8 ;
addr += adj ;
adj *= 8 ;
lowbit -= adj ;
highbit -= adj ;
}
}
DWORD prev_value = value << (highbit-lowbit+1) ;
if (highbit > 16)
{
value = cfg[addr] + (cfg[addr+1] << 8) + ((DWORD)cfg[addr+2] << 16) +
((DWORD)cfg[addr+3] << 24) ;
}
else if (highbit > 8)
value = cfg[addr] + (cfg[addr+1] << 8) ;
else
value = cfg[addr] ;
DWORD mask = 0 ;
for (int i = lowbit ; i <= highbit ; i++)
mask |= (1L << i-lowbit) ;
while (lowbit-- > 0)
value >>= 1 ;
value &= mask ;
if (*s == '<')
{
s++ ;
int shift = 0 ;
while (*s && isdigit(*s))
{
shift = 10*shift + (*s-'0') ;
s++ ;
}
while (shift-- > 0)
{
value <<= 1 ;
prev_value <<= 1 ;
}
}
if (*s == '*')
{
s++ ;
unsigned mult = 0 ;
while (*s && isdigit(*s))
{
mult = 10*mult + (*s-'0') ;
s++ ;
}
if (mult == 0)
mult =1 ;
value *= mult ;
prev_value *= mult ;
}
value |= prev_value ;
if (*s == '+')
{
*s++ ;
int negative = 0 ;
if (*s == '-')
negative = 1 ;
long offset = 0 ;
while (*s && isdigit(*s))
{
offset = 10*offset + (*s-'0') ;
s++ ;
}
if (negative)
offset = -offset ;
value += offset ;
}
if (*s == ']')
{
s++ ;
break ;
}
}
return value ;
}
//----------------------------------------------------------------------
static void format_number(FILE *out, DWORD val, int width, int base)
{
char buf[38] ; // enough for DWORD, plus fudge factor
static char digits[] = "0123456789ABCDEF" ;
int count = 0 ;
do {
int digit = (int)(val % base) ;
val /= base ;
buf[count++] = digits[digit] ;
} while (val) ;
buf[count] = '\0' ;
for (int i = 0 ; i < count/2 ; i++)
{
char tmp = buf[count-i-1] ;
buf[count-i-1] = buf[i] ;
buf[i] = tmp ;
}
if (count < width)
{
for (int i = count ; i < width ; i++)
fputc(base == 10 ? ' ' : '0',out) ;
}
fputs(buf,out) ;
return ;
}
//----------------------------------------------------------------------
static void format_enabled(FILE *out, DWORD value, int width)
{
int w = value ? 6 : 7 ;
for (int i = w ; i < width ; i++)
fputc(' ',out) ;
fputs(value ? "enable" : "disable",out) ;
}
//----------------------------------------------------------------------
static void format_flag(FILE *out, DWORD value, int width)
{
for (int i = 1 ; i < width ; i++)
fputc(' ',out) ;
fputc(value ? '
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -