⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pcicfg.cpp

📁 windwos环境下查看PCI驱动信息的源代码。
💻 CPP
📖 第 1 页 / 共 3 页
字号:
	  ...
	  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,&regs,&regs) ;
#else
   regs.x.ax = 0xB101 ;
   int86(0x1A,&regs,&regs) ;
#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,&regs,&regs) ;
#else
   regs.x.ax = 0xB101 ;
   int86(0x1A,&regs,&regs) ;
#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,&regs,&outregs) ;
      if (outregs.x.cflag != 0)
	 return FALSE ;
      *lo = outregs.w.cx ;
      regs.w.di += 2 ;
      int386(0x1A,&regs,&outregs) ;
      if (outregs.x.cflag != 0)
	 return FALSE ;
      *hi = outregs.w.cx ;
#else
      regs.x.ax = 0xB109 ;
      regs.x.di = reg ;
      int86(0x1A,&regs,&outregs) ;
      if (outregs.x.cflag != 0)
	 return FALSE ;
      *lo = outregs.x.cx ;
      regs.x.di += 2 ;
      int86(0x1A,&regs,&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,&regs,&outregs) ;
#else
      regs.x.ax = 0xB10C ;		// write configuration word
      regs.x.di = reg ;
      regs.x.cx = lo ;
      int86(0x1A,&regs,&outregs) ;
      regs.x.di += 2 ;
      regs.x.cx = hi ;
      int86(0x1A,&regs,&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 + -