minix/drivers/dpeth/dp.c
David van Moolenbroek b423d7b477 Merge of David's ptrace branch. Summary:
o Support for ptrace T_ATTACH/T_DETACH and T_SYSCALL
o PM signal handling logic should now work properly, even with debuggers
  being present
o Asynchronous PM/VFS protocol, full IPC support for senda(), and
  AMF_NOREPLY senda() flag

DETAILS

Process stop and delay call handling of PM:
o Added sys_runctl() kernel call with sys_stop() and sys_resume()
  aliases, for PM to stop and resume a process
o Added exception for sending/syscall-traced processes to sys_runctl(),
  and matching SIGKREADY pseudo-signal to PM
o Fixed PM signal logic to deal with requests from a process after
  stopping it (so-called "delay calls"), using the SIGKREADY facility
o Fixed various PM panics due to race conditions with delay calls versus
  VFS calls
o Removed special PRIO_STOP priority value
o Added SYS_LOCK RTS kernel flag, to stop an individual process from
  running while modifying its process structure

Signal and debugger handling in PM:
o Fixed debugger signals being dropped if a second signal arrives when
  the debugger has not retrieved the first one
o Fixed debugger signals being sent to the debugger more than once
o Fixed debugger signals unpausing process in VFS; removed PM_UNPAUSE_TR
  protocol message
o Detached debugger signals from general signal logic and from being
  blocked on VFS calls, meaning that even VFS can now be traced
o Fixed debugger being unable to receive more than one pending signal in
  one process stop
o Fixed signal delivery being delayed needlessly when multiple signals
  are pending
o Fixed wait test for tracer, which was returning for children that were
  not waited for
o Removed second parallel pending call from PM to VFS for any process
o Fixed process becoming runnable between exec() and debugger trap
o Added support for notifying the debugger before the parent when a
  debugged child exits
o Fixed debugger death causing child to remain stopped forever
o Fixed consistently incorrect use of _NSIG

Extensions to ptrace():
o Added T_ATTACH and T_DETACH ptrace request, to attach and detach a
  debugger to and from a process
o Added T_SYSCALL ptrace request, to trace system calls
o Added T_SETOPT ptrace request, to set trace options
o Added TO_TRACEFORK trace option, to attach automatically to children
  of a traced process
o Added TO_ALTEXEC trace option, to send SIGSTOP instead of SIGTRAP upon
  a successful exec() of the tracee
o Extended T_GETUSER ptrace support to allow retrieving a process's priv
  structure
o Removed T_STOP ptrace request again, as it does not help implementing
  debuggers properly
o Added MINIX3-specific ptrace test (test42)
o Added proper manual page for ptrace(2)

Asynchronous PM/VFS interface:
o Fixed asynchronous messages not being checked when receive() is called
  with an endpoint other than ANY
o Added AMF_NOREPLY senda() flag, preventing such messages from
  satisfying the receive part of a sendrec()
o Added asynsend3() that takes optional flags; asynsend() is now a
  #define passing in 0 as third parameter
o Made PM/VFS protocol asynchronous; reintroduced tell_fs()
o Made PM_BASE request/reply number range unique
o Hacked in a horrible temporary workaround into RS to deal with newly
  revealed RS-PM-VFS race condition triangle until VFS is asynchronous

System signal handling:
o Fixed shutdown logic of device drivers; removed old SIGKSTOP signal
o Removed is-superuser check from PM's do_procstat() (aka getsigset())
o Added sigset macros to allow system processes to deal with the full
  signal set, rather than just the POSIX subset

Miscellaneous PM fixes:
o Split do_getset into do_get and do_set, merging common code and making
  structure clearer
o Fixed setpriority() being able to put to sleep processes using an
  invalid parameter, or revive zombie processes
o Made find_proc() global; removed obsolete proc_from_pid()
o Cleanup here and there

Also included:
o Fixed false-positive boot order kernel warning
o Removed last traces of old NOTIFY_FROM code

THINGS OF POSSIBLE INTEREST

o It should now be possible to run PM at any priority, even lower than
  user processes
o No assumptions are made about communication speed between PM and VFS,
  although communication must be FIFO
o A debugger will now receive incoming debuggee signals at kill time
  only; the process may not yet be fully stopped
o A first step has been made towards making the SYSTEM task preemptible
2009-09-30 09:57:22 +00:00

677 lines
18 KiB
C

#include <assert.h>
/*
** File: dp.c Version 1.01, Oct. 17, 2007
** Original: eth.c Version 1.00, Jan. 14, 1997
**
** Author: Giovanni Falzoni <gfalzoni@inwind.it>
**
** This file contains the ethernet device driver main task.
** It has to be integrated with the board specific drivers.
** It is a rewriting of Minix 2.0.0 ethernet driver (dp8390.c)
** to remove bord specific code. It should operate (I hope)
** with any board driver.
**
** The valid messages and their parameters are:
**
** m_type DL_PORT DL_PROC DL_COUNT DL_MODE DL_ADDR
** +------------+---------+---------+--------+-------+---------+
** | NOTIFY from HARDWARE, CLOCK, TTY, RS, PM, SYSTEM |
** +------------+---------+---------+--------+-------+---------+
** | HARD_STOP | | | | | |
** +------------+---------+---------+--------+-------+---------+
** | DL_WRITE | port nr | proc nr | count | mode | address | (3)
** +------------+---------+---------+--------+-------+---------+
** | DL_WRITEV | port nr | proc nr | count | mode | address | (4)
** +------------+---------+---------+--------+-------+---------+
** | DL_READ | port nr | proc nr | count | | address | (5)
** +------------+---------+---------+--------+-------+---------+
** | DL_READV | port nr | proc nr | count | | address | (6)
** +------------+---------+---------+--------+-------+---------+
** | DL_CONF | port nr | proc nr | | mode | address | (7)
** +------------+---------+---------+--------+-------+---------+
** | DL_STOP | port_nr | | | | | (8)
** +------------+---------+---------+--------+-------+---------+
** | DL_GETSTAT | port nr | proc nr | | | address | (9)
** +------------+---------+---------+--------+-------+---------+
**
** The messages sent are:
**
** m-type DL_PORT DL_PROC DL_COUNT DL_STAT DL_CLCK
** +------------+---------+---------+--------+---------+---------+
** |DL_TASK_REPL| port nr | proc nr |rd-count| err|stat| clock | (21)
** +------------+---------+---------+--------+---------+---------+
**
** m_type m3_i1 m3_i2 m3_ca1
** +------------+---------+---------+---------------+
** |DL_CONF_REPL| port nr |last port| ethernet addr | (20)
** +------------+---------+---------+---------------+
**
** $Id$
**
** 2007-10-17: modified by jfdsmit@gmail.com
** added a third argument to the reply() function because not
** every reply should be of DL_TASK_REPLY (one should be
** DL_STAT_REPLY)
*/
#include "drivers.h"
#include <minix/keymap.h>
#include <minix/endpoint.h>
#include <net/hton.h>
#include <net/gen/ether.h>
#include <net/gen/eth_io.h>
#include "dp.h"
/*
** Local data
*/
extern int errno;
static dpeth_t de_table[DE_PORT_NR];
static char *progname;
typedef struct dp_conf { /* Configuration description structure */
port_t dpc_port;
int dpc_irq;
phys_bytes dpc_mem;
char *dpc_envvar;
} dp_conf_t;
/* Device default configuration */
static dp_conf_t dp_conf[DE_PORT_NR] = {
/* I/O port, IRQ, Buff addr, Env. var, Buf. selector */
{ 0x300, 5, 0xC8000, "DPETH0", },
{ 0x280, 10, 0xCC000, "DPETH1", },
};
static char CopyErrMsg[] = "unable to read/write user data";
static char PortErrMsg[] = "illegal port";
static char RecvErrMsg[] = "receive failed";
static char SendErrMsg[] = "send failed";
static char SizeErrMsg[] = "illegal packet size";
static char TypeErrMsg[] = "illegal message type";
static char DevName[] = "eth#?";
static void do_getname(message *mp);
/*
** Name: void reply(dpeth_t *dep, int err, int m_type)
** Function: Fills a reply message and sends it.
*/
static void reply(dpeth_t * dep, int err, int m_type)
{
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 = m_type;
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;
getuptime(&reply.DL_CLCK);
DEBUG(printf("\t reply %d (%ld)\n", reply.m_type, reply.DL_STAT));
if ((status = send(dep->de_client, &reply)) == OK) {
dep->de_read_s = 0;
dep->de_flags &= NOT(DEF_ACK_SEND | DEF_ACK_RECV);
} else if (status != ELOCKED || err == OK)
panic(dep->de_name, SendErrMsg, status);
return;
}
/*
** Name: void dp_confaddr(dpeth_t *dep)
** Function: Checks environment for a User defined ethernet address.
*/
static void dp_confaddr(dpeth_t * dep)
{
static char ea_fmt[] = "x:x:x:x:x:x";
char ea_key[16];
int ix;
long val;
strcpy(ea_key, dp_conf[dep - de_table].dpc_envvar);
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)
/* It's all or nothing, force a panic */
env_parse(ea_key, "?", 0, &val, 0L, 0L);
return;
}
/*
** Name: void update_conf(dpeth_t *dep, dp_conf_t *dcp)
** Function: Gets the default settings from 'dp_conf' table and
** modifies them from the environment.
*/
static void update_conf(dpeth_t * dep, dp_conf_t * dcp)
{
static char dpc_fmt[] = "x:d:x";
long val;
dep->de_mode = DEM_SINK;
val = dcp->dpc_port; /* Get I/O port address */
switch (env_parse(dcp->dpc_envvar, dpc_fmt, 0, &val, 0x000L, 0x3FFL)) {
case EP_OFF: dep->de_mode = DEM_DISABLED; break;
case EP_ON:
case EP_SET: dep->de_mode = DEM_ENABLED; break;
}
dep->de_base_port = val;
val = dcp->dpc_irq | DEI_DEFAULT; /* Get Interrupt line (IRQ) */
env_parse(dcp->dpc_envvar, dpc_fmt, 1, &val, 0L, (long) NR_IRQ_VECTORS - 1);
dep->de_irq = val;
val = dcp->dpc_mem; /* Get shared memory address */
env_parse(dcp->dpc_envvar, dpc_fmt, 2, &val, 0L, LONG_MAX);
dep->de_linmem = val;
return;
}
/*
** Name: void do_dump(message *mp)
** Function: Displays statistics on screen (SFx key from console)
*/
static void do_dump(message *mp)
{
dpeth_t *dep;
int port;
printf("\n\n");
for (port = 0, dep = de_table; port < DE_PORT_NR; port += 1, dep += 1) {
if (dep->de_mode == DEM_DISABLED) continue;
printf("%s statistics:\t\t", dep->de_name);
/* Network interface status */
printf("Status: 0x%04x (%d)\n\n", dep->de_flags, dep->de_int_pending);
(*dep->de_dumpstatsf) (dep);
/* Transmitted/received bytes */
printf("Tx bytes:%10ld\t", dep->bytes_Tx);
printf("Rx bytes:%10ld\n", dep->bytes_Rx);
/* Transmitted/received packets */
printf("Tx OK: %8ld\t", dep->de_stat.ets_packetT);
printf("Rx OK: %8ld\n", dep->de_stat.ets_packetR);
/* Transmit/receive errors */
printf("Tx Err: %8ld\t", dep->de_stat.ets_sendErr);
printf("Rx Err: %8ld\n", dep->de_stat.ets_recvErr);
/* Transmit unnerruns/receive overrruns */
printf("Tx Und: %8ld\t", dep->de_stat.ets_fifoUnder);
printf("Rx Ovr: %8ld\n", dep->de_stat.ets_fifoOver);
/* Transmit collisions/receive CRC errors */
printf("Tx Coll: %8ld\t", dep->de_stat.ets_collision);
printf("Rx CRC: %8ld\n", dep->de_stat.ets_CRCerr);
}
return;
}
/*
** Name: void get_userdata_s(int user_proc, vir_bytes user_addr, int count, void *loc_addr)
** Function: Copies data from user area.
*/
static void 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);
if ((rc = sys_safecopyfrom(user_proc, grant, 0, (vir_bytes)loc_addr, len, D)) != OK)
panic(DevName, CopyErrMsg, rc);
return;
}
/*
** Name: void do_first_init(dpeth_t *dep, dp_conf_t *dcp);
** Function: Init action to setup task
*/
static void do_first_init(dpeth_t *dep, dp_conf_t *dcp)
{
if (dep->de_linmem != 0) {
dep->de_memsegm = BIOS_SEG;
/* phys2seg(&dep->de_memsegm, &dep->de_memoffs, dep->de_linmem); */
} else
dep->de_linmem = 0xFFFF0000;
/* Make sure statisics are cleared */
memset((void *) &(dep->de_stat), 0, sizeof(eth_stat_t));
/* Device specific initialization */
(*dep->de_initf) (dep);
/* 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 /*IRQ_REENABLE*/, &dep->de_hook);
dep->de_int_pending = FALSE;
sys_irqenable(&dep->de_hook);
return;
}
/*
** Name: void do_init(message *mp)
** Function: Checks for hardware presence.
** Provides initialization of hardware and data structures
*/
static void do_init(message * mp)
{
int port;
dpeth_t *dep;
dp_conf_t *dcp;
message reply_mess;
port = mp->DL_PORT;
if (port >= 0 && port < DE_PORT_NR) {
dep = &de_table[port];
dcp = &dp_conf[port];
strcpy(dep->de_name, DevName);
dep->de_name[4] = '0' + port;
if (dep->de_mode == DEM_DISABLED) {
update_conf(dep, dcp); /* First time thru */
if (dep->de_mode == DEM_ENABLED &&
!el1_probe(dep) && /* Probe for 3c501 */
!wdeth_probe(dep) && /* Probe for WD80x3 */
!ne_probe(dep) && /* Probe for NEx000 */
!el2_probe(dep) && /* Probe for 3c503 */
!el3_probe(dep)) { /* Probe for 3c509 */
printf("%s: warning no ethernet card found at 0x%04X\n",
dep->de_name, dep->de_base_port);
dep->de_mode = DEM_DISABLED;
}
}
/* 'de_mode' may change if probe routines fail, test again */
switch (dep->de_mode) {
case DEM_DISABLED:
/* Device is configured OFF or hardware probe failed */
port = ENXIO;
break;
case DEM_ENABLED:
/* Device is present and probed */
if (dep->de_flags == DEF_EMPTY) {
/* These actions only the first time */
do_first_init(dep, dcp);
dep->de_flags |= DEF_ENABLED;
}
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_flagsf) (dep);
dep->de_client = mp->m_source;
break;
case DEM_SINK:
/* Device not present (sink mode) */
memset(dep->de_address.ea_addr, 0, sizeof(ether_addr_t));
dp_confaddr(dep); /* Station address from env. */
break;
default: break;
}
*(ether_addr_t *) reply_mess.m3_ca1 = dep->de_address;
} 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;
DEBUG(printf("\t reply %d\n", reply_mess.m_type));
if (send(mp->m_source, &reply_mess) != OK) /* Can't send */
panic(dep->de_name, SendErrMsg, mp->m_source);
return;
}
/*
** Name: void dp_next_iovec(iovec_dat_t *iovp)
** Function: Retrieves data from next iovec element.
*/
PUBLIC void dp_next_iovec(iovec_dat_s_t * iovp)
{
iovp->iod_iovec_s -= IOVEC_NR;
iovp->iod_iovec_offset += IOVEC_NR * sizeof(iovec_t);
get_userdata_s(iovp->iod_proc_nr, iovp->iod_grant, iovp->iod_iovec_offset,
iovp->iod_iovec_s, iovp->iod_iovec);
return;
}
/*
** Name: int calc_iovec_size(iovec_dat_t *iovp)
** Function: Compute the size of a request.
*/
static int calc_iovec_size(iovec_dat_s_t * iovp)
{
int size, ix;
size = ix = 0;
do {
size += iovp->iod_iovec[ix].iov_size;
if (++ix >= IOVEC_NR) {
dp_next_iovec(iovp);
ix = 0;
}
/* Till all vectors added */
} while (ix < iovp->iod_iovec_s);
return size;
}
/*
** Name: void do_vwrite_s(message *mp, int vectored)
** Function:
*/
static void do_vwrite_s(message * mp)
{
int port, size;
dpeth_t *dep;
port = mp->DL_PORT;
if (port < 0 || port >= DE_PORT_NR) /* Check for illegal port number */
panic(dep->de_name, PortErrMsg, port);
dep = &de_table[port];
dep->de_client = mp->DL_PROC;
if (dep->de_mode == DEM_ENABLED) {
if (dep->de_flags & DEF_SENDING) /* Is sending in progress? */
panic(dep->de_name, "send already in progress ", NO_NUM);
dep->de_write_iovec.iod_proc_nr = mp->DL_PROC;
get_userdata_s(mp->DL_PROC, mp->DL_GRANT, 0,
mp->DL_COUNT, dep->de_write_iovec.iod_iovec);
dep->de_write_iovec.iod_iovec_s = mp->DL_COUNT;
dep->de_write_iovec.iod_grant = (vir_bytes) mp->DL_GRANT;
dep->de_write_iovec.iod_iovec_offset = 0;
size = calc_iovec_size(&dep->de_write_iovec);
if (size < ETH_MIN_PACK_SIZE || size > ETH_MAX_PACK_SIZE)
panic(dep->de_name, SizeErrMsg, size);
dep->de_flags |= DEF_SENDING;
(*dep->de_sendf) (dep, FALSE, size);
} else if (dep->de_mode == DEM_SINK)
dep->de_flags |= DEF_ACK_SEND;
reply(dep, OK, DL_TASK_REPLY);
return;
}
/*
** Name: void do_vread_s(message *mp, int vectored)
** Function:
*/
static void do_vread_s(message * mp)
{
int port, size;
dpeth_t *dep;
port = mp->DL_PORT;
if (port < 0 || port >= DE_PORT_NR) /* Check for illegal port number */
panic(dep->de_name, PortErrMsg, port);
dep = &de_table[port];
dep->de_client = mp->DL_PROC;
if (dep->de_mode == DEM_ENABLED) {
if (dep->de_flags & DEF_READING) /* Reading in progress */
panic(dep->de_name, "read already in progress", NO_NUM);
dep->de_read_iovec.iod_proc_nr = mp->DL_PROC;
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 = calc_iovec_size(&dep->de_read_iovec);
if (size < ETH_MAX_PACK_SIZE) panic(dep->de_name, SizeErrMsg, size);
dep->de_flags |= DEF_READING;
(*dep->de_recvf) (dep, FALSE, size);
#if 0
if ((dep->de_flags & (DEF_READING | DEF_STOPPED)) == (DEF_READING | DEF_STOPPED))
/* The chip is stopped, and all arrived packets delivered */
(*dep->de_resetf) (dep);
dep->de_flags &= NOT(DEF_STOPPED);
#endif
}
reply(dep, OK, DL_TASK_REPLY);
return;
}
/*
** Name: void do_getstat_s(message *mp)
** Function: Reports device statistics.
*/
static void do_getstat_s(message * mp)
{
int port, rc;
dpeth_t *dep;
port = mp->DL_PORT;
if (port < 0 || port >= DE_PORT_NR) /* Check for illegal port number */
panic(dep->de_name, PortErrMsg, port);
dep = &de_table[port];
dep->de_client = mp->DL_PROC;
if (dep->de_mode == DEM_ENABLED) (*dep->de_getstatsf) (dep);
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(DevName, CopyErrMsg, rc);
reply(dep, OK, DL_STAT_REPLY);
return;
}
static void do_getname(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("dpeth", "do_getname: send failed: %d\n", r);
}
/*
** Name: void do_stop(message *mp)
** Function: Stops network interface.
*/
static void do_stop(message * mp)
{
int port;
dpeth_t *dep;
port = mp->DL_PORT;
if (port < 0 || port >= DE_PORT_NR) /* Check for illegal port number */
panic(dep->de_name, PortErrMsg, port);
dep = &de_table[port];
if (dep->de_mode == DEM_ENABLED && (dep->de_flags & DEF_ENABLED)) {
/* Stop device */
(dep->de_stopf) (dep);
dep->de_flags = DEF_EMPTY;
dep->de_mode = DEM_DISABLED;
}
return;
}
static void do_watchdog(void *message)
{
DEBUG(printf("\t no reply"));
return;
}
PRIVATE void handle_system_signal(message *m)
{
sigset_t set;
int port;
if (getsigset(&set) != 0) return;
if (sigismember(&set, SIGTERM)) { /* Shut down */
for (port = 0; port < DE_PORT_NR; port += 1) {
if (de_table[port].de_mode == DEM_ENABLED) {
m->m_type = DL_STOP;
m->DL_PORT = port;
do_stop(m);
}
}
}
}
PRIVATE void handle_hw_intr(void)
{
dpeth_t *dep;
for (dep = de_table; dep < &de_table[DE_PORT_NR]; dep += 1) {
/* If device is enabled and interrupt pending */
if (dep->de_mode == DEM_ENABLED) {
dep->de_int_pending = TRUE;
(*dep->de_interruptf) (dep);
if (dep->de_flags & (DEF_ACK_SEND | DEF_ACK_RECV))
reply(dep, !OK, DL_TASK_REPLY);
dep->de_int_pending = FALSE;
sys_irqenable(&dep->de_hook);
}
}
}
/*
** Name: int dpeth_task(void)
** Function: Main entry for dp task
*/
PUBLIC int main(int argc, char **argv)
{
message m;
dpeth_t *dep;
int rc, fkeys, sfkeys, tasknr;
(progname=strrchr(argv[0],'/')) ? progname++ : (progname=argv[0]);
env_setargs(argc, argv);
/* Request function key for debug dumps */
fkeys = sfkeys = 0; bit_set(sfkeys, 8);
if ((fkey_map(&fkeys, &sfkeys)) != OK)
printf("%s: couldn't program Shift+F8 key (%d)\n", DevName, errno);
#ifdef ETH_IGN_PROTO
{
static u16_t eth_ign_proto = 0;
long val;
val = 0xFFFF;
env_parse("ETH_IGN_PROTO", "x", 0, &val, 0x0000L, 0xFFFFL);
eth_ign_proto = htons((u16_t) val);
}
#endif
/* Try to notify inet that we are present (again) */
rc = _pm_findproc("inet", &tasknr);
if (rc == OK)
notify(tasknr);
while (TRUE) {
if ((rc = receive(ANY, &m)) != OK) panic(dep->de_name, RecvErrMsg, rc);
DEBUG(printf("eth: got message %d, ", m.m_type));
if (is_notify(m.m_type)) {
switch(_ENDPOINT_P(m.m_source)) {
case CLOCK:
/* to be defined */
do_watchdog(&m);
break;
case RS_PROC_NR:
/* Status request from RS */
notify(m.m_source);
break;
case HARDWARE:
/* Interrupt from device */
handle_hw_intr();
break;
case TTY_PROC_NR:
/* Function key pressed */
do_dump(&m);
break;
case PM_PROC_NR:
handle_system_signal(&m);
break;
default:
/* Invalid message type */
panic(DevName, TypeErrMsg, m.m_type);
break;
}
/* message processed, get another one */
continue;
}
switch (m.m_type) {
case DL_WRITEV_S: /* Write message to device */
do_vwrite_s(&m);
break;
case DL_READV_S: /* Read message from device */
do_vread_s(&m);
break;
case DL_CONF: /* Initialize device */
do_init(&m);
break;
case DL_GETSTAT_S: /* Get device statistics */
do_getstat_s(&m);
break;
case DL_GETNAME:
do_getname(&m);
break;
case DL_STOP: /* Stop device */
do_stop(&m);
break;
default: /* Invalid message type */
panic(DevName, TypeErrMsg, m.m_type);
break;
}
}
return OK; /* Never reached, but keeps compiler happy */
}
/** dp.c **/