#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
#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 */
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 {
#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
};
/*
#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
* 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];
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);
/*
* 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)
{
default: return "(unknown)";
}
}
-#endif /* VERBOSE || XLBC_FKEY */
+#endif /* VERBOSE */
/*
* Determine the current link status, and return the resulting link type.
* 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);
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
* 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;
* 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)
/* 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;
}
* 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);
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);
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;
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;
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;
}
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);
}
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);
(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.
*/
*/
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();
* 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();
}
/*
- * 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 */
}
/*
#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 */
DPADD+= ${LIBNETDRIVER} ${LIBSYS}
LDADD+= -lnetdriver -lsys
+WARNS?= 5
+
.include <minix.service.mk>
DPADD+= ${LIBNETDRIVER} ${LIBSYS}
LDADD+= -lnetdriver -lsys
+WARNS?= 5
+
.include <minix.service.mk>
#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
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)))
#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
};
/*
}
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;
}
* 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.
*/
*res = (uint16_t)(rval & ATL2_MDIO_DATA_MASK);
return TRUE;
}
+#endif
/*
* Allocate DMA ring buffers.
* 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);
/* 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;
}
/* 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);
{
uint16_t vid, did;
#if VERBOSE
- char *dname;
+ const char *dname;
#endif
int r, devind;
#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
* 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;
{
if (stat & ATL2_TXS_SUCCESS)
- state.stat.ets_packetT++;
+ return;
+
+ if (stat & (ATL2_TXS_SINGLECOL | ATL2_TXS_MULTICOL | ATL2_TXS_LATECOL))
+ netdriver_stat_coll(1);
else
- state.stat.ets_recvErr++;
-
- 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++;
+ netdriver_stat_oerror(1);
}
/*
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);
}
/*
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);
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);
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;
}
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;
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)
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 |
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.
*/
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));
/* 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;
}
# 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) */
CPPFLAGS+= -Ddebug=0
+WARNS?= 5
+
.include <minix.service.mk>
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.
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
};
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);
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;
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;
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;
}
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)
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;
/* 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"));
}
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;
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;
io_outl(CSR_ADDR(dep, CSR1), 0xFFFFFFFF);
- dep->de_stat.ets_packetT++;
-
return OK;
}
#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
} 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)*
#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"
/* 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);
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);
/* 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;
DPADD+= ${LIBNETDRIVER} ${LIBSYS}
LDADD+= -lnetdriver -lsys
+WARNS?= 5
+
.include <minix.service.mk>
#include <minix/drivers.h>
#include <minix/netdriver.h>
-#include <net/hton.h>
#include <sys/mman.h>
#include "assert.h"
#include "dp8390.h"
static dpeth_t de_state;
-static int de_instance;
u32_t system_hz;
*/
#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,
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
};
/*===========================================================================*
/*===========================================================================*
* 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);
-
- dp_init(dep);
+ conf_hw(dep, instance);
- 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;
}
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,
}
#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++;
}
}
/*===========================================================================*
- * 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;
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);
}
/*===========================================================================*
/*===========================================================================*
* dp_init *
*===========================================================================*/
-static void dp_init(dpeth_t *dep)
+static void dp_init(dpeth_t *dep, unsigned int instance)
{
int i, r;
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');
}
/* 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);
/*===========================================================================*
* dp_confaddr *
*===========================================================================*/
-static void dp_confaddr(dpeth_t *dep)
+static void dp_confaddr(dpeth_t *dep, unsigned int instance)
{
int i;
char eakey[16];
/* 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 */
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))
{
* 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;
/* 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;
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 */
*/
#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 */
(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), ð_type);
+ 2*sizeof(netdriver_addr_t), sizeof(eth_type),
+ ð_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)
/* 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)
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);
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)
/*===========================================================================*
* 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);
/*===========================================================================*
* 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";
}
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;
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 */
/* 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;
#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"
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;
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);
}
}
if (debug)
{
printf("%s: NE1000 remote DMA test failed\n",
- dep->de_name);
+ netdriver_name());
}
return 0;
}
if (debug)
{
printf("%s: NE2000 remote DMA test failed\n",
- dep->de_name);
+ netdriver_name());
}
return 0;
}
#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"
u16_t vid, did;
u32_t bar;
u8_t ilr;
- char *dname;
+ const char *dname;
pci_init();
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)); */
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;
#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"
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;
((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;
((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;
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
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",
{
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 ||
#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)
*/
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);
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);
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
{
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);
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));
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);
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 */
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)
*/
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;
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 */
*/
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);
#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)
*/
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 */
/* 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);
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');
}
#include <minix/drivers.h>
#include <minix/netdriver.h>
-#include <net/gen/ether.h>
-#include <net/gen/eth_io.h>
#include "dp.h"
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);
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);
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 */
(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);
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)
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 */
/* 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;
}
}
/* 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) {
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');
}
#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"
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);
}
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));
}
/*
*/
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)
*/
static void ns_reset(dpeth_t * dep)
{
- int ix;
+ unsigned int ix;
/* Stop chip */
outb_reg0(dep, DP_CR, CR_STP | CR_NO_DMA);
&header);
#ifdef ETH_IGN_PROTO
(dep->de_getblockf)(dep, pageno * DP_PAGESIZE + sizeof(header) +
- 2 * sizeof(ether_addr_t), sizeof(eth_type), ð_type);
+ 2 * sizeof(netdriver_addr_t), sizeof(eth_type), ð_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) {
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) {
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;
static void ns_interrupt(dpeth_t * dep)
{
int isr, tsr;
- int queue;
+ unsigned int queue;
while ((isr = inb_reg0(dep, DP_ISR)) != 0) {
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;
}
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 */
* 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;
}
*/
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 */
/* 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);
CPPFLAGS+= -DVERBOSE=0
+WARNS?= 5
+
.include <minix.service.mk>
#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)
#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>
{ 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
};
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);
/* 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);
}
/*
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);
** 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;
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);
!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;
}
/* 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);
}
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.
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.
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;
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) */
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 {
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;
#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)
*/
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) {
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');
}
*/
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;
/* 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 */
#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)
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;
}
}
#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)
*===========================================================================*/
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;
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);
}
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);
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;
* 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);
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;
DPADD+= ${LIBNETDRIVER} ${LIBSYS}
LDADD+= -lnetdriver -lsys
+WARNS?= 5
+
.include <minix.service.mk>
#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);
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
};
/*
* 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;
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)
/* 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;
}
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();
/* 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;
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);
/* 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;
* 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";
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]));
}
/*
* 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;
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.
*/
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;
}
/*
- * 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;
-
- E1000_DEBUG(3, ("e1000: stat()\n"));
-
- 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;
-}
+ uint32_t status, type;
-/*
- * Link status has changed. Nothing to do for now.
- */
-static void
-e1000_link_changed(e1000_t * e)
-{
+ status = e1000_reg_read(&e1000_state, E1000_REG_STATUS);
+
+ if (!(status & E1000_REG_STATUS_LU))
+ return NDEV_LINK_DOWN;
+
+ if (status & E1000_REG_STATUS_FD)
+ type = IFM_ETHER | IFM_FDX;
+ else
+ type = IFM_ETHER | IFM_HDX;
+
+ 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;
+ }
- E1000_DEBUG(4, ("%s: link_changed()\n", e->name));
+ *media = type;
+ return NDEV_LINK_UP;
}
/*
/* 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();
}
}
+/*
+ * 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.
*/
e = &e1000_state;
- E1000_DEBUG(3, ("%s: stop()\n", e->name));
+ E1000_DEBUG(3, ("%s: stop()\n", netdriver_name()));
e1000_reset_hw(e);
}
*/
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. */
/** 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 */
+
/**
* @}
*/
/** 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. */
DPADD+= ${LIBNETDRIVER} ${LIBSYS}
LDADD+= -lnetdriver -lsys
+WARNS?= 5
+
.include <minix.service.mk>
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 */
#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)))
#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);
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);
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,
};
/*===========================================================================*
/* 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);
/*===========================================================================*
* 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");
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;
}
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();
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);
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);
#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)
/*===========================================================================*
* 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;
fxp_ru_ptr_cmd(fp, SC_RU_START, fp->fxp_rx_busaddr,
TRUE /* check idle */);
- fxp_confaddr(fp, addr);
+ fxp_confaddr(fp, addr, instance);
}
/*===========================================================================*
/*===========================================================================*
* 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";
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 */
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);
}
}
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);
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;
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 */
}
/*===========================================================================*
- * 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;
/* 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);
}
/*===========================================================================*
}
}
- 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);
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 *
*===========================================================================*/
if (!link_up)
{
#if VERBOSE
- printf("%s: link down\n", fp->fxp_name);
+ printf("%s: link down\n", netdriver_name());
#endif
return;
}
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");
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;
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-");
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))
{
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",
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)
#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
}
#if VERBOSE
printf("%s EEPROM address length: %d\n",
- fp->fxp_name, fp->fxp_ee_addrlen);
+ netdriver_name(), fp->fxp_ee_addrlen);
#endif
}
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 */
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 */
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);
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);
/* 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[]) {
}
/* 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 */
/* ### 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:
}
/* 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 ### */
/* 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);
}
/* 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 ### */
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;
}
/* 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 */
}
/* 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
}
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--;
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
DPADD+= ${LIBNETDRIVER} ${LIBSYS}
LDADD+= -lnetdriver -lsys
+WARNS?= 5
+
.include <minix.service.mk>
#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);
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
};
/*============================================================================*
* 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;
}
* 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";
/*
* 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;
/*
* 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;
}
/*============================================================================*
}
/*============================================================================*
- * lan8710a_stat *
+ * lan8710a_update_stats *
+ *============================================================================*/
+static void
+lan8710a_update_stats(void)
+{
+ 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_stat(eth_stat_t * stat)
+lan8710a_tick(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;
+
+ /* Update statistics. */
+ lan8710a_update_stats();
}
/*============================================================================*
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. */
&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));
&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));
* 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;
lan8710a_init_mdio();
/* Getting MAC Address */
- lan8710a_init_addr(addr);
+ lan8710a_init_addr(addr, instance);
/* Initialize descriptors */
lan8710a_init_desc();
/* 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;
}
#ifndef LAN8710A_H_
#define LAN8710A_H_
-#include <net/gen/ether.h>
-
#define LAN8710A_DEBUG (1)
#if LAN8710A_DEBUG == 1
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 */
DPADD+= ${LIBNETDRIVER} ${LIBSYS}
LDADD+= -lnetdriver -lsys
+WARNS?= 5
+
.include <minix.service.mk>
#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>
#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);
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 */
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,
};
/*===========================================================================*
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);
/*===========================================================================*
* 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];
/* 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)
/*===========================================================================*
* 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
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;
}
}
/* 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);
}
}
/*===========================================================================*
- * 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);
}
#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))
{
#if VERBOSE
printf("TX Timeout\n");
#endif
- ec->eth_stat.ets_sendErr++;
+ netdriver_stat_oerror(1);
}
if (isr & LANCE_CSR0_TINT)
{
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. */
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;
}
return OK;
}
-/*===========================================================================*
- * do_stat *
- *===========================================================================*/
-static void do_stat(eth_stat_t *stat)
-{
-
- memcpy(stat, &ec_state.eth_stat, sizeof(*stat));
-}
-
/*===========================================================================*
* do_stop *
*===========================================================================*/
#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
/*===========================================================================*
* 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;
/* ============= 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 */
/* ----- 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++)
{
}
/* 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);
}
-/* 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;
CPPFLAGS+= -I${NETBSDSRCDIR}/minix
+WARNS?= 5
+
.include <minix.service.mk>
static re_t re_state;
-static int re_instance;
-
static unsigned my_inb(u16_t port) {
u32_t value;
int s;
#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,
};
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),
}
/*===========================================================================*
- * 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;
/*===========================================================================*
* 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;
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))
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);
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;
}
u32_t bar;
u8_t ilr;
#if VERBOSE
- char *dname;
+ const char *dname;
#endif
pci_init();
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);
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;
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;
/*===========================================================================*
* 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;
#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
}
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);
}
/*===========================================================================*
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;
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(
}
/* 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;
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 *
*===========================================================================*/
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;
}
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)
{
}
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;
}
#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;
rl_rec_mode(rep);
- rep->re_stat.ets_missedP++;
+ netdriver_stat_ierror(1);
}
/*===========================================================================*
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 *
{
isr &= ~RL_IMR_FOVW;
/* Should do anything? */
-
- rep->re_stat.ets_fifoOver++;
}
if (isr & RL_IMR_PUN)
{
/* 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);
}
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.
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;
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;
}
/*===========================================================================*
- * 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);
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),
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;
/*
CPPFLAGS+= -I${NETBSDSRCDIR}/minix
+WARNS?= 5
+
.include <minix.service.mk>
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;
#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
};
/*===========================================================================*
/*===========================================================================*
* 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;
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;
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;
}
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);
}
/* 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
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");
#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;
u32_t bar;
u8_t ilr;
#if VERBOSE
- char *dname;
+ const char *dname;
#endif
pci_init();
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
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;
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;
/*===========================================================================*
* 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
#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
/*===========================================================================*
* 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);
}
/*===========================================================================*
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);
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;
}
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);
}
/* 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);
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 *
*===========================================================================*/
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;
}
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)
{
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;
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;
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 */
break;
}
- rep->re_stat.ets_packetT++;
rep->re_tx[tx_tail].ret_busy = FALSE;
rep->re_tx_busy--;
}
/*===========================================================================*
- * 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 */
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;
DPADD+= ${LIBNETDRIVER} ${LIBSYS} ${LIBVIRTIO}
LDADD+= -lnetdriver -lsys -lvirtio
+WARNS?= 5
+
.include <minix.service.mk>
#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>
#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
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 */
*/
#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)
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);
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,
};
{
/* 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)
}
static void
-virtio_net_config(ether_addr_t * addr)
+virtio_net_config(netdriver_addr_t * addr)
{
u32_t mac14;
u32_t mac56;
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"));
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
p->len = len;
STAILQ_INSERT_TAIL(&recv_list, p, next);
in_rx--;
- virtio_net_stats.ets_packetR++;
}
/*
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++;
}
}
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);
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);
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;
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();
virtio_irq_enable(net_dev);
- return(OK);
+ *caps = NDEV_CAP_MCAST | NDEV_CAP_BCAST;
+ return OK;
}
/*
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);
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);
* -- 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 ###)
/* 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[]) {
}
/* 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 */
/* ### 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:
}
/* 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 ### */
/* 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);
}
/* 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 ### */
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;
}
/* 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 */
}
/* 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
}
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--;
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
* 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.
*/
# 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 *
*===========================================================================*/
#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 */
*/
#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 */
} 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;
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;
-/* 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 */
* 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
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);
SRCS= netdriver.c portio.c
+WARNS?= 5
+
.include <bsd.lib.mk>
/* 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 int up;
+
+static unsigned int ticks;
-static endpoint_t pending_endpt;
-static struct netdriver_data pending_recv, pending_send;
+static struct netdriver_data pending_sendq[NETDRIVER_SENDQ_MAX];
+static unsigned int pending_sends, pending_sendtail;
-static int defer_reply;
-static unsigned int pending_flags;
-static size_t pending_size;
+static struct netdriver_data pending_recvq[NETDRIVER_RECVQ_MAX];
+static unsigned int pending_recvs, pending_recvtail;
-static ether_addr_t hw_addr;
+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.";
{
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);
-
- defer_reply = TRUE;
-}
-
-/*
- * 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;
-
- if (defer_reply && !deferred)
- return;
-
- defer_reply = FALSE;
+ assert(pending_recvs > 0);
- if (pending_flags == 0 && !always_send)
- return;
+ data = &pending_recvq[pending_recvtail];
- assert(pending_endpt != NONE);
+ 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;
- 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(data->endpt, &m);
- 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);
+
+ /*
+ * 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);
+
+ if (r == SUSPEND)
+ break;
- if (r == SUSPEND)
- return;
- if (r < 0)
- panic("netdriver: driver reported receive failure: %d", r);
+ if (r < 0)
+ panic("netdriver: driver reported receive failure: %d",
+ r);
+
+ assert(r >= NDEV_ETH_PACKET_MIN && (size_t)r <= data->size);
+
+ finish_recv(r);
+ }
+}
+
+/*
+ * 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);
- assert(r >= ETH_MIN_PACK_SIZE && (size_t)r <= pending_recv.size);
+ data = &pending_sendq[pending_sendtail];
- pending_flags |= DL_PACK_RECV;
- pending_size = r;
+ 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;
- pending_recv.size = 0;
+ send_reply(data->endpt, &m);
- check_replies(FALSE /*deferred*/, FALSE /*always_send*/);
+ pending_sendtail = (pending_sendtail + 1) %
+ __arraycount(pending_sendq);
+ pending_sends--;
}
/*
- * 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().
+ * 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");
+
+ data = &pending_recvq[(pending_recvtail + pending_recvs) %
+ __arraycount(pending_recvq)];
+ }
- if (count == 0 || count > NR_IOREQS)
- panic("netdriver: bad I/O vector count: %u", 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;
- data->endpt = endpt;
- data->count = count;
+ if (data->count == 0 || data->count > NDEV_IOV_MAX)
+ panic("netdriver: bad I/O vector count: %u", data->count);
+
+ data->size = 0;
+
+ 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];
- 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);
+ assert(size > 0);
- for (i = 0; i < count; i++)
- data->size += data->iovec[i].iov_size;
+ data->iovec[i].iov_grant = grant;
+ data->iovec[i].iov_size = size;
+ data->size += size;
+ }
- if (data->size < ETH_MIN_PACK_SIZE ||
- (!do_write && data->size < ETH_MAX_PACK_SIZE_TAGGED))
+ 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;
+
+ set = m_ptr->m_ndev_netdriver_conf.set;
+ mode = m_ptr->m_ndev_netdriver_conf.mode;
+
+ /*
+ * 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);
- if (ndp->ndr_mode != NULL)
- ndp->ndr_mode(m_ptr->m_net_netdrv_dl_conf.mode);
+ 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);
+ }
- 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));
+ /* 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_reply);
+ 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)
+{
+
+ 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_reply;
- eth_stat_t st;
+ message m;
int r;
- memset(&st, 0, sizeof(st));
+ assert(pending_link || pending_stat);
+
+ if (status_endpt == NONE || pending_status)
+ return;
- if (ndp->ndr_stat != NULL)
- ndp->ndr_stat(&st);
+ if (pending_link)
+ update_link();
- 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);
+ 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;
- memset(&m_reply, 0, sizeof(m_reply));
- m_reply.m_type = DL_STAT_REPLY;
+ if ((r = asynsend3(status_endpt, &m, AMF_NOREPLY)) != OK)
+ panic("netdriver: unable to send status: %d", r);
- send_reply(m_ptr->m_source, &m_reply);
+ /*
+ * 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();
}
/*
/* 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:
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.
*/
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;
-
- /* Get the card instance number. */
+ pending_sendtail = 0;
+ pending_sends = 0;
+ pending_recvtail = 0;
+ pending_recvs = 0;
+
+ 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);
}
/*
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)
/* 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,
env_get_prm.c \
env_panic.c \
env_parse.c \
- env_prefix.c \
fkey_ctl.c \
getepinfo.c \
getprocnr.c \
+++ /dev/null
-#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);
-}
-