static void net_io_flush(void) { int n; char *bp = out_buf; #ifdef DEBUG_TCP if (show_tcp) { int old_console; old_console = start_console(); diag_printf("%s.%d\n", __FUNCTION__, __LINE__); diag_dump_buf(out_buf, out_buflen); end_console(old_console); } #endif // SHOW_TCP n = __tcp_write_block(&tcp_sock, bp, out_buflen); if (n < 0) { // The connection is gone! net_io_revert_console(); } else { out_buflen -= n; bp += n; } out_bufp = out_buf; out_buflen = 0; // Check interrupt flag if (CYGACC_CALL_IF_CONSOLE_INTERRUPT_FLAG()) { CYGACC_CALL_IF_CONSOLE_INTERRUPT_FLAG_SET(0); cyg_hal_user_break(0); } }
// // This function is called from the hardware driver when an output operation // has completed - i.e. the packet has been sent. // static void eth_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(); }
static void net_io_read(void* __ch_data, cyg_uint8* __buf, cyg_uint32 __len) { int old_console; old_console = start_console(); diag_printf("%s.%d\n", __FUNCTION__, __LINE__); end_console(old_console); #if 0 CYGARC_HAL_SAVE_GP(); while(__len-- > 0) *__buf++ = net_io_getc(__ch_data); CYGARC_HAL_RESTORE_GP(); #endif }
static cyg_bool _net_io_getc_nonblock(void* __ch_data, cyg_uint8* ch) { if (in_buflen == 0) { __tcp_poll(); if (tcp_sock.state == _CLOSE_WAIT) { // This connection is breaking if (tcp_sock.data_bytes == 0 && tcp_sock.rxcnt == 0) { __tcp_close(&tcp_sock); return false; } } if (tcp_sock.state == _CLOSED) { // The connection is gone net_io_revert_console(); *ch = '\n'; return true; } in_buflen = __tcp_read(&tcp_sock, in_buf, sizeof(in_buf)); in_bufp = in_buf; #ifdef DEBUG_TCP if (show_tcp && (in_buflen > 0)) { int old_console; old_console = start_console(); diag_printf("%s:%d\n", __FUNCTION__, __LINE__); diag_dump_buf(in_buf, in_buflen); end_console(old_console); } #endif // DEBUG_TCP } if (in_buflen) { *ch = *in_bufp++; in_buflen--; return true; } else { return false; } }
// // 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 void eth_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(); }
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; } } }