From 5d16090b766a7ba02de70ef7bac468997d7a70da Mon Sep 17 00:00:00 2001 From: Stefan Lankes Date: Sun, 29 May 2011 15:30:34 -0700 Subject: [PATCH 01/10] map FPGA registers to the kernel space --- arch/x86/include/asm/SCC_API.h | 3 +++ arch/x86/mm/page.c | 4 ++++ 2 files changed, 7 insertions(+) diff --git a/arch/x86/include/asm/SCC_API.h b/arch/x86/include/asm/SCC_API.h index eb1bf99c..8812fefc 100644 --- a/arch/x86/include/asm/SCC_API.h +++ b/arch/x86/include/asm/SCC_API.h @@ -155,6 +155,9 @@ #define CRB_X5_Y3 0xf7000000 #define CRB_OWN 0xf8000000 +// FPGA registers +#define FPGA_BASE 0xf9000000 + // Symbol for RPC #define RPC_BASE 0xfb000000 diff --git a/arch/x86/mm/page.c b/arch/x86/mm/page.c index 184f8865..a202a1bb 100644 --- a/arch/x86/mm/page.c +++ b/arch/x86/mm/page.c @@ -733,6 +733,10 @@ int arch_paging_init(void) // map SCC's message passing buffers viraddr = map_region(MPB_X0_Y0, MPB_X0_Y0, (MPB_OWN-MPB_X0_Y0+16*1024*1024) >> PAGE_SHIFT, MAP_KERNEL_SPACE|MAP_MPE); kprintf("Map message passing buffers at 0x%x\n", viraddr); + + // map the FPGA registers + viraddr = map_region(FPGA_BASE, FPGA_BASE, (16*1024*1024) >> PAGE_SHIFT, MAP_KERNEL_SPACE|MAP_NO_CACHE); + kprintf("Map FPGA regsiters at 0x%x\n", viraddr); #endif /* enable paging */ From 6c80f9e15a1ba550997cfa5f026d53fa48b3e77b Mon Sep 17 00:00:00 2001 From: Stefan Lankes Date: Sun, 5 Jun 2011 00:05:41 -0700 Subject: [PATCH 02/10] add initial version of eMAC driver as workround for some bugs, a few LwIP features and the interrupt handling in ICC are disabled --- arch/x86/scc/icc.c | 4 +- drivers/net/Makefile | 2 +- drivers/net/rckemac.c | 735 ++++++++++++++++++++++++++++++++++++ drivers/net/rckemac.h | 61 +++ kernel/Makefile | 2 +- kernel/init.c | 31 +- kernel/tests.c | 2 +- lwip/src/include/lwipopts.h | 4 +- 8 files changed, 829 insertions(+), 12 deletions(-) create mode 100644 drivers/net/rckemac.c create mode 100644 drivers/net/rckemac.h diff --git a/arch/x86/scc/icc.c b/arch/x86/scc/icc.c index 05292396..730add0b 100644 --- a/arch/x86/scc/icc.c +++ b/arch/x86/scc/icc.c @@ -132,6 +132,7 @@ int icc_init(void) RCCE_barrier(&RCCE_COMM_WORLD); +#if 0 kputs("RCCE test...\t"); if (my_ue == 0) msg = 0x4711; @@ -139,6 +140,7 @@ int icc_init(void) kprintf("successfull! (0x%x)\n", msg); else kprintf("failed! (0x%x)\n", msg); +#endif // reset INTR/LINT0 flag z = Z_PID(RC_COREID[my_ue]); @@ -147,7 +149,7 @@ int icc_init(void) SetConfigReg(CRB_OWN + (z==0 ? GLCFG0 : GLCFG1), tmp); // set interrupt handler (INTR/LINT0) - irq_install_handler(124, intr_handler); + //irq_install_handler(124, intr_handler); kputs("Now, the SCC is initialized!\n"); diff --git a/drivers/net/Makefile b/drivers/net/Makefile index bee77167..871a955c 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -1,4 +1,4 @@ -C_source := rtl8139.c +C_source := rtl8139.c rckemac.c MODULE := drivers_net include $(TOPDIR)/Makefile.inc diff --git a/drivers/net/rckemac.c b/drivers/net/rckemac.c new file mode 100644 index 00000000..319ac04b --- /dev/null +++ b/drivers/net/rckemac.c @@ -0,0 +1,735 @@ +/* + * Copyright 2011 Stefan Lankes, Chair for Operating Systems, + * RWTH Aachen University + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of MetalSVM. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if defined(CONFIG_LWIP) && defined(CONFIG_ROCKCREEK) +#include +#include +#include +#include +#include + +/* Limits */ +#define BUFFER_ORDER 9 +#define BUFFER_NUM (1 << BUFFER_ORDER) +#define BUFFER_SIZE (BUFFER_NUM * PAGE_SIZE) + +#define EMAC0 0x01 +#define EMAC1 0x02 +#define EMAC2 0x04 +#define EMAC3 0x08 + +#define EMAC_IPCONF 0x3200 +#define EMAC_RX_CONTROL 0x9000 +#define EMAC_TX_CONTROL 0x9900 + +/* Xilinx IP configuration - offsets */ +#define CONFIG_FLOW_CONTROL_ADD 0xC0 +#define TRANSMITTER_ADDRESS 0x80 +#define RECEIVER1_ADDRESS 0x40 +#define CONFIG_ADD 0x100 +#define ADD_FILTER_MOD 0x190 + +/* EMAC RX */ +#define EMAC_RX_BUFFER_START_ADDRESS 0x0000 +#define EMAC_RX_BUFFER_READ_OFFSET 0x0100 +#define EMAC_RX_BUFFER_WRITE_OFFSET 0x0200 +#define EMAC_RX_BUFFER_SIZE 0x0300 +#define EMAC_RX_BUFFER_THRESHOLD 0x0400 +#define EMAC_RX_MODE 0x0500 +#define EMAC_RX_NETWORK_PORT_MAC_ADDRESS_HI 0x0600 +#define EMAC_RX_NETWORK_PORT_MAC_ADDRESS_LO 0x0700 +#define EMAC_RX_NETWORK_PORT_ENABLE 0x0800 + +/* EMAC TX */ +#define EMAC_TX_BUFFER_START_ADDRESS 0x0000 +#define EMAC_TX_BUFFER_READ_OFFSET 0x0100 +#define EMAC_TX_BUFFER_WRITE_OFFSET 0x0200 +#define EMAC_TX_BUFFER_SIZE 0x0300 +#define EMAC_TX_MODE 0x0400 +#define EMAC_TX_NETWORK_PORT_ENABLE 0x0500 + +// Using of LVT1 as interrupt line +#define EMAC_IRQ_MASK 0x00000001 +#define EMAC_IRQ_NR 3 +#define EMAC_LVT APIC_LVT1 +#define EMAC_IRQ_CONFIG 1 + +#define IRQ_STATUS 0xD000 +#define IRQ_MASK 0xD200 +#define IRQ_RESET 0xD400 +#define IRQ_CONFIG 0xD800 + +/* Cache line wrappers */ +#define CLINE_SHIFT 5 +#define CLINE_SIZE (1UL << CLINE_SHIFT) +#define CLINE_MASK (~(CLINE_SIZE - 1)) +#define CLINE_ALIGN(_x) (((_x) + CLINE_SIZE - 1) & CLINE_MASK) +#define CLINE_PACKETS(_x) (CLINE_ALIGN(_x) >> CLINE_SHIFT) + +#define MAC_ADDRESS 0x00454D414331ULL +#define MAC_HI(_x) ((((_x) >> 32)) & 0xFFFF) +#define MAC_LO(_x) (((_x) ) & 0xFFFFFFFF) + +static struct netif* mynetif[4] = {NULL, NULL, NULL, NULL}; + +static inline int read_emac(int num_emac, int offset, int core) +{ + return *((volatile int*) (FPGA_BASE + num_emac * 0x1000 + offset + core * 4)); +} + +static inline void write_emac(int num_emac, int offset, int core, int value) +{ + *((volatile int*) (FPGA_BASE + num_emac * 0x1000 + offset + core * 4)) = value; +} + +/* + * @return error code + * - ERR_OK: packet transferred to hardware + * - ERR_CONN: no link or link failure + * - ERR_IF: could not transfer to link (hardware buffer full?) + */ +static err_t rckemacif_output(struct netif* netif, struct pbuf* p) +{ + rckemacif_t* rckemacif = netif->state; + uint32_t i; + struct pbuf *q; + void *addr = NULL; + uint16_t read_offset = 0; + int rest = 0; + int packets = 0; + int sum = 0; + + /* check for over/underflow */ + if (BUILTIN_EXPECT(p->tot_len > 1536, 0)) { + LWIP_DEBUGF(NETIF_DEBUG, ("rckemacif_output: illegal packet length %d => drop\n", p->len)); + return ERR_IF; + } + + rckemacif->tx_write_offset++; + /* check if we need to wrap */ + if (rckemacif->tx_write_offset > rckemacif->tx_buffer_max) + rckemacif->tx_write_offset = 1; + + packets = CLINE_PACKETS(p->tot_len + 2); + + read_offset = read_emac(rckemacif->num_emac, EMAC_TX_CONTROL+EMAC_TX_BUFFER_READ_OFFSET, rckemacif->core); +#if 1 +again: + if (read_offset < rckemacif->tx_write_offset) { + sum = rckemacif->tx_buffer_max - rckemacif->tx_write_offset + read_offset - 1; + } else if (read_offset > rckemacif->tx_write_offset) { + sum = read_offset - rckemacif->tx_write_offset - 1; + } + + if (sum < packets) { + LWIP_DEBUGF(NETIF_DEBUG, ("Warning: not enough space available, retrying...\n")); + goto again; + } +#endif + + addr = rckemacif->tx_buffer + rckemacif->tx_write_offset * 32; + + /* Set frame length */ + ((uint8_t*)addr)[0] = p->tot_len % 256; + ((uint8_t*)addr)[1] = p->tot_len / 256; + +#if ETH_PAD_SIZE + pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */ +#endif + + if (rckemacif->tx_write_offset + packets - 1 <= rckemacif->tx_buffer_max) { + /* + * q traverses through linked list of pbuf's + * This list MUST consist of a single packet ONLY + */ + for (q = p, i = 0; q != 0; q = q->next) { + memcpy(addr + 2 + i, q->payload, q->len); + i += q->len; + } + + /* increment write ptr */ + rckemacif->tx_write_offset += packets - 1; + } else { + /* wrap in offsets. first copy to the end, second at the starting + * point + */ + int bytes_left = p->tot_len; + int bytes_to_copy = (rckemacif->tx_buffer_max - rckemacif->tx_write_offset + 1) * 32 - 2; + int sz = 0; + + if (bytes_left < bytes_to_copy) + bytes_to_copy = bytes_left; + + LWIP_DEBUGF(NETIF_DEBUG, ("special case: copy last %d bytes\n", bytes_to_copy)); + + q = p; i = 0; + while ((q != 0) && (i < bytes_to_copy)) { + sz = q->len > bytes_to_copy-i ? bytes_to_copy-i : q->len; + memcpy(addr + 2 + i, q->payload, sz); + bytes_left -= sz; + i += sz; + if (i < bytes_to_copy) + q = q->next; + } + + if (bytes_left != 0) { + rckemacif->tx_write_offset = 1; + addr = rckemacif->tx_buffer + 32; + LWIP_DEBUGF(NETIF_DEBUG, ("special case: copy remaining %d bytes\n", bytes_left)); + + i = 0; + if (sz < q->len) { + memcpy(addr, q->payload + sz, q->len - sz); + bytes_left -= (q->len - sz); + i = q->len - sz; + } + for(q=q->next; (q != 0); q = q->next) { + memcpy(addr+i, q->payload, q->len); + i += q->len; + } + + rest = bytes_left % 32; + if (rest != 0) + rest = 32 - rest; + + LWIP_DEBUGF(NETIF_DEBUG, ("Rest is %d\n", rest)); + rckemacif->tx_write_offset += CLINE_PACKETS(bytes_left + rest) - 1; + } + } + + *((volatile int*) rckemacif->tx_buffer) = 2; + + /* set new write offset */ + LWIP_DEBUGF(NETIF_DEBUG, ("Update tx write offset: %d (read offset %d)\n", rckemacif->tx_write_offset, read_offset)); + + write_emac(rckemacif->num_emac, EMAC_TX_CONTROL+EMAC_TX_BUFFER_WRITE_OFFSET, rckemacif->core, rckemacif->tx_write_offset); + +#if ETH_PAD_SIZE + pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */ +#endif + + LINK_STATS_INC(link.xmit); + + return ERR_OK; +} + +#if 0 +static void rtl_rx_inthandler(struct netif* netif) +{ + rtl1839if_t* rtl8139if = netif->state; + uint16_t header; + uint16_t length, i; + uint8_t cmd; + struct pbuf *p = NULL; + struct pbuf* q; + + cmd = inportb(rtl8139if->iobase + CR); + while(!(cmd & CR_BUFE)) { + header = *((uint16_t*) (rtl8139if->rx_buffer+rtl8139if->rx_pos)); + rtl8139if->rx_pos = (rtl8139if->rx_pos + 2) % (8192+16); + + if (header & ISR_ROK) { + length = *((uint16_t*) (rtl8139if->rx_buffer+rtl8139if->rx_pos)) - 4; // copy packet (but not the CRC) + rtl8139if->rx_pos = (rtl8139if->rx_pos + 2) % (8192+16); +#if ETH_PAD_SIZE + length += ETH_PAD_SIZE; /* allow room for Ethernet padding */ +#endif + + p = pbuf_alloc(PBUF_RAW, length, PBUF_POOL); + if (p) { +#if ETH_PAD_SIZE + pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */ +#endif + for (q=p; q!=NULL; q=q->next) { + for(i=0; ilen; i++) { + ((uint8_t*) q->payload)[i] = rtl8139if->rx_buffer[rtl8139if->rx_pos]; + rtl8139if->rx_pos = (rtl8139if->rx_pos + 1) % (8192+16); + } + } +#if ETH_PAD_SIZE + pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */ +#endif + mailbox_ptr_post(&rtl8139if->mbox, (void*)p); + //rtl8139if_input(netif, p); + LINK_STATS_INC(link.recv); + } else { + LWIP_DEBUGF(NETIF_DEBUG, ("rtl8139if_rx_inthandler: not enough memory!\n")); + rtl8139if->rx_pos += (rtl8139if->rx_pos + length) % (8192+16); + LINK_STATS_INC(link.memerr); + LINK_STATS_INC(link.drop); + } + + // packets are dword aligned + rtl8139if->rx_pos = ((rtl8139if->rx_pos + 4 + 3) & ~0x3) % (8192+16); + outportw(rtl8139if->iobase + CAPR, rtl8139if->rx_pos - 0x10); + } else { + LWIP_DEBUGF(NETIF_DEBUG, ("rtl8139if_rx_inthandler: invalid header!\n")); + LINK_STATS_INC(link.memerr); + LINK_STATS_INC(link.drop); + break; + } + + cmd = inportb(rtl8139if->iobase + CR); + } +} + +static void rtl_tx_inthandler(struct netif* netif) +{ + rtl1839if_t* rtl8139if = netif->state; + uint32_t checks = rtl8139if->tx_queue - rtl8139if->tx_complete; + uint32_t txstatus; + uint8_t tmp8; + + while(checks > 0) + { + tmp8 = rtl8139if->tx_complete % 4; + txstatus = inportl(rtl8139if->iobase + TSD0 + tmp8 * 4); + + if (!(txstatus & (TSD_TOK|TSD_TUN|TSD_TABT))) + return; + + if (txstatus & (TSD_TABT | TSD_OWC)) { + LWIP_DEBUGF(NETIF_DEBUG, ("rtl8139_tx_inthandler: major error\n")); + continue; + } + + if (txstatus & TSD_TUN) { + LWIP_DEBUGF(NETIF_DEBUG, ("rtl8139_tx_inthandler: transmit underrun\n")); + } + + if (txstatus & TSD_TOK) { + rtl8139if->tx_inuse[tmp8] = 0; + rtl8139if->tx_complete++; + checks--; + } + } +} +#endif + +static void rckemacif_handler(struct state* s) +{ + LWIP_DEBUGF(NETIF_DEBUG, ("HELLO! Got interrupt!\n")); + +#if 0 + rtl1839if_t* rtl8139if = mynetif->state; + uint16_t isr_contents; + + while (1) { + isr_contents = inportw(rtl8139if->iobase + ISR); + if (isr_contents == 0) + break; + + if (isr_contents & ISR_ROK) { + rtl_rx_inthandler(mynetif); + outportw(rtl8139if->iobase + ISR, ISR_ROK); + } + + if (isr_contents & ISR_TOK) { + rtl_tx_inthandler(mynetif); + outportw(rtl8139if->iobase + ISR, ISR_TOK); + } + + if (isr_contents & ISR_RER) { + LWIP_DEBUGF(NETIF_DEBUG, ("rtl8139if_handler: RX error detected!\n")); + outportw(rtl8139if->iobase + ISR, ISR_RER); + } + + if (isr_contents & ISR_TER) { + LWIP_DEBUGF(NETIF_DEBUG, ("rtl8139if_handler: TX error detected!\n")); + outportw(rtl8139if->iobase + ISR, ISR_TER); + } + + if (isr_contents & ISR_RXOVW) { + LWIP_DEBUGF(NETIF_DEBUG, ("rtl8139if_handler: RX overflow detected!\n")); + outportw(rtl8139if->iobase + ISR, ISR_RXOVW); + } + } +#endif +} + +err_t rckemacif_wait(struct netif* netif, uint32_t poll) +{ + return ERR_OK; +#if 0 + rckemacif_t* rckemacif = netif->state; + struct eth_hdr *ethhdr; + struct pbuf *p = NULL; + err_t err = ERR_OK; + + LWIP_DEBUGF(NETIF_DEBUG, ("Hello from rckemacif_wait!\n")); + + if (poll) { + if (mailbox_ptr_tryfetch(&(rckemacif->mbox), (void**) &p)) + return err; + } else { + mailbox_ptr_fetch(&(rckemacif->mbox), (void**) &p); + } + + /* points to packet payload, which starts with an Ethernet header */ + ethhdr = p->payload; + + switch (htons(ethhdr->type)) { + /* IP or ARP packet? */ + case ETHTYPE_ARP: + case ETHTYPE_IP: +#if PPPOE_SUPPORT + /* PPPoE packet? */ + case ETHTYPE_PPPOEDISC: + case ETHTYPE_PPPOE: +#endif /* PPPOE_SUPPORT */ + /* full packet send to tcpip_thread to process */ + if ((err = mynetif[netif->num]->input(p, mynetif[netif->num])) != ERR_OK) { + LWIP_DEBUGF(NETIF_DEBUG, ("rckemacif_poll: IP input error\n")); + pbuf_free(p); + } + break; + default: + pbuf_free(p); + break; + } + + return err; +#endif +} + +err_t rckemacif_init(struct netif* netif) +{ + rckemacif_t* rckemacif; + int num, num_emac; + int macPorts; + int i, tmp, x, y, z, core; + uint64_t tile_offset; + uint16_t write_offset = 0; + uint16_t read_offset = 0; + int mode = 0; + int subdest = 0; + int route = 0; + + LWIP_ASSERT("netif != NULL", (netif != NULL)); + + // Find out who I am... + tmp = ReadConfigReg(CRB_OWN+MYTILEID); + x = (tmp>>3) & 0x0f; // bits 06:03 + y = (tmp>>7) & 0x0f; // bits 10:07 + z = (tmp ) & 0x07; // bits 02:00 + core = 12 * y + 2 * x + z; + + rckemacif = kmalloc(sizeof(rckemacif_t)); + if (!rckemacif) { + LWIP_DEBUGF(NETIF_DEBUG, ("rckemacif_init: out of memory\n")); + return ERR_MEM; + } + memset(rckemacif, 0, sizeof(rckemacif_t)); + rckemacif->core = core; + + /* allocate the receive buffer */ + rckemacif->rx_buffer = mem_allocation(BUFFER_SIZE, MAP_KERNEL_SPACE|MAP_NO_CACHE); + if (!(rckemacif->rx_buffer)) { + LWIP_DEBUGF(NETIF_DEBUG, ("rckemacif_init: out of memory\n")); + kfree(rckemacif, sizeof(rckemacif_t)); + return ERR_MEM; + } + memset(rckemacif->rx_buffer, 0, BUFFER_SIZE); + rckemacif->rx_buffer_max = CLINE_PACKETS(BUFFER_SIZE) - 1; + + /* allocate the send buffers */ + rckemacif->tx_buffer = mem_allocation(BUFFER_SIZE, MAP_KERNEL_SPACE|MAP_NO_CACHE); + if (!(rckemacif->tx_buffer)) { + LWIP_DEBUGF(NETIF_DEBUG, ("rckemacif_init: out of memory\n")); + kfree(rckemacif->rx_buffer, BUFFER_SIZE); + kfree(rckemacif, sizeof(rckemacif_t)); + return ERR_MEM; + } + memset(rckemacif->tx_buffer, 0, BUFFER_SIZE); + rckemacif->tx_buffer_max = CLINE_PACKETS(BUFFER_SIZE) - 1; + + mailbox_ptr_init(&rckemacif->mbox); + netif->state = rckemacif; + + /* Depending on core location read own private data + * (offset, subdest, route) + */ + if (z == 0) { + tmp = ReadConfigReg(CRB_OWN + GLCFG0); + rckemacif->irq_address = CRB_OWN + GLCFG0; + } else { + tmp = ReadConfigReg(CRB_OWN + GLCFG1); + rckemacif->irq_address = CRB_OWN + GLCFG1; + } + tile_offset = (unsigned long long)((unsigned long long) tmp & 0x3FF) << 24; + subdest = (tmp >> 10) & 0x07; + route = (tmp >> 13) & 0xFF; + mode = (subdest << 8) + route; + + /* get fpga/sccKit port settings */ + tmp = *((volatile int*)(FPGA_BASE + 0x822C)); + macPorts = ((tmp >> 9 ) & 0xFF); + + LWIP_DEBUGF(NETIF_DEBUG, ("rckemacif_init: eMAC0: %s eMAC1: %s eMAC2: %s eMAC3: %s\n", + (macPorts & EMAC0) != 0 ? "present" : "-", + (macPorts & EMAC1) != 0 ? "present" : "-", + (macPorts & EMAC2) != 0 ? "present" : "-", + (macPorts & EMAC3) != 0 ? "present" : "-")); + + // determine device and emac number + for(num=0; (num<4) && (mynetif[num] != NULL); num++) + ; + if (num >= 4) + return ERR_ARG; + for(i=0, num_emac=0; (i<=num) && (num_emac < 4); i++) { + while (((macPorts & (1 << num_emac)) == 0) && (num_emac < 4)) + num_emac++; + } + if (num_emac >= 4) + return ERR_ARG; + mynetif[num] = netif; + rckemacif->num_emac = num_emac; + + LWIP_DEBUGF(NETIF_DEBUG, ("rckemacif_init: map device %d to eMAC %d\n", num, num_emac)); + + if (core == 0) { + /* Only core 0 initialize the xilinx port */ + int flow_control = 0; + int transmitter_addr = 0; + int receiver1_addr = 0; + int config_add = 0; + int add_filter_mod = 0; + + /* Disable tx and rx flow control of eMAC */ + LWIP_DEBUGF(NETIF_DEBUG, ("Disabling tx/rx flow control of eMAC%d\n", num_emac)); + flow_control = read_emac(num_emac, EMAC_IPCONF+CONFIG_FLOW_CONTROL_ADD, 0); + + /* Set top 3 bits of the flow control configuration to zero, + * therefore disabling tx and rx flow control + */ + flow_control &= 0x7FFFFFF; + write_emac(num_emac, EMAC_IPCONF+CONFIG_FLOW_CONTROL_ADD, 0, flow_control); + + /* Sanity check */ + flow_control = read_emac(num_emac, EMAC_IPCONF+CONFIG_FLOW_CONTROL_ADD, 0); + LWIP_DEBUGF(NETIF_DEBUG, (" CONFIG_FLOW_CONTROL_ADD set: 0x%x\n", flow_control)); + + /* Setting the tx configuration bit to enable the transmitter and + * set to full duplex mode. + */ + LWIP_DEBUGF(NETIF_DEBUG, ("Setting rx configuration of eMAC%d\n", num_emac)); + transmitter_addr = read_emac(num_emac, EMAC_IPCONF+TRANSMITTER_ADDRESS, 0); + + /* Now set the relevant bits and write back into the register: + * 26 (half duplex) = 0, 28 (transmit enable) = 1, 31 (reset) = 0 + */ + transmitter_addr &= ~(1 << 31); + transmitter_addr &= ~(1 << 26); + transmitter_addr |= (1 << 28); + write_emac(num_emac, EMAC_IPCONF+TRANSMITTER_ADDRESS, 0, transmitter_addr); + + transmitter_addr = read_emac(num_emac, EMAC_IPCONF+TRANSMITTER_ADDRESS, 0); + LWIP_DEBUGF(NETIF_DEBUG, (" TRANSMITTER_ADDRESS set: %x\n", transmitter_addr)); + + /* Setting the rx configuration bit to enable the transmitter and + * set to full duplex mode. + */ + LWIP_DEBUGF(NETIF_DEBUG, ("Setting IP configuration of EMAC%d\n", num_emac)); + + /* Read the current config value from the register */ + receiver1_addr = read_emac(num_emac, EMAC_IPCONF+RECEIVER1_ADDRESS, core); + + /* Now set the relevant bits and write back into the register: + * 25 = 1, 26 = 0, 28 = 1, 31 = 0 + */ + /* Length/Type Error Check Disable */ + receiver1_addr |= (1 << 25); + /* Disable Half Duplex => Full Duplex */ + receiver1_addr &= ~(1 << 26); + /* Receiver enable */ + receiver1_addr |= (1 << 28); + /* Reset */ + receiver1_addr &= ~(1 << 31); + write_emac(num_emac, EMAC_IPCONF+RECEIVER1_ADDRESS, 0, receiver1_addr); + + receiver1_addr = read_emac(num_emac, EMAC_IPCONF+RECEIVER1_ADDRESS, 0); + LWIP_DEBUGF(NETIF_DEBUG, (" RECEIVER1_ADDRESS set: %x\n", receiver1_addr)); + + /* Setting the speed to eMAC to 1Gb/s */ + LWIP_DEBUGF(NETIF_DEBUG, ("Setting speed of EMAC%d to 1Gb/s\n", num_emac)); + + /* Read the current config value from register */ + config_add = read_emac(num_emac, EMAC_IPCONF+CONFIG_ADD, 0); + + /* Now set the relevant bits and write back into the register: + * 31 = 1, 30 = 0 + */ + /* MAC Speed Configuration: 00 - 10Mbps, 01 - 100Mbps, 10 - 1Gbps */ + config_add |= (1 << 31); + config_add &= ~(1 << 30); + write_emac(num_emac, EMAC_IPCONF+CONFIG_ADD, 0, config_add); + + config_add = read_emac(num_emac, EMAC_IPCONF+CONFIG_ADD, 0); + LWIP_DEBUGF(NETIF_DEBUG, (" CONFIG_ADD set: %x\n", config_add)); + + /* Read the current config addr filter mode */ + add_filter_mod = read_emac(num_emac, EMAC_IPCONF+ADD_FILTER_MOD, 0); + + /* Not set the relevant bits and write back into the register: + * 31 (promiscuous mode) = 1 not working, but thats ok! + */ + add_filter_mod |= (1 << 31); + write_emac(num_emac, EMAC_IPCONF+ADD_FILTER_MOD, 0, add_filter_mod); + + add_filter_mod = read_emac(num_emac, EMAC_IPCONF+ADD_FILTER_MOD, 0); + LWIP_DEBUGF(NETIF_DEBUG, (" ADD_FILTER_MOD set: %x\n", add_filter_mod)); + } + + sleep(3); + + /* Start address */ + LWIP_DEBUGF(NETIF_DEBUG, (" RX Buffer %p (%lx phys)\n", rckemacif->rx_buffer, virt_to_phys(rckemacif->rx_buffer))); + + /**** Receiver configuration ****/ + + uint32_t utmp = virt_to_phys(rckemacif->rx_buffer); + uint32_t addr_offset = tile_offset + utmp; + addr_offset >>= 5; + write_emac(num_emac, EMAC_RX_CONTROL + EMAC_RX_BUFFER_START_ADDRESS, core, addr_offset); + utmp = read_emac(num_emac, EMAC_RX_CONTROL + EMAC_RX_BUFFER_START_ADDRESS, core); + LWIP_DEBUGF(NETIF_DEBUG, (" RX Buffer set to @%x\n", utmp)); + + /* Set buffer write offset */ + write_offset = read_emac(num_emac, EMAC_RX_CONTROL + EMAC_RX_BUFFER_WRITE_OFFSET, core); + LWIP_DEBUGF(NETIF_DEBUG, (" RX Buffer write offset at: %d\n", write_offset)); + + /* Set buffer read offset to write offset */ + write_emac(num_emac, EMAC_RX_CONTROL + EMAC_RX_BUFFER_READ_OFFSET, core, write_offset); + LWIP_DEBUGF(NETIF_DEBUG, (" RX Buffer read offset set to: %d\n", read_emac(num_emac, EMAC_RX_CONTROL + EMAC_RX_BUFFER_READ_OFFSET, core))); + rckemacif->rx_read_offset = write_offset; + + /* Size */ + write_emac(num_emac, EMAC_RX_CONTROL + EMAC_RX_BUFFER_SIZE, core, rckemacif->rx_buffer_max); + LWIP_DEBUGF(NETIF_DEBUG, (" RX Size set to %d\n", read_emac(num_emac, EMAC_RX_CONTROL + EMAC_RX_BUFFER_SIZE, core))); + + /* Threshold */ + write_emac(num_emac, EMAC_RX_CONTROL + EMAC_RX_BUFFER_THRESHOLD, core, 0x01); + LWIP_DEBUGF(NETIF_DEBUG, (" RX Threshold set to %x\n", read_emac(num_emac, EMAC_RX_CONTROL + EMAC_RX_BUFFER_THRESHOLD, core))); + + /* Route */ + write_emac(num_emac, EMAC_RX_CONTROL + EMAC_RX_MODE, core, (core << 24) | (((y << 4) | x) << 16) | mode); + LWIP_DEBUGF(NETIF_DEBUG, (" RX Mode set to %x\n", read_emac(num_emac, EMAC_RX_CONTROL + EMAC_RX_MODE, core))); + + // determine mac address + uint32_t mac1 = *((uint32_t*)(FPGA_BASE+0x7E00)); + uint32_t mac2 = *((uint32_t*)(FPGA_BASE+0x7E04)); + uint64_t mac = (((unsigned long long)mac1) << 32) + ( unsigned long long ) mac2; + if (mac == 0x00) + mac = MAC_ADDRESS; + /* Calculate mac address of core depending on selected emac device */ + mac = mac + (1 << num_emac) * 0x100 + core; + + LWIP_DEBUGF(NETIF_DEBUG, ("rckemacif_init: MAC address ")); + for (i=0; i<6; i++) { + mynetif[num]->hwaddr[i] = mac & 0xFF; + mac = mac >> 8; + LWIP_DEBUGF(NETIF_DEBUG, ("%02x ", mynetif[num]->hwaddr[i])); + } + LWIP_DEBUGF(NETIF_DEBUG, ("\n")); + + write_emac(num_emac, EMAC_RX_CONTROL + EMAC_RX_NETWORK_PORT_MAC_ADDRESS_HI, core, MAC_HI(mac)); + LWIP_DEBUGF(NETIF_DEBUG, (" MAC1 set to %x\n", read_emac(num_emac, EMAC_RX_CONTROL + EMAC_RX_NETWORK_PORT_MAC_ADDRESS_HI, core))); + write_emac(num_emac, EMAC_RX_CONTROL + EMAC_RX_NETWORK_PORT_MAC_ADDRESS_LO, core, MAC_LO(mac)); + LWIP_DEBUGF(NETIF_DEBUG, (" MAC2 set to %x\n", read_emac(num_emac, EMAC_RX_CONTROL + EMAC_RX_NETWORK_PORT_MAC_ADDRESS_LO, core))); + + /* Activate network port by setting enable bit */ + write_emac(num_emac, EMAC_RX_CONTROL + EMAC_RX_NETWORK_PORT_ENABLE, core, 0x01); + LWIP_DEBUGF(NETIF_DEBUG, (" RX Port enable set to %x\n", read_emac(num_emac, EMAC_RX_CONTROL + EMAC_RX_NETWORK_PORT_ENABLE, core))); + + /**** Transfer configuration ****/ + + /* Start address */ + LWIP_DEBUGF(NETIF_DEBUG, (" TX Buffer %p (%lx phys)\n", rckemacif->tx_buffer, virt_to_phys(rckemacif->tx_buffer))); + utmp = virt_to_phys(rckemacif->tx_buffer); + write_emac(num_emac, EMAC_TX_CONTROL + EMAC_TX_BUFFER_START_ADDRESS, core, (tmp + tile_offset) >> 5); + utmp = read_emac(num_emac, EMAC_TX_CONTROL + EMAC_TX_BUFFER_START_ADDRESS, core); + LWIP_DEBUGF(NETIF_DEBUG, (" TX Buffer set to @%x\n", tmp)); + + /* Get buffer read offset */ + read_offset = read_emac(num_emac, EMAC_TX_CONTROL + EMAC_TX_BUFFER_READ_OFFSET, core); + LWIP_DEBUGF(NETIF_DEBUG, (" TX Buffer read offset at: %d\n", read_offset)); + + /* Set buffer write offset to read offset */ + write_emac(num_emac, EMAC_TX_CONTROL + EMAC_TX_BUFFER_WRITE_OFFSET, core, read_offset); + LWIP_DEBUGF(NETIF_DEBUG, (" TX Buffer write offset set to: %d\n", read_emac(num_emac, EMAC_TX_CONTROL+ EMAC_TX_BUFFER_WRITE_OFFSET, core))); + rckemacif->tx_write_offset = read_offset; + + /* Size */ + write_emac(num_emac, EMAC_TX_CONTROL + EMAC_TX_BUFFER_SIZE, core, rckemacif->tx_buffer_max); + LWIP_DEBUGF(NETIF_DEBUG, (" TX Size set to %d\n", read_emac(num_emac, EMAC_TX_CONTROL + EMAC_TX_BUFFER_SIZE, core))); + + /* Route */ + write_emac(num_emac, EMAC_TX_CONTROL + EMAC_TX_MODE, core, mode); + LWIP_DEBUGF(NETIF_DEBUG, (" TX Mode set to %x\n", read_emac(num_emac, EMAC_TX_CONTROL + EMAC_TX_MODE, core))); + + /* Activate network port by setting enable bit */ + write_emac(num_emac, EMAC_TX_CONTROL + EMAC_TX_NETWORK_PORT_ENABLE, core, 0x01); + LWIP_DEBUGF(NETIF_DEBUG, (" TX Port enable set to %x\n", read_emac(num_emac, EMAC_TX_CONTROL + EMAC_TX_NETWORK_PORT_ENABLE, core))); + + // set interrupt handler (INTR/LINT0) + irq_install_handler(125, rckemacif_handler); + + /* Enable interrupt */ + tmp = *((volatile int*) (FPGA_BASE + IRQ_MASK + core * 2 * 4)); + *((volatile int*) (FPGA_BASE + IRQ_MASK + core * 2 * 4)) = tmp & ~(1 << num_emac); + *((volatile int*) (FPGA_BASE + IRQ_CONFIG + core * 4)) = EMAC_IRQ_CONFIG; + + /* + * Initialize the snmp variables and counters inside the struct netif. + * The last argument should be replaced with your link speed, in units + * of bits per second. + */ + NETIF_INIT_SNMP(netif, snmp_ifType_ethernet_csmacd, 1000 /* speed */); + + /* administrative details */ + netif->name[0] = 'e'; + netif->name[1] = 'n'; + netif->num = num; + /* downward functions */ + netif->output = etharp_output; + netif->linkoutput = rckemacif_output; + /* maximum transfer unit */ + netif->mtu = 1500; + /* broadcast capability */ + netif->flags |= NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP; + /* hardware address length */ + netif->hwaddr_len = 6; + + rckemacif->ethaddr = (struct eth_addr *)netif->hwaddr; + + return ERR_OK; +} +#endif diff --git a/drivers/net/rckemac.h b/drivers/net/rckemac.h new file mode 100644 index 00000000..b8a8a5ae --- /dev/null +++ b/drivers/net/rckemac.h @@ -0,0 +1,61 @@ +/* + * Copyright 2011 Stefan Lankes, Chair for Operating Systems, + * RWTH Aachen University + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of MetalSVM. + */ + +#ifndef __HAVE_RCKEMAC_H__ +#define __HAVE_RCKEMAC_H__ + +#include +#include + +#if defined(CONFIG_LWIP) && defined(CONFIG_ROCKCREEK) + +/* + * Helper struct to hold private data used to operate your ethernet interface. + */ +typedef struct rckemacif { + struct eth_addr *ethaddr; + /* Add whatever per-interface state that is needed here. */ + uint8_t* tx_buffer; + uint8_t* rx_buffer; + uint32_t rx_buffer_max; + uint32_t rx_read_offset; + uint32_t tx_buffer_max; + uint32_t tx_write_offset; + void* irq_address; + uint32_t core; + uint32_t num_emac; + mailbox_ptr_t mbox; +} rckemacif_t; + +/* + * Wait for incoming messages. + * + * poll = 0 : wait blocks until a message is received + * poll != 0: non-blocking wait + */ +err_t rckemacif_wait(struct netif* netif, uint32_t poll); + +/* + * Initialize the eMAC network driver + */ +err_t rckemacif_init(struct netif* netif); + +#endif + +#endif diff --git a/kernel/Makefile b/kernel/Makefile index fdddee71..8c3b4c8c 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -1,4 +1,4 @@ -C_source := main.c tasks.c syscall.c tests.c echo.c ping.c init.c +C_source := main.c tasks.c syscall.c tests.c echo.c init.c #ping.c init.c MODULE := kernel include $(TOPDIR)/Makefile.inc diff --git a/kernel/init.c b/kernel/init.c index 2ba3b81f..8a8f3d37 100644 --- a/kernel/init.c +++ b/kernel/init.c @@ -37,6 +37,11 @@ #include #endif #include +#include +#ifdef CONFIG_ROCKCREEK +#include +#include +#endif void echo_init(void); void ping_init(void); @@ -50,7 +55,7 @@ int lowlevel_init(void) return 0; } -#if defined(CONFIG_LWIP) && defined(CONFIG_PCI) +#if defined(CONFIG_LWIP) && (defined(CONFIG_PCI) || defined(CONFIG_ROCKCREEK)) static tid_t netid; int STDCALL network_task(void* arg) @@ -62,10 +67,15 @@ int STDCALL network_task(void* arg) kputs("Network task is started\n"); +#ifdef CONFIG_ROCKCREEK /* Set network address variables */ - //IP4_ADDR(&gw, 192,168,1,254); - //IP4_ADDR(&ipaddr, 192,168,1,100); - //IP4_ADDR(&netmask, 255,255,255,0); + IP4_ADDR(&gw, 192,168,4,254); + IP4_ADDR(&ipaddr, 192,168,4,RCCE_ue()+1); + IP4_ADDR(&netmask, 255,255,255,0); + + /* Bring up the network interface */ + if (!netif_add(&netif, &ipaddr, &netmask, &gw, NULL, rckemacif_init, ethernet_input)) { +#else /* Clear network address because we use DHCP to get an ip address */ IP4_ADDR(&gw, 0,0,0,0); IP4_ADDR(&ipaddr, 0,0,0,0); @@ -73,6 +83,7 @@ int STDCALL network_task(void* arg) /* Bring up the network interface */ if (!netif_add(&netif, &ipaddr, &netmask, &gw, NULL, rtl8139if_init, ethernet_input)) { +#endif kputs("Unable to add network interface\n"); return -ENXIO; } @@ -84,6 +95,7 @@ int STDCALL network_task(void* arg) return -EIO; } +#ifndef CONFIG_ROCKCREEK kprintf("Starting DHCPCD...\n"); dhcp_start(&netif); @@ -92,17 +104,24 @@ int STDCALL network_task(void* arg) rtl8139if_wait(&netif, 1); udelay(500000); } +#endif // start echo and ping server echo_init(); - ping_init(); + //ping_init(); while(!done) { +#ifdef CONFIG_PCI rtl8139if_wait(&netif, 0); +#elif defined(CONFIG_ROCKCREEK) + rckemacif_wait(&netif, 0); +#endif } +#ifndef CONFIG_ROCKCREEK dhcp_release(&netif); dhcp_stop(&netif); +#endif return 0; } @@ -122,7 +141,7 @@ int network_init(void) lwip_init(); #endif -#if defined(CONFIG_LWIP) && defined(CONFIG_PCI) +#if defined(CONFIG_LWIP) && (defined(CONFIG_PCI) || defined(CONFIG_ROCKCREEK)) return create_kernel_task(&netid, network_task, NULL); #else return 0; diff --git a/kernel/tests.c b/kernel/tests.c index 8427ca56..78b6f9df 100644 --- a/kernel/tests.c +++ b/kernel/tests.c @@ -139,7 +139,7 @@ int test_init(void) #ifdef CONFIG_LWIP // use ping to test LWIP - ping_send_now(); + //ping_send_now(); #endif return 0; diff --git a/lwip/src/include/lwipopts.h b/lwip/src/include/lwipopts.h index 7279f5c7..b779464f 100644 --- a/lwip/src/include/lwipopts.h +++ b/lwip/src/include/lwipopts.h @@ -13,7 +13,7 @@ * NO_SYS_NO_TIMERS==1: Drop support for sys_timeout when NO_SYS==1 * Mainly for compatibility to old versions. */ -#define NO_SYS_NO_TIMERS 0 +#define NO_SYS_NO_TIMERS 1 /** * LWIP_SOCKET==1: Enable Socket API (require to use sockets.c) @@ -53,7 +53,7 @@ /** * LWIP_HAVE_LOOPIF==1: Support loop interface (127.0.0.1) and loopif.c */ -#define LWIP_HAVE_LOOPIF 1 +#define LWIP_HAVE_LOOPIF 0 /** * LWIP_NETIF_LOOPBACK==1: Support sending packets with a destination IP From 46b86a6746554ffefbbacd40dc0d9c7fa74398b3 Mon Sep 17 00:00:00 2001 From: Stefan Lankes Date: Wed, 8 Jun 2011 06:03:57 -0700 Subject: [PATCH 03/10] remove typo --- drivers/net/rckemac.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/rckemac.c b/drivers/net/rckemac.c index 319ac04b..8e996dc6 100644 --- a/drivers/net/rckemac.c +++ b/drivers/net/rckemac.c @@ -560,7 +560,7 @@ err_t rckemacif_init(struct netif* netif) LWIP_DEBUGF(NETIF_DEBUG, ("Setting IP configuration of EMAC%d\n", num_emac)); /* Read the current config value from the register */ - receiver1_addr = read_emac(num_emac, EMAC_IPCONF+RECEIVER1_ADDRESS, core); + receiver1_addr = read_emac(num_emac, EMAC_IPCONF+RECEIVER1_ADDRESS, 0); /* Now set the relevant bits and write back into the register: * 25 = 1, 26 = 0, 28 = 1, 31 = 0 From b4639fc1ae540ae6f076bf05dcbadcf80af44aaf Mon Sep 17 00:00:00 2001 From: Stefan Lankes Date: Wed, 8 Jun 2011 23:42:20 -0700 Subject: [PATCH 04/10] fix typo, remove some SCC workarounds --- arch/x86/kernel/gdt.c | 2 +- kernel/init.c | 2 +- kernel/tests.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/x86/kernel/gdt.c b/arch/x86/kernel/gdt.c index 53a83b95..ed863eaa 100644 --- a/arch/x86/kernel/gdt.c +++ b/arch/x86/kernel/gdt.c @@ -28,7 +28,7 @@ gdt_ptr_t gp; static tss_t task_state_segments[MAX_TASKS] __attribute__ ((aligned (PAGE_SIZE))); -static unsigned char kstacks[MAX_TASKS][KERNEL_STACK_SIZE] __attribute__ ((aligned (PAGE_SIZE) section (".data"))); +static unsigned char kstacks[MAX_TASKS][KERNEL_STACK_SIZE] __attribute__ ((aligned (PAGE_SIZE), section (".data"))); // currently, our kernel has full access to the ioports static gdt_entry_t gdt[GDT_ENTRIES] = {[0 ... GDT_ENTRIES-1] = {0, 0, 0, 0, 0, 0}}; unsigned char* default_stack_pointer __attribute__ ((section (".data"))) = kstacks[0] + KERNEL_STACK_SIZE - sizeof(size_t); diff --git a/kernel/init.c b/kernel/init.c index da2f7dc1..7fc9d0f1 100644 --- a/kernel/init.c +++ b/kernel/init.c @@ -120,7 +120,7 @@ int STDCALL network_task(void* arg) // start echo and ping server echo_init(); - //ping_init(); + ping_init(); while(!done) { #ifdef CONFIG_PCI diff --git a/kernel/tests.c b/kernel/tests.c index 78b6f9df..8427ca56 100644 --- a/kernel/tests.c +++ b/kernel/tests.c @@ -139,7 +139,7 @@ int test_init(void) #ifdef CONFIG_LWIP // use ping to test LWIP - //ping_send_now(); + ping_send_now(); #endif return 0; From 5517d505db5791a776f2c34caa02ad522c6be49a Mon Sep 17 00:00:00 2001 From: Stefan Lankes Date: Wed, 8 Jun 2011 23:43:29 -0700 Subject: [PATCH 05/10] remove SCC workaround --- kernel/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/Makefile b/kernel/Makefile index 8c3b4c8c..fdddee71 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -1,4 +1,4 @@ -C_source := main.c tasks.c syscall.c tests.c echo.c init.c #ping.c init.c +C_source := main.c tasks.c syscall.c tests.c echo.c ping.c init.c MODULE := kernel include $(TOPDIR)/Makefile.inc From 692e554a3a507f2853992bda90b8afbaef8e168d Mon Sep 17 00:00:00 2001 From: Stefan Lankes Date: Tue, 21 Jun 2011 23:10:45 -0700 Subject: [PATCH 06/10] remove obsolete test --- kernel/tests.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/kernel/tests.c b/kernel/tests.c index 8427ca56..1fbc7a48 100644 --- a/kernel/tests.c +++ b/kernel/tests.c @@ -137,10 +137,5 @@ int test_init(void) //create_user_task(NULL, "/bin/jacobi", argv); //create_user_task(NULL, "/bin/jacobi", argv); -#ifdef CONFIG_LWIP - // use ping to test LWIP - ping_send_now(); -#endif - return 0; } From b68e9051cbf8bfacacc99439a344830eeb814731 Mon Sep 17 00:00:00 2001 From: Stefan Lankes Date: Tue, 21 Jun 2011 23:12:09 -0700 Subject: [PATCH 07/10] MetalSVM is a research project => we trust the incoming IP packets - set ETHARP_TRUST_IP_MAC to 1 --- lwip/src/include/lwipopts.h | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/lwip/src/include/lwipopts.h b/lwip/src/include/lwipopts.h index f6912703..af8d018c 100644 --- a/lwip/src/include/lwipopts.h +++ b/lwip/src/include/lwipopts.h @@ -29,6 +29,18 @@ */ #define DHCP_DOES_ARP_CHECK 0 +/** + * ETHARP_TRUST_IP_MAC==1: Incoming IP packets cause the ARP table to be + * updated with the source MAC and IP addresses supplied in the packet. + * You may want to disable this if you do not trust LAN peers to have the + * correct addresses, or as a limited approach to attempt to handle + * spoofing. If disabled, lwIP will need to make a new ARP request if + * the peer is not already in the ARP table, adding a little latency. + * The peer *is* in the ARP table if it requested our address before. + * Also notice that this slows down input processing of every IP packet! + */ +#define ETHARP_TRUST_IP_MAC 1 + /** * LWIP_TCP==1: Turn on TCP. */ @@ -58,7 +70,7 @@ /** * LWIP_HAVE_LOOPIF==1: Support loop interface (127.0.0.1) and loopif.c */ -#define LWIP_HAVE_LOOPIF 1 +#define LWIP_HAVE_LOOPIF 1 /** * LWIP_NETIF_LOOPBACK==1: Support sending packets with a destination IP From fd89f4f825947c62965905d04b3bccfe82ca0bb0 Mon Sep 17 00:00:00 2001 From: Stefan Lankes Date: Tue, 21 Jun 2011 23:18:10 -0700 Subject: [PATCH 08/10] use the socket version of ping, if this feature is enabled in LwIP --- kernel/ping.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/kernel/ping.c b/kernel/ping.c index 4a02ff0e..98398300 100644 --- a/kernel/ping.c +++ b/kernel/ping.c @@ -53,6 +53,10 @@ #include #include +#if LWIP_SOCKET +#define PING_USE_SOCKETS 1 +#endif + #if PING_USE_SOCKETS #include #include @@ -68,7 +72,7 @@ /** ping target - should be a "ip_addr_t" */ #ifndef PING_TARGET -#define PING_TARGET (netif_default?netif_default->gw:ip_addr_any) +#define PING_TARGET (netif_default?netif_default->gw:ip_addr_any) #endif /** ping receive timeout - in milliseconds */ From 19fffd46c5455de9a8de7948287db9b7211ebfbd Mon Sep 17 00:00:00 2001 From: Stefan Lankes Date: Tue, 21 Jun 2011 23:19:28 -0700 Subject: [PATCH 09/10] use netif_set_up to enable the network device --- kernel/init.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/kernel/init.c b/kernel/init.c index 7fc9d0f1..2f9b883f 100644 --- a/kernel/init.c +++ b/kernel/init.c @@ -101,11 +101,7 @@ int STDCALL network_task(void* arg) } netif_set_default(&netif); - - if (netif_is_up(&netif)) { - kputs("Network interface is not up\n"); - return -EIO; - } + netif_set_up(&netif); #ifndef CONFIG_ROCKCREEK kprintf("Starting DHCPCD...\n"); From f8be2e34833b3c121afb1939527a86b91a1bc986 Mon Sep 17 00:00:00 2001 From: Stefan Lankes Date: Tue, 21 Jun 2011 23:26:31 -0700 Subject: [PATCH 10/10] add first functional version of the eMAC driver - this driver required at least sccKit 1.4.0 --- arch/x86/mm/page.c | 2 +- drivers/net/rckemac.c | 432 +++++++++++++++++++++++------------------- drivers/net/rckemac.h | 2 +- 3 files changed, 238 insertions(+), 198 deletions(-) diff --git a/arch/x86/mm/page.c b/arch/x86/mm/page.c index a202a1bb..4551edc1 100644 --- a/arch/x86/mm/page.c +++ b/arch/x86/mm/page.c @@ -735,7 +735,7 @@ int arch_paging_init(void) kprintf("Map message passing buffers at 0x%x\n", viraddr); // map the FPGA registers - viraddr = map_region(FPGA_BASE, FPGA_BASE, (16*1024*1024) >> PAGE_SHIFT, MAP_KERNEL_SPACE|MAP_NO_CACHE); + viraddr = map_region(FPGA_BASE, FPGA_BASE, 0x10000 >> PAGE_SHIFT, MAP_KERNEL_SPACE|MAP_NO_CACHE); kprintf("Map FPGA regsiters at 0x%x\n", viraddr); #endif diff --git a/drivers/net/rckemac.c b/drivers/net/rckemac.c index 8e996dc6..b2b07f4e 100644 --- a/drivers/net/rckemac.c +++ b/drivers/net/rckemac.c @@ -17,6 +17,12 @@ * This file is part of MetalSVM. */ +/* + * This eMAC driver required at least sccKit 1.4.0 and based on + * the eMAC Driver Description (section 9.6.5) in the + * SccKit 1.4.0 User’s Guide (Revision 0.92 Part 9). + */ + #include #include #include @@ -50,7 +56,7 @@ #define EMAC_RX_CONTROL 0x9000 #define EMAC_TX_CONTROL 0x9900 -/* Xilinx IP configuration - offsets */ +/* IP configuration - offsets */ #define CONFIG_FLOW_CONTROL_ADD 0xC0 #define TRANSMITTER_ADDRESS 0x80 #define RECEIVER1_ADDRESS 0x40 @@ -94,18 +100,30 @@ #define CLINE_ALIGN(_x) (((_x) + CLINE_SIZE - 1) & CLINE_MASK) #define CLINE_PACKETS(_x) (CLINE_ALIGN(_x) >> CLINE_SHIFT) +/* Flush */ +#define CL1FLUSH __asm__ volatile (".byte 0x0F; .byte 0x0A;\n") + +/* Read 16bit from buffer */ +#define U16(_addr) (256 * (*((uint8_t*) (_addr + 1))) + (*((uint8_t*)(_addr)))) + #define MAC_ADDRESS 0x00454D414331ULL #define MAC_HI(_x) ((((_x) >> 32)) & 0xFFFF) #define MAC_LO(_x) (((_x) ) & 0xFFFFFFFF) -static struct netif* mynetif[4] = {NULL, NULL, NULL, NULL}; +static struct netif* mynetif; -static inline int read_emac(int num_emac, int offset, int core) +static int read_emac(int num_emac, int offset, int core) { - return *((volatile int*) (FPGA_BASE + num_emac * 0x1000 + offset + core * 4)); + int ret; + + ret = *((volatile int*) (FPGA_BASE + num_emac * 0x1000 + offset + core * 4)); + /* no error: read twice, as xilinx ip need some time... */ + ret = *((volatile int*) (FPGA_BASE + num_emac * 0x1000 + offset + core * 4)); + + return ret; } -static inline void write_emac(int num_emac, int offset, int core, int value) +static void write_emac(int num_emac, int offset, int core, int value) { *((volatile int*) (FPGA_BASE + num_emac * 0x1000 + offset + core * 4)) = value; } @@ -121,14 +139,14 @@ static err_t rckemacif_output(struct netif* netif, struct pbuf* p) rckemacif_t* rckemacif = netif->state; uint32_t i; struct pbuf *q; - void *addr = NULL; - uint16_t read_offset = 0; - int rest = 0; - int packets = 0; + void *addr; + uint16_t read_offset; + int rest; + int packets; int sum = 0; /* check for over/underflow */ - if (BUILTIN_EXPECT(p->tot_len > 1536, 0)) { + if (BUILTIN_EXPECT((p->tot_len < 20) || (p->tot_len > 1536), 0)) { LWIP_DEBUGF(NETIF_DEBUG, ("rckemacif_output: illegal packet length %d => drop\n", p->len)); return ERR_IF; } @@ -170,8 +188,8 @@ again: * q traverses through linked list of pbuf's * This list MUST consist of a single packet ONLY */ - for (q = p, i = 0; q != 0; q = q->next) { - memcpy(addr + 2 + i, q->payload, q->len); + for (q=p, i=0; q!=0; q=q->next) { + memcpy(((uint8_t*)addr) + 2 + i, q->payload, q->len); i += q->len; } @@ -193,7 +211,7 @@ again: q = p; i = 0; while ((q != 0) && (i < bytes_to_copy)) { sz = q->len > bytes_to_copy-i ? bytes_to_copy-i : q->len; - memcpy(addr + 2 + i, q->payload, sz); + memcpy(((uint8_t*) addr) + 2 + i, q->payload, sz); bytes_left -= sz; i += sz; if (i < bytes_to_copy) @@ -207,12 +225,12 @@ again: i = 0; if (sz < q->len) { - memcpy(addr, q->payload + sz, q->len - sz); + memcpy((uint8_t*) addr, q->payload + sz, q->len - sz); bytes_left -= (q->len - sz); i = q->len - sz; } for(q=q->next; (q != 0); q = q->next) { - memcpy(addr+i, q->payload, q->len); + memcpy(((uint8_t*) addr) + i, q->payload, q->len); i += q->len; } @@ -228,8 +246,7 @@ again: *((volatile int*) rckemacif->tx_buffer) = 2; /* set new write offset */ - LWIP_DEBUGF(NETIF_DEBUG, ("Update tx write offset: %d (read offset %d)\n", rckemacif->tx_write_offset, read_offset)); - + //LWIP_DEBUGF(NETIF_DEBUG, ("Update tx write offset: %d (read offset %d)\n", rckemacif->tx_write_offset, read_offset)); write_emac(rckemacif->num_emac, EMAC_TX_CONTROL+EMAC_TX_BUFFER_WRITE_OFFSET, rckemacif->core, rckemacif->tx_write_offset); #if ETH_PAD_SIZE @@ -241,151 +258,177 @@ again: return ERR_OK; } -#if 0 -static void rtl_rx_inthandler(struct netif* netif) +static void rckemacif_rx_handler(struct netif* netif, unsigned int write_offset) { - rtl1839if_t* rtl8139if = netif->state; - uint16_t header; - uint16_t length, i; - uint8_t cmd; - struct pbuf *p = NULL; + rckemacif_t* rckemacif = netif->state; + unsigned short read_offset; + unsigned int counter; + volatile void *addr; + uint16_t i, length; + struct pbuf *p; struct pbuf* q; - cmd = inportb(rtl8139if->iobase + CR); - while(!(cmd & CR_BUFE)) { - header = *((uint16_t*) (rtl8139if->rx_buffer+rtl8139if->rx_pos)); - rtl8139if->rx_pos = (rtl8139if->rx_pos + 2) % (8192+16); + if (write_offset > rckemacif->rx_buffer_max) { + LWIP_DEBUGF(NETIF_DEBUG, ("Warning, write offset > buffer max!! (%d > %d)\n", write_offset, rckemacif->rx_buffer_max)); + read_offset = 1; + write_emac(rckemacif->num_emac, EMAC_RX_CONTROL + EMAC_RX_BUFFER_READ_OFFSET, rckemacif->core, read_offset); + rckemacif->rx_read_offset = read_offset; + return; + } + + while(1) { + if ((write_offset != 0) && (rckemacif->rx_read_offset != write_offset)) { + read_offset = rckemacif->rx_read_offset; + read_offset++; + if (read_offset < 1 || read_offset > rckemacif->rx_buffer_max) { + read_offset = 1; + } + addr = rckemacif->rx_buffer + read_offset * 32; + + length = U16(addr); + + // Check for over/underflow + if ((length < 20) || (length > 1536)) { + LWIP_DEBUGF(NETIF_DEBUG, ("rckemacif_rx_handler(): illegal packet length %d => drop\n", length)); + LWIP_DEBUGF(NETIF_DEBUG, ("start read at %d; write_offset at %d; addr: %p, packet len: %d\n", read_offset, write_offset, addr, length)); + + read_offset = write_offset; +#if 1 + kprintf("Buffer:\n"); + for (i = 0; i < 32; i++) { + kprintf("%2.2x ", ((char*)addr)[i] & 0xFF); + } + kprintf("\n"); + + kprintf("Buffer0:\n"); + for (i = 0; i < 32; i++) { + kprintf("%2.2x ", ((char*)rckemacif->rx_buffer)[i] & 0xFF); + } + kprintf("\n"); +#endif + + LINK_STATS_INC(link.memerr); + LINK_STATS_INC(link.drop); + + goto rxDone; + } - if (header & ISR_ROK) { - length = *((uint16_t*) (rtl8139if->rx_buffer+rtl8139if->rx_pos)) - 4; // copy packet (but not the CRC) - rtl8139if->rx_pos = (rtl8139if->rx_pos + 2) % (8192+16); #if ETH_PAD_SIZE length += ETH_PAD_SIZE; /* allow room for Ethernet padding */ #endif + //LWIP_DEBUGF(NETIF_DEBUG, ("length %u, read_offset %u, write_offset %u\n", length, read_offset, write_offset)); p = pbuf_alloc(PBUF_RAW, length, PBUF_POOL); if (p) { #if ETH_PAD_SIZE pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */ #endif - for (q=p; q!=NULL; q=q->next) { - for(i=0; ilen; i++) { - ((uint8_t*) q->payload)[i] = rtl8139if->rx_buffer[rtl8139if->rx_pos]; - rtl8139if->rx_pos = (rtl8139if->rx_pos + 1) % (8192+16); - } - } + if (read_offset < write_offset) { + for (q=p, counter=0; q!=NULL; q=q->next) { + for(i=0; ilen; i++, counter++) { + ((uint8_t*) q->payload)[i] = ((uint8_t*)addr)[2 + counter]; + } + } + + read_offset += CLINE_PACKETS(p->len + 2) - 1; + } else { + int rest; + int bytesLeft = length; + int bytesToCopy = length; + + /* rest to the end of buffer - 2 bytes length information */ + rest = (rckemacif->rx_buffer_max - read_offset + 1) * 32 - 2; + if (length > rest) + bytesToCopy = rest; + LWIP_DEBUGF(NETIF_DEBUG, ("bytes to copy: %d, bytesLeft: %d\n", bytesToCopy, bytesLeft)); + + for (q=p, counter=0; q!=NULL; q=q->next) { + for(i=0; ilen; i++, counter++) { + if (counter < bytesToCopy) + ((uint8_t*) q->payload)[i] = ((uint8_t*)addr)[2 + counter]; + else + goto out; + } + } +out: + bytesLeft -= bytesToCopy; + + if (bytesLeft != 0) { + addr = rckemacif->rx_buffer + 0x20; + LWIP_DEBUGF(NETIF_DEBUG, ("copying from %p, left: %d (%x)\n", addr, bytesLeft, ((uint8_t*)addr)[0])); + for(counter=0; (ilen) && (counter < bytesLeft); i++, counter++) + ((uint8_t*) q->payload)[i] = ((uint8_t*)addr)[counter]; + for(q=q->next; (q!=NULL) && (counter < bytesLeft); q=q->next) { + for(i=0; (ilen) && (counter < bytesLeft); i++, counter++) { + ((uint8_t*) q->payload)[i] = ((uint8_t*)addr)[counter]; + } + } + read_offset = CLINE_PACKETS(bytesLeft); + } else { + read_offset += CLINE_PACKETS(p->len + 2) - 1; + } + } + #if ETH_PAD_SIZE pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */ #endif - mailbox_ptr_post(&rtl8139if->mbox, (void*)p); - //rtl8139if_input(netif, p); + mailbox_ptr_post(&rckemacif->mbox, (void*)p); LINK_STATS_INC(link.recv); } else { - LWIP_DEBUGF(NETIF_DEBUG, ("rtl8139if_rx_inthandler: not enough memory!\n")); - rtl8139if->rx_pos += (rtl8139if->rx_pos + length) % (8192+16); + LWIP_DEBUGF(NETIF_DEBUG, ("rckemacif_rx_inthandler: not enough memory!\n")); LINK_STATS_INC(link.memerr); LINK_STATS_INC(link.drop); } - // packets are dword aligned - rtl8139if->rx_pos = ((rtl8139if->rx_pos + 4 + 3) & ~0x3) % (8192+16); - outportw(rtl8139if->iobase + CAPR, rtl8139if->rx_pos - 0x10); - } else { - LWIP_DEBUGF(NETIF_DEBUG, ("rtl8139if_rx_inthandler: invalid header!\n")); - LINK_STATS_INC(link.memerr); - LINK_STATS_INC(link.drop); - break; - } - - cmd = inportb(rtl8139if->iobase + CR); +rxDone: + /* set new read pointer */ + //LWIP_DEBUGF(NETIF_DEBUG, ("Update rx read offset: %d\n", read_offset)); + write_emac(rckemacif->num_emac, EMAC_RX_CONTROL + EMAC_RX_BUFFER_READ_OFFSET, rckemacif->core, read_offset); + rckemacif->rx_read_offset = read_offset; + } else break; } } -static void rtl_tx_inthandler(struct netif* netif) -{ - rtl1839if_t* rtl8139if = netif->state; - uint32_t checks = rtl8139if->tx_queue - rtl8139if->tx_complete; - uint32_t txstatus; - uint8_t tmp8; - - while(checks > 0) - { - tmp8 = rtl8139if->tx_complete % 4; - txstatus = inportl(rtl8139if->iobase + TSD0 + tmp8 * 4); - - if (!(txstatus & (TSD_TOK|TSD_TUN|TSD_TABT))) - return; - - if (txstatus & (TSD_TABT | TSD_OWC)) { - LWIP_DEBUGF(NETIF_DEBUG, ("rtl8139_tx_inthandler: major error\n")); - continue; - } - - if (txstatus & TSD_TUN) { - LWIP_DEBUGF(NETIF_DEBUG, ("rtl8139_tx_inthandler: transmit underrun\n")); - } - - if (txstatus & TSD_TOK) { - rtl8139if->tx_inuse[tmp8] = 0; - rtl8139if->tx_complete++; - checks--; - } - } -} -#endif - static void rckemacif_handler(struct state* s) { - LWIP_DEBUGF(NETIF_DEBUG, ("HELLO! Got interrupt!\n")); + unsigned int status, tmp; + unsigned int write_offset; + rckemacif_t* rckemacif = mynetif->state; -#if 0 - rtl1839if_t* rtl8139if = mynetif->state; - uint16_t isr_contents; - - while (1) { - isr_contents = inportw(rtl8139if->iobase + ISR); - if (isr_contents == 0) - break; - - if (isr_contents & ISR_ROK) { - rtl_rx_inthandler(mynetif); - outportw(rtl8139if->iobase + ISR, ISR_ROK); - } - - if (isr_contents & ISR_TOK) { - rtl_tx_inthandler(mynetif); - outportw(rtl8139if->iobase + ISR, ISR_TOK); - } - - if (isr_contents & ISR_RER) { - LWIP_DEBUGF(NETIF_DEBUG, ("rtl8139if_handler: RX error detected!\n")); - outportw(rtl8139if->iobase + ISR, ISR_RER); - } - - if (isr_contents & ISR_TER) { - LWIP_DEBUGF(NETIF_DEBUG, ("rtl8139if_handler: TX error detected!\n")); - outportw(rtl8139if->iobase + ISR, ISR_TER); - } - - if (isr_contents & ISR_RXOVW) { - LWIP_DEBUGF(NETIF_DEBUG, ("rtl8139if_handler: RX overflow detected!\n")); - outportw(rtl8139if->iobase + ISR, ISR_RXOVW); - } + status = *((volatile int*) (FPGA_BASE + IRQ_STATUS + rckemacif->core * 2 * 4)); + // read twice to be sure + status = *((volatile int*) (FPGA_BASE + IRQ_STATUS + rckemacif->core * 2 * 4)); + if (!(status & (1 << rckemacif->num_emac))) { + LWIP_DEBUGF(NETIF_DEBUG, ("rckemacif_handler: no interrupt\n")); + return; } -#endif + +nexttry: + /* check for updated write offset */ + CL1FLUSH; + write_offset = *((volatile unsigned int*) (rckemacif->rx_buffer)) & 0xFFFF; + //write_offset = read_emac(rckemacif->num_emac, EMAC_RX_CONTROL + EMAC_RX_BUFFER_WRITE_OFFSET, rckemacif->core); + if ((write_offset != 0) && (rckemacif->rx_read_offset != write_offset)) { + rckemacif_rx_handler(mynetif, write_offset); + goto nexttry; + } + + /* Set interrupt bit */ + tmp = *((volatile unsigned int*) rckemacif->irq_address); + tmp &= ~(EMAC_IRQ_MASK); + *((volatile unsigned int*) rckemacif->irq_address) = tmp; + + /* Reset */ + *((volatile unsigned*) (FPGA_BASE + IRQ_RESET + rckemacif->core * 2 * 4)) = (1 << rckemacif->num_emac); } err_t rckemacif_wait(struct netif* netif, uint32_t poll) { - return ERR_OK; -#if 0 rckemacif_t* rckemacif = netif->state; struct eth_hdr *ethhdr; struct pbuf *p = NULL; err_t err = ERR_OK; - LWIP_DEBUGF(NETIF_DEBUG, ("Hello from rckemacif_wait!\n")); - if (poll) { if (mailbox_ptr_tryfetch(&(rckemacif->mbox), (void**) &p)) return err; @@ -396,6 +439,8 @@ err_t rckemacif_wait(struct netif* netif, uint32_t poll) /* points to packet payload, which starts with an Ethernet header */ ethhdr = p->payload; + //LWIP_DEBUGF(NETIF_DEBUG, ("Got packet of type 0x%x!\n", htons(ethhdr->type))); + switch (htons(ethhdr->type)) { /* IP or ARP packet? */ case ETHTYPE_ARP: @@ -406,7 +451,7 @@ err_t rckemacif_wait(struct netif* netif, uint32_t poll) case ETHTYPE_PPPOE: #endif /* PPPOE_SUPPORT */ /* full packet send to tcpip_thread to process */ - if ((err = mynetif[netif->num]->input(p, mynetif[netif->num])) != ERR_OK) { + if ((err = mynetif->input(p, mynetif)) != ERR_OK) { LWIP_DEBUGF(NETIF_DEBUG, ("rckemacif_poll: IP input error\n")); pbuf_free(p); } @@ -417,21 +462,20 @@ err_t rckemacif_wait(struct netif* netif, uint32_t poll) } return err; -#endif } err_t rckemacif_init(struct netif* netif) { rckemacif_t* rckemacif; - int num, num_emac; + int num_emac; int macPorts; int i, tmp, x, y, z, core; uint64_t tile_offset; - uint16_t write_offset = 0; - uint16_t read_offset = 0; - int mode = 0; - int subdest = 0; - int route = 0; + uint16_t write_offset; + uint16_t read_offset; + int mode; + int subdest; + int route; LWIP_ASSERT("netif != NULL", (netif != NULL)); @@ -457,7 +501,8 @@ err_t rckemacif_init(struct netif* netif) kfree(rckemacif, sizeof(rckemacif_t)); return ERR_MEM; } - memset(rckemacif->rx_buffer, 0, BUFFER_SIZE); + memset(rckemacif->rx_buffer, 0x00, 0x20); + memset(rckemacif->rx_buffer + 0x20, 0xDA, BUFFER_SIZE - 0x20); rckemacif->rx_buffer_max = CLINE_PACKETS(BUFFER_SIZE) - 1; /* allocate the send buffers */ @@ -468,7 +513,8 @@ err_t rckemacif_init(struct netif* netif) kfree(rckemacif, sizeof(rckemacif_t)); return ERR_MEM; } - memset(rckemacif->tx_buffer, 0, BUFFER_SIZE); + memset(rckemacif->tx_buffer, 0x00, 0x20); + memset(rckemacif->tx_buffer + 0x20, 0xDA, BUFFER_SIZE - 0x20); rckemacif->tx_buffer_max = CLINE_PACKETS(BUFFER_SIZE) - 1; mailbox_ptr_init(&rckemacif->mbox); @@ -478,42 +524,42 @@ err_t rckemacif_init(struct netif* netif) * (offset, subdest, route) */ if (z == 0) { - tmp = ReadConfigReg(CRB_OWN + GLCFG0); - rckemacif->irq_address = CRB_OWN + GLCFG0; + tmp = ReadConfigReg(CRB_OWN + LUT0); + rckemacif->irq_address = (void*) (CRB_OWN + GLCFG0); } else { - tmp = ReadConfigReg(CRB_OWN + GLCFG1); - rckemacif->irq_address = CRB_OWN + GLCFG1; + tmp = ReadConfigReg(CRB_OWN + LUT1); + rckemacif->irq_address = (void*) (CRB_OWN + GLCFG1); } - tile_offset = (unsigned long long)((unsigned long long) tmp & 0x3FF) << 24; + tile_offset = (uint64_t)((uint64_t) tmp & 0x3FF) << 24; subdest = (tmp >> 10) & 0x07; route = (tmp >> 13) & 0xFF; mode = (subdest << 8) + route; + LWIP_DEBUGF(NETIF_DEBUG, ("tile_offset = 0x%llx\n", tile_offset)); /* get fpga/sccKit port settings */ tmp = *((volatile int*)(FPGA_BASE + 0x822C)); + tmp = *((volatile int*)(FPGA_BASE + 0x822C)); macPorts = ((tmp >> 9 ) & 0xFF); - LWIP_DEBUGF(NETIF_DEBUG, ("rckemacif_init: eMAC0: %s eMAC1: %s eMAC2: %s eMAC3: %s\n", - (macPorts & EMAC0) != 0 ? "present" : "-", - (macPorts & EMAC1) != 0 ? "present" : "-", - (macPorts & EMAC2) != 0 ? "present" : "-", - (macPorts & EMAC3) != 0 ? "present" : "-")); + LWIP_DEBUGF(NETIF_DEBUG, ("rckemacif_init: eMAC0: %s eMAC1: %s eMAC2: %s eMAC3: %s\n", + (macPorts & EMAC0) != 0 ? "present" : "-", + (macPorts & EMAC1) != 0 ? "present" : "-", + (macPorts & EMAC2) != 0 ? "present" : "-", + (macPorts & EMAC3) != 0 ? "present" : "-")); // determine device and emac number - for(num=0; (num<4) && (mynetif[num] != NULL); num++) - ; - if (num >= 4) - return ERR_ARG; - for(i=0, num_emac=0; (i<=num) && (num_emac < 4); i++) { - while (((macPorts & (1 << num_emac)) == 0) && (num_emac < 4)) - num_emac++; - } + num_emac=0; + while (((macPorts & (1 << num_emac)) == 0) && (num_emac < 4)) + num_emac++; if (num_emac >= 4) return ERR_ARG; - mynetif[num] = netif; + mynetif = netif; rckemacif->num_emac = num_emac; - LWIP_DEBUGF(NETIF_DEBUG, ("rckemacif_init: map device %d to eMAC %d\n", num, num_emac)); + LWIP_DEBUGF(NETIF_DEBUG, ("rckemacif_init: used eMAC device %d\n", num_emac)); + + tmp = read_emac(num_emac, EMAC_IPCONF+TRANSMITTER_ADDRESS, 0); + tmp = read_emac(num_emac, EMAC_IPCONF+RECEIVER1_ADDRESS, 0); if (core == 0) { /* Only core 0 initialize the xilinx port */ @@ -524,23 +570,23 @@ err_t rckemacif_init(struct netif* netif) int add_filter_mod = 0; /* Disable tx and rx flow control of eMAC */ - LWIP_DEBUGF(NETIF_DEBUG, ("Disabling tx/rx flow control of eMAC%d\n", num_emac)); - flow_control = read_emac(num_emac, EMAC_IPCONF+CONFIG_FLOW_CONTROL_ADD, 0); + LWIP_DEBUGF(NETIF_DEBUG, ("Disabling tx/rx flow control of eMAC%d\n", num_emac)); + flow_control = read_emac(num_emac, EMAC_IPCONF+CONFIG_FLOW_CONTROL_ADD, 0); /* Set top 3 bits of the flow control configuration to zero, * therefore disabling tx and rx flow control */ flow_control &= 0x7FFFFFF; - write_emac(num_emac, EMAC_IPCONF+CONFIG_FLOW_CONTROL_ADD, 0, flow_control); + write_emac(num_emac, EMAC_IPCONF+CONFIG_FLOW_CONTROL_ADD, 0, flow_control); /* Sanity check */ flow_control = read_emac(num_emac, EMAC_IPCONF+CONFIG_FLOW_CONTROL_ADD, 0); - LWIP_DEBUGF(NETIF_DEBUG, (" CONFIG_FLOW_CONTROL_ADD set: 0x%x\n", flow_control)); + LWIP_DEBUGF(NETIF_DEBUG, (" CONFIG_FLOW_CONTROL_ADD set: 0x%x\n", flow_control)); /* Setting the tx configuration bit to enable the transmitter and * set to full duplex mode. */ - LWIP_DEBUGF(NETIF_DEBUG, ("Setting rx configuration of eMAC%d\n", num_emac)); + LWIP_DEBUGF(NETIF_DEBUG, ("Setting rx configuration of eMAC%d\n", num_emac)); transmitter_addr = read_emac(num_emac, EMAC_IPCONF+TRANSMITTER_ADDRESS, 0); /* Now set the relevant bits and write back into the register: @@ -552,7 +598,7 @@ err_t rckemacif_init(struct netif* netif) write_emac(num_emac, EMAC_IPCONF+TRANSMITTER_ADDRESS, 0, transmitter_addr); transmitter_addr = read_emac(num_emac, EMAC_IPCONF+TRANSMITTER_ADDRESS, 0); - LWIP_DEBUGF(NETIF_DEBUG, (" TRANSMITTER_ADDRESS set: %x\n", transmitter_addr)); + LWIP_DEBUGF(NETIF_DEBUG, (" TRANSMITTER_ADDRESS set: %x\n", transmitter_addr)); /* Setting the rx configuration bit to enable the transmitter and * set to full duplex mode. @@ -602,32 +648,29 @@ err_t rckemacif_init(struct netif* netif) * 31 (promiscuous mode) = 1 not working, but thats ok! */ add_filter_mod |= (1 << 31); - write_emac(num_emac, EMAC_IPCONF+ADD_FILTER_MOD, 0, add_filter_mod); + write_emac(num_emac, EMAC_IPCONF+ADD_FILTER_MOD, 0, add_filter_mod); - add_filter_mod = read_emac(num_emac, EMAC_IPCONF+ADD_FILTER_MOD, 0); + add_filter_mod = read_emac(num_emac, EMAC_IPCONF+ADD_FILTER_MOD, 0); LWIP_DEBUGF(NETIF_DEBUG, (" ADD_FILTER_MOD set: %x\n", add_filter_mod)); } sleep(3); /* Start address */ - LWIP_DEBUGF(NETIF_DEBUG, (" RX Buffer %p (%lx phys)\n", rckemacif->rx_buffer, virt_to_phys(rckemacif->rx_buffer))); + LWIP_DEBUGF(NETIF_DEBUG, (" RX Buffer %p (%lx phys)\n", rckemacif->rx_buffer, virt_to_phys((uint32_t)rckemacif->rx_buffer))); /**** Receiver configuration ****/ - uint32_t utmp = virt_to_phys(rckemacif->rx_buffer); - uint32_t addr_offset = tile_offset + utmp; - addr_offset >>= 5; - write_emac(num_emac, EMAC_RX_CONTROL + EMAC_RX_BUFFER_START_ADDRESS, core, addr_offset); - utmp = read_emac(num_emac, EMAC_RX_CONTROL + EMAC_RX_BUFFER_START_ADDRESS, core); - LWIP_DEBUGF(NETIF_DEBUG, (" RX Buffer set to @%x\n", utmp)); + uint64_t addr_offset = (tile_offset + (uint64_t) virt_to_phys((uint32_t) rckemacif->rx_buffer)) >> 5; + write_emac(num_emac, EMAC_RX_CONTROL + EMAC_RX_BUFFER_START_ADDRESS, core, (uint32_t) addr_offset); + LWIP_DEBUGF(NETIF_DEBUG, (" RX Buffer set to @%x\n", read_emac(num_emac, EMAC_RX_CONTROL + EMAC_RX_BUFFER_START_ADDRESS, core))); - /* Set buffer write offset */ + /* Get buffer write offset */ write_offset = read_emac(num_emac, EMAC_RX_CONTROL + EMAC_RX_BUFFER_WRITE_OFFSET, core); - LWIP_DEBUGF(NETIF_DEBUG, (" RX Buffer write offset at: %d\n", write_offset)); + LWIP_DEBUGF(NETIF_DEBUG, (" RX Buffer write offset at: %d\n", write_offset)); /* Set buffer read offset to write offset */ - write_emac(num_emac, EMAC_RX_CONTROL + EMAC_RX_BUFFER_READ_OFFSET, core, write_offset); + write_emac(num_emac, EMAC_RX_CONTROL + EMAC_RX_BUFFER_READ_OFFSET, core, write_offset); LWIP_DEBUGF(NETIF_DEBUG, (" RX Buffer read offset set to: %d\n", read_emac(num_emac, EMAC_RX_CONTROL + EMAC_RX_BUFFER_READ_OFFSET, core))); rckemacif->rx_read_offset = write_offset; @@ -637,49 +680,46 @@ err_t rckemacif_init(struct netif* netif) /* Threshold */ write_emac(num_emac, EMAC_RX_CONTROL + EMAC_RX_BUFFER_THRESHOLD, core, 0x01); - LWIP_DEBUGF(NETIF_DEBUG, (" RX Threshold set to %x\n", read_emac(num_emac, EMAC_RX_CONTROL + EMAC_RX_BUFFER_THRESHOLD, core))); + LWIP_DEBUGF(NETIF_DEBUG, (" RX Threshold set to %x\n", read_emac(num_emac, EMAC_RX_CONTROL + EMAC_RX_BUFFER_THRESHOLD, core))); /* Route */ - write_emac(num_emac, EMAC_RX_CONTROL + EMAC_RX_MODE, core, (core << 24) | (((y << 4) | x) << 16) | mode); + write_emac(num_emac, EMAC_RX_CONTROL + EMAC_RX_MODE, core, (z << 24) | (((y << 4) | x) << 16) | mode); LWIP_DEBUGF(NETIF_DEBUG, (" RX Mode set to %x\n", read_emac(num_emac, EMAC_RX_CONTROL + EMAC_RX_MODE, core))); // determine mac address - uint32_t mac1 = *((uint32_t*)(FPGA_BASE+0x7E00)); - uint32_t mac2 = *((uint32_t*)(FPGA_BASE+0x7E04)); - uint64_t mac = (((unsigned long long)mac1) << 32) + ( unsigned long long ) mac2; + uint32_t mac1 = *((volatile uint32_t*)(FPGA_BASE+0x7E00)); + uint32_t mac2 = *((volatile uint32_t*)(FPGA_BASE+0x7E04)); + uint64_t mac = (((unsigned long long)mac1) << 32) + (unsigned long long) mac2; if (mac == 0x00) mac = MAC_ADDRESS; /* Calculate mac address of core depending on selected emac device */ mac = mac + (1 << num_emac) * 0x100 + core; + for (i=0; i<6; i++) + mynetif->hwaddr[5-i] = (mac >> (i*8)) & 0xFF; LWIP_DEBUGF(NETIF_DEBUG, ("rckemacif_init: MAC address ")); - for (i=0; i<6; i++) { - mynetif[num]->hwaddr[i] = mac & 0xFF; - mac = mac >> 8; - LWIP_DEBUGF(NETIF_DEBUG, ("%02x ", mynetif[num]->hwaddr[i])); - } + for (i=0; i<6; i++) + LWIP_DEBUGF(NETIF_DEBUG, ("%02x ", mynetif->hwaddr[i])); LWIP_DEBUGF(NETIF_DEBUG, ("\n")); write_emac(num_emac, EMAC_RX_CONTROL + EMAC_RX_NETWORK_PORT_MAC_ADDRESS_HI, core, MAC_HI(mac)); - LWIP_DEBUGF(NETIF_DEBUG, (" MAC1 set to %x\n", read_emac(num_emac, EMAC_RX_CONTROL + EMAC_RX_NETWORK_PORT_MAC_ADDRESS_HI, core))); - write_emac(num_emac, EMAC_RX_CONTROL + EMAC_RX_NETWORK_PORT_MAC_ADDRESS_LO, core, MAC_LO(mac)); - LWIP_DEBUGF(NETIF_DEBUG, (" MAC2 set to %x\n", read_emac(num_emac, EMAC_RX_CONTROL + EMAC_RX_NETWORK_PORT_MAC_ADDRESS_LO, core))); + LWIP_DEBUGF(NETIF_DEBUG, (" MAC1 set to %x\n", read_emac(num_emac, EMAC_RX_CONTROL + EMAC_RX_NETWORK_PORT_MAC_ADDRESS_HI, core))); + write_emac(num_emac, EMAC_RX_CONTROL + EMAC_RX_NETWORK_PORT_MAC_ADDRESS_LO, core, MAC_LO(mac)); + LWIP_DEBUGF(NETIF_DEBUG, (" MAC2 set to %x\n", read_emac(num_emac, EMAC_RX_CONTROL + EMAC_RX_NETWORK_PORT_MAC_ADDRESS_LO, core))); - /* Activate network port by setting enable bit */ - write_emac(num_emac, EMAC_RX_CONTROL + EMAC_RX_NETWORK_PORT_ENABLE, core, 0x01); - LWIP_DEBUGF(NETIF_DEBUG, (" RX Port enable set to %x\n", read_emac(num_emac, EMAC_RX_CONTROL + EMAC_RX_NETWORK_PORT_ENABLE, core))); + /* Activate network port by setting enable bit */ + write_emac(num_emac, EMAC_RX_CONTROL + EMAC_RX_NETWORK_PORT_ENABLE, core, 0x01); + LWIP_DEBUGF(NETIF_DEBUG, (" RX Port enable set to %x\n", read_emac(num_emac, EMAC_RX_CONTROL + EMAC_RX_NETWORK_PORT_ENABLE, core))); /**** Transfer configuration ****/ /* Start address */ - LWIP_DEBUGF(NETIF_DEBUG, (" TX Buffer %p (%lx phys)\n", rckemacif->tx_buffer, virt_to_phys(rckemacif->tx_buffer))); - utmp = virt_to_phys(rckemacif->tx_buffer); - write_emac(num_emac, EMAC_TX_CONTROL + EMAC_TX_BUFFER_START_ADDRESS, core, (tmp + tile_offset) >> 5); - utmp = read_emac(num_emac, EMAC_TX_CONTROL + EMAC_TX_BUFFER_START_ADDRESS, core); - LWIP_DEBUGF(NETIF_DEBUG, (" TX Buffer set to @%x\n", tmp)); + LWIP_DEBUGF(NETIF_DEBUG, (" TX Buffer %p (%lx phys)\n", rckemacif->tx_buffer, virt_to_phys((uint32_t)rckemacif->tx_buffer))); + write_emac(num_emac, EMAC_TX_CONTROL + EMAC_TX_BUFFER_START_ADDRESS, core, (uint32_t) (((uint64_t) virt_to_phys((uint32_t)rckemacif->tx_buffer) + tile_offset) >> 5)); + LWIP_DEBUGF(NETIF_DEBUG, (" TX Buffer set to @%x\n", read_emac(num_emac, EMAC_TX_CONTROL + EMAC_TX_BUFFER_START_ADDRESS, core))); - /* Get buffer read offset */ - read_offset = read_emac(num_emac, EMAC_TX_CONTROL + EMAC_TX_BUFFER_READ_OFFSET, core); + /* Get buffer read offset */ + read_offset = read_emac(num_emac, EMAC_TX_CONTROL + EMAC_TX_BUFFER_READ_OFFSET, core); LWIP_DEBUGF(NETIF_DEBUG, (" TX Buffer read offset at: %d\n", read_offset)); /* Set buffer write offset to read offset */ @@ -717,7 +757,7 @@ err_t rckemacif_init(struct netif* netif) /* administrative details */ netif->name[0] = 'e'; netif->name[1] = 'n'; - netif->num = num; + netif->num = 0; /* downward functions */ netif->output = etharp_output; netif->linkoutput = rckemacif_output; diff --git a/drivers/net/rckemac.h b/drivers/net/rckemac.h index b8a8a5ae..2c53523f 100644 --- a/drivers/net/rckemac.h +++ b/drivers/net/rckemac.h @@ -31,10 +31,10 @@ typedef struct rckemacif { struct eth_addr *ethaddr; /* Add whatever per-interface state that is needed here. */ - uint8_t* tx_buffer; uint8_t* rx_buffer; uint32_t rx_buffer_max; uint32_t rx_read_offset; + uint8_t* tx_buffer; uint32_t tx_buffer_max; uint32_t tx_write_offset; void* irq_address;