diff --git a/drivers/net/rckemac.c b/drivers/net/rckemac.c index 4d6d03e5..07b538ad 100644 --- a/drivers/net/rckemac.c +++ b/drivers/net/rckemac.c @@ -347,15 +347,18 @@ static void rckemacif_input(struct netif* netif, struct pbuf* p) case ETHTYPE_PPPOEDISC: case ETHTYPE_PPPOE: #endif /* PPPOE_SUPPORT */ - /* full packet send to tcpip_thread to process */ - if ((err = mynetif->input(p, mynetif)) != ERR_OK) { - LWIP_DEBUGF(NETIF_DEBUG, ("rckemacif_input: IP input error %d\n", (int32_t) err)); - pbuf_free_callback(p); + /* + * This function is called in the context of the tcpip thread. + * Therefore, we are able to call directly the input functions. + */ + err = ethernet_input(p, netif); + if (err != ERR_OK) { + LWIP_DEBUGF(NETIF_DEBUG, ("rckemacif_input: ethernet_input failed %d\n", err)); } break; default: - LWIP_DEBUGF(NETIF_DEBUG, ("rckemacif_input: invalid ethernet header: 0x%x\n", htons(ethhdr->type))); - pbuf_free_callback(p); + LWIP_DEBUGF(NETIF_DEBUG, ("rckemacif_input: invalid ethernet header 0x%x\n", htons(ethhdr->type))); + pbuf_free(p); break; } } @@ -498,6 +501,19 @@ rxDone: if (read_offset != write_offset) goto again; + + /* Enable eMAC interrupt */ + int tmp = *((volatile int*) (FPGA_BASE + IRQ_MASK + rckemacif->core * 2 * 4)); + *((volatile int*) (FPGA_BASE + IRQ_MASK + rckemacif->core * 2 * 4)) = tmp & ~(1 << rckemacif->num_emac); + rckemacif->polling = 0; +} + +/* this function is called in the context of the tcpip thread */ +static void rckemacif_poll(void* ctx) +{ + unsigned int write_offset = (unsigned int) ctx; + + rckemacif_rx_handler(mynetif, write_offset); } static void rckemacif_handler(struct state* s) @@ -514,13 +530,18 @@ static void rckemacif_handler(struct state* s) return; } -nexttry: /* check for updated write offset */ 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; + if ((write_offset != 0) && (rckemacif->rx_read_offset != write_offset) && !rckemacif->polling) { + if (tcpip_callback_with_block(rckemacif_poll, (void*) write_offset, 0) == ERR_OK) { + /* Maks eMAC interrupt */ + int tmp = *((volatile int*) (FPGA_BASE + IRQ_MASK + rckemacif->core * 2 * 4)); + *((volatile int*) (FPGA_BASE + IRQ_MASK + rckemacif->core * 2 * 4)) = tmp | (1 << rckemacif->num_emac); + rckemacif->polling = 1; + } else { + LWIP_DEBUGF(NETIF_DEBUG, ("rckemacif_handler: unable to send a poll request to the tcpip thread\n")); + } } /* Set interrupt bit */ @@ -561,7 +582,7 @@ err_t rckemacif_init(struct netif* netif) LWIP_DEBUGF(NETIF_DEBUG, ("rckemacif_init: out of memory\n")); return ERR_MEM; } - memset(rckemacif, 0, sizeof(rckemacif_t)); + memset(rckemacif, 0x00, sizeof(rckemacif_t)); rckemacif->core = core; /* allocate the receive buffer */ diff --git a/drivers/net/rckemac.h b/drivers/net/rckemac.h index 2796f14d..f6710594 100644 --- a/drivers/net/rckemac.h +++ b/drivers/net/rckemac.h @@ -39,6 +39,7 @@ typedef struct rckemacif { void* irq_address; uint32_t core; uint32_t num_emac; + volatile uint8_t polling; } rckemacif_t; /* diff --git a/drivers/net/rtl8139.c b/drivers/net/rtl8139.c index fb1127db..de5774e4 100644 --- a/drivers/net/rtl8139.c +++ b/drivers/net/rtl8139.c @@ -38,6 +38,18 @@ #define RX_BUF_LEN 8192 #define TX_BUF_LEN 4096 +#define MIN(a, b) (a) < (b) ? (a) : (b) + +/* + * To set the RTL8139 to accept only the Transmit OK (TOK) and Receive OK (ROK) + * interrupts, we would have the TOK and ROK bits of the IMR high and leave the + * rest low. That way when a TOK or ROK IRQ happens, it actually will go through + * and fire up an IRQ. + */ +#define INT_MASK (ISR_ROK|ISR_TOK|ISR_RXOVW|ISR_TER|ISR_RER) + +// Beside Receive OK (ROK) interrupt, this mask enable all other interrupts +#define INT_MASK_NO_ROK (ISR_TOK|ISR_RXOVW|ISR_TER|ISR_RER) board_t board_tbl[] = { @@ -131,15 +143,18 @@ static void rtl8139if_input(struct netif* netif, struct pbuf* p) case ETHTYPE_PPPOEDISC: case ETHTYPE_PPPOE: #endif /* PPPOE_SUPPORT */ - /* full packet send to tcpip_thread to process */ - err = mynetif->input(p, mynetif); + /* + * This function is called in the context of the tcpip thread. + * Therefore, we are able to call directly the input functions. + */ + err = ethernet_input(p, netif); if (err != ERR_OK) { - LWIP_DEBUGF(NETIF_DEBUG, ("rtl8139if_input: IP input error %d\n", (int32_t) err)); - pbuf_free_callback(p); + LWIP_DEBUGF(NETIF_DEBUG, ("rtl8139if_input: ethernet_input failed %d\n", err)); } break; default: - pbuf_free_callback(p); + LWIP_DEBUGF(NETIF_DEBUG, ("rtl8139_input: invalid ethernet header 0x%x\n", htons(ethhdr->type))); + pbuf_free(p); break; } } @@ -170,11 +185,13 @@ static void rtl_rx_inthandler(struct netif* netif) #if ETH_PAD_SIZE pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */ #endif - for (q=p, i=0; q!=NULL; q=q->next) { - memcpy((uint8_t*) q->payload + i, rtl8139if->rx_buffer + rtl8139if->rx_pos + i, q->len); - i += q->len; - } - rtl8139if->rx_pos = (rtl8139if->rx_pos + p->tot_len) % RX_BUF_LEN; + for (q=p; q!=NULL; q=q->next) { + i = MIN(q->len, RX_BUF_LEN - rtl8139if->rx_pos); + memcpy((uint8_t*) q->payload, rtl8139if->rx_buffer + rtl8139if->rx_pos, i); + if (i < q->len) // wrap around to end of RxBuffer + memcpy((uint8_t*) q->payload + i, rtl8139if->rx_buffer, q->len - i); + rtl8139if->rx_pos = (rtl8139if->rx_pos + q->len) % RX_BUF_LEN; + } #if ETH_PAD_SIZE pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */ #endif @@ -201,6 +218,10 @@ static void rtl_rx_inthandler(struct netif* netif) cmd = inportb(rtl8139if->iobase + CR); } + + rtl8139if->polling = 0; + // enable all known interrupts + outportw(rtl8139if->iobase + IMR, INT_MASK); } static void rtl_tx_inthandler(struct netif* netif) @@ -235,41 +256,55 @@ static void rtl_tx_inthandler(struct netif* netif) } } +/* this function is called in the context of the tcpip thread */ +static void rtl8139if_poll(void* ctx) +{ + rtl_rx_inthandler(mynetif); +} + static void rtl8139if_handler(struct state* s) { rtl1839if_t* rtl8139if = mynetif->state; uint16_t isr_contents; + // disable all interrupts + outportw(rtl8139if->iobase + IMR, 0x00); + 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_ROK) && !rtl8139if->polling) { + if (tcpip_callback_with_block(rtl8139if_poll, NULL, 0) == ERR_OK) { + rtl8139if->polling = 1; + } else { + LWIP_DEBUGF(NETIF_DEBUG, ("rtl8139if_handler: unable to send a poll request to the tcpip thread\n")); + } } - if (isr_contents & ISR_TOK) { + 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); } + + outportw(rtl8139if->iobase + ISR, isr_contents & (ISR_RXOVW|ISR_TER|ISR_RER|ISR_TOK|ISR_ROK)); } + + if (rtl8139if->polling) // now, the tcpip thread will check for incoming messages + outportw(rtl8139if->iobase + IMR, INT_MASK_NO_ROK); + else + outportw(rtl8139if->iobase + IMR, INT_MASK); // enable interrupts } err_t rtl8139if_init(struct netif* netif) @@ -288,10 +323,10 @@ err_t rtl8139if_init(struct netif* netif) LWIP_DEBUGF(NETIF_DEBUG, ("rtl8139if_init: out of memory\n")); return ERR_MEM; } - memset(rtl8139if, 0, sizeof(rtl1839if_t)); + memset(rtl8139if, 0x00, sizeof(rtl1839if_t)); /* allocate the receive buffer */ - rtl8139if->rx_buffer = mem_allocation(RX_BUF_LEN + 1500 /* MTU */ + 16 /* header size */, MAP_KERNEL_SPACE|MAP_NO_CACHE); + rtl8139if->rx_buffer = mem_allocation(RX_BUF_LEN + 16 /* header size */, MAP_KERNEL_SPACE|MAP_NO_CACHE); if (!(rtl8139if->rx_buffer)) { LWIP_DEBUGF(NETIF_DEBUG, ("rtl8139if_init: out of memory\n")); kfree(rtl8139if, sizeof(rtl1839if_t)); @@ -389,7 +424,7 @@ err_t rtl8139if_init(struct netif* netif) * APM - Accept Physical Match: Accept packets send to NIC's MAC address. * AAP - Accept All Packets. Accept all packets (run in promiscuous mode). */ - outportl(rtl8139if->iobase + RCR, RCR_MXDMA2|RCR_MXDMA1|RCR_WRAP|RCR_MXDMA0|RCR_AB|RCR_AM|RCR_APM|RCR_AAP); // The WRAP bit is set! + outportl(rtl8139if->iobase + RCR, RCR_MXDMA2|RCR_MXDMA1|RCR_MXDMA0|RCR_AB|RCR_AM|RCR_APM|RCR_AAP); // The WRAP bit isn't set! // set the transmit config register to // be the normal interframe gap time @@ -405,13 +440,8 @@ err_t rtl8139if_init(struct netif* netif) outportl(rtl8139if->iobase + TSAD2, virt_to_phys((size_t) rtl8139if->tx_buffer[2])); outportl(rtl8139if->iobase + TSAD3, virt_to_phys((size_t) rtl8139if->tx_buffer[3])); - /* - * To set the RTL8139 to accept only the Transmit OK (TOK) and Receive OK (ROK) - * interrupts, we would have the TOK and ROK bits of the IMR high and leave the - * rest low. That way when a TOK or ROK IRQ happens, it actually will go through - * and fire up an IRQ. - */ - outportw(rtl8139if->iobase + IMR, ISR_ROK|ISR_TOK|ISR_RXOVW|ISR_TER|ISR_RER); + // Enable all known interrupts by setting the interrupt mask. + outportw(rtl8139if->iobase + IMR, INT_MASK); outportw(rtl8139if->iobase + BMCR, BMCR_ANE); tmp16 = inportw(rtl8139if->iobase + BMCR); diff --git a/drivers/net/rtl8139.h b/drivers/net/rtl8139.h index 962f5232..d45966bc 100644 --- a/drivers/net/rtl8139.h +++ b/drivers/net/rtl8139.h @@ -148,8 +148,8 @@ // Bits in ISR indicate the status of the card #define ISR_SERR 0x8000 // System error interrupt #define ISR_TUN 0x4000 // time out interrupt -#define ISR__SWInt 0x100 // Software interrupt -#define ISR__TDU 0x80 // Tx Descriptor unavailable +#define ISR_SWInt 0x100 // Software interrupt +#define ISR_TDU 0x80 // Tx Descriptor unavailable #define ISR_FIFOOVW 0x40 // Rx Fifo overflow #define ISR_PUN 0x20 // Packet underrun/link change #define ISR_RXOVW 0x10 // Rx overflow/Rx Descriptor unavailable @@ -227,6 +227,7 @@ typedef struct rtl1839if { uint32_t tx_complete; uint16_t rx_pos; uint8_t tx_inuse[4]; + volatile uint8_t polling; } rtl1839if_t; /* diff --git a/include/metalsvm/spinlock.h b/include/metalsvm/spinlock.h index bba4325a..a86bc603 100644 --- a/include/metalsvm/spinlock.h +++ b/include/metalsvm/spinlock.h @@ -80,7 +80,7 @@ inline static int spinlock_destroy(spinlock_t* s) { * - -EINVAL (-22) on failure */ inline static int spinlock_lock(spinlock_t* s) { - //int32_t ticket; + int32_t ticket; task_t* curr_task; if (BUILTIN_EXPECT(!s, 0)) @@ -92,7 +92,7 @@ inline static int spinlock_lock(spinlock_t* s) { return 0; } -#if 0 +#if 1 ticket = atomic_int32_inc(&s->queue); while(atomic_int32_read(&s->dequeue) != ticket) { NOP1; @@ -118,7 +118,7 @@ inline static int spinlock_unlock(spinlock_t* s) { s->counter--; if (!s->counter) { s->owner = MAX_TASKS; -#if 0 +#if 1 atomic_int32_inc(&s->dequeue); #else atomic_int32_set(&s->dequeue,1); @@ -172,7 +172,7 @@ inline static int spinlock_irqsave_destroy(spinlock_irqsave_t* s) { */ inline static int spinlock_irqsave_lock(spinlock_irqsave_t* s) { uint32_t flags; - //int32_t ticket; + int32_t ticket; if (BUILTIN_EXPECT(!s, 0)) return -EINVAL; @@ -183,7 +183,7 @@ inline static int spinlock_irqsave_lock(spinlock_irqsave_t* s) { return 0; } -#if 0 +#if 1 ticket = atomic_int32_inc(&s->queue); while (atomic_int32_read(&s->dequeue) != ticket) { NOP1; @@ -215,7 +215,7 @@ inline static int spinlock_irqsave_unlock(spinlock_irqsave_t* s) { flags = s->flags; s->coreid = (uint32_t) -1; s->flags = 0; -#if 0 +#if 1 atomic_int32_inc(&s->dequeue); #else atomic_int32_set(&s->dequeue,1); diff --git a/kernel/netio.c b/kernel/netio.c index 35f57e45..4df88f8f 100644 --- a/kernel/netio.c +++ b/kernel/netio.c @@ -202,7 +202,7 @@ static int TCPServer(void* arg) { start = rdtsc(); - kprintf("\nReceiving from client, packet size %s ... ", PacketSize(ctl.data)); + kprintf("\nReceiving from client, packet size %s ... \n", PacketSize(ctl.data)); cBuffer[0] = 0; nData = 0; @@ -229,7 +229,7 @@ static int TCPServer(void* arg) } else if (ctl.cmd == CMD_S2C) { start = rdtsc(); - kprintf("\nSending to client, packet size %s ... ", PacketSize(ctl.data)); + kprintf("\nSending to client, packet size %s ... \n", PacketSize(ctl.data)); cBuffer[0] = 0; nData = 0;