add first version of the network driver for Intel's E1000 NIC
This commit is contained in:
parent
ac20297df9
commit
947d77c775
3 changed files with 796 additions and 1 deletions
|
@ -1,4 +1,4 @@
|
|||
C_source := rtl8139.c rckemac.c mmnif.c util.c
|
||||
C_source := e1000.c rtl8139.c rckemac.c mmnif.c util.c
|
||||
MODULE := drivers_net
|
||||
|
||||
include $(TOPDIR)/Makefile.inc
|
||||
|
|
536
drivers/net/e1000.c
Normal file
536
drivers/net/e1000.c
Normal file
|
@ -0,0 +1,536 @@
|
|||
/*
|
||||
* Copyright 2012 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 <metalsvm/stddef.h>
|
||||
#include <metalsvm/stdio.h>
|
||||
#include <metalsvm/string.h>
|
||||
#include <metalsvm/processor.h>
|
||||
#include <metalsvm/mailbox.h>
|
||||
#include <metalsvm/page.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/irq.h>
|
||||
#if defined(CONFIG_LWIP) && defined(CONFIG_PCI)
|
||||
#include <asm/pci.h>
|
||||
#include <lwip/sys.h>
|
||||
#include <lwip/stats.h>
|
||||
#include <lwip/netif.h>
|
||||
#include <lwip/tcpip.h>
|
||||
#include <netif/etharp.h>
|
||||
#include <net/e1000.h>
|
||||
|
||||
#define RX_BUF_LEN (8192+16)
|
||||
#define TX_BUF_LEN (1792+16)
|
||||
|
||||
#define INT_MASK (E1000_IMS_RXO|E1000_IMS_RXT0|E1000_IMS_RXDMT0|E1000_IMS_RXSEQ|E1000_IMS_LSC)
|
||||
#define INT_MASK_NO_RXT0 (E1000_IMS_RXO|E1000_IMS_RXDMT0|E1000_IMS_RXSEQ|E1000_IMS_LSC)
|
||||
|
||||
typedef struct {
|
||||
char *vendor_str;
|
||||
char *device_str;
|
||||
uint32_t vendor;
|
||||
uint32_t device;
|
||||
} board_t;
|
||||
|
||||
static board_t board_tbl[] =
|
||||
{
|
||||
{"Intel", "Intel E1000 (82542)", 0x8086, 0x1000},
|
||||
{"Intel", "Intel E1000 (82543GC FIBER)", 0x8086, 0x1001},
|
||||
{"Intel", "Intel E1000 (82543GC COPPER)", 0x8086, 0x1004},
|
||||
{"Intel", "Intel E1000 (82544EI COPPER)", 0x8086, 0x1008},
|
||||
{"Intel", "Intel E1000 (82544EI FIBER)", 0x8086, 0x1009},
|
||||
{"Intel", "Intel E1000 (82544GC COPPER)", 0x8086, 0x100C},
|
||||
{"Intel", "Intel E1000 (82544GC LOM)", 0x8086, 0x100D},
|
||||
{"Intel", "Intel E1000 (82540EM)", 0x8086, 0x100E},
|
||||
{"Intel", "Intel E1000 (82540EM LOM)", 0x8086, 0x1015},
|
||||
{"Intel", "Intel E1000 (82540EP LOM)", 0x8086, 0x1016},
|
||||
{"Intel", "Intel E1000 (82540EP)", 0x8086, 0x1017},
|
||||
{"Intel", "Intel E1000 (82540EP LP)", 0x8086, 0x101E},
|
||||
{"Intel", "Intel E1000 (82545EM COPPER)", 0x8086, 0x100F},
|
||||
{"Intel", "Intel E1000 (82545EM FIBER)", 0x8086, 0x1011},
|
||||
{"Intel", "Intel E1000 (82545GM COPPER)", 0x8086, 0x1026},
|
||||
{"Intel", "Intel E1000 (82545GM FIBER)", 0x8086, 0x1027},
|
||||
{"Intel", "Intel E1000 (82545GM SERDES)", 0x8086, 0x1028},
|
||||
{"Intel", "Intel E1000 (82546EB COPPER)", 0x8086, 0x1010},
|
||||
{"Intel", "Intel E1000 (82546EB FIBER)", 0x8086, 0x1012},
|
||||
{"Intel", "Intel E1000 (82546EB QUAD COPPER)", 0x8086, 0x101D},
|
||||
{"Intel", "Intel E1000 (82541EI)", 0x8086, 0x1013},
|
||||
{"Intel", "Intel E1000 (82541EI MOBILE)", 0x8086, 0x1018},
|
||||
{"Intel", "Intel E1000 (82541ER LOM)", 0x8086, 0x1014},
|
||||
{"Intel", "Intel E1000 (82541ER)", 0x8086, 0x1078},
|
||||
{"Intel", "Intel E1000 (82547GI)", 0x8086, 0x1075},
|
||||
{"Intel", "Intel E1000 (82541GI)", 0x8086, 0x1076},
|
||||
{"Intel", "Intel E1000 (82541GI MOBILE)", 0x8086, 0x1077},
|
||||
{"Intel", "Intel E1000 (82541GI LF)", 0x8086, 0x107C},
|
||||
{"Intel", "Intel E1000 (82546GB COPPER)", 0x8086, 0x1079},
|
||||
{"Intel", "Intel E1000 (82546GB FIBER)", 0x8086, 0x107A},
|
||||
{"Intel", "Intel E1000 (82546GB SERDES)", 0x8086, 0x107B},
|
||||
{"Intel", "Intel E1000 (82546GB PCIE)", 0x8086, 0x108A},
|
||||
{"Intel", "Intel E1000 (82546GB QUAD COPPER)", 0x8086, 0x1099},
|
||||
{"Intel", "Intel E1000 (82547EI)", 0x8086, 0x1019},
|
||||
{"Intel", "Intel E1000 (82547EI_MOBILE)", 0x8086, 0x101A},
|
||||
{"Intel", "Intel E1000 (82546GB QUAD COPPER KSP3)", 0x8086, 0x10B5},
|
||||
{NULL,},
|
||||
};
|
||||
|
||||
static struct netif* mynetif = NULL;
|
||||
|
||||
static inline uint32_t e1000_read(uint8_t* base, uint32_t off)
|
||||
{
|
||||
return *((volatile uint32_t*) (base+off));
|
||||
}
|
||||
|
||||
static inline void e1000_write(uint8_t* base, uint32_t off, uint32_t value)
|
||||
{
|
||||
*((volatile uint32_t*) (base+off)) = value;
|
||||
}
|
||||
|
||||
#if 1
|
||||
static uint16_t eeprom_read(uint8_t* base, uint8_t addr)
|
||||
{
|
||||
uint16_t data;
|
||||
uint32_t tmp;
|
||||
|
||||
e1000_write(base, E1000_EERD, 1 | ((uint32_t)(addr) << 8));
|
||||
|
||||
while(!((tmp = e1000_read(base, E1000_EERD)) & (1 << 4)))
|
||||
udelay(1);
|
||||
|
||||
data = (uint16_t)((tmp >> 16) & 0xFFFF);
|
||||
|
||||
return data;
|
||||
}
|
||||
#else
|
||||
// Only for 82541xx and 82547GI/EI
|
||||
static uint16_t eeprom_read(uint8_t* base, uint8_t addr)
|
||||
{
|
||||
uint16_t data;
|
||||
uint32_t tmp;
|
||||
|
||||
e1000_write(base, E1000_EERD, 1 | ((uint32_t)(addr) << 2));
|
||||
|
||||
while(!((tmp = e1000_read(base, E1000_EERD)) & (1 << 1)))
|
||||
udelay(1);
|
||||
|
||||
data = (uint16_t)((tmp >> 16) & 0xFFFF);
|
||||
|
||||
return data;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* @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 e1000if_output(struct netif* netif, struct pbuf* p)
|
||||
{
|
||||
e1000if_t* e1000if = netif->state;
|
||||
uint32_t i;
|
||||
struct pbuf *q;
|
||||
|
||||
if (BUILTIN_EXPECT((p->tot_len > 1792) || (p->tot_len > TX_BUF_LEN), 0)) {
|
||||
LWIP_DEBUGF(NETIF_DEBUG, ("e1000if_output: packet is longer than 1792 bytes\n"));
|
||||
return ERR_IF;
|
||||
}
|
||||
|
||||
if (!(e1000if->tx_desc[e1000if->tx_tail].status & 0xF)) {
|
||||
LWIP_DEBUGF(NETIF_DEBUG, ("e1000if_output: %i already inuse\n", e1000if->tx_tail));
|
||||
return ERR_IF;
|
||||
}
|
||||
|
||||
#if ETH_PAD_SIZE
|
||||
pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */
|
||||
#endif
|
||||
|
||||
/*
|
||||
* 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((void*) ((size_t) e1000if->tx_buffers + e1000if->tx_tail*TX_BUF_LEN + i), q->payload, q->len);
|
||||
i += q->len;
|
||||
}
|
||||
|
||||
e1000if->tx_desc[e1000if->tx_tail].length = p->tot_len;
|
||||
e1000if->tx_desc[e1000if->tx_tail].status = 0;
|
||||
e1000if->tx_desc[e1000if->tx_tail].cmd = (1 << 3) | 3;
|
||||
|
||||
// update the tail so the hardware knows it's ready
|
||||
e1000if->tx_tail = (e1000if->tx_tail + 1) % NUM_TX_DESCRIPTORS;
|
||||
e1000_write(e1000if->bar0, E1000_TDT, e1000if->tx_tail);
|
||||
|
||||
#if ETH_PAD_SIZE
|
||||
pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */
|
||||
#endif
|
||||
|
||||
LINK_STATS_INC(link.xmit);
|
||||
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
static void e1000if_input(struct netif* netif, struct pbuf* p)
|
||||
{
|
||||
struct eth_hdr *ethhdr;
|
||||
err_t err;
|
||||
|
||||
/* 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 */
|
||||
/*
|
||||
* 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, ("e1000if_input: ethernet_input failed %d\n", err));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
LWIP_DEBUGF(NETIF_DEBUG, ("e1000if_input: invalid ethernet header 0x%x\n", htons(ethhdr->type)));
|
||||
pbuf_free(p);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void e1000_rx_inthandler(struct netif* netif)
|
||||
{
|
||||
e1000if_t* e1000if = netif->state;
|
||||
struct pbuf *p = NULL;
|
||||
struct pbuf* q;
|
||||
uint16_t length, i;
|
||||
|
||||
while(e1000if->rx_desc[e1000if->rx_tail].status & (1 << 0))
|
||||
{
|
||||
if (!(e1000if->rx_desc[e1000if->rx_tail].status & (1 << 1))) {
|
||||
LINK_STATS_INC(link.drop);
|
||||
goto no_eop; // currently, we ignore packets without EOP flag
|
||||
}
|
||||
|
||||
length = e1000if->rx_desc[e1000if->rx_tail].length;
|
||||
|
||||
if (!e1000if->rx_desc[e1000if->rx_tail].errors) {
|
||||
#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, i=0; q!=NULL; q=q->next) {
|
||||
memcpy((uint8_t*) q->payload, (void*) ((size_t) e1000if->rx_buffers + e1000if->rx_tail*RX_BUF_LEN + i), q->len);
|
||||
i += q->len;
|
||||
}
|
||||
#if ETH_PAD_SIZE
|
||||
pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */
|
||||
#endif
|
||||
LINK_STATS_INC(link.recv);
|
||||
|
||||
// forward packet to LwIP
|
||||
e1000if_input(netif, p);
|
||||
} else {
|
||||
LWIP_DEBUGF(NETIF_DEBUG, ("e1000if_rx_inthandler: not enough memory!\n"));
|
||||
LINK_STATS_INC(link.memerr);
|
||||
LINK_STATS_INC(link.drop);
|
||||
}
|
||||
} else {
|
||||
LWIP_DEBUGF(NETIF_DEBUG, ("e1000if_rx_inthandler: RX errors (0x%x)\n", e1000if->rx_desc[e1000if->rx_tail].errors));
|
||||
LINK_STATS_INC(link.memerr);
|
||||
LINK_STATS_INC(link.drop);
|
||||
break;
|
||||
}
|
||||
|
||||
no_eop:
|
||||
e1000if->rx_desc[e1000if->rx_tail].status = 0;
|
||||
|
||||
// update tail and write the value to the device
|
||||
e1000if->rx_tail = (e1000if->rx_tail + 1) % NUM_RX_DESCRIPTORS;
|
||||
e1000_write(e1000if->bar0, E1000_RDT, e1000if->rx_tail);
|
||||
}
|
||||
|
||||
e1000if->polling = 0;
|
||||
// enable all known interrupts
|
||||
e1000_write(e1000if->bar0, E1000_IMS, INT_MASK);
|
||||
}
|
||||
|
||||
/* this function is called in the context of the tcpip thread or the irq handler (by using NO_SYS) */
|
||||
static void e1000if_poll(void* ctx)
|
||||
{
|
||||
e1000_rx_inthandler(mynetif);
|
||||
}
|
||||
|
||||
static void e1000if_handler(struct state* s)
|
||||
{
|
||||
e1000if_t* e1000if = mynetif->state;
|
||||
uint32_t icr;
|
||||
|
||||
// disable all interrupts
|
||||
e1000_write(e1000if->bar0, E1000_IMS, 0);
|
||||
|
||||
// read the pending interrupt status
|
||||
icr = e1000_read(e1000if->bar0, E1000_ICR);
|
||||
|
||||
kprintf("INT icr %u\n", icr);
|
||||
|
||||
// ignore tx success stuff
|
||||
icr &= ~3;
|
||||
|
||||
// LINK STATUS CHANGE
|
||||
if (icr & E1000_ICR_LSC)
|
||||
{
|
||||
icr &= ~E1000_ICR_LSC;
|
||||
LWIP_DEBUGF(NETIF_DEBUG, ("e1000if: Link status change (TODO)\n"));
|
||||
}
|
||||
|
||||
if (icr & (E1000_ICR_RXT0|E1000_ICR_RXDMT0|E1000_ICR_RXO)) {
|
||||
icr &= ~(E1000_ICR_RXT0|E1000_ICR_RXDMT0|E1000_ICR_RXO);
|
||||
|
||||
if (!e1000if->polling) {
|
||||
#if NO_SYS
|
||||
e1000if_poll(NULL);
|
||||
#else
|
||||
if (tcpip_callback_with_block(e1000if_poll, NULL, 0) == ERR_OK) {
|
||||
e1000if->polling = 1;
|
||||
} else {
|
||||
LWIP_DEBUGF(NETIF_DEBUG, ("e1000if_handler: unable to send a poll request to the tcpip thread\n"));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
if (e1000if->polling) // now, the tcpip thread will check for incoming messages
|
||||
e1000_write(e1000if->bar0, E1000_IMS, INT_MASK_NO_RXT0);
|
||||
else
|
||||
e1000_write(e1000if->bar0, E1000_IMS, INT_MASK); // enable interrupts
|
||||
|
||||
if (icr & 0x1FFFF) {
|
||||
LWIP_DEBUGF(NETIF_DEBUG, ("e1000if_handler: unhandled interrupt #%u received! (0x%x)\n", e1000if->irq, icr));
|
||||
}
|
||||
}
|
||||
|
||||
err_t e1000if_init(struct netif* netif)
|
||||
{
|
||||
pci_info_t pci_info;
|
||||
e1000if_t* e1000if;
|
||||
uint32_t tmp32;
|
||||
uint16_t tmp16, speed;
|
||||
uint8_t tmp8, is64bit, mem_type, prefetch;
|
||||
static uint8_t num = 0;
|
||||
|
||||
LWIP_ASSERT("netif != NULL", (netif != NULL));
|
||||
|
||||
tmp8 = 0;
|
||||
while (board_tbl[tmp8].vendor_str) {
|
||||
if (pci_get_device_info(board_tbl[tmp8].vendor, board_tbl[tmp8].device, &pci_info) == 0)
|
||||
break;
|
||||
tmp8++;
|
||||
}
|
||||
|
||||
if (!board_tbl[tmp8].vendor_str)
|
||||
return ERR_ARG;
|
||||
|
||||
mem_type = pci_info.base[0] & 0x1;
|
||||
is64bit = pci_info.base[0] & 0x6 ? 1 : 0;
|
||||
prefetch = pci_info.base[0] & 0x8 ? 1 : 0;
|
||||
|
||||
if (mem_type) {
|
||||
LWIP_DEBUGF(NETIF_DEBUG, ("e1000if_init: IO space is currently not supported!\n"));
|
||||
return ERR_ARG;
|
||||
}
|
||||
|
||||
e1000if = kmalloc(sizeof(e1000if_t));
|
||||
if (!e1000if) {
|
||||
LWIP_DEBUGF(NETIF_DEBUG, ("e1000if_init: out of memory\n"));
|
||||
return ERR_MEM;
|
||||
}
|
||||
memset(e1000if, 0x00, sizeof(e1000if_t));
|
||||
|
||||
netif->state = e1000if;
|
||||
mynetif = netif;
|
||||
|
||||
e1000if->bar0 = (uint8_t*) map_region(0, pci_info.base[0] & ~0xF, pci_info.size[0], MAP_KERNEL_SPACE|MAP_NO_CACHE);
|
||||
|
||||
// reset device
|
||||
e1000_write(e1000if->bar0, E1000_CTRL, E1000_CTRL_RST);
|
||||
|
||||
e1000if->irq = pci_info.irq;
|
||||
e1000if->rx_desc = mem_allocation(NUM_RX_DESCRIPTORS*sizeof(rx_desc_t), MAP_KERNEL_SPACE|MAP_NO_CACHE);
|
||||
memset((void*) e1000if->rx_desc, 0x00, NUM_RX_DESCRIPTORS*sizeof(rx_desc_t));
|
||||
e1000if->tx_desc = mem_allocation(NUM_TX_DESCRIPTORS*sizeof(tx_desc_t), MAP_KERNEL_SPACE|MAP_NO_CACHE);
|
||||
memset((void*) e1000if->tx_desc, 0x00, NUM_TX_DESCRIPTORS*sizeof(tx_desc_t));
|
||||
|
||||
LWIP_DEBUGF(NETIF_DEBUG, ("e1000if_init: Found %s at iobase 0x%x (size 0x%x), irq %u\n", board_tbl[tmp8].device_str,
|
||||
pci_info.base[0] & ~0xF, pci_info.size[0], e1000if->irq));
|
||||
//LWIP_DEBUGF(NETIF_DEBUG, ("e1000if_init: Map iobase to %p\n", e1000if->bar0));
|
||||
LWIP_DEBUGF(NETIF_DEBUG, ("e1000if_init: is64bit %u, prefetch %u\n", is64bit, prefetch));
|
||||
|
||||
// determine the mac address of this card
|
||||
for (tmp8=0; tmp8<6; tmp8+=2) {
|
||||
tmp16 = eeprom_read(e1000if->bar0, tmp8 / 2);
|
||||
mynetif->hwaddr[tmp8] = (tmp16 & 0xFF);
|
||||
mynetif->hwaddr[tmp8+1] = (tmp16 >> 8) & 0xFF;
|
||||
}
|
||||
|
||||
e1000if->tx_buffers = mem_allocation(NUM_TX_DESCRIPTORS*TX_BUF_LEN, MAP_KERNEL_SPACE|MAP_NO_CACHE);
|
||||
memset((void*) e1000if->tx_buffers, 0x00, NUM_TX_DESCRIPTORS*TX_BUF_LEN);
|
||||
for(tmp32=0; tmp32 < NUM_TX_DESCRIPTORS; tmp32++) {
|
||||
e1000if->tx_desc[tmp32].addr = virt_to_phys((size_t)e1000if->tx_buffers + tmp32*TX_BUF_LEN);
|
||||
e1000if->tx_desc[tmp32].status = 1;
|
||||
}
|
||||
|
||||
//LWIP_DEBUGF(NETIF_DEBUG, ("e1000if_init: add TX ring buffer %p (viraddr %p)\n", virt_to_phys((size_t)e1000if->tx_desc), e1000if->tx_desc));
|
||||
|
||||
// setup the transmit descriptor ring buffer
|
||||
e1000_write(e1000if->bar0, E1000_TDBAL, (uint32_t)((uint64_t)virt_to_phys((size_t)e1000if->tx_desc) & 0xFFFFFFFF));
|
||||
e1000_write(e1000if->bar0, E1000_TDBAH, (uint32_t)((uint64_t)virt_to_phys((size_t)e1000if->tx_desc) >> 32));
|
||||
//LWIP_DEBUGF(NETIF_DEBUG, ("e1000if_init: TDBAH/TDBAL = 0x%x:0x%x\n", e1000_read(e1000if->bar0, E1000_TDBAH), e1000_read(e1000if->bar0, E1000_TDBAL)));
|
||||
|
||||
// transmit buffer length; NUM_TX_DESCRIPTORS 16-byte descriptors
|
||||
e1000_write(e1000if->bar0, E1000_TDLEN , (uint32_t)(NUM_TX_DESCRIPTORS * sizeof(tx_desc_t)));
|
||||
|
||||
// setup head and tail pointers
|
||||
e1000_write(e1000if->bar0, E1000_TDH, 0);
|
||||
e1000_write(e1000if->bar0, E1000_TDT, 0);
|
||||
e1000if->tx_tail = 0;
|
||||
|
||||
// set the transmit control register (padshortpackets)
|
||||
e1000_write(e1000if->bar0, E1000_TCTL, (E1000_TCTL_EN | E1000_TCTL_PSP | (0x40 << 12) | (0x10 << 4)));
|
||||
|
||||
// set IEEE 802.3 standard IPG value
|
||||
e1000_write(e1000if->bar0, E1000_TIPG, (6 << 20) | (8 << 10) | 10);
|
||||
|
||||
#if 1
|
||||
LWIP_DEBUGF(NETIF_DEBUG, ("e1000if_init: MAC address "));
|
||||
for(tmp8=0; tmp8<6; tmp8++) {
|
||||
LWIP_DEBUGF(NETIF_DEBUG, ("%02x ", mynetif->hwaddr[tmp8]));
|
||||
}
|
||||
LWIP_DEBUGF(NETIF_DEBUG, ("\n"));
|
||||
#else
|
||||
// set MAC address
|
||||
for(tmp8=0; tmp8<4; tmp8++)
|
||||
((uint8_t*) &tmp32)[tmp8] = mynetif->hwaddr[tmp8];
|
||||
e1000_write(e1000if->bar0, E1000_RA, tmp32);
|
||||
tmp32 = 0;
|
||||
for(tmp8=0; tmp8<2; tmp8++)
|
||||
((uint8_t*) &tmp32)[tmp8] = mynetif->hwaddr[tmp8+4];
|
||||
e1000_write(e1000if->bar0, E1000_RA+4, tmp32 | (1 << 31)); // set also AV bit to check incoming packets
|
||||
|
||||
LWIP_DEBUGF(NETIF_DEBUG, ("e1000if_init: MAC address "));
|
||||
tmp32 = e1000_read(e1000if->bar0, E1000_RA);
|
||||
for(tmp8=0; tmp8<4; tmp8++) {
|
||||
LWIP_DEBUGF(NETIF_DEBUG, ("%02x ", ((uint8_t*) &tmp32)[tmp8]));
|
||||
}
|
||||
tmp32 = e1000_read(e1000if->bar0, E1000_RA+4);
|
||||
for(tmp8=0; tmp8<2; tmp8++) {
|
||||
LWIP_DEBUGF(NETIF_DEBUG, ("%02x ", ((uint8_t*) &tmp32)[tmp8]));
|
||||
}
|
||||
LWIP_DEBUGF(NETIF_DEBUG, ("\n"));
|
||||
#endif
|
||||
|
||||
// set multicast table to 0
|
||||
for(tmp8=0; tmp8<128; tmp8++ )
|
||||
e1000_write(e1000if->bar0, E1000_MTA + (tmp8 * 4), 0);
|
||||
|
||||
// set IRQ handler
|
||||
irq_install_handler(e1000if->irq+32, e1000if_handler);
|
||||
|
||||
// enable all interrupts (and clear existing pending ones)
|
||||
e1000_write(e1000if->bar0, E1000_IMS, INT_MASK);
|
||||
e1000_read(e1000if->bar0, E1000_ICR);
|
||||
|
||||
//LWIP_DEBUGF(NETIF_DEBUG, ("e1000if_init: add RX ring buffer %p (viraddr %p)\n", virt_to_phys((size_t)e1000if->rx_desc), e1000if->rx_desc));
|
||||
|
||||
e1000if->rx_buffers = mem_allocation(NUM_RX_DESCRIPTORS*RX_BUF_LEN, MAP_KERNEL_SPACE|MAP_NO_CACHE);
|
||||
memset(e1000if->rx_buffers, 0x00, NUM_RX_DESCRIPTORS*RX_BUF_LEN);
|
||||
for(tmp32=0; tmp32 < NUM_RX_DESCRIPTORS; tmp32++)
|
||||
e1000if->rx_desc[tmp32].addr = virt_to_phys((size_t)e1000if->rx_buffers + tmp32*RX_BUF_LEN);
|
||||
|
||||
// setup the receive descriptor ring buffer
|
||||
e1000_write(e1000if->bar0, E1000_RDBAH, (uint32_t)((uint64_t)virt_to_phys((size_t)e1000if->rx_desc) >> 32));
|
||||
e1000_write(e1000if->bar0, E1000_RDBAL, (uint32_t)((uint64_t)virt_to_phys((size_t)e1000if->rx_desc) & 0xFFFFFFFF));
|
||||
|
||||
// receive buffer length; NUM_RX_DESCRIPTORS 16-byte descriptors
|
||||
e1000_write(e1000if->bar0, E1000_RDLEN , (uint32_t)(NUM_RX_DESCRIPTORS * sizeof(rx_desc_t)));
|
||||
|
||||
// setup head and tail pointers
|
||||
e1000_write(e1000if->bar0, E1000_RDH, 0);
|
||||
e1000_write(e1000if->bar0, E1000_RDT, 0);
|
||||
e1000if->rx_tail = 0;
|
||||
|
||||
// set the receieve control register
|
||||
#if 1
|
||||
e1000_write(e1000if->bar0, E1000_RCTL, (E1000_RCTL_EN|E1000_RCTL_LPE|E1000_RCTL_BAM|E1000_RCTL_SZ_8192|E1000_RCTL_BSEX|
|
||||
E1000_RCTL_SECRC|E1000_RCTL_RDMTS_HALF|E1000_RCTL_MO_0|E1000_RCTL_UPE|E1000_RCTL_MPE));
|
||||
#else
|
||||
e1000_write(e1000if->bar0, E1000_RCTL, (E1000_RCTL_EN|E1000_RCTL_LPE|E1000_RCTL_BAM|E1000_RCTL_SZ_8192|E1000_RCTL_BSEX|
|
||||
E1000_RCTL_SECRC|E1000_RCTL_RDMTS_HALF|E1000_RCTL_MO_0));
|
||||
#endif
|
||||
|
||||
// set the LINK UP
|
||||
e1000_write(e1000if->bar0, E1000_CTRL, (e1000_read(e1000if->bar0, E1000_CTRL) | E1000_CTRL_SLU));
|
||||
|
||||
tmp32 = e1000_read(e1000if->bar0, E1000_CTRL);
|
||||
if (tmp32 & E1000_CTRL_SPD_1000)
|
||||
speed = 1000;
|
||||
else if (tmp32 & E1000_CTRL_SPD_100)
|
||||
speed = 100;
|
||||
else
|
||||
speed = 10;
|
||||
|
||||
LWIP_DEBUGF(NETIF_DEBUG, ("e1000if_init: speed = %u mbps\n", speed));
|
||||
|
||||
/*
|
||||
* 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, speed);
|
||||
|
||||
/* administrative details */
|
||||
netif->name[0] = 'e';
|
||||
netif->name[1] = 'n';
|
||||
netif->num = num;
|
||||
num++;
|
||||
/* downward functions */
|
||||
netif->output = etharp_output;
|
||||
netif->linkoutput = e1000if_output;
|
||||
/* maximum transfer unit */
|
||||
netif->mtu = 1500;
|
||||
/* broadcast capability */
|
||||
netif->flags |= NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_IGMP;
|
||||
/* hardware address length */
|
||||
netif->hwaddr_len = 6;
|
||||
|
||||
e1000if->ethaddr = (struct eth_addr *)netif->hwaddr;
|
||||
|
||||
return ERR_OK;
|
||||
}
|
||||
#endif
|
259
drivers/net/e1000.h
Normal file
259
drivers/net/e1000.h
Normal file
|
@ -0,0 +1,259 @@
|
|||
/*
|
||||
* Copyright 2012 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_E1000_H__
|
||||
#define __HAVE_E1000_H__
|
||||
|
||||
#include <metalsvm/stddef.h>
|
||||
#include <metalsvm/spinlock.h>
|
||||
|
||||
#if defined(CONFIG_LWIP) && defined(CONFIG_PCI)
|
||||
|
||||
|
||||
#define NUM_RX_DESCRIPTORS 64
|
||||
#define NUM_TX_DESCRIPTORS 64
|
||||
|
||||
#define E1000_CTRL 0x00000 /* Device Control - RW */
|
||||
#define E1000_CTRL_DUP 0x00004 /* Device Control Duplicate (Shadow) - RW */
|
||||
#define E1000_STATUS 0x00008 /* Device Status - RO */
|
||||
#define E1000_EECD 0x00010 /* EEPROM/Flash Control - RW */
|
||||
#define E1000_EERD 0x00014 /* EEPROM Read - RW */
|
||||
#define E1000_ICR 0x000C0 /* Interrupt Cause Read - R/clr */
|
||||
#define E1000_ITR 0x000C4 /* Interrupt Throttling Rate - RW */
|
||||
#define E1000_ICS 0x000C8 /* Interrupt Cause Set - WO */
|
||||
#define E1000_IMS 0x000D0 /* Interrupt Mask Set - RW */
|
||||
#define E1000_IMC 0x000D8 /* Interrupt Mask Clear - WO */
|
||||
#define E1000_IAM 0x000E0 /* Interrupt Acknowledge Auto Mask */
|
||||
#define E1000_RCTL 0x00100 /* RX Control - RW */
|
||||
#define E1000_TCTL 0x00400 /* TX Control - RW */
|
||||
#define E1000_TIPG 0x00410 /* TX Inter-packet gap -RW */
|
||||
#define E1000_RDBAL 0x02800 /* RX Descriptor Base Address Low - RW */
|
||||
#define E1000_RDBAH 0x02804 /* RX Descriptor Base Address High - RW */
|
||||
#define E1000_RDLEN 0x02808 /* RX Descriptor Length - RW */
|
||||
#define E1000_RDH 0x02810 /* RX Descriptor Head - RW */
|
||||
#define E1000_RDT 0x02818 /* RX Descriptor Tail - RW */
|
||||
#define E1000_TDBAL 0x03800 /* TX Descriptor Base Address Low - RW */
|
||||
#define E1000_TDBAH 0x03804 /* TX Descriptor Base Address High - RW */
|
||||
#define E1000_TDLEN 0x03808 /* TX Descriptor Length - RW */
|
||||
#define E1000_TDH 0x03810 /* TX Descriptor Head - RW */
|
||||
#define E1000_TDT 0x03818 /* TX Descripotr Tail - RW */
|
||||
#define E1000_MTA 0x05200 /* Multicast Table Array - RW Array */
|
||||
#define E1000_RA 0x05400 /* Receive Address - RW Array */
|
||||
|
||||
/* Device Control */
|
||||
#define E1000_CTRL_FD 0x00000001 /* Full duplex.0=half; 1=full */
|
||||
#define E1000_CTRL_BEM 0x00000002 /* Endian Mode.0=little,1=big */
|
||||
#define E1000_CTRL_PRIOR 0x00000004 /* Priority on PCI. 0=rx,1=fair */
|
||||
#define E1000_CTRL_GIO_MASTER_DISABLE 0x00000004 /*Blocks new Master requests */
|
||||
#define E1000_CTRL_LRST 0x00000008 /* Link reset. 0=normal,1=reset */
|
||||
#define E1000_CTRL_TME 0x00000010 /* Test mode. 0=normal,1=test */
|
||||
#define E1000_CTRL_SLE 0x00000020 /* Serial Link on 0=dis,1=en */
|
||||
#define E1000_CTRL_ASDE 0x00000020 /* Auto-speed detect enable */
|
||||
#define E1000_CTRL_SLU 0x00000040 /* Set link up (Force Link) */
|
||||
#define E1000_CTRL_ILOS 0x00000080 /* Invert Loss-Of Signal */
|
||||
#define E1000_CTRL_SPD_SEL 0x00000300 /* Speed Select Mask */
|
||||
#define E1000_CTRL_SPD_10 0x00000000 /* Force 10Mb */
|
||||
#define E1000_CTRL_SPD_100 0x00000100 /* Force 100Mb */
|
||||
#define E1000_CTRL_SPD_1000 0x00000200 /* Force 1Gb */
|
||||
#define E1000_CTRL_BEM32 0x00000400 /* Big Endian 32 mode */
|
||||
#define E1000_CTRL_FRCSPD 0x00000800 /* Force Speed */
|
||||
#define E1000_CTRL_FRCDPX 0x00001000 /* Force Duplex */
|
||||
#define E1000_CTRL_D_UD_EN 0x00002000 /* Dock/Undock enable */
|
||||
#define E1000_CTRL_D_UD_POLARITY 0x00004000 /* Defined polarity of Dock/Undock indication in SDP[0] */
|
||||
#define E1000_CTRL_FORCE_PHY_RESET 0x00008000 /* Reset both PHY ports, through PHYRST_N pin */
|
||||
#define E1000_CTRL_EXT_LINK_EN 0x00010000 /* enable link status from external LINK_0 and LINK_1 pins */
|
||||
#define E1000_CTRL_SWDPIN0 0x00040000 /* SWDPIN 0 value */
|
||||
#define E1000_CTRL_SWDPIN1 0x00080000 /* SWDPIN 1 value */
|
||||
#define E1000_CTRL_SWDPIN2 0x00100000 /* SWDPIN 2 value */
|
||||
#define E1000_CTRL_SWDPIN3 0x00200000 /* SWDPIN 3 value */
|
||||
#define E1000_CTRL_SWDPIO0 0x00400000 /* SWDPIN 0 Input or output */
|
||||
#define E1000_CTRL_SWDPIO1 0x00800000 /* SWDPIN 1 input or output */
|
||||
#define E1000_CTRL_SWDPIO2 0x01000000 /* SWDPIN 2 input or output */
|
||||
#define E1000_CTRL_SWDPIO3 0x02000000 /* SWDPIN 3 input or output */
|
||||
#define E1000_CTRL_RST 0x04000000 /* Global reset */
|
||||
#define E1000_CTRL_RFCE 0x08000000 /* Receive Flow Control enable */
|
||||
#define E1000_CTRL_TFCE 0x10000000 /* Transmit flow control enable */
|
||||
#define E1000_CTRL_RTE 0x20000000 /* Routing tag enable */
|
||||
#define E1000_CTRL_VME 0x40000000 /* IEEE VLAN mode enable */
|
||||
#define E1000_CTRL_PHY_RST 0x80000000 /* PHY Reset */
|
||||
#define E1000_CTRL_SW2FW_INT 0x02000000 /* Initiate an interrupt to manageability engine */
|
||||
|
||||
/* Transmit Control */
|
||||
#define E1000_TCTL_RST 0x00000001 /* software reset */
|
||||
#define E1000_TCTL_EN 0x00000002 /* enable tx */
|
||||
#define E1000_TCTL_BCE 0x00000004 /* busy check enable */
|
||||
#define E1000_TCTL_PSP 0x00000008 /* pad short packets */
|
||||
#define E1000_TCTL_CT 0x00000ff0 /* collision threshold */
|
||||
#define E1000_TCTL_COLD 0x003ff000 /* collision distance */
|
||||
#define E1000_TCTL_SWXOFF 0x00400000 /* SW Xoff transmission */
|
||||
#define E1000_TCTL_PBE 0x00800000 /* Packet Burst Enable */
|
||||
#define E1000_TCTL_RTLC 0x01000000 /* Re-transmit on late collision */
|
||||
#define E1000_TCTL_NRTU 0x02000000 /* No Re-transmit on underrun */
|
||||
#define E1000_TCTL_MULR 0x10000000 /* Multiple request support */
|
||||
|
||||
/* Receive Control */
|
||||
#define E1000_RCTL_RST 0x00000001 /* Software reset */
|
||||
#define E1000_RCTL_EN 0x00000002 /* enable */
|
||||
#define E1000_RCTL_SBP 0x00000004 /* store bad packet */
|
||||
#define E1000_RCTL_UPE 0x00000008 /* unicast promiscuous enable */
|
||||
#define E1000_RCTL_MPE 0x00000010 /* multicast promiscuous enable */
|
||||
#define E1000_RCTL_LPE 0x00000020 /* long packet enable */
|
||||
#define E1000_RCTL_LBM_NO 0x00000000 /* no loopback mode */
|
||||
#define E1000_RCTL_LBM_MAC 0x00000040 /* MAC loopback mode */
|
||||
#define E1000_RCTL_LBM_SLP 0x00000080 /* serial link loopback mode */
|
||||
#define E1000_RCTL_LBM_TCVR 0x000000C0 /* tcvr loopback mode */
|
||||
#define E1000_RCTL_DTYP_MASK 0x00000C00 /* Descriptor type mask */
|
||||
#define E1000_RCTL_DTYP_PS 0x00000400 /* Packet Split descriptor */
|
||||
#define E1000_RCTL_RDMTS_HALF 0x00000000 /* rx desc min threshold size */
|
||||
#define E1000_RCTL_RDMTS_QUAT 0x00000100 /* rx desc min threshold size */
|
||||
#define E1000_RCTL_RDMTS_EIGTH 0x00000200 /* rx desc min threshold size */
|
||||
#define E1000_RCTL_MO_SHIFT 12 /* multicast offset shift */
|
||||
#define E1000_RCTL_MO_0 0x00000000 /* multicast offset 11:0 */
|
||||
#define E1000_RCTL_MO_1 0x00001000 /* multicast offset 12:1 */
|
||||
#define E1000_RCTL_MO_2 0x00002000 /* multicast offset 13:2 */
|
||||
#define E1000_RCTL_MO_3 0x00003000 /* multicast offset 15:4 */
|
||||
#define E1000_RCTL_MDR 0x00004000 /* multicast desc ring 0 */
|
||||
#define E1000_RCTL_BAM 0x00008000 /* broadcast enable */
|
||||
/* these buffer sizes are valid if E1000_RCTL_BSEX is 0 */
|
||||
#define E1000_RCTL_SZ_2048 0x00000000 /* rx buffer size 2048 */
|
||||
#define E1000_RCTL_SZ_1024 0x00010000 /* rx buffer size 1024 */
|
||||
#define E1000_RCTL_SZ_512 0x00020000 /* rx buffer size 512 */
|
||||
#define E1000_RCTL_SZ_256 0x00030000 /* rx buffer size 256 */
|
||||
/* these buffer sizes are valid if E1000_RCTL_BSEX is 1 */
|
||||
#define E1000_RCTL_SZ_16384 0x00010000 /* rx buffer size 16384 */
|
||||
#define E1000_RCTL_SZ_8192 0x00020000 /* rx buffer size 8192 */
|
||||
#define E1000_RCTL_SZ_4096 0x00030000 /* rx buffer size 4096 */
|
||||
#define E1000_RCTL_VFE 0x00040000 /* vlan filter enable */
|
||||
#define E1000_RCTL_CFIEN 0x00080000 /* canonical form enable */
|
||||
#define E1000_RCTL_CFI 0x00100000 /* canonical form indicator */
|
||||
#define E1000_RCTL_DPF 0x00400000 /* discard pause frames */
|
||||
#define E1000_RCTL_PMCF 0x00800000 /* pass MAC control frames */
|
||||
#define E1000_RCTL_BSEX 0x02000000 /* Buffer size extension */
|
||||
#define E1000_RCTL_SECRC 0x04000000 /* Strip Ethernet CRC */
|
||||
#define E1000_RCTL_FLXBUF_MASK 0x78000000 /* Flexible buffer size */
|
||||
#define E1000_RCTL_FLXBUF_SHIFT 27 /* Flexible buffer shift */
|
||||
|
||||
/* Interrupt Cause Read */
|
||||
#define E1000_ICR_TXDW 0x00000001 /* Transmit desc written back */
|
||||
#define E1000_ICR_TXQE 0x00000002 /* Transmit Queue empty */
|
||||
#define E1000_ICR_LSC 0x00000004 /* Link Status Change */
|
||||
#define E1000_ICR_RXSEQ 0x00000008 /* rx sequence error */
|
||||
#define E1000_ICR_RXDMT0 0x00000010 /* rx desc min. threshold (0) */
|
||||
#define E1000_ICR_RXO 0x00000040 /* rx overrun */
|
||||
#define E1000_ICR_RXT0 0x00000080 /* rx timer intr (ring 0) */
|
||||
#define E1000_ICR_MDAC 0x00000200 /* MDIO access complete */
|
||||
#define E1000_ICR_RXCFG 0x00000400 /* RX /c/ ordered set */
|
||||
#define E1000_ICR_GPI_EN0 0x00000800 /* GP Int 0 */
|
||||
#define E1000_ICR_GPI_EN1 0x00001000 /* GP Int 1 */
|
||||
#define E1000_ICR_GPI_EN2 0x00002000 /* GP Int 2 */
|
||||
#define E1000_ICR_GPI_EN3 0x00004000 /* GP Int 3 */
|
||||
#define E1000_ICR_TXD_LOW 0x00008000
|
||||
#define E1000_ICR_SRPD 0x00010000
|
||||
#define E1000_ICR_ACK 0x00020000 /* Receive Ack frame */
|
||||
#define E1000_ICR_MNG 0x00040000 /* Manageability event */
|
||||
#define E1000_ICR_DOCK 0x00080000 /* Dock/Undock */
|
||||
#define E1000_ICR_INT_ASSERTED 0x80000000 /* If this bit asserted, the driver should claim the interrupt */
|
||||
#define E1000_ICR_RXD_FIFO_PAR0 0x00100000 /* queue 0 Rx descriptor FIFO parity error */
|
||||
#define E1000_ICR_TXD_FIFO_PAR0 0x00200000 /* queue 0 Tx descriptor FIFO parity error */
|
||||
#define E1000_ICR_HOST_ARB_PAR 0x00400000 /* host arb read buffer parity error */
|
||||
#define E1000_ICR_PB_PAR 0x00800000 /* packet buffer parity error */
|
||||
#define E1000_ICR_RXD_FIFO_PAR1 0x01000000 /* queue 1 Rx descriptor FIFO parity error */
|
||||
#define E1000_ICR_TXD_FIFO_PAR1 0x02000000 /* queue 1 Tx descriptor FIFO parity error */
|
||||
#define E1000_ICR_ALL_PARITY 0x03F00000 /* all parity error bits */
|
||||
#define E1000_ICR_DSW 0x00000020 /* FW changed the status of DISSW bit in the FWSM */
|
||||
#define E1000_ICR_PHYINT 0x00001000 /* LAN connected device generates an interrupt */
|
||||
#define E1000_ICR_EPRST 0x00100000 /* ME handware reset occurs */
|
||||
|
||||
/* Interrupt Mask Set */
|
||||
#define E1000_IMS_TXDW E1000_ICR_TXDW /* Transmit desc written back */
|
||||
#define E1000_IMS_TXQE E1000_ICR_TXQE /* Transmit Queue empty */
|
||||
#define E1000_IMS_LSC E1000_ICR_LSC /* Link Status Change */
|
||||
#define E1000_IMS_RXSEQ E1000_ICR_RXSEQ /* rx sequence error */
|
||||
#define E1000_IMS_RXDMT0 E1000_ICR_RXDMT0 /* rx desc min. threshold */
|
||||
#define E1000_IMS_RXO E1000_ICR_RXO /* rx overrun */
|
||||
#define E1000_IMS_RXT0 E1000_ICR_RXT0 /* rx timer intr */
|
||||
#define E1000_IMS_MDAC E1000_ICR_MDAC /* MDIO access complete */
|
||||
#define E1000_IMS_RXCFG E1000_ICR_RXCFG /* RX /c/ ordered set */
|
||||
#define E1000_IMS_GPI_EN0 E1000_ICR_GPI_EN0 /* GP Int 0 */
|
||||
#define E1000_IMS_GPI_EN1 E1000_ICR_GPI_EN1 /* GP Int 1 */
|
||||
#define E1000_IMS_GPI_EN2 E1000_ICR_GPI_EN2 /* GP Int 2 */
|
||||
#define E1000_IMS_GPI_EN3 E1000_ICR_GPI_EN3 /* GP Int 3 */
|
||||
#define E1000_IMS_TXD_LOW E1000_ICR_TXD_LOW
|
||||
#define E1000_IMS_SRPD E1000_ICR_SRPD
|
||||
#define E1000_IMS_ACK E1000_ICR_ACK /* Receive Ack frame */
|
||||
#define E1000_IMS_MNG E1000_ICR_MNG /* Manageability event */
|
||||
#define E1000_IMS_DOCK E1000_ICR_DOCK /* Dock/Undock */
|
||||
#define E1000_IMS_RXD_FIFO_PAR0 E1000_ICR_RXD_FIFO_PAR0 /* queue 0 Rx descriptor FIFO parity error */
|
||||
#define E1000_IMS_TXD_FIFO_PAR0 E1000_ICR_TXD_FIFO_PAR0 /* queue 0 Tx descriptor FIFO parity error */
|
||||
#define E1000_IMS_HOST_ARB_PAR E1000_ICR_HOST_ARB_PAR /* host arb read buffer parity error */
|
||||
#define E1000_IMS_PB_PAR E1000_ICR_PB_PAR /* packet buffer parity error */
|
||||
#define E1000_IMS_RXD_FIFO_PAR1 E1000_ICR_RXD_FIFO_PAR1 /* queue 1 Rx descriptor FIFO parity error */
|
||||
#define E1000_IMS_TXD_FIFO_PAR1 E1000_ICR_TXD_FIFO_PAR1 /* queue 1 Tx descriptor FIFO parity error */
|
||||
#define E1000_IMS_DSW E1000_ICR_DSW
|
||||
#define E1000_IMS_PHYINT E1000_ICR_PHYINT
|
||||
#define E1000_IMS_EPRST E1000_ICR_EPRST
|
||||
|
||||
// TX and RX descriptor
|
||||
typedef struct __attribute__((packed))
|
||||
{
|
||||
uint64_t addr;
|
||||
uint16_t length;
|
||||
uint8_t cso;
|
||||
uint8_t cmd;
|
||||
uint8_t status;
|
||||
uint8_t css;
|
||||
uint16_t special;
|
||||
} tx_desc_t;
|
||||
|
||||
typedef struct __attribute__((packed))
|
||||
{
|
||||
uint64_t addr;
|
||||
uint16_t length;
|
||||
uint16_t checksum;
|
||||
uint8_t status;
|
||||
uint8_t errors;
|
||||
uint16_t special;
|
||||
} rx_desc_t;
|
||||
|
||||
/*
|
||||
* Helper struct to hold private data used to operate your ethernet interface.
|
||||
*/
|
||||
typedef struct e1000if {
|
||||
struct eth_addr *ethaddr;
|
||||
/* Add whatever per-interface state that is needed here. */
|
||||
uint8_t* bar0;
|
||||
uint8_t* tx_buffers;
|
||||
uint8_t* rx_buffers;
|
||||
volatile tx_desc_t* tx_desc; // transmit descriptor buffer
|
||||
uint16_t tx_tail;
|
||||
volatile rx_desc_t* rx_desc; // receive descriptor buffer
|
||||
uint16_t rx_tail;
|
||||
uint8_t irq;
|
||||
volatile uint8_t polling;
|
||||
} e1000if_t;
|
||||
|
||||
/*
|
||||
* Initialize the network driver for the RealTek RTL8139 family
|
||||
*/
|
||||
err_t e1000if_init(struct netif* netif);
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
Loading…
Add table
Reference in a new issue