📄 pcielink.c
字号:
/*
PCIELINK.EXE Written by: Jeff Fabrizio, QLogic Corporation
Examine PCI Bus for PCIexpress device Lane Validations
Supports PCI Express 2.1 Register offsets for VendorId & DeviceID
Device number is a combination of Device+Function where:
device number = bits [7:4]
function number = bits [3:0]
Link Capability Register values are programmable via the CFG file with device data
formatted as follows in decimal values:
VendorId;DeviceId;RegMLW;msb;lsb;RegNLW;msb;lsb;RegNLS;msb;lsb
RegMLW = Register Maximum Link Width
RegNLW = Register Negotiated Link Width
RegNLS = Register Negotiated Link Speed
msb = most significant bit offset
lsb = least significant bit offset
PCIe Link Status Register at offset 5E bits 4:9 can be read to determine PCIe Negotiated Lane Width.
Link Width Link Capability Link Speed
000001b = X1 000001b = X1 0001 = 2.5Gb/s
000010b = X2 000010b = X2 0010 = 5.0Gb/s
000100b = X4 000100b = X4
001000b = X8 001000b = X8
001100b = X12 001100b = X12
010000b = X16 010000b = X16
100000b = X32 100000b = X32
Reference Documentation
PCISIG - PCI BIOS SPECIFICATION V2.1
QLOGIC - FW SPEC 2400 Series Rev: D
Last Update: 06/29/07 11:05 jf V1.0 Initial release
Last Update: 07/02/07 16:43 jf V1.1 chg to AutoDetect by default
only echo fail msgs when using /V
add /I=integer display option
Last Update: 09/12/07 11:46 jf V1.2 add ISP7432, ISP8432, ISP2532
Last Update: 03/24/08 16:04 jf V1.3 add sub-system vendor id and vendor id args,
add ISP6220, ISP7220
add /M0 /N0 /L0 where 0=ignore_test
Last Update: 02/27/09 13:13 jf V2.0 rewrite as PCIELINK using absolute register values
*/
#include <stdio.h>
#include <dos.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <ctype.h>
typedef unsigned char byte; /* 8-bits */
typedef unsigned short word; /* 16-bits */
typedef unsigned long dword; /* 32-bits */
typedef unsigned int UWORD; // Unsigned word 0 to 65535.
typedef unsigned long ULONG; // Unsigned word 0 to 4294967295.
union _REGS inregs;
union _REGS outregs;
#define PCI_FUNCTION_ID 0xB1
#define FIND_PCI_DEVICE 0x02
#define ADAPTER_COUNT 16
#define SUCCESSFUL 0x00
#define BAD_VENDOR_ID 0x83
#define DEVICE_NOT_FOUND 0x86
struct device_info
{
unsigned char Bus_Number;
unsigned char Device_Number;
unsigned int BaseAddress;
ULONG flag;
};
UWORD adapter_count;
struct device_info Device_Info_Array[ADAPTER_COUNT];
unsigned int shift=0; //shift bit-string count
unsigned int mask=0; //mask bit-string count
char trimStr[255];
char trimmedStr[255];
char *result;
//int readCfg(unsigned int, unsigned int);
//void makeCfg(void);
void trimSpace(char *, char *, int);
void makeTxt(void);
//if user specifies /Bus or /Device, use that specifically
//else run autodetect for ISP2432 and only run /Device=0 of each /Bus
int main(int argc, char *argv[])
{
int i=0,rtnVal=0,echo=0,userBD=0,acount=0,tcount=0,doTest=0;
char *test="0",*test1="0",*sarg="0";
char argv10[20]="0",argv11[20]="0",argv12[20]="0",emsg[80]="0",argVal[6]="0";
char version[10]="(V2.0)";
unsigned int count=0;
unsigned int argv0=0; //verbose mode
unsigned int argv1=0; //default pci bus number
unsigned int argv2=0; //default pci device number
unsigned int argv3=4; //default max link width
unsigned int argv4=4; //default negotiate link width
unsigned int argv5=1; //default link speed
unsigned int argv6=9266; //default device id
unsigned int argv7=2; //default 2=binary display, 10=integer display
unsigned int argv8=4215; //default vendor id as QLogic
unsigned int argv9=4215; //default subsystem vendor id as QLogic
unsigned int argv10_r=88; //default maximum link width register
unsigned int argv10_m=9; //default maximum link width register offset most significant bit
unsigned int argv10_l=4; //default maximum link width register offset least significant bit
unsigned int argv11_r=94; //default negotiate link width register
unsigned int argv11_m=9; //default negotiate link width register offset most significant bit
unsigned int argv11_l=4; //default negotiate link width register offset least significant bit
unsigned int argv12_r=94; //default negotiate link speed register
unsigned int argv12_m=3; //default negotiate link speed register offset most significant bit
unsigned int argv12_l=0; //default negotiate link speed register offset least significant bit
unsigned int tmpVal=0; //used to shift and mask 16bit word from &outregs
unsigned int lssVal=0; //used to format link speed value
unsigned int venId=0; //vendor id
unsigned int venIdS=0; //subsystem vendor id
//set default argval10,11,12
strcpy(argv10,"88;9;4");
strcpy(argv11,"94;9;4");
strcpy(argv12,"94;3;0");
//make PCIELINK.TXT sample file
makeTxt();
//loop thru argv[x] and set variables for calling arguments
for(i=1;i!=argc;i++)
{
sarg=strtok(argv[i],"/");
if(i==1 && !strcmp(sarg,"?"))
{
printf("\n");
printf("Verify PCIexpress Link Capability Registers %s\n",version);
printf("PCIELINK [options]\n");
printf(" /I vendorId (0-65535) (default=4215)\n");
printf(" /A deviceId (0-65535) ignored if using /B or /D (default=9266)\n");
printf(" /B PCI Bus Number (0-15) (default=AutoDetect)\n");
printf(" /D PCI Device+Function Number (0-63) (default=AutoDetect)\n");
printf(" /E PCI Maximum Link Width Register;MSB;LSB (default=88;9;4)\n");
printf(" /F PCI Negotiated Link Width Register;MSB;LSB (default=94;9;4)\n");
printf(" /G PCI Negotiated Link Speed Register;MSB;LSB (default=94;3;0)\n");
printf(" /M PCI Maximum Link Width 1,2,4,8,12,16,32 (default=4)\n");
printf(" /N PCI Negotiate Link Width 1,2,4,8,12,16,32 (default=4)\n");
printf(" /L PCI Link Speed Gb/s 0=Ignore 1=2.5, 2=5.0 (default=1)\n");
printf(" /S Sub-system Vendor ID (0-65535) (default=4215)\n");
printf(" /H Display hexidecimal results (requires /V) (default=binary)\n");
printf(" /V Verbose display\n");
printf(" /R Show Return Codes\n\n\n");
printf("Uses 16bit Register /E /F /G, apply Register offset for MSB;LSB of 16-32\n");
printf("AutoDetect mode of (/B and /D) will test for DEVICE=0 on all BUSSES\n\n");
return 1;
}
if(i==1 && (!strcmp(sarg,"r") || !strcmp(sarg,"R")))
{
printf("\n");
printf("Verify PCIexpress Link Negotiation Parameters %s\n",version);
printf(" Return codes:\n");
printf(" 0 = Pass\n");
printf(" 1 = Fail, no adapter found at Bus\n");
printf(" 2 = Fail, no adapter found at Device\n");
printf(" 3 = Fail, Maximum_Link_Width\n");
printf(" 4 = Fail, Negotiate_Link_Width\n");
printf(" 5 = Fail, Link_Speed\n");
printf(" 6 = Fail, Invalid QLogic PCIexpress ASIC\n");
printf(" 7 = Fail, Invalid Vendor ID\n");
printf(" 8 = Fail, Subsystem Vendor ID\n");
printf(" 9 = Fail, Invalid Maximum Link Width Register\n");
printf(" 10 = Fail, Invalid Negotiate Link Width Register\n");
printf(" 11 = Fail, Invalid Negotiate Link Speed Register\n");
return 1;
}
//get bus number
if(!strncmp(sarg,"B",1)|| !strncmp(sarg,"b",1))
{
userBD=1; //set flag user forced bus
strncpy(argVal,sarg,1); //get 1st char after /, dont know if lower or upper
sarg=strtok(sarg,argVal); //split by first char and ignore char case
argv1=atoi(sarg);
if(argv1>=16) argv1=4; //reset to default val if user selects invalid bus number
continue;
}
//get device number
if(!strncmp(sarg,"D",1)||!strncmp(sarg,"d",1))
{
userBD=2; //set flag user forced device
strncpy(argVal,sarg,1);
sarg=strtok(sarg,argVal);
argv2=atoi(sarg);
continue;
}
//get max link width
if(!strncmp(sarg,"M",1)||!strncmp(sarg,"m",1))
{
strncpy(argVal,sarg,1);
sarg=strtok(sarg,argVal);
argv3=atoi(sarg);
continue;
}
//get negotiate link width
if(!strncmp(sarg,"N",1)||!strncmp(sarg,"n",1))
{
strncpy(argVal,sarg,1);
sarg=strtok(sarg,argVal);
argv4=atoi(sarg);
continue;
}
//get bus link speed
if(!strncmp(sarg,"L",1)||!strncmp(sarg,"l",1))
{
strncpy(argVal,sarg,1);
sarg=strtok(sarg,argVal);
argv5=atoi(sarg);
continue;
}
//get device id number
if(!strncmp(sarg,"A",1)||!strncmp(sarg,"a",1))
{
strncpy(argVal,sarg,1);
sarg=strtok(sarg,argVal);
argv6=atoi(sarg);
continue;
}
//get vendor ID number offset 00h
if(!strncmp(sarg,"I",1)||!strncmp(sarg,"i",1))
{
strncpy(argVal,sarg,1);
sarg=strtok(sarg,argVal);
argv8=atoi(sarg);
continue;
}
//get subsystem vendor ID number offset 2Ch
if(!strncmp(sarg,"S",1)||!strncmp(sarg,"s",1))
{
strncpy(argVal,sarg,1);
sarg=strtok(sarg,argVal);
argv9=atoi(sarg);
continue;
}
//verbose mode
if(!strncmp(sarg,"V",1)||!strncmp(sarg,"v",1)) argv0=1;
//display mode integer
if(!strncmp(sarg,"H",1)||!strncmp(sarg,"h",1)) argv7=10;
//get maximum link width register;msb;lsb
if(!strncmp(sarg,"E",1)||!strncmp(sarg,"e",1))
{
strncpy(argVal,sarg,1);
sarg=strtok(sarg,argVal);
strcpy(argv10,sarg);
continue;
}
//get negotiated link width register;msb;lsb
if(!strncmp(sarg,"F",1)||!strncmp(sarg,"f",1))
{
strncpy(argVal,sarg,1);
sarg=strtok(sarg,argVal);
strcpy(argv11,sarg);
continue;
}
//get negotiated link speed register;msb;lsb
if(!strncmp(sarg,"G",1)||!strncmp(sarg,"g",1))
{
strncpy(argVal,sarg,1);
sarg=strtok(sarg,argVal);
strcpy(argv12,sarg);
continue;
}
}
//check verbose mode
if(argv0) echo=1;
//check Bus
strcpy(emsg,"Invalid Bus Number!\n");
switch (argv1)
{
case 0: case 1: case 2: case 3:
case 4: case 5: case 6: case 7:
case 8: case 9: case 10: case 11:
case 12: case 13: case 14: case 15:
case 16:
break;
default:
if(echo) printf(emsg);
rtnVal=1;
break;
}
//check device + function
strcpy(emsg,"Invalid Device Number!\n");
if(argv2<0||argv2>63)
{
if(echo) printf(emsg);
rtnVal=2;
}
//check max_link_width
strcpy(emsg,"Invalid Max Link Width!\n");
switch (argv3)
{
case 0: case 1: case 2: case 4: case 8:
case 12: case 16: case 32:
break;
default:
if(echo) printf(emsg);
rtnVal=3;
break;
}
//check negotiate_link_width
strcpy(emsg,"Invalid Negotiate Link Width!\n");
switch (argv4)
{
case 0: case 1: case 2: case 4: case 8:
case 12: case 16: case 32:
break;
default:
if(echo) printf(emsg);
rtnVal=4;
break;
}
//check link_speed
strcpy(emsg,"Invalid Link Speed!\n");
switch (argv5)
{
case 0: case 1: case 2:
break;
default:
if(echo) printf(emsg);
rtnVal=5;
break;
}
//check maximum link width register
strcpy(emsg,"Invalid Maximum Link Width Register!\n");
result=strtok(argv10,";");
argv10_r=atoi(result);
if(argv10_r<1||argv10_r>255)
{
if(echo) printf(emsg);
rtnVal=9;
}
//check maximum link width register msb
strcpy(emsg,"Invalid Maximum Link Width Register MSB!\n");
result=strtok(NULL,";");
argv10_m=atoi(result);
if(argv10_m<0||argv10_m>32)
{
if(echo) printf(emsg);
rtnVal=9;
}
//check maximum link width register lsb
strcpy(emsg,"Invalid Maximum Link Width Register LSB!\n");
result=strtok(NULL,";");
argv10_l=atoi(result);
if(argv10_l<0||argv10_l>32||argv10_l>=argv10_m)
{
if(echo) printf(emsg);
rtnVal=9;
}
//check negotiate link width register
strcpy(emsg,"Invalid Negotiate Link Width Register!\n");
result=strtok(argv11,";");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -