📄 eth_drv.c
字号:
// This interface not fully initialized, do it now (sc->funs->start)(sc, (unsigned char *)sc->sc_arpcom.esa, 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 = (6+6+2); // 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; } }}//// This function is called from the hardware driver when an output operation// has completed - i.e. the packet has been sent.//static voideth_drv_tx_done(struct eth_drv_sc *sc, CYG_ADDRWORD key, int status){ CYGARC_HAL_SAVE_GP(); if ((int *)key == &packet_sent) { *(int *)key = 1; } else { // It's possible that this acknowledgement is for a different // [logical] driver. Try and pass it on.#if defined(CYGDBG_IO_ETH_DRIVERS_DEBUG) && \ (CYGDBG_IO_ETH_DRIVERS_DEBUG_VERBOSITY >=2 ) // Note: not normally enabled - too verbose if (cyg_io_eth_net_debug > 1) { int old_console; old_console = start_console(); diag_printf("tx_done for other key: %x\n", key); end_console(old_console); }#endif LOCK_APPLICATION_SCHEDULER(); if (sc->funs->eth_drv_old) { (sc->funs->eth_drv_old->tx_done)(sc, key, status); } else { (sc->funs->eth_drv->tx_done)(sc, key, status); } UNLOCK_APPLICATION_SCHEDULER(); } CYGARC_HAL_RESTORE_GP();}//// Receive one packet of data from the hardware, if available//inteth_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 *)sc->sc_arpcom.esa, 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;}#ifdef CYGSEM_IO_ETH_DRIVERS_PASS_PACKETS//// This function is called to copy a message up to the next level.// It is only used when this driver has usurped the processing of// network functions.//static unsigned char *eth_drv_copy_recv_buf;static void eth_drv_copy_recv(struct eth_drv_sc *sc, struct eth_drv_sg *sg_list, int sg_len){ int i; unsigned char *ppp; CYGARC_HAL_SAVE_GP(); ppp = eth_drv_copy_recv_buf; // Be safe against being called again by accident for (i = 0; i < sg_len; i++) { if ( sg_list[i].buf ) // Be safe against discarding calls memcpy((unsigned char *)sg_list[i].buf, ppp, sg_list[i].len); ppp += sg_list[i].len; } CYGARC_HAL_RESTORE_GP();}#endif//// This function is called from a hardware driver to indicate that an input// packet has arrived. The routine will set up appropriate network resources// to hold the data and call back into the driver to retrieve the data.//static voideth_drv_recv(struct eth_drv_sc *sc, int total_len){ struct eth_drv_sg sg_list[MAX_ETH_DRV_SG]; int sg_len = 0; struct eth_msg *msg; unsigned char *buf; CYGARC_HAL_SAVE_GP(); if ((total_len > MAX_ETH_MSG) || (total_len < 0)) { #ifdef CYGSEM_IO_ETH_DRIVERS_WARN int old_console; old_console = start_console(); diag_printf("%s: packet of %d bytes truncated\n", __FUNCTION__, total_len); end_console(old_console);#endif total_len = MAX_ETH_MSG; } msg = eth_drv_msg_get(ð_msg_free); if (msg) { buf = msg->data; } else {#ifdef CYGSEM_IO_ETH_DRIVERS_WARN int old_console; old_console = start_console(); diag_printf("%s: packet of %d bytes dropped\n", __FUNCTION__, total_len); end_console(old_console);#endif buf = (unsigned char *)0; // Drivers know this means "the bit bucket" } sg_list[0].buf = (CYG_ADDRESS)buf; sg_list[0].len = total_len; sg_len = 1; (sc->funs->recv)(sc, sg_list, sg_len);#ifdef CYGDBG_IO_ETH_DRIVERS_DEBUG if (cyg_io_eth_net_debug) { int old_console; old_console = start_console(); diag_printf("Ethernet recv:\n"); if ( buf ) { DIAG_DUMP_BUF_HDR(buf, 14); DIAG_DUMP_BUF_BDY(buf+14, total_len-14); } else diag_printf(" ...NULL buffer.\n"); end_console(old_console); }#endif#ifdef CYGSEM_IO_ETH_DRIVERS_PASS_PACKETS if ((unsigned char *)0 != buf && // Only pass on a packet we actually got! sc->funs->eth_drv_old != (struct eth_drv_funs *)0) { void (*hold_recv)(struct eth_drv_sc *sc, struct eth_drv_sg *sg_list, int sg_len); // See if this packet was for us. If not, pass it upwards // This is a major layering violation!! if (memcmp(&__local_ip_addr, &buf[14+16], 4)) { hold_recv = sc->funs->recv; sc->funs->recv = eth_drv_copy_recv; eth_drv_copy_recv_buf = buf; // This calls into the 'other' driver, giving it a chance to // do something with this data (since it wasn't for us) LOCK_APPLICATION_SCHEDULER(); (sc->funs->eth_drv_old->recv)(sc, total_len); UNLOCK_APPLICATION_SCHEDULER(); sc->funs->recv = hold_recv; } }#endif if (msg) { msg->len = total_len; eth_drv_msg_put(ð_msg_full, msg);#ifdef CYGSEM_IO_ETH_DRIVERS_WARN // there was an else with a dump_buf() here but it's // meaningless; sg_list[0].buf is NULL!#endif } CYGARC_HAL_RESTORE_GP();}//// Determine the interrupt vector used by an interface//inteth_drv_int_vector(void){ struct eth_drv_sc *sc = __local_enet_sc; return sc->funs->int_vector(sc);}void eth_drv_dsr(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data){ diag_printf("eth_drv_dsr should not be called: vector %d, data %x\n", vector, data );}// EOF src/stand_alone/eth_drv.c
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -