📄 rtl8019end.c
字号:
return (OK); }/********************************************************************************* rtl8019Ioctl - the driver I/O control routine** Process an ioctl request.*/LOCAL int rtl8019Ioctl ( void* pCookie, /* device ptr */ int cmd, caddr_t data ) { int error = 0; long value; RTL8019END_DEVICE* pDrvCtrl = (RTL8019END_DEVICE *) pCookie; switch ((UINT) cmd) { case EIOCSADDR: if (data == NULL) { DBG_PRINTF(("EIOCSADDR data is NULL!\n")); return (EINVAL); } bcopy ((char *)data, (char *)END_HADDR(&pDrvCtrl->endObj), END_HADDR_LEN(&pDrvCtrl->endObj)); break; case EIOCGADDR: if (data == NULL) { DBG_PRINTF(("EIOCGADDR data is NULL!\n")); return (EINVAL); } bcopy ((char *)END_HADDR(&pDrvCtrl->endObj), (char *)data, END_HADDR_LEN(&pDrvCtrl->endObj)); break; case EIOCSFLAGS: value = (long)data; if (value < 0) { value = -value; value--; END_FLAGS_CLR (&pDrvCtrl->endObj, value); } else END_FLAGS_SET (&pDrvCtrl->endObj, value); rtl8019Config (pDrvCtrl, TRUE); break; case EIOCGFLAGS: *(int *)data = END_FLAGS_GET(&pDrvCtrl->endObj); break; case EIOCPOLLSTART: error = rtl8019PollStart (pDrvCtrl); break; case EIOCPOLLSTOP: error = rtl8019PollStop (pDrvCtrl); break; case EIOCGMIB2: if (data == NULL) { DBG_PRINTF(("EIOCGMIB2 data is NULL!\n")); return (EINVAL); } bcopy((char *)&pDrvCtrl->endObj.mib2Tbl, (char *)data, sizeof(pDrvCtrl->endObj.mib2Tbl)); break; case EIOCGFBUF: if (data == NULL) { DBG_PRINTF(("EIOCGFBUF data is NULL!\n")); return (EINVAL); }#if 0 /* XXX */ *(int *)data = END_MIN_FBUF;#endif break; case EIOCMULTIADD: error = rtl8019MCastAdd((void*)pDrvCtrl, (char *)data); break; case EIOCMULTIDEL: error = rtl8019MCastDel((void*)pDrvCtrl, (char *)data); break; case EIOCMULTIGET: error = rtl8019MCastGet((void*)pDrvCtrl, (MULTI_TABLE *)data); break; default: DBG_PRINTF(("unknow command %x!\n", cmd)); error = EINVAL; } return (error); }/********************************************************************************* rtl8019Start - start the device** This function calls BSP functions to connect interrupts and start the* device running in interrupt mode.** RETURNS: OK or ERROR**/LOCAL STATUS rtl8019Start ( void* pCookie ) { STATUS result; RTL8019END_DEVICE* pDrvCtrl = (RTL8019END_DEVICE *) pCookie; SYS_INT_CONNECT (pDrvCtrl, rtl8019Int, (int)pDrvCtrl, &result); if (result == ERROR) { ERR_PRINTF (("rtl8019Start fail (SYS_INT_CONNECT error), IntLevel = %d",pDrvCtrl->ivec )); return (ERROR); } /* mark the interface as up (SPR #32034) */ END_FLAGS_SET (&pDrvCtrl->endObj, (IFF_UP | IFF_RUNNING)); /* Enable interrupts */ pDrvCtrl->imask = (pDrvCtrl->flags & END_POLLING) ? 0 : RTL8019_ALL_INTS; SYS_OUT_CHAR (pDrvCtrl, ENE_INTMASK, pDrvCtrl->imask); SYS_INT_ENABLE (pDrvCtrl); return (OK); }/******************************************************************************** rtl8019Config - reconfigure the interface under us.** Reconfigure the interface setting promiscuous mode, and changing the* multicast interface list.** NOMANUAL*/LOCAL void rtl8019Config ( RTL8019END_DEVICE *pDrvCtrl, BOOL intEnable /* TRUE to enable interrupts */ ) { UCHAR rxFilter; /* receiver configuration */ SYS_OUT_CHAR (pDrvCtrl, ENE_CMD, CMD_NODMA | CMD_PAGE0 | CMD_STOP); /* Disable device interrupts */ pDrvCtrl->imask = 0; SYS_OUT_CHAR (pDrvCtrl, ENE_INTMASK, pDrvCtrl->imask); /* Set up address filter for multicasting. */ if (END_MULTI_LST_CNT(&pDrvCtrl->endObj) > 0) rtl8019AddrFilterSet (pDrvCtrl); /* preserve END_POLLING and OVERWRITE flags */ pDrvCtrl->flags &= (END_POLLING | END_OVERWRITE | END_OVERWRITE2); /* 1. program Command Register for page 0 and for no DMA */ SYS_OUT_CHAR (pDrvCtrl, ENE_CMD, CMD_NODMA | CMD_PAGE0 | CMD_STOP); /* 2. initialize Data Configuration Register: * 16-bit bus, burst mode, 8-deep FIFO. * or * 8-bit bus, burst mode, 8-deep FIFO. */ if (pDrvCtrl->byteAccess) SYS_OUT_CHAR (pDrvCtrl, ENE_DCON, DCON_BSIZE1 | DCON_BUS_8 | DCON_LOOPBK_OFF); else SYS_OUT_CHAR (pDrvCtrl, ENE_DCON, DCON_BSIZE1 | DCON_BUS16 | DCON_LOOPBK_OFF); SYS_ENET_ADDR_GET (pDrvCtrl); /* 3. clear Remote Byte Count Register */ SYS_OUT_CHAR (pDrvCtrl, ENE_RBCR0, 0x00); SYS_OUT_CHAR (pDrvCtrl, ENE_RBCR1, 0x00); /* 4. initialize Receive Configuration Register */ /* Always accept broadcast packets. */ rxFilter = RCON_BROAD; /* Set multicast mode if it's asked for. */ if (END_MULTI_LST_CNT(&pDrvCtrl->endObj) > 0) { rxFilter |= RCON_GROUP; } DBG_PRINTF (("\tMulticast mode %s\n", (int)((rxFilter & RCON_GROUP) ? "on" : "off"))); /* Set promiscuous mode if it's asked for. */ if (END_FLAGS_GET(&pDrvCtrl->endObj) & IFF_PROMISC) { rxFilter |= RCON_PROM; } DBG_PRINTF (("\tPromiscuous mode %s\n", (int)((rxFilter & RCON_PROM) ? "on" : "off"))); DBG_PRINTF (("\tsetting rxFilter = 0x%x\n", rxFilter)); SYS_OUT_CHAR (pDrvCtrl, ENE_RCON, rxFilter); /* 5. place the ENE in LOOPBACK mode 0 */ SYS_OUT_CHAR (pDrvCtrl, ENE_TSTART, RTL8019_TSTART); /* +++ ?*/ SYS_OUT_CHAR (pDrvCtrl, ENE_TCON, TCON_LB0); /*后面重新设置了*/ /* 6. initialize Receive Buffer Ring */ SYS_OUT_CHAR (pDrvCtrl, ENE_RSTART, RTL8019_PSTART); SYS_OUT_CHAR (pDrvCtrl, ENE_RSTOP, RTL8019_PSTOP); SYS_OUT_CHAR (pDrvCtrl, ENE_BOUND, RTL8019_PSTART); /* 7. clear Interrupt Status Register */ SYS_OUT_CHAR (pDrvCtrl, ENE_INTSTAT, (char)0xff); SYS_OUT_CHAR (pDrvCtrl, ENE_INTMASK, 0); /* 8. initialize Interrupt Mask Register */ pDrvCtrl->imask = 0; SYS_OUT_CHAR (pDrvCtrl, ENE_INTMASK, pDrvCtrl->imask); /* 9. program Command Register for page 1 */ SYS_OUT_CHAR (pDrvCtrl, ENE_CMD, CMD_PAGE1 | CMD_STOP); /* i) initialize physical address registers */ SYS_OUT_CHAR (pDrvCtrl, ENE_STA0, pDrvCtrl->enetAddr[0]); SYS_OUT_CHAR (pDrvCtrl, ENE_STA1, pDrvCtrl->enetAddr[1]); SYS_OUT_CHAR (pDrvCtrl, ENE_STA2, pDrvCtrl->enetAddr[2]); SYS_OUT_CHAR (pDrvCtrl, ENE_STA3, pDrvCtrl->enetAddr[3]); SYS_OUT_CHAR (pDrvCtrl, ENE_STA4, pDrvCtrl->enetAddr[4]); SYS_OUT_CHAR (pDrvCtrl, ENE_STA5, pDrvCtrl->enetAddr[5]); DBG_PRINTF (("enet addr %02x:%02x:%02x:%02x:%02x:%02x\n", pDrvCtrl->enetAddr[0] & 0xff, pDrvCtrl->enetAddr[1] & 0xff, pDrvCtrl->enetAddr[2] & 0xff, pDrvCtrl->enetAddr[3] & 0xff, pDrvCtrl->enetAddr[4] & 0xff, pDrvCtrl->enetAddr[5] & 0xff)); /* ii) initialize multicast address registers */ rtl8019AddrFilterSet (pDrvCtrl); SYS_OUT_CHAR (pDrvCtrl, ENE_MAR0, pDrvCtrl->mcastFilter[0]); SYS_OUT_CHAR (pDrvCtrl, ENE_MAR1, pDrvCtrl->mcastFilter[1]); SYS_OUT_CHAR (pDrvCtrl, ENE_MAR2, pDrvCtrl->mcastFilter[2]); SYS_OUT_CHAR (pDrvCtrl, ENE_MAR3, pDrvCtrl->mcastFilter[3]); SYS_OUT_CHAR (pDrvCtrl, ENE_MAR4, pDrvCtrl->mcastFilter[4]); SYS_OUT_CHAR (pDrvCtrl, ENE_MAR5, pDrvCtrl->mcastFilter[5]); SYS_OUT_CHAR (pDrvCtrl, ENE_MAR6, pDrvCtrl->mcastFilter[6]); SYS_OUT_CHAR (pDrvCtrl, ENE_MAR7, pDrvCtrl->mcastFilter[7]); DBG_PRINTF (("Setting multicast addresses to: %02x:%02x:%02x:%02x:%02x:%02x\n", pDrvCtrl->mcastFilter[0] & 0xff, pDrvCtrl->mcastFilter[1] & 0xff, pDrvCtrl->mcastFilter[2] & 0xff, pDrvCtrl->mcastFilter[3] & 0xff, pDrvCtrl->mcastFilter[4] & 0xff, pDrvCtrl->mcastFilter[5] & 0xff, pDrvCtrl->mcastFilter[6] & 0xff, pDrvCtrl->mcastFilter[7] & 0xff)); /* iii) initialize current page pointer */ SYS_OUT_CHAR (pDrvCtrl, ENE_CURR, RTL8019_PSTART + 1); pDrvCtrl->nextPacket = RTL8019_PSTART + 1; /* set memory parameters */ SYS_OUT_CHAR (pDrvCtrl, ENE_CMD, CMD_NODMA | CMD_PAGE2 | CMD_STOP); /* * HELP: DP 83905 manual says thas ENE_ENH is address counter lower, * ENE_BLOCK is address counter upper. not wait states, or anything * else. What is with these comments? */ SYS_OUT_CHAR (pDrvCtrl, ENE_ENH, 0x00); /* 0 wait states */ SYS_OUT_CHAR (pDrvCtrl, ENE_BLOCK, 0x00); /* 0x00xxxx */ /* 10. put the ENE in START mode */ SYS_OUT_CHAR (pDrvCtrl, ENE_CMD, CMD_NODMA | CMD_PAGE0 | CMD_START); /* 11. initialize Transmit Configuration Register */ SYS_OUT_CHAR (pDrvCtrl, ENE_TCON, TCON_NORMAL); pDrvCtrl->imask = ((pDrvCtrl->flags & END_POLLING) ? 0 : RTL8019_ALL_INTS); /* Only actually enable interrupts if not polling */ if (intEnable) { SYS_OUT_CHAR (pDrvCtrl, ENE_INTMASK, pDrvCtrl->imask); SYS_OUT_CHAR (pDrvCtrl, ENE_INTSTAT, (char)0xff); /* clear all interrupts */ #ifdef ARCH_S3C2410 *((volatile unsigned int*)0x560000A4) &= ~0x10; #endif }}/********************************************************************************* rtl8019OverwriteRecover - recover from receive buffer ring overflow** This procedure is mandated by National Semiconductor as the only safe* way to recover from an Overwrite Warning Error. The first two steps* of their procedure, reading the Command Register and stopping the NIC,* were accomplished in the interrupt handler. The rest occurs here.** This routine is scheduled to run in the net task since it must delay* to allow the STOP command to take effect.*/LOCAL void rtl8019OverwriteRecover ( RTL8019END_DEVICE *pDrvCtrl, UCHAR cmdStatus ) { UCHAR stat; BOOL reSend; /* We shouldn't get here without the OVERWRITE flags set */ if (!(pDrvCtrl->flags & END_OVERWRITE2)) { DBG_PRINTF (("rtl8019OverwriteRecover: bad flags\n"));#ifdef DEBUG SYS_OUT_CHAR (pDrvCtrl, ENE_INTMASK, 0); taskSuspend (0);#else return;#endif } /* 1. read the TXP bit in the command register (already in cmdStatus) */ /* 2. issue the STOP command (done in the interrupt handler) */ /* 3. delay at least 1.6 milliseconds (1/625 second) */ taskDelay ((sysClkRateGet() + 624)/ 625); /* we are now supposedly sure the NIC is stopped */ /* 4. clear Remote Byte Count Register */ SYS_OUT_CHAR (pDrvCtrl, ENE_RBCR0, 0x00); SYS_OUT_CHAR (pDrvCtrl, ENE_RBCR1, 0x00); /* 5. read the stored value of the TXP bit (in cmdStatus) */ if ((cmdStatus & CMD_TXP) == 0) reSend = FALSE; else { SYS_IN_CHAR (pDrvCtrl, ENE_INTSTAT, &stat); if ((stat & (ISTAT_PTX | ISTAT_TXE)) == 0) { /* transmit was in progress but probably deferring */ reSend = TRUE; } else { /* transmit was completed (probably), don't repeat it */ reSend = FALSE; } } /* 6. place the NIC in loopback mode */ SYS_OUT_CHAR (pDrvCtrl, ENE_TCON, TCON_LB1); /* 7. issue the START command to the NIC */ SYS_OUT_CHAR (pDrvCtrl, ENE_CMD, CMD_NODMA | CMD_PAGE0 | CMD_START); /* 8. remove one or more packets from the receive buffer ring */ /* clear overwrite flag */ pDrvCtrl->flags &= ~END_OVERWRITE; pDrvCtrl->current = rtl8019GetCurr (pDrvCtrl); rtl8019HandleRcvInt (pDrvCtrl); /* 9. reset the overwrite warning bit in the ISR */ /* reset all active interrupt conditions */ SYS_IN_CHAR (pDrvCtrl, ENE_INTSTAT, &stat); SYS_OUT_CHAR (pDrvCtrl, ENE_INTSTAT, stat); /* 10. take the NIC out of loopback */ SYS_OUT_CHAR (pDrvCtrl, ENE_TCON, 0x00); /* 10a. re-enable all device interrupts */ pDrvCtrl->imask = RTL8019_ALL_INTS; SYS_OUT_CHAR (pDrvCtrl, ENE_INTMASK, pDrvCtrl->imask); /* 11. if need to resend, do so, otherwise if anything queued, send that */ pDrvCtrl->flags &= ~END_OVERWRITE2; if (reSend) SYS_OUT_CHAR (pDrvCtrl, ENE_CMD, CMD_TXP); else muxTxRestart (&pDrvCtrl->endObj); DBG_PRINTF (("rtl8019OverwriteRecover: done (flags=%x, imask=%x)\n", pDrvCtrl->flags,pDrvCtrl->imask));}/********************************************************************************* rtl8019Int - handle controller interrupt** This routine is called at interrupt level in response to an interrupt from* the controller.** RETURNS: N/A.*/LOCAL void rtl8019Int ( RTL8019END_DEVICE *pDrvCtrl
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -