From 76f8132545b3d3a9143ff3247e647f908d1a4f6a Mon Sep 17 00:00:00 2001 From: Ben Gras Date: Tue, 26 Jan 2010 10:20:18 +0000 Subject: [PATCH] dec21140A ethernet driver for virtualpc, contributed by nicolas tittley. --- commands/scripts/netconf.sh | 6 +- drivers/Makefile | 1 + drivers/dec21140A/Makefile | 43 ++ drivers/dec21140A/README.txt | 28 + drivers/dec21140A/dec21140A.c | 945 ++++++++++++++++++++++++++++++++++ drivers/dec21140A/dec21140A.h | 238 +++++++++ etc/system.conf | 23 + etc/usr/rc | 2 +- 8 files changed, 1283 insertions(+), 3 deletions(-) create mode 100644 drivers/dec21140A/Makefile create mode 100644 drivers/dec21140A/README.txt create mode 100644 drivers/dec21140A/dec21140A.c create mode 100644 drivers/dec21140A/dec21140A.h diff --git a/commands/scripts/netconf.sh b/commands/scripts/netconf.sh index ff1e0d6be..70a03d1f2 100755 --- a/commands/scripts/netconf.sh +++ b/commands/scripts/netconf.sh @@ -112,7 +112,8 @@ cards() card 7 "AMD LANCE (also emulated by VMWare and VirtualBox)" "1022:2000" card 8 "Intel PRO/1000 Gigabit" "8086:100E" "8086:107C" "8086:10CD" card 9 "Attansic/Atheros L2 FastEthernet" "1969:2048" - card 10 "Different Ethernet card (no networking)" + card 10 "DEC Tulip 21140A in VirtualPC" "1011:0009" + card 11 "Different Ethernet card (no networking)" } warn() @@ -160,7 +161,8 @@ drv_params() 7) driver="lance"; ;; 8) driver="e1000"; ;; 9) driver="atl2"; ;; - 10) driver="psip0"; ;; + 10) driver="dec21140A"; ;; + 11) driver="psip0"; ;; *) warn "choose a number" esac } diff --git a/drivers/Makefile b/drivers/Makefile index 477f1516e..c3e9eeeaf 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -37,6 +37,7 @@ all install depend clean: cd ./dp8390 && $(MAKE) $@ cd ./sb16 && $(MAKE) $@ cd ./lance && $(MAKE) $@ + cd ./dec21140A && $(MAKE) $@ cd ./pci && $(MAKE) $@ cd ./ti1225 && $(MAKE) $@ cd ./memory && $(MAKE) $@ # Must be last for ramdisk image diff --git a/drivers/dec21140A/Makefile b/drivers/dec21140A/Makefile new file mode 100644 index 000000000..94abfd6a4 --- /dev/null +++ b/drivers/dec21140A/Makefile @@ -0,0 +1,43 @@ +## +## Makefile for Dec21140A ethernet board driver +## + +## Programs, flags, etc. +DRIVER = dec21140A + +debug = 0 + +CC = exec cc +LD = $(CC) +CPPFLAGS= -I.. -I/usr/include -Ddebug=$(debug) $(CPROFILE) +CFLAGS = -ws -w -Wall $(CPPFLAGS) +LDFLAGS = -i -o $@ + +SRCS = dec21140A.c +OBJS = dec21140A.o +LIBS = -lsys # -ltimers + +## Build rules +all build: $(DRIVER) + +$(DRIVER): $(OBJS) + $(CC) $(OBJS) $(LIBS) $(LDFLAGS) + install -S 16k $(DRIVER) + +## Install with other drivers +install: /usr/sbin/$(DRIVER) +/usr/sbin/$(DRIVER): $(DRIVER) + install -o root -cs $? $@ + +## Generate dependencies + +depend: + mkdep "$(CC) -E $(CPPFLAGS)" *.c > .depend + +## Clean directory +clean: + @rm -f $(DRIVER) *.o *.BAK *~ + +include .depend + +## end diff --git a/drivers/dec21140A/README.txt b/drivers/dec21140A/README.txt new file mode 100644 index 000000000..d62ccb8c7 --- /dev/null +++ b/drivers/dec21140A/README.txt @@ -0,0 +1,28 @@ +README file for the Dec21140A ethernet board driver as emulated by +Microsoft VirtualPC 2007. + +created August 2009, Nicolas Tittley (first.last@gmail) + +LIMITATIONS: +------------ + +This driver supports only the Dec21140A as emulated by VPC2007. It is +untested in any other environment and will probably panic if you use it +outside VPC2007. + +The driver supports bridged, nat and local network settings. See the +next section for a remark on seting up a nat environment. + +Only one card can be used at a time, do not activate multiple network +cards in VPC2007, the driver will panic. + +NOTE FOR USERS CONFIGURING VPC2007 TO USE NAT: + +in /usr/etc/rc comment out the following three lines: + +trap '' 2 +intr -t 20 hostaddr -h +trap 2 + +VPC2007 does not play well with hostaddr and it will hang the boot process +until you CTRL-C out of it. diff --git a/drivers/dec21140A/dec21140A.c b/drivers/dec21140A/dec21140A.c new file mode 100644 index 000000000..06d635669 --- /dev/null +++ b/drivers/dec21140A/dec21140A.c @@ -0,0 +1,945 @@ +/* + * dec21041.c + * + * This file contains an ethernet device driver for DEC 21140A + * fast ethernet controllers as emulated by VirtualPC 2007. It is not + * intended to support the real card, as much more error checking + * and testing would be needed. It supports both bridged and NAT mode. + * + * Created: Mar 2008 by Nicolas Tittley + */ + +#include "../drivers.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "dec21140A.h" + + +_PROTOTYPE( PRIVATE u32_t io_inl, (u16_t); ); +_PROTOTYPE( PRIVATE void io_outl, (u16_t, u32_t); ); +_PROTOTYPE( PRIVATE void do_conf, (message *); ); +_PROTOTYPE( PRIVATE void do_fkey, (message *); ); +_PROTOTYPE( PRIVATE void do_get_name, (message *); ); +_PROTOTYPE( PRIVATE void do_get_stat_s, (message *); ); +_PROTOTYPE( PRIVATE void do_interrupt, (dpeth_t *); ); +_PROTOTYPE( PRIVATE void do_reply, (dpeth_t *, int, int); ); +_PROTOTYPE( PRIVATE void do_vread_s, (message *, int); ); +_PROTOTYPE( PRIVATE void do_watchdog, (void *); ); + +_PROTOTYPE( PRIVATE void de_update_conf, (dpeth_t *); ); +_PROTOTYPE( PRIVATE int de_probe, (dpeth_t *); ); +_PROTOTYPE( PRIVATE void de_conf_addr, (dpeth_t *); ); +_PROTOTYPE( PRIVATE void de_first_init, (dpeth_t *); ); +_PROTOTYPE( PRIVATE void de_reset, (dpeth_t *); ); +_PROTOTYPE( PRIVATE void de_hw_conf, (dpeth_t *); ); +_PROTOTYPE( PRIVATE void de_start, (dpeth_t *); ); +_PROTOTYPE( PRIVATE void de_setup_frame, (dpeth_t *); ); +_PROTOTYPE( PRIVATE u16_t de_read_rom, (dpeth_t *, u8_t, u8_t); ); +_PROTOTYPE( PRIVATE int de_calc_iov_size, (iovec_dat_s_t *); ); +_PROTOTYPE( PRIVATE void de_next_iov, (iovec_dat_s_t *); ); +_PROTOTYPE( PRIVATE void do_vwrite_s, (message *, int); ); +_PROTOTYPE( PRIVATE void de_get_userdata_s, (int, cp_grant_id_t, + vir_bytes, int, void *); ); + +/* Error messages */ +static char str_CopyErrMsg[] = "unable to read/write user data"; +static char str_PortErrMsg[] = "illegal port"; +static char str_RecvErrMsg[] = "receive failed"; +static char str_SendErrMsg[] = "send failed"; +static char str_SizeErrMsg[] = "illegal packet size"; +static char str_TypeErrMsg[] = "illegal message type"; +static char str_UmapErrMsg[] = "Unable to sys_umap"; +static char str_BusyErrMsg[] = "Send/Recv failed: busy"; +static char str_StatErrMsg[] = "Unable to send stats"; +static char str_AlignErrMsg[] = "Bad align of buffer/descriptor"; +static char str_DevName[] = "dec21140A:eth#?"; + +extern int errno; +static dpeth_t de_table[DE_PORT_NR]; +static char *progname; + +int sef_cb_init(int type, sef_init_info_t *info) +{ + int r; + int fkeys, sfkeys; + endpoint_t tasknr; + /* Request function key for debug dumps */ + fkeys = sfkeys = 0; bit_set(sfkeys, DE_FKEY); + if ((fkey_map(&fkeys, &sfkeys)) != OK) + printf("%s: error using Shift+F%d key(%d)\n", str_DevName, DE_FKEY, errno); + + /* Try to notify inet that we are present (again) */ + r = ds_retrieve_label_num("inet", &tasknr); + if (r == OK) + notify(tasknr); + else if(r != ESRCH) + printf("%s unable to notify inet: %d\n", str_DevName, r); +} + +/*===========================================================================* + * main * + *===========================================================================*/ +int main(int argc, char *argv[]) +{ + dpeth_t *dep; + message m; + int r; + + (progname=strrchr(argv[0],'/')) ? progname++ : (progname=argv[0]); + + env_setargs(argc, argv); + + sef_setcb_init_fresh(sef_cb_init); + sef_setcb_init_restart(sef_cb_init); + sef_startup(); + + while (TRUE) + { + if ((r= sef_receive(ANY, &m)) != OK) + panic(str_DevName, "minix msg sef_receive failed", r); + + if(is_notify(m.m_type)) { + switch(_ENDPOINT_P(m.m_source)) { + case RS_PROC_NR: + notify(m.m_source); + break; + case CLOCK: + do_watchdog(&m); + break; + + case HARDWARE: + for (dep = de_table; dep < &de_table[DE_PORT_NR]; dep += 1) { + if (dep->de_mode == DEM_ENABLED) { + do_interrupt(dep); + if (dep->de_flags & (DEF_ACK_SEND | DEF_ACK_RECV)) + do_reply(dep, OK, TRUE); + sys_irqenable(&dep->de_hook); + } + } + break; + case PM_PROC_NR: + exit(0); + break; + default: + printf("ignoring notify from %d\n", m.m_source); + break; + } + continue; + } + + switch (m.m_type) + { + case DL_WRITEV_S: do_vwrite_s(&m, FALSE); break; + case DL_READV_S: do_vread_s(&m, FALSE); break; + case DL_CONF: do_conf(&m); break; + case DL_GETSTAT_S: do_get_stat_s(&m); break; + case DL_GETNAME: do_get_name(&m); break; + case DL_STOP: /* nothing */ break; + + default: + printf("message 0x%lx; %d from %d\n", + m.m_type, m.m_type-DL_RQ_BASE, m.m_source); + panic(str_DevName, "illegal message", m.m_type); + } + } +} + +PRIVATE void do_get_stat_s(message * mp) +{ + int port, rc; + dpeth_t *dep; + + port = mp->DL_PORT; + if (port < 0 || port >= DE_PORT_NR) + panic(str_DevName, str_PortErrMsg, port); + + dep = &de_table[port]; + dep->de_client = mp->DL_PROC; + + if ((rc = sys_safecopyto(mp->DL_PROC, mp->DL_GRANT, 0, + (vir_bytes)&dep->de_stat, + (vir_bytes) sizeof(dep->de_stat), 0)) != OK) + panic(str_DevName, str_CopyErrMsg, rc); + + mp->m_type = DL_STAT_REPLY; + mp->DL_PORT = port; + mp->DL_STAT = OK; + rc = send(mp->m_source, mp); + if( rc != OK ) + panic(str_DevName, str_StatErrMsg, rc); + return; +} + +PRIVATE void do_conf(message * mp) +{ + int port; + dpeth_t *dep; + message reply_mess; + + port = mp->DL_PORT; + if (port >= 0 && port < DE_PORT_NR) { + + dep = &de_table[port]; + strncpy(dep->de_name, str_DevName, strlen(str_DevName)); + dep->de_name[strlen(dep->de_name)-1] = '0' + port; + + if (dep->de_mode == DEM_DISABLED) { + de_update_conf(dep); + pci_init(); + if (dep->de_mode == DEM_ENABLED && !de_probe(dep)) { + printf("%s: warning no ethernet card found at 0x%04X\n", + dep->de_name, dep->de_base_port); + dep->de_mode = DEM_DISABLED; + } + } + + /* 'de_mode' may change if probe routines fail, test again */ + switch (dep->de_mode) { + + case DEM_DISABLED: + port = ENXIO; /* Device is OFF or hardware probe failed */ + break; + + case DEM_ENABLED: + if (dep->de_flags == DEF_EMPTY) { + de_first_init(dep); + dep->de_flags |= DEF_ENABLED; + de_reset(dep); + de_hw_conf(dep); + de_setup_frame(dep); + de_start(dep); + } + + /* TODO CHECK PROMISC AND MULTI */ + dep->de_flags &= NOT(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; + break; + + case DEM_SINK: + DEBUG(printf("%s running in sink mode\n", str_DevName)); + memset(dep->de_address.ea_addr, 0, sizeof(ether_addr_t)); + de_conf_addr(dep); + break; + + default: break; + } + } else /* Port number is out of range */ + port = ENXIO; + + reply_mess.m_type = DL_CONF_REPLY; + reply_mess.m3_i1 = port; + reply_mess.m3_i2 = DE_PORT_NR; + *(ether_addr_t *) reply_mess.m3_ca1 = dep->de_address; + + if (send(mp->m_source, &reply_mess) != OK) + panic(str_DevName, str_SendErrMsg, mp->m_source); + + return; +} + + +PRIVATE void do_get_name(mp) +message *mp; +{ + int r; + strncpy(mp->DL_NAME, progname, sizeof(mp->DL_NAME)); + mp->DL_NAME[sizeof(mp->DL_NAME)-1]= '\0'; + mp->m_type= DL_NAME_REPLY; + r = send(mp->m_source, mp); + if (r!= OK) + panic(str_DevName, "do_getname: send failed", r); +} + +PRIVATE void do_reply(dpeth_t * dep, int err, int may_block) +{ + message reply; + int status = FALSE; + + if (dep->de_flags & DEF_ACK_SEND) status |= DL_PACK_SEND; + if (dep->de_flags & DEF_ACK_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; + + status = send(dep->de_client, &reply); + + if(status == ELOCKED && may_block){ + /*printf("Warning: Dec21041 send lock prevented\n\n");*/ + return; + } + + if(status < 0) + panic(dep->de_name, str_SendErrMsg, status); + + dep->de_read_s = 0; + dep->de_flags &= NOT(DEF_ACK_SEND | DEF_ACK_RECV); + return; +} + +PRIVATE void do_watchdog(void *message) +{ + /* nothing here yet */ + return; +} + +PRIVATE int de_probe(dpeth_t *dep){ + int i, r, devind; + u16_t vid, did, temp16; + + DEBUG(printf("PROBING...")); + + r= pci_first_dev(&devind, &vid, &did); + if (r == 0) + return FALSE; + + for(;;) + { + if ( DEC21140A_VID == vid && + DEC21140A_DID == did) + break; + + r= pci_next_dev(&devind, &vid, &did); + if (!r) + return FALSE; + } + + pci_reserve(devind); + + dep->de_base_port = pci_attr_r32(devind, PCI_BAR) & 0xffffffe0; + dep->de_irq = pci_attr_r8(devind, PCI_ILR); + + if (dep->de_base_port < DE_MIN_BASE_ADDR) + panic(str_DevName,"de_probe: base address invalid ", dep->de_base_port); + + DEBUG(printf("%s: using I/O address 0x%lx, IRQ %d\n", + dep->de_name, (unsigned long)dep->de_base_port, + dep->de_irq)); + + dep->de_type = pci_attr_r8(devind, PCI_REV); + + /* device validation. We support only the DEC21140A */ + if(dep->de_type != DEC_21140A){ + dep->de_type = DE_TYPE_UNKNOWN; + printf("%s: unsupported device\n", str_DevName); + return FALSE; + } + + de_reset(dep); + + DEBUG(printf("Reading SROM...\n")); + + for(i=0;i<(1<srom[i*2] = temp16 & 0xFF; + dep->srom[i*2+1] = temp16 >> 8; + } + + /* TODO: validate SROM content */ + /* acquire MAC addr */ + DEBUG(printf("Using MAC addr= ")); + for(i=0;i<6;i++){ + dep->de_address.ea_addr[i] = dep->srom[i+DE_SROM_EA_OFFSET]; + DEBUG(printf("%02X%c",dep->de_address.ea_addr[i],i!=5?'-':'\n')); + } + DEBUG(printf("probe success\n")); + return TRUE; +} + +PRIVATE u16_t de_read_rom(dpeth_t *dep, u8_t addr, u8_t nbAddrBits){ + u16_t retVal = 0; + int i; + u32_t csr = 0; + u32_t csr2 = 0; /* csr2 is used to hold constant values that are + setup in the init phase, it makes this a little + more readable, the following macro is also just + to clear up the code a little.*/ + + #define EMIT do { io_outl(CSR_ADDR(dep, CSR9), csr | csr2); io_outl(CSR_ADDR(dep, CSR1), 0);} while(0) + + /* init */ + csr = 0; EMIT; + csr = CSR9_SR; EMIT; + csr = CSR9_SR | CSR9_RD; EMIT; + + csr2 = CSR9_SR | CSR9_RD; + csr = 0; EMIT; + csr2 |= CSR9_CS; + + csr = 0; EMIT; + csr = CSR9_SRC; EMIT; + csr = 0; EMIT; + + /* cmd 110 - Read */ + csr = CSR9_DI; EMIT; + csr = CSR9_DI | CSR9_SRC; EMIT; + csr = CSR9_DI; EMIT; + csr = CSR9_DI | CSR9_SRC; EMIT; + csr = CSR9_DI; EMIT; + csr = 0; EMIT; + csr = CSR9_SRC; EMIT; + csr = 0; EMIT; + + /* addr to read */ + for(i=nbAddrBits;i!=0;i--){ + csr = (addr&(1<<(i-1))) != 0 ? CSR9_DI : 0; EMIT; + csr ^= CSR9_SRC; EMIT; + csr ^= CSR9_SRC; EMIT; + } + + /* actual read */ + retVal=0; + for(i=0;i<16;i++){ + retVal <<= 1; + csr = CSR9_SRC; EMIT; + retVal |= (io_inl(CSR_ADDR(dep, CSR9)) & CSR9_DO) == 0 ? 0 : 1; + csr = 0; EMIT; + } + + /* clean up */ + csr = 0; EMIT; + +#undef EMIT + return retVal; +} + +static void de_update_conf(dpeth_t * dep) +{ + static char dpc_fmt[] = "x:d:x"; + long val; + + dep->de_mode = DEM_ENABLED; + switch (env_parse("DEETH0", dpc_fmt, 0, &val, 0x000L, 0x3FFL)) { + case EP_OFF: dep->de_mode = DEM_DISABLED; break; + case EP_ON: dep->de_mode = DEM_SINK; break; + } + dep->de_base_port = 0; + + return; +} + +PRIVATE void do_vread_s(message * mp, int from_int) +{ + char *buffer; + u32_t size; + int r, bytes, ix = 0; + dpeth_t *dep = NULL; + de_loc_descr_t *descr = NULL; + iovec_dat_s_t *iovp = NULL; + + if (mp->DL_PORT < 0 || mp->DL_PORT >= DE_PORT_NR) + panic(dep->de_name, str_PortErrMsg, mp->DL_PORT); + + dep = &de_table[mp->DL_PORT]; + dep->de_client = mp->DL_PROC; + + if (dep->de_mode == DEM_ENABLED) { + + descr = &dep->descr[DESCR_RECV][dep->cur_descr[DESCR_RECV]]; + + /* check if packet is in the current descr and only there */ + if( !( !(descr->descr->des[DES0] & DES0_OWN) && + (descr->descr->des[DES0] & DES0_FS) && + (descr->descr->des[DES0] & DES0_LS) )) + goto suspend; + + + /*TODO: multi-descr msgs...*/ + /* We only support packets contained in a single descriptor. + Setting the descriptor buffer size to less then + ETH_MAX_PACK_SIZE will result in multi-descriptor + packets that we won't be able to handle + */ + assert(!(descr->descr->des[DES0]&DES0_OWN)); + assert(descr->descr->des[DES0]&DES0_FS); + assert(descr->descr->des[DES0]&DES0_LS); + + /* Check for abnormal messages. We assert here + because this driver is for a virtualized + envrionment where we will not get bad packets + */ + assert(!(descr->descr->des[DES0]&DES0_ES)); + assert(!(descr->descr->des[DES0]&DES0_RE)); + + + /* Setup the iovec entry to allow copying into + client layer + */ + dep->de_read_iovec.iod_proc_nr = mp->DL_PROC; + de_get_userdata_s(mp->DL_PROC, (vir_bytes) mp->DL_GRANT, 0, + mp->DL_COUNT, dep->de_read_iovec.iod_iovec); + dep->de_read_iovec.iod_iovec_s = mp->DL_COUNT; + dep->de_read_iovec.iod_grant = (vir_bytes) mp->DL_GRANT; + dep->de_read_iovec.iod_iovec_offset = 0; + size = de_calc_iov_size(&dep->de_read_iovec); + if (size < ETH_MAX_PACK_SIZE) + panic(str_DevName, str_SizeErrMsg, size); + + /* Copy buffer to user area and clear ownage */ + size = (descr->descr->des[DES0]&DES0_FL)>>DES0_FL_SHIFT; + + /*TODO: Complain to MS */ + /*HACK: VPC2007 returns packet of invalid size. Ethernet standard + specify 46 bytes as the minimum for valid payload. However, this is + artificial in so far as for certain packet types, notably ARP, less + then 46 bytes are needed to contain the full information. In a non + virtualized environment the 46 bytes rule is enforced in order to give + guarantee in the collison detection scheme. Of course, this being a + driver for a VPC2007, we won't have collisions and I can only suppose + MS decided to cut packet size to true minimum, regardless of the + 46 bytes payload standard. Note that this seems to not happen in + bridged mode. Note also, that the card does not return runt or + incomplete frames to us, so this hack is safe + */ + if(size<60){ + bzero(&descr->buf1[size], 60-size); + size=60; + } + /* End ugly hack */ + + iovp = &dep->de_read_iovec; + buffer = descr->buf1; + dep->bytes_rx += size; + dep->de_stat.ets_packetR++; + dep->de_read_s = size; + + do { + bytes = iovp->iod_iovec[ix].iov_size; /* Size of buffer */ + if (bytes >= size) + bytes = size; + + r= sys_safecopyto(iovp->iod_proc_nr, iovp->iod_iovec[ix].iov_grant, 0, + (vir_bytes)buffer, bytes, D); + if (r != OK) + panic(str_DevName, str_CopyErrMsg, r); + buffer += bytes; + + if (++ix >= IOVEC_NR) { /* Next buffer of IO vector */ + de_next_iov(iovp); + ix = 0; + } + } while ((size -= bytes) > 0); + + descr->descr->des[DES0]=DES0_OWN; + dep->cur_descr[DESCR_RECV]++; + if(dep->cur_descr[DESCR_RECV] >= DE_NB_RECV_DESCR) + dep->cur_descr[DESCR_RECV] = 0; + + DEBUG(printf("Read returned size = %d\n", size)); + + /* Reply information */ + dep->de_flags |= DEF_ACK_RECV; + dep->de_flags &= NOT(DEF_READING); + } + + if(!from_int){ + do_reply(dep, OK, FALSE); + } + return; + + suspend: + if(from_int){ + assert(dep->de_flags & DEF_READING); + return; + } + + assert(!(dep->de_flags & DEF_READING)); + dep->rx_return_msg = *mp; + dep->de_flags |= DEF_READING; + do_reply(dep, OK, FALSE); + return; +} + +PRIVATE void de_conf_addr(dpeth_t * dep) +{ + static char ea_fmt[] = "x:x:x:x:x:x"; + char ea_key[16]; + int ix; + long val; + + /* TODO: should be configurable... */ + strcpy(ea_key, "DEETH0"); + strcat(ea_key, "_EA"); + + for (ix = 0; ix < SA_ADDR_LEN; ix++) { + val = dep->de_address.ea_addr[ix]; + if (env_parse(ea_key, ea_fmt, ix, &val, 0x00L, 0xFFL) != EP_SET) + break; + dep->de_address.ea_addr[ix] = val; + } + + if (ix != 0 && ix != SA_ADDR_LEN) + env_parse(ea_key, "?", 0, &val, 0L, 0L); + return; +} + +PRIVATE void do_fkey(message *mp) +{ + dpeth_t *dep; + int port,i; + + printf("\n"); + for (port = 0, dep = de_table; port < DE_PORT_NR; port += 1, dep += 1) { + if (dep->de_mode == DEM_DISABLED) continue; + printf("%s status:\n", dep->de_name); + printf("hwaddr: "); + for(i=0;i<6;i++) + printf("%02X%c",dep->de_address.ea_addr[i], i!=5?':':'\n'); + printf("Tx packets: %-16d Tx kb: %d.%02d\n", dep->de_stat.ets_packetT, + dep->bytes_tx/1024, + (int)(((dep->bytes_tx%1024)/1024.0)*100)); + printf("Rx packets: %-16d Rx kb: %d.%02d\n", dep->de_stat.ets_packetR, + dep->bytes_rx/1024, + (int)(((dep->bytes_rx%1024)/1024.0)*100)); + printf("Rx errors: %-16d Tx errors: %d\n", + dep->de_stat.ets_recvErr, + dep->de_stat.ets_sendErr); + } + return; +} + +PRIVATE void de_first_init(dpeth_t *dep){ + int i,j,r; + vir_bytes descr_vir = dep->sendrecv_descr_buf; + vir_bytes buffer_vir = dep->sendrecv_buf; + de_descr_t *phys_descr; + de_loc_descr_t *loc_descr; + u32_t temp; + + + for(i=0;i<2;i++){ + loc_descr = &dep->descr[i][0]; + for(j=0; j < (i==DESCR_RECV ? DE_NB_RECV_DESCR : DE_NB_SEND_DESCR); j++){ + + /* assign buffer space for descriptor */ + loc_descr->descr = descr_vir; + descr_vir += sizeof(de_descr_t); + + /* assign space for buffer */ + loc_descr->buf1 = buffer_vir; + buffer_vir += (i==DESCR_RECV ? DE_RECV_BUF_SIZE : DE_SEND_BUF_SIZE); + loc_descr->buf2 = 0; + loc_descr++; + } + } + + /* Now that we have buffer space and descriptors, we need to + obtain their physical address to pass to the hardware + */ + for(i=0;i<2;i++){ + loc_descr = &dep->descr[i][0]; + temp = (i==DESCR_RECV ? DE_RECV_BUF_SIZE : DE_SEND_BUF_SIZE); + for(j=0; j < (i==DESCR_RECV ? DE_NB_RECV_DESCR : DE_NB_SEND_DESCR); j++){ + /* translate buffers physical address */ + r = sys_umap(SELF, VM_D, loc_descr->buf1, temp, + &(loc_descr->descr->des[DES_BUF1])); + if(r != OK) panic(dep->de_name, "umap failed", r); + loc_descr->descr->des[DES_BUF2] = 0; + memset(&loc_descr->descr->des[DES0],0,sizeof(u32_t)); + loc_descr->descr->des[DES1] = temp; + if(j==( (i==DESCR_RECV?DE_NB_RECV_DESCR:DE_NB_SEND_DESCR)-1)) + loc_descr->descr->des[DES1] |= DES1_ER; + if(i==DESCR_RECV) + loc_descr->descr->des[DES0] |= DES0_OWN; + loc_descr++; + } + } + + /* record physical location of two first descriptor */ + r = sys_umap(SELF, VM_D, dep->descr[DESCR_RECV][0].descr, + sizeof(de_descr_t), &dep->sendrecv_descr_phys_addr[DESCR_RECV]); + if(r != OK) panic(str_DevName, str_UmapErrMsg, r); + + r = sys_umap(SELF, VM_D, dep->descr[DESCR_TRAN][0].descr, + sizeof(de_descr_t), &dep->sendrecv_descr_phys_addr[DESCR_TRAN]); + if(r != OK) panic(str_DevName, str_UmapErrMsg, r); + + DEBUG(printf("Descr: head tran=[%08X] head recv=[%08X]\n", + dep->sendrecv_descr_phys_addr[DESCR_TRAN], + dep->sendrecv_descr_phys_addr[DESCR_RECV])); + + /* check alignment just to be extra safe */ + for(i=0;i<2;i++){ + loc_descr = &dep->descr[i][0]; + for(j=0;j< (i==DESCR_RECV?DE_NB_RECV_DESCR:DE_NB_SEND_DESCR);j++){ + r = sys_umap(SELF, VM_D, &(loc_descr->descr), sizeof(de_descr_t), + &temp); + if(r != OK) + panic(str_DevName, str_UmapErrMsg, r); + + if( ((loc_descr->descr->des[DES_BUF1] & 0x3) != 0) || + ((loc_descr->descr->des[DES_BUF2] & 0x3) != 0) || + ((temp&0x3)!=0) ) + panic(str_DevName, str_AlignErrMsg, temp); + + loc_descr++; + } + } + + /* Init default values */ + dep->cur_descr[DESCR_TRAN]=1; + dep->cur_descr[DESCR_RECV]=0; + dep->bytes_rx = 0; + dep->bytes_tx = 0; + + /* Set the interrupt handler policy. Request interrupts not to be reenabled + * automatically. Return the IRQ line number when an interrupt occurs. + */ + dep->de_hook = dep->de_irq; + sys_irqsetpolicy(dep->de_irq, 0, &dep->de_hook); + sys_irqenable(&dep->de_hook); +} + +PRIVATE void do_interrupt(dpeth_t *dep){ + u32_t val; + val = io_inl(CSR_ADDR(dep, CSR5)); + + if(val & CSR5_AIS){ + panic(dep->de_name, "Abnormal Int CSR5=", val); + } + + if( (dep->de_flags & DEF_READING) && (val & CSR5_RI) ){ + do_vread_s(&dep->rx_return_msg, TRUE); + } + + if( (dep->de_flags & DEF_SENDING) && (val & CSR5_TI) ){ + do_vwrite_s(&dep->tx_return_msg, TRUE); + } + + /* ack and reset interrupts */ + io_outl(CSR_ADDR(dep, CSR5), 0xFFFFFFFF); + return; +} + +PRIVATE void de_reset(dpeth_t *dep){ + io_outl(CSR_ADDR(dep, CSR0), CSR0_SWR); + micro_delay(1000000); +} + +PRIVATE void de_hw_conf(dpeth_t *dep){ + u32_t val; + + /* CSR0 - global host bus prop */ + val = CSR0_BAR | CSR0_CAL_8; + io_outl(CSR_ADDR(dep, CSR0), val); + + /* CSR3 - Receive list BAR */ + val = dep->sendrecv_descr_phys_addr[DESCR_RECV]; + io_outl(CSR_ADDR(dep, CSR3), val); + + /* CSR4 - Transmit list BAR */ + val = dep->sendrecv_descr_phys_addr[DESCR_TRAN]; + io_outl(CSR_ADDR(dep, CSR4), val); + + /* CSR7 - interrupt mask */ + val = CSR7_TI | CSR7_RI | CSR7_AI; + io_outl(CSR_ADDR(dep, CSR7), val); + + /* CSR6 - operating mode register */ + val = CSR6_MBO | CSR6_PS | CSR6_FD | CSR6_HBD | + CSR6_PCS | CSR6_SCR | CSR6_TR_00; + io_outl(CSR_ADDR(dep, CSR6), val); +} + +PRIVATE void de_start(dpeth_t *dep){ + u32_t val; + val = io_inl(CSR_ADDR(dep, CSR6)) | CSR6_ST | CSR6_SR; + io_outl(CSR_ADDR(dep, CSR6), val); +} + +PRIVATE void de_setup_frame(dpeth_t *dep){ + int i; + u32_t val; + + /* this is not perfect... we assume pass all multicast and only + filter non-multicast frames */ + dep->descr[DESCR_TRAN][0].buf1[0] = 0xFF; + dep->descr[DESCR_TRAN][0].buf1[1] = 0xFF; + dep->descr[DESCR_TRAN][0].buf1[4] = 0xFF; + dep->descr[DESCR_TRAN][0].buf1[5] = 0xFF; + dep->descr[DESCR_TRAN][0].buf1[8] = 0xFF; + dep->descr[DESCR_TRAN][0].buf1[9] = 0xFF; + for(i=1;i<16;i++){ + memset(&(dep->descr[DESCR_TRAN][0].buf1[12*i]), 0, 12); + dep->descr[DESCR_TRAN][0].buf1[12*i+0] = dep->de_address.ea_addr[0]; + dep->descr[DESCR_TRAN][0].buf1[12*i+1] = dep->de_address.ea_addr[1]; + dep->descr[DESCR_TRAN][0].buf1[12*i+4] = dep->de_address.ea_addr[2]; + dep->descr[DESCR_TRAN][0].buf1[12*i+5] = dep->de_address.ea_addr[3]; + dep->descr[DESCR_TRAN][0].buf1[12*i+8] = dep->de_address.ea_addr[4]; + dep->descr[DESCR_TRAN][0].buf1[12*i+9] = dep->de_address.ea_addr[5]; + } + + dep->descr[DESCR_TRAN][0].descr->des[DES0] = DES0_OWN; + dep->descr[DESCR_TRAN][0].descr->des[DES1] = DES1_SET | + DE_SETUP_FRAME_SIZE | DES1_IC; + + /* start transmit process to process setup frame */ + val = io_inl(CSR_ADDR(dep, CSR6)) | CSR6_ST; + io_outl(CSR_ADDR(dep, CSR6), val); + io_outl(CSR_ADDR(dep, CSR1), 0xFFFFFFFF); + + return; +} + +PRIVATE int de_calc_iov_size(iovec_dat_s_t * iovp){ + int size, ix; + size = ix = 0; + + do{ + size += iovp->iod_iovec[ix].iov_size; + if (++ix >= IOVEC_NR) { + de_next_iov(iovp); + ix = 0; + } + } while (ix < iovp->iod_iovec_s); + return size; +} + +PRIVATE void de_get_userdata_s(int user_proc, cp_grant_id_t grant, + vir_bytes offset, int count, void *loc_addr){ + int rc; + vir_bytes len; + + len = (count > IOVEC_NR ? IOVEC_NR : count) * sizeof(iovec_t); + rc = sys_safecopyfrom(user_proc, grant, 0, (vir_bytes)loc_addr, len, D); + if (rc != OK) + panic(str_DevName, str_CopyErrMsg, rc); + return; +} + +PRIVATE void de_next_iov(iovec_dat_s_t * iovp){ + + iovp->iod_iovec_s -= IOVEC_NR; + iovp->iod_iovec_offset += IOVEC_NR * sizeof(iovec_t); + de_get_userdata_s(iovp->iod_proc_nr, iovp->iod_grant, iovp->iod_iovec_offset, + iovp->iod_iovec_s, iovp->iod_iovec); + return; +} + +PRIVATE void do_vwrite_s(message * mp, int from_int){ + static u8_t setupDone = 0; + int size, r, bytes, ix, totalsize; + dpeth_t *dep = NULL; + iovec_dat_s_t *iovp = NULL; + de_loc_descr_t *descr = NULL; + char *buffer = NULL; + + if( mp->DL_PORT < 0 || mp->DL_PORT >= DE_PORT_NR) + panic(str_DevName, str_PortErrMsg, mp->DL_PORT); + + dep = &de_table[mp->DL_PORT]; + dep->de_client = mp->DL_PROC; + + if (dep->de_mode == DEM_ENABLED) { + + if (!from_int && (dep->de_flags & DEF_SENDING)) + panic(str_DevName, str_BusyErrMsg, NO_NUM); + + descr = &dep->descr[DESCR_TRAN][dep->cur_descr[DESCR_TRAN]]; + + if(( descr->descr->des[DES0] & DES0_OWN)!=0) + goto suspend; + + if(!setupDone && (dep->cur_descr[DESCR_TRAN] == 0) ){ + dep->descr[DESCR_TRAN][0].descr->des[DES0] = 0; + setupDone=1; + } + + buffer = descr->buf1; + iovp = &dep->de_write_iovec; + iovp->iod_proc_nr = mp->DL_PROC; + de_get_userdata_s(mp->DL_PROC, mp->DL_GRANT, 0, + mp->DL_COUNT, iovp->iod_iovec); + iovp->iod_iovec_s = mp->DL_COUNT; + iovp->iod_grant = (vir_bytes) mp->DL_GRANT; + iovp->iod_iovec_offset = 0; + totalsize = size = de_calc_iov_size(iovp); + if (size < ETH_MIN_PACK_SIZE || size > ETH_MAX_PACK_SIZE) + panic(str_DevName, str_SizeErrMsg, size); + + dep->bytes_tx += size; + dep->de_stat.ets_packetT++; + + ix=0; + do { + bytes = iovp->iod_iovec[ix].iov_size; + if (bytes >= size) + bytes = size; + + r= sys_safecopyfrom(iovp->iod_proc_nr, iovp->iod_iovec[ix].iov_grant, + 0, (vir_bytes)buffer, bytes, D); + if (r != OK) + panic(str_DevName, str_CopyErrMsg, r); + buffer += bytes; + + if (++ix >= IOVEC_NR) { + de_next_iov(iovp); + ix = 0; + } + } while ((size -= bytes) > 0); + + descr->descr->des[DES1] = (descr->descr->des[DES1]&DES1_ER) | + DES1_FS | DES1_LS | DES1_IC | totalsize; + descr->descr->des[DES0] = DES0_OWN; + + dep->cur_descr[DESCR_TRAN]++; + if(dep->cur_descr[DESCR_TRAN] >= DE_NB_SEND_DESCR) + dep->cur_descr[DESCR_TRAN] = 0; + + io_outl(CSR_ADDR(dep, CSR1), 0xFFFFFFFF); + } + + dep->de_flags |= DEF_ACK_SEND; + if(from_int){ + dep->de_flags &= NOT(DEF_SENDING); + return; + } + do_reply(dep, OK, FALSE); + return; + + suspend: + if(from_int) + panic(str_DevName, "should not happen", 0); + + dep->de_stat.ets_transDef++; + dep->de_flags |= DEF_SENDING; + dep->de_stat.ets_transDef++; + dep->tx_return_msg = *mp; + do_reply(dep, OK, FALSE); +} + +PRIVATE void warning(const char *type, int err){ + printf("Warning: %s sys_%s failed (%d)\n", str_DevName, type, err); + return; +} + +PRIVATE u32_t io_inl(u16_t port){ + u32_t value; + int rc; + if ((rc = sys_inl(port, &value)) != OK) warning("inl", rc); + return value; +} + +PRIVATE void io_outl(u16_t port, u32_t value){ + int rc; + if ((rc = sys_outl(port, value)) != OK) warning("outl", rc); + return; +} diff --git a/drivers/dec21140A/dec21140A.h b/drivers/dec21140A/dec21140A.h new file mode 100644 index 000000000..675070a34 --- /dev/null +++ b/drivers/dec21140A/dec21140A.h @@ -0,0 +1,238 @@ +#ifndef INCL_DEC21041_H_GUARD +#define INCL_DEC21041_H_GUARD +/* +de.h + +Header for the driver of the DEC 21140A ethernet card as emulated +by VirtualPC 2007 + +Created: 09/01/2009 Nicolas Tittley (first.last @ gmail DOT com) +*/ + + +#define DE_PORT_NR 1 + +#define DE_FKEY 8 /* Shitf+ this value will dump info on console */ + +#undef NULL +#define NULL ((void *)0) +#define NOT(x) (~(x)) + +#if debug == 1 +# define DEBUG(statm) statm +#else +# define DEBUG(statm) +#endif + + +#define SA_ADDR_LEN sizeof(ether_addr_t) + +#define DE_NB_SEND_DESCR 32 +#define DE_SEND_BUF_SIZE (ETH_MAX_PACK_SIZE+2) +#define DE_NB_RECV_DESCR 32 +#define DE_RECV_BUF_SIZE (ETH_MAX_PACK_SIZE+2) +#define IOVEC_NR 16 +#define DE_MIN_BASE_ADDR 0x0400 +#define DE_SROM_EA_OFFSET 20 +#define DE_SETUP_FRAME_SIZE 192 +#define DEC21140A_VID 0x1011 +#define DEC21140A_DID 0x0009 + + +typedef struct iovec_dat_s { + iovec_s_t iod_iovec[IOVEC_NR]; + int iod_iovec_s; + int iod_proc_nr; + cp_grant_id_t iod_grant; + vir_bytes iod_iovec_offset; +} iovec_dat_s_t; + +typedef struct de_descr { + u32_t des[4]; +} de_descr_t; + +typedef struct de_local_descr { + de_descr_t *descr; + u8_t *buf1; + u8_t *buf2; +} de_loc_descr_t; + +typedef struct dpeth { + + message rx_return_msg; /* Holds VREAD message until int */ + message tx_return_msg; /* Holds VWRITE message until int */ + char de_name[32]; /* Name of this interface */ + port_t de_base_port; /* Base port, for multiple card instance */ + int de_irq; /* IRQ line number */ + int de_hook; /* interrupt hook at kernel */ + + int de_type; /* What kind of hardware */ + + ether_addr_t de_address; /* Ethernet Address */ + eth_stat_t de_stat; /* Stats */ + unsigned long bytes_tx; /* Number of bytes sent */ + unsigned long bytes_rx; /* Number of bytes recv */ + + /* Space reservation. We will allocate all structures later in the code. + here we just make sure we have the space we need at compile time */ + u8_t sendrecv_descr_buf[(DE_NB_SEND_DESCR+DE_NB_RECV_DESCR)* + sizeof(de_descr_t)]; + u8_t sendrecv_buf[DE_NB_SEND_DESCR*DE_SEND_BUF_SIZE + + DE_NB_RECV_DESCR*DE_RECV_BUF_SIZE]; + phys_bytes sendrecv_descr_phys_addr[2]; + de_loc_descr_t descr[2][MAX(DE_NB_RECV_DESCR, DE_NB_SEND_DESCR)]; + int cur_descr[2]; + +#define DESCR_RECV 0 +#define DESCR_TRAN 1 + + int de_flags; /* Send/Receive mode (Configuration) */ + +#define DEF_EMPTY 0x0000 +#define DEF_READING 0x0001 +#define DEF_RECV_BUSY 0x0002 +#define DEF_ACK_RECV 0x0004 +#define DEF_SENDING 0x0010 +#define DEF_XMIT_BUSY 0x0020 +#define DEF_ACK_SEND 0x0040 +#define DEF_PROMISC 0x0100 +#define DEF_MULTI 0x0200 +#define DEF_BROAD 0x0400 +#define DEF_ENABLED 0x2000 +#define DEF_STOPPED 0x4000 + + int de_mode; /* Status of the Interface */ + +#define DEM_DISABLED 0x0000 +#define DEM_SINK 0x0001 +#define DEM_ENABLED 0x0002 + + + /* Serial ROM */ +#define SROM_BITWIDTH 6 + + u8_t srom[((1<de_base_port + i) */ +#define CSR_ADDR(x, i) (x->de_base_port + i) + +/* CSRs */ +#define CSR0 0x00 +#define CSR0_SWR 0x00000001 /* sw reset */ +#define CSR0_BAR 0x00000002 /* bus arbitration */ +#define CSR0_CAL_8 0x00004000 /* cache align 8 long word */ +#define CSR0_TAP 0x00080000 /* trans auto polling */ +#define CSR1 0x08 /* transmit poll demand */ +#define CSR2 0x10 /* receive poll demand */ +#define CSR3 0x18 /* receive list address */ +#define CSR4 0x20 /* transmit list address */ +#define CSR5 0x28 /* status register */ +#define CSR5_EB 0x03800000 /* error bits */ +#define CSR5_TS 0x00700000 /* Transmit proc state */ +#define CSR5_RS 0x000E0000 /* Receive proc state */ +#define CSR5_NIS 0x00010000 /* Norm Int summ */ +#define CSR5_AIS 0x00008000 /* Abnorm Int sum */ +#define CSR5_FBE 0x00002000 /* Fatal bit error */ +#define CSR5_GTE 0x00000800 /* Gen-purp timer exp */ +#define CSR5_ETI 0x00000400 /* Early Trans int */ +#define CSR5_RWT 0x00000200 /* Recv watchdog timeout */ +#define CSR5_RPS 0x00000100 /* Recv proc stop */ +#define CSR5_RU 0x00000080 /* Recv buf unavail */ +#define CSR5_RI 0x00000040 /* Recv interrupt */ +#define CSR5_UNF 0x00000020 /* Trans underflow */ +#define CSR5_TJT 0x00000008 /* Trans Jabber Timeout */ +#define CSR5_TU 0x00000004 /* Trans buf unavail */ +#define CSR5_TPS 0x00000002 /* Trans proc stopped */ +#define CSR5_TI 0x00000001 /* Trans interrupt */ +#define CSR6 0x30 /* Operation mode */ +#define CSR6_SC 0x80000000 /* Special capt effect ena 31 */ +#define CSR6_RA 0x40000000 /* receive all 30 */ +#define CSR6_MBO 0x02000000 /* must be one 25 */ +#define CSR6_SCR 0x01000000 /* Scrambler mode 24 */ +#define CSR6_PCS 0x00800000 /* PCS function 23 */ +#define CSR6_TTM 0x00400000 /* Trans threshold mode 22 */ +#define CSR6_SF 0x00200000 /* store and forward 21 */ +#define CSR6_HBD 0x00080000 /* Heartbeat disable 19 */ +#define CSR6_PS 0x00040000 /* port select 18 */ +#define CSR6_CA 0x00020000 /* Capt effect ena 17 */ +#define CSR6_TR_00 0x00000000 /* Trans thresh 15:14 */ +#define CSR6_TR_01 0x00004000 /* Trans thresh 15:14 */ +#define CSR6_TR_10 0x00008000 /* Trans thresh 15:14 */ +#define CSR6_TR_11 0x0000C000 /* Trans thresh 15:14 */ +#define CSR6_ST 0x00002000 /* start/stop trans 13 */ +#define CSR6_FD 0x00000200 /* Full Duplex 9 */ +#define CSR6_PM 0x00000080 /* Pass all multicast 7 */ +#define CSR6_PR 0x00000040 /* Promisc mode 6 */ +#define CSR6_IF 0x00000010 /* Inv filtering 4 */ +#define CSR6_HO 0x00000004 /* Hash-only filtering 2 */ +#define CSR6_SR 0x00000002 /* start/stop recv 1 */ +#define CSR6_HP 0x00000001 /* Hash/perfect recv filt mode 0 */ +#define CSR7 0x38 /* Interrupt enable */ +#define CSR7_NI 0x00010000 /* Normal interrupt ena */ +#define CSR7_AI 0x00008000 /* Abnormal int ena */ +#define CSR7_TI 0x00000001 /* trans int ena */ +#define CSR7_TU 0x00000004 /* trans buf unavail ena */ +#define CSR7_RI 0x00000040 /* recv interp ena */ +#define CSR7_GPT 0x00000800 /* gen purpose timer ena */ +#define CSR9 0x48 /* Boot Rom, serial ROM, MII */ +#define CSR9_SR 0x0800 /* serial ROM select */ +#define CSR9_RD 0x4000 /* read */ +#define CSR9_DO 0x0008 /* data out */ +#define CSR9_DI 0x0004 /* data in */ +#define CSR9_SRC 0x0002 /* serial clock */ +#define CSR9_CS 0x0001 /* serial rom chip select */ +/* Send/Recv Descriptors */ + +#define DES0 0 +#define DES0_OWN 0x80000000 /* descr ownership. 1=211140A */ +#define DES0_FL 0x3FFF0000 /* frame length */ +#define DES0_FL_SHIFT 16 /* shift to fix frame length */ +#define DES0_ES 0x00008000 /* Error sum */ +#define DES0_TO 0x00004000 /* Trans jabber timeout */ +#define DES0_LO 0x00000800 /* Loss of carrier */ +#define DES0_NC 0x00000400 /* no carrier */ +#define DES0_LC 0x00000200 /* Late coll */ +#define DES0_EC 0x00000100 /* Excessive coll */ +#define DES0_UF 0x00000002 /* Underflow error */ +#define DES0_RE 0x00000008 /* MII error */ +#define DES0_FS 0x00000200 /* first descr */ +#define DES0_LS 0x00000100 /* last descr */ +#define DES1 1 +#define DES1_ER 0x02000000 /* end of ring */ +#define DES1_SAC 0x01000000 /* 2nd address chained */ +#define DES1_BS2 0x003FF800 /* 2nd buffer size */ +#define DES1_BS2_SHFT 11 /* shift to obtain 2nd buffer size */ +#define DES1_BS1 0x000007FF /* 1nd buffer size */ +#define DES1_IC 0x80000000 /* Interrupt on completion 31 */ +#define DES1_LS 0x40000000 /* Last Segment 30 */ +#define DES1_FS 0x20000000 /* First Segment 29 */ +#define DES1_FT1 0x10000000 /* Filtering type 28 */ +#define DES1_SET 0x08000000 /* Setup frame 27 */ +#define DES1_AC 0x04000000 /* Add CRC disable 26 */ +#define DES1_DPD 0x00800000 /* Disabled padding 23 */ +#define DES1_FT0 0x00400000 /* Filtering type 22 */ +#define DES2 2 /* 1st buffer addr */ +#define DES3 3 /* 2nd buffer addr */ + +#define DES_BUF1 DES2 +#define DES_BUF2 DES3 + +#endif /* Include Guard */ diff --git a/etc/system.conf b/etc/system.conf index 5abdc954c..7123e51b4 100644 --- a/etc/system.conf +++ b/etc/system.conf @@ -568,3 +568,26 @@ service atl2 pci inet ; }; + +service dec21140A +{ + system + UMAP # 14 + IRQCTL # 19 + DEVIO # 21 + #SDEVIO # 22 + SETALARM # 24 + TIMES # 25 + GETINFO # 26 + SAFECOPYFROM # 31 + SAFECOPYTO # 32 + SETGRANT # 34 + PROFBUF # 38 + SYSCTL + ; + pci device 1011/0009; + ipc + SYSTEM PM RS LOG TTY DS VM + pci inet + ; +}; diff --git a/etc/usr/rc b/etc/usr/rc index da71e108d..1db0489f5 100644 --- a/etc/usr/rc +++ b/etc/usr/rc @@ -91,7 +91,7 @@ start) fi # start only network drivers that are in use - for driver in lance rtl8139 rtl8169 fxp e1000 dpeth dp8390 orinoco atl2 + for driver in lance rtl8139 rtl8169 fxp e1000 dpeth dp8390 orinoco atl2 dec21140A do if grep " $driver " /etc/inet.conf > /dev/null 2>&1 then -- 2.44.0