📄 if_ep93xx.c
字号:
} while ((stat & MAC_BMStat_TxAct) == 0) ; HAL_WRITE_UINT32(MAC_TxCtl, MAC_TxCtl_TxON);}// ------------------------------------------------------------------------static bool ep93xx_init(struct cyg_netdevtab_entry *tab){ struct eth_drv_sc *sc = (struct eth_drv_sc *)tab->device_instance; struct ep93xx_priv_data *cpd = (struct ep93xx_priv_data *)sc->driver_private; cyg_uint32 stat; int i; cyg_uint32 uncached;#ifdef ETHDEBUG dprintf("ep93xx_init\n");#endif // ETHDEBUG // Set up uncached addresses for our data structures HAL_VIRT_TO_UNCACHED_ADDRESS( &cpd->_rxhdrs[0], uncached ); cpd->rxhdrs = (RxHdr *)uncached; HAL_VIRT_TO_UNCACHED_ADDRESS( &cpd->_rxstat[0], uncached ); cpd->rxstat = (RxStat *)uncached; HAL_VIRT_TO_UNCACHED_ADDRESS( &cpd->_txhdrs[0], uncached ); cpd->txhdrs = (TxHdr *)uncached; HAL_VIRT_TO_UNCACHED_ADDRESS( &cpd->_txstat[0], uncached ); cpd->txstat = (TxStat *)uncached;#ifdef CYGPKG_NET // Initialize environment, setup interrupt handler cyg_drv_interrupt_create(ETHERNET_INTERRUPT, 99, // Priority - what goes here? (cyg_addrword_t)sc, // Data item passed to interrupt handler (cyg_ISR_t *)ep93xx_isr, (cyg_DSR_t *)eth_drv_dsr, // The logical driver DSR &cpd->interrupt_handle, &cpd->interrupt); cyg_drv_interrupt_attach(cpd->interrupt_handle); cyg_drv_interrupt_acknowledge(ETHERNET_INTERRUPT); cyg_drv_interrupt_unmask(ETHERNET_INTERRUPT);#endif // CYGPKG_NET // Configure and enable PHY (wire) interfaces doPHY(); // Reset the device HAL_WRITE_UINT32(MAC_SelfCtl, MAC_SelfCtl_Reset); do { HAL_READ_UINT32(MAC_SelfCtl, stat); } while (stat & MAC_SelfCtl_Reset); //Set MDC clock to be divided by 8, and enable PreambleSurpress // for Tx and Rx frames. HAL_WRITE_UINT32(MAC_SelfCtl, 0x0f00); // Set the hardware address if ( ! cpd->hardwired_esa ) {#if defined(CYGPKG_REDBOOT) && \ defined(CYGSEM_REDBOOT_FLASH_CONFIG) if(flash_get_config("ep93xx_esa", &cpd->enaddr[0], CONFIG_ESA) == false) { diag_printf("\nFailed to get ep93xx_esa\n"); } #else#error FIXME#endif } HAL_WRITE_UINT32(MAC_AFP, 0); // Individual address slot #0 for (i = 0; i < ETHER_ADDR_LEN; i++) { HAL_WRITE_UINT8(MAC_IAD+i, cpd->enaddr[i]); } // Reset Rx ep93xx_RxReset(cpd); cpd->rxmode = MAC_RxCtl_Broadcast | MAC_RxCtl_IA0 | MAC_RxCtl_SRxON | MAC_RxCtl_RCRCA; // ***FIXME: PROMISCUOUS MODE: add MAC_RxCtl_Prom // And move a load of this into start(). HAL_WRITE_UINT32(MAC_RxCtl, cpd->rxmode); // Reset Tx ep93xx_TxReset(cpd); cpd->txbusy = 0; cpd->txnext = 0; HAL_WRITE_UINT32(MAC_IntStat, 0xFFFFFFFF); // Clear any pending interrupts // Set up interrupts HAL_WRITE_UINT32(MAC_IntEnab, MAC_IntEnab_Rx | MAC_IntEnab_Tx ); HAL_WRITE_UINT32(MAC_IntStat, 0xFFFFFFFF); // Clear again// ***FIXME: this register is NOT DOCUMENTED AT ALL ***// HAL_WRITE_UINT32(MAC_IntCtl, MAC_IntCtl_Enable); // Initialize upper level driver (sc->funs->eth_drv->init)(sc, &cpd->enaddr[0]);#ifdef ETHDEBUG dprintf("ep93xx_init exit\n");#endif // ETHDEBUG return true;}//// This function is used to shutdown an interface.//static voidep93xx_stop(struct eth_drv_sc *sc){#ifdef ETHDEBUG dprintf("ep93xx_stop()\n");#endif // ETHDEBUG}//// This function is called to "start up" the interface. It may be called// multiple times, even when the hardware is already running. It will be// called whenever something "hardware oriented" changes and should leave// the hardware ready to send/receive packets.//static voidep93xx_start(struct eth_drv_sc *sc, unsigned char *enaddr, int flags){#ifdef ETHDEBUG dprintf("ep93xx_start()\n");#endif // ETHDEBUG}//// This routine is called to perform special "control" opertions//static intep93xx_control(struct eth_drv_sc *sc, unsigned long key, void *data, int data_length){#ifdef ETHDEBUG dprintf("ep93xx_control()\n");#endif // ETHDEBUG switch (key) { case ETH_DRV_SET_MAC_ADDRESS: return 0; break; default: return 1; break; }}//// This routine is called to see if it is possible to send another packet.// It will return non-zero if a transmit is possible, zero otherwise.//static intep93xx_can_send(struct eth_drv_sc *sc){ struct ep93xx_priv_data *cpd = (struct ep93xx_priv_data *)sc->driver_private;#ifdef ETHDEBUG dprintf("ep93xx_can_send()\n");#endif // ETHDEBUG#ifdef NOTYET unsigned short stat; stat = get_reg(PP_LineStat); if ((stat & PP_LineStat_LinkOK) == 0) { return false; // Link not connected }#endif // NOTYET return (cpd->txbusy < CYGNUM_DEVS_ETH_ARM_EP93XX_TxNUM);}//// This routine is called to send data to the hardware.static void ep93xx_send(struct eth_drv_sc *sc, struct eth_drv_sg *sg_list, int sg_len, int total_len, unsigned long key){ struct ep93xx_priv_data *cpd = (struct ep93xx_priv_data *)sc->driver_private; TxHdr * volatile hdr; int i; int len; unsigned char * volatile data, * volatile bp; cyg_uint32 phys;#ifdef ETHDEBUG dprintf("ep93xx_send()\n");#endif // ETHDEBUG if(cpd == 0) {#ifdef ETHDEBUG dprintf("ep93xx_send cpd is NULL!");#endif // ETHDEBUG while (1); } if (cpd->txbusy >= CYGNUM_DEVS_ETH_ARM_EP93XX_TxNUM) { diag_printf("ep93xx_send you are hosed!"); while (1); return; } if(cpd->txkey[cpd->txnext] != 0) { diag_printf("ep93xx_send outta places you are hosed!"); while (1); } // Mark xmitter busy cpd->txkey[cpd->txnext] = key; cpd->txbusy++; // Fill in the header hdr = &cpd->txhdrs[cpd->txnext]; HAL_VIRT_TO_PHYS_ADDRESS((cyg_uint32)&cpd->_txbufs[cpd->txnext][0], phys); hdr->bufaddr = (void *)phys; hdr->eof = 1; // Complete frame hdr->bi = cpd->txnext; hdr->len = total_len; if (++cpd->txnext >= CYGNUM_DEVS_ETH_ARM_EP93XX_TxNUM) { cpd->txnext = 0; } // Put data into buffer // TODO is this correct??? this was not here before I added it PJJ// HAL_VIRT_TO_UNCACHED_ADDRESS( hdr->bufaddr, bp ); bp = hdr->bufaddr; for (i = 0; i < sg_len; i++) { data = (unsigned char *)sg_list[i].buf; len = sg_list[i].len; if(bp == 0) { diag_printf("ep93xx_send() bp was 0\n"); while (1); } if(data == 0) { diag_printf("ep93xx_send() data was 0\n"); while (1); } memcpy(bp, data, len); bp += len; if(bp > ((unsigned char *)hdr->bufaddr + CYGNUM_DEVS_ETH_ARM_EP93XX_BUFSIZE)) { diag_printf("ep93xx_send() out of bounds\n"); while (1); } } // Tell the device it's ready HAL_WRITE_UINT32(MAC_TxDEQ, 1); // Increments number of "valid" descriptors#ifdef ETHDEBUG dprintf("ep93xx_send() exit\n");#endif // ETHDEBUG}//// This function is called when a packet has been sentstatic voidep93xx_TxEvent(struct eth_drv_sc *sc, unsigned long stat){ struct ep93xx_priv_data *cpd = (struct ep93xx_priv_data *)sc->driver_private; int i, bi; TxStat *sp;#ifdef ETHDEBUG dprintf("ep93xx_TxEvent()\n");#endif // ETHDEBUG if(cpd == 0) {#ifdef ETHDEBUG dprintf("ep93xx_TxEvent cpd is NULL!");#endif // ETHDEBUG } sp = cpd->txstat; for (i = 0; i < CYGNUM_DEVS_ETH_ARM_EP93XX_TxNUM; i++, sp++) { if (sp->fp) { // This status is valid bi = sp->bi; cpd->txbusy--; sp->fp = 0; (sc->funs->eth_drv->tx_done)(sc, cpd->txkey[bi], 0); cpd->txkey[bi] = 0; } }#ifdef ETHDEBUG dprintf("ep93xx_TxEventExit()\n");#endif // ETHDEBUG}// ------------------------------------------------------------------------// This functio n is called when a packet has been received. Its job is// to prepare to unload the packet from the hardware. Once the length of// the packet is known, the upper layer of the driver can be told. When// the upper layer is ready to unload the packet, the internal function// 'ep93xx_recv' will be called to actually fetch it from the hardware.//static voidep93xx_RxEvent(struct eth_drv_sc *sc){ struct ep93xx_priv_data *cpd = (struct ep93xx_priv_data *)sc->driver_private; static int events=0;#ifdef ETHDEBUG dprintf("ep93xx_RxEvent()\n");#endif // ETHDEBUG if(cpd == 0) {#ifdef ETHDEBUG dprintf("ep93xx_RxEvent cpd is NULL!\n");#endif // ETHDEBUG while (1); } if(sc == 0) {#ifdef ETHDEBUG dprintf("ep93xx_RxEvent sc is NULL!\n");#endif // ETHDEBUG while (1); } while (cpd->rxsp->fp) {#ifdef ETHDEBUG dprintf("recv fp = %08x sc=%08x events %08x len=%08x.\n",cpd->rxsp->fp,sc, events, cpd->rxsp->len);#endif // ETHDEBUG if((events++ < 40) || (cpd->rxsp->len != 0x3a)) { (sc->funs->eth_drv->recv)(sc, cpd->rxsp->len); } cpd->rxsp->fp = 0; cpd->rxsp->rfp = 0; cpd->rxsp->len = 0; cpd->rxsp++; if (cpd->rxsp >= &cpd->rxstat[CYGNUM_DEVS_ETH_ARM_EP93XX_RxNUM]) { cpd->rxsp = cpd->rxstat; } // Tell device we took the data HAL_WRITE_UINT32(MAC_RxDEQ, 1); HAL_WRITE_UINT32(MAC_RxSEQ, 1); }#ifdef ETHDEBUG dprintf("ep93xx_RxEvent() Exit\n");#endif // ETHDEBUG}//// This function is called as a result of the "eth_drv_recv()" call above.// It's job is to actually fetch data for a packet from the hardware once// memory buffers have been allocated for the packet. Note that the buffers// may come in pieces, using a scatter-gather list. This allows for more// efficient processing in the upper layers of the stack.//static voidep93xx_recv(struct eth_drv_sc *sc, struct eth_drv_sg *sg_list, int sg_len){ struct ep93xx_priv_data *cpd = (struct ep93xx_priv_data *)sc->driver_private; int i, mlen; cyg_uint8 *data, *bp; int tot_len = 0; cyg_uint32 pp, uu;#ifdef ETHDEBUG dprintf("ep93xx_recv()\n");#endif // ETHDEBUG if(cpd == 0) { diag_printf("ep93xx_recv cpd is NULL!"); while(1); } if (cpd->rxsp->bi >= CYGNUM_DEVS_ETH_ARM_EP93XX_RxNUM) { dprintf("ep93xx_recv bi is > %03x!",CYGNUM_DEVS_ETH_ARM_EP93XX_RxNUM); while(1); } HAL_PHYS_TO_VIRT_ADDRESS(cpd->rxhdrs[cpd->rxsp->bi].bufaddr, pp); HAL_VIRT_TO_UNCACHED_ADDRESS(pp, uu); bp = (cyg_uint8 *)uu; // uncached access to the data for (i = 0; i < sg_len; i++) { data = (cyg_uint8 *)sg_list[i].buf; mlen = sg_list[i].len; if(data == 0) { dprintf("ep93xx_recv() data was NULL i=%08x len=%08x sg_list=%08x\n",i,mlen,sg_list); continue; } if(bp == 0) { dprintf("ep93xx_recv() bp was NULL\n"); }// diag_printf("ep93xx_recv() data=%08x bp=%08x len=%08x\n",data, bp, mlen); memcpy(data, bp, mlen); bp += mlen; tot_len += mlen; }#ifdef ETHDEBUG dprintf("ep93xx_recv()\n");#endif // ETHDEBUG}// ------------------------------------------------------------------------//// ------------------------------------------------------------------------static voidep93xx_poll(struct eth_drv_sc *sc){ unsigned long status; //, orig_status;// unsigned short seq; HAL_READ_UINT32(MAC_IntStat, status);// orig_status = status;//#if 1// // The chip does not seem to present the RxSQ interrupt// HAL_READ_UINT16(MAC_RxSEQ_Count, seq);// if (seq != CYGNUM_DEVS_ETH_ARM_EP93XX_RxNUM)// // status |= (MAC_IntStat_RxSQ);// }//#endif if (MAC_IntStat_Tx & status) { ep93xx_TxEvent(sc, status); } if (MAC_IntStat_Rx & status) { ep93xx_RxEvent(sc); } // // Clear the interrupts // HAL_WRITE_UINT32(MAC_IntStat, status);} // ------------------------------------------------------------------------// EOF if_ep93xx.c
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -