summaryrefslogtreecommitdiffstats
path: root/main/common/pci.c
diff options
context:
space:
mode:
Diffstat (limited to 'main/common/pci.c')
-rw-r--r--main/common/pci.c1209
1 files changed, 608 insertions, 601 deletions
diff --git a/main/common/pci.c b/main/common/pci.c
index 2dddb0f..3483513 100644
--- a/main/common/pci.c
+++ b/main/common/pci.c
@@ -1,7 +1,7 @@
/**************************************************************************
*
* Copyright (c) 2013 Alcatel-Lucent
- *
+ *
* Alcatel Lucent licenses this file to You under the Apache License,
* Version 2.0 (the "License"); you may not use this file except in
* compliance with the License. A copy of the License is contained the
@@ -24,7 +24,7 @@
* interfacing with a PCI bus. Four target-specific functions are
* required:
*
- * pciCtrl(), pciCfgRead(), pciCfgWrite(), pciShow()
+ * pciCtrl(), pciCfgRead(), pciCfgWrite(), pciShow()
*
* The two most important are pciCfgRead() and pciCfgWrite(). Refer to
* the bottom of pci.h for further details.
@@ -42,18 +42,18 @@
int pciVerbose;
int pciBusNum;
-#define IMPLEMENTED 0x80000000
+#define IMPLEMENTED 0x80000000
#ifdef USE_DEFAULT_PCISHOW
void
pciShow(int interface)
{
- printf("No fixed devices on this platform\n");
+ printf("No fixed devices on this platform\n");
}
#endif
/* pciCfgAddress():
- * Return a 32-bit value based on the input
+ * Return a 32-bit value based on the input
* bus number, device number, function number and register
* number:
*
@@ -74,18 +74,19 @@ pciShow(int interface)
unsigned long
pciCfgAddress(int busno,int devno,int fncno,int regno)
{
- int type;
-
- if (busno > 0)
- type = 1;
- else
- type = 0;
-
- return((type | PCICFG_ENABLE_BIT |
- ((busno & PCICFG_BUSNO_MASK) << PCICFG_BUSNO_SHIFT) |
- ((devno & PCICFG_DEVNO_MASK) << PCICFG_DEVNO_SHIFT) |
- ((fncno & PCICFG_FNCNO_MASK) << PCICFG_FNCNO_SHIFT) |
- ((regno & PCICFG_REGNO_MASK) << PCICFG_REGNO_SHIFT)));
+ int type;
+
+ if(busno > 0) {
+ type = 1;
+ } else {
+ type = 0;
+ }
+
+ return((type | PCICFG_ENABLE_BIT |
+ ((busno & PCICFG_BUSNO_MASK) << PCICFG_BUSNO_SHIFT) |
+ ((devno & PCICFG_DEVNO_MASK) << PCICFG_DEVNO_SHIFT) |
+ ((fncno & PCICFG_FNCNO_MASK) << PCICFG_FNCNO_SHIFT) |
+ ((regno & PCICFG_REGNO_MASK) << PCICFG_REGNO_SHIFT)));
}
/* pciBaseClass():
@@ -95,76 +96,76 @@ pciCfgAddress(int busno,int devno,int fncno,int regno)
char *
pciBaseClass(unsigned long classcode)
{
- unsigned long baseclass;
- unsigned long subclass_progif;
-
- baseclass = (classcode >> 16) & 0xff;
- subclass_progif = classcode & 0xffff;
-
- switch(baseclass) {
- case 0:
- return("pre-class-code-definitions");
- case 1:
- return("mass storage ctrlr");
- case 2:
- return("network ctrlr");
- case 3:
- return("display ctrlr");
- case 4:
- return("multimedia device");
- case 5:
- return("memory ctrlr");
- case 6: /* Supply additional information for bridge class...
- */
- switch(subclass_progif) {
- case 0x0000:
- return("host/pci bridge");
- case 0x0100:
- return("pci/isa bridge");
- case 0x0200:
- return("pci/eisa bridge");
- case 0x0300:
- return("pci/microchannel bridge");
- case 0x0400:
- return("pci/pci bridge");
- case 0x0500:
- return("pci/pcmcia bridge");
- case 0x0600:
- return("pci/nubus bridge");
- case 0x0700:
- return("pci/cardbus bridge");
- case 0x8000:
- return("other bridge type");
- default:
- return("bridge device");
- }
- case 7:
- return("simple communication ctrlr");
- case 8:
- return("base system peripheral");
- case 9:
- return("input device");
- case 10:
- return("docking station");
- case 11:
- return("processor");
- case 12:
- return("serial bus ctrlr");
- case 13:
- return("wireless ctrlr");
- case 14:
- return("intelligent io ctrlr");
- case 15:
- return("satellite communication ctrlr");
- case 16:
- return("encrypt/decrypt ctrlr");
- case 17:
- return("data acquisition ctrlr");
- case 256:
- return("no fit");
- default:
- return("reserved");
- }
+ unsigned long baseclass;
+ unsigned long subclass_progif;
+
+ baseclass = (classcode >> 16) & 0xff;
+ subclass_progif = classcode & 0xffff;
+
+ switch(baseclass) {
+ case 0:
+ return("pre-class-code-definitions");
+ case 1:
+ return("mass storage ctrlr");
+ case 2:
+ return("network ctrlr");
+ case 3:
+ return("display ctrlr");
+ case 4:
+ return("multimedia device");
+ case 5:
+ return("memory ctrlr");
+ case 6: /* Supply additional information for bridge class...
+ */
+ switch(subclass_progif) {
+ case 0x0000:
+ return("host/pci bridge");
+ case 0x0100:
+ return("pci/isa bridge");
+ case 0x0200:
+ return("pci/eisa bridge");
+ case 0x0300:
+ return("pci/microchannel bridge");
+ case 0x0400:
+ return("pci/pci bridge");
+ case 0x0500:
+ return("pci/pcmcia bridge");
+ case 0x0600:
+ return("pci/nubus bridge");
+ case 0x0700:
+ return("pci/cardbus bridge");
+ case 0x8000:
+ return("other bridge type");
+ default:
+ return("bridge device");
+ }
+ case 7:
+ return("simple communication ctrlr");
+ case 8:
+ return("base system peripheral");
+ case 9:
+ return("input device");
+ case 10:
+ return("docking station");
+ case 11:
+ return("processor");
+ case 12:
+ return("serial bus ctrlr");
+ case 13:
+ return("wireless ctrlr");
+ case 14:
+ return("intelligent io ctrlr");
+ case 15:
+ return("satellite communication ctrlr");
+ case 16:
+ return("encrypt/decrypt ctrlr");
+ case 17:
+ return("data acquisition ctrlr");
+ case 256:
+ return("no fit");
+ default:
+ return("reserved");
+ }
}
/* pciscan():
@@ -175,7 +176,7 @@ pciBaseClass(unsigned long classcode)
* assign bus numbers to each bridge appropriately. This function does
* not assign address ranges or anything else, it simply provides a quick
* means of scanning all devices on the bus(es).
- *
+ *
* NOTE: This has only been tested with simple PCI bus configurations (one
* bridge deep) so deeper configurations (bridges on bridges on bridges...)
* are untested as far as I know.
@@ -183,76 +184,78 @@ pciBaseClass(unsigned long classcode)
void
pciscan(long interface, long bus, long func, int showhdr, int enumerate)
{
- long device;
- uchar hdr_type, rev_id;
- ushort vendor_id, device_id;
- ulong value, class_code;
-
- if (showhdr) {
- printf("\nInterface %ld...\n",interface);
- printf("Bus Dev Vndr Dev Rev Hdr Class\n");
- printf("Num Num Id Id Id Type Code\n");
- }
-
- if ((enumerate == 1) && (bus == 0))
- pciBusNum = 0;
-
- for(device=0;device<=31;device++) {
- /* Retrieve portions of the configuration header that
- * are required by all PCI compliant devices...
- * Vendor, Device and Revision IDs, Class Code and Header Type
- * (see pg 191 of spec).
- */
-
- /* Read reg_0 for vendor and device ids:
- */
- value = pciCfgRead(interface,bus,device,func,0);
- if (value == NO_DEVICE)
- continue;
-
- vendor_id = (ushort)(value & 0xffff);
- device_id = (ushort)((value>>16) & 0xffff);
-
- /* Read reg_2 for class code and revision id:
- */
- value = pciCfgRead(interface,bus,device,func,2);
- rev_id = (uchar)(value & 0xff);
- class_code = (ulong)((value>>8) & 0xffffff);
-
- /* Read reg_3: header type:
- */
- value = pciCfgRead(interface,bus,device,func,3);
- hdr_type = (uchar)((value>>16) & 0xff);
-
- printf("%2ld %02ld x%04x x%04x",bus,
- device,vendor_id,device_id);
- printf(" x%02x x%02x x%06lx (%s)\n",rev_id,
- hdr_type,class_code,pciBaseClass(class_code));
-
- /* If enumeration is enabled, see if this is a PCI-to-PCI
- * bridge. If it is, then nest into pciscan...
- */
- if ((enumerate) && (class_code == 0x060400)) {
- ulong pribus, secbus, subbus;
-
- pribus = pciBusNum & 0x0000ff;
- pciBusNum++;
- secbus = ((pciBusNum << 8) & 0x00ff00);
- subbus = ((pciBusNum << 16) & 0xff0000);
-
- value = pciCfgRead(interface,bus,device,func,6);
- value &= 0xffff0000;
- value |= (pribus | secbus);
- pciCfgWrite(interface,bus,device,func,6,value);
-
- pciscan(interface,pciBusNum,func,0,1);
-
- value = pciCfgRead(interface,bus,device,func,6);
- value &= 0xff000000;
- value |= (subbus | pribus | secbus);
- pciCfgWrite(interface,bus,device,func,6,value);
- }
- }
+ long device;
+ uchar hdr_type, rev_id;
+ ushort vendor_id, device_id;
+ ulong value, class_code;
+
+ if(showhdr) {
+ printf("\nInterface %ld...\n",interface);
+ printf("Bus Dev Vndr Dev Rev Hdr Class\n");
+ printf("Num Num Id Id Id Type Code\n");
+ }
+
+ if((enumerate == 1) && (bus == 0)) {
+ pciBusNum = 0;
+ }
+
+ for(device=0; device<=31; device++) {
+ /* Retrieve portions of the configuration header that
+ * are required by all PCI compliant devices...
+ * Vendor, Device and Revision IDs, Class Code and Header Type
+ * (see pg 191 of spec).
+ */
+
+ /* Read reg_0 for vendor and device ids:
+ */
+ value = pciCfgRead(interface,bus,device,func,0);
+ if(value == NO_DEVICE) {
+ continue;
+ }
+
+ vendor_id = (ushort)(value & 0xffff);
+ device_id = (ushort)((value>>16) & 0xffff);
+
+ /* Read reg_2 for class code and revision id:
+ */
+ value = pciCfgRead(interface,bus,device,func,2);
+ rev_id = (uchar)(value & 0xff);
+ class_code = (ulong)((value>>8) & 0xffffff);
+
+ /* Read reg_3: header type:
+ */
+ value = pciCfgRead(interface,bus,device,func,3);
+ hdr_type = (uchar)((value>>16) & 0xff);
+
+ printf("%2ld %02ld x%04x x%04x",bus,
+ device,vendor_id,device_id);
+ printf(" x%02x x%02x x%06lx (%s)\n",rev_id,
+ hdr_type,class_code,pciBaseClass(class_code));
+
+ /* If enumeration is enabled, see if this is a PCI-to-PCI
+ * bridge. If it is, then nest into pciscan...
+ */
+ if((enumerate) && (class_code == 0x060400)) {
+ ulong pribus, secbus, subbus;
+
+ pribus = pciBusNum & 0x0000ff;
+ pciBusNum++;
+ secbus = ((pciBusNum << 8) & 0x00ff00);
+ subbus = ((pciBusNum << 16) & 0xff0000);
+
+ value = pciCfgRead(interface,bus,device,func,6);
+ value &= 0xffff0000;
+ value |= (pribus | secbus);
+ pciCfgWrite(interface,bus,device,func,6,value);
+
+ pciscan(interface,pciBusNum,func,0,1);
+
+ value = pciCfgRead(interface,bus,device,func,6);
+ value &= 0xff000000;
+ value |= (subbus | pribus | secbus);
+ pciCfgWrite(interface,bus,device,func,6,value);
+ }
+ }
}
/* getBarInfo():
@@ -263,303 +266,304 @@ pciscan(long interface, long bus, long func, int showhdr, int enumerate)
*/
ulong
getBarInfo(long interface,long bus,long device,long func,int barnum,
- ulong *sizehi, ulong *sizelo)
+ ulong *sizehi, ulong *sizelo)
{
- int barregno;
- ulong implemented, barval1, barval2, barinfo1, barinfo2, cmd;
-
- /* Translate the incoming bar number to a register number
- * in PCI config space:
- */
- barregno = barnum + 4;
-
- /* Disable decoding through the command register:
- */
- cmd = pciCfgRead(interface,bus,device,func,1);
- pciCfgWrite(interface,bus,device,func,1,
- cmd & ~(IO_SPACE | MEMORY_SPACE));
-
- /* Read the BAR:
- */
- barval1 = pciCfgRead(interface,bus,device,func,barregno);
-
- /* Write 0xffffffff to the BAR:
- */
- pciCfgWrite(interface,bus,device,func,barregno,0xffffffff);
-
- /* Read the value returned as a result of writing
- * 0xffffffff to the BAR:
- */
- barinfo1 = pciCfgRead(interface,bus,device,func,barregno);
-
- /* Restore original bar:
- */
- pciCfgWrite(interface,bus,device,func,barregno,barval1);
-
- if (barinfo1 == 0) {
- implemented = 0;
- }
- else {
- implemented = IMPLEMENTED;
-
- if (barval1 & BASEADDRESS_IO) {
- implemented |= BASEADDRESS_IO;
-
- if (sizelo) {
- /* Clear encoding bits:
- */
- barinfo1 &= 0xfffffffe;
- /* Invert and add 1:
- */
- *sizelo = (~barinfo1 + 1) & 0xffff;
-
- if (sizehi)
- *sizehi = 0;
- }
- }
- else {
- implemented |= (barinfo1 & PREFETCHABLE);
-
- if (barval1 & TYPE_64) {
- implemented |= TYPE_64;
-
- /* Apply same sequence as above to the next bar...
- */
- barregno++;
- barval2 = pciCfgRead(interface,bus,device,func,barregno);
- pciCfgWrite(interface,bus,device,func,barregno,0xffffffff);
- barinfo2 = pciCfgRead(interface,bus,device,func,barregno);
- pciCfgWrite(interface,bus,device,func,barregno,barval2);
-
-
- if (sizelo) {
- barinfo1 &= 0xfffffff0;
- *sizelo = ~barinfo1 + 1;
- if (sizehi)
- *sizehi = ~barinfo2 + 1;
- }
- }
- else {
- if (sizelo) {
- barinfo1 &= 0xfffffff0;
- *sizelo = ~barinfo1 + 1;
-
- if (sizehi)
- *sizehi = 0;
- }
- }
- }
- }
-
- /* Now that we've completed messing with the BARS,
- * restore original cmd:
- */
- pciCfgWrite(interface,bus,device,func,1,cmd);
-
- return(implemented);
+ int barregno;
+ ulong implemented, barval1, barval2, barinfo1, barinfo2, cmd;
+
+ /* Translate the incoming bar number to a register number
+ * in PCI config space:
+ */
+ barregno = barnum + 4;
+
+ /* Disable decoding through the command register:
+ */
+ cmd = pciCfgRead(interface,bus,device,func,1);
+ pciCfgWrite(interface,bus,device,func,1,
+ cmd & ~(IO_SPACE | MEMORY_SPACE));
+
+ /* Read the BAR:
+ */
+ barval1 = pciCfgRead(interface,bus,device,func,barregno);
+
+ /* Write 0xffffffff to the BAR:
+ */
+ pciCfgWrite(interface,bus,device,func,barregno,0xffffffff);
+
+ /* Read the value returned as a result of writing
+ * 0xffffffff to the BAR:
+ */
+ barinfo1 = pciCfgRead(interface,bus,device,func,barregno);
+
+ /* Restore original bar:
+ */
+ pciCfgWrite(interface,bus,device,func,barregno,barval1);
+
+ if(barinfo1 == 0) {
+ implemented = 0;
+ } else {
+ implemented = IMPLEMENTED;
+
+ if(barval1 & BASEADDRESS_IO) {
+ implemented |= BASEADDRESS_IO;
+
+ if(sizelo) {
+ /* Clear encoding bits:
+ */
+ barinfo1 &= 0xfffffffe;
+ /* Invert and add 1:
+ */
+ *sizelo = (~barinfo1 + 1) & 0xffff;
+
+ if(sizehi) {
+ *sizehi = 0;
+ }
+ }
+ } else {
+ implemented |= (barinfo1 & PREFETCHABLE);
+
+ if(barval1 & TYPE_64) {
+ implemented |= TYPE_64;
+
+ /* Apply same sequence as above to the next bar...
+ */
+ barregno++;
+ barval2 = pciCfgRead(interface,bus,device,func,barregno);
+ pciCfgWrite(interface,bus,device,func,barregno,0xffffffff);
+ barinfo2 = pciCfgRead(interface,bus,device,func,barregno);
+ pciCfgWrite(interface,bus,device,func,barregno,barval2);
+
+
+ if(sizelo) {
+ barinfo1 &= 0xfffffff0;
+ *sizelo = ~barinfo1 + 1;
+ if(sizehi) {
+ *sizehi = ~barinfo2 + 1;
+ }
+ }
+ } else {
+ if(sizelo) {
+ barinfo1 &= 0xfffffff0;
+ *sizelo = ~barinfo1 + 1;
+
+ if(sizehi) {
+ *sizehi = 0;
+ }
+ }
+ }
+ }
+ }
+
+ /* Now that we've completed messing with the BARS,
+ * restore original cmd:
+ */
+ pciCfgWrite(interface,bus,device,func,1,cmd);
+
+ return(implemented);
}
int
showBar(int barnum,long interface,long bus,long device,long func)
{
- int rtot;
- ulong bar, barnext, sizehi, sizelo, implemented;
-
- if ((barnum < 0) || (barnum > 5))
- return(-1);
-
- bar = pciCfgRead(interface,bus,device,func,barnum+4);
-
- implemented = getBarInfo(interface,bus,device,func,
- barnum,&sizehi,&sizelo);
-
- if (!implemented) {
- printf("%02d BAR%d : not implemented\n",barnum+4,barnum);
- return(0);
- }
-
- printf("%02d BAR%d",barnum+4,barnum);
- if (!(implemented & BASEADDRESS_IO) && (implemented & TYPE_64)) {
- barnext = pciCfgRead(interface,bus,device,func,barnum+5);
- printf("-%d: 0x%08lx 0x%08lx", barnum+1,bar,barnext);
- }
- else {
- printf(" : 0x%08lx",bar);
- }
-
- printf(" Size: 0x");
- if (!(implemented & BASEADDRESS_IO) && (implemented & TYPE_64)) {
- printf("%08lx%08lx ",sizehi,sizelo);
- rtot = 2;
- }
- else {
- printf("%08lx ",sizelo);
- rtot = 1;
- }
-
- if (bar & BASEADDRESS_IO) {
- printf("IO");
- }
- else {
- printf("MEM %sbit",bar & TYPE_64 ? "64" : "32");
- }
-
- if (bar & PREFETCHABLE)
- printf(" prefetchable");
-
- putchar('\n');
- return(rtot);
+ int rtot;
+ ulong bar, barnext, sizehi, sizelo, implemented;
+
+ if((barnum < 0) || (barnum > 5)) {
+ return(-1);
+ }
+
+ bar = pciCfgRead(interface,bus,device,func,barnum+4);
+
+ implemented = getBarInfo(interface,bus,device,func,
+ barnum,&sizehi,&sizelo);
+
+ if(!implemented) {
+ printf("%02d BAR%d : not implemented\n",barnum+4,barnum);
+ return(0);
+ }
+
+ printf("%02d BAR%d",barnum+4,barnum);
+ if(!(implemented & BASEADDRESS_IO) && (implemented & TYPE_64)) {
+ barnext = pciCfgRead(interface,bus,device,func,barnum+5);
+ printf("-%d: 0x%08lx 0x%08lx", barnum+1,bar,barnext);
+ } else {
+ printf(" : 0x%08lx",bar);
+ }
+
+ printf(" Size: 0x");
+ if(!(implemented & BASEADDRESS_IO) && (implemented & TYPE_64)) {
+ printf("%08lx%08lx ",sizehi,sizelo);
+ rtot = 2;
+ } else {
+ printf("%08lx ",sizelo);
+ rtot = 1;
+ }
+
+ if(bar & BASEADDRESS_IO) {
+ printf("IO");
+ } else {
+ printf("MEM %sbit",bar & TYPE_64 ? "64" : "32");
+ }
+
+ if(bar & PREFETCHABLE) {
+ printf(" prefetchable");
+ }
+
+ putchar('\n');
+ return(rtot);
}
void
dumpRawCfg(long interface,long bus,long device,long func,char *range,
- char* varname)
+ char *varname)
{
- int gotone;
- long regno;
- ulong value;
-
- value = 0;
- gotone = 0;
- for(regno=0;regno<64;regno++) {
- if (inRange(range,regno)) {
- value = pciCfgRead(interface,bus,device,func,regno);
- printf("Cfg reg #%02ld: 0x%08lx\n",regno,value);
- gotone = 1;
- }
- }
- if ((varname) && (gotone))
- shell_sprintf(varname,"0x%08lx",value);
+ int gotone;
+ long regno;
+ ulong value;
+
+ value = 0;
+ gotone = 0;
+ for(regno=0; regno<64; regno++) {
+ if(inRange(range,regno)) {
+ value = pciCfgRead(interface,bus,device,func,regno);
+ printf("Cfg reg #%02ld: 0x%08lx\n",regno,value);
+ gotone = 1;
+ }
+ }
+ if((varname) && (gotone)) {
+ shell_sprintf(varname,"0x%08lx",value);
+ }
}
void
dumpConfig(long interface,long bus,long device,long func)
{
- int i;
- char *multifunc, *type;
- ulong hdrtype, values[16];
-
- for(i=0;i<16;i++)
- values[i] = pciCfgRead(interface,bus,device,func,i);
-
- hdrtype = values[3] & HDR_MASK;
-
- if (hdrtype & HDR_MULTIFUNC) {
- multifunc = "multi-function ";
- hdrtype &= ~HDR_MULTIFUNC;
- }
- else {
- multifunc = "";
- }
-
- switch(hdrtype) {
- case HDR_PCI2PCI:
- type = "PCI-to-PCI";
- break;
- case HDR_CARDBUS:
- type = "CardBus";
- break;
- case HDR_STANDARD:
- type = "Standard";
- break;
- default:
- printf("dumpConfig(): hdrtype 0x%08lx not supported\n",hdrtype);
- return;
- }
- printf("%s %sconfig...\n",type,multifunc);
-
- printf("00 DevId/VendorId: 0x%04lx/%04lx\n",
- (values[0] & 0xffff0000) >> 16,values[0] & 0xffff);
-
- printf("01 Status/Command: 0x%04lx/%04lx\n",
- (values[1] & 0xffff0000) >> 16,values[1] & 0xffff);
-
- printf("02 ClassCode/RevId: 0x%06lx/%02lx\n",
- (values[2] & 0xffffff00) >> 8,values[2] & 0xff);
-
-
- printf("03 BIST/HdrType/LatencyTmr/CacheLnSz: 0x%02lx/%02lx/%02lx/%02lx\n",
- (values[3] & 0xff000000) >> 24, (values[3] & 0xff0000) >> 16,
- (values[3] & 0xff00) >> 8,values[3] & 0xff);
-
- if (showBar(0,interface,bus,device,func) == 1)
- showBar(1,interface,bus,device,func);
-
- if (hdrtype == HDR_STANDARD) {
- if (showBar(2,interface,bus,device,func) == 1)
- showBar(3,interface,bus,device,func);
- if (showBar(4,interface,bus,device,func) == 1)
- showBar(5,interface,bus,device,func);
-
- printf("10 Cardbus CIS Ptr: 0x%08lx\n",values[10]);
- printf("11 SubSysId/SubVendorId: 0x%04lx/%04lx\n",
- (values[11] & 0xffff0000) >> 16,values[11] & 0xffff);
- printf("12 Expansion ROM BaseAddr: 0x%08lx\n",values[12]);
- }
- else if (hdrtype == HDR_PCI2PCI) {
- printf("06 Secondary Latency Tmr: 0x%02lx\n",
- (values[6] & 0xff000000) >> 24);
- printf("06 BusNum Subordinate/Secondary/Primary: 0x%02lx/%02lx/%02lx\n",
- (values[6] & 0xff0000) >> 16,
- (values[6] & 0xff00) >> 8,values[6] & 0xff);
-
- printf("07 Secondary Status: 0x%04lx\n",
- (values[7] & 0xffff0000) >> 16);
- printf("07 IO Limit/Base: 0x%02lx/%02lx\n",
- (values[7] & 0xff00) >> 8,(values[7] & 0xff));
-
- printf("08 Memory Limit/Base: 0x%04lx/%04lx\n",
- (values[8] & 0xffff0000) >> 16,values[8] & 0xffff);
-
- printf("09 Prefetchable Memory Limit/Base: 0x%04lx/%04lx\n",
- (values[9] & 0xffff0000) >> 16,values[9] & 0xffff);
-
- printf("10 Prefetchable Base Upper 32 bits: 0x%08lx\n",values[10]);
- printf("11 Prefetchable Limit Upper 32 bits: 0x%08lx\n",values[11]);
-
- printf("12 IO Upper 16 Bits Limit/Base: 0x%04lx/%04lx\n",
- (values[12] & 0xffff0000) >> 16,values[12] & 0xffff);
- }
-
- printf("13 Capabilities Ptr: 0x%02lx\n",values[13] & 0xff);
-
- if (hdrtype == HDR_STANDARD) {
- printf("15 MaxLat/MinGnt: 0x%02lx/%02lx\n",
- (values[15] & 0xff000000) >> 24, (values[15] & 0xff0000) >> 16);
- }
- else {
- printf("14 Expansion ROM BaseAddr: 0x%08lx\n",
- values[14]);
- printf("15 BridgeControl: 0x%04lx\n",
- (values[15] & 0xffff0000) >> 16);
- }
-
- printf("15 Interrupt Pin/Line: 0x%02lx/%02lx\n",
- (values[15] & 0xff00) >> 8, values[15] & 0xff);
+ int i;
+ char *multifunc, *type;
+ ulong hdrtype, values[16];
+
+ for(i=0; i<16; i++) {
+ values[i] = pciCfgRead(interface,bus,device,func,i);
+ }
+
+ hdrtype = values[3] & HDR_MASK;
+
+ if(hdrtype & HDR_MULTIFUNC) {
+ multifunc = "multi-function ";
+ hdrtype &= ~HDR_MULTIFUNC;
+ } else {
+ multifunc = "";
+ }
+
+ switch(hdrtype) {
+ case HDR_PCI2PCI:
+ type = "PCI-to-PCI";
+ break;
+ case HDR_CARDBUS:
+ type = "CardBus";
+ break;
+ case HDR_STANDARD:
+ type = "Standard";
+ break;
+ default:
+ printf("dumpConfig(): hdrtype 0x%08lx not supported\n",hdrtype);
+ return;
+ }
+ printf("%s %sconfig...\n",type,multifunc);
+
+ printf("00 DevId/VendorId: 0x%04lx/%04lx\n",
+ (values[0] & 0xffff0000) >> 16,values[0] & 0xffff);
+
+ printf("01 Status/Command: 0x%04lx/%04lx\n",
+ (values[1] & 0xffff0000) >> 16,values[1] & 0xffff);
+
+ printf("02 ClassCode/RevId: 0x%06lx/%02lx\n",
+ (values[2] & 0xffffff00) >> 8,values[2] & 0xff);
+
+
+ printf("03 BIST/HdrType/LatencyTmr/CacheLnSz: 0x%02lx/%02lx/%02lx/%02lx\n",
+ (values[3] & 0xff000000) >> 24, (values[3] & 0xff0000) >> 16,
+ (values[3] & 0xff00) >> 8,values[3] & 0xff);
+
+ if(showBar(0,interface,bus,device,func) == 1) {
+ showBar(1,interface,bus,device,func);
+ }
+
+ if(hdrtype == HDR_STANDARD) {
+ if(showBar(2,interface,bus,device,func) == 1) {
+ showBar(3,interface,bus,device,func);
+ }
+ if(showBar(4,interface,bus,device,func) == 1) {
+ showBar(5,interface,bus,device,func);
+ }
+
+ printf("10 Cardbus CIS Ptr: 0x%08lx\n",values[10]);
+ printf("11 SubSysId/SubVendorId: 0x%04lx/%04lx\n",
+ (values[11] & 0xffff0000) >> 16,values[11] & 0xffff);
+ printf("12 Expansion ROM BaseAddr: 0x%08lx\n",values[12]);
+ } else if(hdrtype == HDR_PCI2PCI) {
+ printf("06 Secondary Latency Tmr: 0x%02lx\n",
+ (values[6] & 0xff000000) >> 24);
+ printf("06 BusNum Subordinate/Secondary/Primary: 0x%02lx/%02lx/%02lx\n",
+ (values[6] & 0xff0000) >> 16,
+ (values[6] & 0xff00) >> 8,values[6] & 0xff);
+
+ printf("07 Secondary Status: 0x%04lx\n",
+ (values[7] & 0xffff0000) >> 16);
+ printf("07 IO Limit/Base: 0x%02lx/%02lx\n",
+ (values[7] & 0xff00) >> 8,(values[7] & 0xff));
+
+ printf("08 Memory Limit/Base: 0x%04lx/%04lx\n",
+ (values[8] & 0xffff0000) >> 16,values[8] & 0xffff);
+
+ printf("09 Prefetchable Memory Limit/Base: 0x%04lx/%04lx\n",
+ (values[9] & 0xffff0000) >> 16,values[9] & 0xffff);
+
+ printf("10 Prefetchable Base Upper 32 bits: 0x%08lx\n",values[10]);
+ printf("11 Prefetchable Limit Upper 32 bits: 0x%08lx\n",values[11]);
+
+ printf("12 IO Upper 16 Bits Limit/Base: 0x%04lx/%04lx\n",
+ (values[12] & 0xffff0000) >> 16,values[12] & 0xffff);
+ }
+
+ printf("13 Capabilities Ptr: 0x%02lx\n",values[13] & 0xff);
+
+ if(hdrtype == HDR_STANDARD) {
+ printf("15 MaxLat/MinGnt: 0x%02lx/%02lx\n",
+ (values[15] & 0xff000000) >> 24, (values[15] & 0xff0000) >> 16);
+ } else {
+ printf("14 Expansion ROM BaseAddr: 0x%08lx\n",
+ values[14]);
+ printf("15 BridgeControl: 0x%04lx\n",
+ (values[15] & 0xffff0000) >> 16);
+ }
+
+ printf("15 Interrupt Pin/Line: 0x%02lx/%02lx\n",
+ (values[15] & 0xff00) >> 8, values[15] & 0xff);
}
char *PciHelp[] = {
- "PCI Config Interface",
- "-[b:d:f:i:v] {operation} [args]",
+ "PCI Config Interface",
+ "-[b:d:f:i:v] {operation} [args]",
#if INCLUDE_VERBOSEHELP
- "Options:",
- " -b{###} bus #",
- " -d{###} device #",
- " -f{###} function #",
- " -i{###} interface #",
- " -v verbose",
- "Operations:",
- " scan, enum, bist, show, size {bar#}",
- " crd [reg#] [varname], cwr {reg#} {value}",
+ "Options:",
+ " -b{###} bus #",
+ " -d{###} device #",
+ " -f{###} function #",
+ " -i{###} interface #",
+ " -v verbose",
+ "Operations:",
+ " scan, enum, bist, show, size {bar#}",
+ " crd [reg#] [varname], cwr {reg#} {value}",
"Note:",
- " bus, device, function & interface default to zero",
+ " bus, device, function & interface default to zero",
#endif
- 0
+ 0
};
/* PciCmd():
* General purpose command to provide access to the config portion of
- * a PCI interface.
+ * a PCI interface.
*
* Notice that there is reference to an "interface number" as well as a
* "bus number". In most systems, there will be one host-to-pci interface.
@@ -567,181 +571,184 @@ char *PciHelp[] = {
* interface (galileo 64260A, for example, has 2 distinct host-to-PCI
* interface). Some targets will have more than one bus (depends on whether
* or not there is a pci-to-pci bridge hanging off the bus).
- *
+ *
*/
int
PciCmd(int argc, char *argv[])
{
- ulong value, bar;
- long bus, device, interface, regno, func;
- int enumerate, opt;
-
- bus = 0;
- func = 0;
- device = 0;
- enumerate = 0;
- interface = 0;
- pciVerbose = 0;
- while ((opt=getopt(argc,argv,"b:d:f:i:v")) != -1) {
- switch(opt) {
- case 'b':
- bus = strtol(optarg,0,0);
- break;
- case 'd':
- device = strtol(optarg,0,0);
- break;
- case 'f':
- func = strtol(optarg,0,0);
- break;
- case 'i': /* Most systems will only have 1 interface */
- interface = strtol(optarg,0,0);
- break;
- case 'v':
- pciVerbose = 1;
- break;
- default:
- return(CMD_FAILURE);
- }
- }
-
- if (argc < optind+1)
- return(CMD_PARAM_ERROR);
-
- /* The "scan" and "enum" commands are very similar. They both use
- * the pciscan() function.
- *
- * Scan: look at the devices on the specified bus.
- * Enum: a recursive scan... start with bus 0 and attempt to query
- * all devices on all busses, making the necessary bus-number assignments
- * along the way.
- */
-
- /* For scan, the device number is ignored, all devices on a particular
- * interface/bus are checked. If ths bus number is something other than
- * zero, then this function assumes that the appropriate pci-to-pci
- * bridge device has already had its bus numbers assigned.
- */
- if (!strcmp(argv[optind],"scan")) {
- if (argc != optind+1)
- return(CMD_PARAM_ERROR);
-
- pciscan(interface,bus,func,1,0);
- return(CMD_SUCCESS);
- }
-
- /* For enum, we start with bus 0, and attempt to enumerate all busses...
- */
- if (!strcmp(argv[optind],"enum")) {
- if (argc != optind+1)
- return(CMD_PARAM_ERROR);
-
- pciscan(interface,0,func,1,1);
- return(CMD_SUCCESS);
- }
-
- if (!strcmp(argv[optind],"size")) { /* See pg 204 of PCI2.2 spec */
- int barnum;
- ulong implemented, sizehi, sizelo;
-
- if (argc != optind+2)
- return(CMD_PARAM_ERROR);
-
- /* The argument to size is the BAR #. The value can be a single
- * digit or a range specification...
- */
- printf(" Bar Type Value Size\n");
- for(barnum=0;barnum<6;barnum++) {
- setenv("PCISIZE",0);
- if (inRange(argv[optind+1],barnum)) {
- /* Disable decoding through the command register:
- * See section 6.2.2, pg 193.
- */
- value = pciCfgRead(interface,bus,device,func,1);
- pciCfgWrite(interface,bus,device,0,1,
- value & ~(IO_SPACE | MEMORY_SPACE));
-
- bar = pciCfgRead(interface,bus,device,func,barnum+4);
- implemented = getBarInfo(interface,bus,device,func,
- barnum,&sizehi,&sizelo);
-
- printf(" %d ",barnum);
-
- if (implemented) {
- shell_sprintf("PCISIZE","0x%08lx",bar);
- printf("%s 0x%08lx ",
- implemented & BASEADDRESS_IO ? "io " : "mem", bar);
- if (implemented & TYPE_64)
- printf("0x%08lx%08lx",sizehi,sizelo);
- else
- printf("0x%08lx",sizelo);
- if (implemented & PREFETCHABLE)
- printf(" (prefetchable)");
- putchar('\n');
- }
- else
- printf("not implemented\n");
- }
- }
- }
- else if (!strcmp(argv[optind],"bist")) {
- if (argc != optind+1)
- return(CMD_PARAM_ERROR);
-
- value = pciCfgRead(interface,bus,device,func,3);
-
- if (value & BIST_CAPABLE) {
- /* Set the BIST_START bit to begin the test, then wait for
- * the BIST_START bit to clear as an indication that the
- * test has completed.
- */
- pciCfgWrite(interface,bus,device,func,3,value | BIST_START);
- while(1) {
- value = pciCfgRead(interface,bus,device,func,3);
- if ((value & BIST_START) != BIST_START)
- break;
- }
- if ((value & BIST_COMPCODE_MASK) != 0)
- printf("BIST failed: 0x%lx\n",value & BIST_COMPCODE_MASK);
- else
- printf("BIST passed\n");
- }
- else {
- printf("Device %ld is not BIST-capable\n",device);
- }
- }
- else if (!strcmp(argv[optind],"crd")) {
- char *varname = (char *)0;
-
- if (argc == optind+3) { /* varname specified ? */
- varname = argv[optind+2];
- argc--;
- }
-
- if (argc == optind+2) {
- dumpRawCfg(interface,bus,device,func,argv[optind+1],varname);
- }
- else if (argc == optind+1) {
- dumpConfig(interface,bus,device,func);
- }
- else
- return(CMD_PARAM_ERROR);
- }
- else if (!strcmp(argv[optind],"cwr")) {
- if (argc != optind+3)
- return(CMD_PARAM_ERROR);
-
- regno = strtol(argv[optind+1],0,0);
- value = strtol(argv[optind+2],0,0);
- pciCfgWrite(interface,bus,device,func,regno,value);
- }
- else if (!strcmp(argv[optind],"init")) {
- pciCtrl(interface,PCICTRL_INIT,0,0);
- }
- else if (!strcmp(argv[optind],"show")) {
- pciShow(interface);
- }
- else
- return(CMD_PARAM_ERROR);
- return(CMD_SUCCESS);
+ ulong value, bar;
+ long bus, device, interface, regno, func;
+ int enumerate, opt;
+
+ bus = 0;
+ func = 0;
+ device = 0;
+ enumerate = 0;
+ interface = 0;
+ pciVerbose = 0;
+ while((opt=getopt(argc,argv,"b:d:f:i:v")) != -1) {
+ switch(opt) {
+ case 'b':
+ bus = strtol(optarg,0,0);
+ break;
+ case 'd':
+ device = strtol(optarg,0,0);
+ break;
+ case 'f':
+ func = strtol(optarg,0,0);
+ break;
+ case 'i': /* Most systems will only have 1 interface */
+ interface = strtol(optarg,0,0);
+ break;
+ case 'v':
+ pciVerbose = 1;
+ break;
+ default:
+ return(CMD_FAILURE);
+ }
+ }
+
+ if(argc < optind+1) {
+ return(CMD_PARAM_ERROR);
+ }
+
+ /* The "scan" and "enum" commands are very similar. They both use
+ * the pciscan() function.
+ *
+ * Scan: look at the devices on the specified bus.
+ * Enum: a recursive scan... start with bus 0 and attempt to query
+ * all devices on all busses, making the necessary bus-number assignments
+ * along the way.
+ */
+
+ /* For scan, the device number is ignored, all devices on a particular
+ * interface/bus are checked. If ths bus number is something other than
+ * zero, then this function assumes that the appropriate pci-to-pci
+ * bridge device has already had its bus numbers assigned.
+ */
+ if(!strcmp(argv[optind],"scan")) {
+ if(argc != optind+1) {
+ return(CMD_PARAM_ERROR);
+ }
+
+ pciscan(interface,bus,func,1,0);
+ return(CMD_SUCCESS);
+ }
+
+ /* For enum, we start with bus 0, and attempt to enumerate all busses...
+ */
+ if(!strcmp(argv[optind],"enum")) {
+ if(argc != optind+1) {
+ return(CMD_PARAM_ERROR);
+ }
+
+ pciscan(interface,0,func,1,1);
+ return(CMD_SUCCESS);
+ }
+
+ if(!strcmp(argv[optind],"size")) { /* See pg 204 of PCI2.2 spec */
+ int barnum;
+ ulong implemented, sizehi, sizelo;
+
+ if(argc != optind+2) {
+ return(CMD_PARAM_ERROR);
+ }
+
+ /* The argument to size is the BAR #. The value can be a single
+ * digit or a range specification...
+ */
+ printf(" Bar Type Value Size\n");
+ for(barnum=0; barnum<6; barnum++) {
+ setenv("PCISIZE",0);
+ if(inRange(argv[optind+1],barnum)) {
+ /* Disable decoding through the command register:
+ * See section 6.2.2, pg 193.
+ */
+ value = pciCfgRead(interface,bus,device,func,1);
+ pciCfgWrite(interface,bus,device,0,1,
+ value & ~(IO_SPACE | MEMORY_SPACE));
+
+ bar = pciCfgRead(interface,bus,device,func,barnum+4);
+ implemented = getBarInfo(interface,bus,device,func,
+ barnum,&sizehi,&sizelo);
+
+ printf(" %d ",barnum);
+
+ if(implemented) {
+ shell_sprintf("PCISIZE","0x%08lx",bar);
+ printf("%s 0x%08lx ",
+ implemented & BASEADDRESS_IO ? "io " : "mem", bar);
+ if(implemented & TYPE_64) {
+ printf("0x%08lx%08lx",sizehi,sizelo);
+ } else {
+ printf("0x%08lx",sizelo);
+ }
+ if(implemented & PREFETCHABLE) {
+ printf(" (prefetchable)");
+ }
+ putchar('\n');
+ } else {
+ printf("not implemented\n");
+ }
+ }
+ }
+ } else if(!strcmp(argv[optind],"bist")) {
+ if(argc != optind+1) {
+ return(CMD_PARAM_ERROR);
+ }
+
+ value = pciCfgRead(interface,bus,device,func,3);
+
+ if(value & BIST_CAPABLE) {
+ /* Set the BIST_START bit to begin the test, then wait for
+ * the BIST_START bit to clear as an indication that the
+ * test has completed.
+ */
+ pciCfgWrite(interface,bus,device,func,3,value | BIST_START);
+ while(1) {
+ value = pciCfgRead(interface,bus,device,func,3);
+ if((value & BIST_START) != BIST_START) {
+ break;
+ }
+ }
+ if((value & BIST_COMPCODE_MASK) != 0) {
+ printf("BIST failed: 0x%lx\n",value & BIST_COMPCODE_MASK);
+ } else {
+ printf("BIST passed\n");
+ }
+ } else {
+ printf("Device %ld is not BIST-capable\n",device);
+ }
+ } else if(!strcmp(argv[optind],"crd")) {
+ char *varname = (char *)0;
+
+ if(argc == optind+3) { /* varname specified ? */
+ varname = argv[optind+2];
+ argc--;
+ }
+
+ if(argc == optind+2) {
+ dumpRawCfg(interface,bus,device,func,argv[optind+1],varname);
+ } else if(argc == optind+1) {
+ dumpConfig(interface,bus,device,func);
+ } else {
+ return(CMD_PARAM_ERROR);
+ }
+ } else if(!strcmp(argv[optind],"cwr")) {
+ if(argc != optind+3) {
+ return(CMD_PARAM_ERROR);
+ }
+
+ regno = strtol(argv[optind+1],0,0);
+ value = strtol(argv[optind+2],0,0);
+ pciCfgWrite(interface,bus,device,func,regno,value);
+ } else if(!strcmp(argv[optind],"init")) {
+ pciCtrl(interface,PCICTRL_INIT,0,0);
+ } else if(!strcmp(argv[optind],"show")) {
+ pciShow(interface);
+ } else {
+ return(CMD_PARAM_ERROR);
+ }
+ return(CMD_SUCCESS);
}
#endif