add first functional version of the eMAC driver
- this driver required at least sccKit 1.4.0
This commit is contained in:
parent
19fffd46c5
commit
f8be2e3483
3 changed files with 238 additions and 198 deletions
|
@ -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
|
||||
|
||||
|
|
|
@ -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 <metalsvm/stddef.h>
|
||||
#include <metalsvm/stdio.h>
|
||||
#include <metalsvm/string.h>
|
||||
|
@ -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; i<q->len; 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; i<q->len; 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; i<q->len; 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; (i<q->len) && (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; (i<q->len) && (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;
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Add table
Reference in a new issue