Added dp8390 driver. Additional env_parse functions that take argc and argv.

This commit is contained in:
Philip Homburg 2005-08-05 09:53:08 +00:00
parent c9ab8cce43
commit db5a8bb2b8
16 changed files with 3917 additions and 4 deletions

View file

@ -28,3 +28,4 @@ all install depend clean:
cd ./bios_wini && $(MAKE) $@ cd ./bios_wini && $(MAKE) $@
cd ./cmos && $(MAKE) $@ cd ./cmos && $(MAKE) $@
cd ./random && $(MAKE) $@ cd ./random && $(MAKE) $@
cd ./dp8390 && $(MAKE) $@

201
drivers/dp8390/3c503.c Normal file
View file

@ -0,0 +1,201 @@
/*
* 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 $
*/

64
drivers/dp8390/3c503.h Normal file
View file

@ -0,0 +1,64 @@
/*
* 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 $
*/

44
drivers/dp8390/Makefile Normal file
View file

@ -0,0 +1,44 @@
# 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

1986
drivers/dp8390/dp8390.c Normal file

File diff suppressed because it is too large Load diff

298
drivers/dp8390/dp8390.h Normal file
View file

@ -0,0 +1,298 @@
/*
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 $
*/

30
drivers/dp8390/local.h Normal file
View file

@ -0,0 +1,30 @@
/*
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) );

334
drivers/dp8390/ne2000.c Normal file
View file

@ -0,0 +1,334 @@
/*
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 $
*/

28
drivers/dp8390/ne2000.h Normal file
View file

@ -0,0 +1,28 @@
/*
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 $
*/

376
drivers/dp8390/rtl8029.c Normal file
View file

@ -0,0 +1,376 @@
/*
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 $
*/

15
drivers/dp8390/rtl8029.h Normal file
View file

@ -0,0 +1,15 @@
/*
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 $
*/

369
drivers/dp8390/wdeth.c Normal file
View file

@ -0,0 +1,369 @@
/*
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 $
*/

95
drivers/dp8390/wdeth.h Normal file
View file

@ -0,0 +1,95 @@
/*
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 $
*/

View file

@ -31,9 +31,14 @@
_PROTOTYPE( int get_mon_param, (char *key, char *value, int max_size) ); _PROTOTYPE( int get_mon_param, (char *key, char *value, int max_size) );
_PROTOTYPE( int env_prefix, (char *env, char *prefix) ); _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( void env_panic, (char *key) );
_PROTOTYPE( int env_parse, (char *env, char *fmt, int field, long *param, _PROTOTYPE( int env_parse, (char *env, char *fmt, int field, long *param,
long min, long max) ); 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_map(fkeys, sfkeys) fkey_ctl(FKEY_MAP, (fkeys), (sfkeys))
#define fkey_unmap(fkeys, sfkeys) fkey_ctl(FKEY_UNMAP, (fkeys), (sfkeys)) #define fkey_unmap(fkeys, sfkeys) fkey_ctl(FKEY_UNMAP, (fkeys), (sfkeys))

View file

@ -12,6 +12,21 @@ char *fmt; /* template to parse it with */
int field; /* field number of value to return */ int field; /* field number of value to return */
long *param; /* address of parameter to get */ long *param; /* address of parameter to get */
long min, max; /* minimum and maximum values for the parameter */ 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". /* Parse an environment variable setting, something like "DPETH0=300:3".
* Panic if the parsing fails. Return EP_UNSET if the environment variable * Panic if the parsing fails. Return EP_UNSET if the environment variable
@ -29,9 +44,27 @@ long min, max; /* minimum and maximum values for the parameter */
char value[EP_BUF_SIZE]; char value[EP_BUF_SIZE];
char PUNCT[] = ":,;."; char PUNCT[] = ":,;.";
long newpar; long newpar;
int s, i = 0, radix, r; int s, i, radix, r, keylen;
if ((s=get_mon_param(env, value, sizeof(value))) != 0) { 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 (i >= argc && (s=get_mon_param(env, value, sizeof(value))) != 0) {
if (s == ESRCH) return(EP_UNSET); /* only error allowed */ if (s == ESRCH) return(EP_UNSET); /* only error allowed */
printf("WARNING: get_mon_param() failed in env_parse(): %d\n",s); printf("WARNING: get_mon_param() failed in env_parse(): %d\n",s);
return(EP_EGETKENV); return(EP_EGETKENV);
@ -40,6 +73,7 @@ long min, max; /* minimum and maximum values for the parameter */
if (strcmp(val, "off") == 0) return(EP_OFF); if (strcmp(val, "off") == 0) return(EP_OFF);
if (strcmp(val, "on") == 0) return(EP_ON); if (strcmp(val, "on") == 0) return(EP_ON);
i = 0;
r = EP_ON; r = EP_ON;
for (;;) { for (;;) {
while (*val == ' ') val++; /* skip spaces */ while (*val == ' ') val++; /* skip spaces */

View file

@ -8,16 +8,49 @@
PUBLIC int env_prefix(env, prefix) PUBLIC int env_prefix(env, prefix)
char *env; /* environment variable to inspect */ char *env; /* environment variable to inspect */
char *prefix; /* prefix to test for */ 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". /* An environment setting may be prefixed by a word, usually "pci".
* Return TRUE if a given prefix is used. * Return TRUE if a given prefix is used.
*/ */
char value[EP_BUF_SIZE]; char value[EP_BUF_SIZE];
char punct[] = ":,;."; char punct[] = ":,;.";
int s; int i, s, keylen;
char *val;
size_t n; 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 */ if (s != ESRCH) /* only error allowed */
printf("WARNING: get_mon_param() failed in env_prefix(): %d\n", s); printf("WARNING: get_mon_param() failed in env_prefix(): %d\n", s);
} }