// This function is called during system initialization to register a // network interface with the system. static void eth_drv_init(struct eth_drv_sc *sc, unsigned char *enaddr) { struct netif *netif = &sc->sc_arpcom.ac_if; netif->state = sc; ecosif_init(netif); // enaddr == 0 -> hardware init was incomplete (no ESA) if (enaddr != 0) { // Set up hardware address memcpy(netif->hwaddr, enaddr, ETHER_ADDR_LEN); // Perform any hardware initialization (sc->funs->start) (sc, (unsigned char *) &netif->hwaddr, 0); } #ifdef CYGSEM_HAL_VIRTUAL_VECTOR_DIAG // Set up interfaces so debug environment can share this device { void *dbg = CYGACC_CALL_IF_DBG_DATA(); if (!dbg) { CYGACC_CALL_IF_DBG_DATA_SET((void *)sc); } } #endif // // we call this after the driver was started successfully // lwip_dhcp_init(netif); }
// // Receive one packet of data from the hardware, if available // int eth_drv_read(char *eth_hdr, char *buf, int len) { struct eth_drv_sc *sc = __local_enet_sc; struct eth_msg *msg; int res; void *dbg = CYGACC_CALL_IF_DBG_DATA(); int old_state; void *eth_drv_old = 0; if (dbg) { sc = (struct eth_drv_sc *)dbg; // Use control from installed driver eth_drv_old = sc->funs->eth_drv_old; if (eth_drv_old == 0) { sc->funs->eth_drv_old = sc->funs->eth_drv; sc->funs->eth_drv = ð_drv_funs; // Substitute stand-alone driver old_state = sc->state; if (!old_state & ETH_DRV_STATE_ACTIVE) { // This interface not fully initialized, do it now (sc->funs->start)(sc, (unsigned char *)&__local_enet_addr, 0); sc->state |= ETH_DRV_STATE_ACTIVE; } } } (sc->funs->poll)(sc); // Give the driver a chance to fetch packets msg = eth_drv_msg_get(ð_msg_full); if (msg && len >= msg->len - 14) { memcpy(eth_hdr, msg->data, 14); memcpy(buf, &msg->data[14], msg->len-14); res = msg->len; } else { res = 0; } if (msg) { eth_drv_msg_put(ð_msg_free, msg); } if (dbg) { if (eth_drv_old == 0) { sc->funs->eth_drv = sc->funs->eth_drv_old; sc->funs->eth_drv_old = (struct eth_drv_funs *)0; } // if (!old_state & ETH_DRV_STATE_ACTIVE) { // // This interface was not fully initialized, shut it back down // (sc->funs->stop)(sc); // } } return res; }
void eth_drv_write(char *eth_hdr, char *buf, int len) { struct eth_drv_sg sg_list[MAX_ETH_DRV_SG]; struct eth_drv_sc *sc = __local_enet_sc; int sg_len = 2; void *dbg = CYGACC_CALL_IF_DBG_DATA(); int old_state; int wait_time = 5; // Timeout before giving up void *eth_drv_old = 0; if (dbg) { sc = (struct eth_drv_sc *)dbg; // Use control from installed driver eth_drv_old = sc->funs->eth_drv_old; if (eth_drv_old == 0) { sc->funs->eth_drv_old = sc->funs->eth_drv; sc->funs->eth_drv = ð_drv_funs; // Substitute stand-alone driver old_state = sc->state; if (!old_state & ETH_DRV_STATE_ACTIVE) { // This interface not fully initialized, do it now (sc->funs->start)(sc, (unsigned char *)&__local_enet_addr, 0); sc->state |= ETH_DRV_STATE_ACTIVE; } } } while (!(sc->funs->can_send)(sc)) { // Give driver a chance to service hardware (sc->funs->poll)(sc); CYGACC_CALL_IF_DELAY_US(2*100000); if (--wait_time <= 0) goto reset_and_out; // Give up on sending packet } sg_list[0].buf = (CYG_ADDRESS)eth_hdr; sg_list[0].len = 14; // FIXME sg_list[1].buf = (CYG_ADDRESS)buf; sg_list[1].len = len; packet_sent = 0; #ifdef CYGDBG_IO_ETH_DRIVERS_DEBUG if (cyg_io_eth_net_debug) { int old_console; old_console = start_console(); diag_printf("Ethernet send:\n"); DIAG_DUMP_BUF_HDR(eth_hdr, 14); DIAG_DUMP_BUF_BDY(buf, len); end_console(old_console); } #endif (sc->funs->send)(sc, sg_list, sg_len, len+14, (CYG_ADDRWORD)&packet_sent); wait_time = 50000; while (1) { (sc->funs->poll)(sc); if(packet_sent) break; CYGACC_CALL_IF_DELAY_US(2*10); if (--wait_time <= 0) goto reset_and_out; // Give up on sending packet } reset_and_out: if (dbg) { // if (!old_state & ETH_DRV_STATE_ACTIVE) { // // This interface was not fully initialized, shut it back down // (sc->funs->stop)(sc); // } if (eth_drv_old == 0) { sc->funs->eth_drv = sc->funs->eth_drv_old; sc->funs->eth_drv_old = (struct eth_drv_funs *)0; } } }