📄 if_fei.c
字号:
LINK_WR (&pDrvCtrl->pCSR->scbGP, addr); pDrvCtrl->pCSR->scbCommand |= cmd; /* write SCB command byte */ return (OK); }#ifdef FEI_DEBUG/********************************************************************************* feiDumpPrint - Display statistical counters** This routine displays i82557 statistical counters** RETURNS: OK, or ERROR if the DUMP command failed.*/LOCAL STATUS feiDumpPrint ( int unit ) { UINT32 dumpArray [18]; UINT32 * pDump; STATUS status = OK; /* dump area must be long-word allign */ pDump = (UINT32 *) (((UINT32) dumpArray + 4) & 0xfffffffc); status = feiErrCounterDump(unit,pDump); printf ("\n"); printf ("Tx good frames: %d\n", *pDump++); printf ("Tx MAXCOL errors: %d\n", *pDump++); printf ("Tx LATECOL errors: %d\n", *pDump++); printf ("Tx underrun errors: %d\n", *pDump++); printf ("Tx lost CRS errors: %d\n", *pDump++); printf ("Tx deferred: %d\n", *pDump++); printf ("Tx single collisions: %d\n", *pDump++); printf ("Tx multiple collisions: %d\n", *pDump++); printf ("Tx total collisions: %d\n", *pDump++); printf ("Rx good frames: %d\n", *pDump++); printf ("Rx CRC errors: %d\n", *pDump++); printf ("Rx allignment errors: %d\n", *pDump++); printf ("Rx resource errors: %d\n", *pDump++); printf ("Rx overrun errors: %d\n", *pDump++); printf ("Rx collision detect errors: %d\n", *pDump++); printf ("Rx short frame errors: %d\n", *pDump++); return (status); }/******************************************************************************* feiErrCounterDump - dump statistical counters ** This routine dumps statistical counters for the purpose of debugging and* tuning the 82557.** The <memAddr> parameter is the pointer to an array of 68 bytes in the* local memory. This memory region must be allocated before this routine is* called. The memory space must also be DWORD (4 bytes) aligned. When the* last DWORD (4 bytes) is written to a value, 0xa007, it indicates the dump* command has completed. To determine the meaning of each statistical* counter, see the Intel 82557 manual.** RETURNS: OK or ERROR.*/LOCAL STATUS feiErrCounterDump ( int unit, UINT32 *memAddr ) { DRV_CTRL * pDrvCtrl = &drvCtrl [unit]; STATUS status = OK; int i; int s = splimp (); /* block network access to 82557 resource */ memAddr[16]=0; /* make sure the last DWORD is 0 */ /* tells the 82557 where to write dump data */ if (feiSCBCommand (pDrvCtrl, SCB_C_CULDDUMP, TRUE, (UINT32 *) LOCAL_TO_SYS_ADDR(unit,(UINT32)memAddr) ) == ERROR) status = ERROR; /* issue the dump and reset counter command */ if (feiSCBCommand (pDrvCtrl, SCB_C_CUDUMPRST,FALSE,(UINT32)0) == ERROR) status = ERROR; splx (s); /* release 82557 resource to network */ /* waits for it done */ for (i=0;i<60;i++) { if (memAddr[16] == (UINT32)0xa007) break; taskDelay(2); } if (i==60) status = ERROR; return (status); }#endif /* FEI_DEBUG *//****************************************************************************** feiMDIRead - read the MDI register** This routine reads the specific register in the PHY device* Valid PHY address is 0-31** RETURNS: OK or ERROR.**/static int feiMDIRead ( int unit, int regAddr, int phyAddr, UINT16 *retVal ) { DRV_CTRL * pDrvCtrl = &drvCtrl [unit]; int i; UINT32 mdrValue; volatile UINT32 *mdiReg = (volatile UINT32 *)&pDrvCtrl->pCSR->mdiCR; mdrValue = ((regAddr<<16) | (phyAddr << 21) | (MDI_READ<<26) ); /* write to MDI */ *mdiReg = mdrValue; taskDelay(2); /* wait for a while */ /* check if it's done */ for (i=0;i<40;i++) { if ( (*mdiReg) & (1<<28) ) break; taskDelay(1); } if (i==40) return (ERROR); *retVal = (UINT16)((*mdiReg)&0xffff); return(OK); } /**************************************************************************** feiMDIWrite - write to the MDI register** This routine writes the specific register in the PHY device* Valid PHY address is 0-31** RETURNS: OK or ERROR.*/static int feiMDIWrite ( int unit, int regAddr, int phyAddr, UINT16 writeData ) { DRV_CTRL * pDrvCtrl = &drvCtrl [unit]; int i; UINT32 mdrValue; volatile UINT32 *mdrReg = (volatile UINT32 *)&pDrvCtrl->pCSR->mdiCR; mdrValue = ((regAddr<<16) | (phyAddr << 21) | (MDI_WRITE<<26) | writeData ); /* write to M */ *mdrReg = mdrValue; taskDelay(2); /* wait for a while */ /* check if it's done */ for (i=0;i<40;i++) { if ( (*mdrReg) & (1<<28) ) break; taskDelay(1); } if (i==40) return (ERROR); return(OK); }/****************************************************************************** feiMDIPhyLinkSet - detect and set the link for the PHY device** This routine first checks if the link has been established. If not, it* isolates the other one, and tries to establish the link. PHY device 0 is* always at PHY address 0. PHY 1 can be at 1-31 PHY addresses.** RETURNS: OK or ERROR.**/static int feiMDIPhyLinkSet ( int unit, int phyAddr ) { UINT16 ctlReg; UINT16 statusReg; int isoDev,i; /* read control register */ feiMDIRead (unit, MDI_CTRL_REG, phyAddr, &ctlReg); /* read again */ feiMDIRead (unit, MDI_CTRL_REG, phyAddr, &ctlReg); /* check if the PHY is there */ if (ctlReg == (UINT16)0xffff) return (ERROR); /* no PHY present */#if 0 /* CR RESET will cause link down */ feiMDIWrite (unit,MDI_CTRL_REG,phyAddr,MDI_CR_RESET); taskDelay(4);#endif /* The PHY is there, read status register */ feiMDIRead (unit, MDI_STATUS_REG, phyAddr,&statusReg); /* in case the status bit is the latched bit */ if ( !(statusReg & MDI_SR_LINK_STATUS)) feiMDIRead (unit, MDI_STATUS_REG, phyAddr, &statusReg); if (statusReg & MDI_SR_LINK_STATUS) return (OK); /* Device found and link OK */ /* no link is established, let's configure it */ /* isolates the other PHY */ isoDev = (phyAddr)?0:1; feiMDIWrite (unit,MDI_CTRL_REG,isoDev,MDI_CR_ISOLATE); /* wait for a while */ taskDelay (2); /* enable the PHY device we try to configure */ feiMDIWrite (unit,MDI_CTRL_REG,phyAddr,MDI_CR_SELECT); taskDelay (2); /* wait for a while for command take effect */ /* restart the auto negotiation process, execute anyways even if * it has no such capability. */ feiMDIWrite (unit,MDI_CTRL_REG,phyAddr,MDI_CR_RESTART | MDI_CR_SELECT); /* wait for auto-negotiation to complete */ for (i=0;i<80;i++) { /* read the status register */ feiMDIRead (unit, MDI_STATUS_REG, phyAddr, &statusReg); feiMDIRead (unit, MDI_STATUS_REG, phyAddr, &statusReg); if (statusReg & (MDI_SR_AUTO_NEG | MDI_SR_REMOTE_FAULT) ) break; taskDelay (2); if (!(statusReg & MDI_SR_AUTO_SELECT) ) break; /* no such capability */ } /* Read the status register */ feiMDIRead (unit, MDI_STATUS_REG, phyAddr, &statusReg); /* some of the status bits require to clear a latch */ if ( !(statusReg & MDI_SR_LINK_STATUS)) feiMDIRead (unit, MDI_STATUS_REG, phyAddr, &statusReg); if (statusReg & MDI_SR_LINK_STATUS) return (OK); /* Link configure done and successful */ return (PHY_LINK_ERROR); /* device is there, cann't establish link */ }/***************************************************************************** feiMDIPhyConfig - configure the PHY device** This routine configures the PHY device according to the parameters* specified by users or the default value.** RETURNS: OK or ERROR.**/static int feiMDIPhyConfig ( int unit, int phyAddr ) { DRV_CTRL * pDrvCtrl = &drvCtrl [unit]; UINT16 ctlReg = 0; int fullDpx=FALSE; int autoSelect =FALSE; UINT16 statusReg; int status,i; /* find out what capabilities the device have */ /* read status register */ feiMDIRead (unit, MDI_STATUS_REG, phyAddr,&statusReg); /* some of the status bits require to read twice */ feiMDIRead (unit, MDI_STATUS_REG, phyAddr, &statusReg); /* The device at least has to have the half duplex and 10mb speed */ if (statusReg & (MDI_SR_10T_FULL_DPX | MDI_SR_TX_FULL_DPX) ) fullDpx = TRUE; if (statusReg & MDI_SR_AUTO_SELECT) autoSelect = TRUE;#ifdef FEI_DEBUG logMsg ("status REG = %x !!!! \n",statusReg,0,0,0,0,0);#endif /* FEI_DEBUG */ if (pDrvCtrl->board.phyDpx == PHY_FULL_DPX && fullDpx == TRUE) ctlReg |= MDI_CR_FDX; if (pDrvCtrl->board.phySpeed == PHY_100MBS) ctlReg |= MDI_CR_100; if (pDrvCtrl->board.phySpeed == PHY_AUTO_SPEED || pDrvCtrl->board.phyDpx == PHY_AUTO_DPX ) { if (autoSelect != TRUE) { /* set back to default */ pDrvCtrl->board.phySpeed = PHY_10MBS; pDrvCtrl->board.phyDpx = PHY_HALF_DPX; ctlReg |= (PHY_10MBS | PHY_HALF_DPX); } else ctlReg |= (MDI_CR_SELECT|MDI_CR_RESTART); } /* or other possible board level selection */ ctlReg |= pDrvCtrl->board.others; /* configure the PHY */ feiMDIWrite (unit,MDI_CTRL_REG,phyAddr,ctlReg); taskDelay (2); /* wait for a while */ if (! (ctlReg & MDI_CR_RESTART) ) return (OK); /* we are here if the restart auto negotiation is selected */#ifdef FEI_DEBUG logMsg ("auto NEGOTIATION STARTS !!!! \n",0,0,0,0,0,0);#endif /* FEI_DEBUG */ /* wait for it done */ for (status = PHY_AUTO_FAIL,i=0;i<80;i++) { /* read status register, some bits have the latch,first read clears */ feiMDIRead (unit, MDI_STATUS_REG, phyAddr,&statusReg); feiMDIRead (unit, MDI_STATUS_REG, phyAddr, &statusReg); if (statusReg & MDI_SR_AUTO_NEG) { status = OK; /* auto negotiation completed */ break; } if (statusReg & MDI_SR_REMOTE_FAULT) { status = PHY_AUTO_FAIL; /* auto negotiation fails */ break; } } return (status); } /**************************************************************************** feiPhyInit - initialize and configure the PHY device if there is one** This routine initialize and configure the PHY device if there is one.** RETURNS: OK or ERROR.**/static int feiPhyInit ( int unit ) { int status; int phyDevice; DRV_CTRL * pDrvCtrl = &drvCtrl [unit]; if (pDrvCtrl->board.phyAddr > 31) return (OK); /* not a MII interface,no need to initialize PHY */ /* configure the Physical layer medium if it's MII interface */ /* starts with logical PHY 1 */ phyDevice = pDrvCtrl->board.phyAddr?pDrvCtrl->board.phyAddr:1; status = feiMDIPhyLinkSet(unit,phyDevice); if (status != OK) { phyDevice = 0; status = feiMDIPhyLinkSet(unit,phyDevice); } if (status != OK) { printf ("LINK_FAIL error, check the line connection !!!\n"); return (status); } /* we are here if a valid link is established */ status = feiMDIPhyConfig (unit,phyDevice); if (status == PHY_AUTO_FAIL) { /* force default speed and duplex */ pDrvCtrl->board.phySpeed = PHY_10MBS; pDrvCtrl->board.phyDpx = PHY_HALF_DPX; pDrvCtrl->board.others = 0; /* and configure it again */ status = feiMDIPhyConfig (unit,phyDevice); } return (status); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -