?? drivers_net_arm_ep93xx_eth_c_diff.htm
字號:
+}/*_phy_write()*/
+
+/*****************************************************************************
+* _phy_read()
+*****************************************************************************/
+static u16 _phy_read(struct net_device *pD, int idPhy, int reg)
+{
+ u16 dt;
+
+/* _PRTK_ENTRY(("_phy_read(pD:0x%p,idPhy:%d,reg:0x%x)\n",pD,idPhy,reg)); */
+
+ phy_waitRdy();
+ RegWr32(REG_MIICmd,
+ MIICmd_OP_RD | ((idPhy & 0x1f) << 5) | ((reg & 0x1f) << 0));
+ phy_waitRdy();
+ dt = (unsigned short)RegRd32(REG_MIIData);
+
+/* _PRTK_INFO(("_phy_read(): read 0x%x\n",dt));*/
+
+ return dt;
+}/*_phy_read()*/
+
+#ifndef _PRTK_DUMP
+#define _dbg_phy_dumpReg(pD)
+#else
+/*****************************************************************************
+* _dbg_phy_dumpReg()
+*****************************************************************************/
+static void _dbg_phy_dumpReg(struct net_device *pD)
+{
+ _PRTK_DUMP(("Dumping registers of Ethernet PHY\n"));
+ _PRTK_DUMP((" pD:0x%p, Eth Base Address:0x%x\n", pD,
+ (unsigned int)pD->base_addr));
+
+ _PRTK_DUMP((" 0-3:0x%04x 0x%04x 0x%04x 0x%04x\n",
+ phy_rd(0), phy_rd(1), phy_rd(2), phy_rd(3)));
+ _PRTK_DUMP((" 4-6:0x%04x 0x%04x 0x%04x\n",
+ phy_rd(4), phy_rd(5), phy_rd(6)));
+ _PRTK_DUMP((" 16-19:0x%04x 0x%04x 0x%04x 0x%04x\n",
+ phy_rd(16), phy_rd(17), phy_rd(18), phy_rd(19)));
+ _PRTK_DUMP((" 20:0x%04x\n", phy_rd(20)));
+}/*_dbg_phy_dumpReg()*/
+#endif /*ifndef _PRTK_DUMP else */
+
+/*****************************************************************************
+* phy_autoNegotiation()
+*****************************************************************************/
+static int phy_autoNegotiation(struct net_device *pD)
+{
+ u16 val;
+ u16 oldVal;
+ u16 count = 0;
+
+ phy_wr(4, 0x01e1); /* Set 802.3, 100M/10M Full/Half ability */
+ phy_wr(0, (1 << 12) | (1 << 9)); /* enable auto negotiation */
+ while (1) {
+ val = phy_rd(1); /* read BM status Reg */
+ if (val & 0x0020) { /* if Auto_Neg_complete? */
+ break;
+ } else {
+ if (count >= 3)
+ return -1;
+ mdelay(1000); /* delay 1 second. */
+ count++;
+ }
+ }
+
+ /* CS8952 PHY needs the delay. Otherwise it won't send the 1st frame. */
+ mdelay(1000); /* delay 1 second. */
+
+ val = phy_rd(5); /* read ANLPAR Reg */
+ if (val & 0x0140) { /* if 100M_FDX or 10M_FDX? */
+ oldVal = RegRd16(REG_TestCTL);
+ /* Enable MAC's Full Duplex mode. */
+ RegWr16(REG_TestCTL, oldVal | TestCTL_MFDX);
+ /* printk("ep93xx_eth(): set MAC to Full Duplex mode\n"); */
+ } else {
+ /* printk("ep93xx_eth(): set MAC to Half Duplex mode\n"); */
+ }
+ /* TODO PJJ-added to get rid of _dbg_phy_dumpReg be sure returning zero is ok. */
+ gPhyAutoNegoDone = 1;
+ return 0;
+}
+
+/*****************************************************************************
+* phy_init()
+*****************************************************************************/
+static int phy_init(struct net_device *pD)
+{
+ u32 oldVal;
+ int status = -1;
+ u16 val;
+
+ _PRTK_ENTRY(("phy_init(pD:0x%x)\n", (unsigned int)pD));
+
+ oldVal = RegRd32(REG_SelfCTL);
+ RegWr32(REG_SelfCTL, 0x0e00); /*Set MDC clock to be divided by 8
+ and disable PreambleSuppress bit */
+
+ val = phy_rd(1); /* read BM status Reg; Link Status Bit remains cleared
+ until the Reg is read. */
+ val = phy_rd(1); /* read BMStaReg again to get the current link status */
+ if (val & 0x0004) { /* if Link Status == established? */
+ status = phy_autoNegotiation(pD);
+ }
+
+ RegWr32(REG_SelfCTL, oldVal); /*restore the old value */
+
+ return status;
+} /*phy_init() */
+
+/*****************************************************************************
+* phy_reset()
+*****************************************************************************/
+#if 0
+static int phy_reset(struct net_device *pD)
+{
+ int i;
+
+ _PRTK_ENTRY(("phy_reset(pD:0x%p)\n", pD));
+
+ phy_wr(0, 1 << 15); /*reset PHY */
+ for (i = 0; i < 1000; i++)
+ if (0 == ((1 << 15) & phy_rd(0)))
+ break;
+ if (0 != ((1 << 15) & phy_rd(0))) {
+ _PRTK_HWFAIL(("phy_reset(): PHY reset does not self-clear\n"));
+ return -1;
+ }
+ /*if */
+ phy_wr(19, 0x00); /*@ override default value from H/W pin that is not correct */
+ phy_wr(4, (1 << 8) | (1 << 7) | (1 << 6) | (1 << 5) | (0x01 << 0)); /*advertise 100/10M full/half */
+ phy_wr(0, (1 << 12) | (1 << 9)); /*enable auto negotiation */
+
+ return 0;
+} /*phy_reset() */
+#endif
+
+#ifndef _PRTK_DUMP
+# define _dbg_ep9312Eth_dumpQueues(pD)
+#else
+/*****************************************************************************
+* _dbg_ep9312Eth_dumpQueues()
+*****************************************************************************/
+static void _dbg_ep9312Eth_dumpQueues(struct net_device *pD)
+{
+
+ int i;
+
+ _PRTK_DUMP(("Dumping Descriptor/Status Queues\n"));
+ _PRTK_DUMP((" pD:0x%p, Base Address:0x%x\n", pD,
+ (unsigned int)pD->base_addr));
+
+ _PRTK_DUMP((" o Rx Status Queue: at 0x%p, %d entries\n",
+ pP->s.pQueRxSts, LEN_QueRxSts));
+ for (i = 0; i < LEN_QueRxSts; i++)
+ _PRTK_DUMP((" - %2d: 0x%08x 0x%08x \n",
+ i, (unsigned int)pP->s.pQueRxSts[i].w.e0,
+ (unsigned int)pP->s.pQueRxSts[i].w.e1));
+
+ _PRTK_DUMP((" o Rx Descriptor Queue: at 0x%p, %d entries\n",
+ pP->s.pQueRxDesc, LEN_QueRxDesc));
+ for (i = 0; i < LEN_QueRxDesc; i++)
+ _PRTK_DUMP((" - %2d: 0x%08x 0x%08x \n",
+ i, (unsigned int)pP->s.pQueRxDesc[i].w.e0,
+ (unsigned int)pP->s.pQueRxDesc[i].w.e1));
+
+ _PRTK_DUMP((" o Tx Status Queue: at 0x%p, %d entries\n",
+ pP->s.pQueTxSts, LEN_QueTxSts));
+ for (i = 0; i < LEN_QueTxSts; i++)
+ _PRTK_DUMP((" - %2d: 0x%08x \n", i,
+ (unsigned int)pP->s.pQueTxSts[i].w.e0));
+
+ _PRTK_DUMP((" o Tx Descriptor Queue: at 0x%p, %d entries\n",
+ pP->s.pQueTxDesc, LEN_QueTxDesc));
+ for (i = 0; i < LEN_QueTxDesc; i++)
+ _PRTK_DUMP((" - %2d: 0x%08x 0x%08x \n",
+ i, (unsigned int)pP->s.pQueTxDesc[i].w.e0,
+ (unsigned int)pP->s.pQueTxDesc[i].w.e1));
+}/*_dbg_ep9312Eth_dumpQueues()*/
+#endif /*ifndef _PRTK_DUMP else */
+
+/*****************************************************************************
+* devQue_start()
+*
+ make descriptor queues active
+ allocate queue entries if needed
+ and set device registers up to make it operational
+ assume device has been initialized
+*
+*****************************************************************************/
+static int devQue_start(struct net_device *pD)
+{
+ int err;
+ struct ep93xxEth_info *pP = netdev_priv(pD);
+ int i;
+ void *pBuf;
+ u32 phyA;
+
+ _PRTK_ENTRY(("devQue_start(pD:0x%p)\n", pD));
+
+ /*turn off device bus mastering */
+ RegWr32(REG_BMCtl, BMCtl_RxDis | BMCtl_TxDis | RegRd32(REG_BMCtl));
+ err = waitOnReg32(pD, REG_BMSts, BMSts_TxAct, ~BMSts_TxAct, 1);
+ err |= waitOnReg32(pD, REG_BMSts, BMSts_RxAct, ~BMSts_RxAct, 1);
+ if (err)
+ _PRTK_HWFAIL(("devQue_start(): BM does not stop\n"));
+
+ /*if */
+ /*Tx Status Queue */
+ memset(pP->s.pQueTxSts, 0, sizeof(pP->s.pQueTxSts[0]) * LEN_QueTxSts); /*clear status */
+ pP->d.idxQueTxSts = 0; /*init index */
+ RegWr32(REG_TxSBA, pP->s.phyQueTxSts); /*base addr */
+ RegWr32(REG_TxSCA, pP->s.phyQueTxSts); /*current addr */
+ RegWr16(REG_TxSBL, sizeof(pP->s.pQueTxSts[0]) * LEN_QueTxSts); /*base len */
+ RegWr16(REG_TxSCL, sizeof(pP->s.pQueTxSts[0]) * LEN_QueTxSts); /*current len */
+
+ /*Tx Descriptor Queue */
+ memset(pP->s.pQueTxDesc, 0, sizeof(pP->s.pQueTxDesc[0]) * LEN_QueTxDesc); /*clear descriptor */
+ pP->d.idxQueTxDescHead = pP->d.idxQueTxDescTail = 0; /*init index */
+ RegWr32(REG_TxDBA, pP->s.phyQueTxDesc); /*base addr */
+ RegWr32(REG_TxDCA, pP->s.phyQueTxDesc); /*current addr */
+ RegWr16(REG_TxDBL, sizeof(pP->s.pQueTxDesc[0]) * LEN_QueTxDesc); /*base len */
+ RegWr16(REG_TxDCL, sizeof(pP->s.pQueTxDesc[0]) * LEN_QueTxDesc); /*current len */
+
+ /*Rx Status Queue */
+ memset(pP->s.pQueRxSts, 0, sizeof(pP->s.pQueRxSts[0]) * LEN_QueRxSts); /*clear status */
+ pP->d.idxQueRxSts = 0; /*init index */
+ RegWr32(REG_RxSBA, pP->s.phyQueRxSts); /*base addr */
+ RegWr32(REG_RxSCA, pP->s.phyQueRxSts); /*current addr */
+ RegWr16(REG_RxSBL, sizeof(pP->s.pQueRxSts[0]) * LEN_QueRxSts); /*base len */
+ RegWr16(REG_RxSCL, sizeof(pP->s.pQueRxSts[0]) * LEN_QueRxSts); /*current len */
+
+ /*Rx Descriptor Queue */
+ memset(pP->s.pQueRxDesc, 0, sizeof(pP->s.pQueRxDesc[0]) * LEN_QueRxDesc); /*clear descriptor */
+ phyA = pP->s.phyRxBuf;
+ for (i = 0; i < LEN_QueRxDesc; i++) {
+ pP->s.pQueRxDesc[i].f.bi = i; /*Rx Buffer Index */
+ pP->s.pQueRxDesc[i].f.ba = phyA; /*physical address of Rx Buf */
+ pP->s.pQueRxDesc[i].f.bl = LEN_RxBuf; /*Rx Buffer Length */
+ phyA += (LEN_RxBuf + 3) & ~0x03;
+ } /*for */
+ pP->d.idxQueRxDesc = 0; /*init index */
+ RegWr32(REG_RxDBA, pP->s.phyQueRxDesc); /*base addr */
+ RegWr32(REG_RxDCA, pP->s.phyQueRxDesc); /*current addr */
+ RegWr16(REG_RxDBL, sizeof(pP->s.pQueRxDesc[0]) * LEN_QueRxDesc); /*base len */
+ RegWr16(REG_RxDCL, sizeof(pP->s.pQueRxDesc[0]) * LEN_QueRxDesc); /*current len */
+
+ /*init Rx Buffer Descriptors */
+ pBuf = pP->s.pRxBuf;
+ for (i = 0; i < LEN_QueRxDesc; i++) {
+ pP->s.pRxBufDesc[i].vaddr = pBuf; /*system address of buffer */
+ pP->s.pRxBufDesc[i].pFreeRtn = NULL; /*no freeing after use */
+ pBuf += (LEN_RxBuf + 3) & ~0x03;
+ } /*for */
+
+ /*init Tx Buffer Descriptors */
+ memset(pP->s.pTxBufDesc, 0x0,
+ sizeof(*pP->s.pTxBufDesc) * LEN_QueTxDesc);
+ pP->s.pTxBuf = &gTxDataBuff[0][0];
+ for (i = 0; i < LEN_QueTxDesc; i++) {
+ pP->s.pTxBufDesc[i].vaddr = &gTxDataBuff[i][0]; /*system address of buffer */
+ pP->s.pTxBufDesc[i].pFreeRtn = NULL; /*no freeing after use */
+ } /*for */
+
+ /*turn on device bus mastering */
+ RegWr32(REG_BMCtl, BMCtl_TxEn | BMCtl_RxEn | RegRd32(REG_BMCtl));
+ err =
+ waitOnReg32(pD, REG_BMSts, BMSts_TxAct | BMSts_TxAct,
+ BMSts_TxAct | BMSts_TxAct, 1);
+ if (err)
+ _PRTK_HWFAIL(("devQue_start(): BM does not start\n"));
+
+ /*if */
+ /*Enqueue whole entries; this must be done after BM activation */
+ RegWr32(REG_RxSEQ, LEN_QueRxSts); /*Rx Status Queue */
+ RegWr32(REG_RxDEQ, LEN_QueRxDesc); /*Rx Descriptor queue */
+
+ return 0;
+} /*devQue_start() */
+
+/*****************************************************************************
+* devQue_init()
+ init device descriptor queues at system level
+ device access is not recommended at this point
+*
+*****************************************************************************/
+static int devQue_init(struct net_device *pD)
+{
+ struct ep93xxEth_info *pP = netdev_priv(pD);
+ void *pBuf;
+ int size;
+
+ _PRTK_ENTRY(("devQue_init(pD:0x%x)\n", (unsigned int)pD));
+
+ /*verify device Tx/Rx Descriptor/Status Queue data size */
+ if (8 != sizeof(union receiveDescriptor)) {
+ _PRTK_SWERR(("devQue_init(): size of receiveDescriptor is not 8 bytes!!!\n"));
+ return -1;
+ } else if (8 != sizeof(union receiveStatus)) {
+ _PRTK_SWERR(("devQue_init(): size of receiveStatus is not 8 bytes!!!\n"));
+ return -1;
+ } else if (8 != sizeof(union transmitDescriptor)) {
+ _PRTK_SWERR(("devQue_init(): size of transmitDescriptor is not 8 bytes!!!\n"));
+ return -1;
+ } else if (4 != sizeof(union transmitStatus)) {
+ _PRTK_SWERR(("devQue_init(): size of transmitStatus is not 4 bytes!!!\n"));
+ return -1;
+ }
+
+ /*else */
+ /*
+ allocate kernel memory for whole queues
+ best if non-cached memory block due to DMA access by the device
+ if CPU doesn't have bus snooping
+ */
+ size = sizeof(union receiveDescriptor) * (LEN_QueRxDesc + 1) +
+ sizeof(union receiveStatus) * (LEN_QueRxSts + 1) +
+ sizeof(union transmitDescriptor) * (LEN_QueTxDesc + 1) +
+ sizeof(union transmitStatus) * (LEN_QueTxSts + 1) +
+ sizeof(unsigned long) * 4;
+
+ pBuf = MALLOC_DMA(size, &pP->s.phyQueueBase); /*request memory allocation */
+ if (!pBuf) {
+ _PRTK_SYSFAIL(("devQue_initAll(): fail to allocate memory for queues\n"));
+ return -1;
+ }
+
+ /*if */
+ /*
+ assign memory to each queue
+ */
+ pP->s.pQueRxDesc = (void *)Align32(pBuf);
+ pBuf =
+ (char *)pBuf + sizeof(union receiveDescriptor) * (LEN_QueRxDesc +
+ 1);
+ pP->s.pQueRxSts = (void *)Align32(pBuf);
+ pBuf = (char *)pBuf + sizeof(union receiveStatus) * (LEN_QueRxSts + 1);
+ pP->s.pQueTxDesc = (void *)Align32(pBuf);
+ pBuf =
+ (char *)pBuf + sizeof(union transmitDescriptor) * (LEN_QueTxDesc +
+ 1);
+ pP->s.pQueTxSts = (void *)Align32(pBuf);
+ pBuf = (char *)pBuf + sizeof(union transmitStatus) * (LEN_QueTxSts + 1);
+
+ /*
+ store physical address of each queue
+ */
+ pP->s.phyQueRxDesc = Align32(pP->s.phyQueueBase);
+ pP->s.phyQueRxSts =
+ pP->s.phyQueRxDesc + ((u32) pP->s.pQueRxSts -
+ (u32) pP->s.pQueRxDesc);
+ pP->s.phyQueTxDesc =
+ pP->s.phyQueRxDesc + ((u32) pP->s.pQueTxDesc -
+ (u32) pP->s.pQueRxDesc);
+ pP->s.phyQueTxSts =
+ pP->s.phyQueRxDesc + ((u32) pP->s.pQueTxSts -
+ (u32) pP->s.pQueRxDesc);
+
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -