cd ./bios_wini && $(MAKE) $@
cd ./cmos && $(MAKE) $@
cd ./random && $(MAKE) $@
+ cd ./dp8390 && $(MAKE) $@
--- /dev/null
+/*
+ * 3c503.c A shared memory driver for Etherlink II board.
+ *
+ * Created: Dec. 20, 1996 by G. Falzoni <falzoni@marina.scn.de>
+ *
+ * Inspired by the TNET package by M. Ostrowski, the driver for Linux
+ * by D. Becker, the Crynwr 3c503 packet driver, and the Amoeba driver.
+ *
+ * It works in shared memory mode and should be used with the
+ * device driver for NS 8390 based cards of Minix. Programmed
+ * I/O could be used as well but would result in poor performance.
+ */
+
+#include "../drivers.h"
+
+#include <net/gen/ether.h>
+#include <net/gen/eth_io.h>
+
+#include "local.h"
+#include "dp8390.h"
+#include "3c503.h"
+
+#if ENABLE_3C503
+
+#define MILLIS_TO_TICKS(m) (((m)*HZ/1000)+1)
+
+_PROTOTYPE(static void el2_init, (dpeth_t *dep));
+_PROTOTYPE(static void el2_stop, (dpeth_t *dep));
+_PROTOTYPE( static void milli_delay, (unsigned long millis) );
+
+
+/*===========================================================================*
+ * el2_init *
+ *===========================================================================*/
+static void el2_init(dep)
+dpeth_t * dep;
+{
+ /* Initalize hardware and data structures. */
+ int ix, irq;
+ int sendq_nr;
+ int cntr;
+
+ /* Map the address PROM to lower I/O address range */
+ cntr = inb_el2(dep, EL2_CNTR);
+ outb_el2(dep, EL2_CNTR, cntr | ECNTR_SAPROM);
+
+ /* Read station address from PROM */
+ for (ix = EL2_EA0; ix <= EL2_EA5; ix += 1)
+ dep->de_address.ea_addr[ix] = inb_el2(dep, ix);
+
+ /* Map the 8390 back to lower I/O address range */
+ outb_el2(dep, EL2_CNTR, cntr);
+
+ /* Enable memory, but turn off interrupts until we are ready */
+ outb_el2(dep, EL2_CFGR, ECFGR_IRQOFF);
+
+ dep->de_data_port = dep->de_dp8390_port = dep->de_base_port;
+ dep->de_prog_IO = 0; /* Programmed I/O not yet available */
+
+ /* Check width of data bus:
+ * 1. Write 0 to WTS bit. The board will drive it to 1 if it is a
+ * 16-bit card.
+ * 2. Select page 2
+ * 3. See if it is a 16-bit card
+ * 4. Select page 0
+ */
+ outb_el2(dep, DP_CR, CR_PS_P0|CR_DM_ABORT|CR_STP);
+ outb_el2(dep, DP_DCR, 0);
+ outb_el2(dep, DP_CR, CR_PS_P2|CR_DM_ABORT|CR_STP);
+ dep->de_16bit = (inb_el2(dep, DP_DCR) & DCR_WTS) != 0;
+ outb_el2(dep, DP_CR, CR_PS_P0|CR_DM_ABORT|CR_STP);
+
+ /* Allocate one send buffer (1.5KB) per 8KB of on board memory. */
+ sendq_nr = (dep->de_ramsize - dep->de_offset_page) / 0x2000;
+ if (sendq_nr < 1)
+ sendq_nr = 1;
+ else if (sendq_nr > SENDQ_NR)
+ sendq_nr = SENDQ_NR;
+
+ dep->de_sendq_nr = sendq_nr;
+ for (ix = 0; ix < sendq_nr; ix++)
+ dep->de_sendq[ix].sq_sendpage = (ix * SENDQ_PAGES) + EL2_SM_START_PG;
+
+ dep->de_startpage = (ix * SENDQ_PAGES) + EL2_SM_START_PG;
+ dep->de_stoppage = EL2_SM_STOP_PG;
+
+ outb_el2(dep, EL2_STARTPG, dep->de_startpage);
+ outb_el2(dep, EL2_STOPPG, dep->de_stoppage);
+
+ /* Point the vector pointer registers somewhere ?harmless?. */
+ outb_el2(dep, EL2_VP2, 0xFF); /* Point at the ROM restart location */
+ outb_el2(dep, EL2_VP1, 0xFF); /* 0xFFFF:0000 (from original sources) */
+ outb_el2(dep, EL2_VP0, 0x00); /* - What for protected mode? */
+
+ /* Set interrupt level for 3c503 */
+ irq = (dep->de_irq &= ~DEI_DEFAULT); /* Strip the default flag. */
+ if (irq == 9) irq = 2;
+ if (irq < 2 || irq > 5) panic("", "bad 3c503 irq configuration", irq);
+ outb_el2(dep, EL2_IDCFG, (0x04 << irq));
+
+ outb_el2(dep, EL2_DRQCNT, 0x08); /* Set burst size to 8 */
+ outb_el2(dep, EL2_DMAAH, EL2_SM_START_PG); /* Put start of TX */
+ outb_el2(dep, EL2_DMAAL, 0x00); /* buffer in the GA DMA reg */
+
+ outb_el2(dep, EL2_CFGR, ECFGR_NORM); /* Enable shared memory */
+
+ if (!debug) {
+ printf("%s: 3c503 at %X:%d:%lX\n",
+ dep->de_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) " : "",
+ dep->de_base_port,
+ dep->de_linmem + dep->de_offset_page,
+ dep->de_irq);
+ }
+}
+
+
+/*===========================================================================*
+ * el2_stop *
+ *===========================================================================*/
+static void el2_stop(dep)
+dpeth_t * dep;
+{
+ /* Stops board by disabling interrupts. */
+
+#if DEBUG
+ printf("%s: stopping Etherlink\n", dep->de_name);
+#endif
+ outb_el2(dep, EL2_CFGR, ECFGR_IRQOFF);
+ return;
+}
+
+
+/*===========================================================================*
+ * el2_probe *
+ *===========================================================================*/
+int el2_probe(dep)
+dpeth_t * dep;
+{
+ /* Probe for the presence of an EtherLink II card. Initialize memory
+ * addressing if card detected.
+ */
+ int iobase, membase;
+ int thin;
+
+ /* Thin ethernet or AUI? */
+ thin = (dep->de_linmem & 1) ? ECNTR_AUI : ECNTR_THIN;
+
+ /* Location registers should have 1 bit set */
+ if (!(iobase = inb_el2(dep, EL2_IOBASE))) return 0;
+ if (!((membase = inb_el2(dep, EL2_MEMBASE)) & 0xF0)) return 0;
+ if ((iobase & (iobase - 1)) || (membase & (membase - 1))) return 0;
+
+ /* Resets board */
+ outb_el2(dep, EL2_CNTR, ECNTR_RESET | thin);
+ milli_delay(1);
+ outb_el2(dep, EL2_CNTR, thin);
+ milli_delay(5);
+
+ /* Map the address PROM to lower I/O address range */
+ outb_el2(dep, EL2_CNTR, ECNTR_SAPROM | thin);
+ if (inb_el2(dep, EL2_EA0) != 0x02 || /* Etherlink II Station address */
+ inb_el2(dep, EL2_EA1) != 0x60 || /* MUST be 02:60:8c:xx:xx:xx */
+ inb_el2(dep, EL2_EA2) != 0x8C)
+ return 0; /* No Etherlink board at this address */
+
+ /* Map the 8390 back to lower I/O address range */
+ outb_el2(dep, EL2_CNTR, thin);
+
+ /* Setup shared memory addressing for 3c503 */
+ dep->de_linmem = ((membase & 0xC0) ? EL2_BASE_0D8000 : EL2_BASE_0C8000) +
+ ((membase & 0xA0) ? (EL2_BASE_0CC000 - EL2_BASE_0C8000) : 0x0000);
+ dep->de_offset_page = (EL2_SM_START_PG * DP_PAGESIZE);
+ dep->de_ramsize = (EL2_SM_STOP_PG - EL2_SM_START_PG) * DP_PAGESIZE;
+
+ /* (Bad kludge, something Philip needs to look into. -- kjb) */
+ dep->de_linmem -= dep->de_offset_page;
+ dep->de_ramsize += dep->de_offset_page;
+
+ /* Board initialization and stop functions */
+ dep->de_initf = el2_init;
+ dep->de_stopf = el2_stop;
+ return 1;
+}
+
+static void milli_delay(unsigned long millis)
+{
+ tickdelay(MILLIS_TO_TICKS(millis));
+}
+
+#endif /* ENABLE_3C503 */
+
+/** 3c503.c **/
+
+/*
+ * $PchId: 3c503.c,v 1.3 2003/09/10 15:33:04 philip Exp $
+ */
--- /dev/null
+/*
+ * 3c503.h A shared memory driver for Etherlink II board.
+ *
+ * Created: Dec. 20, 1996 by G. Falzoni <falzoni@marina.scn.de>
+ */
+
+#define EL2_MEMTEST 0 /* Set to 1 for on board memory test */
+
+#define EL2_GA 0x0400 /* Offset of registers in Gate Array */
+
+/* EtherLink II card */
+
+#define EL2_STARTPG (EL2_GA+0x00) /* Start page matching DP_PSTARTPG */
+#define EL2_STOPPG (EL2_GA+0x01) /* Stop page matching DP_PSTOPPG */
+#define EL2_DRQCNT (EL2_GA+0x02) /* DMA burst count */
+#define EL2_IOBASE (EL2_GA+0x03) /* I/O base jumpers (bit coded) */
+#define EL2_MEMBASE (EL2_GA+0x04) /* Memory base jumpers (bit coded) */
+#define EL2_CFGR (EL2_GA+0x05) /* Configuration Register for GA */
+#define EL2_CNTR (EL2_GA+0x06) /* Control(write) and status(read) */
+#define EL2_STATUS (EL2_GA+0x07)
+#define EL2_IDCFG (EL2_GA+0x08) /* Interrupt/DMA configuration reg */
+#define EL2_DMAAH (EL2_GA+0x09) /* DMA address register (High byte) */
+#define EL2_DMAAL (EL2_GA+0x0A) /* DMA address register (Low byte) */
+#define EL2_VP2 (EL2_GA+0x0B) /* Vector pointer - set to */
+#define EL2_VP1 (EL2_GA+0x0C) /* reset address (0xFFFF:0) */
+#define EL2_VP0 (EL2_GA+0x0D) /* */
+#define EL2_FIFOH (EL2_GA+0x0E) /* FIFO for progr. I/O (High byte) */
+#define EL2_FIFOL (EL2_GA+0x0F) /* FIFO for progr. I/O (Low byte) */
+
+#define EL2_EA0 0x00 /* Most significant byte of ethernet address */
+#define EL2_EA1 0x01
+#define EL2_EA2 0x02
+#define EL2_EA3 0x03
+#define EL2_EA4 0x04
+#define EL2_EA5 0x05 /* Least significant byte of ethernet address */
+
+/* Bits in EL2_CNTR register */
+#define ECNTR_RESET 0x01 /* Software Reset */
+#define ECNTR_THIN 0x02 /* Onboard transceiver enable */
+#define ECNTR_AUI 0x00 /* Onboard transceiver disable */
+#define ECNTR_SAPROM 0x04 /* Map the station address prom */
+
+/* Bits in EL2_CFGR register */
+#define ECFGR_NORM 0x49 /* Enable 8k shared memory, no DMA, TC int */
+#define ECFGR_IRQOFF 0xC9 /* As above, disable 8390 IRQ */
+
+/* Shared memory management parameters */
+#define EL2_SM_START_PG 0x20 /* First page of TX buffer */
+#define EL2_SM_STOP_PG 0x40 /* Last page +1 of RX ring */
+
+/* Physical addresses where an Etherlink board can be configured */
+#define EL2_BASE_0C8000 0x0C8000
+#define EL2_BASE_0CC000 0x0CC000
+#define EL2_BASE_0D8000 0x0D8000
+#define EL2_BASE_0DC000 0x0DC000
+
+#define inb_el2(dep,reg) (inb((dep)->de_base_port+(reg)))
+#define outb_el2(dep,reg,data) (outb((dep)->de_base_port+(reg),(data)))
+
+/** 3c503.h **/
+
+/*
+ * $PchId: 3c503.h,v 1.3 2003/09/10 15:34:29 philip Exp $
+ */
--- /dev/null
+# Makefile for dp8390 driver
+DRIVER = dp8390
+
+# directories
+u = /usr
+i = $u/include
+s = $i/sys
+m = $i/minix
+b = $i/ibm
+d = ..
+
+# programs, flags, etc.
+CC = exec cc
+CFLAGS = -I$i
+LDFLAGS = -i
+LIBS = -lsys -lsysutil -ltimers
+
+OBJ = 3c503.o dp8390.o ne2000.o rtl8029.o wdeth.o
+LIBPCI = $d/libpci/pci.o $d/libpci/pci_table.o
+
+# build local binary
+all build: $(DRIVER)
+$(DRIVER): $(OBJ) $(LIBPCI)
+ $(CC) -o $@ $(LDFLAGS) $(OBJ) $(LIBPCI) $(LIBS)
+ install -S 256w $(DRIVER)
+
+$(LIBPCI):
+ cd $d/libpci && $(MAKE)
+
+# install with other drivers
+install: /usr/sbin/$(DRIVER)
+/usr/sbin/$(DRIVER): $(DRIVER)
+ install -o root -cs $? $@
+
+# clean up local files
+clean:
+ rm -f *.o *.bak $(DRIVER)
+
+depend:
+ /usr/bin/mkdep "$(CC) -E $(CPPFLAGS)" *.c ../libpci/*.c > .depend
+
+# Include generated dependencies.
+include .depend
+
--- /dev/null
+/*
+ * dp8390.c
+ *
+ * This file contains a ethernet device driver for NS dp8390 based ethernet
+ * cards.
+ *
+ * The valid messages and their parameters are:
+ *
+ * m_type DL_PORT DL_PROC DL_COUNT DL_MODE DL_ADDR
+ * |------------+----------+---------+----------+---------+---------|
+ * | HARDINT | | | | | |
+ * |------------|----------|---------|----------|---------|---------|
+ * | DL_WRITE | port nr | proc nr | count | mode | address |
+ * |------------|----------|---------|----------|---------|---------|
+ * | DL_WRITEV | port nr | proc nr | count | mode | address |
+ * |------------|----------|---------|----------|---------|---------|
+ * | DL_READ | port nr | proc nr | count | | address |
+ * |------------|----------|---------|----------|---------|---------|
+ * | DL_READV | port nr | proc nr | count | | address |
+ * |------------|----------|---------|----------|---------|---------|
+ * | DL_INIT | port nr | proc nr | mode | | address |
+ * |------------|----------|---------|----------|---------|---------|
+ * | DL_GETSTAT | port nr | proc nr | | | address |
+ * |------------|----------|---------|----------|---------|---------|
+ * | DL_STOP | port_nr | | | | |
+ * |------------|----------|---------|----------|---------|---------|
+ *
+ * The messages sent are:
+ *
+ * m-type DL_PORT DL_PROC DL_COUNT DL_STAT DL_CLCK
+ * |-------------+----------+---------+----------+---------+---------|
+ * |DL_TASK_REPLY| port nr | proc nr | rd-count | err|stat| clock |
+ * |-------------+----------+---------+----------+---------+---------|
+ *
+ * m_type m3_i1 m3_i2 m3_ca1
+ * |-------------+---------+-----------+---------------|
+ * |DL_INIT_REPLY| port nr | last port | ethernet addr |
+ * |-------------+---------+-----------+---------------|
+ *
+ * Created: before Dec 28, 1992 by Philip Homburg <philip@f-mnx.phicoh.com>
+ *
+ * Modified Mar 10 1994 by Philip Homburg
+ * Become a generic dp8390 driver.
+ *
+ * Modified Dec 20 1996 by G. Falzoni <falzoni@marina.scn.de>
+ * Added support for 3c503 boards.
+ */
+
+#include "../drivers.h"
+
+#include <stdlib.h>
+#include <minix/com.h>
+#include <net/hton.h>
+#include <net/gen/ether.h>
+#include <net/gen/eth_io.h>
+#include "assert.h"
+
+#include "local.h"
+#include "dp8390.h"
+
+#define DE_PORT_NR 3
+
+static dpeth_t de_table[DE_PORT_NR];
+static u16_t eth_ign_proto;
+static int arg_c;
+static char **arg_v;
+
+/* Configuration */
+typedef struct dp_conf
+{
+ port_t dpc_port;
+ int dpc_irq;
+ phys_bytes dpc_mem;
+ char *dpc_envvar;
+} dp_conf_t;
+
+dp_conf_t dp_conf[]= /* Card addresses */
+{
+ /* I/O port, IRQ, Buffer address, Env. var. */
+ { 0x280, 3, 0xD0000, "DPETH0" },
+ { 0x300, 5, 0xC8000, "DPETH1" },
+ { 0x380, 10, 0xD8000, "DPETH2" },
+};
+
+/* Test if dp_conf has exactly DE_PORT_NR entries. If not then you will see
+ * the error: "array size is negative".
+ */
+extern int ___dummy[DE_PORT_NR == sizeof(dp_conf)/sizeof(dp_conf[0]) ? 1 : -1];
+
+/* Card inits configured out? */
+#if !ENABLE_WDETH
+#define wdeth_probe(dep) (0)
+#endif
+#if !ENABLE_NE2000
+#define ne_probe(dep) (0)
+#endif
+#if !ENABLE_3C503
+#define el2_probe(dep) (0)
+#endif
+
+/* Some clones of the dp8390 and the PC emulator 'Bochs' require the CR_STA
+ * on writes to the CR register. Additional CR_STAs do not appear to hurt
+ * genuine dp8390s
+ */
+#define CR_EXTRA CR_STA
+
+#if ENABLE_PCI
+_PROTOTYPE( static void pci_conf, (void) );
+#endif
+_PROTOTYPE( static void do_vwrite, (message *mp, int from_int,
+ int vectored) );
+_PROTOTYPE( static void do_vread, (message *mp, int vectored) );
+_PROTOTYPE( static void do_init, (message *mp) );
+_PROTOTYPE( static void do_int, (dpeth_t *dep) );
+_PROTOTYPE( static void do_getstat, (message *mp) );
+_PROTOTYPE( static void do_stop, (message *mp) );
+_PROTOTYPE( static void dp_init, (dpeth_t *dep) );
+_PROTOTYPE( static void dp_confaddr, (dpeth_t *dep) );
+_PROTOTYPE( static void dp_reinit, (dpeth_t *dep) );
+_PROTOTYPE( static void dp_reset, (dpeth_t *dep) );
+_PROTOTYPE( static void dp_check_ints, (dpeth_t *dep) );
+_PROTOTYPE( static void dp_recv, (dpeth_t *dep) );
+_PROTOTYPE( static void dp_send, (dpeth_t *dep) );
+_PROTOTYPE( static void dp8390_stop, (void) );
+_PROTOTYPE( static void dp_getblock, (dpeth_t *dep, int page,
+ size_t offset, size_t size, void *dst) );
+_PROTOTYPE( static void dp_pio8_getblock, (dpeth_t *dep, int page,
+ size_t offset, size_t size, void *dst) );
+_PROTOTYPE( static void dp_pio16_getblock, (dpeth_t *dep, int page,
+ size_t offset, size_t size, void *dst) );
+_PROTOTYPE( static int dp_pkt2user, (dpeth_t *dep, int page,
+ int length) );
+_PROTOTYPE( static void dp_user2nic, (dpeth_t *dep, iovec_dat_t *iovp,
+ vir_bytes offset, int nic_addr, vir_bytes count) );
+_PROTOTYPE( static void dp_pio8_user2nic, (dpeth_t *dep,
+ iovec_dat_t *iovp, vir_bytes offset,
+ int nic_addr, vir_bytes count) );
+_PROTOTYPE( static void dp_pio16_user2nic, (dpeth_t *dep,
+ iovec_dat_t *iovp, vir_bytes offset,
+ int nic_addr, vir_bytes count) );
+_PROTOTYPE( static void dp_nic2user, (dpeth_t *dep, int nic_addr,
+ iovec_dat_t *iovp, vir_bytes offset, vir_bytes count) );
+_PROTOTYPE( static void dp_pio8_nic2user, (dpeth_t *dep, int nic_addr,
+ iovec_dat_t *iovp, vir_bytes offset, vir_bytes count) );
+_PROTOTYPE( static void dp_pio16_nic2user, (dpeth_t *dep, int nic_addr,
+ iovec_dat_t *iovp, vir_bytes offset, vir_bytes count) );
+_PROTOTYPE( static void dp_next_iovec, (iovec_dat_t *iovp) );
+_PROTOTYPE( static void conf_hw, (dpeth_t *dep) );
+_PROTOTYPE( static void update_conf, (dpeth_t *dep, dp_conf_t *dcp) );
+_PROTOTYPE( static int calc_iovec_size, (iovec_dat_t *iovp) );
+_PROTOTYPE( static void reply, (dpeth_t *dep, int err, int may_block) );
+_PROTOTYPE( static void mess_reply, (message *req, message *reply) );
+_PROTOTYPE( static void get_userdata, (int user_proc,
+ vir_bytes user_addr, vir_bytes count, void *loc_addr) );
+_PROTOTYPE( static void put_userdata, (int user_proc,
+ vir_bytes user_addr, vir_bytes count, void *loc_addr) );
+_PROTOTYPE( static void insb, (port_t port, void *buf, size_t size) );
+_PROTOTYPE( static void insw, (port_t port, void *buf, size_t size) );
+_PROTOTYPE( static void do_vir_insb, (port_t port, int proc,
+ vir_bytes buf, size_t size) );
+_PROTOTYPE( static void do_vir_insw, (port_t port, int proc,
+ vir_bytes buf, size_t size) );
+_PROTOTYPE( static void do_vir_outsb, (port_t port, int proc,
+ vir_bytes buf, size_t size) );
+_PROTOTYPE( static void do_vir_outsw, (port_t port, int proc,
+ vir_bytes buf, size_t size) );
+
+/*===========================================================================*
+ * dpeth_task *
+ *===========================================================================*/
+int main(int argc, char *argv[])
+{
+ message m;
+ int i, irq, r;
+ dpeth_t *dep;
+ long v;
+
+ arg_c= argc;
+ arg_v= argv;
+
+ for (i= 0, dep= de_table; i<DE_PORT_NR; i++, dep++)
+ {
+ strcpy(dep->de_name, "dp8390#0");
+ dep->de_name[7] += i;
+ }
+
+ v= 0;
+ (void) env_parse_x(arg_c, arg_v,
+ "ETH_IGN_PROTO", "x", 0, &v, 0x0000L, 0xFFFFL);
+ eth_ign_proto= htons((u16_t) v);
+
+ while (TRUE)
+ {
+ if ((r= receive(ANY, &m)) != OK)
+ panic("", "dp8390: receive failed", r);
+
+ switch (m.m_type)
+ {
+ case DL_WRITE: do_vwrite(&m, FALSE, FALSE); break;
+ case DL_WRITEV: do_vwrite(&m, FALSE, TRUE); break;
+ case DL_READ: do_vread(&m, FALSE); break;
+ case DL_READV: do_vread(&m, TRUE); break;
+ case DL_INIT: do_init(&m); break;
+ case DL_GETSTAT: do_getstat(&m); break;
+ case DL_STOP: do_stop(&m); break;
+ case HARD_INT:
+ for (i= 0, dep= &de_table[0]; i<DE_PORT_NR; i++, dep++)
+ {
+ if (dep->de_mode != DEM_ENABLED)
+ continue;
+ assert(dep->de_flags & DEF_ENABLED);
+ irq= dep->de_irq;
+ assert(irq >= 0 && irq < NR_IRQ_VECTORS);
+ if (dep->de_int_pending || 1)
+ {
+ dep->de_int_pending= 0;
+ dp_check_ints(dep);
+ do_int(dep);
+ r= sys_irqenable(&dep->de_hook);
+ if (r != OK)
+ {
+ panic("DP8390",
+ "unable enable interrupts", r);
+ }
+ }
+ }
+ break;
+ case SYS_SIG: {
+ sigset_t sigset = m.NOTIFY_ARG;
+ if (sigismember(&sigset, SIGKSTOP)) dp8390_stop();
+ break;
+ }
+ case SYN_ALARM:
+ printf("dp8390: strange, got SYN_ALARM\n");
+ break;
+ default:
+ panic("", "dp8390: illegal message", m.m_type);
+ }
+ }
+}
+
+
+#if 0
+/*===========================================================================*
+ * dp8390_dump *
+ *===========================================================================*/
+void dp8390_dump()
+{
+ dpeth_t *dep;
+ int i, isr;
+
+ printf("\n");
+ for (i= 0, dep = &de_table[0]; i<DE_PORT_NR; i++, dep++)
+ {
+#if XXX
+ if (dep->de_mode == DEM_DISABLED)
+ printf("dp8390 port %d is disabled\n", i);
+ else if (dep->de_mode == DEM_SINK)
+ printf("dp8390 port %d is in sink mode\n", i);
+#endif
+
+ if (dep->de_mode != DEM_ENABLED)
+ continue;
+
+ printf("dp8390 statistics of port %d:\n", i);
+
+ 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);
+
+ isr= inb_reg0(dep, DP_ISR);
+ printf("dp_isr = 0x%x + 0x%x, de_flags = 0x%x\n", isr,
+ inb_reg0(dep, DP_ISR), dep->de_flags);
+ }
+}
+#endif
+
+
+/*===========================================================================*
+ * dp8390_stop *
+ *===========================================================================*/
+static void dp8390_stop()
+{
+ message mess;
+ int i;
+
+ for (i= 0; i<DE_PORT_NR; i++)
+ {
+ if (de_table[i].de_mode != DEM_ENABLED)
+ continue;
+ mess.m_type= DL_STOP;
+ mess.DL_PORT= i;
+ do_stop(&mess);
+ }
+}
+
+#if ENABLE_PCI
+/*===========================================================================*
+ * pci_conf *
+ *===========================================================================*/
+static void pci_conf()
+{
+ int i, h;
+ char *envvar;
+ struct dpeth *dep;
+ static char envfmt[] = "*:d.d.d";
+ long v;
+ static int first_time= 1;
+
+ if (!first_time)
+ return;
+ first_time= 0;
+
+ for (i= 0, dep= de_table; i<DE_PORT_NR; i++, dep++)
+ {
+ envvar= dp_conf[i].dpc_envvar;
+ if (!(dep->de_pci= env_prefix_x(arg_c, arg_v, envvar, "pci")))
+ continue; /* no PCI config */
+ v= 0;
+ (void) env_parse_x(arg_c, arg_v, envvar, envfmt, 1, &v, 0, 255);
+ dep->de_pcibus= v;
+ v= 0;
+ (void) env_parse_x(arg_c, arg_v, envvar, envfmt, 2, &v, 0, 255);
+ dep->de_pcidev= v;
+ v= 0;
+ (void) env_parse_x(arg_c, arg_v, envvar, envfmt, 3, &v, 0, 255);
+ dep->de_pcifunc= v;
+ }
+
+ for (h= 1; h >= 0; h--) {
+ for (i= 0, dep= de_table; i<DE_PORT_NR; i++, dep++)
+ {
+ if (!dep->de_pci)
+ continue;
+ if (((dep->de_pcibus | dep->de_pcidev |
+ dep->de_pcifunc) != 0) != h)
+ {
+ continue;
+ }
+ if (!rtl_probe(dep))
+ dep->de_pci= -1;
+ }
+ }
+}
+#endif /* ENABLE_PCI */
+
+/*===========================================================================*
+ * do_vwrite *
+ *===========================================================================*/
+static void do_vwrite(mp, from_int, vectored)
+message *mp;
+int from_int;
+int vectored;
+{
+ int port, count, size;
+ int sendq_head;
+ dpeth_t *dep;
+
+ port = mp->DL_PORT;
+ count = mp->DL_COUNT;
+ if (port < 0 || port >= DE_PORT_NR)
+ panic("", "dp8390: illegal port", port);
+ dep= &de_table[port];
+ dep->de_client= mp->DL_PROC;
+
+ if (dep->de_mode == DEM_SINK)
+ {
+ assert(!from_int);
+ dep->de_flags |= DEF_PACK_SEND;
+ reply(dep, OK, FALSE);
+ return;
+ }
+ assert(dep->de_mode == DEM_ENABLED);
+ assert(dep->de_flags & DEF_ENABLED);
+ if (dep->de_flags & DEF_SEND_AVAIL)
+ panic("", "dp8390: send already in progress", NO_NUM);
+
+ sendq_head= dep->de_sendq_head;
+ if (dep->de_sendq[sendq_head].sq_filled)
+ {
+ if (from_int)
+ panic("", "dp8390: should not be sending\n", NO_NUM);
+ dep->de_sendmsg= *mp;
+ dep->de_flags |= DEF_SEND_AVAIL;
+ reply(dep, OK, FALSE);
+ return;
+ }
+ assert(!(dep->de_flags & DEF_PACK_SEND));
+
+ if (vectored)
+ {
+ get_userdata(mp->DL_PROC, (vir_bytes) mp->DL_ADDR,
+ (count > IOVEC_NR ? IOVEC_NR : count) *
+ sizeof(iovec_t), dep->de_write_iovec.iod_iovec);
+ dep->de_write_iovec.iod_iovec_s = count;
+ dep->de_write_iovec.iod_proc_nr = mp->DL_PROC;
+ dep->de_write_iovec.iod_iovec_addr = (vir_bytes) mp->DL_ADDR;
+
+ dep->de_tmp_iovec = dep->de_write_iovec;
+ size = calc_iovec_size(&dep->de_tmp_iovec);
+ }
+ else
+ {
+ dep->de_write_iovec.iod_iovec[0].iov_addr =
+ (vir_bytes) mp->DL_ADDR;
+ dep->de_write_iovec.iod_iovec[0].iov_size =
+ mp->DL_COUNT;
+ dep->de_write_iovec.iod_iovec_s = 1;
+ dep->de_write_iovec.iod_proc_nr = mp->DL_PROC;
+ dep->de_write_iovec.iod_iovec_addr = 0;
+ size= mp->DL_COUNT;
+ }
+ if (size < ETH_MIN_PACK_SIZE || size > ETH_MAX_PACK_SIZE_TAGGED)
+ {
+ panic("", "dp8390: invalid packet size", size);
+ }
+ (dep->de_user2nicf)(dep, &dep->de_write_iovec, 0,
+ dep->de_sendq[sendq_head].sq_sendpage * DP_PAGESIZE,
+ size);
+ dep->de_sendq[sendq_head].sq_filled= TRUE;
+ if (dep->de_sendq_tail == sendq_head)
+ {
+ outb_reg0(dep, DP_TPSR, dep->de_sendq[sendq_head].sq_sendpage);
+ outb_reg0(dep, DP_TBCR1, size >> 8);
+ outb_reg0(dep, DP_TBCR0, size & 0xff);
+ outb_reg0(dep, DP_CR, CR_TXP | CR_EXTRA);/* there it goes.. */
+ }
+ else
+ dep->de_sendq[sendq_head].sq_size= size;
+
+ if (++sendq_head == dep->de_sendq_nr)
+ sendq_head= 0;
+ assert(sendq_head < SENDQ_NR);
+ dep->de_sendq_head= sendq_head;
+
+ dep->de_flags |= DEF_PACK_SEND;
+
+ /* If the interrupt handler called, don't send a reply. The reply
+ * will be sent after all interrupts are handled.
+ */
+ if (from_int)
+ return;
+ reply(dep, OK, FALSE);
+
+ assert(dep->de_mode == DEM_ENABLED);
+ assert(dep->de_flags & DEF_ENABLED);
+}
+
+
+/*===========================================================================*
+ * do_vread *
+ *===========================================================================*/
+static void do_vread(mp, vectored)
+message *mp;
+int vectored;
+{
+ int port, count;
+ int size;
+ dpeth_t *dep;
+
+ port = mp->DL_PORT;
+ count = mp->DL_COUNT;
+ if (port < 0 || port >= DE_PORT_NR)
+ panic("", "dp8390: illegal port", port);
+ dep= &de_table[port];
+ dep->de_client= mp->DL_PROC;
+ if (dep->de_mode == DEM_SINK)
+ {
+ reply(dep, OK, FALSE);
+ return;
+ }
+ assert(dep->de_mode == DEM_ENABLED);
+ assert(dep->de_flags & DEF_ENABLED);
+
+ if(dep->de_flags & DEF_READING)
+ panic("", "dp8390: read already in progress", NO_NUM);
+
+ if (vectored)
+ {
+ get_userdata(mp->DL_PROC, (vir_bytes) mp->DL_ADDR,
+ (count > IOVEC_NR ? IOVEC_NR : count) *
+ sizeof(iovec_t), dep->de_read_iovec.iod_iovec);
+ dep->de_read_iovec.iod_iovec_s = count;
+ dep->de_read_iovec.iod_proc_nr = mp->DL_PROC;
+ dep->de_read_iovec.iod_iovec_addr = (vir_bytes) mp->DL_ADDR;
+
+ dep->de_tmp_iovec = dep->de_read_iovec;
+ size= calc_iovec_size(&dep->de_tmp_iovec);
+ }
+ else
+ {
+ dep->de_read_iovec.iod_iovec[0].iov_addr =
+ (vir_bytes) mp->DL_ADDR;
+ dep->de_read_iovec.iod_iovec[0].iov_size =
+ mp->DL_COUNT;
+ dep->de_read_iovec.iod_iovec_s = 1;
+ dep->de_read_iovec.iod_proc_nr = mp->DL_PROC;
+ dep->de_read_iovec.iod_iovec_addr = 0;
+ size= count;
+ }
+ if (size < ETH_MAX_PACK_SIZE_TAGGED)
+ panic("", "dp8390: wrong packet size", size);
+ dep->de_flags |= DEF_READING;
+
+ dp_recv(dep);
+
+ if ((dep->de_flags & (DEF_READING|DEF_STOPPED)) ==
+ (DEF_READING|DEF_STOPPED))
+ {
+ /* The chip is stopped, and all arrived packets are
+ * delivered.
+ */
+ dp_reset(dep);
+ }
+ reply(dep, OK, FALSE);
+}
+
+
+/*===========================================================================*
+ * do_init *
+ *===========================================================================*/
+static void do_init(mp)
+message *mp;
+{
+ int port;
+ dpeth_t *dep;
+ message reply_mess;
+
+#if ENABLE_PCI
+ pci_conf(); /* Configure PCI devices. */
+#endif
+
+ port = mp->DL_PORT;
+ if (port < 0 || port >= DE_PORT_NR)
+ {
+ reply_mess.m_type= DL_INIT_REPLY;
+ reply_mess.m3_i1= ENXIO;
+ mess_reply(mp, &reply_mess);
+ return;
+ }
+ dep= &de_table[port];
+ if (dep->de_mode == DEM_DISABLED)
+ {
+ /* This is the default, try to (re)locate the device. */
+ conf_hw(dep);
+ if (dep->de_mode == DEM_DISABLED)
+ {
+ /* Probe failed, or the device is configured off. */
+ reply_mess.m_type= DL_INIT_REPLY;
+ reply_mess.m3_i1= ENXIO;
+ mess_reply(mp, &reply_mess);
+ return;
+ }
+ if (dep->de_mode == DEM_ENABLED)
+ dp_init(dep);
+ }
+
+ if (dep->de_mode == DEM_SINK)
+ {
+ strncpy((char *) dep->de_address.ea_addr, "ZDP", 6);
+ dep->de_address.ea_addr[5] = port;
+ dp_confaddr(dep);
+ reply_mess.m_type = DL_INIT_REPLY;
+ reply_mess.m3_i1 = mp->DL_PORT;
+ reply_mess.m3_i2 = DE_PORT_NR;
+ *(ether_addr_t *) reply_mess.m3_ca1 = dep->de_address;
+ mess_reply(mp, &reply_mess);
+ return;
+ }
+ assert(dep->de_mode == DEM_ENABLED);
+ assert(dep->de_flags & DEF_ENABLED);
+
+ dep->de_flags &= ~(DEF_PROMISC | DEF_MULTI | DEF_BROAD);
+
+ if (mp->DL_MODE & DL_PROMISC_REQ)
+ dep->de_flags |= DEF_PROMISC | DEF_MULTI | DEF_BROAD;
+ if (mp->DL_MODE & DL_MULTI_REQ)
+ dep->de_flags |= DEF_MULTI;
+ if (mp->DL_MODE & DL_BROAD_REQ)
+ dep->de_flags |= DEF_BROAD;
+
+ dep->de_client = mp->m_source;
+ dp_reinit(dep);
+
+ reply_mess.m_type = DL_INIT_REPLY;
+ reply_mess.m3_i1 = mp->DL_PORT;
+ reply_mess.m3_i2 = DE_PORT_NR;
+ *(ether_addr_t *) reply_mess.m3_ca1 = dep->de_address;
+
+ mess_reply(mp, &reply_mess);
+}
+
+/*===========================================================================*
+ * do_int *
+ *===========================================================================*/
+static void do_int(dep)
+dpeth_t *dep;
+{
+ if (dep->de_flags & (DEF_PACK_SEND | DEF_PACK_RECV))
+ reply(dep, OK, TRUE);
+}
+
+
+/*===========================================================================*
+ * do_getstat *
+ *===========================================================================*/
+static void do_getstat(mp)
+message *mp;
+{
+ int port;
+ dpeth_t *dep;
+
+ port = mp->DL_PORT;
+ if (port < 0 || port >= DE_PORT_NR)
+ panic("", "dp8390: illegal port", port);
+ dep= &de_table[port];
+ dep->de_client= mp->DL_PROC;
+ if (dep->de_mode == DEM_SINK)
+ {
+ put_userdata(mp->DL_PROC, (vir_bytes) mp->DL_ADDR,
+ (vir_bytes) sizeof(dep->de_stat), &dep->de_stat);
+ reply(dep, OK, FALSE);
+ return;
+ }
+ assert(dep->de_mode == DEM_ENABLED);
+ assert(dep->de_flags & DEF_ENABLED);
+
+ 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);
+
+ put_userdata(mp->DL_PROC, (vir_bytes) mp->DL_ADDR,
+ (vir_bytes) sizeof(dep->de_stat), &dep->de_stat);
+ reply(dep, OK, FALSE);
+}
+
+
+/*===========================================================================*
+ * do_stop *
+ *===========================================================================*/
+static void do_stop(mp)
+message *mp;
+{
+ int port;
+ dpeth_t *dep;
+
+ port = mp->DL_PORT;
+
+ if (port < 0 || port >= DE_PORT_NR)
+ panic("", "dp8390: illegal port", port);
+ dep= &de_table[port];
+ if (dep->de_mode == DEM_SINK)
+ return;
+ assert(dep->de_mode == DEM_ENABLED);
+
+ if (!(dep->de_flags & DEF_ENABLED))
+ return;
+
+ outb_reg0(dep, DP_CR, CR_STP | CR_DM_ABORT);
+ (dep->de_stopf)(dep);
+
+ dep->de_flags= DEF_EMPTY;
+}
+
+
+/*===========================================================================*
+ * dp_init *
+ *===========================================================================*/
+static void dp_init(dep)
+dpeth_t *dep;
+{
+ int dp_rcr_reg;
+ int i, r;
+
+ /* General initialization */
+ dep->de_flags = DEF_EMPTY;
+ (*dep->de_initf)(dep);
+
+ dp_confaddr(dep);
+
+ if (debug)
+ {
+ printf("%s: Ethernet address ", dep->de_name);
+ for (i= 0; i < 6; i++)
+ printf("%x%c", dep->de_address.ea_addr[i],
+ i < 5 ? ':' : '\n');
+ }
+
+ /* Initialization of the dp8390 following the mandatory procedure
+ * in reference manual ("DP8390D/NS32490D NIC Network Interface
+ * Controller", National Semiconductor, July 1995, Page 29).
+ */
+ /* Step 1: */
+ outb_reg0(dep, DP_CR, CR_PS_P0 | CR_STP | CR_DM_ABORT);
+ /* Step 2: */
+ if (dep->de_16bit)
+ outb_reg0(dep, DP_DCR, DCR_WORDWIDE | DCR_8BYTES | DCR_BMS);
+ else
+ outb_reg0(dep, DP_DCR, DCR_BYTEWIDE | DCR_8BYTES | DCR_BMS);
+ /* Step 3: */
+ outb_reg0(dep, DP_RBCR0, 0);
+ outb_reg0(dep, DP_RBCR1, 0);
+ /* Step 4: */
+ dp_rcr_reg = 0;
+ if (dep->de_flags & DEF_PROMISC)
+ dp_rcr_reg |= RCR_AB | RCR_PRO | RCR_AM;
+ if (dep->de_flags & DEF_BROAD)
+ dp_rcr_reg |= RCR_AB;
+ if (dep->de_flags & DEF_MULTI)
+ dp_rcr_reg |= RCR_AM;
+ outb_reg0(dep, DP_RCR, dp_rcr_reg);
+ /* Step 5: */
+ outb_reg0(dep, DP_TCR, TCR_INTERNAL);
+ /* Step 6: */
+ outb_reg0(dep, DP_BNRY, dep->de_startpage);
+ outb_reg0(dep, DP_PSTART, dep->de_startpage);
+ outb_reg0(dep, DP_PSTOP, dep->de_stoppage);
+ /* Step 7: */
+ outb_reg0(dep, DP_ISR, 0xFF);
+ /* Step 8: */
+ outb_reg0(dep, DP_IMR, IMR_PRXE | IMR_PTXE | IMR_RXEE | IMR_TXEE |
+ IMR_OVWE | IMR_CNTE);
+ /* 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_MAR0, 0xff);
+ outb_reg1(dep, DP_MAR1, 0xff);
+ outb_reg1(dep, DP_MAR2, 0xff);
+ outb_reg1(dep, DP_MAR3, 0xff);
+ outb_reg1(dep, DP_MAR4, 0xff);
+ outb_reg1(dep, DP_MAR5, 0xff);
+ outb_reg1(dep, DP_MAR6, 0xff);
+ outb_reg1(dep, DP_MAR7, 0xff);
+
+ outb_reg1(dep, DP_CURR, dep->de_startpage + 1);
+ /* Step 10: */
+ outb_reg0(dep, DP_CR, CR_DM_ABORT | CR_STA);
+ /* Step 11: */
+ outb_reg0(dep, DP_TCR, TCR_NORMAL);
+
+ inb_reg0(dep, DP_CNTR0); /* reset counters by reading */
+ inb_reg0(dep, DP_CNTR1);
+ inb_reg0(dep, DP_CNTR2);
+
+ /* Finish the initialization. */
+ dep->de_flags |= DEF_ENABLED;
+ for (i= 0; i<dep->de_sendq_nr; i++)
+ dep->de_sendq[i].sq_filled= 0;
+ dep->de_sendq_head= 0;
+ dep->de_sendq_tail= 0;
+ if (!dep->de_prog_IO)
+ {
+ dep->de_user2nicf= dp_user2nic;
+ dep->de_nic2userf= dp_nic2user;
+ dep->de_getblockf= dp_getblock;
+ }
+ else if (dep->de_16bit)
+ {
+ dep->de_user2nicf= dp_pio16_user2nic;
+ dep->de_nic2userf= dp_pio16_nic2user;
+ dep->de_getblockf= dp_pio16_getblock;
+ }
+ else
+ {
+ dep->de_user2nicf= dp_pio8_user2nic;
+ dep->de_nic2userf= dp_pio8_nic2user;
+ dep->de_getblockf= dp_pio8_getblock;
+ }
+
+ /* Set the interrupt handler and policy. Do not automatically
+ * reenable interrupts. Return the IRQ line number on interrupts.
+ */
+ dep->de_hook = dep->de_irq;
+ r= sys_irqsetpolicy(dep->de_irq, 0, &dep->de_hook);
+ if (r != OK)
+ panic("DP8390", "sys_irqsetpolicy failed", r);
+
+ r= sys_irqenable(&dep->de_hook);
+ if (r != OK)
+ {
+ panic("DP8390", "unable enable interrupts", r);
+ }
+}
+
+
+/*===========================================================================*
+ * dp_confaddr *
+ *===========================================================================*/
+static void dp_confaddr(dep)
+dpeth_t *dep;
+{
+ int i;
+ char eakey[16];
+ static char eafmt[]= "x:x:x:x:x:x";
+ long v;
+
+ /* User defined ethernet address? */
+ strcpy(eakey, dp_conf[dep-de_table].dpc_envvar);
+ strcat(eakey, "_EA");
+
+ for (i= 0; i < 6; i++)
+ {
+ v= dep->de_address.ea_addr[i];
+ if (env_parse_x(arg_c, arg_v,
+ eakey, eafmt, i, &v, 0x00L, 0xFFL) != EP_SET)
+ {
+ break;
+ }
+ dep->de_address.ea_addr[i]= v;
+ }
+
+ if (i != 0 && i != 6) env_panic(eakey); /* It's all or nothing */
+}
+
+
+/*===========================================================================*
+ * dp_reinit *
+ *===========================================================================*/
+static void dp_reinit(dep)
+dpeth_t *dep;
+{
+ int dp_rcr_reg;
+
+ outb_reg0(dep, DP_CR, CR_PS_P0 | CR_EXTRA);
+
+ dp_rcr_reg = 0;
+ if (dep->de_flags & DEF_PROMISC)
+ dp_rcr_reg |= RCR_AB | RCR_PRO | RCR_AM;
+ if (dep->de_flags & DEF_BROAD)
+ dp_rcr_reg |= RCR_AB;
+ if (dep->de_flags & DEF_MULTI)
+ dp_rcr_reg |= RCR_AM;
+ outb_reg0(dep, DP_RCR, dp_rcr_reg);
+}
+
+
+/*===========================================================================*
+ * dp_reset *
+ *===========================================================================*/
+static void dp_reset(dep)
+dpeth_t *dep;
+{
+ int i;
+
+ /* Stop chip */
+ outb_reg0(dep, DP_CR, CR_STP | CR_DM_ABORT);
+ outb_reg0(dep, DP_RBCR0, 0);
+ outb_reg0(dep, DP_RBCR1, 0);
+ for (i= 0; i < 0x1000 && ((inb_reg0(dep, DP_ISR) & ISR_RST) == 0); i++)
+ ; /* Do nothing */
+ outb_reg0(dep, DP_TCR, TCR_1EXTERNAL|TCR_OFST);
+ outb_reg0(dep, DP_CR, CR_STA|CR_DM_ABORT);
+ outb_reg0(dep, DP_TCR, TCR_NORMAL);
+
+ /* Acknowledge the ISR_RDC (remote dma) interrupt. */
+ for (i= 0; i < 0x1000 && ((inb_reg0(dep, DP_ISR) & ISR_RDC) == 0); i++)
+ ; /* Do nothing */
+ outb_reg0(dep, DP_ISR, inb_reg0(dep, DP_ISR) & ~ISR_RDC);
+
+ /* Reset the transmit ring. If we were transmitting a packet, we
+ * pretend that the packet is processed. Higher layers will
+ * retransmit if the packet wasn't actually sent.
+ */
+ dep->de_sendq_head= dep->de_sendq_tail= 0;
+ for (i= 0; i<dep->de_sendq_nr; i++)
+ dep->de_sendq[i].sq_filled= 0;
+ dp_send(dep);
+ dep->de_flags &= ~DEF_STOPPED;
+}
+
+
+/*===========================================================================*
+ * dp_check_ints *
+ *===========================================================================*/
+static void dp_check_ints(dep)
+dpeth_t *dep;
+{
+ int isr, tsr;
+ int size, sendq_tail;
+
+ if (!(dep->de_flags & DEF_ENABLED))
+ panic("", "dp8390: got premature interrupt", NO_NUM);
+
+ for(;;)
+ {
+ isr = inb_reg0(dep, DP_ISR);
+ if (!isr)
+ break;
+ outb_reg0(dep, DP_ISR, isr);
+ if (isr & (ISR_PTX|ISR_TXE))
+ {
+ if (isr & ISR_TXE)
+ {
+#if DEBUG
+ { printf("%s: got send Error\n", dep->de_name); }
+#endif
+ dep->de_stat.ets_sendErr++;
+ }
+ else
+ {
+ tsr = inb_reg0(dep, DP_TSR);
+
+ if (tsr & TSR_PTX) dep->de_stat.ets_packetT++;
+#if 0 /* Reserved in later manuals, should be ignored */
+ if (!(tsr & TSR_DFR))
+ {
+ /* In most (all?) implementations of
+ * 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++;
+ }
+ sendq_tail= dep->de_sendq_tail;
+
+ if (!(dep->de_sendq[sendq_tail].sq_filled))
+ {
+ /* Software bug? */
+ assert(!debug);
+
+ /* Or hardware bug? */
+ printf(
+ "%s: transmit interrupt, but not sending\n",
+ dep->de_name);
+ continue;
+ }
+ dep->de_sendq[sendq_tail].sq_filled= 0;
+ if (++sendq_tail == dep->de_sendq_nr)
+ sendq_tail= 0;
+ dep->de_sendq_tail= sendq_tail;
+ if (dep->de_sendq[sendq_tail].sq_filled)
+ {
+ size= dep->de_sendq[sendq_tail].sq_size;
+ outb_reg0(dep, DP_TPSR,
+ dep->de_sendq[sendq_tail].sq_sendpage);
+ outb_reg0(dep, DP_TBCR1, size >> 8);
+ outb_reg0(dep, DP_TBCR0, size & 0xff);
+ outb_reg0(dep, DP_CR, CR_TXP | CR_EXTRA);
+ }
+ if (dep->de_flags & DEF_SEND_AVAIL)
+ dp_send(dep);
+ }
+
+ if (isr & ISR_PRX)
+ {
+ /* Only call dp_recv if there is a read request */
+ if (dep->de_flags & DEF_READING)
+ dp_recv(dep);
+ }
+
+ if (isr & ISR_RXE) dep->de_stat.ets_recvErr++;
+ 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
+ if (dep->de_flags & DEF_READING)
+ {
+ printf(
+"dp_check_ints: strange: overwrite warning and pending read request\n");
+ dp_recv(dep);
+ }
+ }
+ if (isr & ISR_RDC)
+ {
+ /* Nothing to do */
+ }
+ if (isr & ISR_RST)
+ {
+ /* this means we got an interrupt but the ethernet
+ * chip is shutdown. We set the flag DEF_STOPPED,
+ * and continue processing arrived packets. When the
+ * receive buffer is empty, we reset the dp8390.
+ */
+#if 0
+ { printW(); printf(
+ "%s: NIC stopped\n", dep->de_name); }
+#endif
+ dep->de_flags |= DEF_STOPPED;
+ break;
+ }
+ }
+ if ((dep->de_flags & (DEF_READING|DEF_STOPPED)) ==
+ (DEF_READING|DEF_STOPPED))
+ {
+ /* The chip is stopped, and all arrived packets are
+ * delivered.
+ */
+ dp_reset(dep);
+ }
+}
+
+
+/*===========================================================================*
+ * dp_recv *
+ *===========================================================================*/
+static void dp_recv(dep)
+dpeth_t *dep;
+{
+ dp_rcvhdr_t header;
+ unsigned pageno, curr, next;
+ vir_bytes length;
+ int packet_processed, r;
+ u16_t eth_type;
+
+ packet_processed = FALSE;
+ pageno = inb_reg0(dep, DP_BNRY) + 1;
+ if (pageno == dep->de_stoppage) pageno = dep->de_startpage;
+
+ do
+ {
+ outb_reg0(dep, DP_CR, CR_PS_P1 | CR_EXTRA);
+ curr = inb_reg1(dep, DP_CURR);
+ outb_reg0(dep, DP_CR, CR_PS_P0 | CR_EXTRA);
+
+ if (curr == pageno) break;
+
+ (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);
+
+ length = (header.dr_rbcl | (header.dr_rbch << 8)) -
+ sizeof(dp_rcvhdr_t);
+ next = header.dr_next;
+ if (length < ETH_MIN_PACK_SIZE ||
+ length > ETH_MAX_PACK_SIZE_TAGGED)
+ {
+ printf("%s: packet with strange length arrived: %d\n",
+ dep->de_name, (int) length);
+ next= curr;
+ }
+ else if (next < dep->de_startpage || next >= dep->de_stoppage)
+ {
+ printf("%s: strange next page\n", dep->de_name);
+ next= curr;
+ }
+ else if (eth_type == eth_ign_proto)
+ {
+ /* Hack: ignore packets of a given protocol, useful
+ * if you share a net with 80 computers sending
+ * Amoeba FLIP broadcasts. (Protocol 0x8146.)
+ */
+ static int first= 1;
+ if (first)
+ {
+ first= 0;
+ printf("%s: dropping proto 0x%04x packets\n",
+ dep->de_name,
+ ntohs(eth_ign_proto));
+ }
+ dep->de_stat.ets_packetR++;
+ }
+ 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++;
+ next = curr;
+ }
+ else if ((header.dr_status & RSR_PRX) &&
+ (dep->de_flags & DEF_ENABLED))
+ {
+ r = dp_pkt2user(dep, pageno, length);
+ if (r != OK)
+ return;
+
+ packet_processed = TRUE;
+ dep->de_stat.ets_packetR++;
+ }
+ if (next == dep->de_startpage)
+ outb_reg0(dep, DP_BNRY, dep->de_stoppage - 1);
+ else
+ outb_reg0(dep, DP_BNRY, next - 1);
+
+ pageno = next;
+ }
+ while (!packet_processed);
+}
+
+
+/*===========================================================================*
+ * dp_send *
+ *===========================================================================*/
+static void dp_send(dep)
+dpeth_t *dep;
+{
+ if (!(dep->de_flags & DEF_SEND_AVAIL))
+ return;
+
+ dep->de_flags &= ~DEF_SEND_AVAIL;
+ switch(dep->de_sendmsg.m_type)
+ {
+ case DL_WRITE: do_vwrite(&dep->de_sendmsg, TRUE, FALSE); break;
+ case DL_WRITEV: do_vwrite(&dep->de_sendmsg, TRUE, TRUE); break;
+ default:
+ panic("", "dp8390: wrong type:", dep->de_sendmsg.m_type);
+ break;
+ }
+}
+
+
+/*===========================================================================*
+ * dp_getblock *
+ *===========================================================================*/
+static void dp_getblock(dep, page, offset, size, dst)
+dpeth_t *dep;
+int page;
+size_t offset;
+size_t size;
+void *dst;
+{
+ int r;
+
+ offset = page * DP_PAGESIZE + offset;
+
+ r= sys_vircopy(SELF, D, (vir_bytes)dst,
+ BIOS_SEG, D, dep->de_linmem + offset, size);
+
+ if (r != OK)
+ panic("DP8390", "dp_getblock: sys_vircopy failed", r);
+}
+
+
+/*===========================================================================*
+ * dp_pio8_getblock *
+ *===========================================================================*/
+static void dp_pio8_getblock(dep, page, offset, size, dst)
+dpeth_t *dep;
+int page;
+size_t offset;
+size_t size;
+void *dst;
+{
+ offset = page * DP_PAGESIZE + offset;
+ outb_reg0(dep, DP_RBCR0, size & 0xFF);
+ outb_reg0(dep, DP_RBCR1, size >> 8);
+ outb_reg0(dep, DP_RSAR0, offset & 0xFF);
+ outb_reg0(dep, DP_RSAR1, offset >> 8);
+ outb_reg0(dep, DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA);
+
+ insb(dep->de_data_port, dst, size);
+}
+
+
+/*===========================================================================*
+ * dp_pio16_getblock *
+ *===========================================================================*/
+static void dp_pio16_getblock(dep, page, offset, size, dst)
+dpeth_t *dep;
+int page;
+size_t offset;
+size_t size;
+void *dst;
+{
+ offset = page * DP_PAGESIZE + offset;
+ outb_reg0(dep, DP_RBCR0, size & 0xFF);
+ outb_reg0(dep, DP_RBCR1, size >> 8);
+ outb_reg0(dep, DP_RSAR0, offset & 0xFF);
+ outb_reg0(dep, DP_RSAR1, offset >> 8);
+ outb_reg0(dep, DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA);
+
+ assert (!(size & 1));
+ insw(dep->de_data_port, dst, size);
+}
+
+
+/*===========================================================================*
+ * dp_pkt2user *
+ *===========================================================================*/
+static int dp_pkt2user(dep, page, length)
+dpeth_t *dep;
+int page, length;
+{
+ int last, count;
+
+ if (!(dep->de_flags & DEF_READING))
+ return EGENERIC;
+
+ last = page + (length - 1) / DP_PAGESIZE;
+ if (last >= dep->de_stoppage)
+ {
+ count = (dep->de_stoppage - page) * DP_PAGESIZE -
+ sizeof(dp_rcvhdr_t);
+
+ /* Save read_iovec since we need it twice. */
+ dep->de_tmp_iovec = dep->de_read_iovec;
+ (dep->de_nic2userf)(dep, page * DP_PAGESIZE +
+ sizeof(dp_rcvhdr_t), &dep->de_tmp_iovec, 0, count);
+ (dep->de_nic2userf)(dep, dep->de_startpage * DP_PAGESIZE,
+ &dep->de_read_iovec, count, length - count);
+ }
+ else
+ {
+ (dep->de_nic2userf)(dep, page * DP_PAGESIZE +
+ sizeof(dp_rcvhdr_t), &dep->de_read_iovec, 0, length);
+ }
+
+ dep->de_read_s = length;
+ dep->de_flags |= DEF_PACK_RECV;
+ dep->de_flags &= ~DEF_READING;
+
+ return OK;
+}
+
+
+/*===========================================================================*
+ * dp_user2nic *
+ *===========================================================================*/
+static void dp_user2nic(dep, iovp, offset, nic_addr, count)
+dpeth_t *dep;
+iovec_dat_t *iovp;
+vir_bytes offset;
+int nic_addr;
+vir_bytes count;
+{
+ vir_bytes vir_hw, vir_user;
+ int bytes, i, r;
+
+ vir_hw = dep->de_linmem + nic_addr;
+
+ i= 0;
+ while (count > 0)
+ {
+ if (i >= IOVEC_NR)
+ {
+ dp_next_iovec(iovp);
+ i= 0;
+ continue;
+ }
+ assert(i < iovp->iod_iovec_s);
+ if (offset >= iovp->iod_iovec[i].iov_size)
+ {
+ offset -= iovp->iod_iovec[i].iov_size;
+ i++;
+ continue;
+ }
+ bytes = iovp->iod_iovec[i].iov_size - offset;
+ if (bytes > count)
+ bytes = count;
+
+ r= sys_vircopy(iovp->iod_proc_nr, D,
+ iovp->iod_iovec[i].iov_addr + offset,
+ BIOS_SEG, D, vir_hw, bytes);
+ if (r != OK)
+ panic("DP8390", "dp_user2nic: sys_vircopy failed", r);
+
+ count -= bytes;
+ vir_hw += bytes;
+ offset += bytes;
+ }
+ assert(count == 0);
+}
+
+
+/*===========================================================================*
+ * dp_pio8_user2nic *
+ *===========================================================================*/
+static void dp_pio8_user2nic(dep, iovp, offset, nic_addr, count)
+dpeth_t *dep;
+iovec_dat_t *iovp;
+vir_bytes offset;
+int nic_addr;
+vir_bytes count;
+{
+ phys_bytes phys_user;
+ int bytes, i;
+
+ outb_reg0(dep, DP_ISR, ISR_RDC);
+
+ outb_reg0(dep, DP_RBCR0, count & 0xFF);
+ outb_reg0(dep, DP_RBCR1, count >> 8);
+ outb_reg0(dep, DP_RSAR0, nic_addr & 0xFF);
+ outb_reg0(dep, DP_RSAR1, nic_addr >> 8);
+ outb_reg0(dep, DP_CR, CR_DM_RW | CR_PS_P0 | CR_STA);
+
+ i= 0;
+ while (count > 0)
+ {
+ if (i >= IOVEC_NR)
+ {
+ dp_next_iovec(iovp);
+ i= 0;
+ continue;
+ }
+ assert(i < iovp->iod_iovec_s);
+ if (offset >= iovp->iod_iovec[i].iov_size)
+ {
+ offset -= iovp->iod_iovec[i].iov_size;
+ i++;
+ continue;
+ }
+ bytes = iovp->iod_iovec[i].iov_size - offset;
+ if (bytes > count)
+ bytes = count;
+
+ do_vir_outsb(dep->de_data_port, iovp->iod_proc_nr,
+ iovp->iod_iovec[i].iov_addr + offset, bytes);
+ count -= bytes;
+ offset += bytes;
+ }
+ assert(count == 0);
+
+ for (i= 0; i<100; i++)
+ {
+ if (inb_reg0(dep, DP_ISR) & ISR_RDC)
+ break;
+ }
+ if (i == 100)
+ {
+ panic("", "dp8390: remote dma failed to complete", NO_NUM);
+ }
+}
+
+
+/*===========================================================================*
+ * dp_pio16_user2nic *
+ *===========================================================================*/
+static void dp_pio16_user2nic(dep, iovp, offset, nic_addr, count)
+dpeth_t *dep;
+iovec_dat_t *iovp;
+vir_bytes offset;
+int nic_addr;
+vir_bytes count;
+{
+ vir_bytes vir_user;
+ vir_bytes ecount;
+ int i, r, bytes, user_proc;
+ u8_t two_bytes[2];
+ int odd_byte;
+
+ ecount= (count+1) & ~1;
+ odd_byte= 0;
+
+ outb_reg0(dep, DP_ISR, ISR_RDC);
+ outb_reg0(dep, DP_RBCR0, ecount & 0xFF);
+ outb_reg0(dep, DP_RBCR1, ecount >> 8);
+ outb_reg0(dep, DP_RSAR0, nic_addr & 0xFF);
+ outb_reg0(dep, DP_RSAR1, nic_addr >> 8);
+ outb_reg0(dep, DP_CR, CR_DM_RW | CR_PS_P0 | CR_STA);
+
+ i= 0;
+ while (count > 0)
+ {
+ if (i >= IOVEC_NR)
+ {
+ dp_next_iovec(iovp);
+ i= 0;
+ continue;
+ }
+ assert(i < iovp->iod_iovec_s);
+ if (offset >= iovp->iod_iovec[i].iov_size)
+ {
+ offset -= iovp->iod_iovec[i].iov_size;
+ i++;
+ continue;
+ }
+ bytes = iovp->iod_iovec[i].iov_size - offset;
+ if (bytes > count)
+ bytes = count;
+
+ user_proc= iovp->iod_proc_nr;
+ vir_user= iovp->iod_iovec[i].iov_addr + offset;
+ if (odd_byte)
+ {
+ r= sys_vircopy(user_proc, D, vir_user,
+ SELF, D, (vir_bytes)&two_bytes[1], 1);
+ if (r != OK)
+ {
+ panic("DP8390",
+ "dp_pio16_user2nic: sys_vircopy failed",
+ r);
+ }
+ outw(dep->de_data_port, *(u16_t *)two_bytes);
+ count--;
+ offset++;
+ bytes--;
+ vir_user++;
+ odd_byte= 0;
+ if (!bytes)
+ continue;
+ }
+ ecount= bytes & ~1;
+ if (ecount != 0)
+ {
+ do_vir_outsw(dep->de_data_port, user_proc, vir_user,
+ ecount);
+ count -= ecount;
+ offset += ecount;
+ bytes -= ecount;
+ vir_user += ecount;
+ }
+ if (bytes)
+ {
+ assert(bytes == 1);
+ r= sys_vircopy(user_proc, D, vir_user,
+ SELF, D, (vir_bytes)&two_bytes[0], 1);
+ if (r != OK)
+ {
+ panic("DP8390",
+ "dp_pio16_user2nic: sys_vircopy failed",
+ r);
+ }
+ count--;
+ offset++;
+ bytes--;
+ vir_user++;
+ odd_byte= 1;
+ }
+ }
+ assert(count == 0);
+
+ if (odd_byte)
+ outw(dep->de_data_port, *(u16_t *)two_bytes);
+
+ for (i= 0; i<100; i++)
+ {
+ if (inb_reg0(dep, DP_ISR) & ISR_RDC)
+ break;
+ }
+ if (i == 100)
+ {
+ panic("", "dp8390: remote dma failed to complete", NO_NUM);
+ }
+}
+
+
+/*===========================================================================*
+ * dp_nic2user *
+ *===========================================================================*/
+static void dp_nic2user(dep, nic_addr, iovp, offset, count)
+dpeth_t *dep;
+int nic_addr;
+iovec_dat_t *iovp;
+vir_bytes offset;
+vir_bytes count;
+{
+ vir_bytes vir_hw, vir_user;
+ int bytes, i, r;
+
+ vir_hw = dep->de_linmem + nic_addr;
+
+ i= 0;
+ while (count > 0)
+ {
+ if (i >= IOVEC_NR)
+ {
+ dp_next_iovec(iovp);
+ i= 0;
+ continue;
+ }
+ assert(i < iovp->iod_iovec_s);
+ if (offset >= iovp->iod_iovec[i].iov_size)
+ {
+ offset -= iovp->iod_iovec[i].iov_size;
+ i++;
+ continue;
+ }
+ bytes = iovp->iod_iovec[i].iov_size - offset;
+ if (bytes > count)
+ bytes = count;
+
+ r= sys_vircopy(BIOS_SEG, D, vir_hw,
+ iovp->iod_proc_nr, D,
+ iovp->iod_iovec[i].iov_addr + offset, bytes);
+ if (r != OK)
+ panic("DP8390", "dp_nic2user: sys_vircopy failed", r);
+
+ count -= bytes;
+ vir_hw += bytes;
+ offset += bytes;
+ }
+ assert(count == 0);
+}
+
+
+/*===========================================================================*
+ * dp_pio8_nic2user *
+ *===========================================================================*/
+static void dp_pio8_nic2user(dep, nic_addr, iovp, offset, count)
+dpeth_t *dep;
+int nic_addr;
+iovec_dat_t *iovp;
+vir_bytes offset;
+vir_bytes count;
+{
+ phys_bytes phys_user;
+ int bytes, i;
+
+ outb_reg0(dep, DP_RBCR0, count & 0xFF);
+ outb_reg0(dep, DP_RBCR1, count >> 8);
+ outb_reg0(dep, DP_RSAR0, nic_addr & 0xFF);
+ outb_reg0(dep, DP_RSAR1, nic_addr >> 8);
+ outb_reg0(dep, DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA);
+
+ i= 0;
+ while (count > 0)
+ {
+ if (i >= IOVEC_NR)
+ {
+ dp_next_iovec(iovp);
+ i= 0;
+ continue;
+ }
+ assert(i < iovp->iod_iovec_s);
+ if (offset >= iovp->iod_iovec[i].iov_size)
+ {
+ offset -= iovp->iod_iovec[i].iov_size;
+ i++;
+ continue;
+ }
+ bytes = iovp->iod_iovec[i].iov_size - offset;
+ if (bytes > count)
+ bytes = count;
+
+ do_vir_insb(dep->de_data_port, iovp->iod_proc_nr,
+ iovp->iod_iovec[i].iov_addr + offset, bytes);
+ count -= bytes;
+ offset += bytes;
+ }
+ assert(count == 0);
+}
+
+
+/*===========================================================================*
+ * dp_pio16_nic2user *
+ *===========================================================================*/
+static void dp_pio16_nic2user(dep, nic_addr, iovp, offset, count)
+dpeth_t *dep;
+int nic_addr;
+iovec_dat_t *iovp;
+vir_bytes offset;
+vir_bytes count;
+{
+ vir_bytes vir_user;
+ vir_bytes ecount;
+ int i, r, bytes, user_proc;
+ u8_t two_bytes[2];
+ int odd_byte;
+
+ ecount= (count+1) & ~1;
+ odd_byte= 0;
+
+ outb_reg0(dep, DP_RBCR0, ecount & 0xFF);
+ outb_reg0(dep, DP_RBCR1, ecount >> 8);
+ outb_reg0(dep, DP_RSAR0, nic_addr & 0xFF);
+ outb_reg0(dep, DP_RSAR1, nic_addr >> 8);
+ outb_reg0(dep, DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA);
+
+ i= 0;
+ while (count > 0)
+ {
+ if (i >= IOVEC_NR)
+ {
+ dp_next_iovec(iovp);
+ i= 0;
+ continue;
+ }
+ assert(i < iovp->iod_iovec_s);
+ if (offset >= iovp->iod_iovec[i].iov_size)
+ {
+ offset -= iovp->iod_iovec[i].iov_size;
+ i++;
+ continue;
+ }
+ bytes = iovp->iod_iovec[i].iov_size - offset;
+ if (bytes > count)
+ bytes = count;
+
+ user_proc= iovp->iod_proc_nr;
+ vir_user= iovp->iod_iovec[i].iov_addr + offset;
+ if (odd_byte)
+ {
+ r= sys_vircopy(SELF, D, (vir_bytes)&two_bytes[1],
+ user_proc, D, vir_user, 1);
+ if (r != OK)
+ {
+ panic("DP8390",
+ "dp_pio16_nic2user: sys_vircopy failed",
+ r);
+ }
+ count--;
+ offset++;
+ bytes--;
+ vir_user++;
+ odd_byte= 0;
+ if (!bytes)
+ continue;
+ }
+ ecount= bytes & ~1;
+ if (ecount != 0)
+ {
+ do_vir_insw(dep->de_data_port, user_proc, vir_user,
+ ecount);
+ count -= ecount;
+ offset += ecount;
+ bytes -= ecount;
+ vir_user += ecount;
+ }
+ if (bytes)
+ {
+ assert(bytes == 1);
+ *(u16_t *)two_bytes= inw(dep->de_data_port);
+ r= sys_vircopy(SELF, D, (vir_bytes)&two_bytes[0],
+ user_proc, D, vir_user, 1);
+ if (r != OK)
+ {
+ panic("DP8390",
+ "dp_pio16_nic2user: sys_vircopy failed",
+ r);
+ }
+ count--;
+ offset++;
+ bytes--;
+ vir_user++;
+ odd_byte= 1;
+ }
+ }
+ assert(count == 0);
+}
+
+
+/*===========================================================================*
+ * dp_next_iovec *
+ *===========================================================================*/
+static void dp_next_iovec(iovp)
+iovec_dat_t *iovp;
+{
+ assert(iovp->iod_iovec_s > IOVEC_NR);
+
+ iovp->iod_iovec_s -= IOVEC_NR;
+
+ iovp->iod_iovec_addr += IOVEC_NR * sizeof(iovec_t);
+
+ get_userdata(iovp->iod_proc_nr, iovp->iod_iovec_addr,
+ (iovp->iod_iovec_s > IOVEC_NR ? IOVEC_NR : iovp->iod_iovec_s) *
+ sizeof(iovec_t), iovp->iod_iovec);
+}
+
+
+/*===========================================================================*
+ * conf_hw *
+ *===========================================================================*/
+static void conf_hw(dep)
+dpeth_t *dep;
+{
+ static eth_stat_t empty_stat = {0, 0, 0, 0, 0, 0 /* ,... */ };
+
+ int ifnr;
+ dp_conf_t *dcp;
+
+ dep->de_mode= DEM_DISABLED; /* Superfluous */
+ ifnr= dep-de_table;
+
+ dcp= &dp_conf[ifnr];
+ update_conf(dep, dcp);
+ if (dep->de_mode != DEM_ENABLED)
+ return;
+ if (!wdeth_probe(dep) && !ne_probe(dep) && !el2_probe(dep))
+ {
+ printf("%s: No ethernet card found at 0x%x\n",
+ dep->de_name, dep->de_base_port);
+ dep->de_mode= DEM_DISABLED;
+ return;
+ }
+
+/* XXX */ if (dep->de_linmem == 0) dep->de_linmem= 0xFFFF0000;
+
+ dep->de_flags = DEF_EMPTY;
+ dep->de_stat = empty_stat;
+}
+
+
+/*===========================================================================*
+ * update_conf *
+ *===========================================================================*/
+static void update_conf(dep, dcp)
+dpeth_t *dep;
+dp_conf_t *dcp;
+{
+ long v;
+ static char dpc_fmt[] = "x:d:x:x";
+
+#if ENABLE_PCI
+ if (dep->de_pci)
+ {
+ if (dep->de_pci == 1)
+ {
+ /* PCI device is present */
+ dep->de_mode= DEM_ENABLED;
+ }
+ return; /* Already configured */
+ }
+#endif
+
+ /* Get the default settings and modify them from the environment. */
+ dep->de_mode= DEM_SINK;
+ v= dcp->dpc_port;
+ switch (env_parse_x(arg_c, arg_v,
+ dcp->dpc_envvar, dpc_fmt, 0, &v, 0x0000L, 0xFFFFL)) {
+ case EP_OFF:
+ dep->de_mode= DEM_DISABLED;
+ break;
+ case EP_ON:
+ case EP_SET:
+ dep->de_mode= DEM_ENABLED; /* Might become disabled if
+ * all probes fail */
+ break;
+ }
+ dep->de_base_port= v;
+
+ v= dcp->dpc_irq | DEI_DEFAULT;
+ (void) env_parse_x(arg_c, arg_v, dcp->dpc_envvar, dpc_fmt, 1, &v, 0L,
+ (long) NR_IRQ_VECTORS - 1);
+ dep->de_irq= v;
+
+ v= dcp->dpc_mem;
+ (void) env_parse_x(arg_c, arg_v,
+ dcp->dpc_envvar, dpc_fmt, 2, &v, 0L, 0xFFFFFL);
+ dep->de_linmem= v;
+
+ v= 0;
+ (void) env_parse_x(arg_c, arg_v,
+ dcp->dpc_envvar, dpc_fmt, 3, &v, 0x2000L, 0x8000L);
+ dep->de_ramsize= v;
+}
+
+
+/*===========================================================================*
+ * calc_iovec_size *
+ *===========================================================================*/
+static int calc_iovec_size(iovp)
+iovec_dat_t *iovp;
+{
+ /* Calculate the size of a request. Note that the iovec_dat
+ * structure will be unusable after calc_iovec_size.
+ */
+ int size;
+ int i;
+
+ size= 0;
+ i= 0;
+ while (i < iovp->iod_iovec_s)
+ {
+ if (i >= IOVEC_NR)
+ {
+ dp_next_iovec(iovp);
+ i= 0;
+ continue;
+ }
+ size += iovp->iod_iovec[i].iov_size;
+ i++;
+ }
+ return size;
+}
+
+
+/*===========================================================================*
+ * reply *
+ *===========================================================================*/
+static void reply(dep, err, may_block)
+dpeth_t *dep;
+int err;
+int may_block;
+{
+ message reply;
+ int status;
+ int r;
+
+ status = 0;
+ if (dep->de_flags & DEF_PACK_SEND)
+ status |= DL_PACK_SEND;
+ if (dep->de_flags & DEF_PACK_RECV)
+ status |= DL_PACK_RECV;
+
+ reply.m_type = DL_TASK_REPLY;
+ reply.DL_PORT = dep - de_table;
+ reply.DL_PROC = dep->de_client;
+ reply.DL_STAT = status | ((u32_t) err << 16);
+ reply.DL_COUNT = dep->de_read_s;
+ reply.DL_CLCK = 0; /* Don't know */
+ r= send(dep->de_client, &reply);
+
+ if (r == ELOCKED && may_block)
+ {
+ printf("send locked\n");
+ return;
+ }
+
+ if (r < 0)
+ panic("", "dp8390: send failed:", r);
+
+ dep->de_read_s = 0;
+ dep->de_flags &= ~(DEF_PACK_SEND | DEF_PACK_RECV);
+}
+
+
+/*===========================================================================*
+ * mess_reply *
+ *===========================================================================*/
+static void mess_reply(req, reply_mess)
+message *req;
+message *reply_mess;
+{
+ if (send(req->m_source, reply_mess) != OK)
+ panic("", "dp8390: unable to mess_reply", NO_NUM);
+}
+
+
+/*===========================================================================*
+ * get_userdata *
+ *===========================================================================*/
+static void get_userdata(user_proc, user_addr, count, loc_addr)
+int user_proc;
+vir_bytes user_addr;
+vir_bytes count;
+void *loc_addr;
+{
+ int r;
+
+ r= sys_vircopy(user_proc, D, user_addr,
+ SELF, D, (vir_bytes)loc_addr, count);
+ if (r != OK)
+ panic("DP8390", "get_userdata: sys_vircopy failed", r);
+}
+
+
+/*===========================================================================*
+ * put_userdata *
+ *===========================================================================*/
+static void put_userdata(user_proc, user_addr, count, loc_addr)
+int user_proc;
+vir_bytes user_addr;
+vir_bytes count;
+void *loc_addr;
+{
+ int r;
+
+ r= sys_vircopy(SELF, D, (vir_bytes)loc_addr,
+ user_proc, D, user_addr, count);
+ if (r != OK)
+ panic("DP8390", "put_userdata: sys_vircopy failed", r);
+}
+
+u8_t inb(port_t port)
+{
+ int r;
+ u8_t value;
+
+ r= sys_inb(port, &value);
+ if (r != OK)
+ panic("DP8390","sys_inb failed", r);
+ return value;
+}
+
+u16_t inw(port_t port)
+{
+ int r;
+ u16_t value;
+
+ r= sys_inw(port, &value);
+ if (r != OK)
+ panic("DP8390", "sys_inw failed", r);
+ return value;
+}
+
+void outb(port_t port, u8_t value)
+{
+ int r;
+
+ r= sys_outb(port, value);
+ if (r != OK)
+ panic("DP8390", "sys_outb failed", r);
+}
+
+void outw(port_t port, u16_t value)
+{
+ int r;
+
+ r= sys_outw(port, value);
+ if (r != OK)
+ panic("DP8390", "sys_outw failed", r);
+}
+
+static void insb(port_t port, void *buf, size_t size)
+{
+ do_vir_insb(port, SELF, (vir_bytes)buf, size);
+}
+
+static void insw(port_t port, void *buf, size_t size)
+{
+ do_vir_insw(port, SELF, (vir_bytes)buf, size);
+}
+
+static void do_vir_insb(port_t port, int proc, vir_bytes buf, size_t size)
+{
+ int r;
+
+ r= sys_sdevio(DIO_INPUT, port, DIO_BYTE, proc, (void *)buf, size);
+ if (r != OK)
+ panic("DP8390", "sys_sdevio failed", r);
+}
+
+static void do_vir_insw(port_t port, int proc, vir_bytes buf, size_t size)
+{
+ int r;
+
+ r= sys_sdevio(DIO_INPUT, port, DIO_WORD, proc, (void *)buf, size);
+ if (r != OK)
+ panic("DP8390", "sys_sdevio failed", r);
+}
+
+static void do_vir_outsb(port_t port, int proc, vir_bytes buf, size_t size)
+{
+ int r;
+
+ r= sys_sdevio(DIO_OUTPUT, port, DIO_BYTE, proc, (void *)buf, size);
+ if (r != OK)
+ panic("DP8390", "sys_sdevio failed", r);
+}
+
+static void do_vir_outsw(port_t port, int proc, vir_bytes buf, size_t size)
+{
+ int r;
+
+ r= sys_sdevio(DIO_OUTPUT, port, DIO_WORD, proc, (void *)buf, size);
+ if (r != OK)
+ panic("DP8390", "sys_sdevio failed", r);
+}
+
+
+/*
+ * $PchId: dp8390.c,v 1.25 2005/02/10 17:32:07 philip Exp $
+ */
--- /dev/null
+/*
+dp8390.h
+
+Created: before Dec 28, 1992 by Philip Homburg
+*/
+
+/* National Semiconductor DP8390 Network Interface Controller. */
+
+ /* Page 0, for reading ------------- */
+#define DP_CR 0x0 /* Read side of Command Register */
+#define DP_CLDA0 0x1 /* Current Local Dma Address 0 */
+#define DP_CLDA1 0x2 /* Current Local Dma Address 1 */
+#define DP_BNRY 0x3 /* Boundary Pointer */
+#define DP_TSR 0x4 /* Transmit Status Register */
+#define DP_NCR 0x5 /* Number of Collisions Register */
+#define DP_FIFO 0x6 /* Fifo ?? */
+#define DP_ISR 0x7 /* Interrupt Status Register */
+#define DP_CRDA0 0x8 /* Current Remote Dma Address 0 */
+#define DP_CRDA1 0x9 /* Current Remote Dma Address 1 */
+#define DP_DUM1 0xA /* unused */
+#define DP_DUM2 0xB /* unused */
+#define DP_RSR 0xC /* Receive Status Register */
+#define DP_CNTR0 0xD /* Tally Counter 0 */
+#define DP_CNTR1 0xE /* Tally Counter 1 */
+#define DP_CNTR2 0xF /* Tally Counter 2 */
+
+ /* Page 0, for writing ------------- */
+#define DP_CR 0x0 /* Write side of Command Register */
+#define DP_PSTART 0x1 /* Page Start Register */
+#define DP_PSTOP 0x2 /* Page Stop Register */
+#define DP_BNRY 0x3 /* Boundary Pointer */
+#define DP_TPSR 0x4 /* Transmit Page Start Register */
+#define DP_TBCR0 0x5 /* Transmit Byte Count Register 0 */
+#define DP_TBCR1 0x6 /* Transmit Byte Count Register 1 */
+#define DP_ISR 0x7 /* Interrupt Status Register */
+#define DP_RSAR0 0x8 /* Remote Start Address Register 0 */
+#define DP_RSAR1 0x9 /* Remote Start Address Register 1 */
+#define DP_RBCR0 0xA /* Remote Byte Count Register 0 */
+#define DP_RBCR1 0xB /* Remote Byte Count Register 1 */
+#define DP_RCR 0xC /* Receive Configuration Register */
+#define DP_TCR 0xD /* Transmit Configuration Register */
+#define DP_DCR 0xE /* Data Configuration Register */
+#define DP_IMR 0xF /* Interrupt Mask Register */
+
+ /* Page 1, read/write -------------- */
+#define DP_CR 0x0 /* Command Register */
+#define DP_PAR0 0x1 /* Physical Address Register 0 */
+#define DP_PAR1 0x2 /* Physical Address Register 1 */
+#define DP_PAR2 0x3 /* Physical Address Register 2 */
+#define DP_PAR3 0x4 /* Physical Address Register 3 */
+#define DP_PAR4 0x5 /* Physical Address Register 4 */
+#define DP_PAR5 0x6 /* Physical Address Register 5 */
+#define DP_CURR 0x7 /* Current Page Register */
+#define DP_MAR0 0x8 /* Multicast Address Register 0 */
+#define DP_MAR1 0x9 /* Multicast Address Register 1 */
+#define DP_MAR2 0xA /* Multicast Address Register 2 */
+#define DP_MAR3 0xB /* Multicast Address Register 3 */
+#define DP_MAR4 0xC /* Multicast Address Register 4 */
+#define DP_MAR5 0xD /* Multicast Address Register 5 */
+#define DP_MAR6 0xE /* Multicast Address Register 6 */
+#define DP_MAR7 0xF /* Multicast Address Register 7 */
+
+/* Bits in dp_cr */
+#define CR_STP 0x01 /* Stop: software reset */
+#define CR_STA 0x02 /* Start: activate NIC */
+#define CR_TXP 0x04 /* Transmit Packet */
+#define CR_DMA 0x38 /* Mask for DMA control */
+#define CR_DM_NOP 0x00 /* DMA: No Operation */
+#define CR_DM_RR 0x08 /* DMA: Remote Read */
+#define CR_DM_RW 0x10 /* DMA: Remote Write */
+#define CR_DM_SP 0x18 /* DMA: Send Packet */
+#define CR_DM_ABORT 0x20 /* DMA: Abort Remote DMA Operation */
+#define CR_PS 0xC0 /* Mask for Page Select */
+#define CR_PS_P0 0x00 /* Register Page 0 */
+#define CR_PS_P1 0x40 /* Register Page 1 */
+#define CR_PS_P2 0x80 /* Register Page 2 */
+#define CR_PS_T1 0xC0 /* Test Mode Register Map */
+
+/* Bits in dp_isr */
+#define ISR_PRX 0x01 /* Packet Received with no errors */
+#define ISR_PTX 0x02 /* Packet Transmitted with no errors */
+#define ISR_RXE 0x04 /* Receive Error */
+#define ISR_TXE 0x08 /* Transmit Error */
+#define ISR_OVW 0x10 /* Overwrite Warning */
+#define ISR_CNT 0x20 /* Counter Overflow */
+#define ISR_RDC 0x40 /* Remote DMA Complete */
+#define ISR_RST 0x80 /* Reset Status */
+
+/* Bits in dp_imr */
+#define IMR_PRXE 0x01 /* Packet Received iEnable */
+#define IMR_PTXE 0x02 /* Packet Transmitted iEnable */
+#define IMR_RXEE 0x04 /* Receive Error iEnable */
+#define IMR_TXEE 0x08 /* Transmit Error iEnable */
+#define IMR_OVWE 0x10 /* Overwrite Warning iEnable */
+#define IMR_CNTE 0x20 /* Counter Overflow iEnable */
+#define IMR_RDCE 0x40 /* DMA Complete iEnable */
+
+/* Bits in dp_dcr */
+#define DCR_WTS 0x01 /* Word Transfer Select */
+#define DCR_BYTEWIDE 0x00 /* WTS: byte wide transfers */
+#define DCR_WORDWIDE 0x01 /* WTS: word wide transfers */
+#define DCR_BOS 0x02 /* Byte Order Select */
+#define DCR_LTLENDIAN 0x00 /* BOS: Little Endian */
+#define DCR_BIGENDIAN 0x02 /* BOS: Big Endian */
+#define DCR_LAS 0x04 /* Long Address Select */
+#define DCR_BMS 0x08 /* Burst Mode Select
+ * Called Loopback Select (LS) in
+ * later manuals. Should be set. */
+#define DCR_AR 0x10 /* Autoinitialize Remote */
+#define DCR_FTS 0x60 /* Fifo Threshold Select */
+#define DCR_2BYTES 0x00 /* 2 bytes */
+#define DCR_4BYTES 0x40 /* 4 bytes */
+#define DCR_8BYTES 0x20 /* 8 bytes */
+#define DCR_12BYTES 0x60 /* 12 bytes */
+
+/* Bits in dp_tcr */
+#define TCR_CRC 0x01 /* Inhibit CRC */
+#define TCR_ELC 0x06 /* Encoded Loopback Control */
+#define TCR_NORMAL 0x00 /* ELC: Normal Operation */
+#define TCR_INTERNAL 0x02 /* ELC: Internal Loopback */
+#define TCR_0EXTERNAL 0x04 /* ELC: External Loopback LPBK=0 */
+#define TCR_1EXTERNAL 0x06 /* ELC: External Loopback LPBK=1 */
+#define TCR_ATD 0x08 /* Auto Transmit Disable */
+#define TCR_OFST 0x10 /* Collision Offset Enable (be nice) */
+
+/* Bits in dp_tsr */
+#define TSR_PTX 0x01 /* Packet Transmitted (without error)*/
+#define TSR_DFR 0x02 /* Transmit Deferred, reserved in
+ * later manuals. */
+#define TSR_COL 0x04 /* Transmit Collided */
+#define TSR_ABT 0x08 /* Transmit Aborted */
+#define TSR_CRS 0x10 /* Carrier Sense Lost */
+#define TSR_FU 0x20 /* FIFO Underrun */
+#define TSR_CDH 0x40 /* CD Heartbeat */
+#define TSR_OWC 0x80 /* Out of Window Collision */
+
+/* Bits in tp_rcr */
+#define RCR_SEP 0x01 /* Save Errored Packets */
+#define RCR_AR 0x02 /* Accept Runt Packets */
+#define RCR_AB 0x04 /* Accept Broadcast */
+#define RCR_AM 0x08 /* Accept Multicast */
+#define RCR_PRO 0x10 /* Physical Promiscuous */
+#define RCR_MON 0x20 /* Monitor Mode */
+
+/* Bits in dp_rsr */
+#define RSR_PRX 0x01 /* Packet Received Intact */
+#define RSR_CRC 0x02 /* CRC Error */
+#define RSR_FAE 0x04 /* Frame Alignment Error */
+#define RSR_FO 0x08 /* FIFO Overrun */
+#define RSR_MPA 0x10 /* Missed Packet */
+#define RSR_PHY 0x20 /* Multicast Address Match */
+#define RSR_DIS 0x40 /* Receiver Disabled */
+#define RSR_DFR 0x80 /* In later manuals: Deferring */
+
+
+typedef struct dp_rcvhdr
+{
+ u8_t dr_status; /* Copy of rsr */
+ u8_t dr_next; /* Pointer to next packet */
+ u8_t dr_rbcl; /* Receive Byte Count Low */
+ u8_t dr_rbch; /* Receive Byte Count High */
+} dp_rcvhdr_t;
+
+#define DP_PAGESIZE 256
+
+/* Some macros to simplify accessing the dp8390 */
+#define inb_reg0(dep, reg) (inb(dep->de_dp8390_port+reg))
+#define outb_reg0(dep, reg, data) (outb(dep->de_dp8390_port+reg, data))
+#define inb_reg1(dep, reg) (inb(dep->de_dp8390_port+reg))
+#define outb_reg1(dep, reg, data) (outb(dep->de_dp8390_port+reg, data))
+
+/* Software interface to the dp8390 driver */
+
+struct dpeth;
+struct iovec_dat;
+_PROTOTYPE( typedef void (*dp_initf_t), (struct dpeth *dep) );
+_PROTOTYPE( typedef void (*dp_stopf_t), (struct dpeth *dep) );
+_PROTOTYPE( typedef void (*dp_user2nicf_t), (struct dpeth *dep,
+ struct iovec_dat *iovp, vir_bytes offset,
+ int nic_addr, vir_bytes count) );
+_PROTOTYPE( typedef void (*dp_nic2userf_t), (struct dpeth *dep,
+ int nic_addr, struct iovec_dat *iovp,
+ vir_bytes offset, vir_bytes count) );
+#if 0
+_PROTOTYPE( typedef void (*dp_getheaderf_t), (struct dpeth *dep,
+ int page, struct dp_rcvhdr *h, u16_t *eth_type) );
+#endif
+_PROTOTYPE( typedef void (*dp_getblock_t), (struct dpeth *dep,
+ int page, size_t offset, size_t size, void *dst) );
+
+/* iovectors are handled IOVEC_NR entries at a time. */
+#define IOVEC_NR 16
+
+typedef int irq_hook_t;
+
+typedef struct iovec_dat
+{
+ iovec_t iod_iovec[IOVEC_NR];
+ int iod_iovec_s;
+ int iod_proc_nr;
+ vir_bytes iod_iovec_addr;
+} iovec_dat_t;
+
+#define SENDQ_NR 2 /* Maximum size of the send queue */
+#define SENDQ_PAGES 6 /* 6 * DP_PAGESIZE >= 1514 bytes */
+
+typedef struct dpeth
+{
+ /* The de_base_port field is the starting point of the probe.
+ * The conf routine also fills de_linmem and de_irq. If the probe
+ * routine knows the irq and/or memory address because they are
+ * hardwired in the board, the probe should modify these fields.
+ * Futhermore, the probe routine should also fill in de_initf and
+ * de_stopf fields with the appropriate function pointers and set
+ * de_prog_IO iff programmed I/O is to be used.
+ */
+ port_t de_base_port;
+ phys_bytes de_linmem;
+ int de_irq;
+ int de_int_pending;
+ irq_hook_t de_hook;
+ 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;
+ 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;
+
+#if ENABLE_PCI
+ /* PCI config */
+ char de_pci; /* TRUE iff PCI device */
+ u8_t de_pcibus;
+ u8_t de_pcidev;
+ u8_t de_pcifunc;
+#endif
+
+ /* Do it yourself send queue */
+ struct sendq
+ {
+ int sq_filled; /* this buffer contains a packet */
+ 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 */
+
+ /* Fields for internal use by the dp8390 driver. */
+ int de_flags;
+ int de_mode;
+ eth_stat_t de_stat;
+ iovec_dat_t de_read_iovec;
+ iovec_dat_t de_write_iovec;
+ iovec_dat_t de_tmp_iovec;
+ vir_bytes de_read_s;
+ int de_client;
+ message de_sendmsg;
+ dp_user2nicf_t de_user2nicf;
+ dp_nic2userf_t de_nic2userf;
+ dp_getblock_t de_getblockf;
+} dpeth_t;
+
+#define DEI_DEFAULT 0x8000
+
+#define DEF_EMPTY 0x000
+#define DEF_PACK_SEND 0x001
+#define DEF_PACK_RECV 0x002
+#define DEF_SEND_AVAIL 0x004
+#define DEF_READING 0x010
+#define DEF_PROMISC 0x040
+#define DEF_MULTI 0x080
+#define DEF_BROAD 0x100
+#define DEF_ENABLED 0x200
+#define DEF_STOPPED 0x400
+
+#define DEM_DISABLED 0x0
+#define DEM_SINK 0x1
+#define DEM_ENABLED 0x2
+
+#if !__minix_vmd
+#define debug 0 /* Standard Minix lacks debug variable */
+#endif
+
+/*
+ * $PchId: dp8390.h,v 1.10 2005/02/10 17:26:06 philip Exp $
+ */
--- /dev/null
+/*
+local.h
+*/
+
+#define ENABLE_WDETH 1
+#define ENABLE_NE2000 1
+#define ENABLE_3C503 1
+#define ENABLE_PCI 1
+
+struct dpeth;
+
+/* 3c503.c */
+_PROTOTYPE( int el2_probe, (struct dpeth* dep) );
+
+/* dp8390.c */
+_PROTOTYPE( u8_t inb, (port_t port) );
+_PROTOTYPE( u16_t inw, (port_t port) );
+_PROTOTYPE( void outb, (port_t port, u8_t v) );
+_PROTOTYPE( void outw, (port_t port, u16_t v) );
+
+/* ne2000.c */
+_PROTOTYPE( int ne_probe, (struct dpeth *dep) );
+_PROTOTYPE( void ne_init, (struct dpeth *dep) );
+
+/* rtl8029.c */
+_PROTOTYPE( int rtl_probe, (struct dpeth *dep) );
+
+/* wdeth.c */
+_PROTOTYPE( int wdeth_probe, (struct dpeth* dep) );
+
--- /dev/null
+/*
+ne2000.c
+
+Driver for the ne2000 ethernet cards. This file contains only the ne2000
+specific code, the rest is in dp8390.c
+
+Created: March 15, 1994 by Philip Homburg <philip@f-mnx.phicoh.com>
+*/
+
+#include "../drivers.h"
+
+#include <net/gen/ether.h>
+#include <net/gen/eth_io.h>
+#if __minix_vmd
+#include "config.h"
+#endif
+
+#include "local.h"
+#include "dp8390.h"
+#include "ne2000.h"
+
+#if ENABLE_NE2000
+
+#define N 100
+
+#define MILLIS_TO_TICKS(m) (((m)*HZ/1000)+1)
+
+_PROTOTYPE( typedef int (*testf_t), (dpeth_t *dep, int pos, u8_t *pat) );
+
+u8_t pat0[]= { 0x00, 0x00, 0x00, 0x00 };
+u8_t pat1[]= { 0xFF, 0xFF, 0xFF, 0xFF };
+u8_t pat2[]= { 0xA5, 0x5A, 0x69, 0x96 };
+u8_t pat3[]= { 0x96, 0x69, 0x5A, 0xA5 };
+
+_PROTOTYPE( static int test_8, (dpeth_t *dep, int pos, u8_t *pat) );
+_PROTOTYPE( static int test_16, (dpeth_t *dep, int pos, u8_t *pat) );
+_PROTOTYPE( static void ne_stop, (dpeth_t *dep) );
+_PROTOTYPE( static void milli_delay, (unsigned long millis) );
+
+/*===========================================================================*
+ * ne_probe *
+ *===========================================================================*/
+int ne_probe(dep)
+dpeth_t *dep;
+{
+ int byte;
+ int i;
+ int loc1, loc2;
+ testf_t f;
+
+ dep->de_dp8390_port= dep->de_base_port + NE_DP8390;
+
+ /* We probe for an ne1000 or an ne2000 by testing whether the
+ * on board is reachable through the dp8390. Note that the
+ * ne1000 is an 8bit card and has a memory region distict from
+ * the 16bit ne2000
+ */
+
+ for (dep->de_16bit= 0; dep->de_16bit < 2; dep->de_16bit++)
+ {
+ /* Reset the ethernet card */
+ byte= inb_ne(dep, NE_RESET);
+ milli_delay(2);
+ outb_ne(dep, NE_RESET, byte);
+ milli_delay(2);
+
+ /* Reset the dp8390 */
+ outb_reg0(dep, DP_CR, CR_STP | CR_DM_ABORT);
+ for (i= 0; i < 0x1000 && ((inb_reg0(dep, DP_ISR) & ISR_RST) == 0); i++)
+ ; /* Do nothing */
+
+ /* Check if the dp8390 is really there */
+ if ((inb_reg0(dep, DP_CR) & (CR_STP|CR_DM_ABORT)) !=
+ (CR_STP|CR_DM_ABORT))
+ {
+ return 0;
+ }
+
+ /* Disable the receiver and init TCR and DCR. */
+ outb_reg0(dep, DP_RCR, RCR_MON);
+ outb_reg0(dep, DP_TCR, TCR_NORMAL);
+ if (dep->de_16bit)
+ {
+ outb_reg0(dep, DP_DCR, DCR_WORDWIDE | DCR_8BYTES |
+ DCR_BMS);
+ }
+ else
+ {
+ outb_reg0(dep, DP_DCR, DCR_BYTEWIDE | DCR_8BYTES |
+ DCR_BMS);
+ }
+
+ if (dep->de_16bit)
+ {
+ loc1= NE2000_START;
+ loc2= NE2000_START + NE2000_SIZE - 4;
+ f= test_16;
+ }
+ else
+ {
+ loc1= NE1000_START;
+ loc2= NE1000_START + NE1000_SIZE - 4;
+ f= test_8;
+ }
+ if (f(dep, loc1, pat0) && f(dep, loc1, pat1) &&
+ f(dep, loc1, pat2) && f(dep, loc1, pat3) &&
+ f(dep, loc2, pat0) && f(dep, loc2, pat1) &&
+ f(dep, loc2, pat2) && f(dep, loc2, pat3))
+ {
+ /* We don't need a memory segment */
+ dep->de_linmem= 0;
+ if (!dep->de_pci)
+ dep->de_initf= ne_init;
+ dep->de_stopf= ne_stop;
+ dep->de_prog_IO= 1;
+ return 1;
+ }
+ }
+ return 0;
+}
+
+
+/*===========================================================================*
+ * ne_init *
+ *===========================================================================*/
+void ne_init(dep)
+dpeth_t *dep;
+{
+ int i;
+ int word, sendq_nr;
+
+ /* Setup a transfer to get the ethernet address. */
+ if (dep->de_16bit)
+ outb_reg0(dep, DP_RBCR0, 6*2);
+ else
+ outb_reg0(dep, DP_RBCR0, 6);
+ outb_reg0(dep, DP_RBCR1, 0);
+ outb_reg0(dep, DP_RSAR0, 0);
+ outb_reg0(dep, DP_RSAR1, 0);
+ outb_reg0(dep, DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA);
+
+ for (i= 0; i<6; i++)
+ {
+ if (dep->de_16bit)
+ {
+ word= inw_ne(dep, NE_DATA);
+ dep->de_address.ea_addr[i]= word;
+ }
+ else
+ {
+ dep->de_address.ea_addr[i] = inb_ne(dep, NE_DATA);
+ }
+ }
+ dep->de_data_port= dep->de_base_port + NE_DATA;
+ if (dep->de_16bit)
+ {
+ dep->de_ramsize= NE2000_SIZE;
+ dep->de_offset_page= NE2000_START / DP_PAGESIZE;
+ }
+ else
+ {
+ dep->de_ramsize= NE1000_SIZE;
+ dep->de_offset_page= NE1000_START / DP_PAGESIZE;
+ }
+
+ /* Allocate one send buffer (1.5KB) per 8KB of on board memory. */
+ sendq_nr= dep->de_ramsize / 0x2000;
+ if (sendq_nr < 1)
+ sendq_nr= 1;
+ else if (sendq_nr > SENDQ_NR)
+ sendq_nr= SENDQ_NR;
+ dep->de_sendq_nr= sendq_nr;
+ for (i= 0; i<sendq_nr; i++)
+ {
+ dep->de_sendq[i].sq_sendpage= dep->de_offset_page +
+ i*SENDQ_PAGES;
+ }
+
+ dep->de_startpage= dep->de_offset_page + i*SENDQ_PAGES;
+ dep->de_stoppage= dep->de_offset_page + dep->de_ramsize / DP_PAGESIZE;
+
+ /* Can't override the default IRQ. */
+ dep->de_irq &= ~DEI_DEFAULT;
+
+ if (!debug)
+ {
+ printf("%s: NE%d000 at %X:%d\n",
+ dep->de_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,
+ dep->de_base_port, dep->de_ramsize, dep->de_irq);
+ }
+}
+
+
+/*===========================================================================*
+ * test_8 *
+ *===========================================================================*/
+static int test_8(dep, pos, pat)
+dpeth_t *dep;
+int pos;
+u8_t *pat;
+{
+ u8_t buf[4];
+ int i;
+ int r;
+
+ outb_reg0(dep, DP_ISR, 0xFF);
+
+ /* Setup a transfer to put the pattern. */
+ outb_reg0(dep, DP_RBCR0, 4);
+ outb_reg0(dep, DP_RBCR1, 0);
+ outb_reg0(dep, DP_RSAR0, pos & 0xFF);
+ outb_reg0(dep, DP_RSAR1, pos >> 8);
+ outb_reg0(dep, DP_CR, CR_DM_RW | CR_PS_P0 | CR_STA);
+
+ for (i= 0; i<4; i++)
+ outb_ne(dep, NE_DATA, pat[i]);
+
+ for (i= 0; i<N; i++)
+ {
+ if (inb_reg0(dep, DP_ISR) & ISR_RDC)
+ break;
+ }
+ if (i == N)
+ {
+ if (debug)
+ {
+ printf("%s: NE1000 remote DMA test failed\n",
+ dep->de_name);
+ }
+ return 0;
+ }
+
+ outb_reg0(dep, DP_RBCR0, 4);
+ outb_reg0(dep, DP_RBCR1, 0);
+ outb_reg0(dep, DP_RSAR0, pos & 0xFF);
+ outb_reg0(dep, DP_RSAR1, pos >> 8);
+ outb_reg0(dep, DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA);
+
+ for (i= 0; i<4; i++)
+ buf[i]= inb_ne(dep, NE_DATA);
+
+ r= (memcmp(buf, pat, 4) == 0);
+ return r;
+}
+
+
+/*===========================================================================*
+ * test_16 *
+ *===========================================================================*/
+static int test_16(dep, pos, pat)
+dpeth_t *dep;
+int pos;
+u8_t *pat;
+{
+ u8_t buf[4];
+ int i;
+ int r;
+
+ outb_reg0(dep, DP_ISR, 0xFF);
+
+ /* Setup a transfer to put the pattern. */
+ outb_reg0(dep, DP_RBCR0, 4);
+ outb_reg0(dep, DP_RBCR1, 0);
+ outb_reg0(dep, DP_RSAR0, pos & 0xFF);
+ outb_reg0(dep, DP_RSAR1, pos >> 8);
+ outb_reg0(dep, DP_CR, CR_DM_RW | CR_PS_P0 | CR_STA);
+
+ for (i= 0; i<4; i += 2)
+ {
+ outw_ne(dep, NE_DATA, *(u16_t *)(pat+i));
+ }
+
+ for (i= 0; i<N; i++)
+ {
+ if (inb_reg0(dep, DP_ISR) & ISR_RDC)
+ break;
+ }
+ if (i == N)
+ {
+ if (debug)
+ {
+ printf("%s: NE2000 remote DMA test failed\n",
+ dep->de_name);
+ }
+ return 0;
+ }
+
+ outb_reg0(dep, DP_RBCR0, 4);
+ outb_reg0(dep, DP_RBCR1, 0);
+ outb_reg0(dep, DP_RSAR0, pos & 0xFF);
+ outb_reg0(dep, DP_RSAR1, pos >> 8);
+ outb_reg0(dep, DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA);
+
+ for (i= 0; i<4; i += 2)
+ {
+ *(u16_t *)(buf+i)= inw_ne(dep, NE_DATA);
+ }
+
+ r= (memcmp(buf, pat, 4) == 0);
+ return r;
+}
+
+
+/*===========================================================================*
+ * ne_stop *
+ *===========================================================================*/
+static void ne_stop(dep)
+dpeth_t *dep;
+{
+ int byte;
+
+ /* Reset the ethernet card */
+ byte= inb_ne(dep, NE_RESET);
+ milli_delay(2);
+ outb_ne(dep, NE_RESET, byte);
+}
+
+static void milli_delay(unsigned long millis)
+{
+ tickdelay(MILLIS_TO_TICKS(millis));
+}
+
+#endif /* ENABLE_NE2000 */
+
+/*
+ * $PchId: ne2000.c,v 1.10 2004/08/03 12:03:00 philip Exp $
+ */
--- /dev/null
+/*
+ne2000.h
+
+Created: March 15, 1994 by Philip Homburg <philip@f-mnx.phicoh.com>
+*/
+
+#ifndef NE2000_H
+#define NE2000_H
+
+#define NE_DP8390 0x00
+#define NE_DATA 0x10
+#define NE_RESET 0x1F
+
+#define NE1000_START 0x2000
+#define NE1000_SIZE 0x2000
+#define NE2000_START 0x4000
+#define NE2000_SIZE 0x4000
+
+#define inb_ne(dep, reg) (inb(dep->de_base_port+reg))
+#define outb_ne(dep, reg, data) (outb(dep->de_base_port+reg, data))
+#define inw_ne(dep, reg) (inw(dep->de_base_port+reg))
+#define outw_ne(dep, reg, data) (outw(dep->de_base_port+reg, data))
+
+#endif /* NE2000_H */
+
+/*
+ * $PchId: ne2000.h,v 1.4 2004/08/03 12:03:20 philip Exp $
+ */
--- /dev/null
+/*
+rtl8029.c
+
+Initialization of PCI DP8390-based ethernet cards
+
+Created: April 2000 by Philip Homburg <philip@f-mnx.phicoh.com>
+*/
+
+#include "../drivers.h"
+
+#include <stdlib.h>
+#include <sys/types.h>
+#include <net/gen/ether.h>
+#include <net/gen/eth_io.h>
+
+#include "assert.h"
+#include "../libpci/pci.h"
+
+#include "local.h"
+#include "dp8390.h"
+#include "rtl8029.h"
+
+#if ENABLE_PCI
+
+#define MICROS_TO_TICKS(m) (((m)*HZ/1000000)+1)
+
+PRIVATE struct pcitab
+{
+ u16_t vid;
+ u16_t did;
+ int checkclass;
+} pcitab[]=
+{
+ { 0x10ec, 0x8029, 0 }, /* Realtek RTL8029 */
+
+ { 0x0000, 0x0000, 0 }
+};
+
+_PROTOTYPE( static void rtl_init, (struct dpeth *dep) );
+_PROTOTYPE( static u16_t get_ee_word, (dpeth_t *dep, int a) );
+_PROTOTYPE( static void ee_wen, (dpeth_t *dep) );
+_PROTOTYPE( static void set_ee_word, (dpeth_t *dep, int a, U16_t w) );
+_PROTOTYPE( static void ee_wds, (dpeth_t *dep) );
+_PROTOTYPE( static void micro_delay, (unsigned long usecs) );
+
+PUBLIC int rtl_probe(dep)
+struct dpeth *dep;
+{
+ int i, r, devind, just_one;
+ u16_t vid, did;
+ u32_t bar;
+ u8_t ilr;
+ char *dname;
+
+ pci_init();
+
+ if ((dep->de_pcibus | dep->de_pcidev | dep->de_pcifunc) != 0)
+ {
+ /* Look for specific PCI device */
+ r= pci_find_dev(dep->de_pcibus, dep->de_pcidev,
+ dep->de_pcifunc, &devind);
+ if (r == 0)
+ {
+ printf("%s: no PCI found at %d.%d.%d\n",
+ dep->de_name, dep->de_pcibus,
+ dep->de_pcidev, dep->de_pcifunc);
+ return 0;
+ }
+ pci_ids(devind, &vid, &did);
+ just_one= TRUE;
+ }
+ else
+ {
+ r= pci_first_dev(&devind, &vid, &did);
+ if (r == 0)
+ return 0;
+ just_one= FALSE;
+ }
+
+ for(;;)
+ {
+ for (i= 0; pcitab[i].vid != 0; i++)
+ {
+ if (pcitab[i].vid != vid)
+ continue;
+ if (pcitab[i].did != did)
+ continue;
+ if (pcitab[i].checkclass)
+ {
+ panic("",
+ "rtl_probe: class check not implemented",
+ NO_NUM);
+ }
+ break;
+ }
+ if (pcitab[i].vid != 0)
+ break;
+
+ if (just_one)
+ {
+ printf(
+ "%s: wrong PCI device (%04X/%04X) found at %d.%d.%d\n",
+ dep->de_name, vid, did,
+ dep->de_pcibus,
+ dep->de_pcidev, dep->de_pcifunc);
+ return 0;
+ }
+
+ r= pci_next_dev(&devind, &vid, &did);
+ if (!r)
+ return 0;
+ }
+
+ dname= pci_dev_name(vid, did);
+ if (!dname)
+ dname= "unknown device";
+ printf("%s: %s (%04X/%04X) at %s\n",
+ dep->de_name, dname, vid, did, pci_slot_name(devind));
+ pci_reserve(devind);
+ /* printf("cr = 0x%x\n", pci_attr_r16(devind, PCI_CR)); */
+ bar= pci_attr_r32(devind, PCI_BAR) & 0xffffffe0;
+ if ((bar & 0x3ff) >= 0x100-32 || bar < 0x400)
+ panic("", "base address is not properly configured", NO_NUM);
+ dep->de_base_port= bar;
+
+ ilr= pci_attr_r8(devind, PCI_ILR);
+ dep->de_irq= ilr;
+ if (debug)
+ {
+ printf("%s: using I/O address 0x%lx, IRQ %d\n",
+ dep->de_name, (unsigned long)bar, ilr);
+ }
+ dep->de_initf= rtl_init;
+
+ return TRUE;
+}
+
+static void rtl_init(dep)
+dpeth_t *dep;
+{
+ u8_t reg_a, reg_b, cr, config0, config2, config3;
+ int i;
+
+#if DEBUG
+ printf("rtl_init called\n");
+#endif
+ ne_init(dep);
+
+ /* ID */
+ outb_reg0(dep, DP_CR, CR_PS_P0);
+ reg_a = inb_reg0(dep, DP_DUM1);
+ reg_b = inb_reg0(dep, DP_DUM2);
+
+#if DEBUG
+ printf("rtl_init: '%c', '%c'\n", reg_a, reg_b);
+#endif
+
+ outb_reg0(dep, DP_CR, CR_PS_P3);
+ config0 = inb_reg3(dep, 3);
+ config2 = inb_reg3(dep, 5);
+ config3 = inb_reg3(dep, 6);
+ outb_reg0(dep, DP_CR, CR_PS_P0);
+
+#if DEBUG
+ printf("rtl_init: config 0/2/3 = %x/%x/%x\n",
+ config0, config2, config3);
+#endif
+
+ if (getenv("RTL8029FD"))
+ {
+ printf("rtl_init: setting full-duplex mode\n");
+ outb_reg0(dep, DP_CR, CR_PS_P3);
+
+ cr= inb_reg3(dep, 1);
+ outb_reg3(dep, 1, cr | 0xc0);
+
+ outb_reg3(dep, 6, config3 | 0x40);
+ config3 = inb_reg3(dep, 6);
+
+ config2= inb_reg3(dep, 5);
+ outb_reg3(dep, 5, config2 | 0x20);
+ config2= inb_reg3(dep, 5);
+
+ outb_reg3(dep, 1, cr);
+
+ outb_reg0(dep, DP_CR, CR_PS_P0);
+
+#if DEBUG
+ printf("rtl_init: config 2 = %x\n", config2);
+ printf("rtl_init: config 3 = %x\n", config3);
+#endif
+ }
+
+#if DEBUG
+ for (i= 0; i<64; i++)
+ printf("%x ", get_ee_word(dep, i));
+ printf("\n");
+#endif
+
+ if (getenv("RTL8029MN"))
+ {
+ ee_wen(dep);
+
+ set_ee_word(dep, 0x78/2, 0x10ec);
+ set_ee_word(dep, 0x7A/2, 0x8029);
+ set_ee_word(dep, 0x7C/2, 0x10ec);
+ set_ee_word(dep, 0x7E/2, 0x8029);
+
+ ee_wds(dep);
+
+ assert(get_ee_word(dep, 0x78/2) == 0x10ec);
+ assert(get_ee_word(dep, 0x7A/2) == 0x8029);
+ assert(get_ee_word(dep, 0x7C/2) == 0x10ec);
+ assert(get_ee_word(dep, 0x7E/2) == 0x8029);
+ }
+
+ if (getenv("RTL8029XXX"))
+ {
+ ee_wen(dep);
+
+ set_ee_word(dep, 0x76/2, 0x8029);
+
+ ee_wds(dep);
+
+ assert(get_ee_word(dep, 0x76/2) == 0x8029);
+ }
+}
+
+static u16_t get_ee_word(dep, a)
+dpeth_t *dep;
+int a;
+{
+ int b, i, cmd;
+ u16_t w;
+
+ outb_reg0(dep, DP_CR, CR_PS_P3); /* Bank 3 */
+
+ /* Switch to 9346 mode and enable CS */
+ outb_reg3(dep, 1, 0x80 | 0x8);
+
+ cmd= 0x180 | (a & 0x3f); /* 1 1 0 a5 a4 a3 a2 a1 a0 */
+ for (i= 8; i >= 0; i--)
+ {
+ b= (cmd & (1 << i));
+ b= (b ? 2 : 0);
+
+ /* Cmd goes out on the rising edge of the clock */
+ outb_reg3(dep, 1, 0x80 | 0x8 | b);
+ outb_reg3(dep, 1, 0x80 | 0x8 | 0x4 | b);
+ }
+ outb_reg3(dep, 1, 0x80 | 0x8); /* End of cmd */
+
+ w= 0;
+ for (i= 0; i<16; i++)
+ {
+ w <<= 1;
+
+ /* Data is shifted out on the rising edge. Read at the
+ * falling edge.
+ */
+ outb_reg3(dep, 1, 0x80 | 0x8 | 0x4);
+ outb_reg3(dep, 1, 0x80 | 0x8 | b);
+ b= inb_reg3(dep, 1);
+ w |= (b & 1);
+ }
+
+ outb_reg3(dep, 1, 0x80); /* drop CS */
+ outb_reg3(dep, 1, 0x00); /* back to normal */
+ outb_reg0(dep, DP_CR, CR_PS_P0); /* back to bank 0 */
+
+ return w;
+}
+
+static void ee_wen(dep)
+dpeth_t *dep;
+{
+ int b, i, cmd;
+
+ outb_reg0(dep, DP_CR, CR_PS_P3); /* Bank 3 */
+
+ /* Switch to 9346 mode and enable CS */
+ outb_reg3(dep, 1, 0x80 | 0x8);
+
+ cmd= 0x130; /* 1 0 0 1 1 x x x x */
+ for (i= 8; i >= 0; i--)
+ {
+ b= (cmd & (1 << i));
+ b= (b ? 2 : 0);
+
+ /* Cmd goes out on the rising edge of the clock */
+ outb_reg3(dep, 1, 0x80 | 0x8 | b);
+ outb_reg3(dep, 1, 0x80 | 0x8 | 0x4 | b);
+ }
+ outb_reg3(dep, 1, 0x80 | 0x8); /* End of cmd */
+ outb_reg3(dep, 1, 0x80); /* Drop CS */
+ micro_delay(1); /* Is this required? */
+}
+
+static void set_ee_word(dep, a, w)
+dpeth_t *dep;
+int a;
+u16_t w;
+{
+ int b, i, cmd;
+
+ outb_reg3(dep, 1, 0x80 | 0x8); /* Set CS */
+
+ cmd= 0x140 | (a & 0x3f); /* 1 0 1 a5 a4 a3 a2 a1 a0 */
+ for (i= 8; i >= 0; i--)
+ {
+ b= (cmd & (1 << i));
+ b= (b ? 2 : 0);
+
+ /* Cmd goes out on the rising edge of the clock */
+ outb_reg3(dep, 1, 0x80 | 0x8 | b);
+ outb_reg3(dep, 1, 0x80 | 0x8 | 0x4 | b);
+ }
+ for (i= 15; i >= 0; i--)
+ {
+ b= (w & (1 << i));
+ b= (b ? 2 : 0);
+
+ /* Cmd goes out on the rising edge of the clock */
+ outb_reg3(dep, 1, 0x80 | 0x8 | b);
+ outb_reg3(dep, 1, 0x80 | 0x8 | 0x4 | b);
+ }
+ outb_reg3(dep, 1, 0x80 | 0x8); /* End of data */
+ outb_reg3(dep, 1, 0x80); /* Drop CS */
+ micro_delay(1); /* Is this required? */
+ outb_reg3(dep, 1, 0x80 | 0x8); /* Set CS */
+ for (i= 0; i<10000; i++)
+ {
+ if (inb_reg3(dep, 1) & 1)
+ break;
+ micro_delay(1);
+ }
+ if (!(inb_reg3(dep, 1) & 1))
+ panic("", "set_ee_word: device remains busy", NO_NUM);
+}
+
+static void ee_wds(dep)
+dpeth_t *dep;
+{
+ int b, i, cmd;
+
+ outb_reg0(dep, DP_CR, CR_PS_P3); /* Bank 3 */
+
+ /* Switch to 9346 mode and enable CS */
+ outb_reg3(dep, 1, 0x80 | 0x8);
+
+ cmd= 0x100; /* 1 0 0 0 0 x x x x */
+ for (i= 8; i >= 0; i--)
+ {
+ b= (cmd & (1 << i));
+ b= (b ? 2 : 0);
+
+ /* Cmd goes out on the rising edge of the clock */
+ outb_reg3(dep, 1, 0x80 | 0x8 | b);
+ outb_reg3(dep, 1, 0x80 | 0x8 | 0x4 | b);
+ }
+ outb_reg3(dep, 1, 0x80 | 0x8); /* End of cmd */
+ outb_reg3(dep, 1, 0x80); /* Drop CS */
+ outb_reg3(dep, 1, 0x00); /* back to normal */
+ outb_reg0(dep, DP_CR, CR_PS_P0); /* back to bank 0 */
+}
+
+static void micro_delay(unsigned long usecs)
+{
+ tickdelay(MICROS_TO_TICKS(usecs));
+}
+
+#endif /* ENABLE_PCI */
+
+/*
+ * $PchId: rtl8029.c,v 1.7 2004/08/03 12:16:58 philip Exp $
+ */
--- /dev/null
+/*
+rtl8029.h
+
+Created: Sep 2003 by Philip Homburg <philip@f-mnx.phicoh.com>
+*/
+
+/* Bits in dp_cr */
+#define CR_PS_P3 0xC0 /* Register Page 3 */
+
+#define inb_reg3(dep, reg) (inb (dep->de_dp8390_port+reg))
+#define outb_reg3(dep, reg, data) (outb(dep->de_dp8390_port+reg, data))
+
+/*
+ * $PchId: rtl8029.h,v 1.3 2004/08/03 15:11:06 philip Exp $
+ */
--- /dev/null
+/*
+wdeth.c
+
+Created: March 14, 1994 by Philip Homburg
+*/
+
+#include "../drivers.h"
+
+#include <net/gen/ether.h>
+#include <net/gen/eth_io.h>
+#include "assert.h"
+
+#include "local.h"
+#include "dp8390.h"
+#include "wdeth.h"
+
+#if ENABLE_WDETH
+
+#define WET_ETHERNET 0x01 /* Ethernet transceiver */
+#define WET_STARLAN 0x02 /* Starlan transceiver */
+#define WET_INTERF_CHIP 0x04 /* has a WD83C583 interface chip */
+#define WET_BRD_16BIT 0x08 /* 16 bit board */
+#define WET_SLT_16BIT 0x10 /* 16 bit slot */
+#define WET_790 0x20 /* '790 chip */
+
+static int we_int_table[8]= { 9, 3, 5, 7, 10, 11, 15, 4 };
+static int we_790int_table[8]= { 0, 9, 3, 5, 7, 10, 11, 15 };
+
+_PROTOTYPE( static void we_init, (dpeth_t *dep) );
+_PROTOTYPE( static void we_stop, (dpeth_t *dep) );
+_PROTOTYPE( static int we_aliasing, (dpeth_t *dep) );
+_PROTOTYPE( static int we_interface_chip, (dpeth_t *dep) );
+_PROTOTYPE( static int we_16bitboard, (dpeth_t *dep) );
+_PROTOTYPE( static int we_16bitslot, (dpeth_t *dep) );
+_PROTOTYPE( static int we_ultra, (dpeth_t *dep) );
+
+/*===========================================================================*
+ * wdeth_probe *
+ *===========================================================================*/
+int wdeth_probe(dep)
+dpeth_t *dep;
+{
+ int sum;
+
+ if (dep->de_linmem == 0)
+ return 0; /* No shared memory, so no WD board */
+
+ sum = inb_we(dep, EPL_EA0) + inb_we(dep, EPL_EA1) +
+ inb_we(dep, EPL_EA2) + inb_we(dep, EPL_EA3) +
+ inb_we(dep, EPL_EA4) + inb_we(dep, EPL_EA5) +
+ inb_we(dep, EPL_TLB) + inb_we(dep, EPL_CHKSUM);
+ if ((sum & 0xFF) != 0xFF)
+ return 0; /* No ethernet board at this address */
+
+ dep->de_initf= we_init;
+ dep->de_stopf= we_stop;
+ dep->de_prog_IO= 0;
+ return 1;
+}
+
+
+/*===========================================================================*
+ * we_init *
+ *===========================================================================*/
+static void we_init(dep)
+dpeth_t *dep;
+{
+ int i, int_indx, int_nr;
+ int tlb, rambit, revision;
+ int icr, irr, hwr, b, gcr;
+ int we_type;
+ int sendq_nr;
+
+ assert(dep->de_mode == DEM_ENABLED);
+ assert(!(dep->de_flags & DEF_ENABLED));
+
+ 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_dp8390_port= dep->de_base_port + EPL_DP8390;
+
+ dep->de_16bit= 0;
+
+ we_type= 0;
+ we_type |= WET_ETHERNET; /* assume ethernet */
+ if (we_ultra(dep))
+ we_type |= WET_790;
+ if (!we_aliasing(dep))
+ {
+ if (we_interface_chip(dep))
+ we_type |= WET_INTERF_CHIP;
+ if (we_16bitboard(dep))
+ {
+ we_type |= WET_BRD_16BIT;
+ if (we_16bitslot(dep))
+ we_type |= WET_SLT_16BIT;
+ }
+ }
+ if (we_type & WET_SLT_16BIT)
+ dep->de_16bit= 1;
+
+ /* look at the on board ram size. */
+ tlb= inb_we(dep, EPL_TLB);
+ revision= tlb & E_TLB_REV;
+ rambit= tlb & E_TLB_RAM;
+
+ if (dep->de_ramsize != 0)
+ {
+ /* size set from boot environment. */
+ }
+ else if (revision < 2)
+ {
+ dep->de_ramsize= 0x2000; /* 8K */
+ if (we_type & WET_BRD_16BIT)
+ dep->de_ramsize= 0x4000; /* 16K */
+ else if ((we_type & WET_INTERF_CHIP) &&
+ inb_we(dep, EPL_ICR) & E_ICR_MEMBIT)
+ {
+ dep->de_ramsize= 0x8000; /* 32K */
+ }
+ }
+ else
+ {
+ if (we_type & WET_BRD_16BIT)
+ {
+ /* 32K or 16K */
+ dep->de_ramsize= rambit ? 0x8000 : 0x4000;
+ }
+ else
+ {
+ /* 32K or 8K */
+ dep->de_ramsize= rambit ? 0x8000 : 0x2000;
+ }
+ }
+
+ if (we_type & WET_790)
+ {
+ outb_we(dep, EPL_MSR, E_MSR_RESET);
+ if ((we_type & (WET_BRD_16BIT|WET_SLT_16BIT)) ==
+ (WET_BRD_16BIT|WET_SLT_16BIT))
+ {
+ outb_we(dep, EPL_LAAR, E_LAAR_LAN16E | E_LAAR_MEM16E);
+ }
+ }
+ else if (we_type & WET_BRD_16BIT)
+ {
+ if (we_type & WET_SLT_16BIT)
+ {
+ outb_we(dep, EPL_LAAR, E_LAAR_A19 | E_LAAR_SOFTINT |
+ E_LAAR_LAN16E | E_LAAR_MEM16E);
+ }
+ else
+ {
+ outb_we(dep, EPL_LAAR, E_LAAR_A19 | E_LAAR_SOFTINT |
+ E_LAAR_LAN16E);
+ }
+ }
+
+ if (we_type & WET_790)
+ {
+ outb_we(dep, EPL_MSR, E_MSR_MENABLE);
+ hwr= inb_we(dep, EPL_790_HWR);
+ outb_we(dep, EPL_790_HWR, hwr | E_790_HWR_SWH);
+ b= inb_we(dep, EPL_790_B);
+ outb_we(dep, EPL_790_B, ((dep->de_linmem >> 13) & 0x0f) |
+ ((dep->de_linmem >> 11) & 0x40) | (b & 0xb0));
+ outb_we(dep, EPL_790_HWR, hwr & ~E_790_HWR_SWH);
+ }
+ else
+ {
+ outb_we(dep, EPL_MSR, E_MSR_RESET);
+ outb_we(dep, EPL_MSR, E_MSR_MENABLE |
+ ((dep->de_linmem >> 13) & E_MSR_MEMADDR));
+ }
+
+ if ((we_type & WET_INTERF_CHIP) && !(we_type & WET_790))
+ {
+ icr= inb_we(dep, EPL_ICR);
+ 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];
+#if DEBUG
+ { printf("%s: encoded irq= %d\n", dep->de_name, int_nr); }
+#endif
+ if (dep->de_irq & DEI_DEFAULT) dep->de_irq= int_nr;
+
+ outb_we(dep, EPL_IRR, irr | E_IRR_IEN);
+ }
+ if (we_type & WET_790)
+ {
+ hwr= inb_we(dep, EPL_790_HWR);
+ outb_we(dep, EPL_790_HWR, hwr | E_790_HWR_SWH);
+
+ gcr= inb_we(dep, EPL_790_GCR);
+
+ outb_we(dep, EPL_790_HWR, hwr & ~E_790_HWR_SWH);
+
+ 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];
+#if DEBUG
+ { printf("%s: encoded irq= %d\n", dep->de_name, int_nr); }
+#endif
+ 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);
+ }
+
+ /* Strip the "default flag." */
+ dep->de_irq &= ~DEI_DEFAULT;
+
+ if (!debug)
+ {
+ printf("%s: WD80%d3 at %X:%d:%lX\n",
+ dep->de_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,
+ we_type & WET_BRD_16BIT ? "16-bit " : "",
+ we_type & WET_ETHERNET ? "Ethernet" :
+ we_type & WET_STARLAN ? "Starlan" : "Network",
+ we_type & WET_INTERF_CHIP ? "with an interface chip " : "",
+ we_type & WET_SLT_16BIT ? "in a 16-bit slot " : "",
+ dep->de_base_port, dep->de_linmem, dep->de_ramsize,
+ dep->de_irq);
+ }
+
+ dep->de_offset_page= 0; /* Shared memory starts at 0 */
+
+ /* Allocate one send buffer (1.5KB) per 8KB of on board memory. */
+ sendq_nr= dep->de_ramsize / 0x2000;
+ if (sendq_nr < 1)
+ sendq_nr= 1;
+ else if (sendq_nr > SENDQ_NR)
+ sendq_nr= SENDQ_NR;
+ dep->de_sendq_nr= sendq_nr;
+ for (i= 0; i<sendq_nr; i++)
+ dep->de_sendq[i].sq_sendpage= i*SENDQ_PAGES;
+
+ dep->de_startpage= i*SENDQ_PAGES;
+ dep->de_stoppage= dep->de_ramsize / DP_PAGESIZE;
+}
+
+
+/*===========================================================================*
+ * we_stop *
+ *===========================================================================*/
+static void we_stop(dep)
+dpeth_t *dep;
+{
+ if (dep->de_16bit)
+ outb_we(dep, EPL_LAAR, E_LAAR_A19 | E_LAAR_LAN16E);
+ outb_we(dep, EPL_MSR, E_MSR_RESET);
+ outb_we(dep, EPL_MSR, 0);
+}
+
+
+/*===========================================================================*
+ * we_aliasing *
+ *===========================================================================*/
+static int we_aliasing(dep)
+dpeth_t *dep;
+{
+/* Determine whether wd8003 hardware performs register aliasing. This implies
+ * an old WD8003E board. */
+
+ if (inb_we(dep, EPL_REG1) != inb_we(dep, EPL_EA1))
+ return 0;
+ if (inb_we(dep, EPL_REG2) != inb_we(dep, EPL_EA2))
+ return 0;
+ if (inb_we(dep, EPL_REG3) != inb_we(dep, EPL_EA3))
+ return 0;
+ if (inb_we(dep, EPL_REG4) != inb_we(dep, EPL_EA4))
+ return 0;
+ if (inb_we(dep, EPL_REG7) != inb_we(dep, EPL_CHKSUM))
+ return 0;
+ return 1;
+}
+
+
+/*===========================================================================*
+ * we_interface_chip *
+ *===========================================================================*/
+static int we_interface_chip(dep)
+dpeth_t *dep;
+{
+/* Determine if the board has an interface chip. */
+
+ outb_we(dep, EPL_GP2, 0x35);
+ if (inb_we(dep, EPL_GP2) != 0x35)
+ return 0;
+ outb_we(dep, EPL_GP2, 0x3A);
+ if (inb_we(dep, EPL_GP2) != 0x3A)
+ return 0;
+ return 1;
+}
+
+
+/*===========================================================================*
+ * we_16bitboard *
+ *===========================================================================*/
+static int we_16bitboard(dep)
+dpeth_t *dep;
+{
+/* Determine whether the board is capable of doing 16 bit memory moves.
+ * If the 16 bit enable bit is unchangable by software we'll assume an
+ * 8 bit board.
+ */
+ int icr;
+ u8_t tlb;
+
+ icr= inb_we(dep, EPL_ICR);
+
+ outb_we(dep, EPL_ICR, icr ^ E_ICR_16BIT);
+ if (inb_we(dep, EPL_ICR) == icr)
+ {
+ tlb= inb_we(dep, EPL_TLB);
+#if DEBUG
+ printf("%s: tlb= 0x%x\n", dep->de_name, tlb);
+#endif
+ return tlb == E_TLB_EB || tlb == E_TLB_E ||
+ tlb == E_TLB_SMCE || tlb == E_TLB_SMC8216T ||
+ tlb == E_TLB_SMC8216C;
+ }
+ outb_we(dep, EPL_ICR, icr);
+ return (icr & E_ICR_16BIT);
+}
+
+
+/*===========================================================================*
+ * we_16bitslot *
+ *===========================================================================*/
+static int we_16bitslot(dep)
+dpeth_t *dep;
+{
+/* Determine if the 16 bit board in plugged into a 16 bit slot. */
+ return !!(inb_we(dep, EPL_ICR) & E_ICR_16BIT);
+}
+
+
+/*===========================================================================*
+ * we_ultra *
+ *===========================================================================*/
+static int we_ultra(dep)
+dpeth_t *dep;
+{
+/* Determine if we has an '790 chip. */
+ u8_t tlb;
+
+ tlb= inb_we(dep, EPL_TLB);
+ return tlb == E_TLB_SMC8216T || tlb == E_TLB_SMC8216C;
+}
+
+#endif /* ENABLE_WDETH */
+
+/*
+ * $PchId: wdeth.c,v 1.10 2003/09/10 19:31:50 philip Exp $
+ */
--- /dev/null
+/*
+wdeth.h
+
+Created: before Dec 28, 1992 by Philip Homburg
+*/
+
+#ifndef WDETH_H
+#define WDETH_H
+
+/* Western Digital Ethercard Plus, or WD8003E card. */
+
+#define EPL_REG0 0x0 /* Control(write) and status(read) */
+#define EPL_REG1 0x1
+#define EPL_REG2 0x2
+#define EPL_REG3 0x3
+#define EPL_REG4 0x4
+#define EPL_REG5 0x5
+#define EPL_REG6 0x6
+#define EPL_REG7 0x7
+#define EPL_EA0 0x8 /* Most significant eaddr byte */
+#define EPL_EA1 0x9
+#define EPL_EA2 0xA
+#define EPL_EA3 0xB
+#define EPL_EA4 0xC
+#define EPL_EA5 0xD /* Least significant eaddr byte */
+#define EPL_TLB 0xE
+#define EPL_CHKSUM 0xF /* sum from epl_ea0 upto here is 0xFF */
+#define EPL_DP8390 0x10 /* NatSemi chip */
+
+#define EPL_MSR EPL_REG0 /* memory select register */
+#define EPL_ICR EPL_REG1 /* interface configuration register */
+#define EPL_IRR EPL_REG4 /* interrupt request register (IRR) */
+#define EPL_790_HWR EPL_REG4 /* '790 hardware support register */
+#define EPL_LAAR EPL_REG5 /* LA address register (write only) */
+#define EPL_790_ICR EPL_REG6 /* '790 interrupt control register */
+#define EPL_GP2 EPL_REG7 /* general purpose register 2 */
+#define EPL_790_B EPL_EA3 /* '790 memory register */
+#define EPL_790_GCR EPL_EA5 /* '790 General Control Register */
+
+/* Bits in EPL_MSR */
+#define E_MSR_MEMADDR 0x3F /* Bits SA18-SA13, SA19 implicit 1 */
+#define E_MSR_MENABLE 0x40 /* Memory Enable */
+#define E_MSR_RESET 0x80 /* Software Reset */
+
+/* Bits in EPL_ICR */
+#define E_ICR_16BIT 0x01 /* 16 bit bus */
+#define E_ICR_IR2 0x04 /* bit 2 of encoded IRQ */
+#define E_ICR_MEMBIT 0x08 /* 583 mem size mask */
+
+/* Bits in EPL_IRR */
+#define E_IRR_IR0 0x20 /* bit 0 of encoded IRQ */
+#define E_IRR_IR1 0x40 /* bit 1 of encoded IRQ */
+#define E_IRR_IEN 0x80 /* enable interrupts */
+
+/* Bits in EPL_LAAR */
+#define E_LAAR_A19 0x01 /* address lines for above 1M ram */
+#define E_LAAR_A20 0x02 /* address lines for above 1M ram */
+#define E_LAAR_A21 0x04 /* address lines for above 1M ram */
+#define E_LAAR_A22 0x08 /* address lines for above 1M ram */
+#define E_LAAR_A23 0x10 /* address lines for above 1M ram */
+#define E_LAAR_SOFTINT 0x20 /* enable software interrupt */
+#define E_LAAR_LAN16E 0x40 /* enables 16 bit RAM for LAN */
+#define E_LAAR_MEM16E 0x80 /* enables 16 bit RAM for host */
+
+/* Bits and values in EPL_TLB */
+#define E_TLB_EB 0x05 /* WD8013EB */
+#define E_TLB_E 0x27 /* WD8013 Elite */
+#define E_TLB_SMCE 0x29 /* SMC Elite 16 */
+#define E_TLB_SMC8216T 0x2A /* SMC 8216 T */
+#define E_TLB_SMC8216C 0x2B /* SMC 8216 C */
+
+#define E_TLB_REV 0x1F /* revision mask */
+#define E_TLB_SOFT 0x20 /* soft config */
+#define E_TLB_RAM 0x40 /* extra ram bit */
+
+/* Bits in EPL_790_HWR */
+#define E_790_HWR_SWH 0x80 /* switch register set */
+
+/* Bits in EPL_790_ICR */
+#define E_790_ICR_EIL 0x01 /* enable interrupts */
+
+/* Bits in EPL_790_GCR when E_790_HWR_SWH is set in EPL_790_HWR */
+#define E_790_GCR_IR0 0x04 /* bit 0 of encoded IRQ */
+#define E_790_GCR_IR1 0x08 /* bit 1 of encoded IRQ */
+#define E_790_GCR_IR2 0x40 /* bit 2 of encoded IRQ */
+
+
+#define inb_we(dep, reg) (inb(dep->de_base_port+reg))
+#define outb_we(dep, reg, data) (outb(dep->de_base_port+reg, data))
+
+#endif /* WDETH_H */
+
+/*
+ * $PchId: wdeth.h,v 1.6 2003/09/10 19:29:52 philip Exp $
+ */
_PROTOTYPE( int get_mon_param, (char *key, char *value, int max_size) );
_PROTOTYPE( int env_prefix, (char *env, char *prefix) );
+_PROTOTYPE( int env_prefix_x, (int argc, char *argv[],
+ char *env, char *prefix) );
_PROTOTYPE( void env_panic, (char *key) );
_PROTOTYPE( int env_parse, (char *env, char *fmt, int field, long *param,
long min, long max) );
+_PROTOTYPE( int env_parse_x, (int argc, char *argv[], char *env,
+ char *fmt, int field, long *param, long min, long max) );
+
#define fkey_map(fkeys, sfkeys) fkey_ctl(FKEY_MAP, (fkeys), (sfkeys))
#define fkey_unmap(fkeys, sfkeys) fkey_ctl(FKEY_UNMAP, (fkeys), (sfkeys))
int field; /* field number of value to return */
long *param; /* address of parameter to get */
long min, max; /* minimum and maximum values for the parameter */
+{
+ return env_parse_x(0, NULL, env, fmt, field, param, min, max);
+}
+
+/*=========================================================================*
+ * env_parse_x *
+ *=========================================================================*/
+PUBLIC int env_parse_x(argc, argv, env, fmt, field, param, min, max)
+int argc;
+char *argv[];
+char *env; /* environment variable to inspect */
+char *fmt; /* template to parse it with */
+int field; /* field number of value to return */
+long *param; /* address of parameter to get */
+long min, max; /* minimum and maximum values for the parameter */
{
/* Parse an environment variable setting, something like "DPETH0=300:3".
* Panic if the parsing fails. Return EP_UNSET if the environment variable
char value[EP_BUF_SIZE];
char PUNCT[] = ":,;.";
long newpar;
- int s, i = 0, radix, r;
+ int s, i, radix, r, keylen;
+
+ keylen= strlen(env);
+ for (i= 0; i<argc; i++)
+ {
+ if (strncmp(argv[i], env, keylen) != 0)
+ continue;
+ if (strlen(argv[i]) <= keylen)
+ continue;
+ if (argv[i][keylen] != '=')
+ continue;
+ val= argv[i]+keylen+1;
+ if (strlen(val)+1 > EP_BUF_SIZE)
+ {
+ printf("WARNING: env_parse() failed: argument too long\n");
+ return(EP_EGETKENV);
+ }
+ strcpy(value, val);
+ }
- if ((s=get_mon_param(env, value, sizeof(value))) != 0) {
+ if (i >= argc && (s=get_mon_param(env, value, sizeof(value))) != 0) {
if (s == ESRCH) return(EP_UNSET); /* only error allowed */
printf("WARNING: get_mon_param() failed in env_parse(): %d\n",s);
return(EP_EGETKENV);
if (strcmp(val, "off") == 0) return(EP_OFF);
if (strcmp(val, "on") == 0) return(EP_ON);
+ i = 0;
r = EP_ON;
for (;;) {
while (*val == ' ') val++; /* skip spaces */
PUBLIC int env_prefix(env, prefix)
char *env; /* environment variable to inspect */
char *prefix; /* prefix to test for */
+{
+ return env_prefix_x(0, NULL, env, prefix);
+}
+
+
+/*=========================================================================*
+ * env_prefix_x *
+ *=========================================================================*/
+PUBLIC int env_prefix_x(argc, argv, env, prefix)
+int argc;
+char *argv[];
+char *env; /* environment variable to inspect */
+char *prefix; /* prefix to test for */
{
/* An environment setting may be prefixed by a word, usually "pci".
* Return TRUE if a given prefix is used.
*/
char value[EP_BUF_SIZE];
char punct[] = ":,;.";
- int s;
+ int i, s, keylen;
+ char *val;
size_t n;
- if ((s = get_mon_param(env, value, sizeof(value))) != 0) {
+ keylen= strlen(env);
+ for (i= 0; i<argc; i++)
+ {
+ printf("env_prefix_x: argv[%d] = '%s'\n", i, argv[i]);
+ if (strncmp(argv[i], env, keylen) != 0)
+ continue;
+ if (strlen(argv[i]) <= keylen)
+ continue;
+ if (argv[i][keylen] != '=')
+ continue;
+ val= argv[i]+keylen+1;
+ if (strlen(val)+1 > EP_BUF_SIZE)
+ {
+ printf("WARNING: env_parse() failed: argument too long\n");
+ return(EP_EGETKENV);
+ }
+ strcpy(value, val);
+ }
+
+ if (i >= argc && (s = get_mon_param(env, value, sizeof(value))) != 0) {
if (s != ESRCH) /* only error allowed */
printf("WARNING: get_mon_param() failed in env_prefix(): %d\n", s);
}