int ethernet_service(struct sim *s) { /* fpga --> tap */ ETH_SOURCE_ACK = 1; if(ETH_SOURCE_STB == 1) { s->eth_txbuffer[s->eth_txbuffer_len] = ETH_SOURCE_DATA; s->eth_txbuffer_len++; } else { if(s->eth_last_source_stb) { eth_write(s, s->eth_txbuffer, s->eth_txbuffer_len); s->eth_txbuffer_len = 0; } } s->eth_last_source_stb = ETH_SOURCE_STB; /* tap --> fpga */ if(s->eth_rxbuffer_len == 0) { ETH_SINK_STB = 0; s->eth_rxbuffer_pos = 0; s->eth_rxbuffer_len = eth_read(s, s->eth_rxbuffer); } else { if(s->eth_rxbuffer_pos < MAX(s->eth_rxbuffer_len, 60)) { ETH_SINK_STB = 1; ETH_SINK_DATA = s->eth_rxbuffer[s->eth_rxbuffer_pos]; s->eth_rxbuffer_pos++; } else { ETH_SINK_STB = 0; s->eth_rxbuffer_len = 0; memset(s->eth_rxbuffer, 0, 1532); } } }
static void eth_rx(struct device *port) { struct eth_runtime *context = port->driver_data; struct eth_config *config = port->config->config_info; uint32_t base_addr = config->base_addr; struct net_buf *buf; uint32_t frm_len = 0; /* Check whether the RX descriptor is still owned by the device. If not, * process the received frame or an error that may have occurred. */ if (context->rx_desc.own == 1) { ETH_ERR("Spurious receive interrupt from Ethernet MAC.\n"); return; } if (!net_driver_ethernet_is_opened()) { goto release_desc; } if (context->rx_desc.err_summary) { ETH_ERR("Error receiving frame: RDES0 = %08x, RDES1 = %08x.\n", context->rx_desc.rdes0, context->rx_desc.rdes1); goto release_desc; } frm_len = context->rx_desc.frm_len; if (frm_len > UIP_BUFSIZE) { ETH_ERR("Frame too large: %u.\n", frm_len); goto release_desc; } buf = ip_buf_get_reserve_rx(0); if (buf == NULL) { ETH_ERR("Failed to obtain RX buffer.\n"); goto release_desc; } memcpy(net_buf_add(buf, frm_len), (void *)context->rx_buf, frm_len); uip_len(buf) = frm_len; net_driver_ethernet_recv(buf); release_desc: /* Return ownership of the RX descriptor to the device. */ context->rx_desc.own = 1; /* Request that the device check for an available RX descriptor, since * ownership of the descriptor was just transferred to the device. */ eth_write(base_addr, REG_ADDR_RX_POLL_DEMAND, 1); }
/* @brief Transmit the current Ethernet frame. * * This procedure will block indefinitely until the Ethernet device is * ready to accept a new outgoing frame. It then copies the current * Ethernet frame from the global uip_buf buffer to the device DMA * buffer and signals to the device that a new frame is available to be * transmitted. */ static int eth_tx(struct device *port, struct net_buf *buf) { struct eth_runtime *context = port->driver_data; struct eth_config *config = port->config->config_info; uint32_t base_addr = config->base_addr; /* Wait until the TX descriptor is no longer owned by the device. */ while (context->tx_desc.own == 1) { } #ifdef CONFIG_ETHERNET_DEBUG /* Check whether an error occurred transmitting the previous frame. */ if (context->tx_desc.err_summary) { ETH_ERR("Error transmitting frame: TDES0 = %08x, TDES1 = %08x.\n", context->tx_desc.tdes0, context->tx_desc.tdes1); } #endif /* Transmit the next frame. */ if (uip_len(buf) > UIP_BUFSIZE) { ETH_ERR("Frame too large to TX: %u\n", uip_len(buf)); return -1; } memcpy((void *)context->tx_buf, uip_buf(buf), uip_len(buf)); context->tx_desc.tx_buf1_sz = uip_len(buf); context->tx_desc.own = 1; /* Request that the device check for an available TX descriptor, since * ownership of the descriptor was just transferred to the device. */ eth_write(base_addr, REG_ADDR_TX_POLL_DEMAND, 1); return 1; }
static void eth_dw_isr(struct device *port) { struct eth_runtime *context = port->driver_data; uint32_t base_addr = context->base_addr; uint32_t int_status; int_status = eth_read(base_addr, REG_ADDR_STATUS); #ifdef CONFIG_SHARED_IRQ /* If using with shared IRQ, this function will be called * by the shared IRQ driver. So check here if the interrupt * is coming from the GPIO controller (or somewhere else). */ if ((int_status & STATUS_RX_INT) == 0) { return; } #endif eth_rx(port); /* Acknowledge the interrupt. */ eth_write(base_addr, REG_ADDR_STATUS, STATUS_NORMAL_INT | STATUS_RX_INT); }
int write_command(int num, int adr, char* block){ if(DEBUG>10){ if(block==0) std::cout<<"DEBUG[commands.cpp] write_command("<<num<<",0,NULL)"<<std::endl; else std::cout<<"DEBUG[commands.cpp] write_command("<<num<<","<<adr<<",{"<<HEX(0xff&block[0])<<HEX(0xff&block[1])<<"...})"<<DEC()<<std::endl; } nwdat=12; // so there are no troubles sending a small packet char* command = wdat; switch(num){ case 0: command[0]=0xf0; command[1]=0xf0; command[2]=0x00; command[3]=0x00; break; case 1: command[0]=0xf1; command[1]=0xf1; command[2]=0x00; command[3]=0x00; break; case 2: command[0]=0xf2; command[1]=0xf2; command[2]=0x00; command[3]=0x00; break; case 3: // read command command[0]=0xf3; command[1]=0xf3; command[2]=adr&0x00ff; command[3]=(adr&0xff00)>>8; break; case 5: command[0]=0xf5; command[1]=0xf5; command[2]=0x00; command[3]=0x00; break; case 7: // write command command[0]=0xf7; command[1]=0xf7; command[2]=adr&0x00ff; command[3]=(adr&0xff00)>>8; memcpy((void*)&command[4], (const void*)&block[0], RAMPAGE_SIZE); // fill 4KB nwdat=4+RAMPAGE_SIZE; break; case 0xe: // send out to otmb (not used now) command[0]=0xfe; command[1]=0xfe; command[2]=adr&0x00ff; command[3]=(adr&0xff00)>>8; break; case 0xd: // send out to otmb command[0]=0xfd; command[1]=0xfd; command[2]=adr&0x00ff; command[3]=0x00; break; default: if(DEBUG>10) std::cout<<"DEBUG[commands.cpp] write_command return -1 <== command number "<<num<<" not recognized"<<std::endl; return -1; } // testing >>> //std::cout<<"TESTING: write_command return 0"<<std::endl; //return 0; // <<< testing int n=eth_write(); if(n!=nwdat){ if(DEBUG>10) std::cout<<"DEBUG[commands.cpp] write_command return -2 <== n="<<n<<" != nwdat="<<nwdat<<std::endl; return -2; } if(DEBUG>10) std::cout<<"DEBUG[commands.cpp] write_command return 0"<<std::endl; return 0; }
static int eth_initialize(struct device *port) { struct eth_runtime *context = port->driver_data; const struct eth_config *config = port->config->config_info; uint32_t base_addr; union { struct { uint8_t bytes[6]; uint8_t pad[2]; } __attribute__((packed)); uint32_t words[2]; } mac_addr; if (!eth_setup(port)) return -EPERM; base_addr = context->base_addr; /* Read the MAC address from the device. */ mac_addr.words[1] = eth_read(base_addr, REG_ADDR_MACADDR_HI); mac_addr.words[0] = eth_read(base_addr, REG_ADDR_MACADDR_LO); net_set_mac(mac_addr.bytes, sizeof(mac_addr.bytes)); /* Initialize the frame filter enabling unicast messages */ eth_write(base_addr, REG_ADDR_MAC_FRAME_FILTER, MAC_FILTER_4_PM); /* Initialize transmit descriptor. */ context->tx_desc.tdes0 = 0; context->tx_desc.tdes1 = 0; context->tx_desc.buf1_ptr = (uint8_t *)context->tx_buf; context->tx_desc.tx_end_of_ring = 1; context->tx_desc.first_seg_in_frm = 1; context->tx_desc.last_seg_in_frm = 1; context->tx_desc.tx_end_of_ring = 1; /* Initialize receive descriptor. */ context->rx_desc.rdes0 = 0; context->rx_desc.rdes1 = 0; context->rx_desc.buf1_ptr = (uint8_t *)context->rx_buf; context->rx_desc.own = 1; context->rx_desc.first_desc = 1; context->rx_desc.last_desc = 1; context->rx_desc.rx_buf1_sz = UIP_BUFSIZE; context->rx_desc.rx_end_of_ring = 1; /* Install transmit and receive descriptors. */ eth_write(base_addr, REG_ADDR_RX_DESC_LIST, (uint32_t)&context->rx_desc); eth_write(base_addr, REG_ADDR_TX_DESC_LIST, (uint32_t)&context->tx_desc); eth_write(base_addr, REG_ADDR_MAC_CONF, /* Set the RMII speed to 100Mbps */ MAC_CONF_14_RMII_100M | /* Enable full-duplex mode */ MAC_CONF_11_DUPLEX | /* Enable transmitter */ MAC_CONF_3_TX_EN | /* Enable receiver */ MAC_CONF_2_RX_EN); eth_write(base_addr, REG_ADDR_INT_ENABLE, INT_ENABLE_NORMAL | /* Enable receive interrupts */ INT_ENABLE_RX); /* Mask all the MMC interrupts */ eth_write(base_addr, REG_MMC_RX_INTR_MASK, MMC_DEFAULT_MASK); eth_write(base_addr, REG_MMC_TX_INTR_MASK, MMC_DEFAULT_MASK); eth_write(base_addr, REG_MMC_RX_IPC_INTR_MASK, MMC_DEFAULT_MASK); eth_write(base_addr, REG_ADDR_DMA_OPERATION, /* Enable receive store-and-forward mode for simplicity. */ OP_MODE_25_RX_STORE_N_FORWARD | /* Enable transmit store-and-forward mode for simplicity. */ OP_MODE_21_TX_STORE_N_FORWARD | /* Place the transmitter state machine in the Running state. */ OP_MODE_13_START_TX | /* Place the receiver state machine in the Running state. */ OP_MODE_1_START_RX); SYS_LOG_INF("Enabled 100M full-duplex mode."); net_driver_ethernet_register_tx(eth_net_tx); config->config_func(port); return 0; }