libnetdriver: rewrite

This is a driver-breaking update to the netdriver library, which is
used by all network drivers.  The aim of this change is to make the
library more compatible with NetBSD, and in particular with various
features that are expected to be supported by the NetBSD userland.
The main changes made by this patch are the following:

- each network driver now has a NetBSD-style short device name;
- drivers are not expected to receive packets right after startup;
- extended support for receipt modes, including multicast lists;
- support for multiple parallel send, receive requests;
- embedding of I/O vectors in send and receive requests;
- support for capabilities, including checksum offloading;
- support for reporting link status updates to the TCP/IP stack;
- support for setting and retrieving media status;
- support for changing the hardware (MAC) address;
- support for NetBSD interface flags IFF_DEBUG, IFF_LINK[0-2];
- support for NetBSD error statistics;
- support for regular time-based ("tick") callbacks.

IMPORTANT: this patch applies a minimal update to the existing drivers
in order to make them work at all with the new netdriver library.  It
however does *not* change all drivers to make use of the new features.
In fact, strictly speaking, all drivers are now violating requirements
imposed by the new library in one way or another, most notably by
enabling packet receipt when starting the driver.  Changing all the
drivers to be compliant, and to support the newly added options, is
left to future patches.  The existing drivers should currently *not*
be taken as examples of how to implement a new network driver!

With that said, a few drivers have already been changed to make use of
some of the new features: fxp, e1000, rtl8139, and rtl8169 now report
link and media status, and the last three of those now support setting
the hardware MAC address on the fly.  In addition, dp8390 has been
changed to default to PCI autoconfiguration if no configuration is
specified through environment variables.

Change-Id: I4b3ea9c0b9bc25d5b0609c6ff256fb0db71cdc42
This commit is contained in:
David van Moolenbroek 2016-10-12 04:41:08 +00:00
parent 686761dbbc
commit f7df02e747
63 changed files with 1994 additions and 1701 deletions

View File

@ -10,7 +10,6 @@
#include "3c90x.h"
#define VERBOSE 0 /* verbose debugging output */
#define XLBC_FKEY 11 /* use Shift+Fn to dump statistics (0=off) */
#if VERBOSE
#define XLBC_DEBUG(x) printf x
@ -19,8 +18,6 @@
#endif
static struct {
char name[sizeof("3c90x#0")]; /* driver name */
int hook_id; /* IRQ hook ID */
uint8_t *base; /* base address of memory-mapped registers */
uint32_t size; /* size of memory-mapped register area */
@ -41,8 +38,6 @@ static struct {
size_t txb_tail; /* index of tail TX byte in buffer */
size_t txb_used; /* number of in-use TX buffer bytes */
unsigned int upd_head; /* index of head RX descriptor */
eth_stat_t stat; /* statistics */
} state;
enum xlbc_link_type {
@ -64,24 +59,25 @@ enum xlbc_link_type {
#define XLBC_WRITE_32(off, val) \
(*(volatile uint32_t *)(state.base + (off)) = (val))
static int xlbc_init(unsigned int instance, ether_addr_t *addr);
static int xlbc_init(unsigned int, netdriver_addr_t *, uint32_t *,
unsigned int *);
static void xlbc_stop(void);
static void xlbc_mode(unsigned int mode);
static ssize_t xlbc_recv(struct netdriver_data *data, size_t max);
static int xlbc_send(struct netdriver_data *data, size_t size);
static void xlbc_stat(eth_stat_t *stat);
static void xlbc_intr(unsigned int mask);
static void xlbc_other(const message *m_ptr, int ipc_status);
static void xlbc_set_mode(unsigned int, const netdriver_addr_t *,
unsigned int);
static ssize_t xlbc_recv(struct netdriver_data *, size_t);
static int xlbc_send(struct netdriver_data *, size_t);
static void xlbc_intr(unsigned int);
static void xlbc_tick(void);
static const struct netdriver xlbc_table = {
.ndr_name = "xl",
.ndr_init = xlbc_init,
.ndr_stop = xlbc_stop,
.ndr_mode = xlbc_mode,
.ndr_set_mode = xlbc_set_mode,
.ndr_recv = xlbc_recv,
.ndr_send = xlbc_send,
.ndr_stat = xlbc_stat,
.ndr_intr = xlbc_intr,
.ndr_other = xlbc_other,
.ndr_tick = xlbc_tick
};
/*
@ -108,7 +104,7 @@ xlbc_probe(unsigned int skip)
#if VERBOSE
dname = pci_dev_name(vid, did);
XLBC_DEBUG(("%s: found %s (%04x:%04x) at %s\n", state.name,
XLBC_DEBUG(("%s: found %s (%04x:%04x) at %s\n", netdriver_name(),
dname ? dname : "<unknown>", vid, did, pci_slot_name(devind)));
#endif
@ -223,7 +219,7 @@ xlbc_read_eeprom(unsigned int word)
* Obtain the preconfigured hardware address of the device.
*/
static void
xlbc_get_hwaddr(ether_addr_t * addr)
xlbc_get_hwaddr(netdriver_addr_t * addr)
{
uint16_t word[3];
@ -233,34 +229,35 @@ xlbc_get_hwaddr(ether_addr_t * addr)
word[1] = xlbc_read_eeprom(XLBC_EEPROM_WORD_OEM_ADDR1);
word[2] = xlbc_read_eeprom(XLBC_EEPROM_WORD_OEM_ADDR2);
addr->ea_addr[0] = word[0] >> 8;
addr->ea_addr[1] = word[0] & 0xff;
addr->ea_addr[2] = word[1] >> 8;
addr->ea_addr[3] = word[1] & 0xff;
addr->ea_addr[4] = word[2] >> 8;
addr->ea_addr[5] = word[2] & 0xff;
addr->na_addr[0] = word[0] >> 8;
addr->na_addr[1] = word[0] & 0xff;
addr->na_addr[2] = word[1] >> 8;
addr->na_addr[3] = word[1] & 0xff;
addr->na_addr[4] = word[2] >> 8;
addr->na_addr[5] = word[2] & 0xff;
XLBC_DEBUG(("%s: MAC address %02x:%02x:%02x:%02x:%02x:%02x\n",
state.name, addr->ea_addr[0], addr->ea_addr[1], addr->ea_addr[2],
addr->ea_addr[3], addr->ea_addr[4], addr->ea_addr[5]));
netdriver_name(),
addr->na_addr[0], addr->na_addr[1], addr->na_addr[2],
addr->na_addr[3], addr->na_addr[4], addr->na_addr[5]));
}
/*
* Configure the device to use the given hardware address.
*/
static void
xlbc_set_hwaddr(ether_addr_t * addr)
xlbc_set_hwaddr(netdriver_addr_t * addr)
{
xlbc_select_window(XLBC_STATION_WINDOW);
/* Set station address. */
XLBC_WRITE_16(XLBC_STATION_ADDR0_REG,
addr->ea_addr[0] | (addr->ea_addr[1] << 8));
addr->na_addr[0] | (addr->na_addr[1] << 8));
XLBC_WRITE_16(XLBC_STATION_ADDR1_REG,
addr->ea_addr[2] | (addr->ea_addr[3] << 8));
addr->na_addr[2] | (addr->na_addr[3] << 8));
XLBC_WRITE_16(XLBC_STATION_ADDR2_REG,
addr->ea_addr[4] | (addr->ea_addr[5] << 8));
addr->na_addr[4] | (addr->na_addr[5] << 8));
/* Set station mask. */
XLBC_WRITE_16(XLBC_STATION_MASK0_REG, 0);
@ -527,7 +524,7 @@ xlbc_mii_write(uint16_t phy, uint16_t reg, uint16_t data)
/*
* Return a human-readable description for the given link type.
*/
#if VERBOSE || XLBC_FKEY
#if VERBOSE
static const char *
xlbc_get_link_name(enum xlbc_link_type link_type)
{
@ -542,7 +539,7 @@ xlbc_get_link_name(enum xlbc_link_type link_type)
default: return "(unknown)";
}
}
#endif /* VERBOSE || XLBC_FKEY */
#endif /* VERBOSE */
/*
* Determine the current link status, and return the resulting link type.
@ -625,7 +622,7 @@ xlbc_set_duplex(enum xlbc_link_type link)
* on a link change, so we're probably not doing much extra damage.
* TODO: recovery for packets currently on the transmission queue.
*/
XLBC_DEBUG(("%s: %s full-duplex mode\n", state.name,
XLBC_DEBUG(("%s: %s full-duplex mode\n", netdriver_name(),
duplex ? "setting" : "clearing"));
XLBC_WRITE_16(XLBC_MAC_CTRL_REG, word ^ XLBC_MAC_CTRL_ENA_FD);
@ -654,7 +651,7 @@ xlbc_link_event(void)
link_type = xlbc_get_link_type();
#if VERBOSE
XLBC_DEBUG(("%s: link %s\n", state.name,
XLBC_DEBUG(("%s: link %s\n", netdriver_name(),
xlbc_get_link_name(link_type)));
#endif
@ -665,7 +662,7 @@ xlbc_link_event(void)
* Initialize the device.
*/
static void
xlbc_init_hw(int devind, ether_addr_t * addr)
xlbc_init_hw(int devind, netdriver_addr_t * addr)
{
uint32_t bar;
uint16_t cr;
@ -734,16 +731,12 @@ xlbc_init_hw(int devind, ether_addr_t * addr)
* Initialize the 3c90x driver and device.
*/
static int
xlbc_init(unsigned int instance, ether_addr_t * addr)
xlbc_init(unsigned int instance, netdriver_addr_t * addr, uint32_t * caps,
unsigned int * ticks)
{
int devind;
#if XLBC_FKEY
int fkeys, sfkeys;
#endif
memset(&state, 0, sizeof(state));
strlcpy(state.name, "3c90x#0", sizeof(state.name));
state.name[sizeof(state.name) - 2] += instance;
/* Try to find a recognized device. */
if ((devind = xlbc_probe(instance)) < 0)
@ -752,13 +745,8 @@ xlbc_init(unsigned int instance, ether_addr_t * addr)
/* Initialize the device. */
xlbc_init_hw(devind, addr);
#if XLBC_FKEY
/* Register debug dump function key. */
fkeys = sfkeys = 0;
bit_set(sfkeys, XLBC_FKEY);
(void)fkey_map(&fkeys, &sfkeys); /* ignore failure */
#endif
*caps = NDEV_CAP_MCAST | NDEV_CAP_BCAST;
*ticks = sys_hz() / 10; /* update statistics 10x/sec */
return OK;
}
@ -777,16 +765,17 @@ xlbc_stop(void)
* Set packet receipt mode.
*/
static void
xlbc_mode(unsigned int mode)
xlbc_set_mode(unsigned int mode, const netdriver_addr_t * mcast_list __unused,
unsigned int mcast_count __unused)
{
state.filter = XLBC_FILTER_STATION;
if (mode & NDEV_MULTI)
if (mode & (NDEV_MODE_MCAST_LIST | NDEV_MODE_MCAST_ALL))
state.filter |= XLBC_FILTER_MULTI;
if (mode & NDEV_BROAD)
if (mode & NDEV_MODE_BCAST)
state.filter |= XLBC_FILTER_BROAD;
if (mode & NDEV_PROMISC)
if (mode & NDEV_MODE_PROMISC)
state.filter |= XLBC_FILTER_PROMISC;
xlbc_issue_cmd(XLBC_CMD_SET_FILTER | state.filter);
@ -814,22 +803,16 @@ xlbc_recv(struct netdriver_data * data, size_t max)
return SUSPEND;
if (flags & XLBC_UP_ERROR) {
XLBC_DEBUG(("%s: received error\n", state.name));
XLBC_DEBUG(("%s: received error\n", netdriver_name()));
state.stat.ets_recvErr++;
if (flags & XLBC_UP_OVERRUN)
state.stat.ets_fifoOver++;
if (flags & XLBC_UP_ALIGN_ERR)
state.stat.ets_frameAll++;
if (flags & XLBC_UP_CRC_ERR)
state.stat.ets_CRCerr++;
netdriver_stat_ierror(1);
len = 0; /* immediately move on to the next descriptor */
} else {
len = flags & XLBC_UP_LEN;
XLBC_DEBUG(("%s: received packet (size %zu)\n", state.name,
len));
XLBC_DEBUG(("%s: received packet (size %zu)\n",
netdriver_name(), len));
/* The device is supposed to not give us runt frames. */
assert(len >= XLBC_MIN_PKT_LEN);
@ -902,7 +885,8 @@ xlbc_send(struct netdriver_data * data, size_t size)
if (left < size)
return SUSPEND;
XLBC_DEBUG(("%s: transmitting packet (size %zu)\n", state.name, size));
XLBC_DEBUG(("%s: transmitting packet (size %zu)\n",
netdriver_name(), size));
/* Copy in the packet. */
off = (state.txb_tail + used) % XLBC_TXB_SIZE;
@ -966,7 +950,8 @@ xlbc_advance_tx(void)
if (!(flags & XLBC_DN_DN_COMPLETE))
break;
XLBC_DEBUG(("%s: packet copied to transmitter\n", state.name));
XLBC_DEBUG(("%s: packet copied to transmitter\n",
netdriver_name()));
len = state.dpd_base[state.dpd_tail].len & ~XLBC_LEN_LAST;
@ -995,25 +980,20 @@ xlbc_recover_tx(void)
while ((status = XLBC_READ_8(XLBC_TX_STATUS_REG)) &
XLBC_TX_STATUS_COMPLETE) {
XLBC_DEBUG(("%s: transmission error (0x%04x)\n", state.name,
status));
XLBC_DEBUG(("%s: transmission error (0x%04x)\n",
netdriver_name(), status));
/* This is an internal (non-packet) error status. */
if (status & XLBC_TX_STATUS_OVERFLOW)
enable = TRUE;
if (status & XLBC_TX_STATUS_MAX_COLL) {
state.stat.ets_sendErr++;
state.stat.ets_transAb++;
netdriver_stat_coll(1);
enable = TRUE;
}
if (status & XLBC_TX_STATUS_UNDERRUN) {
state.stat.ets_sendErr++;
state.stat.ets_fifoUnder++;
reset = TRUE;
}
if (status & XLBC_TX_STATUS_JABBER) {
state.stat.ets_sendErr++;
if (status &
(XLBC_TX_STATUS_UNDERRUN | XLBC_TX_STATUS_JABBER)) {
netdriver_stat_oerror(1);
reset = TRUE;
}
@ -1047,7 +1027,7 @@ xlbc_recover_tx(void)
XLBC_WRITE_32(XLBC_DN_LIST_PTR_REG,
state.dpd_phys + state.dpd_tail * sizeof(xlbc_pd_t));
XLBC_DEBUG(("%s: performed recovery\n", state.name));
XLBC_DEBUG(("%s: performed recovery\n", netdriver_name()));
} else if (enable)
xlbc_issue_cmd(XLBC_CMD_TX_ENABLE);
}
@ -1059,24 +1039,20 @@ xlbc_recover_tx(void)
static void
xlbc_update_stats(void)
{
uint8_t upper, up_rx, up_tx;
xlbc_select_window(XLBC_STATS_WINDOW);
state.stat.ets_carrSense += XLBC_READ_8(XLBC_CARRIER_LOST_REG);
(void)XLBC_READ_8(XLBC_CARRIER_LOST_REG);
(void)XLBC_READ_8(XLBC_SQE_ERR_REG);
state.stat.ets_collision += XLBC_READ_8(XLBC_MULTI_COLL_REG);
state.stat.ets_collision += XLBC_READ_8(XLBC_SINGLE_COLL_REG);
state.stat.ets_OWC += XLBC_READ_8(XLBC_LATE_COLL_REG);
state.stat.ets_missedP += XLBC_READ_8(XLBC_RX_OVERRUNS_REG);
state.stat.ets_transDef += XLBC_READ_8(XLBC_FRAMES_DEFERRED_REG);
netdriver_stat_coll(XLBC_READ_8(XLBC_MULTI_COLL_REG));
netdriver_stat_coll(XLBC_READ_8(XLBC_SINGLE_COLL_REG));
netdriver_stat_coll(XLBC_READ_8(XLBC_LATE_COLL_REG));
netdriver_stat_ierror(XLBC_READ_8(XLBC_RX_OVERRUNS_REG));
(void)XLBC_READ_8(XLBC_FRAMES_DEFERRED_REG);
upper = XLBC_READ_8(XLBC_UPPER_FRAMES_REG);
up_tx = ((upper & XLBC_UPPER_TX_MASK) >> XLBC_UPPER_TX_SHIFT) << 8;
up_rx = ((upper & XLBC_UPPER_RX_MASK) >> XLBC_UPPER_RX_SHIFT) << 8;
state.stat.ets_packetT += XLBC_READ_8(XLBC_FRAMES_XMIT_OK_REG) + up_tx;
state.stat.ets_packetR += XLBC_READ_8(XLBC_FRAMES_RCVD_OK_REG) + up_rx;
(void)XLBC_READ_8(XLBC_UPPER_FRAMES_REG);
(void)XLBC_READ_8(XLBC_FRAMES_XMIT_OK_REG);
(void)XLBC_READ_8(XLBC_FRAMES_RCVD_OK_REG);
(void)XLBC_READ_16(XLBC_BYTES_RCVD_OK_REG);
(void)XLBC_READ_16(XLBC_BYTES_XMIT_OK_REG);
@ -1086,18 +1062,6 @@ xlbc_update_stats(void)
(void)XLBC_READ_8(XLBC_BAD_SSD_REG);
}
/*
* Copy out statistics.
*/
static void
xlbc_stat(eth_stat_t * stat)
{
xlbc_update_stats();
memcpy(stat, &state.stat, sizeof(*stat));
}
/*
* Process an interrupt.
*/
@ -1116,7 +1080,7 @@ xlbc_intr(unsigned int __unused mask)
*/
val = XLBC_READ_16(XLBC_STATUS_AUTO_REG);
XLBC_DEBUG(("%s: interrupt (0x%04x)\n", state.name, val));
XLBC_DEBUG(("%s: interrupt (0x%04x)\n", netdriver_name(), val));
if (val & XLBC_STATUS_UP_COMPLETE)
netdriver_recv();
@ -1136,7 +1100,8 @@ xlbc_intr(unsigned int __unused mask)
* Since this entire condition is effectively untestable, we
* do not even try to be smart about it.
*/
XLBC_DEBUG(("%s: host error, performing reset\n", state.name));
XLBC_DEBUG(("%s: host error, performing reset\n",
netdriver_name()));
xlbc_reset_tx();
@ -1166,61 +1131,13 @@ xlbc_intr(unsigned int __unused mask)
}
/*
* Dump statistics.
* Do regular processing.
*/
#if XLBC_FKEY
static void
xlbc_dump(void)
xlbc_tick(void)
{
enum xlbc_link_type link_type;
link_type = xlbc_get_link_type();
xlbc_update_stats();
printf("\n");
printf("%s statistics:\n", state.name);
printf("recvErr: %8ld\t", state.stat.ets_recvErr);
printf("sendErr: %8ld\t", state.stat.ets_sendErr);
printf("OVW: %8ld\n", state.stat.ets_OVW);
printf("CRCerr: %8ld\t", state.stat.ets_CRCerr);
printf("frameAll: %8ld\t", state.stat.ets_frameAll);
printf("missedP: %8ld\n", state.stat.ets_missedP);
printf("packetR: %8ld\t", state.stat.ets_packetR);
printf("packetT: %8ld\t", state.stat.ets_packetT);
printf("transDef: %8ld\n", state.stat.ets_transDef);
printf("collision: %8ld\t", state.stat.ets_collision);
printf("transAb: %8ld\t", state.stat.ets_transAb);
printf("carrSense: %8ld\n", state.stat.ets_carrSense);
printf("fifoUnder: %8ld\t", state.stat.ets_fifoUnder);
printf("fifoOver: %8ld\t", state.stat.ets_fifoOver);
printf("CDheartbeat: %8ld\n", state.stat.ets_CDheartbeat);
printf("OWC: %8ld\t", state.stat.ets_OWC);
printf("link: %s\n", xlbc_get_link_name(link_type));
}
#endif /* XLBC_FKEY */
/*
* Process miscellaneous messages.
*/
static void
xlbc_other(const message * m_ptr, int ipc_status)
{
#if XLBC_FKEY
int sfkeys;
if (!is_ipc_notify(ipc_status) || m_ptr->m_source != TTY_PROC_NR)
return;
if (fkey_events(NULL, &sfkeys) == OK && bit_isset(sfkeys, XLBC_FKEY))
xlbc_dump();
#endif /* XLBC_FKEY */
}
/*

View File

@ -21,8 +21,8 @@
#define XLBC_TXB_SIZE 48128 /* TX buffer size in bytes */
#define XLBC_UPD_COUNT 32 /* RX descriptor count */
#define XLBC_MIN_PKT_LEN ETH_MIN_PACK_SIZE
#define XLBC_MAX_PKT_LEN ETH_MAX_PACK_SIZE_TAGGED
#define XLBC_MIN_PKT_LEN NDEV_ETH_PACKET_MIN
#define XLBC_MAX_PKT_LEN NDEV_ETH_PACKET_MAX_TAGGED
#define XLBC_MIN_REG_SIZE 128 /* min. register memory size */

View File

@ -9,4 +9,6 @@ FILESDIR= /etc/system.conf.d
DPADD+= ${LIBNETDRIVER} ${LIBSYS}
LDADD+= -lnetdriver -lsys
WARNS?= 5
.include <minix.service.mk>

View File

@ -9,4 +9,6 @@ FILESDIR= /etc/system.conf.d
DPADD+= ${LIBNETDRIVER} ${LIBSYS}
LDADD+= -lnetdriver -lsys
WARNS?= 5
.include <minix.service.mk>

View File

@ -14,7 +14,6 @@
#include "atl2.h"
#define VERBOSE 0 /* Verbose debugging output */
#define ATL2_FKEY 11 /* Use Shift+Fn to dump statistics (0=off) */
#if VERBOSE
#define ATL2_DEBUG(x) printf x
@ -54,8 +53,6 @@ static struct {
int rxd_tail; /* tail index into RxD, in elements */
int rx_avail; /* is there a packet available for receipt? */
eth_stat_t stat; /* statistics */
} state;
#define ATL2_READ_U8(off) (*(volatile uint8_t *)(state.base + (off)))
@ -70,24 +67,23 @@ static struct {
#define ATL2_ALIGN_32(n) (((n) + 3) & ~3)
static int atl2_init(unsigned int instance, ether_addr_t *addr);
static int atl2_init(unsigned int, netdriver_addr_t *, uint32_t *,
unsigned int *);
static void atl2_stop(void);
static void atl2_mode(unsigned int mode);
static int atl2_send(struct netdriver_data *data, size_t size);
static ssize_t atl2_recv(struct netdriver_data *data, size_t max);
static void atl2_stat(eth_stat_t *stat);
static void atl2_set_mode(unsigned int, const netdriver_addr_t *,
unsigned int);
static int atl2_send(struct netdriver_data *, size_t);
static ssize_t atl2_recv(struct netdriver_data *, size_t);
static void atl2_intr(unsigned int mask);
static void atl2_other(const message *m_ptr, int ipc_status);
static const struct netdriver atl2_table = {
.ndr_name = "lii",
.ndr_init = atl2_init,
.ndr_stop = atl2_stop,
.ndr_mode = atl2_mode,
.ndr_set_mode = atl2_set_mode,
.ndr_recv = atl2_recv,
.ndr_send = atl2_send,
.ndr_stat = atl2_stat,
.ndr_intr = atl2_intr,
.ndr_other = atl2_other
};
/*
@ -115,7 +111,8 @@ atl2_read_vpd(int index, uint32_t * res)
}
if (i == ATL2_VPD_NTRIES) {
printf("ATL2: timeout reading EEPROM register %d\n", index);
printf("%s: timeout reading EEPROM register %d\n",
netdriver_name(), index);
return FALSE;
}
@ -181,27 +178,28 @@ atl2_get_vpd_hwaddr(void)
* use whatever the card was already set to.
*/
static void
atl2_get_hwaddr(ether_addr_t * addr)
atl2_get_hwaddr(netdriver_addr_t * addr)
{
if (!atl2_get_vpd_hwaddr()) {
printf("ATL2: unable to read from VPD\n");
printf("%s: unable to read from VPD\n", netdriver_name());
state.hwaddr[0] = ATL2_READ_U32(ATL2_HWADDR0_REG);
state.hwaddr[1] = ATL2_READ_U32(ATL2_HWADDR1_REG) & 0xffff;
}
ATL2_DEBUG(("ATL2: MAC address %04x%08x\n",
state.hwaddr[1], state.hwaddr[0]));
ATL2_DEBUG(("%s: MAC address %04x%08x\n",
netdriver_name(), state.hwaddr[1], state.hwaddr[0]));
addr->ea_addr[0] = state.hwaddr[1] >> 8;
addr->ea_addr[1] = state.hwaddr[1] & 0xff;
addr->ea_addr[2] = state.hwaddr[0] >> 24;
addr->ea_addr[3] = (state.hwaddr[0] >> 16) & 0xff;
addr->ea_addr[4] = (state.hwaddr[0] >> 8) & 0xff;
addr->ea_addr[5] = state.hwaddr[0] & 0xff;
addr->na_addr[0] = state.hwaddr[1] >> 8;
addr->na_addr[1] = state.hwaddr[1] & 0xff;
addr->na_addr[2] = state.hwaddr[0] >> 24;
addr->na_addr[3] = (state.hwaddr[0] >> 16) & 0xff;
addr->na_addr[4] = (state.hwaddr[0] >> 8) & 0xff;
addr->na_addr[5] = state.hwaddr[0] & 0xff;
}
#if 0 /* TODO: link status */
/*
* Read a MII PHY register using MDIO.
*/
@ -231,6 +229,7 @@ atl2_read_mdio(int addr, uint16_t * res)
*res = (uint16_t)(rval & ATL2_MDIO_DATA_MASK);
return TRUE;
}
#endif
/*
* Allocate DMA ring buffers.
@ -340,18 +339,19 @@ atl2_reset(void)
* settings.
*/
static void
atl2_mode(unsigned int mode)
atl2_set_mode(unsigned int mode, const netdriver_addr_t * mcast_list __unused,
unsigned int mcast_count __unused)
{
uint32_t val;
val = ATL2_READ_U32(ATL2_MAC_REG);
val &= ~(ATL2_MAC_PROMISC_EN | ATL2_MAC_MCAST_EN | ATL2_MAC_BCAST_EN);
if (mode & NDEV_PROMISC)
if (mode & NDEV_MODE_PROMISC)
val |= ATL2_MAC_PROMISC_EN;
if (mode & NDEV_MULTI)
if (mode & (NDEV_MODE_MCAST_LIST | NDEV_MODE_MCAST_ALL))
val |= ATL2_MAC_MCAST_EN;
if (mode & NDEV_BROAD)
if (mode & NDEV_MODE_BCAST)
val |= ATL2_MAC_BCAST_EN;
ATL2_WRITE_U32(ATL2_MAC_REG, val);
@ -428,7 +428,7 @@ atl2_setup(void)
/* Did everything go alright? */
val = ATL2_READ_U32(ATL2_ISR_REG);
if (val & ATL2_ISR_PHY_LINKDOWN) {
printf("ATL2: initialization failed\n");
printf("%s: initialization failed\n", netdriver_name());
return FALSE;
}
@ -442,15 +442,10 @@ atl2_setup(void)
/* Configure MAC. */
ATL2_WRITE_U32(ATL2_MAC_REG, ATL2_MAC_DEFAULT);
/*
* Inet does not tell us about the multicast addresses that it is
* interested in, so we have to simply accept all multicast packets.
*/
/* TODO: multicast lists. */
ATL2_WRITE_U32(ATL2_MHT0_REG, 0xffffffff);
ATL2_WRITE_U32(ATL2_MHT1_REG, 0xffffffff);
atl2_mode(NDEV_NOMODE);
/* Enable Tx/Rx. */
val = ATL2_READ_U32(ATL2_MAC_REG);
ATL2_WRITE_U32(ATL2_MAC_REG, val | ATL2_MAC_TX_EN | ATL2_MAC_RX_EN);
@ -466,7 +461,7 @@ atl2_probe(int skip)
{
uint16_t vid, did;
#if VERBOSE
char *dname;
const char *dname;
#endif
int r, devind;
@ -484,7 +479,7 @@ atl2_probe(int skip)
#if VERBOSE
dname = pci_dev_name(vid, did);
ATL2_DEBUG(("ATL2: found %s (%x/%x) at %s\n",
ATL2_DEBUG(("%s: found %s (%x/%x) at %s\n", netdriver_name(),
dname ? dname : "<unknown>", vid, did, pci_slot_name(devind)));
#endif
@ -497,7 +492,7 @@ atl2_probe(int skip)
* Initialize the device.
*/
static void
atl2_init_hw(int devind, ether_addr_t * addr)
atl2_init_hw(int devind, netdriver_addr_t * addr)
{
uint32_t bar;
int r, flag;
@ -543,22 +538,12 @@ atl2_tx_stat(uint32_t stat)
{
if (stat & ATL2_TXS_SUCCESS)
state.stat.ets_packetT++;
else
state.stat.ets_recvErr++;
return;
if (stat & ATL2_TXS_DEFER)
state.stat.ets_transDef++;
if (stat & (ATL2_TXS_EXCDEFER | ATL2_TXS_ABORTCOL))
state.stat.ets_transAb++;
if (stat & ATL2_TXS_SINGLECOL)
state.stat.ets_collision++;
if (stat & ATL2_TXS_MULTICOL)
state.stat.ets_collision++;
if (stat & ATL2_TXS_LATECOL)
state.stat.ets_OWC++;
if (stat & ATL2_TXS_UNDERRUN)
state.stat.ets_fifoUnder++;
if (stat & (ATL2_TXS_SINGLECOL | ATL2_TXS_MULTICOL | ATL2_TXS_LATECOL))
netdriver_stat_coll(1);
else
netdriver_stat_oerror(1);
}
/*
@ -568,19 +553,8 @@ static void
atl2_rx_stat(uint32_t stat)
{
if (stat & ATL2_RXD_SUCCESS)
state.stat.ets_packetR++;
else
state.stat.ets_recvErr++;
if (stat & ATL2_RXD_CRCERR)
state.stat.ets_CRCerr++;
if (stat & ATL2_RXD_FRAG)
state.stat.ets_collision++;
if (stat & ATL2_RXD_TRUNC)
state.stat.ets_fifoOver++;
if (stat & ATL2_RXD_ALIGN)
state.stat.ets_frameAll++;
if (!(stat & ATL2_RXD_SUCCESS))
netdriver_stat_ierror(1);
}
/*
@ -612,8 +586,8 @@ atl2_tx_advance(void)
dsize =
*(volatile uint32_t *)(state.txd_base + state.txd_tail);
if (size != dsize)
printf("ATL2: TxD/TxS size mismatch (%x vs %x)\n",
size, dsize);
printf("%s: TxD/TxS size mismatch (%x vs %x)\n",
netdriver_name(), size, dsize);
/* Advance tails accordingly. */
size = sizeof(uint32_t) + ATL2_ALIGN_32(dsize);
@ -625,9 +599,11 @@ atl2_tx_advance(void)
state.txs_num--;
if (stat & ATL2_TXS_SUCCESS)
ATL2_DEBUG(("ATL2: successfully sent packet\n"));
ATL2_DEBUG(("%s: successfully sent packet\n",
netdriver_name()));
else
ATL2_DEBUG(("ATL2: failed to send packet\n"));
ATL2_DEBUG(("%s: failed to send packet\n",
netdriver_name()));
/* Update statistics. */
atl2_tx_stat(stat);
@ -657,7 +633,8 @@ atl2_rx_advance(int next)
state.rxd_tail = (state.rxd_tail + 1) % ATL2_RXD_COUNT;
update_tail = TRUE;
ATL2_DEBUG(("ATL2: successfully received packet\n"));
ATL2_DEBUG(("%s: successfully received packet\n",
netdriver_name()));
state.rx_avail = FALSE;
}
@ -685,15 +662,15 @@ atl2_rx_advance(int next)
size = hdr & ATL2_RXD_SIZE_MASK;
if ((hdr & ATL2_RXD_SUCCESS) &&
size >= ETH_MIN_PACK_SIZE + ETH_CRC_SIZE) {
ATL2_DEBUG(("ATL2: packet available, size %zu\n",
size));
size >= NDEV_ETH_PACKET_MIN + NDEV_ETH_PACKET_CRC) {
ATL2_DEBUG(("%s: packet available, size %zu\n",
netdriver_name(), size));
state.rx_avail = TRUE;
break;
}
ATL2_DEBUG(("ATL2: packet receipt failed\n"));
ATL2_DEBUG(("%s: packet receipt failed\n", netdriver_name()));
/* Advance tail. */
state.rxd_tail = (state.rxd_tail + 1) % ATL2_RXD_COUNT;
@ -725,9 +702,10 @@ atl2_recv(struct netdriver_data * data, size_t max)
rxd = &state.rxd_base[state.rxd_tail];
size = rxd->hdr & ATL2_RXD_SIZE_MASK;
size -= ETH_CRC_SIZE;
size -= NDEV_ETH_PACKET_CRC;
ATL2_DEBUG(("ATL2: receiving packet with length %zu\n", size));
ATL2_DEBUG(("%s: receiving packet with length %zu\n",
netdriver_name(), size));
/* Truncate large packets. */
if (size > max)
@ -810,7 +788,7 @@ atl2_intr(unsigned int __unused mask)
ATL2_WRITE_U32(ATL2_ISR_REG, val | ATL2_ISR_DISABLE);
ATL2_DEBUG(("ATL2: interrupt (0x%08x)\n", val));
ATL2_DEBUG(("%s: interrupt (0x%08x)\n", netdriver_name(), val));
/* If an error occurred, reset the card. */
if (val & (ATL2_ISR_DMAR_TIMEOUT | ATL2_ISR_DMAW_TIMEOUT |
@ -847,16 +825,7 @@ atl2_intr(unsigned int __unused mask)
netdriver_recv();
}
/*
* Copy out statistics.
*/
static void
atl2_stat(eth_stat_t * stat)
{
memcpy(stat, &state.stat, sizeof(*stat));
}
#if 0 /* TODO: link status (using part of this code) */
/*
* Dump link status.
*/
@ -892,76 +861,16 @@ atl2_dump_link(void)
printf("%s duplex)", (val & ATL2_MII_PSSR_DUPLEX) ? "full" : "half");
}
/*
* Dump statistics.
*/
static void
atl2_dump(void)
{
printf("\n");
printf("Attansic L2 statistics:\n");
printf("recvErr: %8ld\t", state.stat.ets_recvErr);
printf("sendErr: %8ld\t", state.stat.ets_sendErr);
printf("OVW: %8ld\n", state.stat.ets_OVW);
printf("CRCerr: %8ld\t", state.stat.ets_CRCerr);
printf("frameAll: %8ld\t", state.stat.ets_frameAll);
printf("missedP: %8ld\n", state.stat.ets_missedP);
printf("packetR: %8ld\t", state.stat.ets_packetR);
printf("packetT: %8ld\t", state.stat.ets_packetT);
printf("transDef: %8ld\n", state.stat.ets_transDef);
printf("collision: %8ld\t", state.stat.ets_collision);
printf("transAb: %8ld\t", state.stat.ets_transAb);
printf("carrSense: %8ld\n", state.stat.ets_carrSense);
printf("fifoUnder: %8ld\t", state.stat.ets_fifoUnder);
printf("fifoOver: %8ld\t", state.stat.ets_fifoOver);
printf("CDheartbeat: %8ld\n", state.stat.ets_CDheartbeat);
printf("OWC: %8ld\t", state.stat.ets_OWC);
printf("TxD tail: %8d\t", state.txd_tail);
printf("TxD count: %8d\n", state.txd_num);
printf("RxD tail: %8d\t", state.rxd_tail);
printf("TxS tail: %8d\t", state.txs_tail);
printf("TxS count: %8d\n", state.txs_num);
atl2_dump_link();
printf("\n");
}
/*
* Process miscellaneous messages.
*/
static void
atl2_other(const message * m_ptr, int ipc_status)
{
#if ATL2_FKEY
int sfkeys;
if (!is_ipc_notify(ipc_status) || m_ptr->m_source != TTY_PROC_NR)
return;
if (fkey_events(NULL, &sfkeys) == OK && bit_isset(sfkeys, ATL2_FKEY))
atl2_dump();
#endif
}
/*
* Initialize the atl2 driver.
*/
static int
atl2_init(unsigned int instance, ether_addr_t * addr)
atl2_init(unsigned int instance, netdriver_addr_t * addr, uint32_t * caps,
unsigned int * ticks __unused)
{
int devind;
#if ATL2_FKEY
int r, fkeys, sfkeys;
#endif
memset(&state, 0, sizeof(state));
@ -974,15 +883,7 @@ atl2_init(unsigned int instance, ether_addr_t * addr)
/* Initialize the device. */
atl2_init_hw(devind, addr);
#if ATL2_FKEY
/* Register debug dump function key. */
fkeys = sfkeys = 0;
bit_set(sfkeys, ATL2_FKEY);
if ((r = fkey_map(&fkeys, &sfkeys)) != OK)
printf("ATL2: warning, could not map Shift+F%u key (%d)\n",
r, ATL2_FKEY);
#endif
*caps = NDEV_CAP_MCAST | NDEV_CAP_BCAST;
return OK;
}

View File

@ -94,7 +94,7 @@
# define ATL2_ICT_DEFAULT 50000 /* 100 ms */
#define ATL2_MTU_REG 0x149c /* MTU config */
# define ATL2_MTU_DEFAULT ETH_MAX_PACK_SIZE_TAGGED
# define ATL2_MTU_DEFAULT NDEV_ETH_PACKET_MAX
#define ATL2_CUT_THRESH_REG 0x1590 /* cut-through config */
# define ATL2_CUT_THRESH_DEFAULT 0x177 /* (magic) */

View File

@ -11,4 +11,6 @@ LDADD+= -lnetdriver -lsys
CPPFLAGS+= -Ddebug=0
WARNS?= 5
.include <minix.service.mk>

View File

@ -10,19 +10,4 @@ This driver supports only the Dec21140A as emulated by VPC2007. It is
untested in any other environment and will probably panic if you use it
outside VPC2007.
The driver supports bridged, nat and local network settings. See the
next section for a remark on seting up a nat environment.
Only one card can be used at a time, do not activate multiple network
cards in VPC2007, the driver will panic.
NOTE FOR USERS CONFIGURING VPC2007 TO USE NAT:
in /usr/etc/rc comment out the following three lines:
trap '' 2
intr -t 20 hostaddr -h
trap 2
VPC2007 does not play well with hostaddr and it will hang the boot process
until you CTRL-C out of it.
The driver supports bridged, nat and local network settings.

View File

@ -20,31 +20,30 @@
static u32_t io_inl(u16_t);
static void io_outl(u16_t, u32_t);
static int do_init(unsigned int, ether_addr_t *);
static int do_init(unsigned int, netdriver_addr_t *, uint32_t *,
unsigned int *);
static void do_stop(void);
static int do_send(struct netdriver_data *, size_t);
static ssize_t do_recv(struct netdriver_data *, size_t);
static void do_stat(eth_stat_t *);
static void do_intr(unsigned int);
static int de_probe(dpeth_t *, unsigned int skip);
static void de_conf_addr(dpeth_t *, ether_addr_t *);
static void de_conf_addr(dpeth_t *, netdriver_addr_t *);
static void de_init_buf(dpeth_t *);
static void de_reset(const dpeth_t *);
static void de_hw_conf(const dpeth_t *);
static void de_start(const dpeth_t *);
static void de_setup_frame(const dpeth_t *, const ether_addr_t *);
static void de_setup_frame(const dpeth_t *, const netdriver_addr_t *);
static u16_t de_read_rom(const dpeth_t *, u8_t, u8_t);
static dpeth_t de_state;
static int de_instance;
static const struct netdriver de_table = {
.ndr_name = "dec",
.ndr_init = do_init,
.ndr_stop = do_stop,
.ndr_recv = do_recv,
.ndr_send = do_send,
.ndr_stat = do_stat,
.ndr_intr = do_intr
};
@ -57,7 +56,7 @@ int main(int argc, char *argv[])
return 0;
}
static void de_init_hw(dpeth_t *dep, ether_addr_t *addr)
static void de_init_hw(dpeth_t *dep, netdriver_addr_t *addr)
{
de_reset(dep);
de_conf_addr(dep, addr);
@ -76,7 +75,8 @@ static void de_init_hw(dpeth_t *dep, ether_addr_t *addr)
de_start(dep);
}
static int do_init(unsigned int instance, ether_addr_t *addr)
static int do_init(unsigned int instance, netdriver_addr_t *addr,
uint32_t *caps, unsigned int *ticks)
{
/* Initialize the DEC 21140A driver. */
dpeth_t *dep;
@ -84,24 +84,15 @@ static int do_init(unsigned int instance, ether_addr_t *addr)
dep = &de_state;
memset(dep, 0, sizeof(*dep));
strlcpy(dep->de_name, "dec21140A:?", sizeof(dep->de_name));
dep->de_name[strlen(dep->de_name)-1] = '0' + instance;
de_instance = instance;
if (!de_probe(dep, instance))
return ENXIO;
de_init_hw(dep, addr);
*caps = NDEV_CAP_MCAST | NDEV_CAP_BCAST;
return OK;
}
static void do_stat(eth_stat_t *stat)
{
memcpy(stat, &de_state.de_stat, sizeof(*stat));
}
static int de_probe(dpeth_t *dep, unsigned int skip)
{
int r, devind;
@ -131,14 +122,15 @@ static int de_probe(dpeth_t *dep, unsigned int skip)
panic("de_probe: base address invalid: %d", dep->de_base_port);
DEBUG(printf("%s: using I/O address 0x%lx, IRQ %d\n",
dep->de_name, (unsigned long)dep->de_base_port,
netdriver_name(), (unsigned long)dep->de_base_port,
dep->de_irq));
dep->de_type = pci_attr_r8(devind, PCI_REV);
/* device validation. We support only the DEC21140A */
if(dep->de_type != DEC_21140A){
printf("%s: unsupported card type %x\n", dep->de_name, dep->de_type);
printf("%s: unsupported card type %x\n", netdriver_name(),
dep->de_type);
return FALSE;
}
@ -252,8 +244,6 @@ static ssize_t do_recv(struct netdriver_data *data, size_t max)
netdriver_copyout(data, 0, descr->buf1, size);
dep->de_stat.ets_packetR++;
descr->descr->des[DES0]=DES0_OWN;
dep->cur_descr[DESCR_RECV]++;
if(dep->cur_descr[DESCR_RECV] >= DE_NB_RECV_DESCR)
@ -264,7 +254,7 @@ static ssize_t do_recv(struct netdriver_data *data, size_t max)
return size;
}
static void de_conf_addr(dpeth_t *dep, ether_addr_t *addr)
static void de_conf_addr(dpeth_t *dep, netdriver_addr_t *addr)
{
u16_t temp16;
int i;
@ -281,8 +271,8 @@ static void de_conf_addr(dpeth_t *dep, ether_addr_t *addr)
/* acquire MAC addr */
DEBUG(printf("Using MAC addr= "));
for(i=0;i<6;i++){
addr->ea_addr[i] = dep->srom[i+DE_SROM_EA_OFFSET];
DEBUG(printf("%02X%c", addr->ea_addr[i],i!=5?'-':'\n'));
addr->na_addr[i] = dep->srom[i+DE_SROM_EA_OFFSET];
DEBUG(printf("%02X%c", addr->na_addr[i],i!=5?'-':'\n'));
}
DEBUG(printf("probe success\n"));
}
@ -436,7 +426,7 @@ static void de_start(const dpeth_t *dep)
io_outl(CSR_ADDR(dep, CSR6), val);
}
static void de_setup_frame(const dpeth_t *dep, const ether_addr_t *addr)
static void de_setup_frame(const dpeth_t *dep, const netdriver_addr_t *addr)
{
int i;
u32_t val;
@ -451,12 +441,12 @@ static void de_setup_frame(const dpeth_t *dep, const ether_addr_t *addr)
dep->descr[DESCR_TRAN][0].buf1[9] = 0xFF;
for(i=1;i<16;i++){
memset(&(dep->descr[DESCR_TRAN][0].buf1[12*i]), 0, 12);
dep->descr[DESCR_TRAN][0].buf1[12*i+0] = addr->ea_addr[0];
dep->descr[DESCR_TRAN][0].buf1[12*i+1] = addr->ea_addr[1];
dep->descr[DESCR_TRAN][0].buf1[12*i+4] = addr->ea_addr[2];
dep->descr[DESCR_TRAN][0].buf1[12*i+5] = addr->ea_addr[3];
dep->descr[DESCR_TRAN][0].buf1[12*i+8] = addr->ea_addr[4];
dep->descr[DESCR_TRAN][0].buf1[12*i+9] = addr->ea_addr[5];
dep->descr[DESCR_TRAN][0].buf1[12*i+0] = addr->na_addr[0];
dep->descr[DESCR_TRAN][0].buf1[12*i+1] = addr->na_addr[1];
dep->descr[DESCR_TRAN][0].buf1[12*i+4] = addr->na_addr[2];
dep->descr[DESCR_TRAN][0].buf1[12*i+5] = addr->na_addr[3];
dep->descr[DESCR_TRAN][0].buf1[12*i+8] = addr->na_addr[4];
dep->descr[DESCR_TRAN][0].buf1[12*i+9] = addr->na_addr[5];
}
dep->descr[DESCR_TRAN][0].descr->des[DES0] = DES0_OWN;
@ -499,8 +489,6 @@ static int do_send(struct netdriver_data *data, size_t size)
io_outl(CSR_ADDR(dep, CSR1), 0xFFFFFFFF);
dep->de_stat.ets_packetT++;
return OK;
}

View File

@ -18,9 +18,9 @@ Created: 09/01/2009 Nicolas Tittley (first.last @ gmail DOT com)
#endif
#define DE_NB_SEND_DESCR 32
#define DE_SEND_BUF_SIZE (ETH_MAX_PACK_SIZE+2)
#define DE_SEND_BUF_SIZE (NDEV_ETH_PACKET_MAX+2)
#define DE_NB_RECV_DESCR 32
#define DE_RECV_BUF_SIZE (ETH_MAX_PACK_SIZE+2)
#define DE_RECV_BUF_SIZE (NDEV_ETH_PACKET_MAX+2)
#define DE_MIN_BASE_ADDR 0x0400
#define DE_SROM_EA_OFFSET 20
@ -37,15 +37,12 @@ typedef struct de_local_descr {
} de_loc_descr_t;
typedef struct dpeth {
char de_name[32]; /* Name of this interface */
port_t de_base_port; /* Base port, for multiple card instance */
int de_irq; /* IRQ line number */
int de_hook; /* interrupt hook at kernel */
int de_type; /* What kind of hardware */
eth_stat_t de_stat; /* Stats */
/* Space reservation. We will allocate all structures later in the code.
here we just make sure we have the space we need at compile time */
u8_t sendrecv_descr_buf[(DE_NB_SEND_DESCR+DE_NB_RECV_DESCR)*

View File

@ -14,9 +14,6 @@
#include <minix/drivers.h>
#include <minix/netdriver.h>
#include <net/gen/ether.h>
#include <net/gen/eth_io.h>
#include "local.h"
#include "dp8390.h"
#include "3c503.h"
@ -48,7 +45,7 @@ dpeth_t * dep;
/* Read station address from PROM */
for (ix = EL2_EA0; ix <= EL2_EA5; ix += 1)
dep->de_address.ea_addr[ix] = inb_el2(dep, ix);
dep->de_address.na_addr[ix] = inb_el2(dep, ix);
/* Map the 8390 back to lower I/O address range */
outb_el2(dep, EL2_CNTR, cntr);
@ -108,12 +105,12 @@ dpeth_t * dep;
if (!debug) {
printf("%s: 3c503 at %X:%d:%lX\n",
dep->de_name, dep->de_base_port, dep->de_irq,
netdriver_name(), dep->de_base_port, dep->de_irq,
dep->de_linmem + dep->de_offset_page);
} else {
printf("%s: 3Com Etherlink II %sat I/O address 0x%X, "
"memory address 0x%lX, irq %d\n",
dep->de_name, dep->de_16bit ? "(16-bit) " : "",
netdriver_name(), dep->de_16bit ? "(16-bit) " : "",
dep->de_base_port,
dep->de_linmem + dep->de_offset_page,
dep->de_irq);
@ -129,7 +126,7 @@ dpeth_t * dep;
/* Stops board by disabling interrupts. */
#if DEBUG
printf("%s: stopping Etherlink\n", dep->de_name);
printf("%s: stopping Etherlink\n", netdriver_name());
#endif
outb_el2(dep, EL2_CFGR, ECFGR_IRQOFF);
return;

View File

@ -9,4 +9,6 @@ FILESDIR= /etc/system.conf.d
DPADD+= ${LIBNETDRIVER} ${LIBSYS}
LDADD+= -lnetdriver -lsys
WARNS?= 5
.include <minix.service.mk>

View File

@ -16,7 +16,6 @@
#include <minix/drivers.h>
#include <minix/netdriver.h>
#include <net/hton.h>
#include <sys/mman.h>
#include "assert.h"
@ -24,7 +23,6 @@
#include "dp8390.h"
static dpeth_t de_state;
static int de_instance;
u32_t system_hz;
@ -63,17 +61,19 @@ static dp_conf_t dp_conf[DP_CONF_NR]= /* Card addresses */
*/
#define CR_EXTRA CR_STA
static int do_init(unsigned int instance, ether_addr_t *addr);
static void pci_conf(void);
static int do_init(unsigned int instance, netdriver_addr_t *addr,
uint32_t *caps, unsigned int *ticks);
static void pci_conf(unsigned int instance);
static int do_send(struct netdriver_data *data, size_t size);
static ssize_t do_recv(struct netdriver_data *data, size_t max);
static void do_mode(unsigned int mode);
static void do_stat(eth_stat_t *stat);
static void do_set_mode(unsigned int mode, const netdriver_addr_t *mcast_list,
unsigned int mcast_count);
static void do_stop(void);
static void dp_init(dpeth_t *dep);
static void dp_confaddr(dpeth_t *dep);
static void dp_init(dpeth_t *dep, unsigned int instance);
static void dp_confaddr(dpeth_t *dep, unsigned int instance);
static void dp_reset(dpeth_t *dep);
static void do_intr(unsigned int mask);
static void do_tick(void);
static void dp_getblock(dpeth_t *dep, int page, size_t offset, size_t
size, void *dst);
static void dp_pio8_getblock(dpeth_t *dep, int page, size_t offset,
@ -94,20 +94,21 @@ static void dp_pio8_nic2user_s(dpeth_t *dep, struct netdriver_data *data,
int nic_addr, size_t offset, size_t count);
static void dp_pio16_nic2user_s(dpeth_t *dep, struct netdriver_data *data,
int nic_addr, size_t offset, size_t count);
static void conf_hw(dpeth_t *dep);
static void update_conf(dpeth_t *dep, dp_conf_t *dcp);
static void conf_hw(dpeth_t *dep, unsigned int instance);
static void update_conf(dpeth_t *dep, dp_conf_t *dcp, unsigned int instance);
static void map_hw_buffer(dpeth_t *dep);
static void insb(port_t port, void *buf, size_t size);
static void insw(port_t port, void *buf, size_t size);
static const struct netdriver dp_table = {
.ndr_name = "dp",
.ndr_init = do_init,
.ndr_stop = do_stop,
.ndr_mode = do_mode,
.ndr_set_mode = do_set_mode,
.ndr_recv = do_recv,
.ndr_send = do_send,
.ndr_stat = do_stat,
.ndr_intr = do_intr
.ndr_intr = do_intr,
.ndr_tick = do_tick
};
/*===========================================================================*
@ -125,30 +126,27 @@ int main(int argc, char *argv[])
/*===========================================================================*
* do_init *
*===========================================================================*/
static int do_init(unsigned int instance, ether_addr_t *addr)
static int do_init(unsigned int instance, netdriver_addr_t *addr,
uint32_t *caps, unsigned int *ticks)
{
/* Initialize the dp8390 driver. */
dpeth_t *dep;
system_hz = sys_hz();
de_instance = instance;
dep = &de_state;
memset(dep, 0, sizeof(*dep));
strlcpy(dep->de_name, "dp8390#0", sizeof(dep->de_name));
dep->de_name[7] += de_instance;
pci_conf(); /* Configure PCI devices. */
pci_conf(instance); /* Configure PCI devices. */
/* This is the default, try to (re)locate the device. */
conf_hw(dep);
conf_hw(dep, instance);
dp_init(dep);
memcpy(addr, dep->de_address.ea_addr, sizeof(*addr));
dp_init(dep, instance);
memcpy(addr, dep->de_address.na_addr, sizeof(*addr));
*caps = NDEV_CAP_MCAST | NDEV_CAP_BCAST;
*ticks = sys_hz(); /* update statistics once a second */
return OK;
}
@ -164,29 +162,7 @@ void dp8390_dump(void)
dep = &de_state;
printf("\n");
printf("dp8390 statistics of instance %d:\n", de_instance);
printf("recvErr :%8ld\t", dep->de_stat.ets_recvErr);
printf("sendErr :%8ld\t", dep->de_stat.ets_sendErr);
printf("OVW :%8ld\n", dep->de_stat.ets_OVW);
printf("CRCerr :%8ld\t", dep->de_stat.ets_CRCerr);
printf("frameAll :%8ld\t", dep->de_stat.ets_frameAll);
printf("missedP :%8ld\n", dep->de_stat.ets_missedP);
printf("packetR :%8ld\t", dep->de_stat.ets_packetR);
printf("packetT :%8ld\t", dep->de_stat.ets_packetT);
printf("transDef :%8ld\n", dep->de_stat.ets_transDef);
printf("collision :%8ld\t", dep->de_stat.ets_collision);
printf("transAb :%8ld\t", dep->de_stat.ets_transAb);
printf("carrSense :%8ld\n", dep->de_stat.ets_carrSense);
printf("fifoUnder :%8ld\t", dep->de_stat.ets_fifoUnder);
printf("fifoOver :%8ld\t", dep->de_stat.ets_fifoOver);
printf("CDheartbeat:%8ld\n", dep->de_stat.ets_CDheartbeat);
printf("OWC :%8ld\t", dep->de_stat.ets_OWC);
printf("dp8390 statistics of %s:\n", netdriver_name());
isr= inb_reg0(dep, DP_ISR);
printf("dp_isr = 0x%x + 0x%x, de_flags = 0x%x\n", isr,
@ -194,29 +170,45 @@ void dp8390_dump(void)
}
#endif
/*===========================================================================*
* pci_env *
*===========================================================================*/
static int pci_env(unsigned int instance)
{
char envvar[16], value[EP_BUF_SIZE];
const char punct[] = ":,;.";
strlcpy(envvar, "DPETH0", sizeof(envvar));
envvar[5] += instance;
/* If no setting with this name is present, default to PCI. */
if (env_get_param(envvar, value, sizeof(value)) != 0)
return TRUE;
/* Legacy support: check for a "pci" prefix. */
return (strncmp(value, "pci", 3) == 0 &&
strchr(punct, value[3]) != NULL);
}
/*===========================================================================*
* pci_conf *
*===========================================================================*/
static void pci_conf(void)
static void pci_conf(unsigned int instance)
{
char envvar[16];
struct dpeth *dep;
int i, pci_instance;
unsigned int i, pci_instance;
dep= &de_state;
strlcpy(envvar, "DPETH0", sizeof(envvar));
envvar[5] += de_instance;
if (!(dep->de_pci= env_prefix(envvar, "pci")))
if (!(dep->de_pci= pci_env(instance)))
return; /* no PCI config */
/* Count the number of dp instances before this one that are configured
* for PCI, so that we can skip that many when enumerating PCI devices.
*/
pci_instance= 0;
for (i= 0; i < de_instance; i++) {
envvar[5]= i;
if (env_prefix(envvar, "pci"))
for (i= 0; i < instance; i++) {
if (pci_env(i))
pci_instance++;
}
@ -261,9 +253,11 @@ static int do_send(struct netdriver_data *data, size_t size)
}
/*===========================================================================*
* do_mode *
* do_set_mode *
*===========================================================================*/
static void do_mode(unsigned int mode)
static void do_set_mode(unsigned int mode,
const netdriver_addr_t * mcast_list __unused,
unsigned int mcast_count __unused)
{
dpeth_t *dep;
int dp_rcr_reg;
@ -273,29 +267,33 @@ static void do_mode(unsigned int mode)
outb_reg0(dep, DP_CR, CR_PS_P0 | CR_EXTRA);
dp_rcr_reg = 0;
if (mode & NDEV_PROMISC)
if (mode & NDEV_MODE_PROMISC)
dp_rcr_reg |= RCR_AB | RCR_PRO | RCR_AM;
if (mode & NDEV_BROAD)
if (mode & NDEV_MODE_BCAST)
dp_rcr_reg |= RCR_AB;
if (mode & NDEV_MULTI)
if (mode & (NDEV_MODE_MCAST_LIST | NDEV_MODE_MCAST_ALL))
dp_rcr_reg |= RCR_AM;
outb_reg0(dep, DP_RCR, dp_rcr_reg);
}
/*===========================================================================*
* do_stat *
* dp_update_stats *
*===========================================================================*/
static void do_stat(eth_stat_t *stat)
static void dp_update_stats(dpeth_t * dep)
{
dpeth_t *dep;
dep= &de_state;
netdriver_stat_ierror(inb_reg0(dep, DP_CNTR0));
netdriver_stat_ierror(inb_reg0(dep, DP_CNTR1));
netdriver_stat_ierror(inb_reg0(dep, DP_CNTR2));
}
dep->de_stat.ets_CRCerr += inb_reg0(dep, DP_CNTR0);
dep->de_stat.ets_frameAll += inb_reg0(dep, DP_CNTR1);
dep->de_stat.ets_missedP += inb_reg0(dep, DP_CNTR2);
/*===========================================================================*
* do_tick *
*===========================================================================*/
static void do_tick(void)
{
memcpy(stat, &dep->de_stat, sizeof(*stat));
dp_update_stats(&de_state);
}
/*===========================================================================*
@ -314,7 +312,7 @@ static void do_stop(void)
/*===========================================================================*
* dp_init *
*===========================================================================*/
static void dp_init(dpeth_t *dep)
static void dp_init(dpeth_t *dep, unsigned int instance)
{
int i, r;
@ -322,13 +320,13 @@ static void dp_init(dpeth_t *dep)
dep->de_flags = DEF_EMPTY;
(*dep->de_initf)(dep);
dp_confaddr(dep);
dp_confaddr(dep, instance);
if (debug)
{
printf("%s: Ethernet address ", dep->de_name);
printf("%s: Ethernet address ", netdriver_name());
for (i= 0; i < 6; i++)
printf("%x%c", dep->de_address.ea_addr[i],
printf("%x%c", dep->de_address.na_addr[i],
i < 5 ? ':' : '\n');
}
@ -365,12 +363,12 @@ static void dp_init(dpeth_t *dep)
/* Step 9: */
outb_reg0(dep, DP_CR, CR_PS_P1 | CR_DM_ABORT | CR_STP);
outb_reg1(dep, DP_PAR0, dep->de_address.ea_addr[0]);
outb_reg1(dep, DP_PAR1, dep->de_address.ea_addr[1]);
outb_reg1(dep, DP_PAR2, dep->de_address.ea_addr[2]);
outb_reg1(dep, DP_PAR3, dep->de_address.ea_addr[3]);
outb_reg1(dep, DP_PAR4, dep->de_address.ea_addr[4]);
outb_reg1(dep, DP_PAR5, dep->de_address.ea_addr[5]);
outb_reg1(dep, DP_PAR0, dep->de_address.na_addr[0]);
outb_reg1(dep, DP_PAR1, dep->de_address.na_addr[1]);
outb_reg1(dep, DP_PAR2, dep->de_address.na_addr[2]);
outb_reg1(dep, DP_PAR3, dep->de_address.na_addr[3]);
outb_reg1(dep, DP_PAR4, dep->de_address.na_addr[4]);
outb_reg1(dep, DP_PAR5, dep->de_address.na_addr[5]);
outb_reg1(dep, DP_MAR0, 0xff);
outb_reg1(dep, DP_MAR1, 0xff);
@ -431,7 +429,7 @@ static void dp_init(dpeth_t *dep)
/*===========================================================================*
* dp_confaddr *
*===========================================================================*/
static void dp_confaddr(dpeth_t *dep)
static void dp_confaddr(dpeth_t *dep, unsigned int instance)
{
int i;
char eakey[16];
@ -440,16 +438,16 @@ static void dp_confaddr(dpeth_t *dep)
/* User defined ethernet address? */
strlcpy(eakey, "DPETH0_EA", sizeof(eakey));
eakey[5] += de_instance;
eakey[5] += instance;
for (i= 0; i < 6; i++)
{
v= dep->de_address.ea_addr[i];
v= dep->de_address.na_addr[i];
if (env_parse(eakey, eafmt, i, &v, 0x00L, 0xFFL) != EP_SET)
{
break;
}
dep->de_address.ea_addr[i]= v;
dep->de_address.na_addr[i]= v;
}
if (i != 0 && i != 6) env_panic(eakey); /* It's all or nothing */
@ -510,15 +508,18 @@ static void do_intr(unsigned int __unused mask)
if (isr & ISR_TXE)
{
#if DEBUG
{ printf("%s: got send Error\n", dep->de_name); }
printf("%s: got send error\n",
netdriver_name());
#endif
dep->de_stat.ets_sendErr++;
netdriver_stat_oerror(1);
}
else
{
tsr = inb_reg0(dep, DP_TSR);
if (tsr & TSR_PTX) dep->de_stat.ets_packetT++;
if (tsr & TSR_PTX) {
/* Transmission was successful. */
}
#if 0 /* Reserved in later manuals, should be ignored */
if (!(tsr & TSR_DFR))
{
@ -526,25 +527,9 @@ static void do_intr(unsigned int __unused mask)
* the dp8390, this bit is set
* when the packet is not deferred
*/
dep->de_stat.ets_transDef++;
}
#endif
if (tsr & TSR_COL) dep->de_stat.ets_collision++;
if (tsr & TSR_ABT) dep->de_stat.ets_transAb++;
if (tsr & TSR_CRS) dep->de_stat.ets_carrSense++;
if (tsr & TSR_FU
&& ++dep->de_stat.ets_fifoUnder <= 10)
{
printf("%s: fifo underrun\n",
dep->de_name);
}
if (tsr & TSR_CDH
&& ++dep->de_stat.ets_CDheartbeat <= 10)
{
printf("%s: CD heart beat failure\n",
dep->de_name);
}
if (tsr & TSR_OWC) dep->de_stat.ets_OWC++;
if (tsr & TSR_COL) netdriver_stat_coll(1);
}
sendq_tail= dep->de_sendq_tail;
@ -556,7 +541,7 @@ static void do_intr(unsigned int __unused mask)
/* Or hardware bug? */
printf(
"%s: transmit interrupt, but not sending\n",
dep->de_name);
netdriver_name());
continue;
}
dep->de_sendq[sendq_tail].sq_filled= 0;
@ -578,21 +563,10 @@ static void do_intr(unsigned int __unused mask)
if (isr & ISR_PRX)
netdriver_recv();
if (isr & ISR_RXE) dep->de_stat.ets_recvErr++;
if (isr & ISR_RXE)
netdriver_stat_ierror(1);
if (isr & ISR_CNT)
{
dep->de_stat.ets_CRCerr += inb_reg0(dep, DP_CNTR0);
dep->de_stat.ets_frameAll += inb_reg0(dep, DP_CNTR1);
dep->de_stat.ets_missedP += inb_reg0(dep, DP_CNTR2);
}
if (isr & ISR_OVW)
{
dep->de_stat.ets_OVW++;
#if 0
{ printW(); printf(
"%s: got overwrite warning\n", dep->de_name); }
#endif
}
dp_update_stats(dep);
if (isr & ISR_RDC)
{
/* Nothing to do */
@ -606,7 +580,7 @@ static void do_intr(unsigned int __unused mask)
*/
#if 0
{ printW(); printf(
"%s: NIC stopped\n", dep->de_name); }
"%s: NIC stopped\n", netdriver_name()); }
#endif
dep->de_flags |= DEF_STOPPED;
netdriver_recv(); /* see if we can reset right now */
@ -656,20 +630,21 @@ static ssize_t do_recv(struct netdriver_data *data, size_t max)
(dep->de_getblockf)(dep, pageno, (size_t)0, sizeof(header),
&header);
(dep->de_getblockf)(dep, pageno, sizeof(header) +
2*sizeof(ether_addr_t), sizeof(eth_type), &eth_type);
2*sizeof(netdriver_addr_t), sizeof(eth_type),
&eth_type);
length = (header.dr_rbcl | (header.dr_rbch << 8)) -
sizeof(dp_rcvhdr_t);
next = header.dr_next;
if (length < ETH_MIN_PACK_SIZE || length > max)
if (length < NDEV_ETH_PACKET_MIN || length > max)
{
printf("%s: packet with strange length arrived: %d\n",
dep->de_name, (int) length);
netdriver_name(), (int) length);
next= curr;
}
else if (next < dep->de_startpage || next >= dep->de_stoppage)
{
printf("%s: strange next page\n", dep->de_name);
printf("%s: strange next page\n", netdriver_name());
next= curr;
}
else if (header.dr_status & RSR_FO)
@ -677,8 +652,8 @@ static ssize_t do_recv(struct netdriver_data *data, size_t max)
/* This is very serious, so we issue a warning and
* reset the buffers */
printf("%s: fifo overrun, resetting receive buffer\n",
dep->de_name);
dep->de_stat.ets_fifoOver++;
netdriver_name());
netdriver_stat_ierror(1);
next = curr;
}
else if (header.dr_status & RSR_PRX)
@ -686,7 +661,6 @@ static ssize_t do_recv(struct netdriver_data *data, size_t max)
dp_pkt2user_s(dep, data, pageno, length);
packet_processed = TRUE;
dep->de_stat.ets_packetR++;
}
if (next == dep->de_startpage)
outb_reg0(dep, DP_BNRY, dep->de_stoppage - 1);
@ -749,7 +723,7 @@ static void dp_pio16_getblock(dpeth_t *dep, int page, size_t offset,
static void dp_pkt2user_s(dpeth_t *dep, struct netdriver_data *data, int page,
size_t length)
{
int last, count;
unsigned int last, count;
last = page + (length - 1) / DP_PAGESIZE;
if (last >= dep->de_stoppage)
@ -884,16 +858,16 @@ static void dp_pio16_nic2user_s(dpeth_t *dep, struct netdriver_data *data,
/*===========================================================================*
* conf_hw *
*===========================================================================*/
static void conf_hw(dpeth_t *dep)
static void conf_hw(dpeth_t *dep, unsigned int instance)
{
int confnr;
dp_conf_t *dcp;
/* Pick a default configuration for this instance. */
confnr= MIN(de_instance, DP_CONF_NR-1);
confnr= MIN(instance, DP_CONF_NR-1);
dcp= &dp_conf[confnr];
update_conf(dep, dcp);
update_conf(dep, dcp, instance);
if (!wdeth_probe(dep) && !ne_probe(dep) && !el2_probe(dep))
panic("no ethernet card found at 0x%x\n", dep->de_base_port);
@ -903,7 +877,7 @@ static void conf_hw(dpeth_t *dep)
/*===========================================================================*
* update_conf *
*===========================================================================*/
static void update_conf(dpeth_t *dep, dp_conf_t *dcp)
static void update_conf(dpeth_t *dep, dp_conf_t *dcp, unsigned int instance)
{
long v;
static char dpc_fmt[] = "x:d:x:x";
@ -916,7 +890,7 @@ static void update_conf(dpeth_t *dep, dp_conf_t *dcp)
}
strlcpy(eckey, "DPETH0", sizeof(eckey));
eckey[5] += de_instance;
eckey[5] += instance;
/* Get the default settings and modify them from the environment. */
v= dcp->dpc_port;

View File

@ -208,21 +208,20 @@ typedef struct dpeth
dp_initf_t de_initf;
dp_stopf_t de_stopf;
int de_prog_IO;
char de_name[sizeof("dp8390#n")];
/* The initf function fills the following fields. Only cards that do
* programmed I/O fill in the de_pata_port field.
* In addition, the init routine has to fill in the sendq data
* structures.
*/
ether_addr_t de_address;
netdriver_addr_t de_address;
port_t de_dp8390_port;
port_t de_data_port;
int de_16bit;
int de_ramsize;
int de_offset_page;
int de_startpage;
int de_stoppage;
unsigned int de_ramsize;
unsigned int de_offset_page;
unsigned int de_startpage;
unsigned int de_stoppage;
/* PCI config */
char de_pci; /* TRUE iff PCI device */
@ -240,7 +239,6 @@ typedef struct dpeth
/* Fields for internal use by the dp8390 driver. */
int de_flags;
eth_stat_t de_stat;
dp_user2nicf_s_t de_user2nicf_s;
dp_nic2userf_s_t de_nic2userf_s;
dp_getblock_t de_getblockf;

View File

@ -10,9 +10,6 @@ Created: March 15, 1994 by Philip Homburg <philip@f-mnx.phicoh.com>
#include <minix/drivers.h>
#include <minix/netdriver.h>
#include <net/gen/ether.h>
#include <net/gen/eth_io.h>
#include "local.h"
#include "dp8390.h"
#include "ne2000.h"
@ -142,11 +139,11 @@ dpeth_t *dep;
if (dep->de_16bit)
{
word= inw_ne(dep, NE_DATA);
dep->de_address.ea_addr[i]= word;
dep->de_address.na_addr[i]= word;
}
else
{
dep->de_address.ea_addr[i] = inb_ne(dep, NE_DATA);
dep->de_address.na_addr[i] = inb_ne(dep, NE_DATA);
}
}
dep->de_data_port= dep->de_base_port + NE_DATA;
@ -183,14 +180,14 @@ dpeth_t *dep;
if (!debug)
{
printf("%s: NE%d000 at %X:%d\n",
dep->de_name, dep->de_16bit ? 2 : 1,
netdriver_name(), dep->de_16bit ? 2 : 1,
dep->de_base_port, dep->de_irq);
}
else
{
printf("%s: Novell NE%d000 ethernet card at I/O address "
"0x%X, memory size 0x%X, irq %d\n",
dep->de_name, dep->de_16bit ? 2 : 1,
netdriver_name(), dep->de_16bit ? 2 : 1,
dep->de_base_port, dep->de_ramsize, dep->de_irq);
}
}
@ -229,7 +226,7 @@ u8_t *pat;
if (debug)
{
printf("%s: NE1000 remote DMA test failed\n",
dep->de_name);
netdriver_name());
}
return 0;
}
@ -283,7 +280,7 @@ u8_t *pat;
if (debug)
{
printf("%s: NE2000 remote DMA test failed\n",
dep->de_name);
netdriver_name());
}
return 0;
}

View File

@ -11,8 +11,6 @@ Created: April 2000 by Philip Homburg <philip@f-mnx.phicoh.com>
#include <stdlib.h>
#include <sys/types.h>
#include <net/gen/ether.h>
#include <net/gen/eth_io.h>
#include <machine/pci.h>
#include "assert.h"
@ -37,7 +35,7 @@ int skip;
u16_t vid, did;
u32_t bar;
u8_t ilr;
char *dname;
const char *dname;
pci_init();
@ -56,7 +54,7 @@ int skip;
if (!dname)
dname= "unknown device";
printf("%s: %s (%04X/%04X) at %s\n",
dep->de_name, dname, vid, did, pci_slot_name(devind));
netdriver_name(), dname, vid, did, pci_slot_name(devind));
if(pci_reserve_ok(devind) != OK)
return 0;
/* printf("cr = 0x%x\n", pci_attr_r16(devind, PCI_CR)); */
@ -72,7 +70,7 @@ int skip;
if (debug)
{
printf("%s: using I/O address 0x%lx, IRQ %d\n",
dep->de_name, (unsigned long)bar, ilr);
netdriver_name(), (unsigned long)bar, ilr);
}
dep->de_initf= rtl_init;

View File

@ -7,9 +7,7 @@ Created: March 14, 1994 by Philip Homburg
#include <minix/drivers.h>
#include <minix/netdriver.h>
#include <net/gen/ether.h>
#include <net/gen/eth_io.h>
#include "assert.h"
#include <assert.h>
#include "local.h"
#include "dp8390.h"
@ -71,12 +69,12 @@ dpeth_t *dep;
int we_type;
int sendq_nr;
dep->de_address.ea_addr[0] = inb_we(dep, EPL_EA0);
dep->de_address.ea_addr[1] = inb_we(dep, EPL_EA1);
dep->de_address.ea_addr[2] = inb_we(dep, EPL_EA2);
dep->de_address.ea_addr[3] = inb_we(dep, EPL_EA3);
dep->de_address.ea_addr[4] = inb_we(dep, EPL_EA4);
dep->de_address.ea_addr[5] = inb_we(dep, EPL_EA5);
dep->de_address.na_addr[0] = inb_we(dep, EPL_EA0);
dep->de_address.na_addr[1] = inb_we(dep, EPL_EA1);
dep->de_address.na_addr[2] = inb_we(dep, EPL_EA2);
dep->de_address.na_addr[3] = inb_we(dep, EPL_EA3);
dep->de_address.na_addr[4] = inb_we(dep, EPL_EA4);
dep->de_address.na_addr[5] = inb_we(dep, EPL_EA5);
dep->de_dp8390_port= dep->de_base_port + EPL_DP8390;
@ -182,7 +180,7 @@ dpeth_t *dep;
((irr & (E_IRR_IR0|E_IRR_IR1)) >> 5);
int_nr= we_int_table[int_indx];
#if DEBUG
{ printf("%s: encoded irq= %d\n", dep->de_name, int_nr); }
printf("%s: encoded irq= %d\n", netdriver_name(), int_nr);
#endif
if (dep->de_irq & DEI_DEFAULT) dep->de_irq= int_nr;
@ -201,7 +199,7 @@ dpeth_t *dep;
((gcr & (E_790_GCR_IR1|E_790_GCR_IR0)) >> 2);
int_nr= we_790int_table[int_indx];
#if DEBUG
{ printf("%s: encoded irq= %d\n", dep->de_name, int_nr); }
printf("%s: encoded irq= %d\n", netdriver_name(), int_nr);
#endif
if (dep->de_irq & DEI_DEFAULT) dep->de_irq= int_nr;
@ -215,7 +213,7 @@ dpeth_t *dep;
if (!debug)
{
printf("%s: WD80%d3 at %X:%d:%lX\n",
dep->de_name, we_type & WET_BRD_16BIT ? 1 : 0,
netdriver_name(), we_type & WET_BRD_16BIT ? 1 : 0,
dep->de_base_port, dep->de_irq, dep->de_linmem);
}
else
@ -223,7 +221,7 @@ dpeth_t *dep;
printf("%s: Western Digital %s%s card %s%s at I/O "
"address 0x%X, memory address 0x%lX, "
"memory size 0x%X, irq %d\n",
dep->de_name,
netdriver_name(),
we_type & WET_BRD_16BIT ? "16-bit " : "",
we_type & WET_ETHERNET ? "Ethernet" :
we_type & WET_STARLAN ? "Starlan" : "Network",
@ -320,7 +318,7 @@ dpeth_t *dep;
{
tlb= inb_we(dep, EPL_TLB);
#if DEBUG
printf("%s: tlb= 0x%x\n", dep->de_name, tlb);
printf("%s: tlb= 0x%x\n", netdriver_name(), tlb);
#endif
return tlb == E_TLB_EB || tlb == E_TLB_E ||
tlb == E_TLB_SMCE || tlb == E_TLB_SMC8216T ||

View File

@ -11,8 +11,6 @@
#include <minix/drivers.h>
#include <minix/netdriver.h>
#include <net/gen/ether.h>
#include <net/gen/eth_io.h>
#include "dp.h"
#if (ENABLE_3C501 == 1)
@ -38,7 +36,7 @@ static void el1_getstats(dpeth_t * dep)
*/
static void el1_reset(dpeth_t * dep)
{
int ix;
unsigned int ix;
for (ix = 0; ix < 8; ix += 1) /* Resets the board */
outb_el1(dep, EL1_CSR, ECSR_RESET);
@ -113,7 +111,7 @@ static ssize_t el1_recv(dpeth_t *dep, struct netdriver_data *data, size_t max)
dep->de_recvq_head = rxptr->next;
/* Copy buffer to user area */
size = MIN(rxptr->size, max);
size = MIN((size_t)rxptr->size, max);
netdriver_copyout(data, 0, rxptr->buffer, size);
@ -137,7 +135,7 @@ static int el1_send(dpeth_t *dep, struct netdriver_data *data, size_t size)
if ((now - dep->de_xmit_start) > 4) {
/* Transmitter timed out */
DEBUG(printf("3c501: transmitter timed out ... \n"));
dep->de_stat.ets_sendErr += 1;
netdriver_stat_oerror(1);
dep->de_flags &= NOT(DEF_XMIT_BUSY);
/* Try sending anyway. */
} else
@ -184,7 +182,7 @@ static void el1_stop(dpeth_t * dep)
{
int ix;
DEBUG(printf("%s: stopping Etherlink ....\n", dep->de_name));
DEBUG(printf("%s: stopping Etherlink ....\n", netdriver_name()));
for (ix = 0; ix < 8; ix += 1) /* Reset board */
outb_el1(dep, EL1_CSR, ECSR_RESET);
outb_el1(dep, EL1_CSR, ECSR_SYS);
@ -211,7 +209,7 @@ static void el1_interrupt(dpeth_t * dep)
DEBUG(printf("3c501: got xmit interrupt (ASR=0x%02X XSR=0x%02X)\n", csr, isr));
if (isr & EXSR_JAM) {
/* Sending, packet got a collision */
dep->de_stat.ets_collision += 1;
netdriver_stat_coll(1);
/* Put pointer back to beginning of packet */
outb_el1(dep, EL1_CSR, ECSR_RIDE | ECSR_SYS);
outw_el1(dep, EL1_XMITPTR, (EL1_BFRSIZ - TxBuff->size));
@ -220,17 +218,15 @@ static void el1_interrupt(dpeth_t * dep)
return;
} else if ((isr & EXSR_16JAM) || !(isr & EXSR_IDLE)) {
dep->de_stat.ets_sendErr += 1;
netdriver_stat_oerror(1);
} else if (isr & EXSR_UNDER) {
dep->de_stat.ets_fifoUnder += 1;
netdriver_stat_oerror(1);
}
DEBUG(printf("3c501: got xmit interrupt (0x%02X)\n", isr));
el1_reset(dep);
} else {
/** if (inw_el1(dep, EL1_XMITPTR) == EL1_BFRSIZ) **/
/* Packet transmitted successfully */
dep->de_stat.ets_packetT += 1;
dep->bytes_Tx += (long) (TxBuff->size);
free_buff(dep, TxBuff);
dep->de_flags &= NOT(DEF_XMIT_BUSY);
@ -245,16 +241,19 @@ static void el1_interrupt(dpeth_t * dep)
isr = inb_el1(dep, EL1_RECV);
pktsize = inw_el1(dep, EL1_RECVPTR);
if ((isr & ERSR_RERROR) || (isr & ERSR_STALE)) {
DEBUG(printf("Rx0 (ASR=0x%02X RSR=0x%02X size=%d)\n", csr, isr, pktsize));
dep->de_stat.ets_recvErr += 1;
DEBUG(printf("Rx0 (ASR=0x%02X RSR=0x%02X size=%d)\n",
csr, isr, pktsize));
netdriver_stat_ierror(1);
} else if (pktsize < ETH_MIN_PACK_SIZE || pktsize > ETH_MAX_PACK_SIZE) {
DEBUG(printf("Rx1 (ASR=0x%02X RSR=0x%02X size=%d)\n", csr, isr, pktsize));
dep->de_stat.ets_recvErr += 1;
} else if (pktsize < NDEV_ETH_PACKET_MIN ||
pktsize > NDEV_ETH_PACKET_MAX) {
DEBUG(printf("Rx1 (ASR=0x%02X RSR=0x%02X size=%d)\n",
csr, isr, pktsize));
netdriver_stat_ierror(1);
} else if ((rxptr = alloc_buff(dep, pktsize + sizeof(buff_t))) == NULL) {
/* Memory not available. Drop packet */
dep->de_stat.ets_fifoOver += 1;
netdriver_stat_ierror(1);
} else if (isr & (ERSR_GOOD | ERSR_ANY)) {
/* Got a good packet. Read it from buffer */
@ -263,7 +262,6 @@ static void el1_interrupt(dpeth_t * dep)
insb(dep->de_data_port, rxptr->buffer, pktsize);
rxptr->next = NULL;
rxptr->size = pktsize;
dep->de_stat.ets_packetR += 1;
dep->bytes_Rx += (long) pktsize;
/* Queue packet to receive queue */
if (dep->de_recvq_head == NULL)
@ -303,7 +301,7 @@ static void el1_interrupt(dpeth_t * dep)
*/
static void el1_init(dpeth_t * dep)
{
int ix;
unsigned int ix;
dep->de_irq &= NOT(DEI_DEFAULT); /* Strip the default flag. */
dep->de_offset_page = 0;
@ -320,9 +318,9 @@ static void el1_init(dpeth_t * dep)
el1_mode_init(dep);
printf("%s: Etherlink (%s) at %X:%d - ",
dep->de_name, "3c501", dep->de_base_port, dep->de_irq);
netdriver_name(), "3c501", dep->de_base_port, dep->de_irq);
for (ix = 0; ix < SA_ADDR_LEN; ix += 1)
printf("%02X%c", (dep->de_address.ea_addr[ix] = StationAddress[ix]),
printf("%02X%c", (dep->de_address.na_addr[ix] = StationAddress[ix]),
ix < SA_ADDR_LEN - 1 ? ':' : '\n');
/* Device specific functions */
@ -341,7 +339,7 @@ static void el1_init(dpeth_t * dep)
*/
int el1_probe(dpeth_t * dep)
{
int ix;
unsigned int ix;
for (ix = 0; ix < 8; ix += 1) /* Reset the board */
outb_el1(dep, EL1_CSR, ECSR_RESET);

View File

@ -11,8 +11,6 @@
#include <minix/drivers.h>
#include <minix/netdriver.h>
#include <net/gen/ether.h>
#include <net/gen/eth_io.h>
#include "dp.h"
#if (ENABLE_3C503 == 1)
@ -26,8 +24,8 @@
*/
static void el2_init(dpeth_t * dep)
{
int ix, irq;
int sendq_nr;
unsigned int ix, irq;
unsigned int sendq_nr;
int cntr;
/* Map the address PROM to lower I/O address range */
@ -36,7 +34,7 @@ static void el2_init(dpeth_t * dep)
/* Read station address from PROM */
for (ix = EL2_EA0; ix <= EL2_EA5; ix += 1)
dep->de_address.ea_addr[ix] = inb_el2(dep, ix);
dep->de_address.na_addr[ix] = inb_el2(dep, ix);
/* Map the 8390 back to lower I/O address range */
outb_el2(dep, EL2_CNTR, cntr);
@ -92,11 +90,11 @@ static void el2_init(dpeth_t * dep)
ns_init(dep); /* Initialize DP controller */
printf("%s: Etherlink II%s (%s) at %X:%d:%05lX - ",
dep->de_name, dep->de_16bit ? "/16" : "", "3c503",
netdriver_name(), dep->de_16bit ? "/16" : "", "3c503",
dep->de_base_port, dep->de_irq,
dep->de_linmem + dep->de_offset_page);
for (ix = 0; ix < SA_ADDR_LEN; ix += 1)
printf("%02X%c", dep->de_address.ea_addr[ix],
printf("%02X%c", dep->de_address.na_addr[ix],
ix < SA_ADDR_LEN - 1 ? ':' : '\n');
}

View File

@ -11,8 +11,6 @@
#include <minix/drivers.h>
#include <minix/netdriver.h>
#include <net/gen/ether.h>
#include <net/gen/eth_io.h>
#include "dp.h"
@ -37,17 +35,12 @@ static void el3_update_stats(dpeth_t * dep)
SetWindow(WNO_Statistics);
/* Reads everything, adding values to the local counters */
dep->de_stat.ets_sendErr += inb_el3(dep, REG_TxCarrierLost); /* Reg. 00 */
dep->de_stat.ets_sendErr += inb_el3(dep, REG_TxNoCD); /* Reg. 01 */
dep->de_stat.ets_collision += inb_el3(dep, REG_TxMultColl); /* Reg. 02 */
dep->de_stat.ets_collision += inb_el3(dep, REG_TxSingleColl); /* Reg. 03 */
dep->de_stat.ets_collision += inb_el3(dep, REG_TxLate); /* Reg. 04 */
dep->de_stat.ets_recvErr += inb_el3(dep, REG_RxDiscarded); /* Reg. 05 */
dep->de_stat.ets_packetT += inb_el3(dep, REG_TxFrames); /* Reg. 06 */
dep->de_stat.ets_packetR += inb_el3(dep, REG_RxFrames); /* Reg. 07 */
dep->de_stat.ets_transDef += inb_el3(dep, REG_TxDefer); /* Reg. 08 */
dep->bytes_Rx += (unsigned) inw_el3(dep, REG_RxBytes); /* Reg. 10 */
dep->bytes_Tx += (unsigned) inw_el3(dep, REG_TxBytes); /* Reg. 12 */
netdriver_stat_oerror(inb_el3(dep, REG_TxCarrierLost)); /* Reg. 00 */
netdriver_stat_oerror(inb_el3(dep, REG_TxNoCD)); /* Reg. 01 */
netdriver_stat_coll(inb_el3(dep, REG_TxMultColl)); /* Reg. 02 */
netdriver_stat_coll(inb_el3(dep, REG_TxSingleColl)); /* Reg. 03 */
netdriver_stat_coll(inb_el3(dep, REG_TxLate)); /* Reg. 04 */
netdriver_stat_ierror(inb_el3(dep, REG_RxDiscarded)); /* Reg. 05 */
/* Goes back to operating window and enables statistics */
SetWindow(WNO_Operating);
@ -120,7 +113,7 @@ static ssize_t el3_recv(dpeth_t *dep, struct netdriver_data *data, size_t max)
dep->de_recvq_head = rxptr->next;
/* Copy buffer to user area and free it */
size = MIN(rxptr->size, max);
size = MIN((size_t)rxptr->size, max);
netdriver_copyout(data, 0, rxptr->buffer, size);
@ -151,15 +144,16 @@ static void el3_rx_complete(dpeth_t * dep)
switch (RxStatus) { /* Bad packet (see error type) */
case RXS_Dribble:
case RXS_Oversize:
case RXS_Runt: dep->de_stat.ets_recvErr += 1; break;
case RXS_Overrun: dep->de_stat.ets_OVW += 1; break;
case RXS_Framing: dep->de_stat.ets_frameAll += 1; break;
case RXS_CRC: dep->de_stat.ets_CRCerr += 1; break;
case RXS_Runt:
case RXS_Overrun:
case RXS_Framing:
case RXS_CRC:
netdriver_stat_ierror(1);
}
} else if ((rxptr = alloc_buff(dep, pktsize + sizeof(buff_t))) == NULL) {
/* Memory not available. Drop packet */
dep->de_stat.ets_fifoOver += 1;
netdriver_stat_ierror(1);
} else {
/* Good packet. Read it from FIFO */
@ -199,8 +193,8 @@ static int el3_send(dpeth_t *dep, struct netdriver_data *data, size_t size)
(now - dep->de_xmit_start) > 4) {
DEBUG(printf("3c509: Transmitter timed out. Resetting ....\n");)
dep->de_stat.ets_sendErr += 1;
/* Resets and restars the transmitter */
netdriver_stat_oerror(1);
/* Resets and restarts the transmitter */
outw_el3(dep, REG_CmdStatus, CMD_TxReset);
outw_el3(dep, REG_CmdStatus, CMD_TxEnable);
dep->de_flags &= NOT(DEF_XMIT_BUSY);
@ -219,17 +213,18 @@ static int el3_send(dpeth_t *dep, struct netdriver_data *data, size_t size)
dep->de_xmit_start = getticks();
dep->de_flags |= DEF_XMIT_BUSY;
if (inw_el3(dep, REG_TxFree) > ETH_MAX_PACK_SIZE) {
if (inw_el3(dep, REG_TxFree) > NDEV_ETH_PACKET_MAX) {
/* Tx has enough room for a packet of maximum size */
dep->de_flags &= NOT(DEF_XMIT_BUSY);
} else {
/* Interrupt driver when enough room is available */
outw_el3(dep, REG_CmdStatus, CMD_SetTxAvailable | ETH_MAX_PACK_SIZE);
outw_el3(dep, REG_CmdStatus, CMD_SetTxAvailable | NDEV_ETH_PACKET_MAX);
}
/* Pops Tx status stack */
for (ix = 4; --ix && (TxStatus = inb_el3(dep, REG_TxStatus)) > 0;) {
if (TxStatus & 0x38) dep->de_stat.ets_sendErr += 1;
if (TxStatus & 0x38)
netdriver_stat_oerror(1);
if (TxStatus & 0x30)
outw_el3(dep, REG_CmdStatus, CMD_TxReset);
if (TxStatus & 0x3C)
@ -262,7 +257,7 @@ static void el3_close(dpeth_t * dep)
NOT((MediaLBeatEnable | MediaJabberEnable)));
/* micro_delay(5000); */
}
DEBUG(printf("%s: stopping Etherlink ... \n", dep->de_name));
DEBUG(printf("%s: stopping Etherlink ... \n", netdriver_name()));
/* Issues a global reset
outw_el3(dep, REG_CmdStatus, CMD_GlobalReset); */
sys_irqdisable(&dep->de_hook); /* Disable interrupt */
@ -341,8 +336,8 @@ static void el3_read_StationAddress(dpeth_t * dep)
/* Accesses with word No. */
rc = el3_read_eeprom(dep->de_id_port, ix / 2);
/* Swaps bytes of word */
dep->de_address.ea_addr[ix++] = (rc >> 8) & 0xFF;
dep->de_address.ea_addr[ix++] = rc & 0xFF;
dep->de_address.na_addr[ix++] = (rc >> 8) & 0xFF;
dep->de_address.na_addr[ix++] = rc & 0xFF;
}
}
@ -387,7 +382,7 @@ static void el3_open(dpeth_t * dep)
/* Set "my own" address */
SetWindow(WNO_StationAddress);
for (ix = 0; ix < 6; ix += 1)
outb_el3(dep, REG_SA0_1 + ix, dep->de_address.ea_addr[ix]);
outb_el3(dep, REG_SA0_1 + ix, dep->de_address.na_addr[ix]);
/* Start Transceivers as required */
if (dep->de_if_port == BNC_XCVR) {
@ -445,10 +440,10 @@ static void el3_open(dpeth_t * dep)
dep->de_interruptf = el3_interrupt;
printf("%s: Etherlink III (%s) at %X:%d, %s port - ",
dep->de_name, "3c509", dep->de_base_port, dep->de_irq,
netdriver_name(), "3c509", dep->de_base_port, dep->de_irq,
IfNamesMsg[dep->de_if_port >> 14]);
for (ix = 0; ix < SA_ADDR_LEN; ix += 1)
printf("%02X%c", dep->de_address.ea_addr[ix],
printf("%02X%c", dep->de_address.na_addr[ix],
ix < SA_ADDR_LEN - 1 ? ':' : '\n');
}

View File

@ -12,8 +12,6 @@
#include <minix/drivers.h>
#include <minix/netdriver.h>
#include <net/gen/ether.h>
#include <net/gen/eth_io.h>
#include <assert.h>
#include "dp.h"
@ -57,7 +55,8 @@ static void ns_start_xmit(const dpeth_t * dep, int size, int pageno)
static void mem_getblock(dpeth_t *dep, u16_t offset, int size, void *dst)
{
assert(offset + size <= dep->de_ramsize);
assert(size >= 0);
assert(offset + (unsigned int)size <= dep->de_ramsize);
memcpy(dst, dep->de_locmem + offset, size);
}
@ -179,9 +178,9 @@ static void pio_user2nic(dpeth_t *dep, int pageno, struct netdriver_data *data,
static void ns_stats(dpeth_t * dep)
{
dep->de_stat.ets_CRCerr += inb_reg0(dep, DP_CNTR0);
dep->de_stat.ets_recvErr += inb_reg0(dep, DP_CNTR1);
dep->de_stat.ets_fifoOver += inb_reg0(dep, DP_CNTR2);
netdriver_stat_ierror(inb_reg0(dep, DP_CNTR0));
netdriver_stat_ierror(inb_reg0(dep, DP_CNTR1));
netdriver_stat_ierror(inb_reg0(dep, DP_CNTR2));
}
/*
@ -215,7 +214,7 @@ static void ns_reinit(dpeth_t * dep)
*/
static int ns_send(dpeth_t *dep, struct netdriver_data *data, size_t size)
{
int queue;
unsigned int queue;
queue = dep->de_sendq_head;
if (dep->de_sendq[queue].sq_filled)
@ -242,7 +241,7 @@ static int ns_send(dpeth_t *dep, struct netdriver_data *data, size_t size)
*/
static void ns_reset(dpeth_t * dep)
{
int ix;
unsigned int ix;
/* Stop chip */
outb_reg0(dep, DP_CR, CR_STP | CR_NO_DMA);
@ -298,21 +297,21 @@ static ssize_t ns_recv(dpeth_t *dep, struct netdriver_data *data, size_t max)
&header);
#ifdef ETH_IGN_PROTO
(dep->de_getblockf)(dep, pageno * DP_PAGESIZE + sizeof(header) +
2 * sizeof(ether_addr_t), sizeof(eth_type), &eth_type);
2 * sizeof(netdriver_addr_t), sizeof(eth_type), &eth_type);
#endif
length = (header.dr_rbcl | (header.dr_rbch << 8)) -
sizeof(dp_rcvhdr_t);
next = header.dr_next;
if (length < ETH_MIN_PACK_SIZE || length > max) {
if (length < NDEV_ETH_PACKET_MIN || length > max) {
printf("%s: packet with strange length arrived: %zu\n",
dep->de_name, length);
dep->de_stat.ets_recvErr += 1;
netdriver_name(), length);
netdriver_stat_ierror(1);
next = curr;
} else if (next < dep->de_startpage || next >= dep->de_stoppage) {
printf("%s: strange next page\n", dep->de_name);
dep->de_stat.ets_recvErr += 1;
printf("%s: strange next page\n", netdriver_name());
netdriver_stat_ierror(1);
next = curr;
#ifdef ETH_IGN_PROTO
} else if (eth_type == eth_ign_proto) {
@ -321,15 +320,15 @@ static ssize_t ns_recv(dpeth_t *dep, struct netdriver_data *data, size_t max)
if (first) {
first = FALSE;
printf("%s: dropping proto %04x packet\n",
dep->de_name, ntohs(eth_ign_proto));
netdriver_name(), ntohs(eth_ign_proto));
}
next = curr;
#endif
} else if (header.dr_status & RSR_FO) {
/* This is very serious, issue a warning and reset buffers */
printf("%s: fifo overrun, resetting receive buffer\n",
dep->de_name);
dep->de_stat.ets_fifoOver += 1;
netdriver_name());
netdriver_stat_ierror(1);
next = curr;
} else if (header.dr_status & RSR_PRX) {
@ -337,7 +336,6 @@ static ssize_t ns_recv(dpeth_t *dep, struct netdriver_data *data, size_t max)
packet_processed = TRUE;
}
dep->bytes_Rx += (long) length;
dep->de_stat.ets_packetR += 1;
outb_reg0(dep, DP_BNRY,
(next == dep->de_startpage ? dep->de_stoppage : next) - 1);
pageno = next;
@ -353,7 +351,7 @@ static ssize_t ns_recv(dpeth_t *dep, struct netdriver_data *data, size_t max)
static void ns_interrupt(dpeth_t * dep)
{
int isr, tsr;
int queue;
unsigned int queue;
while ((isr = inb_reg0(dep, DP_ISR)) != 0) {
@ -362,22 +360,23 @@ static void ns_interrupt(dpeth_t * dep)
tsr = inb_reg0(dep, DP_TSR);
if (tsr & TSR_PTX) {
dep->de_stat.ets_packetT++;
/* Packet transmission was successful. */
}
if (tsr & TSR_COL) dep->de_stat.ets_collision++;
if (tsr & TSR_COL)
netdriver_stat_coll(1);
if (tsr & (TSR_ABT | TSR_FU)) {
dep->de_stat.ets_fifoUnder++;
netdriver_stat_oerror(1);
}
if ((isr & ISR_TXE) || (tsr & (TSR_CRS | TSR_CDH | TSR_OWC))) {
printf("%s: got send Error (0x%02X)\n",
dep->de_name, tsr);
dep->de_stat.ets_sendErr++;
netdriver_name(), tsr);
netdriver_stat_oerror(1);
}
queue = dep->de_sendq_tail;
if (!(dep->de_sendq[queue].sq_filled)) { /* Hardware bug? */
printf("%s: transmit interrupt, but not sending\n",
dep->de_name);
netdriver_name());
continue;
}
dep->de_sendq[queue].sq_filled = FALSE;
@ -394,16 +393,14 @@ static void ns_interrupt(dpeth_t * dep)
}
if (isr & ISR_RXE) {
printf("%s: got recv Error (0x%04X)\n",
dep->de_name, inb_reg0(dep, DP_RSR));
dep->de_stat.ets_recvErr++;
netdriver_name(), inb_reg0(dep, DP_RSR));
netdriver_stat_ierror(1);
}
if (isr & ISR_CNT) {
dep->de_stat.ets_CRCerr += inb_reg0(dep, DP_CNTR0);
dep->de_stat.ets_recvErr += inb_reg0(dep, DP_CNTR1);
dep->de_stat.ets_fifoOver += inb_reg0(dep, DP_CNTR2);
ns_stats(dep);
}
if (isr & ISR_OVW) {
printf("%s: got overwrite warning\n", dep->de_name);
printf("%s: got overwrite warning\n", netdriver_name());
}
if (isr & ISR_RDC) {
/* Nothing to do */
@ -415,7 +412,8 @@ static void ns_interrupt(dpeth_t * dep)
* approach of resetting only after all pending packets had
* been accepted, but it was broken and this is simpler anyway.
*/
printf("%s: network interface stopped\n", dep->de_name);
printf("%s: network interface stopped\n",
netdriver_name());
ns_reset(dep);
break;
}
@ -428,8 +426,8 @@ static void ns_interrupt(dpeth_t * dep)
*/
void ns_init(dpeth_t * dep)
{
int dp_reg;
int ix;
unsigned int dp_reg;
unsigned int ix;
/* NS8390 initialization (as recommended in National Semiconductor specs) */
outb_reg0(dep, DP_CR, CR_PS_P0 | CR_STP | CR_NO_DMA); /* 0x21 */
@ -448,7 +446,7 @@ void ns_init(dpeth_t * dep)
/* Copies station address in page 1 registers */
outb_reg0(dep, DP_CR, CR_PS_P1 | CR_NO_DMA); /* Selects Page 1 */
for (ix = 0; ix < SA_ADDR_LEN; ix += 1) /* Initializes address */
outb_reg1(dep, DP_PAR0 + ix, dep->de_address.ea_addr[ix]);
outb_reg1(dep, DP_PAR0 + ix, dep->de_address.na_addr[ix]);
for (ix = DP_MAR0; ix <= DP_MAR7; ix += 1) /* Initializes address */
outb_reg1(dep, ix, 0xFF);

View File

@ -11,4 +11,6 @@ LDADD+= -lnetdriver -lsys
CPPFLAGS+= -DVERBOSE=0
WARNS?= 5
.include <minix.service.mk>

View File

@ -9,8 +9,6 @@
#include <minix/drivers.h>
#include <minix/netdriver.h>
#include <net/gen/ether.h>
#include <net/gen/eth_io.h>
#include "dp.h"
#if (USE_IOPL == 0)

View File

@ -14,8 +14,6 @@
#include <minix/drivers.h>
#include <minix/netdriver.h>
#include <minix/endpoint.h>
#include <net/gen/ether.h>
#include <net/gen/eth_io.h>
#include <sys/mman.h>
#include <assert.h>
@ -41,23 +39,26 @@ static dp_conf_t dp_conf[DP_CONF_NR] = {
{ 0x000, 0, 0x00000, },
};
static int do_init(unsigned int instance, ether_addr_t *addr);
static int do_init(unsigned int instance, netdriver_addr_t *addr,
uint32_t *caps, unsigned int *ticks);
static void do_stop(void);
static void do_mode(unsigned int mode);
static void do_set_mode(unsigned int mode, const netdriver_addr_t *mcast_list,
unsigned int mcast_count);
static int do_send(struct netdriver_data *data, size_t size);
static ssize_t do_recv(struct netdriver_data *data, size_t max);
static void do_stat(eth_stat_t *stat);
static void do_intr(unsigned int mask);
static void do_tick(void);
static void do_other(const message *m_ptr, int ipc_status);
static const struct netdriver dp_table = {
.ndr_name = "dpe",
.ndr_init = do_init,
.ndr_stop = do_stop,
.ndr_mode = do_mode,
.ndr_set_mode = do_set_mode,
.ndr_recv = do_recv,
.ndr_send = do_send,
.ndr_stat = do_stat,
.ndr_intr = do_intr,
.ndr_tick = do_tick,
.ndr_other = do_other
};
@ -101,7 +102,7 @@ static void do_dump(void)
printf("\n\n");
printf("%s statistics:\t\t", dep->de_name);
printf("%s statistics:\t\t", netdriver_name());
/* Network interface status */
printf("Status: 0x%04x\n\n", dep->de_flags);
@ -111,22 +112,6 @@ static void do_dump(void)
/* Transmitted/received bytes */
printf("Tx bytes:%10ld\t", dep->bytes_Tx);
printf("Rx bytes:%10ld\n", dep->bytes_Rx);
/* Transmitted/received packets */
printf("Tx OK: %8ld\t", dep->de_stat.ets_packetT);
printf("Rx OK: %8ld\n", dep->de_stat.ets_packetR);
/* Transmit/receive errors */
printf("Tx Err: %8ld\t", dep->de_stat.ets_sendErr);
printf("Rx Err: %8ld\n", dep->de_stat.ets_recvErr);
/* Transmit unnerruns/receive overrruns */
printf("Tx Und: %8ld\t", dep->de_stat.ets_fifoUnder);
printf("Rx Ovr: %8ld\n", dep->de_stat.ets_fifoOver);
/* Transmit collisions/receive CRC errors */
printf("Tx Coll: %8ld\t", dep->de_stat.ets_collision);
printf("Rx CRC: %8ld\n", dep->de_stat.ets_CRCerr);
}
/*
@ -138,9 +123,6 @@ static void do_first_init(dpeth_t *dep, const dp_conf_t *dcp)
dep->de_linmem = 0xFFFF0000; /* FIXME: this overrides update_conf, why? */
/* Make sure statisics are cleared */
memset(&dep->de_stat, 0, sizeof(dep->de_stat));
/* Device specific initialization */
(*dep->de_initf)(dep);
@ -168,7 +150,8 @@ static void do_first_init(dpeth_t *dep, const dp_conf_t *dcp)
** Initialize hardware and data structures.
** Return status and ethernet address.
*/
static int do_init(unsigned int instance, ether_addr_t *addr)
static int do_init(unsigned int instance, netdriver_addr_t *addr,
uint32_t *caps, unsigned int *ticks)
{
dpeth_t *dep;
dp_conf_t *dcp;
@ -176,9 +159,6 @@ static int do_init(unsigned int instance, ether_addr_t *addr)
dep = &de_state;
strlcpy(dep->de_name, "dpeth#?", sizeof(dep->de_name));
dep->de_name[4] = '0' + instance;
/* Pick a default configuration for this instance. */
confnr = MIN(instance, DP_CONF_NR-1);
@ -192,7 +172,7 @@ static int do_init(unsigned int instance, ether_addr_t *addr)
!el2_probe(dep) && /* Probe for 3c503 */
!el3_probe(dep)) { /* Probe for 3c509 */
printf("%s: warning no ethernet card found at 0x%04X\n",
dep->de_name, dep->de_base_port);
netdriver_name(), dep->de_base_port);
return ENXIO;
}
@ -201,28 +181,33 @@ static int do_init(unsigned int instance, ether_addr_t *addr)
/* Request function key for debug dumps */
fkeys = sfkeys = 0; bit_set(sfkeys, 7);
if (fkey_map(&fkeys, &sfkeys) != OK)
printf("%s: couldn't bind Shift+F7 key (%d)\n", dep->de_name, errno);
printf("%s: couldn't bind Shift+F7 key (%d)\n",
netdriver_name(), errno);
memcpy(addr, dep->de_address.ea_addr, sizeof(*addr));
memcpy(addr, dep->de_address.na_addr, sizeof(*addr));
*caps = NDEV_CAP_MCAST | NDEV_CAP_BCAST; /* ..is this even accurate? */
*ticks = sys_hz(); /* update statistics once a second */
return OK;
}
/*
** Name: de_mode
** Name: de_set_mode
** Function: Sets packet receipt mode.
*/
static void do_mode(unsigned int mode)
static void do_set_mode(unsigned int mode,
const netdriver_addr_t * mcast_list __unused,
unsigned int mcast_count __unused)
{
dpeth_t *dep;
dep = &de_state;
dep->de_flags &= NOT(DEF_PROMISC | DEF_MULTI | DEF_BROAD);
if (mode & NDEV_PROMISC)
if (mode & NDEV_MODE_PROMISC)
dep->de_flags |= DEF_PROMISC | DEF_MULTI | DEF_BROAD;
if (mode & NDEV_MULTI)
if (mode & (NDEV_MODE_MCAST_LIST | NDEV_MODE_MCAST_ALL))
dep->de_flags |= DEF_MULTI;
if (mode & NDEV_BROAD)
if (mode & NDEV_MODE_BCAST)
dep->de_flags |= DEF_BROAD;
(*dep->de_flagsf)(dep);
}
@ -253,16 +238,6 @@ static ssize_t do_recv(struct netdriver_data *data, size_t max)
return (*dep->de_recvf)(dep, data, max);
}
/*
** Name: do_stat
** Function: Reports device statistics.
*/
static void do_stat(eth_stat_t *stat)
{
memcpy(stat, &de_state.de_stat, sizeof(*stat));
}
/*
** Name: do_stop
** Function: Stops network interface.
@ -292,6 +267,20 @@ static void do_intr(unsigned int __unused mask)
sys_irqenable(&dep->de_hook);
}
/*
** Name: do_tick
** Function: perform regular processing.
*/
static void do_tick(void)
{
dpeth_t *dep;
dep = &de_state;
if (dep->de_getstatsf != NULL)
(*dep->de_getstatsf)(dep);
}
/*
** Name: do_other
** Function: Processes miscellaneous messages.

View File

@ -101,17 +101,15 @@ typedef struct dpeth {
port_t de_base_port;
port_t de_data_port; /* For boards using Prog. I/O for xmit/recv */
int de_irq;
unsigned int de_irq;
int de_hook; /* interrupt hook at kernel */
char de_name[8];
#define DEI_DEFAULT 0x8000
phys_bytes de_linmem; /* For boards using shared memory */
char *de_locmem; /* Locally mapped (virtual) address */
int de_ramsize; /* Size of on board memory */
int de_offset_page; /* Offset of shared memory page */
unsigned int de_ramsize; /* Size of on board memory */
unsigned int de_offset_page; /* Offset of shared memory page */
/* Board specific functions */
dp_eth_t de_initf;
@ -124,12 +122,11 @@ typedef struct dpeth {
dp_recv_t de_recvf;
dp_send_t de_sendf;
ether_addr_t de_address; /* Ethernet Address */
eth_stat_t de_stat; /* Ethernet Statistics */
netdriver_addr_t de_address; /* Ethernet Address */
unsigned long bytes_Tx; /* Total bytes sent/received */
unsigned long bytes_Rx;
#define SA_ADDR_LEN sizeof(ether_addr_t)
#define SA_ADDR_LEN sizeof(netdriver_addr_t)
int de_flags; /* Send/Receive mode (Configuration) */
@ -144,8 +141,8 @@ typedef struct dpeth {
port_t de_dp8390_port;
int de_prog_IO;
int de_16bit;
int de_startpage;
int de_stoppage;
unsigned int de_startpage;
unsigned int de_stoppage;
/* Do it yourself send queue */
struct sendq {
@ -153,9 +150,9 @@ typedef struct dpeth {
int sq_size; /* with this size */
int sq_sendpage; /* starting page of the buffer */
} de_sendq[SENDQ_NR];
int de_sendq_nr;
int de_sendq_head; /* Enqueue at the head */
int de_sendq_tail; /* Dequeue at the tail */
unsigned int de_sendq_nr;
unsigned int de_sendq_head; /* Enqueue at the head */
unsigned int de_sendq_tail; /* Dequeue at the tail */
dp_user2nicf_t de_user2nicf;
dp_nic2userf_t de_nic2userf;

View File

@ -14,8 +14,6 @@
#include <minix/drivers.h>
#include <minix/netdriver.h>
#include <net/gen/ether.h>
#include <net/gen/eth_io.h>
#include "dp.h"
#if (ENABLE_NE2000 == 1)
@ -58,7 +56,7 @@ static void ne_close(dpeth_t * dep)
*/
static void ne_init(dpeth_t * dep)
{
int ix;
unsigned int ix;
dep->de_data_port = dep->de_base_port + NE_DATA;
if (dep->de_16bit) {
@ -85,12 +83,12 @@ static void ne_init(dpeth_t * dep)
ns_init(dep); /* Initialize DP controller */
printf("%s: NE%d000 (%dkB RAM) at %X:%d - ",
dep->de_name,
netdriver_name(),
dep->de_16bit ? 2 : 1,
dep->de_ramsize / 1024,
dep->de_base_port, dep->de_irq);
for (ix = 0; ix < SA_ADDR_LEN; ix += 1)
printf("%02X%c", dep->de_address.ea_addr[ix],
printf("%02X%c", dep->de_address.na_addr[ix],
ix < SA_ADDR_LEN - 1 ? ':' : '\n');
}
@ -103,7 +101,7 @@ static void ne_init(dpeth_t * dep)
*/
int ne_probe(dpeth_t * dep)
{
int ix, wd, loc1, loc2;
unsigned int ix, wd, loc1, loc2;
char EPROM[32];
static const struct {
unsigned char offset;
@ -176,7 +174,7 @@ int ne_probe(dpeth_t * dep)
/* Setup the ethernet address. */
for (ix = 0; ix < SA_ADDR_LEN; ix += 1) {
dep->de_address.ea_addr[ix] = EPROM[ix];
dep->de_address.na_addr[ix] = EPROM[ix];
}
dep->de_16bit = wd;
dep->de_linmem = 0; /* Uses Programmed I/O only */

View File

@ -9,8 +9,6 @@
#include <minix/drivers.h>
#include <minix/netdriver.h>
#include <net/gen/ether.h>
#include <net/gen/eth_io.h>
#include "dp.h"
#if (HAVE_BUFFERS == 1)
@ -90,7 +88,8 @@ void init_buff(dpeth_t *dep, buff_t **tx_buff)
free_buff(dep, rx + 1);
dep->de_recvq_tail = dep->de_recvq_head = NULL;
if (tx_buff != NULL) {
*tx_buff = alloc_buff(dep, ETH_MAX_PACK_SIZE + sizeof(buff_t));
*tx_buff = alloc_buff(dep,
NDEV_ETH_PACKET_MAX + sizeof(buff_t));
(*tx_buff)->size = 0;
}
}

View File

@ -14,8 +14,6 @@
#include <minix/drivers.h>
#include <minix/netdriver.h>
#include <net/gen/ether.h>
#include <net/gen/eth_io.h>
#include "dp.h"
#if (ENABLE_WDETH == 1)
@ -69,14 +67,14 @@ int wdeth_probe(dpeth_t *dep)
*===========================================================================*/
static void we_init(dpeth_t *dep)
{
int i, int_indx, int_nr;
unsigned int i, int_indx, int_nr;
int tlb, rambit, revision;
int icr, irr, hwr, b, gcr;
int we_type;
int sendq_nr;
unsigned int sendq_nr;
for (i = 0; i < 6; i += 1) {
dep->de_address.ea_addr[i] = inb_we(dep, EPL_EA0 + i);
dep->de_address.na_addr[i] = inb_we(dep, EPL_EA0 + i);
}
dep->de_dp8390_port = dep->de_base_port + EPL_DP8390;
@ -154,7 +152,7 @@ static void we_init(dpeth_t *dep)
irr = inb_we(dep, EPL_IRR);
int_indx = (icr & E_ICR_IR2) | ((irr & (E_IRR_IR0 | E_IRR_IR1)) >> 5);
int_nr = we_int_table[int_indx];
DEBUG(printf("%s: encoded irq= %d\n", dep->de_name, int_nr));
DEBUG(printf("%s: encoded irq= %d\n", netdriver_name(), int_nr));
if (dep->de_irq & DEI_DEFAULT) dep->de_irq = int_nr;
outb_we(dep, EPL_IRR, irr | E_IRR_IEN);
}
@ -169,7 +167,7 @@ static void we_init(dpeth_t *dep)
int_indx = ((gcr & E_790_GCR_IR2) >> 4) |
((gcr & (E_790_GCR_IR1 | E_790_GCR_IR0)) >> 2);
int_nr = we_790int_table[int_indx];
DEBUG(printf("%s: encoded irq= %d\n", dep->de_name, int_nr));
DEBUG(printf("%s: encoded irq= %d\n", netdriver_name(), int_nr));
if (dep->de_irq & DEI_DEFAULT) dep->de_irq = int_nr;
icr = inb_we(dep, EPL_790_ICR);
outb_we(dep, EPL_790_ICR, icr | E_790_ICR_EIL);
@ -195,14 +193,14 @@ static void we_init(dpeth_t *dep)
ns_init(dep); /* Initialize DP controller */
printf("%s: WD80%d3 (%dkB RAM) at %X:%d:%lX - ",
dep->de_name,
netdriver_name(),
we_type & WET_BRD_16BIT ? 1 : 0,
dep->de_ramsize / 1024,
dep->de_base_port,
dep->de_irq,
dep->de_linmem);
for (i = 0; i < SA_ADDR_LEN; i += 1)
printf("%02X%c", dep->de_address.ea_addr[i],
printf("%02X%c", dep->de_address.na_addr[i],
i < SA_ADDR_LEN - 1 ? ':' : '\n');
return;
@ -260,7 +258,7 @@ static int we_16bitboard(dpeth_t *dep)
* If the 16 bit enable bit is unchangable by software we'll assume an
* 8 bit board.
*/
int icr;
unsigned int icr;
u8_t tlb;
icr = inb_we(dep, EPL_ICR);
@ -269,7 +267,7 @@ static int we_16bitboard(dpeth_t *dep)
if (inb_we(dep, EPL_ICR) == icr) {
tlb = inb_we(dep, EPL_TLB);
DEBUG(printf("%s: tlb= 0x%x\n", dep->de_name, tlb));
DEBUG(printf("%s: tlb= 0x%x\n", netdriver_name(), tlb));
return tlb == E_TLB_EB || tlb == E_TLB_E ||
tlb == E_TLB_SMCE || tlb == E_TLB_SMC8216C;

View File

@ -9,4 +9,6 @@ FILESDIR= /etc/system.conf.d
DPADD+= ${LIBNETDRIVER} ${LIBSYS}
LDADD+= -lnetdriver -lsys
WARNS?= 5
.include <minix.service.mk>

View File

@ -10,14 +10,19 @@
#include "e1000_reg.h"
#include "e1000_pci.h"
static int e1000_init(unsigned int instance, ether_addr_t *addr);
static int e1000_init(unsigned int instance, netdriver_addr_t *addr,
uint32_t *caps, unsigned int *ticks);
static void e1000_stop(void);
static void e1000_set_mode(unsigned int, const netdriver_addr_t *,
unsigned int);
static void e1000_set_hwaddr(const netdriver_addr_t *);
static int e1000_send(struct netdriver_data *data, size_t size);
static ssize_t e1000_recv(struct netdriver_data *data, size_t max);
static void e1000_stat(eth_stat_t *stat);
static unsigned int e1000_get_link(uint32_t *);
static void e1000_intr(unsigned int mask);
static void e1000_tick(void);
static int e1000_probe(e1000_t *e, int skip);
static void e1000_init_hw(e1000_t *e, ether_addr_t *addr);
static void e1000_init_hw(e1000_t *e, netdriver_addr_t *addr);
static uint32_t e1000_reg_read(e1000_t *e, uint32_t reg);
static void e1000_reg_write(e1000_t *e, uint32_t reg, uint32_t value);
static void e1000_reg_set(e1000_t *e, uint32_t reg, uint32_t value);
@ -31,12 +36,16 @@ static int e1000_instance;
static e1000_t e1000_state;
static const struct netdriver e1000_table = {
.ndr_init = e1000_init,
.ndr_stop = e1000_stop,
.ndr_recv = e1000_recv,
.ndr_send = e1000_send,
.ndr_stat = e1000_stat,
.ndr_intr = e1000_intr,
.ndr_name = "em",
.ndr_init = e1000_init,
.ndr_stop = e1000_stop,
.ndr_set_mode = e1000_set_mode,
.ndr_set_hwaddr = e1000_set_hwaddr,
.ndr_recv = e1000_recv,
.ndr_send = e1000_send,
.ndr_get_link = e1000_get_link,
.ndr_intr = e1000_intr,
.ndr_tick = e1000_tick
};
/*
@ -58,7 +67,8 @@ main(int argc, char * argv[])
* Initialize the e1000 driver and device.
*/
static int
e1000_init(unsigned int instance, ether_addr_t * addr)
e1000_init(unsigned int instance, netdriver_addr_t * addr, uint32_t * caps,
unsigned int * ticks)
{
e1000_t *e;
int r;
@ -69,8 +79,6 @@ e1000_init(unsigned int instance, ether_addr_t * addr)
memset(&e1000_state, 0, sizeof(e1000_state));
e = &e1000_state;
strlcpy(e->name, "e1000#0", sizeof(e->name));
e->name[6] += instance;
/* Perform calibration. */
if ((r = tsc_calibrate()) != OK)
@ -83,6 +91,8 @@ e1000_init(unsigned int instance, ether_addr_t * addr)
/* Initialize the hardware, and return its ethernet address. */
e1000_init_hw(e, addr);
*caps = NDEV_CAP_MCAST | NDEV_CAP_BCAST | NDEV_CAP_HWADDR;
*ticks = sys_hz() / 10; /* update statistics 10x/sec */
return OK;
}
@ -138,9 +148,9 @@ e1000_probe(e1000_t * e, int skip)
u16_t vid, did, cr;
u32_t status;
u32_t base, size;
char *dname;
const char *dname;
E1000_DEBUG(3, ("%s: probe()\n", e->name));
E1000_DEBUG(3, ("%s: probe()\n", netdriver_name()));
/* Initialize communication to the PCI driver. */
pci_init();
@ -152,7 +162,7 @@ e1000_probe(e1000_t * e, int skip)
/* Loop devices on the PCI bus. */
while (skip--) {
E1000_DEBUG(3, ("%s: probe() devind %d vid 0x%x did 0x%x\n",
e->name, devind, vid, did));
netdriver_name(), devind, vid, did));
if (!(r = pci_next_dev(&devind, &vid, &did)))
return FALSE;
@ -184,7 +194,7 @@ e1000_probe(e1000_t * e, int skip)
if (!(dname = pci_dev_name(vid, did)))
dname = "Intel Pro/1000 Gigabit Ethernet Card";
E1000_DEBUG(1, ("%s: %s (%04x/%04x) at %s\n",
e->name, dname, vid, did, pci_slot_name(devind)));
netdriver_name(), dname, vid, did, pci_slot_name(devind)));
/* Reserve PCI resources found. */
pci_reserve(devind);
@ -210,8 +220,9 @@ e1000_probe(e1000_t * e, int skip)
/* Output debug information. */
status = e1000_reg_read(e, E1000_REG_STATUS);
E1000_DEBUG(3, ("%s: MEM at %p, IRQ %d\n", e->name, e->regs, e->irq));
E1000_DEBUG(3, ("%s: link %s, %s duplex\n", e->name,
E1000_DEBUG(3, ("%s: MEM at %p, IRQ %d\n", netdriver_name(),
e->regs, e->irq));
E1000_DEBUG(3, ("%s: link %s, %s duplex\n", netdriver_name(),
status & 3 ? "up" : "down", status & 1 ? "full" : "half"));
return TRUE;
@ -235,7 +246,7 @@ e1000_reset_hw(e1000_t * e)
* Initialize and return the card's ethernet address.
*/
static void
e1000_init_addr(e1000_t * e, ether_addr_t * addr)
e1000_init_addr(e1000_t * e, netdriver_addr_t * addr)
{
static char eakey[] = E1000_ENVVAR "#_EA";
static char eafmt[] = "x:x:x:x:x:x";
@ -250,27 +261,25 @@ e1000_init_addr(e1000_t * e, ether_addr_t * addr)
if (env_parse(eakey, eafmt, i, &v, 0x00L, 0xFFL) != EP_SET)
break;
else
addr->ea_addr[i] = v;
addr->na_addr[i] = v;
}
/* If that fails, read Ethernet Address from EEPROM. */
if (i != 6) {
for (i = 0; i < 3; i++) {
word = e->eeprom_read(e, i);
addr->ea_addr[i * 2] = (word & 0x00ff);
addr->ea_addr[i * 2 + 1] = (word & 0xff00) >> 8;
addr->na_addr[i * 2] = (word & 0x00ff);
addr->na_addr[i * 2 + 1] = (word & 0xff00) >> 8;
}
}
/* Set Receive Address. */
e1000_reg_write(e, E1000_REG_RAL, *(u32_t *)(&addr->ea_addr[0]));
e1000_reg_write(e, E1000_REG_RAH, *(u16_t *)(&addr->ea_addr[4]));
e1000_reg_set(e, E1000_REG_RAH, E1000_REG_RAH_AV);
e1000_reg_set(e, E1000_REG_RCTL, E1000_REG_RCTL_MPE);
e1000_set_hwaddr(addr);
E1000_DEBUG(3, ("%s: Ethernet Address %x:%x:%x:%x:%x:%x\n", e->name,
addr->ea_addr[0], addr->ea_addr[1], addr->ea_addr[2],
addr->ea_addr[3], addr->ea_addr[4], addr->ea_addr[5]));
E1000_DEBUG(3, ("%s: Ethernet Address %x:%x:%x:%x:%x:%x\n",
netdriver_name(),
addr->na_addr[0], addr->na_addr[1], addr->na_addr[2],
addr->na_addr[3], addr->na_addr[4], addr->na_addr[5]));
}
/*
@ -348,7 +357,7 @@ e1000_init_buf(e1000_t * e)
* Initialize the hardware. Return the ethernet address.
*/
static void
e1000_init_hw(e1000_t * e, ether_addr_t * addr)
e1000_init_hw(e1000_t * e, netdriver_addr_t * addr)
{
int r, i;
@ -399,6 +408,52 @@ e1000_init_hw(e1000_t * e, ether_addr_t * addr)
E1000_REG_IMS_RXT | E1000_REG_IMS_TXQE | E1000_REG_IMS_TXDW);
}
/*
* Set receive mode.
*/
static void
e1000_set_mode(unsigned int mode, const netdriver_addr_t * mcast_list __unused,
unsigned int mcast_count __unused)
{
e1000_t *e;
uint32_t rctl;
e = &e1000_state;
rctl = e1000_reg_read(e, E1000_REG_RCTL);
rctl &= ~(E1000_REG_RCTL_BAM | E1000_REG_RCTL_MPE |
E1000_REG_RCTL_UPE);
/* TODO: support for NDEV_MODE_DOWN and multicast lists */
if (mode & NDEV_MODE_BCAST)
rctl |= E1000_REG_RCTL_BAM;
if (mode & (NDEV_MODE_MCAST_LIST | NDEV_MODE_MCAST_ALL))
rctl |= E1000_REG_RCTL_MPE;
if (mode & NDEV_MODE_PROMISC)
rctl |= E1000_REG_RCTL_BAM | E1000_REG_RCTL_MPE |
E1000_REG_RCTL_UPE;
e1000_reg_write(e, E1000_REG_RCTL, rctl);
}
/*
* Set hardware address.
*/
static void
e1000_set_hwaddr(const netdriver_addr_t * hwaddr)
{
e1000_t *e;
e = &e1000_state;
e1000_reg_write(e, E1000_REG_RAL,
*(const u32_t *)(&hwaddr->na_addr[0]));
e1000_reg_write(e, E1000_REG_RAH,
*(const u16_t *)(&hwaddr->na_addr[4]));
e1000_reg_set(e, E1000_REG_RAH, E1000_REG_RAH_AV);
}
/*
* Try to send a packet.
*/
@ -463,7 +518,8 @@ e1000_recv(struct netdriver_data * data, size_t max)
head = e1000_reg_read(e, E1000_REG_RDH);
tail = e1000_reg_read(e, E1000_REG_RDT);
E1000_DEBUG(4, ("%s: head=%u, tail=%u\n", e->name, head, tail));
E1000_DEBUG(4, ("%s: head=%u, tail=%u\n",
netdriver_name(), head, tail));
if (head == tail)
return SUSPEND;
@ -506,40 +562,38 @@ e1000_recv(struct netdriver_data * data, size_t max)
}
/*
* Return statistics.
* Return the link and media status.
*/
static void
e1000_stat(eth_stat_t * stat)
static unsigned int
e1000_get_link(uint32_t * media)
{
e1000_t *e = &e1000_state;
uint32_t status, type;
E1000_DEBUG(3, ("e1000: stat()\n"));
status = e1000_reg_read(&e1000_state, E1000_REG_STATUS);
stat->ets_recvErr = e1000_reg_read(e, E1000_REG_RXERRC);
stat->ets_sendErr = 0;
stat->ets_OVW = 0;
stat->ets_CRCerr = e1000_reg_read(e, E1000_REG_CRCERRS);
stat->ets_frameAll = 0;
stat->ets_missedP = e1000_reg_read(e, E1000_REG_MPC);
stat->ets_packetR = e1000_reg_read(e, E1000_REG_TPR);
stat->ets_packetT = e1000_reg_read(e, E1000_REG_TPT);
stat->ets_collision = e1000_reg_read(e, E1000_REG_COLC);
stat->ets_transAb = 0;
stat->ets_carrSense = 0;
stat->ets_fifoUnder = 0;
stat->ets_fifoOver = 0;
stat->ets_CDheartbeat = 0;
stat->ets_OWC = 0;
}
if (!(status & E1000_REG_STATUS_LU))
return NDEV_LINK_DOWN;
/*
* Link status has changed. Nothing to do for now.
*/
static void
e1000_link_changed(e1000_t * e)
{
if (status & E1000_REG_STATUS_FD)
type = IFM_ETHER | IFM_FDX;
else
type = IFM_ETHER | IFM_HDX;
E1000_DEBUG(4, ("%s: link_changed()\n", e->name));
switch (status & E1000_REG_STATUS_SPEED) {
case E1000_REG_STATUS_SPEED_10:
type |= IFM_10_T;
break;
case E1000_REG_STATUS_SPEED_100:
type |= IFM_100_TX;
break;
case E1000_REG_STATUS_SPEED_1000_A:
case E1000_REG_STATUS_SPEED_1000_B:
type |= IFM_1000_T;
break;
}
*media = type;
return NDEV_LINK_UP;
}
/*
@ -562,7 +616,7 @@ e1000_intr(unsigned int __unused mask)
/* Read the Interrupt Cause Read register. */
if ((cause = e1000_reg_read(e, E1000_REG_ICR)) != 0) {
if (cause & E1000_REG_ICR_LSC)
e1000_link_changed(e);
netdriver_link();
if (cause & (E1000_REG_ICR_RXO | E1000_REG_ICR_RXT))
netdriver_recv();
@ -572,6 +626,23 @@ e1000_intr(unsigned int __unused mask)
}
}
/*
* Do regular processing.
*/
static void
e1000_tick(void)
{
e1000_t *e;
e = &e1000_state;
/* Update statistics. */
netdriver_stat_ierror(e1000_reg_read(e, E1000_REG_RXERRC));
netdriver_stat_ierror(e1000_reg_read(e, E1000_REG_CRCERRS));
netdriver_stat_ierror(e1000_reg_read(e, E1000_REG_MPC));
netdriver_stat_coll(e1000_reg_read(e, E1000_REG_COLC));
}
/*
* Stop the card.
*/
@ -582,7 +653,7 @@ e1000_stop(void)
e = &e1000_state;
E1000_DEBUG(3, ("%s: stop()\n", e->name));
E1000_DEBUG(3, ("%s: stop()\n", netdriver_name()));
e1000_reset_hw(e);
}

View File

@ -112,7 +112,6 @@
*/
typedef struct e1000
{
char name[8]; /**< String containing the device name. */
int irq; /**< Interrupt Request Vector. */
int irq_hook; /**< Interrupt Request Vector Hook. */
u8_t *regs; /**< Memory mapped hardware registers. */

View File

@ -164,6 +164,11 @@
/** Link Speed Setting. */
#define E1000_REG_STATUS_SPEED ((1 << 6) | (1 << 7))
#define E1000_REG_STATUS_SPEED_10 (0 << 6) /* 10 Mb/s */
#define E1000_REG_STATUS_SPEED_100 (1 << 6) /* 100 Mb/s */
#define E1000_REG_STATUS_SPEED_1000_A (2 << 6) /* 1000 Mb/s */
#define E1000_REG_STATUS_SPEED_1000_B (3 << 6) /* 1000 Mb/s */
/**
* @}
*/
@ -245,7 +250,10 @@
/** Receive Enable. */
#define E1000_REG_RCTL_EN (1 << 1)
/** Multicast Promiscious Enable. */
/** Unicast Promiscuous Enable. */
#define E1000_REG_RCTL_UPE (1 << 3)
/** Multicast Promiscuous Enable. */
#define E1000_REG_RCTL_MPE (1 << 4)
/** Broadcast Accept Mode. */

View File

@ -9,4 +9,6 @@ FILESDIR= /etc/system.conf.d
DPADD+= ${LIBNETDRIVER} ${LIBSYS}
LDADD+= -lnetdriver -lsys
WARNS?= 5
.include <minix.service.mk>

View File

@ -76,7 +76,6 @@ typedef struct fxp
irq_hook_t fxp_hook;
struct sc fxp_stat;
u8_t fxp_conf_bytes[CC_BYTES_NR];
char fxp_name[sizeof("fxp#n")];
} fxp_t;
/* fxp_type */
@ -86,8 +85,6 @@ typedef struct fxp
#define FT_82559 0x4
#define FT_82801 0x8
static int fxp_instance;
static fxp_t *fxp_state;
#define fxp_inb(port, offset) (do_inb((port) + (offset)))
@ -95,16 +92,20 @@ static fxp_t *fxp_state;
#define fxp_outb(port, offset, value) (do_outb((port) + (offset), (value)))
#define fxp_outl(port, offset, value) (do_outl((port) + (offset), (value)))
static int fxp_init(unsigned int instance, ether_addr_t *addr);
static int fxp_init(unsigned int instance, netdriver_addr_t *addr,
uint32_t *caps, unsigned int *ticks);
static void fxp_intr(unsigned int __unused mask);
static void fxp_stop(void);
static int fxp_probe(fxp_t *fp, int skip);
static void fxp_conf_hw(fxp_t *fp);
static void fxp_init_hw(fxp_t *fp, ether_addr_t *addr);
static void fxp_init_hw(fxp_t *fp, netdriver_addr_t *addr,
unsigned int instance);
static void fxp_init_buf(fxp_t *fp);
static void fxp_reset_hw(fxp_t *fp);
static void fxp_confaddr(fxp_t *fp, ether_addr_t *addr);
static void fxp_mode(unsigned int mode);
static void fxp_confaddr(fxp_t *fp, netdriver_addr_t *addr,
unsigned int instance);
static void fxp_set_mode(unsigned int mode, const netdriver_addr_t *mcast_list,
unsigned int mcast_count);
static int fxp_send(struct netdriver_data *data, size_t size);
static ssize_t fxp_recv(struct netdriver_data *data, size_t max);
static void fxp_do_conf(fxp_t *fp);
@ -113,11 +114,11 @@ static void fxp_cu_ptr_cmd(fxp_t *fp, int cmd, phys_bytes bus_addr, int
static void fxp_ru_ptr_cmd(fxp_t *fp, int cmd, phys_bytes bus_addr, int
check_idle);
static void fxp_restart_ru(fxp_t *fp);
static void fxp_stat(eth_stat_t *stat);
static void fxp_handler(fxp_t *fp);
static void fxp_check_ints(fxp_t *fp);
static void fxp_alarm(clock_t stamp);
static void fxp_tick(void);
static int fxp_link_changed(fxp_t *fp);
static unsigned int fxp_get_link(uint32_t *media);
static void fxp_report_link(fxp_t *fp);
static u16_t eeprom_read(fxp_t *fp, int reg);
static void eeprom_addrsize(fxp_t *fp);
@ -130,14 +131,15 @@ static void tell_iommu(vir_bytes start, size_t size, int pci_bus, int
pci_dev, int pci_func);
static const struct netdriver fxp_table = {
.ndr_name = "fxp",
.ndr_init = fxp_init,
.ndr_stop = fxp_stop,
.ndr_mode = fxp_mode,
.ndr_set_mode = fxp_set_mode,
.ndr_recv = fxp_recv,
.ndr_send = fxp_send,
.ndr_stat = fxp_stat,
.ndr_get_link = fxp_get_link,
.ndr_intr = fxp_intr,
.ndr_alarm = fxp_alarm,
.ndr_tick = fxp_tick,
};
/*===========================================================================*
@ -187,7 +189,7 @@ static void fxp_stop(void)
/* Stop device */
#if VERBOSE
printf("%s: stopping device\n", fp->fxp_name);
printf("%s: stopping device\n", netdriver_name());
#endif
fxp_outl(port, CSR_PORT, CP_CMD_SOFT_RESET);
@ -196,13 +198,12 @@ static void fxp_stop(void)
/*===========================================================================*
* fxp_init *
*===========================================================================*/
static int fxp_init(unsigned int instance, ether_addr_t *addr)
static int fxp_init(unsigned int instance, netdriver_addr_t *addr,
uint32_t *caps, unsigned int *ticks)
{
fxp_t *fp;
int r;
fxp_instance = instance;
if (!(fxp_state = alloc_contig(sizeof(*fxp_state), 0, NULL)))
panic("couldn't allocate table");
@ -210,25 +211,20 @@ static int fxp_init(unsigned int instance, ether_addr_t *addr)
memset(fp, 0, sizeof(*fp));
strlcpy(fp->fxp_name, "fxp#0", sizeof(fp->fxp_name));
fp->fxp_name[4] += fxp_instance;
if ((r = tsc_calibrate()) != OK)
panic("tsc_calibrate failed: %d", r);
/* Configure PCI device. */
if (!fxp_probe(fp, fxp_instance))
if (!fxp_probe(fp, instance))
return ENXIO;
fxp_conf_hw(fp);
fxp_init_hw(fp, addr);
fxp_init_hw(fp, addr, instance);
fxp_report_link(fp);
/* Set watchdog timer. */
if ((r = sys_setalarm(sys_hz(), 0)) != OK)
panic("unable to set watchdog alarm");
*caps = NDEV_CAP_MCAST | NDEV_CAP_BCAST;
*ticks = sys_hz();
return OK;
}
@ -241,9 +237,9 @@ static int fxp_probe(fxp_t *fp, int skip)
u16_t vid, did, cr;
u32_t bar;
u8_t ilr, rev;
char *str;
const char *str;
#if VERBOSE
char *dname;
const char *dname;
#endif
pci_init();
@ -264,7 +260,7 @@ static int fxp_probe(fxp_t *fp, int skip)
if (!dname)
dname= "unknown device";
printf("%s: %s (%04x/%04x) at %s\n",
fp->fxp_name, dname, vid, did, pci_slot_name(devind));
netdriver_name(), dname, vid, did, pci_slot_name(devind));
#endif
pci_reserve(devind);
@ -283,7 +279,7 @@ static int fxp_probe(fxp_t *fp, int skip)
fp->fxp_irq= ilr;
#if VERBOSE
printf("%s: using I/O address 0x%lx, IRQ %d\n",
fp->fxp_name, (unsigned long)bar, ilr);
netdriver_name(), (unsigned long)bar, ilr);
#endif
rev= pci_attr_r8(devind, PCI_REV);
@ -338,9 +334,10 @@ static int fxp_probe(fxp_t *fp, int skip)
#if VERBOSE
if (str)
printf("%s: device revision: %s\n", fp->fxp_name, str);
printf("%s: device revision: %s\n", netdriver_name(), str);
else
printf("%s: unknown revision: 0x%x\n", fp->fxp_name, rev);
printf("%s: unknown revision: 0x%x\n", netdriver_name(),
rev);
#endif
if (fp->fxp_type == FT_UNKNOWN)
@ -445,7 +442,8 @@ static void fxp_conf_hw(fxp_t *fp)
/*===========================================================================*
* fxp_init_hw *
*===========================================================================*/
static void fxp_init_hw(fxp_t *fp, ether_addr_t *addr)
static void fxp_init_hw(fxp_t *fp, netdriver_addr_t *addr,
unsigned int instance)
{
int r, isr;
port_t port;
@ -490,7 +488,7 @@ static void fxp_init_hw(fxp_t *fp, ether_addr_t *addr)
fxp_ru_ptr_cmd(fp, SC_RU_START, fp->fxp_rx_busaddr,
TRUE /* check idle */);
fxp_confaddr(fp, addr);
fxp_confaddr(fp, addr, instance);
}
/*===========================================================================*
@ -624,7 +622,8 @@ fxp_t *fp;
/*===========================================================================*
* fxp_confaddr *
*===========================================================================*/
static void fxp_confaddr(fxp_t *fp, ether_addr_t *addr)
static void fxp_confaddr(fxp_t *fp, netdriver_addr_t *addr,
unsigned int instance)
{
static char eakey[]= FXP_ENVVAR "#_EA";
static char eafmt[]= "x:x:x:x:x:x";
@ -633,13 +632,13 @@ static void fxp_confaddr(fxp_t *fp, ether_addr_t *addr)
long v;
/* User defined ethernet address? */
eakey[sizeof(FXP_ENVVAR)-1]= '0' + fxp_instance;
eakey[sizeof(FXP_ENVVAR)-1]= '0' + instance;
for (i= 0; i < 6; i++)
{
if (env_parse(eakey, eafmt, i, &v, 0x00L, 0xFFL) != EP_SET)
break;
addr->ea_addr[i]= v;
addr->na_addr[i]= v;
}
if (i != 0 && i != 6) env_panic(eakey); /* It's all or nothing */
@ -650,8 +649,8 @@ static void fxp_confaddr(fxp_t *fp, ether_addr_t *addr)
for (i= 0; i<3; i++)
{
v= eeprom_read(fp, i);
addr->ea_addr[i*2]= (v & 0xff);
addr->ea_addr[i*2+1]= ((v >> 8) & 0xff);
addr->na_addr[i*2]= (v & 0xff);
addr->na_addr[i*2+1]= ((v >> 8) & 0xff);
}
}
@ -659,7 +658,7 @@ static void fxp_confaddr(fxp_t *fp, ether_addr_t *addr)
tmpbufp->ias.ias_status= 0;
tmpbufp->ias.ias_command= CBL_C_EL | CBL_AIS;
tmpbufp->ias.ias_linkaddr= 0;
memcpy(tmpbufp->ias.ias_ethaddr, addr->ea_addr,
memcpy(tmpbufp->ias.ias_ethaddr, addr->na_addr,
sizeof(tmpbufp->ias.ias_ethaddr));
r= sys_umap(SELF, VM_D, (vir_bytes)&tmpbufp->ias,
(phys_bytes)sizeof(tmpbufp->ias), &bus_addr);
@ -677,17 +676,19 @@ static void fxp_confaddr(fxp_t *fp, ether_addr_t *addr)
panic("fxp_confaddr: CU command failed");
#if VERBOSE
printf("%s: hardware ethernet address: ", fp->fxp_name);
printf("%s: hardware ethernet address: ", netdriver_name());
for (i= 0; i<6; i++)
printf("%02x%s", addr->ea_addr[i], i < 5 ? ":" : "");
printf("%02x%s", addr->na_addr[i], i < 5 ? ":" : "");
printf("\n");
#endif
}
/*===========================================================================*
* fxp_mode *
* fxp_set_mode *
*===========================================================================*/
static void fxp_mode(unsigned int mode)
static void fxp_set_mode(unsigned int mode,
const netdriver_addr_t * mcast_list __unused,
unsigned int mcast_count __unused)
{
fxp_t *fp;
@ -697,12 +698,13 @@ static void fxp_mode(unsigned int mode)
fp->fxp_conf_bytes[15] &= ~(CCB15_BD|CCB15_PM);
fp->fxp_conf_bytes[21] &= ~CCB21_MA;
if (mode & NDEV_PROMISC)
if (mode & NDEV_MODE_PROMISC)
fp->fxp_conf_bytes[15] |= CCB15_PM;
if (mode & NDEV_MULTI)
if (mode & (NDEV_MODE_MCAST_LIST | NDEV_MODE_MCAST_ALL))
fp->fxp_conf_bytes[21] |= CCB21_MA;
if (!(mode & (NDEV_BROAD|NDEV_MULTI|NDEV_PROMISC)))
if (!(mode & (NDEV_MODE_BCAST | NDEV_MODE_MCAST_LIST |
NDEV_MODE_MCAST_ALL | NDEV_MODE_PROMISC)))
fp->fxp_conf_bytes[15] |= CCB15_BD;
/* Queue request if not idle */
@ -1034,9 +1036,9 @@ fxp_t *fp;
}
/*===========================================================================*
* fxp_stat *
* fxp_update_stats *
*===========================================================================*/
static void fxp_stat(eth_stat_t *stat)
static void fxp_update_stats(void)
{
fxp_t *fp;
u32_t *p;
@ -1049,41 +1051,26 @@ static void fxp_stat(eth_stat_t *stat)
/* The dump commmand doesn't take a pointer. Setting a pointer
* doesn't hurt though.
*/
fxp_cu_ptr_cmd(fp, SC_CU_DUMP_SC, 0, FALSE /* do not check idle */);
fxp_cu_ptr_cmd(fp, SC_CU_DUMP_RSET_SC, 0,
FALSE /* do not check idle */);
/* Wait for CU command to complete */
SPIN_UNTIL(*p != 0, 1000);
SPIN_UNTIL(*p != 0, 2500);
if (*p == 0)
panic("fxp_stat: CU command failed to complete");
if (*p != SCM_DSC)
if (*p != SCM_DRSC)
panic("fxp_stat: bad magic");
stat->ets_recvErr=
fp->fxp_stat.sc_rx_crc +
netdriver_stat_ierror(fp->fxp_stat.sc_rx_crc +
fp->fxp_stat.sc_rx_align +
fp->fxp_stat.sc_rx_resource +
fp->fxp_stat.sc_rx_overrun +
fp->fxp_stat.sc_rx_cd +
fp->fxp_stat.sc_rx_short;
stat->ets_sendErr=
fp->fxp_stat.sc_tx_maxcol +
fp->fxp_stat.sc_tx_latecol +
fp->fxp_stat.sc_tx_crs;
stat->ets_OVW= fp->fxp_stat.sc_rx_overrun;
stat->ets_CRCerr= fp->fxp_stat.sc_rx_crc;
stat->ets_frameAll= fp->fxp_stat.sc_rx_align;
stat->ets_missedP= fp->fxp_stat.sc_rx_resource;
stat->ets_packetR= fp->fxp_stat.sc_rx_good;
stat->ets_packetT= fp->fxp_stat.sc_tx_good;
stat->ets_transDef= fp->fxp_stat.sc_tx_defered;
stat->ets_collision= fp->fxp_stat.sc_tx_totcol;
stat->ets_transAb= fp->fxp_stat.sc_tx_maxcol;
stat->ets_carrSense= fp->fxp_stat.sc_tx_crs;
stat->ets_fifoUnder= fp->fxp_stat.sc_tx_underrun;
stat->ets_fifoOver= fp->fxp_stat.sc_rx_overrun;
stat->ets_CDheartbeat= 0;
stat->ets_OWC= fp->fxp_stat.sc_tx_latecol;
fp->fxp_stat.sc_rx_short);
netdriver_stat_coll(fp->fxp_stat.sc_tx_maxcol +
fp->fxp_stat.sc_tx_latecol);
netdriver_stat_oerror(fp->fxp_stat.sc_tx_crs);
}
/*===========================================================================*
@ -1243,25 +1230,28 @@ static void fxp_check_ints(fxp_t *fp)
}
}
if (fp->fxp_report_link)
if (fp->fxp_report_link) {
netdriver_link();
fxp_report_link(fp);
}
}
/*===========================================================================*
* fxp_alarm *
* fxp_tick *
*===========================================================================*/
static void fxp_alarm(clock_t __unused stamp)
static void fxp_tick(void)
{
fxp_t *fp;
sys_setalarm(sys_hz(), 0);
fxp_update_stats();
fp= fxp_state;
/* Check the link status. */
if (fxp_link_changed(fp)) {
#if VERBOSE
printf("fxp_alarm: link changed\n");
printf("fxp_tick: link changed\n");
#endif
fp->fxp_report_link= TRUE;
fxp_check_ints(fp);
@ -1297,6 +1287,37 @@ static int fxp_link_changed(fxp_t *fp)
return (fp->fxp_mii_scr != scr);
}
/*===========================================================================*
* fxp_get_link *
*===========================================================================*/
static unsigned int fxp_get_link(uint32_t *media)
{
fxp_t *fp;
u16_t mii_status, scr;
fp = fxp_state;
scr= mii_read(fp, MII_SCR);
mii_read(fp, MII_STATUS); /* The status reg is latched, read twice */
mii_status= mii_read(fp, MII_STATUS);
if (!(mii_status & MII_STATUS_LS))
return NDEV_LINK_DOWN;
if (scr & MII_SCR_100)
*media = IFM_ETHER | IFM_100_TX;
else
*media = IFM_ETHER | IFM_10_T;
if (scr & MII_SCR_FD)
*media |= IFM_FDX;
else
*media |= IFM_HDX;
return NDEV_LINK_UP;
}
/*===========================================================================*
* fxp_report_link *
*===========================================================================*/
@ -1345,7 +1366,7 @@ static void fxp_report_link(fxp_t *fp)
if (!link_up)
{
#if VERBOSE
printf("%s: link down\n", fp->fxp_name);
printf("%s: link down\n", netdriver_name());
#endif
return;
}
@ -1361,8 +1382,9 @@ static void fxp_report_link(fxp_t *fp)
if (mii_ctrl & (MII_CTRL_LB|MII_CTRL_PD|MII_CTRL_ISO))
{
printf("%s: PHY: ", fp->fxp_name);
f= 1;
#if VERBOSE
printf("%s: PHY: ", netdriver_name());
if (mii_ctrl & MII_CTRL_LB)
{
printf("loopback mode");
@ -1381,11 +1403,13 @@ static void fxp_report_link(fxp_t *fp)
printf("isolated");
}
printf("\n");
#endif
return;
}
if (!(mii_ctrl & MII_CTRL_ANE))
{
printf("%s: manual config: ", fp->fxp_name);
#if VERBOSE
printf("%s: manual config: ", netdriver_name());
switch(mii_ctrl & (MII_CTRL_SP_LSB|MII_CTRL_SP_MSB))
{
case MII_CTRL_SP_10: printf("10 Mbps"); break;
@ -1398,36 +1422,38 @@ static void fxp_report_link(fxp_t *fp)
else
printf(", half duplex");
printf("\n");
#endif
return;
}
#if VERBOSE
printf("%s: ", fp->fxp_name);
printf("%s: ", netdriver_name());
mii_print_stat_speed(mii_status, mii_extstat);
printf("\n");
if (!(mii_status & MII_STATUS_ANC))
printf("%s: auto-negotiation not complete\n", fp->fxp_name);
printf("%s: auto-negotiation not complete\n",
netdriver_name());
if (mii_status & MII_STATUS_RF)
printf("%s: remote fault detected\n", fp->fxp_name);
printf("%s: remote fault detected\n", netdriver_name());
if (!(mii_status & MII_STATUS_ANA))
{
printf("%s: local PHY has no auto-negotiation ability\n",
fp->fxp_name);
netdriver_name());
}
if (!(mii_status & MII_STATUS_LS))
printf("%s: link down\n", fp->fxp_name);
printf("%s: link down\n", netdriver_name());
if (mii_status & MII_STATUS_JD)
printf("%s: jabber condition detected\n", fp->fxp_name);
printf("%s: jabber condition detected\n", netdriver_name());
if (!(mii_status & MII_STATUS_EC))
{
printf("%s: no extended register set\n", fp->fxp_name);
printf("%s: no extended register set\n", netdriver_name());
goto resspeed;
}
if (!(mii_status & MII_STATUS_ANC))
goto resspeed;
printf("%s: local cap.: ", fp->fxp_name);
printf("%s: local cap.: ", netdriver_name());
if (mii_ms_ctrl & (MII_MSC_1000T_FD | MII_MSC_1000T_HD))
{
printf("1000 Mbps: T-");
@ -1444,15 +1470,15 @@ static void fxp_report_link(fxp_t *fp)
printf("\n");
if (mii_ane & MII_ANE_PDF)
printf("%s: parallel detection fault\n", fp->fxp_name);
printf("%s: parallel detection fault\n", netdriver_name());
if (!(mii_ane & MII_ANE_LPANA))
{
printf("%s: link-partner does not support auto-negotiation\n",
fp->fxp_name);
netdriver_name());
goto resspeed;
}
printf("%s: remote cap.: ", fp->fxp_name);
printf("%s: remote cap.: ", netdriver_name());
if (mii_ms_ctrl & (MII_MSC_1000T_FD | MII_MSC_1000T_HD))
if (mii_ms_status & (MII_MSS_LP1000T_FD | MII_MSS_LP1000T_HD))
{
@ -1472,7 +1498,7 @@ static void fxp_report_link(fxp_t *fp)
if (fp->fxp_ms_regs)
{
printf("%s: ", fp->fxp_name);
printf("%s: ", netdriver_name());
if (mii_ms_ctrl & MII_MSC_MS_MANUAL)
{
printf("manual %s",
@ -1502,17 +1528,17 @@ static void fxp_report_link(fxp_t *fp)
if (!(mii_ms_status & MII_MSS_LOCREC))
{
printf("%s: local receiver not OK\n",
fp->fxp_name);
netdriver_name());
}
if (!(mii_ms_status & MII_MSS_REMREC))
{
printf("%s: remote receiver not OK\n",
fp->fxp_name);
netdriver_name());
}
}
if (mii_ms_status & (MII_MSS_RES|MII_MSS_IDLE_ERR))
{
printf("%s", fp->fxp_name);
printf("%s", netdriver_name());
if (mii_ms_status & MII_MSS_RES)
printf(" reserved<0x%x>", mii_ms_status & MII_MSS_RES);
if (mii_ms_status & MII_MSS_IDLE_ERR)
@ -1527,7 +1553,7 @@ resspeed:
#if VERBOSE
printf("%s: link up, %d Mbps, %s duplex\n",
fp->fxp_name, (scr & MII_SCR_100) ? 100 : 10,
netdriver_name(), (scr & MII_SCR_100) ? 100 : 10,
(scr & MII_SCR_FD) ? "full" : "half");
#endif
}
@ -1643,7 +1669,7 @@ static void eeprom_addrsize(fxp_t *fp)
#if VERBOSE
printf("%s EEPROM address length: %d\n",
fp->fxp_name, fp->fxp_ee_addrlen);
netdriver_name(), fp->fxp_ee_addrlen);
#endif
}

View File

@ -429,7 +429,7 @@ struct tx
u16_t tx_size;
u8_t tx_tthresh;
u8_t tx_ntbd;
u8_t tx_buf[ETH_MAX_PACK_SIZE_TAGGED];
u8_t tx_buf[NDEV_ETH_PACKET_MAX_TAGGED];
};
#define TXS_C 0x8000 /* Transmit DMA has completed */
@ -506,7 +506,7 @@ struct rfd
u32_t rfd_reserved;
u16_t rfd_res;
u16_t rfd_size;
u8_t rfd_buf[ETH_MAX_PACK_SIZE_TAGGED];
u8_t rfd_buf[NDEV_ETH_PACKET_MAX_TAGGED];
};
#define RFDS_C 0x8000 /* Frame Reception Completed */

View File

@ -10,20 +10,21 @@ static NDR_driver g_driver;
static int g_instance;
/* driver interface */
static int NDR_init(unsigned int instance, ether_addr_t *addr);
static int NDR_init(unsigned int instance, netdriver_addr_t * addr,
uint32_t * caps, unsigned int * ticks);
static void NDR_stop(void);
static void NDR_mode(unsigned int mode);
static void NDR_set_mode(unsigned int mode,
const netdriver_addr_t * mcast_list, unsigned int mcast_count);
static ssize_t NDR_recv(struct netdriver_data *data, size_t max);
static int NDR_send(struct netdriver_data *data, size_t size);
static void NDR_intr(unsigned int mask);
static void NDR_stat(eth_stat_t *stat);
/* internal function */
static int dev_probe(NDR_driver *pdev, int instance);
static int dev_init_buf(NDR_driver *pdev);
static int dev_init_hw(NDR_driver *pdev, ether_addr_t *addr);
static int dev_init_hw(NDR_driver *pdev, netdriver_addr_t *addr);
static int dev_reset_hw(NDR_driver *pdev);
static void dev_conf_addr(NDR_driver *pdev, ether_addr_t *addr);
static void dev_conf_addr(NDR_driver *pdev, netdriver_addr_t *addr);
static void dev_handler(NDR_driver *pdev);
static void dev_check_ints(NDR_driver *pdev);
@ -338,11 +339,11 @@ static void dev_set_rec_mode(u32_t *base, int mode) {
u32_t data, base0 = base[0];
data = ndr_in8(base0, REG_RCR);
data &= ~(CMD_RCR_UNICAST | CMD_RCR_MULTICAST | CMD_RCR_BROADCAST);
if (mode & NDEV_PROMISC)
if (mode & NDEV_MODE_PROMISC)
data |= CMD_RCR_UNICAST | CMD_RCR_MULTICAST | CMD_RCR_MULTICAST;
if (mode & NDEV_BROAD)
if (mode & NDEV_MODE_BCAST)
data |= CMD_RCR_BROADCAST;
if (mode & NDEV_MULTI)
if (mode & (NDEV_MODE_MCAST_LIST | NDEV_MODE_MCAST_ALL))
data |= CMD_RCR_MULTICAST;
data |= CMD_RCR_UNICAST;
ndr_out8(base0, REG_RCR, data);
@ -455,13 +456,13 @@ static void dev_set_tx_desc_done(u32_t *base, NDR_desc *desc, int index) {
/* Driver interface table */
static const struct netdriver NDR_table = {
.ndr_name = "stge",
.ndr_init = NDR_init,
.ndr_stop = NDR_stop,
.ndr_mode = NDR_mode,
.ndr_set_mode = NDR_set_mode,
.ndr_recv = NDR_recv,
.ndr_send = NDR_send,
.ndr_intr = NDR_intr,
.ndr_stat = NDR_stat
};
int main(int argc, char *argv[]) {
@ -470,15 +471,15 @@ int main(int argc, char *argv[]) {
}
/* Initialize the driver */
static int NDR_init(unsigned int instance, ether_addr_t *addr) {
static int
NDR_init(unsigned int instance, netdriver_addr_t * addr, uint32_t * caps,
unsigned int * ticks __unused)
{
int i, ret = 0;
/* Intialize driver data structure */
memset(&g_driver, 0, sizeof(g_driver));
g_driver.link = LINK_UNKNOWN;
strcpy(g_driver.name, DRIVER_NAME);
strcat(g_driver.name, "#0");
g_driver.name[strlen(g_driver.name) - 1] += instance;
g_instance = instance;
/* Probe the device */
@ -510,14 +511,12 @@ static int NDR_init(unsigned int instance, ether_addr_t *addr) {
/* ### RX_TX_ENABLE_DISABLE ### */
dev_rx_tx_control(g_driver.base, RX_TX_ENABLE);
/* Use a synchronous alarm instead of a watchdog timer */
sys_setalarm(sys_hz(), 0);
/* Clear send and recv flag */
g_driver.send_flag = FALSE;
g_driver.recv_flag = FALSE;
return 0;
*caps = NDEV_CAP_MCAST | NDEV_CAP_BCAST;
return OK;
err_init_buf:
err_init_hw:
@ -540,7 +539,10 @@ static void NDR_stop(void) {
}
/* Set driver mode */
static void NDR_mode(unsigned int mode) {
static void
NDR_set_mode(unsigned int mode, const netdriver_addr_t * mcast_list __unused,
unsigned int mcast_count __unused)
{
g_driver.mode = mode;
/* Set driver receive mode */
/* ### SET_REC_MODE ### */
@ -570,7 +572,7 @@ static ssize_t NDR_recv(struct netdriver_data *data, size_t max) {
/* Get data length */
/* ### Get , int inde, int indexxRx data length ### */
if (totlen < 8 || totlen > 2 * ETH_MAX_PACK_SIZE) {
if (totlen < 8 || totlen > 2 * NDEV_ETH_PACKET_MAX) {
printf("NDR: Bad data length: %d\n", totlen);
panic(NULL);
}
@ -581,7 +583,6 @@ static ssize_t NDR_recv(struct netdriver_data *data, size_t max) {
/* Copy data to user */
netdriver_copyout(data, 0, pdev->rx[index].buf + offset, packlen);
pdev->stat.ets_packetR++;
/* Set Rx descriptor after Rx done */
/* ### SET_RX_DESC_DONE ### */
@ -649,11 +650,6 @@ static void NDR_intr(unsigned int mask) {
dev_check_ints(&g_driver);
}
/* Get driver status */
static void NDR_stat(eth_stat_t *stat) {
memcpy(stat, &g_driver.stat, sizeof(*stat));
}
/* Match the device and get base address */
static int dev_probe(NDR_driver *pdev, int instance) {
int devind, ioflag, i;
@ -717,7 +713,7 @@ static int dev_probe(NDR_driver *pdev, int instance) {
}
/* Intialize hardware */
static int dev_init_hw(NDR_driver *pdev, ether_addr_t *addr) {
static int dev_init_hw(NDR_driver *pdev, netdriver_addr_t *addr) {
int r, ret;
/* Set the OS interrupt handler */
@ -800,22 +796,22 @@ err_real_reset:
}
/* Configure MAC address */
static void dev_conf_addr(NDR_driver *pdev, ether_addr_t *addr) {
static void dev_conf_addr(NDR_driver *pdev, netdriver_addr_t *addr) {
u8_t pa[6];
/* Get MAC address */
/* ### GET_MAC_ADDR ### */
dev_get_addr(pdev->base, pa);
addr->ea_addr[0] = pa[0];
addr->ea_addr[1] = pa[1];
addr->ea_addr[2] = pa[2];
addr->ea_addr[3] = pa[3];
addr->ea_addr[4] = pa[4];
addr->ea_addr[5] = pa[5];
addr->na_addr[0] = pa[0];
addr->na_addr[1] = pa[1];
addr->na_addr[2] = pa[2];
addr->na_addr[3] = pa[3];
addr->na_addr[4] = pa[4];
addr->na_addr[5] = pa[5];
#ifdef MY_DEBUG
printf("NDR: Ethernet address is %02x:%02x:%02x:%02x:%02x:%02x\n",
addr->ea_addr[0], addr->ea_addr[1], addr->ea_addr[2],
addr->ea_addr[3], addr->ea_addr[4], addr->ea_addr[5]);
addr->na_addr[0], addr->na_addr[1], addr->na_addr[2],
addr->na_addr[3], addr->na_addr[4], addr->na_addr[5]);
#endif
}
@ -950,7 +946,6 @@ static void dev_handler(NDR_driver *pdev) {
else if (ret == TX_ERROR)
printf("NDR: Tx error now\n");
pdev->stat.ets_packetT++;
pdev->tx[tx_tail].busy = FALSE;
pdev->tx_busy_num--;

View File

@ -185,8 +185,6 @@ typedef struct NDR_driver {
phys_bytes tx_desc_dma; /* Tx descriptor DMA buffer */
int hook; /* IRQ hook id at kernel */
eth_stat_t stat; /* Ethernet status */
char name[50]; /* Driver name */
} NDR_driver;
#endif

View File

@ -9,4 +9,6 @@ FILESDIR= /etc/system.conf.d
DPADD+= ${LIBNETDRIVER} ${LIBSYS}
LDADD+= -lnetdriver -lsys
WARNS?= 5
.include <minix.service.mk>

View File

@ -7,21 +7,22 @@
#include "lan8710a_reg.h"
/* Local functions */
static int lan8710a_init(unsigned int instance, ether_addr_t *addr);
static int lan8710a_init(unsigned int instance, netdriver_addr_t *addr,
uint32_t *caps, unsigned int *ticks);
static void lan8710a_stop(void);
static ssize_t lan8710a_recv(struct netdriver_data *data, size_t max);
static int lan8710a_send(struct netdriver_data *data, size_t size);
static void lan8710a_stat(eth_stat_t *stat);
static void lan8710a_intr(unsigned int mask);
static void lan8710a_tick(void);
static void lan8710a_enable_interrupt(int interrupt);
static void lan8710a_map_regs(void);
static void lan8710a_dma_config_tx(u8_t desc_idx);
static void lan8710a_dma_reset_init(void);
static void lan8710a_init_addr(ether_addr_t *addr);
static void lan8710a_init_addr(netdriver_addr_t *addr, unsigned int instance);
static void lan8710a_init_desc(void);
static void lan8710a_init_mdio(void);
static int lan8710a_init_hw(ether_addr_t *addr);
static int lan8710a_init_hw(netdriver_addr_t *addr, unsigned int instance);
static void lan8710a_reset_hw(void);
static void lan8710a_phy_write(u32_t reg, u32_t value);
@ -36,12 +37,13 @@ static void lan8710a_reg_unset(volatile u32_t *reg, u32_t value);
static lan8710a_t lan8710a_state;
static const struct netdriver lan8710a_table = {
.ndr_name = "cpsw",
.ndr_init = lan8710a_init,
.ndr_stop = lan8710a_stop,
.ndr_recv = lan8710a_recv,
.ndr_send = lan8710a_send,
.ndr_stat = lan8710a_stat,
.ndr_intr = lan8710a_intr
.ndr_intr = lan8710a_intr,
.ndr_tick = lan8710a_tick
};
/*============================================================================*
@ -65,22 +67,21 @@ main(int argc, char *argv[])
* lan8710a_init *
*============================================================================*/
static int
lan8710a_init(unsigned int instance, ether_addr_t * addr)
lan8710a_init(unsigned int instance, netdriver_addr_t * addr, uint32_t * caps,
unsigned int * ticks)
{
/* Initialize the ethernet driver. */
/* Clear state. */
memset(&lan8710a_state, 0, sizeof(lan8710a_state));
strlcpy(lan8710a_state.name, "lan8710a#0", LAN8710A_NAME_LEN);
lan8710a_state.name[9] += instance;
lan8710a_state.instance = instance;
/* Initialize driver. */
lan8710a_map_regs();
lan8710a_init_hw(addr);
lan8710a_init_hw(addr, instance);
*caps = NDEV_CAP_MCAST | NDEV_CAP_BCAST;
*ticks = sys_hz(); /* update statistics once a second */
return OK;
}
@ -158,7 +159,7 @@ lan8710a_intr(unsigned int mask)
* lan8710a_init_addr *
*============================================================================*/
static void
lan8710a_init_addr(ether_addr_t * addr)
lan8710a_init_addr(netdriver_addr_t * addr, unsigned int instance)
{
static char eakey[]= LAN8710A_ENVVAR "#_EA";
static char eafmt[]= "x:x:x:x:x:x";
@ -168,13 +169,13 @@ lan8710a_init_addr(ether_addr_t * addr)
/*
* Do we have a user defined ethernet address?
*/
eakey[sizeof(LAN8710A_ENVVAR)-1] = '0' + lan8710a_state.instance;
eakey[sizeof(LAN8710A_ENVVAR)-1] = '0' + instance;
for (i= 0; i < 6; i++) {
if (env_parse(eakey, eafmt, i, &v, 0x00L, 0xFFL) != EP_SET)
break;
else
addr->ea_addr[i] = v;
addr->na_addr[i] = v;
}
if (i == 6)
return;
@ -182,12 +183,12 @@ lan8710a_init_addr(ether_addr_t * addr)
/*
* No; get the address from the chip itself.
*/
addr->ea_addr[0] = lan8710a_reg_read(CTRL_MAC_ID0_HI) & 0xFF;
addr->ea_addr[1] = (lan8710a_reg_read(CTRL_MAC_ID0_HI) >> 8) & 0xFF;
addr->ea_addr[2] = (lan8710a_reg_read(CTRL_MAC_ID0_HI) >> 16) & 0xFF;
addr->ea_addr[3] = (lan8710a_reg_read(CTRL_MAC_ID0_HI) >> 24) & 0xFF;
addr->ea_addr[4] = lan8710a_reg_read(CTRL_MAC_ID0_LO) & 0xFF;
addr->ea_addr[5] = (lan8710a_reg_read(CTRL_MAC_ID0_LO) >> 8) & 0xFF;
addr->na_addr[0] = lan8710a_reg_read(CTRL_MAC_ID0_HI) & 0xFF;
addr->na_addr[1] = (lan8710a_reg_read(CTRL_MAC_ID0_HI) >> 8) & 0xFF;
addr->na_addr[2] = (lan8710a_reg_read(CTRL_MAC_ID0_HI) >> 16) & 0xFF;
addr->na_addr[3] = (lan8710a_reg_read(CTRL_MAC_ID0_HI) >> 24) & 0xFF;
addr->na_addr[4] = lan8710a_reg_read(CTRL_MAC_ID0_LO) & 0xFF;
addr->na_addr[5] = (lan8710a_reg_read(CTRL_MAC_ID0_LO) >> 8) & 0xFF;
}
/*============================================================================*
@ -287,28 +288,44 @@ lan8710a_map_regs(void)
}
/*============================================================================*
* lan8710a_stat *
* lan8710a_update_stats *
*============================================================================*/
static void
lan8710a_stat(eth_stat_t * stat)
lan8710a_update_stats(void)
{
stat->ets_recvErr = lan8710a_reg_read(CPSW_STAT_RX_CRC_ERR)
+ lan8710a_reg_read(CPSW_STAT_RX_AGNCD_ERR)
+ lan8710a_reg_read(CPSW_STAT_RX_OVERSIZE);
stat->ets_sendErr = 0;
stat->ets_OVW = 0;
stat->ets_CRCerr = lan8710a_reg_read(CPSW_STAT_RX_CRC_ERR);
stat->ets_frameAll = lan8710a_reg_read(CPSW_STAT_RX_AGNCD_ERR);
stat->ets_missedP = 0;
stat->ets_packetR = lan8710a_reg_read(CPSW_STAT_RX_GOOD);
stat->ets_packetT = lan8710a_reg_read(CPSW_STAT_TX_GOOD);
stat->ets_collision = lan8710a_reg_read(CPSW_STAT_COLLISIONS);
stat->ets_transAb = 0;
stat->ets_carrSense = lan8710a_reg_read(CPSW_STAT_CARR_SENS_ERR);
stat->ets_fifoUnder = lan8710a_reg_read(CPSW_STAT_TX_UNDERRUN);
stat->ets_fifoOver = lan8710a_reg_read(CPSW_STAT_RX_OVERRUN);
stat->ets_CDheartbeat = 0;
stat->ets_OWC = 0;
uint32_t val;
/*
* AM335x Technical Reference (SPRUH73J) Sec. 14.3.2.20: statistics
* registers are decrement-on-write when any of the statistics port
* enable bits are set.
*/
val = lan8710a_reg_read(CPSW_STAT_RX_CRC_ERR);
lan8710a_reg_write(CPSW_STAT_RX_CRC_ERR, val);
netdriver_stat_ierror(val);
val = lan8710a_reg_read(CPSW_STAT_RX_AGNCD_ERR);
lan8710a_reg_write(CPSW_STAT_RX_AGNCD_ERR, val);
netdriver_stat_ierror(val);
val = lan8710a_reg_read(CPSW_STAT_RX_OVERSIZE);
lan8710a_reg_write(CPSW_STAT_RX_OVERSIZE, val);
netdriver_stat_ierror(val);
val = lan8710a_reg_read(CPSW_STAT_COLLISIONS);
lan8710a_reg_write(CPSW_STAT_COLLISIONS, val);
netdriver_stat_coll(val);
}
/*============================================================================*
* lan8710a_tick *
*============================================================================*/
static void
lan8710a_tick(void)
{
/* Update statistics. */
lan8710a_update_stats();
}
/*============================================================================*
@ -399,7 +416,6 @@ lan8710a_init_desc(void)
lan8710a_desc_t *p_rx_desc;
lan8710a_desc_t *p_tx_desc;
phys_bytes buf_phys_addr;
u8_t *p_buf;
u8_t i;
/* Attempt to allocate. */
@ -408,7 +424,6 @@ lan8710a_init_desc(void)
&buf_phys_addr)) == NULL) {
panic("failed to allocate RX buffers.");
}
p_buf = lan8710a_state.p_rx_buf;
for (i = 0; i < LAN8710A_NUM_RX_DESC; i++) {
p_rx_desc = &(lan8710a_state.rx_desc[i]);
memset(p_rx_desc, 0x0, sizeof(lan8710a_desc_t));
@ -430,7 +445,6 @@ lan8710a_init_desc(void)
&buf_phys_addr)) == NULL) {
panic("failed to allocate TX buffers");
}
p_buf = lan8710a_state.p_tx_buf;
for (i = 0; i < LAN8710A_NUM_TX_DESC; i++) {
p_tx_desc = &(lan8710a_state.tx_desc[i]);
memset(p_tx_desc, 0x0, sizeof(lan8710a_desc_t));
@ -445,7 +459,7 @@ lan8710a_init_desc(void)
* lan8710a_init_hw *
*============================================================================*/
static int
lan8710a_init_hw(ether_addr_t * addr)
lan8710a_init_hw(netdriver_addr_t * addr, unsigned int instance)
{
int r, i;
@ -615,7 +629,7 @@ lan8710a_init_hw(ether_addr_t * addr)
lan8710a_init_mdio();
/* Getting MAC Address */
lan8710a_init_addr(addr);
lan8710a_init_addr(addr, instance);
/* Initialize descriptors */
lan8710a_init_desc();
@ -703,7 +717,8 @@ lan8710a_send(struct netdriver_data * data, size_t size)
/* Drop packets that exceed the size of our transmission buffer. */
if (size > LAN8710A_IOBUF_SIZE) {
printf("%s: dropping large packet (%zu)\n", e->name, size);
printf("%s: dropping large packet (%zu)\n",
netdriver_name(), size);
return OK;
}

View File

@ -1,8 +1,6 @@
#ifndef LAN8710A_H_
#define LAN8710A_H_
#include <net/gen/ether.h>
#define LAN8710A_DEBUG (1)
#if LAN8710A_DEBUG == 1
@ -68,10 +66,8 @@ typedef struct lan8710a_t
lan8710a_desc_t *tx_desc;
phys_bytes rx_desc_phy;
phys_bytes tx_desc_phy;
char name[LAN8710A_NAME_LEN];
int irq_rx_hook; /* Rx interrupt Request Vector Hook. */
int irq_tx_hook; /* Tx interrupt Request Vector Hook. */
int instance;
u8_t *regs;
u32_t phy_address;
u8_t *p_rx_buf; /* pointer to the buffer with receive frames */

View File

@ -9,4 +9,6 @@ FILESDIR= /etc/system.conf.d
DPADD+= ${LIBNETDRIVER} ${LIBSYS}
LDADD+= -lnetdriver -lsys
WARNS?= 5
.include <minix.service.mk>

View File

@ -14,9 +14,6 @@
#include <minix/drivers.h>
#include <minix/netdriver.h>
#include <net/hton.h>
#include <net/gen/ether.h>
#include <net/gen/eth_io.h>
#include <assert.h>
#include <minix/syslib.h>
@ -26,21 +23,23 @@
#include "lance.h"
static int do_init(unsigned int instance, ether_addr_t *addr);
static void ec_confaddr(ether_addr_t *addr);
static int do_init(unsigned int instance, netdriver_addr_t *addr,
uint32_t *caps, unsigned int *ticks);
static void ec_confaddr(netdriver_addr_t *addr, unsigned int instance);
static void ec_reinit(ether_card_t *ec);
static void ec_reset(ether_card_t *ec);
static void do_intr(unsigned int mask);
static void do_mode(unsigned int mode);
static void do_set_mode(unsigned int mode, const netdriver_addr_t *mcast_list,
unsigned int mcast_count);
static int do_send(struct netdriver_data *data, size_t size);
static ssize_t do_recv(struct netdriver_data *data, size_t max);
static void do_stat(eth_stat_t *stat);
static void do_stop(void);
static void lance_dump(void);
static void do_other(const message *m_ptr, int ipc_status);
static void get_addressing(int devind, ether_card_t *ec);
static int lance_probe(ether_card_t *ec, unsigned int skip);
static void lance_init_hw(ether_card_t *ec, ether_addr_t *addr);
static void lance_init_hw(ether_card_t *ec, netdriver_addr_t *addr,
unsigned int instance);
/* Accesses Lance Control and Status Registers */
static u8_t in_byte(port_t port);
@ -50,7 +49,6 @@ static u16_t read_csr(port_t ioaddr, u16_t csrno);
static void write_csr(port_t ioaddr, u16_t csrno, u16_t value);
static ether_card_t ec_state;
static int ec_instance;
/* --- LANCE --- */
/* General */
@ -159,14 +157,14 @@ static phys_bytes tx_ring_base[TX_RING_SIZE]; /* Tx-slot physical address */
static char isstored[TX_RING_SIZE]; /* Tx-slot in-use */
static const struct netdriver lance_table = {
.ndr_init = do_init,
.ndr_stop = do_stop,
.ndr_mode = do_mode,
.ndr_recv = do_recv,
.ndr_send = do_send,
.ndr_stat = do_stat,
.ndr_intr = do_intr,
.ndr_other = do_other,
.ndr_name = "le",
.ndr_init = do_init,
.ndr_stop = do_stop,
.ndr_set_mode = do_set_mode,
.ndr_recv = do_recv,
.ndr_send = do_send,
.ndr_intr = do_intr,
.ndr_other = do_other,
};
/*===========================================================================*
@ -194,34 +192,11 @@ static void lance_dump()
printf("\n");
ec = &ec_state;
printf("lance statistics of instance %d:\n", ec_instance);
printf("recvErr :%8ld\t", ec->eth_stat.ets_recvErr);
printf("sendErr :%8ld\t", ec->eth_stat.ets_sendErr);
printf("OVW :%8ld\n", ec->eth_stat.ets_OVW);
printf("CRCerr :%8ld\t", ec->eth_stat.ets_CRCerr);
printf("frameAll :%8ld\t", ec->eth_stat.ets_frameAll);
printf("missedP :%8ld\n", ec->eth_stat.ets_missedP);
printf("packetR :%8ld\t", ec->eth_stat.ets_packetR);
printf("packetT :%8ld\t", ec->eth_stat.ets_packetT);
printf("transDef :%8ld\n", ec->eth_stat.ets_transDef);
printf("collision :%8ld\t", ec->eth_stat.ets_collision);
printf("transAb :%8ld\t", ec->eth_stat.ets_transAb);
printf("carrSense :%8ld\n", ec->eth_stat.ets_carrSense);
printf("fifoUnder :%8ld\t", ec->eth_stat.ets_fifoUnder);
printf("fifoOver :%8ld\t", ec->eth_stat.ets_fifoOver);
printf("CDheartbeat:%8ld\n", ec->eth_stat.ets_CDheartbeat);
printf("OWC :%8ld\t", ec->eth_stat.ets_OWC);
printf("lance driver %s:\n", netdriver_name());
ioaddr = ec->ec_port;
isr = read_csr(ioaddr, LANCE_CSR0);
printf("isr = 0x%x, flags = 0x%x\n", isr,
ec->flags);
printf("isr = 0x%x, mode = 0x%x\n", isr, ec->ec_mode);
printf("irq = %d\tioadr = 0x%x\n", ec->ec_irq, ec->ec_port);
@ -250,7 +225,7 @@ static void do_other(const message *m_ptr, int ipc_status)
/*===========================================================================*
* ec_confaddr *
*===========================================================================*/
static void ec_confaddr(ether_addr_t *addr)
static void ec_confaddr(netdriver_addr_t *addr, unsigned int instance)
{
int i;
char eakey[16];
@ -259,14 +234,14 @@ static void ec_confaddr(ether_addr_t *addr)
/* User defined ethernet address? */
strlcpy(eakey, "LANCE0_EA", sizeof(eakey));
eakey[5] += ec_instance;
eakey[5] += instance;
for (i = 0; i < 6; i++)
{
v= addr->ea_addr[i];
v= addr->na_addr[i];
if (env_parse(eakey, eafmt, i, &v, 0x00L, 0xFFL) != EP_SET)
break;
addr->ea_addr[i]= v;
addr->na_addr[i]= v;
}
if (i != 0 && i != 6)
@ -279,15 +254,16 @@ static void ec_confaddr(ether_addr_t *addr)
/*===========================================================================*
* do_init *
*===========================================================================*/
static int do_init(unsigned int instance, ether_addr_t *addr)
static int do_init(unsigned int instance, netdriver_addr_t *addr,
uint32_t *caps, unsigned int *ticks __unused)
{
/* Initialize the lance driver. */
ether_card_t *ec;
#if VERBOSE
int i, r;
int i;
#endif
#if LANCE_FKEY
int fkeys, sfkeys;
int r, fkeys, sfkeys;
#endif
#if LANCE_FKEY
@ -297,27 +273,24 @@ static int do_init(unsigned int instance, ether_addr_t *addr)
printf("Warning: lance couldn't observe Shift+F7 key: %d\n",r);
#endif
ec_instance = instance;
/* Initialize the driver state. */
ec= &ec_state;
memset(ec, 0, sizeof(*ec));
strlcpy(ec->port_name, "lance#0", sizeof(ec->port_name));
ec->port_name[6] += instance;
/* See if there is a matching card. */
if (!lance_probe(ec, instance))
return ENXIO;
/* Initialize the hardware. */
lance_init_hw(ec, addr);
lance_init_hw(ec, addr, instance);
#if VERBOSE
printf("%s: Ethernet address ", ec->port_name);
printf("%s: Ethernet address ", netdriver_name());
for (i= 0; i < 6; i++)
printf("%x%c", addr->ea_addr[i], i < 5 ? ':' : '\n');
printf("%x%c", addr->na_addr[i], i < 5 ? ':' : '\n');
#endif
*caps = NDEV_CAP_MCAST | NDEV_CAP_BCAST;
return OK;
}
@ -349,13 +322,14 @@ static void ec_reinit(ether_card_t *ec)
}
/* Set 'Receive Mode' */
if (ec->flags & ECF_PROMISC)
if (ec->ec_mode & NDEV_MODE_PROMISC)
{
write_csr(ioaddr, LANCE_CSR15, LANCE_CSR15_PROM);
}
else
{
if (ec->flags & (ECF_BROAD | ECF_MULTI))
if (ec->ec_mode &
(NDEV_MODE_BCAST | NDEV_MODE_MCAST_LIST | NDEV_MODE_MCAST_ALL))
{
write_csr(ioaddr, LANCE_CSR15, 0x0000);
}
@ -373,22 +347,17 @@ static void ec_reinit(ether_card_t *ec)
}
/*===========================================================================*
* do_mode *
* do_set_mode *
*===========================================================================*/
static void do_mode(unsigned int mode)
static void do_set_mode(unsigned int mode,
const netdriver_addr_t *mcast_list __unused,
unsigned int mcast_count __unused)
{
ether_card_t *ec;
ec = &ec_state;
ec->flags &= ~(ECF_PROMISC | ECF_MULTI | ECF_BROAD);
if (mode & NDEV_PROMISC)
ec->flags |= ECF_PROMISC | ECF_MULTI | ECF_BROAD;
if (mode & NDEV_MULTI)
ec->flags |= ECF_MULTI;
if (mode & NDEV_BROAD)
ec->flags |= ECF_BROAD;
ec->ec_mode = mode;
ec_reinit(ec);
}
@ -436,7 +405,7 @@ static void do_intr(unsigned int __unused mask)
#if VERBOSE
printf("RX Missed Frame\n");
#endif
ec->eth_stat.ets_recvErr++;
netdriver_stat_ierror(1);
}
if ((isr & LANCE_CSR0_BABL) || (isr & LANCE_CSR0_TINT))
{
@ -445,7 +414,7 @@ static void do_intr(unsigned int __unused mask)
#if VERBOSE
printf("TX Timeout\n");
#endif
ec->eth_stat.ets_sendErr++;
netdriver_stat_oerror(1);
}
if (isr & LANCE_CSR0_TINT)
{
@ -459,24 +428,16 @@ static void do_intr(unsigned int __unused mask)
if (status & 0x40000000)
{
status = lp->tx_ring[cur_tx_slot_nr].misc;
ec->eth_stat.ets_sendErr++;
if (status & 0x0400) /* RTRY */
ec->eth_stat.ets_transAb++;
if (status & 0x0800) /* LCAR */
ec->eth_stat.ets_carrSense++;
if (status & 0x1000) /* LCOL */
ec->eth_stat.ets_OWC++;
netdriver_stat_oerror(1);
if (status & 0x4000) /* UFLO */
{
ec->eth_stat.ets_fifoUnder++;
must_restart=1;
}
}
else
{
if (status & 0x18000000)
ec->eth_stat.ets_collision++;
ec->eth_stat.ets_packetT++;
netdriver_stat_coll(1);
}
}
/* transmit a packet on the next slot if it exists. */
@ -597,20 +558,11 @@ static ssize_t do_recv(struct netdriver_data *data, size_t max)
if (status != 0x03)
{
if (status & 0x01)
ec->eth_stat.ets_recvErr++;
if (status & 0x04)
ec->eth_stat.ets_fifoOver++;
if (status & 0x08)
ec->eth_stat.ets_CRCerr++;
if (status & 0x10)
ec->eth_stat.ets_OVW++;
if (status & 0x20)
ec->eth_stat.ets_frameAll++;
netdriver_stat_ierror(1);
length = 0;
}
else
{
ec->eth_stat.ets_packetR++;
length = lp->rx_ring[rx_slot_nr].msg_length;
}
@ -677,15 +629,6 @@ static int do_send(struct netdriver_data *data, size_t size)
return OK;
}
/*===========================================================================*
* do_stat *
*===========================================================================*/
static void do_stat(eth_stat_t *stat)
{
memcpy(stat, &ec_state.eth_stat, sizeof(*stat));
}
/*===========================================================================*
* do_stop *
*===========================================================================*/
@ -799,7 +742,7 @@ static int lance_probe(ether_card_t *ec, unsigned int skip)
#if VERBOSE
printf("%s: %s at %X:%d\n",
ec->port_name, chip_table[lance_version].name,
netdriver_name(), chip_table[lance_version].name,
ec->ec_port, ec->ec_irq);
#endif
@ -823,7 +766,8 @@ static phys_bytes virt_to_bus(void *ptr)
/*===========================================================================*
* lance_init_hw *
*===========================================================================*/
static void lance_init_hw(ether_card_t *ec, ether_addr_t *addr)
static void lance_init_hw(ether_card_t *ec, netdriver_addr_t *addr,
unsigned int instance)
{
phys_bytes lance_buf_phys;
int i, r;
@ -859,10 +803,10 @@ static void lance_init_hw(ether_card_t *ec, ether_addr_t *addr)
/* ============= Get MAC address (cf. lance_probe1) ================ */
for (i = 0; i < 6; ++i)
addr->ea_addr[i]=in_byte(ioaddr+LANCE_ETH_ADDR+i);
addr->na_addr[i]=in_byte(ioaddr+LANCE_ETH_ADDR+i);
/* Allow the user to override the hardware address. */
ec_confaddr(addr);
ec_confaddr(addr, instance);
/* ============ (re)start init_block(cf. lance_reset) =============== */
/* Reset the LANCE */
@ -871,7 +815,7 @@ static void lance_init_hw(ether_card_t *ec, ether_addr_t *addr)
/* ----- Re-initialize the LANCE ----- */
/* Set station address */
for (i = 0; i < 6; ++i)
lp->init_block.phys_addr[i] = addr->ea_addr[i];
lp->init_block.phys_addr[i] = addr->na_addr[i];
/* Preset the receive ring headers */
for (i=0; i<RX_RING_SIZE; i++)
{
@ -915,13 +859,14 @@ static void lance_init_hw(ether_card_t *ec, ether_addr_t *addr)
}
/* Set 'Receive Mode' */
if (ec->flags & ECF_PROMISC)
if (ec->ec_mode & NDEV_MODE_PROMISC)
{
write_csr(ioaddr, LANCE_CSR15, LANCE_CSR15_PROM);
}
else
{
if (ec->flags & (ECF_BROAD | ECF_MULTI))
if (ec->ec_mode &
(NDEV_MODE_BCAST | NDEV_MODE_MCAST_LIST | NDEV_MODE_MCAST_ALL))
{
write_csr(ioaddr, LANCE_CSR15, 0x0000);
}

View File

@ -1,18 +1,8 @@
/* macros for 'flags' */
#define ECF_PROMISC 0x01
#define ECF_MULTI 0x02
#define ECF_BROAD 0x04
/* ====== ethernet card info. ====== */
typedef struct ether_card
{
/* ####### MINIX style ####### */
char port_name[sizeof("lance#n")];
int flags;
eth_stat_t eth_stat;
/* ######## device info. ####### */
unsigned int ec_mode;
port_t ec_port;
int ec_irq;
int ec_hook;

View File

@ -11,4 +11,6 @@ LDADD+= -lnetdriver -lsys
CPPFLAGS+= -I${NETBSDSRCDIR}/minix
WARNS?= 5
.include <minix.service.mk>

View File

@ -18,8 +18,6 @@
static re_t re_state;
static int re_instance;
static unsigned my_inb(u16_t port) {
u32_t value;
int s;
@ -64,46 +62,53 @@ static void my_outl(u16_t port, u32_t value) {
#define rl_outw(port, offset, value) (my_outw((port) + (offset), (value)))
#define rl_outl(port, offset, value) (my_outl((port) + (offset), (value)))
static int rl_init(unsigned int instance, ether_addr_t *addr);
static int rl_init(unsigned int instance, netdriver_addr_t *addr,
uint32_t *caps, unsigned int *ticks);
static int rl_probe(re_t *rep, unsigned int skip);
static void rl_init_buf(re_t *rep);
static void rl_init_hw(re_t *rep, ether_addr_t *addr);
static void rl_init_hw(re_t *rep, netdriver_addr_t *addr,
unsigned int instance);
static void rl_reset_hw(re_t *rep);
static void rl_confaddr(re_t *rep, ether_addr_t *addr);
static void rl_set_hwaddr(const netdriver_addr_t *addr);
static void rl_confaddr(re_t *rep, netdriver_addr_t *addr,
unsigned int instance);
static void rl_stop(void);
static void rl_rec_mode(re_t *rep);
static void rl_mode(unsigned int mode);
static void rl_set_mode(unsigned int mode, const netdriver_addr_t *mcast_list,
unsigned int mcast_count);
static ssize_t rl_recv(struct netdriver_data *data, size_t max);
static int rl_send(struct netdriver_data *data, size_t size);
static unsigned int rl_get_link(uint32_t *media);
static void rl_intr(unsigned int mask);
static void rl_check_ints(re_t *rep);
static void rl_report_link(re_t *rep);
#if VERBOSE
static void rl_report_link(re_t *rep);
static void mii_print_techab(u16_t techab);
static void mii_print_stat_speed(u16_t stat, u16_t extstat);
#endif
static void rl_clear_rx(re_t *rep);
static void rl_do_reset(re_t *rep);
static void rl_stat(eth_stat_t *stat);
static void rl_other(const message *m_ptr, int ipc_status);
static void rl_dump(void);
#if 0
static void dump_phy(re_t *rep);
#endif
static int rl_handler(re_t *rep);
static void rl_alarm(clock_t stamp);
static void rl_tick(void);
static void tell_iommu(vir_bytes start, size_t size, int pci_bus, int
pci_dev, int pci_func);
static const struct netdriver rl_table = {
.ndr_name = "rl",
.ndr_init = rl_init,
.ndr_stop = rl_stop,
.ndr_mode = rl_mode,
.ndr_set_mode = rl_set_mode,
.ndr_set_hwaddr = rl_set_hwaddr,
.ndr_recv = rl_recv,
.ndr_send = rl_send,
.ndr_stat = rl_stat,
.ndr_get_link = rl_get_link,
.ndr_intr = rl_intr,
.ndr_alarm = rl_alarm,
.ndr_tick = rl_tick,
.ndr_other = rl_other,
};
@ -172,29 +177,7 @@ static void rl_dump(void)
rep= &re_state;
printf("\n");
printf("Realtek RTL 8139 statistics of instance %d:\n", re_instance);
printf("recvErr :%8ld\t", rep->re_stat.ets_recvErr);
printf("sendErr :%8ld\t", rep->re_stat.ets_sendErr);
printf("OVW :%8ld\n", rep->re_stat.ets_OVW);
printf("CRCerr :%8ld\t", rep->re_stat.ets_CRCerr);
printf("frameAll :%8ld\t", rep->re_stat.ets_frameAll);
printf("missedP :%8ld\n", rep->re_stat.ets_missedP);
printf("packetR :%8ld\t", rep->re_stat.ets_packetR);
printf("packetT :%8ld\t", rep->re_stat.ets_packetT);
printf("transDef :%8ld\n", rep->re_stat.ets_transDef);
printf("collision :%8ld\t", rep->re_stat.ets_collision);
printf("transAb :%8ld\t", rep->re_stat.ets_transAb);
printf("carrSense :%8ld\n", rep->re_stat.ets_carrSense);
printf("fifoUnder :%8ld\t", rep->re_stat.ets_fifoUnder);
printf("fifoOver :%8ld\t", rep->re_stat.ets_fifoOver);
printf("CDheartbeat:%8ld\n", rep->re_stat.ets_CDheartbeat);
printf("OWC :%8ld\t", rep->re_stat.ets_OWC);
printf("Realtek RTL 8139 device %s:\n", netdriver_name());
printf("TSAD: 0x%04x, TSD: 0x%08x, 0x%08x, 0x%08x, 0x%08x\n",
rl_inw(rep->re_base_port, RL_TSAD),
@ -209,9 +192,10 @@ static void rl_dump(void)
}
/*===========================================================================*
* rl_mode *
* rl_set_mode *
*===========================================================================*/
static void rl_mode(unsigned int mode)
static void rl_set_mode(unsigned int mode, const netdriver_addr_t *mcast_list,
unsigned int mcast_count)
{
re_t *rep;
@ -225,7 +209,8 @@ static void rl_mode(unsigned int mode)
/*===========================================================================*
* rl_init *
*===========================================================================*/
static int rl_init(unsigned int instance, ether_addr_t *addr)
static int rl_init(unsigned int instance, netdriver_addr_t *addr,
uint32_t *caps, unsigned int *ticks)
{
/* Initialize the rtl8139 driver. */
re_t *rep;
@ -239,10 +224,6 @@ static int rl_init(unsigned int instance, ether_addr_t *addr)
rep->re_link_up= -1; /* Unknown */
rep->re_ertxth= RL_TSD_ERTXTH_8;
strlcpy(rep->re_name, "rtl8139#0", sizeof(rep->re_name));
rep->re_name[8] += instance;
re_instance = instance;
/* Try to find a matching device. */
if (!rl_probe(rep, instance))
@ -252,16 +233,13 @@ static int rl_init(unsigned int instance, ether_addr_t *addr)
rl_init_buf(rep);
/* Initialize the device we found. */
rl_init_hw(rep, addr);
rl_init_hw(rep, addr, instance);
#if VERBOSE
/* Report initial link status. */
rl_report_link(rep);
#endif
/* Use a synchronous alarm instead of a watchdog timer. */
sys_setalarm(sys_hz(), 0);
#if RTL8139_FKEY
/* Observe some function key for debug dumps. */
fkeys = sfkeys = 0; bit_set(sfkeys, 9);
@ -269,6 +247,8 @@ static int rl_init(unsigned int instance, ether_addr_t *addr)
printf("Warning: RTL8139 couldn't observe Shift+F9 key: %d\n",r);
#endif
*caps = NDEV_CAP_MCAST | NDEV_CAP_BCAST | NDEV_CAP_HWADDR;
*ticks = sys_hz();
return OK;
}
@ -282,7 +262,7 @@ static int rl_probe(re_t *rep, unsigned int skip)
u32_t bar;
u8_t ilr;
#if VERBOSE
char *dname;
const char *dname;
#endif
pci_init();
@ -302,7 +282,7 @@ static int rl_probe(re_t *rep, unsigned int skip)
dname= pci_dev_name(vid, did);
if (!dname)
dname= "unknown device";
printf("%s: ", rep->re_name);
printf("%s: ", netdriver_name());
printf("%s (%x/%x) at %s\n", dname, vid, did, pci_slot_name(devind));
#endif
pci_reserve(devind);
@ -323,7 +303,7 @@ static int rl_probe(re_t *rep, unsigned int skip)
rep->re_irq= ilr;
#if VERBOSE
printf("%s: using I/O address 0x%lx, IRQ %d\n",
rep->re_name, (unsigned long)bar, ilr);
netdriver_name(), (unsigned long)bar, ilr);
#endif
return TRUE;
@ -340,7 +320,7 @@ static void rl_init_buf(re_t *rep)
int i, off;
/* Allocate receive and transmit buffers */
tx_bufsize= ETH_MAX_PACK_SIZE_TAGGED;
tx_bufsize= NDEV_ETH_PACKET_MAX_TAGGED;
if (tx_bufsize % 4)
tx_bufsize += 4-(tx_bufsize % 4); /* Align */
rx_bufsize= RX_BUFSIZE;
@ -378,7 +358,8 @@ static void rl_init_buf(re_t *rep)
/*===========================================================================*
* rl_init_hw *
*===========================================================================*/
static void rl_init_hw(re_t *rep, ether_addr_t *addr)
static void rl_init_hw(re_t *rep, netdriver_addr_t *addr,
unsigned int instance)
{
#if VERBOSE
int i;
@ -400,22 +381,22 @@ static void rl_init_hw(re_t *rep, ether_addr_t *addr)
#if VERBOSE /* stay silent during startup, can always get status later */
if (rep->re_model) {
printf("%s: model %s\n", rep->re_name, rep->re_model);
printf("%s: model %s\n", netdriver_name(), rep->re_model);
} else
{
printf("%s: unknown model 0x%08x\n",
rep->re_name,
netdriver_name(),
rl_inl(rep->re_base_port, RL_TCR) &
(RL_TCR_HWVER_AM | RL_TCR_HWVER_BM));
}
#endif
rl_confaddr(rep, addr);
rl_confaddr(rep, addr, instance);
#if VERBOSE
printf("%s: Ethernet address ", rep->re_name);
printf("%s: Ethernet address ", netdriver_name());
for (i= 0; i < 6; i++)
printf("%x%c", addr->ea_addr[i], i < 5 ? ':' : '\n');
printf("%x%c", addr->na_addr[i], i < 5 ? ':' : '\n');
#endif
}
@ -527,52 +508,64 @@ static void rl_reset_hw(re_t *rep)
rl_outl(port, RL_TCR, t | RL_TCR_IFG_STD);
}
/*===========================================================================*
* rl_set_hwaddr *
*===========================================================================*/
static void rl_set_hwaddr(const netdriver_addr_t *addr)
{
re_t *rep;
port_t port;
u32_t w;
int i;
rep = &re_state;
port= rep->re_base_port;
rl_outb(port, RL_9346CR, RL_9346CR_EEM_CONFIG);
w= 0;
for (i= 0; i<4; i++)
w |= (addr->na_addr[i] << (i*8));
rl_outl(port, RL_IDR, w);
w= 0;
for (i= 4; i<6; i++)
w |= (addr->na_addr[i] << ((i-4)*8));
rl_outl(port, RL_IDR+4, w);
rl_outb(port, RL_9346CR, RL_9346CR_EEM_NORMAL);
}
/*===========================================================================*
* rl_confaddr *
*===========================================================================*/
static void rl_confaddr(re_t *rep, ether_addr_t *addr)
static void rl_confaddr(re_t *rep, netdriver_addr_t *addr,
unsigned int instance)
{
static char eakey[]= RL_ENVVAR "#_EA";
static char eafmt[]= "x:x:x:x:x:x";
int i;
port_t port;
u32_t w;
int i;
long v;
/* User defined ethernet address? */
eakey[sizeof(RL_ENVVAR)-1]= '0' + re_instance;
port= rep->re_base_port;
eakey[sizeof(RL_ENVVAR)-1]= '0' + instance;
for (i= 0; i < 6; i++)
{
if (env_parse(eakey, eafmt, i, &v, 0x00L, 0xFFL) != EP_SET)
break;
addr->ea_addr[i]= v;
addr->na_addr[i]= v;
}
if (i != 0 && i != 6) env_panic(eakey); /* It's all or nothing */
/* Should update ethernet address in hardware */
if (i == 6)
{
port= rep->re_base_port;
rl_outb(port, RL_9346CR, RL_9346CR_EEM_CONFIG);
w= 0;
for (i= 0; i<4; i++)
w |= (addr->ea_addr[i] << (i*8));
rl_outl(port, RL_IDR, w);
w= 0;
for (i= 4; i<6; i++)
w |= (addr->ea_addr[i] << ((i-4)*8));
rl_outl(port, RL_IDR+4, w);
rl_outb(port, RL_9346CR, RL_9346CR_EEM_NORMAL);
}
rl_set_hwaddr(addr);
/* Get ethernet address */
port= rep->re_base_port;
for (i= 0; i<6; i++)
addr->ea_addr[i]= rl_inb(port, RL_IDR+i);
addr->na_addr[i]= rl_inb(port, RL_IDR+i);
}
/*===========================================================================*
@ -586,11 +579,11 @@ static void rl_rec_mode(re_t *rep)
port= rep->re_base_port;
rcr= rl_inl(port, RL_RCR);
rcr &= ~(RL_RCR_AB|RL_RCR_AM|RL_RCR_APM|RL_RCR_AAP);
if (rep->re_mode & NDEV_PROMISC)
if (rep->re_mode & NDEV_MODE_PROMISC)
rcr |= RL_RCR_AB | RL_RCR_AM | RL_RCR_AAP;
if (rep->re_mode & NDEV_BROAD)
if (rep->re_mode & NDEV_MODE_BCAST)
rcr |= RL_RCR_AB;
if (rep->re_mode & NDEV_MULTI)
if (rep->re_mode & (NDEV_MODE_MCAST_LIST | NDEV_MODE_MCAST_ALL))
rcr |= RL_RCR_AM;
rcr |= RL_RCR_APM;
@ -651,7 +644,7 @@ static ssize_t rl_recv(struct netdriver_data *data, size_t max)
panic("received packet not OK");
}
totlen= (rxstat >> RL_RXS_LEN_S);
if (totlen < 8 || totlen > 2*ETH_MAX_PACK_SIZE)
if (totlen < 8 || totlen > 2*NDEV_ETH_PACKET_MAX)
{
/* Someting went wrong */
printf(
@ -675,18 +668,16 @@ static ssize_t rl_recv(struct netdriver_data *data, size_t max)
}
/* Should subtract the CRC */
packlen = MIN(totlen - ETH_CRC_SIZE, max);
packlen = MIN(totlen - NDEV_ETH_PACKET_CRC, max);
/* Copy out the data. The packet may wrap in the receive buffer. */
o = (d_start+4) % RX_BUFSIZE;
s = MIN(RX_BUFSIZE - o, packlen);
s = MIN(RX_BUFSIZE - o, (int)packlen);
netdriver_copyout(data, 0, rep->v_re_rx_buf + o, s);
if (s < packlen)
if (s < (int)packlen)
netdriver_copyout(data, s, rep->v_re_rx_buf, packlen - s);
rep->re_stat.ets_packetR++;
/* Avoid overflow in 16-bit computations */
l= d_start;
l += totlen+4;
@ -794,10 +785,46 @@ static void rl_check_ints(re_t *rep)
if (rep->re_report_link) {
rep->re_report_link = FALSE;
netdriver_link();
#if VERBOSE
rl_report_link(rep);
#endif
}
}
/*===========================================================================*
* rl_get_link *
*===========================================================================*/
static unsigned int rl_get_link(uint32_t *media)
{
port_t port;
u8_t msr;
u16_t mii_ctrl;
re_t *rep;
rep = &re_state;
port= rep->re_base_port;
msr= rl_inb(port, RL_MSR);
if (msr & RL_MSR_LINKB)
return NDEV_LINK_DOWN;
if (msr & RL_MSR_SPEED_10)
*media = IFM_ETHER | IFM_10_T;
else
*media = IFM_ETHER | IFM_100_TX;
mii_ctrl= rl_inw(port, RL_BMCR);
if (mii_ctrl & MII_CTRL_DM)
*media |= IFM_FDX;
else
*media |= IFM_HDX;
return NDEV_LINK_UP;
}
#if VERBOSE
/*===========================================================================*
* rl_report_link *
*===========================================================================*/
@ -814,7 +841,7 @@ static void rl_report_link(re_t *rep)
rep->re_link_up= link_up;
if (!link_up)
{
printf("%s: link down\n", rep->re_name);
printf("%s: link down\n", netdriver_name());
return;
}
@ -827,7 +854,7 @@ static void rl_report_link(re_t *rep)
if (mii_ctrl & (MII_CTRL_LB|MII_CTRL_PD|MII_CTRL_ISO))
{
printf("%s: PHY: ", rep->re_name);
printf("%s: PHY: ", netdriver_name());
f= 1;
if (mii_ctrl & MII_CTRL_LB)
{
@ -851,7 +878,7 @@ static void rl_report_link(re_t *rep)
}
if (!(mii_ctrl & MII_CTRL_ANE))
{
printf("%s: manual config: ", rep->re_name);
printf("%s: manual config: ", netdriver_name());
switch(mii_ctrl & (MII_CTRL_SP_LSB|MII_CTRL_SP_MSB))
{
case MII_CTRL_SP_10: printf("10 Mbps"); break;
@ -868,57 +895,58 @@ static void rl_report_link(re_t *rep)
}
#if VERBOSE
printf("%s: ", rep->re_name);
printf("%s: ", netdriver_name());
mii_print_stat_speed(mii_status, mii_extstat);
printf("\n");
if (!(mii_status & MII_STATUS_ANC))
printf("%s: auto-negotiation not complete\n", rep->re_name);
printf("%s: auto-negotiation not complete\n",
netdriver_name());
if (mii_status & MII_STATUS_RF)
printf("%s: remote fault detected\n", rep->re_name);
printf("%s: remote fault detected\n", netdriver_name());
if (!(mii_status & MII_STATUS_ANA))
{
printf("%s: local PHY has no auto-negotiation ability\n",
rep->re_name);
netdriver_name());
}
if (!(mii_status & MII_STATUS_LS))
printf("%s: link down\n", rep->re_name);
printf("%s: link down\n", netdriver_name());
if (mii_status & MII_STATUS_JD)
printf("%s: jabber condition detected\n", rep->re_name);
printf("%s: jabber condition detected\n",
netdriver_name());
if (!(mii_status & MII_STATUS_EC))
{
printf("%s: no extended register set\n", rep->re_name);
printf("%s: no extended register set\n", netdriver_name());
goto resspeed;
}
if (!(mii_status & MII_STATUS_ANC))
goto resspeed;
printf("%s: local cap.: ", rep->re_name);
printf("%s: local cap.: ", netdriver_name());
mii_print_techab(mii_ana);
printf("\n");
if (mii_ane & MII_ANE_PDF)
printf("%s: parallel detection fault\n", rep->re_name);
printf("%s: parallel detection fault\n", netdriver_name());
if (!(mii_ane & MII_ANE_LPANA))
{
printf("%s: link-partner does not support auto-negotiation\n",
rep->re_name);
netdriver_name());
goto resspeed;
}
printf("%s: remote cap.: ", rep->re_name);
printf("%s: remote cap.: ", netdriver_name());
mii_print_techab(mii_anlpa);
printf("\n");
resspeed:
#endif
printf("%s: ", rep->re_name);
printf("%s: ", netdriver_name());
printf("link up at %d Mbps, ", (msr & RL_MSR_SPEED_10) ? 10 : 100);
printf("%s duplex\n", ((mii_ctrl & MII_CTRL_DM) ? "full" : "half"));
}
#if VERBOSE
static void mii_print_techab(u16_t techab)
{
int fs, ft;
@ -1121,7 +1149,7 @@ static void rl_clear_rx(re_t *rep)
rl_rec_mode(rep);
rep->re_stat.ets_missedP++;
netdriver_stat_ierror(1);
}
/*===========================================================================*
@ -1140,14 +1168,6 @@ static void rl_do_reset(re_t *rep)
rep->re_send_int= TRUE;
}
/*===========================================================================*
* rl_stat *
*===========================================================================*/
static void rl_stat(eth_stat_t *stat)
{
memcpy(stat, &re_state.re_stat, sizeof(*stat));
}
#if 0
/*===========================================================================*
* dump_phy *
@ -1265,8 +1285,6 @@ static int rl_handler(re_t *rep)
{
isr &= ~RL_IMR_FOVW;
/* Should do anything? */
rep->re_stat.ets_fifoOver++;
}
if (isr & RL_IMR_PUN)
{
@ -1331,7 +1349,8 @@ static int rl_handler(re_t *rep)
/* Aborted transmission, just kick the device
* and be done with it.
*/
rep->re_stat.ets_transAb++;
netdriver_stat_oerror(1);
tcr= rl_inl(port, RL_TCR);
rl_outl(port, RL_TCR, tcr | RL_TCR_CLRABT);
}
@ -1341,6 +1360,8 @@ static int rl_handler(re_t *rep)
tx_tail= rep->re_tx_tail;
for (i= 0; i< 2*N_TX_BUF; i++)
{
if (rep->re_tx_busy == 0)
break;
if (!rep->re_tx[tx_tail].ret_busy)
{
/* Strange, this buffer is not in-use.
@ -1357,40 +1378,29 @@ static int rl_handler(re_t *rep)
continue;
}
tsd= rl_inl(port, RL_TSD0+tx_tail*4);
if (!(tsd & RL_TSD_OWN))
if (!(tsd & (RL_TSD_TABT | RL_TSD_TOK | RL_TSD_TUN)))
{
/* Buffer is not yet ready */
break;
}
/* Should collect statistics */
if (tsd & RL_TSD_CRS)
rep->re_stat.ets_carrSense++;
if (tsd & RL_TSD_TABT)
{
printf("rl_handler, TABT, TSD%d = 0x%04x\n",
tx_tail, tsd);
assert(0); /* CLRABT is not all that
* effective, why not?
*/
rep->re_stat.ets_transAb++;
panic("TX abort"); /* CLRABT is not all that
* that effective, why not?
*/
tcr= rl_inl(port, RL_TCR);
rl_outl(port, RL_TCR, tcr | RL_TCR_CLRABT);
}
if (tsd & RL_TSD_OWC)
rep->re_stat.ets_OWC++;
if (tsd & RL_TSD_CDH)
rep->re_stat.ets_CDheartbeat++;
/* What about collisions? */
if (tsd & RL_TSD_TOK)
rep->re_stat.ets_packetT++;
else
rep->re_stat.ets_sendErr++;
if (!(tsd & RL_TSD_TOK))
netdriver_stat_oerror(1);
if (tsd & RL_TSD_TUN)
{
rep->re_stat.ets_fifoUnder++;
/* Increase ERTXTH */
ertxth= tsd + (1 << RL_TSD_ERTXTH_S);
ertxth &= RL_TSD_ERTXTH_M;
@ -1398,7 +1408,7 @@ static int rl_handler(re_t *rep)
if (ertxth > rep->re_ertxth)
{
printf("%s: new ertxth: %d bytes\n",
rep->re_name,
netdriver_name(),
(ertxth >> RL_TSD_ERTXTH_S) *
32);
rep->re_ertxth= ertxth;
@ -1438,15 +1448,12 @@ static int rl_handler(re_t *rep)
}
/*===========================================================================*
* rl_alarm *
* rl_tick *
*===========================================================================*/
static void rl_alarm(clock_t __unused stamp)
static void rl_tick(void)
{
re_t *rep;
/* Use a synchronous alarm instead of a watchdog timer. */
sys_setalarm(sys_hz(), 0);
rep= &re_state;
assert(rep->re_tx_busy >= 0 && rep->re_tx_busy <= N_TX_BUF);
@ -1461,7 +1468,7 @@ static void rl_alarm(clock_t __unused stamp)
rep->re_tx_alive= FALSE;
return;
}
printf("rl_alarm: resetting instance %d\n", re_instance);
printf("%s: TX timeout, resetting\n", netdriver_name());
printf("TSAD: 0x%04x, TSD: 0x%08x, 0x%08x, 0x%08x, 0x%08x\n",
rl_inw(rep->re_base_port, RL_TSAD),
rl_inl(rep->re_base_port, RL_TSD0+0*4),

View File

@ -470,8 +470,6 @@ typedef struct re
u32_t re_ertxth; /* Early Tx Threshold */
int re_hook_id; /* IRQ hook id at kernel */
eth_stat_t re_stat;
char re_name[sizeof("rtl8139#n")];
} re_t;
/*

View File

@ -11,4 +11,6 @@ LDADD+= -lnetdriver -lsys
CPPFLAGS+= -I${NETBSDSRCDIR}/minix
WARNS?= 5
.include <minix.service.mk>

View File

@ -90,18 +90,14 @@ typedef struct re {
int re_tx_busy; /* how many Tx descriptors are busy? */
int re_hook_id; /* IRQ hook id at kernel */
eth_stat_t re_stat;
phys_bytes dtcc_buf; /* Dump Tally Counter buffer physical */
re_dtcc *v_dtcc_buf; /* Dump Tally Counter buffer */
u32_t dtcc_counter; /* DTCC update counter */
char re_name[sizeof("rtl8169#n")];
u32_t interrupts;
} re_t;
static re_t re_state;
static int re_instance;
static unsigned my_inb(u16_t port)
{
u32_t value;
@ -155,37 +151,44 @@ static void my_outl(u16_t port, u32_t value)
#define rl_outw(port, offset, value) (my_outw((port) + (offset), (value)))
#define rl_outl(port, offset, value) (my_outl((port) + (offset), (value)))
static int rl_init(unsigned int instance, ether_addr_t *addr);
static int rl_init(unsigned int instance, netdriver_addr_t *addr,
uint32_t *caps, unsigned int *ticks);
static int rl_probe(re_t *rep, unsigned int skip);
static void rl_init_buf(re_t *rep);
static void rl_init_hw(re_t *rep, ether_addr_t *addr);
static void rl_init_hw(re_t *rep, netdriver_addr_t *addr,
unsigned int instance);
static void rl_reset_hw(re_t *rep);
static void rl_confaddr(re_t *rep, ether_addr_t *addr);
static void rl_confaddr(re_t *rep, netdriver_addr_t *addr,
unsigned int instance);
static void rl_set_hwaddr(const netdriver_addr_t *addr);
static void rl_stop(void);
static void rl_rec_mode(re_t *rep);
static void rl_mode(unsigned int mode);
static void rl_set_mode(unsigned int mode, const netdriver_addr_t *mcast_list,
unsigned int mcast_count);
static ssize_t rl_recv(struct netdriver_data *data, size_t max);
static int rl_send(struct netdriver_data *data, size_t size);
static unsigned int rl_get_link(uint32_t *media);
static void rl_intr(unsigned int mask);
static void rl_check_ints(re_t *rep);
static void rl_do_reset(re_t *rep);
static void rl_stat(eth_stat_t *stat);
#if VERBOSE
static void rl_report_link(re_t *rep);
static void dump_phy(const re_t *rep);
#endif
static void rl_handler(re_t *rep);
static void rl_alarm(clock_t stamp);
static void rl_tick(void);
static const struct netdriver rl_table = {
.ndr_name = "re",
.ndr_init = rl_init,
.ndr_stop = rl_stop,
.ndr_mode = rl_mode,
.ndr_set_mode = rl_set_mode,
.ndr_set_hwaddr = rl_set_hwaddr,
.ndr_recv = rl_recv,
.ndr_send = rl_send,
.ndr_stat = rl_stat,
.ndr_get_link = rl_get_link,
.ndr_intr = rl_intr,
.ndr_alarm = rl_alarm
.ndr_tick = rl_tick
};
/*===========================================================================*
@ -203,7 +206,8 @@ int main(int argc, char *argv[])
/*===========================================================================*
* rl_init *
*===========================================================================*/
static int rl_init(unsigned int instance, ether_addr_t *addr)
static int rl_init(unsigned int instance, netdriver_addr_t *addr,
uint32_t *caps, unsigned int *ticks)
{
/* Initialize the rtl8169 driver. */
re_t *rep;
@ -212,11 +216,6 @@ static int rl_init(unsigned int instance, ether_addr_t *addr)
rep = &re_state;
memset(rep, 0, sizeof(*rep));
strlcpy(rep->re_name, "rtl8169#0", sizeof(rep->re_name));
rep->re_name[8] += re_instance;
re_instance = instance;
/* Try to find a matching device. */
if (!rl_probe(rep, instance))
return ENXIO;
@ -225,11 +224,10 @@ static int rl_init(unsigned int instance, ether_addr_t *addr)
rl_init_buf(&re_state);
/* Initialize the device we found. */
rl_init_hw(rep, addr);
/* Use a synchronous alarm instead of a watchdog timer. */
sys_setalarm(sys_hz(), 0);
rl_init_hw(rep, addr, instance);
*caps = NDEV_CAP_MCAST | NDEV_CAP_BCAST | NDEV_CAP_HWADDR;
*ticks = sys_hz();
return OK;
}
@ -286,15 +284,13 @@ static int mdio_read(u16_t port, int regaddr)
static void rtl8169_update_stat(re_t *rep)
{
static u64_t last_miss = 0, last_coll = 0;
u64_t miss, coll;
port_t port;
int i;
port = rep->re_base_port;
/* Fetch Missed Packets */
rep->re_stat.ets_missedP += rl_inw(port, RL_MPC);
rl_outw(port, RL_MPC, 0x00);
/* Dump Tally Counter Command */
rl_outl(port, RL_DTCCR_HI, 0); /* 64 bits */
rl_outl(port, RL_DTCCR_LO, rep->dtcc_buf | RL_DTCCR_CMD);
@ -305,11 +301,13 @@ static void rtl8169_update_stat(re_t *rep)
}
/* Update counters */
rep->re_stat.ets_frameAll = rep->v_dtcc_buf->FAE;
rep->re_stat.ets_transDef = rep->v_dtcc_buf->TxUndrn;
rep->re_stat.ets_transAb = rep->v_dtcc_buf->TxAbt;
rep->re_stat.ets_collision =
rep->v_dtcc_buf->Tx1Col + rep->v_dtcc_buf->TxMCol;
miss = rep->v_dtcc_buf->MissPkt;
netdriver_stat_ierror(miss - last_miss);
last_miss = miss;
coll = rep->v_dtcc_buf->Tx1Col + rep->v_dtcc_buf->TxMCol;
netdriver_stat_coll(coll - last_coll);
last_coll = coll;
}
#if 0
@ -327,27 +325,8 @@ static void rtl8169_dump(void)
rtl8169_update_stat(rep);
printf("Realtek RTL 8169 statistics of instance %d:\n", re_instance);
printf("Realtek RTL 8169 driver %s:\n", netdriver_name());
printf("recvErr :%8ld\t", rep->re_stat.ets_recvErr);
printf("sendErr :%8ld\t", rep->re_stat.ets_sendErr);
printf("OVW :%8ld\n", rep->re_stat.ets_OVW);
printf("CRCerr :%8ld\t", rep->re_stat.ets_CRCerr);
printf("frameAll :%8ld\t", rep->re_stat.ets_frameAll);
printf("missedP :%8ld\n", rep->re_stat.ets_missedP);
printf("packetR :%8ld\t", rep->re_stat.ets_packetR);
printf("packetT :%8ld\t", rep->re_stat.ets_packetT);
printf("transDef :%8ld\n", rep->re_stat.ets_transDef);
printf("collision :%8ld\t", rep->re_stat.ets_collision);
printf("transAb :%8ld\t", rep->re_stat.ets_transAb);
printf("carrSense :%8ld\n", rep->re_stat.ets_carrSense);
printf("fifoUnder :%8ld\t", rep->re_stat.ets_fifoUnder);
printf("fifoOver :%8ld\t", rep->re_stat.ets_fifoOver);
printf("OWC :%8ld\n", rep->re_stat.ets_OWC);
printf("interrupts :%8u\n", rep->interrupts);
printf("\nRealtek RTL 8169 Tally Counters:\n");
@ -400,9 +379,11 @@ static void rtl8169_dump(void)
#endif
/*===========================================================================*
* rl_mode *
* rl_set_mode *
*===========================================================================*/
static void rl_mode(unsigned int mode)
static void rl_set_mode(unsigned int mode,
const netdriver_addr_t * mcast_list __unused,
unsigned int mcast_count __unused)
{
re_t *rep;
@ -423,7 +404,7 @@ static int rl_probe(re_t *rep, unsigned int skip)
u32_t bar;
u8_t ilr;
#if VERBOSE
char *dname;
const char *dname;
#endif
pci_init();
@ -442,7 +423,7 @@ static int rl_probe(re_t *rep, unsigned int skip)
dname = pci_dev_name(vid, did);
if (!dname)
dname = "unknown device";
printf("%s: ", rep->re_name);
printf("%s: ", netdriver_name());
printf("%s (%x/%x) at %s\n", dname, vid, did, pci_slot_name(devind));
#endif
@ -457,7 +438,7 @@ static int rl_probe(re_t *rep, unsigned int skip)
rep->re_irq = ilr;
#if VERBOSE
printf("%s: using I/O address 0x%lx, IRQ %d\n",
rep->re_name, (unsigned long)bar, ilr);
netdriver_name(), (unsigned long)bar, ilr);
#endif
return TRUE;
@ -479,7 +460,7 @@ static void rl_init_buf(re_t *rep)
tx_descsize = (N_TX_DESC * sizeof(struct re_desc));
/* Allocate receive and transmit buffers */
tx_bufsize = ETH_MAX_PACK_SIZE_TAGGED;
tx_bufsize = NDEV_ETH_PACKET_MAX_TAGGED;
if (tx_bufsize % 4)
tx_bufsize += 4-(tx_bufsize % 4); /* Align */
rx_bufsize = RX_BUFSIZE;
@ -548,7 +529,8 @@ static void rl_init_buf(re_t *rep)
/*===========================================================================*
* rl_init_hw *
*===========================================================================*/
static void rl_init_hw(re_t *rep, ether_addr_t *addr)
static void rl_init_hw(re_t *rep, netdriver_addr_t *addr,
unsigned int instance)
{
int s;
#if VERBOSE
@ -571,15 +553,15 @@ static void rl_init_hw(re_t *rep, ether_addr_t *addr)
#if VERBOSE
printf("%s: model: %s mac: 0x%08x\n",
rep->re_name, rep->re_model, rep->re_mac);
netdriver_name(), rep->re_model, rep->re_mac);
#endif
rl_confaddr(rep, addr);
rl_confaddr(rep, addr, instance);
#if VERBOSE
printf("%s: Ethernet address ", rep->re_name);
printf("%s: Ethernet address ", netdriver_name());
for (i = 0; i < 6; i++) {
printf("%x%c", addr->ea_addr[i],
printf("%x%c", addr->na_addr[i],
i < 5 ? ':' : '\n');
}
#endif
@ -828,47 +810,61 @@ static void rl_reset_hw(re_t *rep)
/*===========================================================================*
* rl_confaddr *
*===========================================================================*/
static void rl_confaddr(re_t *rep, ether_addr_t *addr)
static void rl_confaddr(re_t *rep, netdriver_addr_t *addr,
unsigned int instance)
{
static char eakey[] = RL_ENVVAR "#_EA";
static char eafmt[] = "x:x:x:x:x:x";
int i;
port_t port;
u32_t w;
long v;
/* User defined ethernet address? */
eakey[sizeof(RL_ENVVAR)-1] = '0' + re_instance;
eakey[sizeof(RL_ENVVAR)-1] = '0' + instance;
port = rep->re_base_port;
for (i = 0; i < 6; i++) {
if (env_parse(eakey, eafmt, i, &v, 0x00L, 0xFFL) != EP_SET)
break;
addr->ea_addr[i] = v;
addr->na_addr[i] = v;
}
if (i != 0 && i != 6)
env_panic(eakey); /* It's all or nothing */
/* Should update ethernet address in hardware */
if (i == 6) {
port = rep->re_base_port;
rl_outb(port, RL_9346CR, RL_9346CR_EEM_CONFIG);
w = 0;
for (i = 0; i < 4; i++)
w |= (addr->ea_addr[i] << (i * 8));
rl_outl(port, RL_IDR, w);
w = 0;
for (i = 4; i < 6; i++)
w |= (addr->ea_addr[i] << ((i-4) * 8));
rl_outl(port, RL_IDR + 4, w);
rl_outb(port, RL_9346CR, RL_9346CR_EEM_NORMAL);
}
if (i == 6)
rl_set_hwaddr(addr);
/* Get ethernet address */
for (i = 0; i < 6; i++)
addr->ea_addr[i] = rl_inb(port, RL_IDR+i);
addr->na_addr[i] = rl_inb(port, RL_IDR+i);
}
/*===========================================================================*
* rl_set_hwaddr *
*===========================================================================*/
static void rl_set_hwaddr(const netdriver_addr_t *addr)
{
re_t *rep;
port_t port;
u32_t w;
int i;
rep = &re_state;
port = rep->re_base_port;
rl_outb(port, RL_9346CR, RL_9346CR_EEM_CONFIG);
w = 0;
for (i = 0; i < 4; i++)
w |= (addr->na_addr[i] << (i * 8));
rl_outl(port, RL_IDR, w);
w = 0;
for (i = 4; i < 6; i++)
w |= (addr->na_addr[i] << ((i-4) * 8));
rl_outl(port, RL_IDR + 4, w);
rl_outb(port, RL_9346CR, RL_9346CR_EEM_NORMAL);
}
/*===========================================================================*
@ -888,11 +884,11 @@ static void rl_rec_mode(re_t *rep)
rcr = rl_inl(port, RL_RCR);
rcr &= ~(RL_RCR_AB | RL_RCR_AM | RL_RCR_APM | RL_RCR_AAP);
if (rep->re_mode & NDEV_PROMISC)
if (rep->re_mode & NDEV_MODE_PROMISC)
rcr |= RL_RCR_AB | RL_RCR_AM | RL_RCR_AAP;
if (rep->re_mode & NDEV_BROAD)
if (rep->re_mode & NDEV_MODE_BCAST)
rcr |= RL_RCR_AB;
if (rep->re_mode & NDEV_MULTI)
if (rep->re_mode & (NDEV_MODE_MCAST_LIST | NDEV_MODE_MCAST_ALL))
rcr |= RL_RCR_AM;
rcr |= RL_RCR_APM;
rl_outl(port, RL_RCR, RL_RCR_RXFTH_UNLIM | RL_RCR_MXDMA_1024 | rcr);
@ -928,7 +924,7 @@ static ssize_t rl_recv(struct netdriver_data *data, size_t max)
return SUSPEND;
if (rxstat & DESC_RX_CRC)
rep->re_stat.ets_CRCerr++;
netdriver_stat_ierror(1);
if ((rxstat & (DESC_FS | DESC_LS)) == (DESC_FS | DESC_LS))
break;
@ -952,7 +948,7 @@ static ssize_t rl_recv(struct netdriver_data *data, size_t max)
}
totlen = rxstat & DESC_RX_LENMASK;
if (totlen < 8 || totlen > 2 * ETH_MAX_PACK_SIZE) {
if (totlen < 8 || totlen > 2 * NDEV_ETH_PACKET_MAX) {
/* Someting went wrong */
printf("rl_recv: bad length (%u) in status 0x%08x\n",
totlen, rxstat);
@ -960,14 +956,12 @@ static ssize_t rl_recv(struct netdriver_data *data, size_t max)
}
/* Should subtract the CRC */
packlen = totlen - ETH_CRC_SIZE;
packlen = totlen - NDEV_ETH_PACKET_CRC;
if (packlen > max)
packlen = max;
netdriver_copyout(data, 0, rep->re_rx[index].v_ret_buf, packlen);
rep->re_stat.ets_packetR++;
if (index == N_RX_DESC - 1) {
desc->status = DESC_EOR | DESC_OWN |
(RX_BUFSIZE & DESC_RX_LENMASK);
@ -1049,12 +1043,44 @@ static void rl_check_ints(re_t *rep)
if (rep->re_report_link) {
rep->re_report_link = FALSE;
netdriver_link();
#if VERBOSE
rl_report_link(rep);
#endif
}
}
/*===========================================================================*
* rl_get_link *
*===========================================================================*/
static unsigned int rl_get_link(uint32_t *media)
{
re_t *rep;
u8_t mii_status;
rep = &re_state;
mii_status = rl_inb(rep->re_base_port, RL_PHYSTAT);
if (!(mii_status & RL_STAT_LINK))
return NDEV_LINK_DOWN;
if (mii_status & RL_STAT_1000)
*media = IFM_ETHER | IFM_1000_T;
else if (mii_status & RL_STAT_100)
*media = IFM_ETHER | IFM_100_TX;
else if (mii_status & RL_STAT_10)
*media = IFM_ETHER | IFM_10_T;
if (mii_status & RL_STAT_FULLDUP)
*media |= IFM_FDX;
else
*media |= IFM_HDX;
return NDEV_LINK_UP;
}
/*===========================================================================*
* rl_report_link *
*===========================================================================*/
@ -1070,10 +1096,10 @@ static void rl_report_link(re_t *rep)
if (mii_status & RL_STAT_LINK) {
rep->re_link_up = 1;
printf("%s: link up at ", rep->re_name);
printf("%s: link up at ", netdriver_name());
} else {
rep->re_link_up = 0;
printf("%s: link down\n", rep->re_name);
printf("%s: link down\n", netdriver_name());
return;
}
@ -1110,14 +1136,6 @@ static void rl_do_reset(re_t *rep)
rep->re_send_int = TRUE;
}
/*===========================================================================*
* rl_stat *
*===========================================================================*/
static void rl_stat(eth_stat_t *stat)
{
memcpy(stat, &re_state.re_stat, sizeof(*stat));
}
#if VERBOSE
static void dump_phy(const re_t *rep)
{
@ -1341,8 +1359,6 @@ static void rl_handler(re_t *rep)
if (isr & RL_IMR_FOVW) {
isr &= ~RL_IMR_FOVW;
/* Should do anything? */
rep->re_stat.ets_fifoOver++;
}
if (isr & RL_IMR_PUN) {
isr &= ~RL_IMR_PUN;
@ -1360,7 +1376,7 @@ static void rl_handler(re_t *rep)
if (isr & (RL_ISR_RDU | RL_ISR_RER | RL_ISR_ROK)) {
if (isr & RL_ISR_RER)
rep->re_stat.ets_recvErr++;
netdriver_stat_ierror(1);
isr &= ~(RL_ISR_RDU | RL_ISR_RER | RL_ISR_ROK);
rep->re_got_int = TRUE;
@ -1368,7 +1384,7 @@ static void rl_handler(re_t *rep)
if ((isr & (RL_ISR_TDU | RL_ISR_TER | RL_ISR_TOK)) || 1) {
if (isr & RL_ISR_TER)
rep->re_stat.ets_sendErr++;
netdriver_stat_oerror(1);
isr &= ~(RL_ISR_TDU | RL_ISR_TER | RL_ISR_TOK);
/* Transmit completed */
@ -1397,7 +1413,6 @@ static void rl_handler(re_t *rep)
break;
}
rep->re_stat.ets_packetT++;
rep->re_tx[tx_tail].ret_busy = FALSE;
rep->re_tx_busy--;
@ -1421,15 +1436,12 @@ static void rl_handler(re_t *rep)
}
/*===========================================================================*
* rl_alarm *
* rl_tick *
*===========================================================================*/
static void rl_alarm(clock_t __unused stamp)
static void rl_tick(void)
{
re_t *rep;
/* Use a synchronous alarm instead of a watchdog timer. */
sys_setalarm(sys_hz(), 0);
rep = &re_state;
/* Should collect statistics */
@ -1446,7 +1458,7 @@ static void rl_alarm(clock_t __unused stamp)
rep->re_tx_alive = FALSE;
return;
}
printf("rl_alarm: resetting instance %d\n", re_instance);
printf("%s: TX timeout, resetting\n", netdriver_name());
printf("tx_head :%8d busy %d\t",
rep->re_tx_head, rep->re_tx[rep->re_tx_head].ret_busy);
rep->re_need_reset = TRUE;

View File

@ -9,4 +9,6 @@ FILESDIR= /etc/system.conf.d
DPADD+= ${LIBNETDRIVER} ${LIBSYS} ${LIBVIRTIO}
LDADD+= -lnetdriver -lsys -lvirtio
WARNS?= 5
.include <minix.service.mk>

View File

@ -10,12 +10,8 @@
#include <assert.h>
#include <sys/types.h>
#include <net/gen/ether.h>
#include <net/gen/eth_io.h>
#include <minix/drivers.h>
#include <minix/netdriver.h>
#include <minix/sysutil.h>
#include <minix/virtio.h>
#include <sys/queue.h>
@ -27,7 +23,7 @@
#if VERBOSE
#define dput(s) do { dprintf(s); printf("\n"); } while (0)
#define dprintf(s) do { \
printf("%s: ", name); \
printf("%s: ", netdriver_name()); \
printf s; \
} while (0)
#else
@ -37,8 +33,6 @@
static struct virtio_device *net_dev;
static const char *const name = "virtio-net";
enum queue {RX_Q, TX_Q, CTRL_Q};
/* Number of packets to work with */
@ -47,7 +41,7 @@ enum queue {RX_Q, TX_Q, CTRL_Q};
*/
#define BUF_PACKETS 64
/* Maximum size of a packet */
#define MAX_PACK_SIZE ETH_MAX_PACK_SIZE
#define MAX_PACK_SIZE NDEV_ETH_PACKET_MAX
/* Buffer size needed for the payload of BUF_PACKETS */
#define PACKET_BUF_SZ (BUF_PACKETS * MAX_PACK_SIZE)
@ -76,12 +70,11 @@ static STAILQ_HEAD(free_list, packet) free_list;
static STAILQ_HEAD(recv_list, packet) recv_list;
/* Various state data */
static eth_stat_t virtio_net_stats;
static int spurious_interrupt;
/* Prototypes */
static int virtio_net_probe(unsigned int skip);
static void virtio_net_config(ether_addr_t *addr);
static void virtio_net_config(netdriver_addr_t *addr);
static int virtio_net_alloc_bufs(void);
static void virtio_net_init_queues(void);
@ -89,19 +82,19 @@ static void virtio_net_refill_rx_queue(void);
static void virtio_net_check_queues(void);
static void virtio_net_check_pending(void);
static int virtio_net_init(unsigned int instance, ether_addr_t *addr);
static int virtio_net_init(unsigned int instance, netdriver_addr_t * addr,
uint32_t * caps, unsigned int * ticks);
static void virtio_net_stop(void);
static int virtio_net_send(struct netdriver_data *data, size_t len);
static ssize_t virtio_net_recv(struct netdriver_data *data, size_t max);
static void virtio_net_stat(eth_stat_t *stat);
static void virtio_net_intr(unsigned int mask);
static const struct netdriver virtio_net_table = {
.ndr_name = "vio",
.ndr_init = virtio_net_init,
.ndr_stop = virtio_net_stop,
.ndr_recv = virtio_net_recv,
.ndr_send = virtio_net_send,
.ndr_stat = virtio_net_stat,
.ndr_intr = virtio_net_intr,
};
@ -119,7 +112,7 @@ virtio_net_probe(unsigned int skip)
{
/* virtio-net has at least 2 queues */
int queues = 2;
net_dev= virtio_setup_device(0x00001, name, netf,
net_dev= virtio_setup_device(0x00001, netdriver_name(), netf,
sizeof(netf) / sizeof(netf[0]),
1 /* threads */, skip);
if (net_dev == NULL)
@ -138,7 +131,7 @@ virtio_net_probe(unsigned int skip)
}
static void
virtio_net_config(ether_addr_t * addr)
virtio_net_config(netdriver_addr_t * addr)
{
u32_t mac14;
u32_t mac56;
@ -148,11 +141,11 @@ virtio_net_config(ether_addr_t * addr)
dprintf(("Mac set by host: "));
mac14 = virtio_sread32(net_dev, 0);
mac56 = virtio_sread32(net_dev, 4);
memcpy(&addr->ea_addr[0], &mac14, 4);
memcpy(&addr->ea_addr[4], &mac56, 2);
memcpy(&addr->na_addr[0], &mac14, 4);
memcpy(&addr->na_addr[4], &mac56, 2);
for (i = 0; i < 6; i++)
dprintf(("%02x%s", addr->ea_addr[i],
dprintf(("%02x%s", addr->na_addr[i],
i == 5 ? "\n" : ":"));
} else {
dput(("No mac"));
@ -247,10 +240,8 @@ virtio_net_refill_rx_queue(void)
in_rx++;
}
if (in_rx == 0 && STAILQ_EMPTY(&free_list)) {
if (in_rx == 0 && STAILQ_EMPTY(&free_list))
dput(("warning: rx queue underflow!"));
virtio_net_stats.ets_fifoUnder++;
}
}
static void
@ -264,7 +255,6 @@ virtio_net_check_queues(void)
p->len = len;
STAILQ_INSERT_TAIL(&recv_list, p, next);
in_rx--;
virtio_net_stats.ets_packetR++;
}
/*
@ -275,7 +265,6 @@ virtio_net_check_queues(void)
memset(p->vhdr, 0, sizeof(*p->vhdr));
memset(p->vdata, 0, MAX_PACK_SIZE);
STAILQ_INSERT_HEAD(&free_list, p, next);
virtio_net_stats.ets_packetT++;
}
}
@ -330,7 +319,8 @@ virtio_net_send(struct netdriver_data * data, size_t len)
STAILQ_REMOVE_HEAD(&free_list, next);
if (len > MAX_PACK_SIZE)
panic("%s: packet too large to send: %zu", name, len);
panic("%s: packet too large to send: %zu",
netdriver_name(), len);
netdriver_copyin(data, 0, p->vdata, len);
@ -363,18 +353,21 @@ virtio_net_recv(struct netdriver_data * data, size_t max)
STAILQ_REMOVE_HEAD(&recv_list, next);
/* Copy out the packet contents. */
if (p->len < sizeof(struct virtio_net_hdr))
panic("received packet does not have virtio header");
len = p->len - sizeof(struct virtio_net_hdr);
if (len > max)
len = max;
if ((size_t)len > max)
len = (ssize_t)max;
/*
* HACK: due to lack of padding, received packets may in fact be
* smaller than the minimum ethernet packet size. Inet will accept the
* packets just fine if we increase the length to its minimum. We
* already zeroed out the rest of the packet data, so this is safe.
* smaller than the minimum ethernet packet size. The TCP/IP service
* will accept the packets just fine if we increase the length to its
* minimum. We already zeroed out the rest of the packet data, so this
* is safe.
*/
if (len < ETH_MIN_PACK_SIZE)
len = ETH_MIN_PACK_SIZE;
if (len < NDEV_ETH_PACKET_MIN)
len = NDEV_ETH_PACKET_MIN;
netdriver_copyout(data, 0, p->vdata, len);
@ -389,21 +382,12 @@ virtio_net_recv(struct netdriver_data * data, size_t max)
return len;
}
/*
* Return statistics.
*/
static void
virtio_net_stat(eth_stat_t *stat)
{
memcpy(stat, &virtio_net_stats, sizeof(*stat));
}
/*
* Initialize the driver and the virtual hardware.
*/
static int
virtio_net_init(unsigned int instance, ether_addr_t *addr)
virtio_net_init(unsigned int instance, netdriver_addr_t * addr,
uint32_t * caps, unsigned int * ticks __unused)
{
int r;
@ -413,7 +397,7 @@ virtio_net_init(unsigned int instance, ether_addr_t *addr)
virtio_net_config(addr);
if (virtio_net_alloc_bufs() != OK)
panic("%s: Buffer allocation failed", name);
panic("%s: Buffer allocation failed", netdriver_name());
virtio_net_init_queues();
@ -424,7 +408,8 @@ virtio_net_init(unsigned int instance, ether_addr_t *addr)
virtio_irq_enable(net_dev);
return(OK);
*caps = NDEV_CAP_MCAST | NDEV_CAP_BCAST;
return OK;
}
/*

View File

@ -10,20 +10,21 @@ static NDR_driver g_driver;
static int g_instance;
/* driver interface */
static int NDR_init(unsigned int instance, ether_addr_t *addr);
static int NDR_init(unsigned int instance, netdriver_addr_t * addr,
uint32_t * caps, unsigned int * ticks);
static void NDR_stop(void);
static void NDR_mode(unsigned int mode);
static void NDR_set_mode(unsigned int mode,
const netdriver_addr_t * mcast_list, unsigned int mcast_count);
static ssize_t NDR_recv(struct netdriver_data *data, size_t max);
static int NDR_send(struct netdriver_data *data, size_t size);
static void NDR_intr(unsigned int mask);
static void NDR_stat(eth_stat_t *stat);
/* internal function */
static int dev_probe(NDR_driver *pdev, int instance);
static int dev_init_buf(NDR_driver *pdev);
static int dev_init_hw(NDR_driver *pdev, ether_addr_t *addr);
static int dev_init_hw(NDR_driver *pdev, netdriver_addr_t *addr);
static int dev_reset_hw(NDR_driver *pdev);
static void dev_conf_addr(NDR_driver *pdev, ether_addr_t *addr);
static void dev_conf_addr(NDR_driver *pdev, netdriver_addr_t *addr);
static void dev_handler(NDR_driver *pdev);
static void dev_check_ints(NDR_driver *pdev);
@ -150,11 +151,11 @@ static void dev_set_rec_mode(u32_t *base, int mode) {
u32_t data, base0 = base[0];
data = ndr_in8(base0, REG_RCR);
data &= ~(CMD_RCR_UNICAST | CMD_RCR_MULTICAST | CMD_RCR_BROADCAST);
if (mode & NDEV_PROMISC)
if (mode & NDEV_MODE_PROMISC)
data |= CMD_RCR_UNICAST | CMD_RCR_BROADCAST | CMD_RCR_MULTICAST;
if (mode & NDEV_BROAD)
if (mode & NDEV_MODE_BCAST)
data |= CMD_RCR_BROADCAST;
if (mode & NDEV_MULTI)
if (mode & (NDEV_MODE_MCAST_LIST | NDEV_MODE_MCAST_ALL))
data |= CMD_RCR_MULTICAST;
data |= CMD_RCR_UNICAST;
ndr_out8(base0, REG_RCR, data);
@ -226,8 +227,7 @@ static int dev_rx_ok_desc(u32_t *base, NDR_desc *desc, int index) {
* -- Current buffer number is index
* -- Return the length */
static int dev_rx_len_desc(u32_t *base, NDR_desc *desc, int index) {
int len = ((desc->status & DESC_RX_LENMASK) >> 16) - ETH_CRC_SIZE;
return len;
return ((desc->status & DESC_RX_LENMASK) >> 16) - NDEV_ETH_PACKET_CRC;
}
/* Set Rx descriptor after Rx done (### SET_RX_DESC_DONE ###)
@ -264,13 +264,13 @@ static void dev_set_tx_desc_done(u32_t *base, NDR_desc *desc, int index) {
/* Driver interface table */
static const struct netdriver NDR_table = {
.ndr_name = "vr",
.ndr_init = NDR_init,
.ndr_stop = NDR_stop,
.ndr_mode = NDR_mode,
.ndr_set_mode = NDR_set_mode,
.ndr_recv = NDR_recv,
.ndr_send = NDR_send,
.ndr_intr = NDR_intr,
.ndr_stat = NDR_stat
};
int main(int argc, char *argv[]) {
@ -279,15 +279,15 @@ int main(int argc, char *argv[]) {
}
/* Initialize the driver */
static int NDR_init(unsigned int instance, ether_addr_t *addr) {
static int
NDR_init(unsigned int instance, netdriver_addr_t * addr, uint32_t * caps,
unsigned int * ticks __unused)
{
int i, ret = 0;
/* Intialize driver data structure */
memset(&g_driver, 0, sizeof(g_driver));
g_driver.link = LINK_UNKNOWN;
strcpy(g_driver.name, DRIVER_NAME);
strcat(g_driver.name, "#0");
g_driver.name[strlen(g_driver.name) - 1] += instance;
g_instance = instance;
/* Probe the device */
@ -319,14 +319,12 @@ static int NDR_init(unsigned int instance, ether_addr_t *addr) {
/* ### RX_TX_ENABLE_DISABLE ### */
dev_rx_tx_control(g_driver.base, RX_TX_ENABLE);
/* Use a synchronous alarm instead of a watchdog timer */
sys_setalarm(sys_hz(), 0);
/* Clear send and recv flag */
g_driver.send_flag = FALSE;
g_driver.recv_flag = FALSE;
return 0;
*caps = NDEV_CAP_MCAST | NDEV_CAP_BCAST;
return OK;
err_init_buf:
err_init_hw:
@ -349,7 +347,10 @@ static void NDR_stop(void) {
}
/* Set driver mode */
static void NDR_mode(unsigned int mode) {
static void
NDR_set_mode(unsigned int mode, const netdriver_addr_t * mcast_list __unused,
unsigned int mcast_count __unused)
{
g_driver.mode = mode;
/* Set driver receive mode */
/* ### SET_REC_MODE ### */
@ -379,7 +380,7 @@ static ssize_t NDR_recv(struct netdriver_data *data, size_t max) {
/* Get data length */
/* ### Get , int inde, int indexxRx data length ### */
if (totlen < 8 || totlen > 2 * ETH_MAX_PACK_SIZE) {
if (totlen < 8 || totlen > 2 * NDEV_ETH_PACKET_MAX) {
printf("NDR: Bad data length: %d\n", totlen);
panic(NULL);
}
@ -390,7 +391,6 @@ static ssize_t NDR_recv(struct netdriver_data *data, size_t max) {
/* Copy data to user */
netdriver_copyout(data, 0, pdev->rx[index].buf + offset, packlen);
pdev->stat.ets_packetR++;
/* Set Rx descriptor after Rx done */
/* ### SET_RX_DESC_DONE ### */
@ -458,11 +458,6 @@ static void NDR_intr(unsigned int mask) {
dev_check_ints(&g_driver);
}
/* Get driver status */
static void NDR_stat(eth_stat_t *stat) {
memcpy(stat, &g_driver.stat, sizeof(*stat));
}
/* Match the device and get base address */
static int dev_probe(NDR_driver *pdev, int instance) {
int devind, ioflag, i;
@ -526,7 +521,7 @@ static int dev_probe(NDR_driver *pdev, int instance) {
}
/* Intialize hardware */
static int dev_init_hw(NDR_driver *pdev, ether_addr_t *addr) {
static int dev_init_hw(NDR_driver *pdev, netdriver_addr_t *addr) {
int r, ret;
/* Set the OS interrupt handler */
@ -609,22 +604,22 @@ err_real_reset:
}
/* Configure MAC address */
static void dev_conf_addr(NDR_driver *pdev, ether_addr_t *addr) {
static void dev_conf_addr(NDR_driver *pdev, netdriver_addr_t *addr) {
u8_t pa[6];
/* Get MAC address */
/* ### GET_MAC_ADDR ### */
dev_get_addr(pdev->base, pa);
addr->ea_addr[0] = pa[0];
addr->ea_addr[1] = pa[1];
addr->ea_addr[2] = pa[2];
addr->ea_addr[3] = pa[3];
addr->ea_addr[4] = pa[4];
addr->ea_addr[5] = pa[5];
addr->na_addr[0] = pa[0];
addr->na_addr[1] = pa[1];
addr->na_addr[2] = pa[2];
addr->na_addr[3] = pa[3];
addr->na_addr[4] = pa[4];
addr->na_addr[5] = pa[5];
#ifdef MY_DEBUG
printf("NDR: Ethernet address is %02x:%02x:%02x:%02x:%02x:%02x\n",
addr->ea_addr[0], addr->ea_addr[1], addr->ea_addr[2],
addr->ea_addr[3], addr->ea_addr[4], addr->ea_addr[5]);
addr->na_addr[0], addr->na_addr[1], addr->na_addr[2],
addr->na_addr[3], addr->na_addr[4], addr->na_addr[5]);
#endif
}
@ -759,7 +754,6 @@ static void dev_handler(NDR_driver *pdev) {
else if (ret == TX_ERROR)
printf("NDR: Tx error now\n");
pdev->stat.ets_packetT++;
pdev->tx[tx_tail].busy = FALSE;
pdev->tx_busy_num--;

View File

@ -133,8 +133,6 @@ typedef struct NDR_driver {
phys_bytes tx_desc_dma; /* Tx descriptor DMA buffer */
int hook; /* IRQ hook id at kernel */
eth_stat_t stat; /* Ethernet status */
char name[50]; /* Driver name */
} NDR_driver;
#endif

View File

@ -31,6 +31,7 @@
* 0x1700 - 0x17FF PTYFS requests
* 0x1800 - 0x18FF Management Information Base (MIB) requests
* 0x1900 - 0x19FF Socket device requests and responses
* 0x1A00 - 0x1AFF Network device requests and responses
*
* Zero and negative values are widely used for OK and error responses.
*/
@ -1076,6 +1077,73 @@
# define SDEV_OP_ERR 0x04 /* selected for error operation */
# define SDEV_NOTIFY 0x08 /* notification requested */
/*===========================================================================*
* Messages for network devices *
*===========================================================================*/
/* Base type for network device requests and responses. */
#define NDEV_RQ_BASE 0x1A00 /* ndev -> netdriver */
#define NDEV_RS_BASE 0x1A80 /* netdriver -> ndev */
#define IS_NDEV_RQ(type) (((type) & ~0x7f) == NDEV_RQ_BASE)
#define IS_NDEV_RS(type) (((type) & ~0x7f) == NDEV_RS_BASE)
/*
* Status requests and responses travel in the opposite direction, so we group
* them with their sending party, so that the IS_NDEV_R[QS] macros can be used
* by either side to see whether the message is indeed for them.
*/
#define NDEV_INIT (NDEV_RQ_BASE + 0) /* initialize driver */
#define NDEV_CONF (NDEV_RQ_BASE + 1) /* configure driver */
#define NDEV_SEND (NDEV_RQ_BASE + 2) /* send a packet */
#define NDEV_RECV (NDEV_RQ_BASE + 3) /* receive a packet */
#define NDEV_IOCTL (NDEV_RQ_BASE + 4) /* (reserved) */
#define NDEV_STATUS_REPLY (NDEV_RQ_BASE + 5) /* status reply */
#define NDEV_INIT_REPLY (NDEV_RS_BASE + 0) /* initialize reply */
#define NDEV_CONF_REPLY (NDEV_RS_BASE + 1) /* configure reply */
#define NDEV_SEND_REPLY (NDEV_RS_BASE + 2) /* send reply */
#define NDEV_RECV_REPLY (NDEV_RS_BASE + 3) /* receive reply */
#define NDEV_IOCTL_REPLY (NDEV_RS_BASE + 4) /* (reserved) */
#define NDEV_STATUS (NDEV_RS_BASE + 5) /* status report */
/* Bits in the 'set' field of configuration requests. */
# define NDEV_SET_MODE 0x01 /* set I/O mode and multicast list */
# define NDEV_SET_CAPS 0x02 /* enable or disable capabilities */
# define NDEV_SET_FLAGS 0x04 /* set driver-specific flags */
# define NDEV_SET_MEDIA 0x08 /* set media type */
# define NDEV_SET_HWADDR 0x10 /* change the hardware address */
/* Bits in the 'mode' field of configuration requests. */
# define NDEV_MODE_DOWN 0x00 /* transmission and receipt disabled */
# define NDEV_MODE_UP 0x01 /* receive unicast packets for me */
# define NDEV_MODE_BCAST 0x02 /* receive broadcast packets */
# define NDEV_MODE_MCAST_LIST 0x04 /* receive certain multicast packets */
# define NDEV_MODE_MCAST_ALL 0x08 /* receive all multicast packets */
# define NDEV_MODE_PROMISC 0x10 /* receive all packets */
/* Bits in the 'caps' field of initialization and configuration requests. */
# define NDEV_CAP_CS_IP4_TX 0x01 /* IPv4 header checksum generation */
# define NDEV_CAP_CS_IP4_RX 0x02 /* IPv4 header checksum verification */
# define NDEV_CAP_CS_UDP_TX 0x04 /* UDP header checksum generation */
# define NDEV_CAP_CS_UDP_RX 0x08 /* UDP header checksum verification */
# define NDEV_CAP_CS_TCP_TX 0x10 /* TCP header checksum generation */
# define NDEV_CAP_CS_TCP_RX 0x20 /* TCP header checksum verification */
# define NDEV_CAP_MCAST 0x20000000 /* init only: mcast capable */
# define NDEV_CAP_BCAST 0x40000000 /* init only: bcast capable */
# define NDEV_CAP_HWADDR 0x80000000 /* init only: can set hwaddr */
/* Values for the 'flags' field of configuration requests. */
# define NDEV_FLAG_DEBUG 0x01 /* enable driver-specific debug mode */
# define NDEV_FLAG_LINK0 0x02 /* enable driver-specific LINK0 flag */
# define NDEV_FLAG_LINK1 0x04 /* enable driver-specific LINK1 flag */
# define NDEV_FLAG_LINK2 0x08 /* enable driver-specific LINK2 flag */
/* Values for the 'link' field of initialization and status replies. */
# define NDEV_LINK_UNKNOWN 0 /* link status is unknown, assume up */
# define NDEV_LINK_UP 1 /* link is up */
# define NDEV_LINK_DOWN 2 /* link is down */
/*===========================================================================*
* Internal codes used by several services *
*===========================================================================*/

View File

@ -98,4 +98,9 @@
#define NR_PCIBUS 40
#define NR_PCIDEV 50
/* Network device driver protocol parameters. */
#define NDEV_NAME_MAX 16 /* max network driver name length (incl nul) */
#define NDEV_HWADDR_MAX 6 /* max network hardware address length */
#define NDEV_IOV_MAX 8 /* max number of elements in I/O vector */
#endif /* _CONFIG_H */

View File

@ -175,4 +175,11 @@
*/
#define MINIX_CPUSTATES 5
/* Network device driver constants. TODO: move to a better location. */
#define NDEV_ETH_PACKET_MIN 60 /* min network packet size, in bytes */
#define NDEV_ETH_PACKET_MAX 1514 /* max network packet size, in bytes */
#define NDEV_ETH_PACKET_TAG 4 /* ethernet VLAN tag size, in bytes */
#define NDEV_ETH_PACKET_CRC 4 /* ethernet CRC size, in bytes */
#define NDEV_ETH_PACKET_MAX_TAGGED (NDEV_ETH_PACKET_MAX + NDEV_ETH_PACKET_TAG)
#endif /* _MINIX_CONST_H */

View File

@ -1592,6 +1592,79 @@ typedef struct {
} mess_mmap;
_ASSERT_MSG_SIZE(mess_mmap);
typedef struct {
uint32_t id;
uint8_t padding[52];
} mess_ndev_netdriver_init;
_ASSERT_MSG_SIZE(mess_ndev_netdriver_init);
typedef struct {
uint32_t id;
uint32_t set;
uint32_t mode;
cp_grant_id_t mcast_grant;
unsigned int mcast_count;
uint32_t caps;
uint32_t flags;
uint32_t media;
uint8_t hwaddr[NDEV_HWADDR_MAX];
uint8_t padding[18];
} mess_ndev_netdriver_conf;
_ASSERT_MSG_SIZE(mess_ndev_netdriver_conf);
typedef struct {
uint32_t id;
uint32_t count;
cp_grant_id_t grant[NDEV_IOV_MAX];
uint16_t len[NDEV_IOV_MAX];
} mess_ndev_netdriver_transfer;
_ASSERT_MSG_SIZE(mess_ndev_netdriver_transfer);
typedef struct {
uint32_t id;
uint8_t padding[52];
} mess_ndev_netdriver_status_reply;
_ASSERT_MSG_SIZE(mess_ndev_netdriver_status_reply);
typedef struct {
uint32_t id;
uint32_t link;
uint32_t media;
uint32_t caps;
char name[NDEV_NAME_MAX];
uint8_t hwaddr[NDEV_HWADDR_MAX];
uint8_t hwaddr_len;
uint8_t max_send;
uint8_t max_recv;
uint8_t padding[15];
} mess_netdriver_ndev_init_reply;
_ASSERT_MSG_SIZE(mess_netdriver_ndev_init_reply);
typedef struct {
uint32_t id;
int32_t result;
uint8_t padding[48];
} mess_netdriver_ndev_reply;
_ASSERT_MSG_SIZE(mess_netdriver_ndev_reply);
typedef struct {
uint32_t id;
uint32_t link;
uint32_t media;
uint32_t oerror;
uint32_t coll;
uint32_t ierror;
uint32_t iqdrop;
uint8_t padding[28];
} mess_netdriver_ndev_status;
_ASSERT_MSG_SIZE(mess_netdriver_ndev_status);
typedef struct {
int mode;
@ -2509,6 +2582,13 @@ typedef struct noxfer_message {
mess_mib_lsys_call m_mib_lsys_call;
mess_mib_lsys_info m_mib_lsys_info;
mess_mmap m_mmap;
mess_ndev_netdriver_init m_ndev_netdriver_init;
mess_ndev_netdriver_conf m_ndev_netdriver_conf;
mess_ndev_netdriver_transfer m_ndev_netdriver_transfer;
mess_ndev_netdriver_status_reply m_ndev_netdriver_status_reply;
mess_netdriver_ndev_init_reply m_netdriver_ndev_init_reply;
mess_netdriver_ndev_reply m_netdriver_ndev_reply;
mess_netdriver_ndev_status m_netdriver_ndev_status;
mess_net_netdrv_dl_conf m_net_netdrv_dl_conf;
mess_net_netdrv_dl_getstat_s m_net_netdrv_dl_getstat_s;
mess_net_netdrv_dl_readv_s m_net_netdrv_dl_readv_s;

View File

@ -1,67 +1,75 @@
/* Prototypes and definitions for network drivers. */
#ifndef _MINIX_NETDRIVER_H
#define _MINIX_NETDRIVER_H
/*
* Prototypes and definitions for network drivers.
*/
#include <minix/config.h>
#include <minix/endpoint.h>
#include <minix/ipc.h>
#include <minix/com.h>
/* The flags that make up the requested receive mode. */
#define NDEV_NOMODE DL_NOMODE /* targeted packets only */
#define NDEV_PROMISC DL_PROMISC_REQ /* promiscuous mode */
#define NDEV_MULTI DL_MULTI_REQ /* receive multicast packets */
#define NDEV_BROAD DL_BROAD_REQ /* receive broadcast packets */
/*
* For now, only ethernet-type network drivers are supported, and thus, we use
* some ethernet-specific data structures.
*/
#include <net/gen/ether.h>
#include <net/gen/eth_io.h>
#include <net/if_media.h>
/* Opaque data structure for copying in and out actual packet data. */
struct netdriver_data;
/* Function call table for network drivers. */
/* Network (ethernet) address structure. */
typedef struct {
uint8_t na_addr[NDEV_HWADDR_MAX];
} netdriver_addr_t;
/* Information and function call table for network drivers. */
struct netdriver {
int (*ndr_init)(unsigned int instance, ether_addr_t *addr);
void (*ndr_stop)(void);
void (*ndr_mode)(unsigned int mode);
ssize_t (*ndr_recv)(struct netdriver_data *data, size_t max);
int (*ndr_send)(struct netdriver_data *data, size_t size);
void (*ndr_stat)(eth_stat_t *stat);
void (*ndr_intr)(unsigned int mask);
void (*ndr_alarm)(clock_t stamp);
void (*ndr_other)(const message *m_ptr, int ipc_status);
const char *ndr_name;
int (* ndr_init)(unsigned int instance, netdriver_addr_t * hwaddr,
uint32_t * caps, unsigned int * ticks);
void (* ndr_stop)(void);
void (* ndr_set_mode)(unsigned int mode,
const netdriver_addr_t * mcast_list, unsigned int mcast_count);
void (* ndr_set_caps)(uint32_t caps);
void (* ndr_set_flags)(uint32_t flags);
void (* ndr_set_media)(uint32_t media);
void (* ndr_set_hwaddr)(const netdriver_addr_t * hwaddr);
ssize_t (* ndr_recv)(struct netdriver_data * data, size_t max);
int (* ndr_send)(struct netdriver_data * data, size_t size);
unsigned int (* ndr_get_link)(uint32_t * media);
void (* ndr_intr)(unsigned int mask);
void (* ndr_tick)(void);
void (* ndr_other)(const message * m_ptr, int ipc_status);
};
/* Functions defined by libnetdriver. */
void netdriver_task(const struct netdriver *ndp);
void netdriver_task(const struct netdriver * ndp);
void netdriver_announce(void); /* legacy; deprecated */
int netdriver_init(const struct netdriver *ndp);
int netdriver_init(const struct netdriver * ndp);
void netdriver_process(const struct netdriver * __restrict ndp,
const message * __restrict m_ptr, int ipc_status);
void netdriver_terminate(void);
const char *netdriver_name(void);
void netdriver_recv(void);
void netdriver_send(void);
void netdriver_link(void);
void netdriver_stat_oerror(uint32_t count);
void netdriver_stat_coll(uint32_t count);
void netdriver_stat_ierror(uint32_t count);
void netdriver_stat_iqdrop(uint32_t count);
void netdriver_copyin(struct netdriver_data * __restrict data, size_t off,
void * __restrict ptr, size_t size);
void netdriver_copyout(struct netdriver_data * __restrict data, size_t off,
const void * __restrict ptr, size_t size);
void netdriver_portinb(struct netdriver_data *data, size_t off, long port,
void netdriver_portinb(struct netdriver_data * data, size_t off, long port,
size_t size);
void netdriver_portoutb(struct netdriver_data *data, size_t off, long port,
void netdriver_portoutb(struct netdriver_data * data, size_t off, long port,
size_t size);
void netdriver_portinw(struct netdriver_data *data, size_t off, long port,
void netdriver_portinw(struct netdriver_data * data, size_t off, long port,
size_t size);
void netdriver_portoutw(struct netdriver_data *data, size_t off, long port,
void netdriver_portoutw(struct netdriver_data * data, size_t off, long port,
size_t size);
#define netdriver_receive sef_receive_status /* legacy; deprecated */
#endif /* _MINIX_NETDRIVER_H */

View File

@ -13,7 +13,7 @@
* May 31, 2005: added printf, kputc (relocated from syslib)
* May 31, 2005: added getuptime
* Mar 18, 2005: added tickdelay
* Oct 01, 2004: added env_parse, env_prefix, env_panic
* Oct 01, 2004: added env_parse, env_panic
* Jul 13, 2004: added fkey_ctl
* Apr 28, 2004: added report, panic
* Mar 31, 2004: setup like other libraries, such as syslib
@ -36,7 +36,6 @@ extern char **env_argv;
void env_setargs(int argc, char *argv[]);
int env_get_param(const char *key, char *value, int max_size);
int env_prefix(const char *env, const char *prefix);
void __dead env_panic(const char *key);
int env_parse(const char *env, const char *fmt, int field,
long *param, long min, long max);

View File

@ -6,4 +6,6 @@ LIB= netdriver
SRCS= netdriver.c portio.c
WARNS?= 5
.include <bsd.lib.mk>

View File

@ -1,32 +1,60 @@
/* The device-independent network driver framework. */
#include <minix/drivers.h>
#include <minix/endpoint.h>
#include <minix/netdriver.h>
#include <minix/ds.h>
#include <assert.h>
#include "netdriver.h"
/*
* These maximum values should be at least somewhat synchronized with the
* values in the LWIP service's ndev module.
*/
#define NETDRIVER_SENDQ_MAX 8
#define NETDRIVER_RECVQ_MAX 2
/*
* Maximum number of multicast addresses that can be copied in from the TCP/IP
* service and passed to the driver. If the actual number from the service
* exceeds this maximum, the driver will be told to receive all multicast
* packets instead.
*/
#define NETDRIVER_MCAST_MAX 16
static const struct netdriver *netdriver_table = NULL;
static int running;
static int conf_expected;
static int init_expected;
static endpoint_t pending_endpt;
static struct netdriver_data pending_recv, pending_send;
static int up;
static int defer_reply;
static unsigned int pending_flags;
static size_t pending_size;
static unsigned int ticks;
static ether_addr_t hw_addr;
static struct netdriver_data pending_sendq[NETDRIVER_SENDQ_MAX];
static unsigned int pending_sends, pending_sendtail;
static struct netdriver_data pending_recvq[NETDRIVER_RECVQ_MAX];
static unsigned int pending_recvs, pending_recvtail;
static int pending_status;
static endpoint_t status_endpt;
static int pending_link, pending_stat;
static uint32_t stat_oerror, stat_coll, stat_ierror, stat_iqdrop;
static char device_name[NDEV_NAME_MAX];
static netdriver_addr_t device_hwaddr;
static uint32_t device_caps;
static unsigned int device_link;
static uint32_t device_media;
/*
* Announce we are up after a fresh start or restart.
*/
void
static void
netdriver_announce(void)
{
const char *driver_prefix = "drv.net.";
@ -183,240 +211,549 @@ send_reply(endpoint_t endpt, message * m_ptr)
{
int r;
if ((r = ipc_send(endpt, m_ptr)) != OK)
if ((r = asynsend(endpt, m_ptr)) != OK)
panic("netdriver: unable to send to %d: %d", endpt, r);
}
/*
* Defer sending any replies to task requests until the next call to
* check_replies(). The purpose of this is aggregation of task replies to both
* send and receive requests into a single reply message, which saves on
* messages, in particular when processing interrupts.
* A packet receive request has finished. Send a reply and clean up.
*/
static void
defer_replies(void)
finish_recv(int32_t result)
{
struct netdriver_data *data;
message m;
assert(netdriver_table != NULL);
assert(defer_reply == FALSE);
assert(pending_recvs > 0);
defer_reply = TRUE;
}
data = &pending_recvq[pending_recvtail];
/*
* Check if we have to reply to earlier task (I/O) requests, and if so, send
* the reply. If deferred is FALSE and the call to this function was preceded
* by a call to defer_replies(), do not send a reply yet. If always_send is
* TRUE, send a reply even if no tasks have completed yet.
*/
static void
check_replies(int deferred, int always_send)
{
message m_reply;
memset(&m, 0, sizeof(m));
m.m_type = NDEV_RECV_REPLY;
m.m_netdriver_ndev_reply.id = data->id;
m.m_netdriver_ndev_reply.result = result;
if (defer_reply && !deferred)
return;
send_reply(data->endpt, &m);
defer_reply = FALSE;
if (pending_flags == 0 && !always_send)
return;
assert(pending_endpt != NONE);
memset(&m_reply, 0, sizeof(m_reply));
m_reply.m_type = DL_TASK_REPLY;
m_reply.m_netdrv_net_dl_task.flags = pending_flags;
m_reply.m_netdrv_net_dl_task.count = pending_size;
send_reply(pending_endpt, &m_reply);
pending_flags = 0;
pending_size = 0;
pending_recvtail = (pending_recvtail + 1) %
__arraycount(pending_recvq);
pending_recvs--;
}
/*
* Resume receiving packets. In particular, if a receive request was pending,
* call the driver's receive function. If the call is successful, schedule
* sending a reply to the requesting party.
* call the driver's receive function. If the call is successful, send a reply
* to the requesting party.
*/
void
netdriver_recv(void)
{
struct netdriver_data *data;
ssize_t r;
if (pending_recv.size == 0)
return;
assert(netdriver_table != NULL);
/*
* For convenience of driver writers: if the receive function returns
* zero, simply call it again, to simplify discarding invalid packets.
*/
do {
r = netdriver_table->ndr_recv(&pending_recv,
pending_recv.size);
while (pending_recvs > 0) {
data = &pending_recvq[pending_recvtail];
/*
* The default policy is: drop undersized packets, panic on
* oversized packets. The driver may implement any other
* policy (e.g., pad small packets, drop or truncate large
* packets), but it should at least test against the given
* 'max' value. The reason that truncation should be
* implemented in the driver rather than here, is explained in
* an earlier comment about truncating copy operations.
* For convenience of driver writers: if the receive function
* returns zero, simply call it again, to simplify discarding
* invalid packets.
*/
if (r >= 0 && r < ETH_MIN_PACK_SIZE)
r = 0;
else if (r > (ssize_t)pending_recv.size)
panic("netdriver: oversized packet returned: %zd", r);
} while (r == 0);
do {
r = netdriver_table->ndr_recv(data, data->size);
if (r == SUSPEND)
return;
if (r < 0)
panic("netdriver: driver reported receive failure: %d", r);
/*
* The default policy is: drop undersized packets,
* panic on oversized packets. The driver may
* implement any other policy (e.g., pad small packets,
* drop or truncate large packets), but it should at
* least test against the given 'max' value. The
* reason that truncation should be implemented in the
* driver rather than here, is explained in an earlier
* comment about truncating copy operations.
*/
if (r >= 0 && r < NDEV_ETH_PACKET_MIN)
r = 0;
else if (r > (ssize_t)data->size)
panic("netdriver: oversized packet returned: "
"%zd", r);
} while (r == 0);
assert(r >= ETH_MIN_PACK_SIZE && (size_t)r <= pending_recv.size);
if (r == SUSPEND)
break;
pending_flags |= DL_PACK_RECV;
pending_size = r;
if (r < 0)
panic("netdriver: driver reported receive failure: %d",
r);
pending_recv.size = 0;
assert(r >= NDEV_ETH_PACKET_MIN && (size_t)r <= data->size);
check_replies(FALSE /*deferred*/, FALSE /*always_send*/);
finish_recv(r);
}
}
/*
* Resume sending packets. In particular, if a send request was pending, call
* the driver's send function. If the call is successful, schedule sending a
* reply to the requesting party. This function relies on being called
* between init_pending() and check_pending().
* A packet send request has finished. Send a reply and clean up.
*/
static void
finish_send(int32_t result)
{
struct netdriver_data *data;
message m;
assert(pending_sends > 0);
data = &pending_sendq[pending_sendtail];
memset(&m, 0, sizeof(m));
m.m_type = NDEV_SEND_REPLY;
m.m_netdriver_ndev_reply.id = data->id;
m.m_netdriver_ndev_reply.result = result;
send_reply(data->endpt, &m);
pending_sendtail = (pending_sendtail + 1) %
__arraycount(pending_sendq);
pending_sends--;
}
/*
* Resume sending packets. In particular, if any send requests were pending,
* call the driver's send function for each of them, until the driver can take
* no more. For each successful request is successful, send a reply to the
* requesting party.
*/
void
netdriver_send(void)
{
struct netdriver_data *data;
int r;
if (pending_send.size == 0)
return;
assert(netdriver_table != NULL);
r = netdriver_table->ndr_send(&pending_send, pending_send.size);
while (pending_sends > 0) {
data = &pending_sendq[pending_sendtail];
if (r == SUSPEND)
return;
if (r < 0)
panic("netdriver: driver reported send failure: %d", r);
r = netdriver_table->ndr_send(data, data->size);
pending_flags |= DL_PACK_SEND;
if (r == SUSPEND)
break;
pending_send.size = 0;
if (r < 0)
panic("netdriver: driver reported send failure: %d",
r);
check_replies(FALSE /*deferred*/, FALSE /*always_send*/);
finish_send(r);
}
}
/*
* Process a request to receive or send a packet.
* Process a request to send or receive a packet.
*/
static void
do_readwrite(const struct netdriver * __restrict ndp, endpoint_t endpt,
cp_grant_id_t grant, unsigned int count, int do_write)
do_transfer(const struct netdriver * __restrict ndp, const message * m_ptr,
int do_write)
{
struct netdriver_data *data;
cp_grant_id_t grant;
size_t size;
unsigned int i;
int r;
/* Copy in the I/O vector. */
data = (do_write) ? &pending_send : &pending_recv;
/* Prepare the local data structure. */
if (do_write) {
if (pending_sends == __arraycount(pending_sendq))
panic("netdriver: too many concurrent send requests");
if (data->size != 0)
panic("netdriver: multiple concurrent requests");
data = &pending_sendq[(pending_sendtail + pending_sends) %
__arraycount(pending_sendq)];
} else {
if (pending_recvs == __arraycount(pending_recvq))
panic("netdriver: too many concurrent receive "
"requests");
if (count == 0 || count > NR_IOREQS)
panic("netdriver: bad I/O vector count: %u", count);
data = &pending_recvq[(pending_recvtail + pending_recvs) %
__arraycount(pending_recvq)];
}
data->endpt = endpt;
data->count = count;
data->endpt = m_ptr->m_source;
data->id = m_ptr->m_ndev_netdriver_transfer.id;
data->count = m_ptr->m_ndev_netdriver_transfer.count;
if ((r = sys_safecopyfrom(endpt, grant, 0, (vir_bytes)data->iovec,
sizeof(data->iovec[0]) * count)) != OK)
panic("netdriver: unable to copy in I/O vector: %d", r);
if (data->count == 0 || data->count > NDEV_IOV_MAX)
panic("netdriver: bad I/O vector count: %u", data->count);
for (i = 0; i < count; i++)
data->size += data->iovec[i].iov_size;
data->size = 0;
if (data->size < ETH_MIN_PACK_SIZE ||
(!do_write && data->size < ETH_MAX_PACK_SIZE_TAGGED))
for (i = 0; i < data->count; i++) {
grant = m_ptr->m_ndev_netdriver_transfer.grant[i];
size = (size_t)m_ptr->m_ndev_netdriver_transfer.len[i];
assert(size > 0);
data->iovec[i].iov_grant = grant;
data->iovec[i].iov_size = size;
data->size += size;
}
if (data->size < NDEV_ETH_PACKET_MIN ||
(!do_write && data->size < NDEV_ETH_PACKET_MAX_TAGGED))
panic("netdriver: invalid I/O vector size: %zu\n", data->size);
/* Save the endpoint to which we should reply. */
if (pending_endpt != NONE && pending_endpt != endpt)
panic("netdriver: multiple request sources");
pending_endpt = endpt;
if (do_write)
pending_sends++;
else
pending_recvs++;
/* Resume sending or receiving. */
defer_replies();
/*
* If the driver is down, immediately abort the request again. This
* is not a common case but does occur as part of queue draining by the
* TCP/IP stack, and is way easier to handle here than up there..
*/
if (!up) {
if (do_write)
finish_send(EINTR);
else
finish_recv(EINTR);
return;
}
/* Otherwise, resume sending or receiving. */
if (do_write)
netdriver_send();
else
netdriver_recv();
/* Always send a reply in this case, even if no flags are set. */
check_replies(TRUE /*deferred*/, TRUE /*always_send*/);
}
/*
* Process a request to configure the driver, by setting its mode and obtaining
* its ethernet hardware address. We already have the latter as a result of
* calling the ndr_init callback function.
* Process a request to (re)configure the driver.
*/
static void
do_conf(const struct netdriver * __restrict ndp,
const message * __restrict m_ptr)
{
message m_reply;
netdriver_addr_t mcast_list[NETDRIVER_MCAST_MAX];
uint32_t set, mode;
unsigned int mcast_count;
message m;
int r;
if (ndp->ndr_mode != NULL)
ndp->ndr_mode(m_ptr->m_net_netdrv_dl_conf.mode);
set = m_ptr->m_ndev_netdriver_conf.set;
mode = m_ptr->m_ndev_netdriver_conf.mode;
memset(&m_reply, 0, sizeof(m_reply));
m_reply.m_type = DL_CONF_REPLY;
m_reply.m_netdrv_net_dl_conf.stat = OK; /* legacy */
memcpy(&m_reply.m_netdrv_net_dl_conf.hw_addr, &hw_addr,
sizeof(m_reply.m_netdrv_net_dl_conf.hw_addr));
/*
* If the request includes taking down the interface, perform that step
* first: it is expected that in many cases, changing other settings
* requires stopping and restarting the device.
*/
if ((set & NDEV_SET_MODE) && mode == NDEV_MODE_DOWN &&
ndp->ndr_set_mode != NULL)
ndp->ndr_set_mode(mode, NULL, 0);
send_reply(m_ptr->m_source, &m_reply);
if ((set & NDEV_SET_CAPS) && ndp->ndr_set_caps != NULL)
ndp->ndr_set_caps(m_ptr->m_ndev_netdriver_conf.caps);
if ((set & NDEV_SET_FLAGS) && ndp->ndr_set_flags != NULL)
ndp->ndr_set_flags(m_ptr->m_ndev_netdriver_conf.flags);
if ((set & NDEV_SET_MEDIA) && ndp->ndr_set_media != NULL)
ndp->ndr_set_media(m_ptr->m_ndev_netdriver_conf.media);
if ((set & NDEV_SET_HWADDR) && ndp->ndr_set_hwaddr != NULL) {
/* Save the new hardware address. */
memcpy(&device_hwaddr, m_ptr->m_ndev_netdriver_conf.hwaddr,
sizeof(device_hwaddr));
ndp->ndr_set_hwaddr(&device_hwaddr);
}
if ((set & NDEV_SET_MODE) && mode != NDEV_MODE_DOWN &&
ndp->ndr_set_mode != NULL) {
/*
* If we have a multicast list, copy it in, unless it is too
* large: in that case, enable all-multicast receipt mode.
*/
if ((mode & NDEV_MODE_MCAST_LIST) &&
m_ptr->m_ndev_netdriver_conf.mcast_count >
__arraycount(mcast_list)) {
mode &= ~NDEV_MODE_MCAST_LIST;
mode |= NDEV_MODE_MCAST_ALL;
}
if (mode & NDEV_MODE_MCAST_LIST) {
assert(m_ptr->m_ndev_netdriver_conf.mcast_grant !=
GRANT_INVALID);
mcast_count = m_ptr->m_ndev_netdriver_conf.mcast_count;
if ((r = sys_safecopyfrom(m_ptr->m_source,
m_ptr->m_ndev_netdriver_conf.mcast_grant, 0,
(vir_bytes)mcast_list,
mcast_count * sizeof(mcast_list[0]))) != OK)
panic("netdriver: unable to copy data: %d", r);
ndp->ndr_set_mode(mode, mcast_list, mcast_count);
} else
ndp->ndr_set_mode(mode, NULL, 0);
}
/* We always report OK: the caller cannot do anything upon failure. */
memset(&m, 0, sizeof(m));
m.m_type = NDEV_CONF_REPLY;
m.m_netdriver_ndev_reply.id = m_ptr->m_ndev_netdriver_conf.id;
m.m_netdriver_ndev_reply.result = OK;
send_reply(m_ptr->m_source, &m);
/*
* Finally, if the device has been taken down, abort pending send and
* receive requests.
*/
if (set & NDEV_SET_MODE) {
if (mode == NDEV_MODE_DOWN) {
while (pending_sends > 0)
finish_send(EINTR);
while (pending_recvs > 0)
finish_recv(EINTR);
up = FALSE;
} else
up = TRUE;
}
}
/*
* Process a request to obtain statistics from the driver.
* Request an update of the link state and active media of the device. This
* routine may be called both from the driver and internally.
*/
static void
do_getstat(const struct netdriver * __restrict ndp,
const message * __restrict m_ptr)
update_link(void)
{
message m_reply;
eth_stat_t st;
if (netdriver_table->ndr_get_link != NULL)
device_link = netdriver_table->ndr_get_link(&device_media);
pending_link = FALSE;
}
/*
* Attempt to send a status update to the endpoint registered to receive status
* updates, if any.
*/
static void
send_status(void)
{
message m;
int r;
memset(&st, 0, sizeof(st));
assert(pending_link || pending_stat);
if (ndp->ndr_stat != NULL)
ndp->ndr_stat(&st);
if (status_endpt == NONE || pending_status)
return;
if ((r = sys_safecopyto(m_ptr->m_source,
m_ptr->m_net_netdrv_dl_getstat_s.grant, 0, (vir_bytes)&st,
sizeof(st))) != OK)
panic("netdriver: unable to copy out statistics: %d", r);
if (pending_link)
update_link();
memset(&m_reply, 0, sizeof(m_reply));
m_reply.m_type = DL_STAT_REPLY;
memset(&m, 0, sizeof(m));
m.m_type = NDEV_STATUS;
m.m_netdriver_ndev_status.id = 0; /* for now */
m.m_netdriver_ndev_status.link = device_link;
m.m_netdriver_ndev_status.media = device_media;
m.m_netdriver_ndev_status.oerror = stat_oerror;
m.m_netdriver_ndev_status.coll = stat_coll;
m.m_netdriver_ndev_status.ierror = stat_ierror;
m.m_netdriver_ndev_status.iqdrop = stat_iqdrop;
send_reply(m_ptr->m_source, &m_reply);
if ((r = asynsend3(status_endpt, &m, AMF_NOREPLY)) != OK)
panic("netdriver: unable to send status: %d", r);
/*
* Do not send another status message until either the one we just sent
* gets acknowledged or we get a new initialization request. This way
* we get "natural pacing" (i.e., we avoid overflowing the asynsend
* message queue by design) without using timers.
*/
pending_status = TRUE;
/*
* The status message sends incremental updates for statistics. This
* means that while a restart of the TCP/IP stack means the statistics
* are lost (not great), a restart of the driver leaves the statistics
* mostly intact (more important).
*/
stat_oerror = 0;
stat_coll = 0;
stat_ierror = 0;
stat_iqdrop = 0;
pending_stat = FALSE;
}
/*
* Process a reply to a status update that we sent earlier on (supposedly).
*/
static void
do_status_reply(const struct netdriver * __restrict ndp __unused,
const message * __restrict m_ptr)
{
if (m_ptr->m_source != status_endpt)
return;
if (!pending_status || m_ptr->m_ndev_netdriver_status_reply.id != 0)
panic("netdriver: unexpected status reply");
pending_status = FALSE;
/*
* If the local status has changed since our last status update,
* send a new one right away.
*/
if (pending_link || pending_stat)
send_status();
}
/*
* The driver reports that the link state and/or active media may have changed.
* When convenient, request the new state from the driver and send a status
* message to the TCP/IP stack.
*/
void
netdriver_link(void)
{
pending_link = TRUE;
send_status();
}
/*
* The driver reports that a number of output errors have occurred. Update
* statistics accordingly.
*/
void
netdriver_stat_oerror(uint32_t count)
{
if (count == 0)
return;
stat_oerror += count;
pending_stat = TRUE;
send_status();
}
/*
* The driver reports that one or more packet collisions have occurred. Update
* statistics accordingly.
*/
void
netdriver_stat_coll(uint32_t count)
{
if (count == 0)
return;
stat_coll += count;
pending_stat = TRUE;
send_status();
}
/*
* The driver reports that a number of input errors have occurred. Adjust
* statistics accordingly.
*/
void
netdriver_stat_ierror(uint32_t count)
{
if (count == 0)
return;
stat_ierror += count;
pending_stat = TRUE;
send_status();
}
/*
* The driver reports that a number of input queue drops have occurred. Update
* statistics accordingly.
*/
void
netdriver_stat_iqdrop(uint32_t count)
{
if (count == 0)
return;
stat_iqdrop += count;
pending_stat = TRUE;
send_status();
}
/*
* Process an initialization request. Actual initialization has already taken
* place, so we simply report the information gathered at that time. If the
* caller (the TCP/IP stack) has crashed and restarted, we will get another
* initialization request message, so keep the information up-to-date.
*/
static void
do_init(const struct netdriver * __restrict ndp,
const message * __restrict m_ptr)
{
message m;
/*
* First of all, an initialization request is a sure indication that
* the caller does not have any send or receive requests pending, and
* will not acknowledge our previous status request, if any. Forget
* any such previous requests and start sending status requests to the
* (new) endpoint.
*/
pending_sends = 0;
pending_recvs = 0;
pending_status = FALSE;
status_endpt = m_ptr->m_source;
/*
* Update link and media now, because we are about to send the initial
* values of those to the caller as well.
*/
update_link();
memset(&m, 0, sizeof(m));
m.m_type = NDEV_INIT_REPLY;
m.m_netdriver_ndev_init_reply.id = m_ptr->m_ndev_netdriver_init.id;
m.m_netdriver_ndev_init_reply.link = device_link;
m.m_netdriver_ndev_init_reply.media = device_media;
m.m_netdriver_ndev_init_reply.caps = device_caps;
strlcpy(m.m_netdriver_ndev_init_reply.name, device_name,
sizeof(m.m_netdriver_ndev_init_reply.name));
assert(sizeof(device_hwaddr) <=
sizeof(m.m_netdriver_ndev_init_reply.hwaddr));
memcpy(m.m_netdriver_ndev_init_reply.hwaddr, &device_hwaddr,
sizeof(device_hwaddr));
m.m_netdriver_ndev_init_reply.hwaddr_len = sizeof(device_hwaddr);
m.m_netdriver_ndev_init_reply.max_send = __arraycount(pending_sendq);
m.m_netdriver_ndev_init_reply.max_recv = __arraycount(pending_recvq);
send_reply(m_ptr->m_source, &m);
/*
* Also send the current status. This is not required by the protocol
* and only serves to provide updated statistics to a new TCP/IP stack
* instance right away.
*/
if (pending_stat)
send_status();
}
/*
@ -431,17 +768,18 @@ netdriver_process(const struct netdriver * __restrict ndp,
/* Check for notifications first. */
if (is_ipc_notify(ipc_status)) {
defer_replies();
switch (_ENDPOINT_P(m_ptr->m_source)) {
switch (m_ptr->m_source) {
case HARDWARE:
if (ndp->ndr_intr != NULL)
ndp->ndr_intr(m_ptr->m_notify.interrupts);
break;
case CLOCK:
if (ndp->ndr_alarm != NULL)
ndp->ndr_alarm(m_ptr->m_notify.timestamp);
if (ndp->ndr_tick != NULL)
ndp->ndr_tick();
if (ticks > 0)
(void)sys_setalarm(ticks, FALSE /*abs_time*/);
break;
default:
@ -449,62 +787,83 @@ netdriver_process(const struct netdriver * __restrict ndp,
ndp->ndr_other(m_ptr, ipc_status);
}
/*
* Any of the above calls may end up invoking netdriver_send()
* and/or netdriver_recv(), which may in turn have deferred
* sending a reply to an earlier request. See if we have to
* send the reply now.
*/
check_replies(TRUE /*deferred*/, FALSE /*always_send*/);
return;
}
/*
* Discard datalink requests preceding a first DL_CONF request, so that
* after a driver restart, any in-flight request is discarded. This is
* a rather blunt approach and must be revised if the protocol is ever
* made less inefficient (i.e. not strictly serialized). Note that for
* correct driver operation it is important that non-datalink requests,
* interrupts in particular, do not go through this check.
* Discard datalink requests preceding a first NDEV_INIT request, so
* that after a driver restart, any in-flight request is discarded.
* Note that for correct driver operation it is important that
* non-datalink requests, and interrupts in particular, do not go
* through this check.
*/
if (IS_DL_RQ(m_ptr->m_type) && conf_expected) {
if (m_ptr->m_type != DL_CONF)
if (IS_NDEV_RQ(m_ptr->m_type) && init_expected) {
if (m_ptr->m_type != NDEV_INIT)
return; /* do not send a reply */
conf_expected = FALSE;
init_expected = FALSE;
}
switch (m_ptr->m_type) {
case DL_CONF:
case NDEV_INIT:
do_init(ndp, m_ptr);
break;
case NDEV_CONF:
do_conf(ndp, m_ptr);
break;
case DL_GETSTAT_S:
do_getstat(ndp, m_ptr);
case NDEV_SEND:
do_transfer(ndp, m_ptr, TRUE /*do_write*/);
break;
case DL_READV_S:
do_readwrite(ndp, m_ptr->m_source,
m_ptr->m_net_netdrv_dl_readv_s.grant,
m_ptr->m_net_netdrv_dl_readv_s.count, FALSE /*do_write*/);
case NDEV_RECV:
do_transfer(ndp, m_ptr, FALSE /*do_write*/);
break;
case DL_WRITEV_S:
do_readwrite(ndp, m_ptr->m_source,
m_ptr->m_net_netdrv_dl_writev_s.grant,
m_ptr->m_net_netdrv_dl_writev_s.count, TRUE /*do_write*/);
case NDEV_STATUS_REPLY:
do_status_reply(ndp, m_ptr);
break;
default:
defer_replies();
if (ndp->ndr_other != NULL)
ndp->ndr_other(m_ptr, ipc_status);
/* As above: see if we have to send a reply now. */
check_replies(TRUE /*deferred*/, FALSE /*always_send*/);
}
}
/*
* Set a name for the device, based on the base name 'base' and the instance
* number 'instance'.
*/
static void
netdriver_set_name(const char * base, unsigned int instance)
{
size_t len;
assert(instance <= 255);
len = strlen(base);
assert(len <= sizeof(device_name) - 4);
memcpy(device_name, base, len);
if (instance >= 100)
device_name[len++] = '0' + instance / 100;
if (instance >= 10)
device_name[len++] = '0' + (instance % 100) / 10;
device_name[len++] = '0' + instance % 10;
device_name[len] = 0;
}
/*
* Return the device name generated at driver initialization time.
*/
const char *
netdriver_name(void)
{
return device_name;
}
/*
* Perform initialization. Return OK or an error code.
*/
@ -516,44 +875,63 @@ netdriver_init(const struct netdriver * ndp)
int r;
/* Initialize global variables. */
pending_recv.size = 0;
pending_send.size = 0;
pending_endpt = NONE;
defer_reply = FALSE;
pending_flags = 0;
pending_size = 0;
conf_expected = TRUE;
pending_sendtail = 0;
pending_sends = 0;
pending_recvtail = 0;
pending_recvs = 0;
/* Get the card instance number. */
memset(device_name, 0, sizeof(device_name));
memset(&device_hwaddr, 0, sizeof(device_hwaddr));
device_caps = 0;
/* Use sensible defaults for the link state and active media. */
device_link = NDEV_LINK_UNKNOWN;
device_media = IFM_MAKEWORD(IFM_ETHER, IFM_AUTO, 0, 0);
status_endpt = NONE;
pending_status = FALSE;
pending_link = FALSE;
up = FALSE;
ticks = 0;
/* Get the device instance number. */
v = 0;
(void)env_parse("instance", "d", 0, &v, 0, 255);
instance = (unsigned int)v;
/* Call the initialization routine. */
memset(&hw_addr, 0, sizeof(hw_addr));
/* Generate the full driver name. */
netdriver_set_name(ndp->ndr_name, instance);
if (ndp->ndr_init != NULL &&
(r = ndp->ndr_init(instance, &hw_addr)) != OK)
/* Call the initialization routine. */
if ((r = ndp->ndr_init(instance, &device_hwaddr, &device_caps,
&ticks)) != OK)
return r;
/* Announce we are up! */
netdriver_announce();
init_expected = TRUE;
running = TRUE;
if (ticks > 0)
(void)sys_setalarm(ticks, FALSE /*abs_time*/);
return OK;
}
/*
* SEF initialization function.
* Perform SEF initialization.
*/
static int
do_init(int __unused type, sef_init_info_t * __unused info)
local_init(int type __unused, sef_init_info_t * info __unused)
{
const struct netdriver *ndp;
ndp = netdriver_table;
assert(ndp != NULL);
assert(netdriver_table != NULL);
return netdriver_init(ndp);
return netdriver_init(netdriver_table);
}
/*
@ -594,18 +972,14 @@ netdriver_task(const struct netdriver * ndp)
int r, ipc_status;
/* Perform SEF initialization. */
sef_setcb_init_fresh(do_init);
sef_setcb_init_fresh(local_init);
sef_setcb_signal_handler(got_signal);
netdriver_table = ndp;
sef_startup();
netdriver_table = NULL;
/* The main message loop. */
running = TRUE;
while (running) {
if ((r = sef_receive_status(ANY, &mess, &ipc_status)) != OK) {
if (r == EINTR)

View File

@ -4,9 +4,10 @@
/* Data (I/O) structure. */
struct netdriver_data {
endpoint_t endpt;
uint32_t id;
size_t size;
unsigned int count;
iovec_s_t iovec[NR_IOREQS];
iovec_s_t iovec[NDEV_IOV_MAX];
};
size_t netdriver_prepare_copy(struct netdriver_data *data, size_t offp,

View File

@ -21,7 +21,6 @@ SRCS+= \
env_get_prm.c \
env_panic.c \
env_parse.c \
env_prefix.c \
fkey_ctl.c \
getepinfo.c \
getprocnr.c \

View File

@ -1,29 +0,0 @@
#include "sysutil.h"
#include <stdlib.h>
#include <string.h>
/*=========================================================================*
* env_prefix *
*=========================================================================*/
int env_prefix(const char *env, const char *prefix)
{
/* An environment setting may be prefixed by a word, usually "pci".
* - env: environment variable to inspect
* - prefix: prefix to test for
* Return TRUE if a given prefix is used.
*/
char value[EP_BUF_SIZE];
char punct[] = ":,;.";
int s;
size_t n;
if ((s = env_get_param(env, value, sizeof(value))) != 0) {
if (s != ESRCH) /* only error allowed */
printf("WARNING: env_get_param() failed in env_prefix(): %d\n", s);
return FALSE;
}
n = strlen(prefix);
return(strncmp(value, prefix, n) == 0
&& strchr(punct, value[n]) != NULL);
}