📄 sysgei82543end.c
字号:
UINT32 deviceId; /* store a PCI device ID */ UINT8 revisionId; /* store a PCI revision ID */ pciConfigInLong (pciBus, pciDevice, pciFunc, PCI_CFG_VENDOR_ID, &vendorId); pciConfigInByte (pciBus, pciDevice, pciFunc, PCI_CFG_REVISION, &revisionId); deviceId = ((vendorId >> 16) & 0x0000ffff); vendorId = (vendorId & 0x0000ffff); if ((boardType = sysGeiDevToType (vendorId, deviceId, revisionId)) != (UINT32)(BOARD_TYPE_UNKNOWN)) { int pciSysNum = *(int *)pPciSysNum; sys543PciInit (pciBus, pciDevice, pciFunc, vendorId, deviceId, revisionId, boardType, pciSysNum); } return OK; }/******************************************************************************* sys543PciInit - initialize a GEI 8254x PCI ethernet device** This routine performs basic PCI initialization for 8254x ethernet* devices supported by the gei82543End END driver. Parameters to this* routine specify a PCI function, including PCI ID registers, to* initialize. If supported, the device memory and I/O addresses are* mapped into the local CPU address space and an internal board-specific* PCI resources table is updated with information on the board type,* memory address, and IO address.** RETURNS:* OK, or ERROR if the specified device is not supported, or if* the device could not be mapped into the local CPU memory space.*/STATUS sys543PciInit ( UINT32 pciBus, /* store a PCI bus number */ UINT32 pciDevice, /* store a PCI device number */ UINT32 pciFunc, /* store a PCI function number */ UINT32 vendorId, /* store a PCI vendor ID */ UINT32 deviceId, /* store a PCI device ID */ UINT8 revisionId, /* store a PCI revision ID */ UINT32 boardType, /* board type */ int pciSysNum /* PCI system number */ ) { UINT32 memBaseLo; /* temporary BAR storage */ UINT32 memBaseHi; UINT32 flashBase; UINT8 irq; /* store PCI interrupt line (IRQ) number */ GEI_RESOURCE * pReso; /* alias extended resource table */ /* number of physical units exceeded the number supported ? */ if (geiUnits >= GEI_MAX_DEV) { return (ERROR); } if (pciSysNum != PCI_1_BUS && pciSysNum != PCI_2_BUS) return ERROR; /* BAR information will be saved in the extended resource table */ /* * Note to enable configuration of PCI1 and PCI2 gei pciSysNum is used * to distinguish. It is assumed only one gei is available for either. */ pReso = (GEI_RESOURCE *)(geiPciResources[geiUnits].pExtended); geiPciResources[geiUnits].pciSysNum = pciSysNum;#if (PCI_CFG_TYPE != PCI_CFG_AUTO) { pciConfigOutLong (pciBus, pciDevice, pciFunc, PCI_CFG_BASE_ADDRESS_0, pReso->memBaseLow); if (pReso->adr64) { pciConfigOutLong (pciBus, pciDevice, pciFunc,PCI_CFG_BASE_ADDRESS_1, pReso->memBaseHigh); pciConfigOutLong (pciBus, pciDevice, pciFunc, PCI_CFG_BASE_ADDRESS_2, pReso->flashBase); } { pciConfigOutLong (pciBus, pciDevice, pciFunc, PCI_CFG_BASE_ADDRESS_1, pReso->flashBase); pciConfigOutLong (pciBus, pciDevice, pciFunc, PCI_CFG_BASE_ADDRESS_2, pReso->flashBase); } pciConfigOutByte (pciBus, pciDevice, pciFunc, PCI_CFG_DEV_INT_LINE, geiPciResources[geiUnits].irq); }#endif /* * BAR0: [32:17]: memory base * [16:4] : read as "0"; * [3] : 0 - device is not prefetchable * [2:1] : 00b - 32-bit address space, or * 01b - 64-bit address space * [0] : 0 - memory map decoded * * BAR1: if BAR0[2:1] == 00b, optional flash memory base * if BAR0[2:1] == 01b, high portion of memory base * for 64-bit address space * * BAR2: if BAR0[2:1] == 01b, optional flash memory base * if BAR0[2:1] == 00b, behaves as BAR-1 when BAR-0 is * a 32-bit value */ pciConfigInLong (pciBus, pciDevice, pciFunc, PCI_CFG_BASE_ADDRESS_0, &memBaseLo); pReso->adr64 = ((memBaseLo & BAR0_64_BIT) == BAR0_64_BIT) ? TRUE : FALSE; if (pReso->adr64) { pciConfigInLong (pciBus, pciDevice, pciFunc, PCI_CFG_BASE_ADDRESS_1, &memBaseHi); pciConfigInLong (pciBus, pciDevice, pciFunc, PCI_CFG_BASE_ADDRESS_2, &flashBase); } else { memBaseHi = 0x0; pciConfigInLong (pciBus, pciDevice, pciFunc, PCI_CFG_BASE_ADDRESS_1, &flashBase); } memBaseLo &= PCI_MEMBASE_MASK; flashBase &= PCI_MEMBASE_MASK; /* get the device's interrupt line (IRQ) number */ pciConfigInByte (pciBus, pciDevice, pciFunc, PCI_CFG_DEV_INT_LINE, &irq); /* update the board-specific resource tables */ pReso->memBaseLow = memBaseLo; pReso->memBaseHigh = memBaseHi; pReso->flashBase = flashBase; geiPciResources[geiUnits].irq = irq; geiPciResources[geiUnits].irqvec = irq; geiPciResources[geiUnits].vendorID = vendorId; geiPciResources[geiUnits].deviceID = deviceId; geiPciResources[geiUnits].revisionID = revisionId; geiPciResources[geiUnits].boardType = boardType; /* the following support legacy interfaces and data structures */ geiPciResources[geiUnits].pciBus = pciBus; geiPciResources[geiUnits].pciDevice = pciDevice; geiPciResources[geiUnits].pciFunc = pciFunc; /* enable mapped memory and IO decoders */ pciConfigOutWord (pciBus, pciDevice, pciFunc, PCI_CFG_COMMAND, PCI_CMD_MEM_ENABLE | PCI_CMD_IO_ENABLE | PCI_CMD_MASTER_ENABLE); /* disable sleep mode */ pciConfigOutByte (pciBus, pciDevice, pciFunc, PCI_CFG_MODE, SLEEP_MODE_DIS); ++geiUnits; /* increment number of units initialized */ return (OK); }/******************************************************************************** sysGei8254xEndLoad - create load string and load a gei driver.** This routine will be invoked by the MUX for the purpose of loading an* gei82543End (gei) device with initial parameters. This routine is* constructed as an interface wrapper for the driver load routine. Thus,* the arguments and return values are consistent with any xxxEndLoad()* routine defined for an END driver and the MUX API.** INTERNAL* The muxDevLoad() operation calls this routine twice. A zero length* <pParamStr> parameter string indicates that this is the first time* through this routine. The driver load routine should return the* driver name in <pParamStr>.** On the second pass though this routine, the initialization parameter* string is constructed. Note that on the second pass, the <pParamStr>* consists of a colon-delimited END device unit number and rudimentary* initialization string (often empty) constructed from entries in the* BSP END Device Table such that:** <pParamStr> = "<unit>:<default initialization string>"** In the process of building the rest of <pParamStr>, the prepended unit* number must be preserved and passed to the driver load routine. The* <default initialization string> portion mentioned above is discarded,* but future versions of this routine may use it.** The complete gei82543End driver load string has format:** <unit>:<shMemBase>:<shMemSize>:<rxDesNum>:<txDesNum>:<usrFlags>:* <offset>:<mtu>** RETURNS: An END object pointer, or NULL on error, or 0 and the name of the* device if the <pParamStr> was NULL.** SEE ALSO: gei82543EndLoad()*/END_OBJ * sysGei8254xEndLoad ( char * pParamStr, /* ptr to initialization parameter string */ void * unused /* unused optional argument */ ) { END_OBJ * pEnd; char paramStr [END_INIT_STR_MAX]; if (strlen (pParamStr) == 0) { /* PASS (1) * The driver load routine returns the driver name in <pParamStr>. */ pEnd = gei82543EndLoad (pParamStr); } else { /* PASS (2) * The END <unit> number is prepended to <pParamStr>. Construct * the rest of the driver load string based on physical devices * discovered in sys543PciInit(). When this routine is called * to process a particular END <unit> number, use the END <unit> as * an index into the PCI "resources" table to build the driver * parameter string. */ GEI_RESOURCE * pReso; char * holder = NULL; int unit = atoi (strtok_r (pParamStr, ":", &holder)); /* is there a PCI resource associated with this END unit ? */ if (unit >= geiUnits) { return NULL; } pReso = (GEI_RESOURCE *)(geiPciResources[unit].pExtended); /* finish off the initialization parameter string */ sprintf (paramStr,"%d:0x%x:0x%x:0x%x:0x%x:0x%x:%d:%d", unit, /* END unit number */ pReso->shMemBase, /* share memory base */ pReso->shMemSize, /* share memory size */ pReso->rxDesNum, /* RX Descriptor Number*/ pReso->txDesNum, /* TX Descriptor Number*/ pReso->usrFlags, /* user's flags */ GEI_OFFSET_VALUE, /* offset value */ GEI_JUMBO_MTU_VALUE /* mtu value */ ); if ((pEnd = gei82543EndLoad (paramStr)) == (END_OBJ *)NULL) { printf ("ERROR: sysGei8254xEndLoad fails to load gei %d\n", unit); } } return (pEnd); }/******************************************************************************* sys82543BoardInit - Adaptor initialization for 8254x chip** This routine is expected to perform any adapter-specific or target-specific* initialization that must be done prior to initializing the 8254x chip.** The 82543 driver calls this routine from the driver load routine before* any other routines.** RETURNS: OK or ERROR*/STATUS sys82543BoardInit ( int unit, /* unit number */ ADAPTOR_INFO * pBoard /* board information for the GEI driver */ ) { PCI_BOARD_RESOURCE * pRsrc; GEI_RESOURCE * pReso; BOOL lanB = FALSE; /* sanity check */ if (unit >= geiUnits) return (ERROR); pRsrc = &geiPciResources[unit]; pReso = (GEI_RESOURCE *)(pRsrc->pExtended); if (pRsrc->boardType != PRO1000_543_BOARD && pRsrc->boardType != PRO1000_544_BOARD && pRsrc->boardType != PRO1000_546_BOARD) return ERROR; if (pRsrc->pciSysNum != PCI_1_BUS && pRsrc->pciSysNum != PCI_2_BUS) { printf ("ERROR: UNKNOWN PCI system number %d in gei unit %d \n", pRsrc->pciSysNum, unit); return ERROR; } /* configure the PCI system number */ sysPciConfigEnable (pRsrc->pciSysNum); if (pRsrc->boardType == PRO1000_546_BOARD) { UINT32 eecd; UINT16 devId; if (!((eecd = GEI_SYS_READ_REG(unit, INTEL_82543GC_EECD)) & EECD_PRES_BIT)) { printf ("ERROR: gei unit %d eeprom not presented\n", unit); return ERROR; } pReso->eepromSize = (eecd & EECD_SIZE_BIT)? 256 : 64; /* detect if this is one of 82546EB dual ports */ pciConfigInWord (pRsrc->pciBus, pRsrc->pciDevice, pRsrc->pciFunc, PCI_CFG_DEVICE_ID, &devId); if (devId == PRO1000_546_PCI_DEVICE_ID_XT || devId == PRO1000_546_PCI_DEVICE_ID_MF) { UINT8 headerType; pciConfigInByte (pRsrc->pciBus, pRsrc->pciDevice, pRsrc->pciFunc, PCI_CFG_HEADER_TYPE, &headerType); if (headerType == 0x80) lanB = (pRsrc->pciFunc == 1)? TRUE : FALSE; else if (pRsrc->pciFunc != 0) { printf ("Error in detecting 82546 dual port: header type =%2d, " "pci func=%2d\n", (UINT32)headerType, (UINT32)(pRsrc->pciFunc)); } } } /* perform EEPROM checksum */ if (sys543eepromCheckSum (unit) != OK) { printf ("ERROR: gei unit=%d, EEPROM checksum error!\n", unit); } /* get the Ethernet Address from eeprom */ if (sys543EtherAdrGet (unit) == OK) { if (pRsrc->boardType == PRO1000_546_BOARD && lanB == TRUE) { int ix; /* update LANB address */ for (ix = 5; ix >= 0; ix--) { if (pReso->enetAddr[ix] != 0xff) { pReso->enetAddr[ix]++; break; } else pReso->enetAddr[ix] = 0; } } } else printf ("ERROR: gei unit=%d, Invalid Ethernet Address!\n", unit); /* get the initialization control word 1 (ICW1) in EEPROM */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -