dec21140A ethernet driver for virtualpc, contributed by nicolas tittley.
This commit is contained in:
parent
f23a37e10f
commit
76f8132545
@ -112,7 +112,8 @@ cards()
|
|||||||
card 7 "AMD LANCE (also emulated by VMWare and VirtualBox)" "1022:2000"
|
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 8 "Intel PRO/1000 Gigabit" "8086:100E" "8086:107C" "8086:10CD"
|
||||||
card 9 "Attansic/Atheros L2 FastEthernet" "1969:2048"
|
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()
|
warn()
|
||||||
@ -160,7 +161,8 @@ drv_params()
|
|||||||
7) driver="lance"; ;;
|
7) driver="lance"; ;;
|
||||||
8) driver="e1000"; ;;
|
8) driver="e1000"; ;;
|
||||||
9) driver="atl2"; ;;
|
9) driver="atl2"; ;;
|
||||||
10) driver="psip0"; ;;
|
10) driver="dec21140A"; ;;
|
||||||
|
11) driver="psip0"; ;;
|
||||||
*) warn "choose a number"
|
*) warn "choose a number"
|
||||||
esac
|
esac
|
||||||
}
|
}
|
||||||
|
@ -37,6 +37,7 @@ all install depend clean:
|
|||||||
cd ./dp8390 && $(MAKE) $@
|
cd ./dp8390 && $(MAKE) $@
|
||||||
cd ./sb16 && $(MAKE) $@
|
cd ./sb16 && $(MAKE) $@
|
||||||
cd ./lance && $(MAKE) $@
|
cd ./lance && $(MAKE) $@
|
||||||
|
cd ./dec21140A && $(MAKE) $@
|
||||||
cd ./pci && $(MAKE) $@
|
cd ./pci && $(MAKE) $@
|
||||||
cd ./ti1225 && $(MAKE) $@
|
cd ./ti1225 && $(MAKE) $@
|
||||||
cd ./memory && $(MAKE) $@ # Must be last for ramdisk image
|
cd ./memory && $(MAKE) $@ # Must be last for ramdisk image
|
||||||
|
43
drivers/dec21140A/Makefile
Normal file
43
drivers/dec21140A/Makefile
Normal file
@ -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
|
28
drivers/dec21140A/README.txt
Normal file
28
drivers/dec21140A/README.txt
Normal file
@ -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.
|
945
drivers/dec21140A/dec21140A.c
Normal file
945
drivers/dec21140A/dec21140A.c
Normal file
@ -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 <first.last@ google's mail>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "../drivers.h"
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <ibm/pci.h>
|
||||||
|
#include <minix/syslib.h>
|
||||||
|
#include <minix/endpoint.h>
|
||||||
|
#include <minix/com.h>
|
||||||
|
#include <minix/sef.h>
|
||||||
|
#include <minix/ds.h>
|
||||||
|
#include <net/hton.h>
|
||||||
|
#include <net/gen/ether.h>
|
||||||
|
#include <net/gen/eth_io.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#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_BITWIDTH)-1;i++){
|
||||||
|
temp16 = de_read_rom(dep, i, SROM_BITWIDTH);
|
||||||
|
dep->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;
|
||||||
|
}
|
238
drivers/dec21140A/dec21140A.h
Normal file
238
drivers/dec21140A/dec21140A.h
Normal file
@ -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<<SROM_BITWIDTH)-1)*2]; /* Space to read in
|
||||||
|
all the configuration ROM */
|
||||||
|
|
||||||
|
|
||||||
|
/* Temporary storage for RECV/SEND requests */
|
||||||
|
iovec_dat_s_t de_read_iovec;
|
||||||
|
iovec_dat_s_t de_write_iovec;
|
||||||
|
vir_bytes de_read_s;
|
||||||
|
vir_bytes de_send_s;
|
||||||
|
int de_client;
|
||||||
|
|
||||||
|
} dpeth_t;
|
||||||
|
|
||||||
|
|
||||||
|
/************/
|
||||||
|
/* Revisons */
|
||||||
|
/************/
|
||||||
|
|
||||||
|
#define DEC_21140A 0x20
|
||||||
|
#define DE_TYPE_UNKNOWN 0x0
|
||||||
|
/* #define CSR_ADDR(x, i) csraddr2(x->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 */
|
@ -568,3 +568,26 @@ service atl2
|
|||||||
pci inet
|
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
|
||||||
|
;
|
||||||
|
};
|
||||||
|
@ -91,7 +91,7 @@ start)
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# start only network drivers that are in use
|
# 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
|
do
|
||||||
if grep " $driver " /etc/inet.conf > /dev/null 2>&1
|
if grep " $driver " /etc/inet.conf > /dev/null 2>&1
|
||||||
then
|
then
|
||||||
|
Loading…
x
Reference in New Issue
Block a user