📄 dp.c
字号:
/*** File: 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** +------------+---------+---------+--------+-------+---------+** | HARD_INT | | | | | | ** +------------+---------+---------+--------+-------+---------+** | SYN_ALARM | | | | | | ** +------------+---------+---------+--------+-------+---------+** | HARD_STOP | | | | | | ** +------------+---------+---------+--------+-------+---------+** | FKEY_PRESSED | | | | | (99)** +------------+---------+---------+--------+-------+---------+** | 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_INIT | 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_INIT_REPL| port nr |last port| ethernet addr | (20)** +------------+---------+---------+---------------+**** $Id: dp.c,v 1.11 2005/10/21 17:09:08 philip Exp $*/#include "drivers.h"#include <minix/keymap.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 const char CopyErrMsg[] = "unable to read/write user data";static const char PortErrMsg[] = "illegal port";static const char RecvErrMsg[] = "receive failed";static const char SendErrMsg[] = "send failed";static const char SizeErrMsg[] = "illegal packet size";static const char TypeErrMsg[] = "illegal message type";static const char DevName[] = "eth#?";static void do_getname(message *mp);/*** Name: void reply(dpeth_t *dep, int err)** Function: Fills a DL_TASK_REPLY reply message and sends it.*/static void reply(dpeth_t * dep, int err){ 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; 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(int user_proc, vir_bytes user_addr, int count, void *loc_addr)** Function: Copies data from user area.*/static void get_userdata(int user_proc, vir_bytes user_addr, int count, void *loc_addr){ int rc; vir_bytes len; len = (count > IOVEC_NR ? IOVEC_NR : count) * sizeof(iovec_t); if ((rc = sys_datacopy(user_proc, user_addr, SELF, (vir_bytes)loc_addr, len)) != 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) */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -