dec21140A: use new libnetdriver
Change-Id: I54be3b770e4d1fd320200c30e9e9073a7c1b405b
This commit is contained in:
parent
b80fc5be89
commit
29018b4ecd
@ -12,288 +12,105 @@
|
|||||||
#include <minix/drivers.h>
|
#include <minix/drivers.h>
|
||||||
#include <minix/netdriver.h>
|
#include <minix/netdriver.h>
|
||||||
|
|
||||||
#include <assert.h>
|
|
||||||
#include <machine/pci.h>
|
#include <machine/pci.h>
|
||||||
#include <minix/syslib.h>
|
#include <assert.h>
|
||||||
#include <minix/endpoint.h>
|
|
||||||
#include <minix/com.h>
|
|
||||||
#include <minix/sef.h>
|
|
||||||
#include <minix/ds.h>
|
|
||||||
#include <net/gen/ether.h>
|
|
||||||
#include <net/gen/eth_io.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
#include "dec21140A.h"
|
#include "dec21140A.h"
|
||||||
|
|
||||||
|
|
||||||
static u32_t io_inl(u16_t);
|
static u32_t io_inl(u16_t);
|
||||||
static void io_outl(u16_t, u32_t);
|
static void io_outl(u16_t, u32_t);
|
||||||
static void do_conf(const message *);
|
|
||||||
static void do_get_stat_s(message *);
|
|
||||||
static void do_interrupt(const dpeth_t *);
|
|
||||||
static void do_reply(dpeth_t *);
|
|
||||||
static void do_vread_s(const message *, int);
|
|
||||||
static void do_watchdog(void *);
|
|
||||||
|
|
||||||
static void de_update_conf(dpeth_t *);
|
static int do_init(unsigned int, ether_addr_t *);
|
||||||
static int de_probe(dpeth_t *, int skip);
|
static void do_stop(void);
|
||||||
static void de_conf_addr(dpeth_t *);
|
static int do_send(struct netdriver_data *, size_t);
|
||||||
static void de_first_init(dpeth_t *);
|
static ssize_t do_recv(struct netdriver_data *, size_t);
|
||||||
|
static void do_stat(eth_stat_t *);
|
||||||
|
static void do_intr(unsigned int);
|
||||||
|
|
||||||
|
static int de_probe(dpeth_t *, unsigned int skip);
|
||||||
|
static void de_conf_addr(dpeth_t *, ether_addr_t *);
|
||||||
|
static void de_init_buf(dpeth_t *);
|
||||||
static void de_reset(const dpeth_t *);
|
static void de_reset(const dpeth_t *);
|
||||||
static void de_hw_conf(const dpeth_t *);
|
static void de_hw_conf(const dpeth_t *);
|
||||||
static void de_start(const dpeth_t *);
|
static void de_start(const dpeth_t *);
|
||||||
static void de_setup_frame(const dpeth_t *);
|
static void de_setup_frame(const dpeth_t *, const ether_addr_t *);
|
||||||
static u16_t de_read_rom(const dpeth_t *, u8_t, u8_t);
|
static u16_t de_read_rom(const dpeth_t *, u8_t, u8_t);
|
||||||
static int de_calc_iov_size(iovec_dat_s_t *);
|
|
||||||
static void de_next_iov(iovec_dat_s_t *);
|
|
||||||
static void do_vwrite_s(const message *, int);
|
|
||||||
static 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_SendErrMsg[] = "send failed";
|
|
||||||
static char str_SizeErrMsg[] = "illegal packet size";
|
|
||||||
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#?";
|
|
||||||
|
|
||||||
static dpeth_t de_state;
|
static dpeth_t de_state;
|
||||||
static int de_instance;
|
static int de_instance;
|
||||||
|
|
||||||
/* SEF functions and variables. */
|
static const struct netdriver de_table = {
|
||||||
static void sef_local_startup(void);
|
.ndr_init = do_init,
|
||||||
static int sef_cb_init_fresh(int type, sef_init_info_t *info);
|
.ndr_stop = do_stop,
|
||||||
|
.ndr_recv = do_recv,
|
||||||
|
.ndr_send = do_send,
|
||||||
|
.ndr_stat = do_stat,
|
||||||
|
.ndr_intr = do_intr
|
||||||
|
};
|
||||||
|
|
||||||
/*===========================================================================*
|
|
||||||
* main *
|
|
||||||
*===========================================================================*/
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
dpeth_t *dep;
|
|
||||||
message m;
|
|
||||||
int ipc_status;
|
|
||||||
int r;
|
|
||||||
|
|
||||||
/* SEF local startup. */
|
|
||||||
env_setargs(argc, argv);
|
env_setargs(argc, argv);
|
||||||
sef_local_startup();
|
|
||||||
|
|
||||||
while (TRUE)
|
netdriver_task(&de_table);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void de_init_hw(dpeth_t *dep, ether_addr_t *addr)
|
||||||
{
|
{
|
||||||
if ((r= netdriver_receive(ANY, &m, &ipc_status)) != OK)
|
de_reset(dep);
|
||||||
panic("netdriver_receive failed: %d", r);
|
de_conf_addr(dep, addr);
|
||||||
|
de_init_buf(dep);
|
||||||
|
|
||||||
if(is_ipc_notify(ipc_status)) {
|
/* Set the interrupt handler policy. Request interrupts not to be reenabled
|
||||||
switch(_ENDPOINT_P(m.m_source)) {
|
* automatically. Return the IRQ line number when an interrupt occurs.
|
||||||
case CLOCK:
|
*/
|
||||||
do_watchdog(&m);
|
dep->de_hook = dep->de_irq;
|
||||||
break;
|
sys_irqsetpolicy(dep->de_irq, 0, &dep->de_hook);
|
||||||
|
|
||||||
case HARDWARE:
|
|
||||||
dep = &de_state;
|
|
||||||
if (dep->de_mode == DEM_ENABLED) {
|
|
||||||
do_interrupt(dep);
|
|
||||||
if (dep->de_flags & (DEF_ACK_SEND | DEF_ACK_RECV))
|
|
||||||
do_reply(dep);
|
|
||||||
sys_irqenable(&dep->de_hook);
|
sys_irqenable(&dep->de_hook);
|
||||||
}
|
|
||||||
break;
|
de_reset(dep);
|
||||||
default:
|
de_hw_conf(dep);
|
||||||
printf("ignoring notify from %d\n", m.m_source);
|
de_setup_frame(dep, addr);
|
||||||
break;
|
de_start(dep);
|
||||||
}
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (m.m_type)
|
static int do_init(unsigned int instance, ether_addr_t *addr)
|
||||||
{
|
|
||||||
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;
|
|
||||||
|
|
||||||
default:
|
|
||||||
printf("message 0x%x; %d from %d\n",
|
|
||||||
m.m_type, m.m_type-DL_RQ_BASE, m.m_source);
|
|
||||||
panic("illegal message: %d", m.m_type);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*===========================================================================*
|
|
||||||
* sef_local_startup *
|
|
||||||
*===========================================================================*/
|
|
||||||
static void sef_local_startup()
|
|
||||||
{
|
|
||||||
/* Register init callbacks. */
|
|
||||||
sef_setcb_init_fresh(sef_cb_init_fresh);
|
|
||||||
sef_setcb_init_lu(sef_cb_init_fresh);
|
|
||||||
sef_setcb_init_restart(sef_cb_init_fresh);
|
|
||||||
|
|
||||||
/* Register live update callbacks. */
|
|
||||||
sef_setcb_lu_prepare(sef_cb_lu_prepare_always_ready);
|
|
||||||
sef_setcb_lu_state_isvalid(sef_cb_lu_state_isvalid_workfree);
|
|
||||||
|
|
||||||
/* Register signal callbacks. */
|
|
||||||
sef_setcb_signal_handler(sef_cb_signal_handler_term);
|
|
||||||
|
|
||||||
/* Let SEF perform startup. */
|
|
||||||
sef_startup();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*===========================================================================*
|
|
||||||
* sef_cb_init_fresh *
|
|
||||||
*===========================================================================*/
|
|
||||||
static int sef_cb_init_fresh(int type, sef_init_info_t *UNUSED(info))
|
|
||||||
{
|
{
|
||||||
/* Initialize the DEC 21140A driver. */
|
/* Initialize the DEC 21140A driver. */
|
||||||
int fkeys, sfkeys;
|
dpeth_t *dep;
|
||||||
long v;
|
|
||||||
|
|
||||||
v = 0;
|
dep = &de_state;
|
||||||
(void) env_parse("instance", "d", 0, &v, 0, 255);
|
memset(dep, 0, sizeof(*dep));
|
||||||
de_instance = (int) v;
|
|
||||||
|
|
||||||
/* Request function key for debug dumps */
|
strlcpy(dep->de_name, "dec21140A:?", sizeof(dep->de_name));
|
||||||
fkeys = sfkeys = 0;
|
dep->de_name[strlen(dep->de_name)-1] = '0' + instance;
|
||||||
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);
|
|
||||||
|
|
||||||
/* Announce we are up! */
|
de_instance = instance;
|
||||||
netdriver_announce();
|
|
||||||
|
if (!de_probe(dep, instance))
|
||||||
|
return ENXIO;
|
||||||
|
|
||||||
|
de_init_hw(dep, addr);
|
||||||
|
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void do_get_stat_s(message * mp)
|
static void do_stat(eth_stat_t *stat)
|
||||||
{
|
{
|
||||||
int rc;
|
memcpy(stat, &de_state.de_stat, sizeof(*stat));
|
||||||
dpeth_t *dep;
|
|
||||||
|
|
||||||
dep = &de_state;
|
|
||||||
|
|
||||||
if ((rc = sys_safecopyto(mp->m_source, mp->m_net_netdrv_dl_getstat_s.grant,
|
|
||||||
0, (vir_bytes)&dep->de_stat, sizeof(dep->de_stat))) != OK)
|
|
||||||
panic("%s %d", str_CopyErrMsg, rc);
|
|
||||||
|
|
||||||
mp->m_type = DL_STAT_REPLY;
|
|
||||||
rc = ipc_send(mp->m_source, mp);
|
|
||||||
if( rc != OK )
|
|
||||||
panic("%s %d", str_StatErrMsg, rc);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void do_conf(const message * mp)
|
static int de_probe(dpeth_t *dep, unsigned int skip)
|
||||||
{
|
{
|
||||||
int r;
|
int r, devind;
|
||||||
dpeth_t *dep;
|
u16_t vid, did;
|
||||||
message reply_mess;
|
|
||||||
|
|
||||||
dep = &de_state;
|
|
||||||
|
|
||||||
strncpy(dep->de_name, str_DevName, strlen(str_DevName));
|
|
||||||
dep->de_name[strlen(dep->de_name)-1] = '0' + de_instance;
|
|
||||||
|
|
||||||
if (dep->de_mode == DEM_DISABLED) {
|
|
||||||
de_update_conf(dep);
|
|
||||||
pci_init();
|
|
||||||
if (dep->de_mode == DEM_ENABLED && !de_probe(dep, de_instance)) {
|
|
||||||
printf("%s: warning no ethernet card found at 0x%04X\n",
|
|
||||||
dep->de_name, dep->de_base_port);
|
|
||||||
dep->de_mode = DEM_DISABLED;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
r = OK;
|
|
||||||
|
|
||||||
/* 'de_mode' may change if probe routines fail, test again */
|
|
||||||
switch (dep->de_mode) {
|
|
||||||
|
|
||||||
case DEM_DISABLED:
|
|
||||||
r = 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->m_net_netdrv_dl_conf.mode & DL_PROMISC_REQ)
|
|
||||||
dep->de_flags |= DEF_PROMISC | DEF_MULTI | DEF_BROAD;
|
|
||||||
if (mp->m_net_netdrv_dl_conf.mode & DL_MULTI_REQ)
|
|
||||||
dep->de_flags |= DEF_MULTI;
|
|
||||||
if (mp->m_net_netdrv_dl_conf.mode & DL_BROAD_REQ)
|
|
||||||
dep->de_flags |= DEF_BROAD;
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
reply_mess.m_type = DL_CONF_REPLY;
|
|
||||||
reply_mess.m_netdrv_net_dl_conf.stat = r;
|
|
||||||
if(r == OK){
|
|
||||||
memcpy(reply_mess.m_netdrv_net_dl_conf.hw_addr, dep->de_address.ea_addr,
|
|
||||||
sizeof(reply_mess.m_netdrv_net_dl_conf.hw_addr));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ipc_send(mp->m_source, &reply_mess) != OK)
|
|
||||||
panic("%s %d", str_SendErrMsg, mp->m_source);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void do_reply(dpeth_t * dep)
|
|
||||||
{
|
|
||||||
message reply;
|
|
||||||
int r, flags = DL_NOFLAGS;
|
|
||||||
|
|
||||||
if (dep->de_flags & DEF_ACK_SEND) flags |= DL_PACK_SEND;
|
|
||||||
if (dep->de_flags & DEF_ACK_RECV) flags |= DL_PACK_RECV;
|
|
||||||
|
|
||||||
reply.m_type = DL_TASK_REPLY;
|
|
||||||
reply.m_netdrv_net_dl_task.flags = flags;
|
|
||||||
reply.m_netdrv_net_dl_task.count = dep->de_read_s;
|
|
||||||
|
|
||||||
r = ipc_send(dep->de_client, &reply);
|
|
||||||
|
|
||||||
if(r < 0)
|
|
||||||
panic("%s %d", str_SendErrMsg, r);
|
|
||||||
|
|
||||||
dep->de_read_s = 0;
|
|
||||||
dep->de_flags &= NOT(DEF_ACK_SEND | DEF_ACK_RECV);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void do_watchdog(void *UNUSED(message))
|
|
||||||
{
|
|
||||||
/* nothing here yet */
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int de_probe(dpeth_t *dep, int skip)
|
|
||||||
{
|
|
||||||
int i, r, devind;
|
|
||||||
u16_t vid, did, temp16;
|
|
||||||
|
|
||||||
DEBUG(printf("PROBING..."));
|
DEBUG(printf("PROBING..."));
|
||||||
|
|
||||||
|
pci_init();
|
||||||
|
|
||||||
r= pci_first_dev(&devind, &vid, &did);
|
r= pci_first_dev(&devind, &vid, &did);
|
||||||
if (r == 0)
|
if (r == 0)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
@ -321,33 +138,15 @@ static int de_probe(dpeth_t *dep, int skip)
|
|||||||
|
|
||||||
/* device validation. We support only the DEC21140A */
|
/* device validation. We support only the DEC21140A */
|
||||||
if(dep->de_type != DEC_21140A){
|
if(dep->de_type != DEC_21140A){
|
||||||
dep->de_type = DE_TYPE_UNKNOWN;
|
printf("%s: unsupported card type %x\n", dep->de_name, dep->de_type);
|
||||||
printf("%s: unsupported device\n", str_DevName);
|
|
||||||
return FALSE;
|
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;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static u16_t de_read_rom(const dpeth_t *dep, u8_t addr, u8_t nbAddrBits){
|
static u16_t de_read_rom(const dpeth_t *dep, u8_t addr, u8_t nbAddrBits)
|
||||||
|
{
|
||||||
u16_t retVal = 0;
|
u16_t retVal = 0;
|
||||||
int i;
|
int i;
|
||||||
u32_t csr = 0;
|
u32_t csr = 0;
|
||||||
@ -356,7 +155,11 @@ static u16_t de_read_rom(const dpeth_t *dep, u8_t addr, u8_t nbAddrBits){
|
|||||||
more readable, the following macro is also just
|
more readable, the following macro is also just
|
||||||
to clear up the code a little.*/
|
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)
|
#define EMIT \
|
||||||
|
do { \
|
||||||
|
io_outl(CSR_ADDR(dep, CSR9), csr | csr2); \
|
||||||
|
io_outl(CSR_ADDR(dep, CSR1), 0); \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
/* init */
|
/* init */
|
||||||
csr = 0; EMIT;
|
csr = 0; EMIT;
|
||||||
@ -404,49 +207,21 @@ static u16_t de_read_rom(const dpeth_t *dep, u8_t addr, u8_t nbAddrBits){
|
|||||||
return retVal;
|
return retVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void de_update_conf(dpeth_t * dep)
|
static ssize_t do_recv(struct netdriver_data *data, size_t max)
|
||||||
{
|
{
|
||||||
static char dpc_fmt[] = "x:d:x";
|
|
||||||
char ec_key[16];
|
|
||||||
long val;
|
|
||||||
|
|
||||||
strlcpy(ec_key, "DEETH0", sizeof(ec_key));
|
|
||||||
ec_key[5] += de_instance;
|
|
||||||
|
|
||||||
dep->de_mode = DEM_ENABLED;
|
|
||||||
switch (env_parse(ec_key, 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void do_vread_s(const message * mp, int from_int)
|
|
||||||
{
|
|
||||||
u8_t *buffer;
|
|
||||||
u32_t size;
|
u32_t size;
|
||||||
int r, ix = 0;
|
dpeth_t *dep;
|
||||||
vir_bytes bytes;
|
de_loc_descr_t *descr;
|
||||||
dpeth_t *dep = NULL;
|
|
||||||
de_loc_descr_t *descr = NULL;
|
|
||||||
iovec_dat_s_t *iovp = NULL;
|
|
||||||
|
|
||||||
dep = &de_state;
|
dep = &de_state;
|
||||||
|
|
||||||
dep->de_client = mp->m_source;
|
|
||||||
|
|
||||||
if (dep->de_mode == DEM_ENABLED) {
|
|
||||||
|
|
||||||
descr = &dep->descr[DESCR_RECV][dep->cur_descr[DESCR_RECV]];
|
descr = &dep->descr[DESCR_RECV][dep->cur_descr[DESCR_RECV]];
|
||||||
|
|
||||||
/* check if packet is in the current descr and only there */
|
/* check if packet is in the current descr and only there */
|
||||||
if( !( !(descr->descr->des[DES0] & DES0_OWN) &&
|
if ((descr->descr->des[DES0] & DES0_OWN) ||
|
||||||
(descr->descr->des[DES0] & DES0_FS) &&
|
!(descr->descr->des[DES0] & DES0_FS) ||
|
||||||
(descr->descr->des[DES0] & DES0_LS) ))
|
!(descr->descr->des[DES0] & DES0_LS))
|
||||||
goto suspend;
|
return SUSPEND;
|
||||||
|
|
||||||
|
|
||||||
/*TODO: multi-descr msgs...*/
|
/*TODO: multi-descr msgs...*/
|
||||||
/* We only support packets contained in a single descriptor.
|
/* We only support packets contained in a single descriptor.
|
||||||
@ -454,9 +229,6 @@ static void do_vread_s(const message * mp, int from_int)
|
|||||||
ETH_MAX_PACK_SIZE will result in multi-descriptor
|
ETH_MAX_PACK_SIZE will result in multi-descriptor
|
||||||
packets that we won't be able to handle
|
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
|
/* Check for abnormal messages. We assert here
|
||||||
because this driver is for a virtualized
|
because this driver is for a virtualized
|
||||||
@ -465,65 +237,22 @@ static void do_vread_s(const message * mp, int from_int)
|
|||||||
assert(!(descr->descr->des[DES0]&DES0_ES));
|
assert(!(descr->descr->des[DES0]&DES0_ES));
|
||||||
assert(!(descr->descr->des[DES0]&DES0_RE));
|
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->m_source;
|
|
||||||
de_get_userdata_s(mp->m_source, mp->m_net_netdrv_dl_readv_s.grant, 0,
|
|
||||||
mp->m_net_netdrv_dl_readv_s.count,
|
|
||||||
dep->de_read_iovec.iod_iovec);
|
|
||||||
dep->de_read_iovec.iod_iovec_s = mp->m_net_netdrv_dl_readv_s.count;
|
|
||||||
dep->de_read_iovec.iod_grant = mp->m_net_netdrv_dl_readv_s.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("%s %d", str_SizeErrMsg, size);
|
|
||||||
|
|
||||||
/* Copy buffer to user area and clear ownage */
|
/* Copy buffer to user area and clear ownage */
|
||||||
size = (descr->descr->des[DES0]&DES0_FL)>>DES0_FL_SHIFT;
|
size = (descr->descr->des[DES0]&DES0_FL)>>DES0_FL_SHIFT;
|
||||||
|
|
||||||
/*TODO: Complain to MS */
|
/* HACK: VPC2007 sends short-sized packets, pad to minimum ethernet length */
|
||||||
/*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){
|
if(size<60){
|
||||||
memset(&descr->buf1[size], 0, 60-size);
|
memset(&descr->buf1[size], 0, 60-size);
|
||||||
size=60;
|
size=60;
|
||||||
}
|
}
|
||||||
/* End ugly hack */
|
|
||||||
|
|
||||||
iovp = &dep->de_read_iovec;
|
/* Truncate large packets */
|
||||||
buffer = descr->buf1;
|
if (size > max)
|
||||||
dep->bytes_rx += size;
|
size = max;
|
||||||
|
|
||||||
|
netdriver_copyout(data, 0, descr->buf1, size);
|
||||||
|
|
||||||
dep->de_stat.ets_packetR++;
|
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);
|
|
||||||
if (r != OK)
|
|
||||||
panic("%s %d", 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;
|
descr->descr->des[DES0]=DES0_OWN;
|
||||||
dep->cur_descr[DESCR_RECV]++;
|
dep->cur_descr[DESCR_RECV]++;
|
||||||
@ -532,52 +261,33 @@ static void do_vread_s(const message * mp, int from_int)
|
|||||||
|
|
||||||
DEBUG(printf("Read returned size = %d\n", size));
|
DEBUG(printf("Read returned size = %d\n", size));
|
||||||
|
|
||||||
/* Reply information */
|
return size;
|
||||||
dep->de_flags |= DEF_ACK_RECV;
|
|
||||||
dep->de_flags &= NOT(DEF_READING);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!from_int){
|
static void de_conf_addr(dpeth_t *dep, ether_addr_t *addr)
|
||||||
do_reply(dep);
|
|
||||||
}
|
|
||||||
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);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void de_conf_addr(dpeth_t * dep)
|
|
||||||
{
|
{
|
||||||
static char ea_fmt[] = "x:x:x:x:x:x";
|
u16_t temp16;
|
||||||
char ea_key[16];
|
int i;
|
||||||
int ix;
|
|
||||||
long val;
|
|
||||||
|
|
||||||
strlcpy(ea_key, "DEETH0_EA", sizeof(ea_key));
|
DEBUG(printf("Reading SROM...\n"));
|
||||||
ea_key[5] += de_instance;
|
|
||||||
|
|
||||||
for (ix = 0; ix < SA_ADDR_LEN; ix++) {
|
for(i=0;i<(1<<SROM_BITWIDTH)-1;i++){
|
||||||
val = dep->de_address.ea_addr[ix];
|
temp16 = de_read_rom(dep, i, SROM_BITWIDTH);
|
||||||
if (env_parse(ea_key, ea_fmt, ix, &val, 0x00L, 0xFFL) != EP_SET)
|
dep->srom[i*2] = temp16 & 0xFF;
|
||||||
break;
|
dep->srom[i*2+1] = temp16 >> 8;
|
||||||
dep->de_address.ea_addr[ix] = val;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ix != 0 && ix != SA_ADDR_LEN)
|
/* TODO: validate SROM content */
|
||||||
env_parse(ea_key, "?", 0, &val, 0L, 0L);
|
/* acquire MAC addr */
|
||||||
return;
|
DEBUG(printf("Using MAC addr= "));
|
||||||
|
for(i=0;i<6;i++){
|
||||||
|
addr->ea_addr[i] = dep->srom[i+DE_SROM_EA_OFFSET];
|
||||||
|
DEBUG(printf("%02X%c", addr->ea_addr[i],i!=5?'-':'\n'));
|
||||||
|
}
|
||||||
|
DEBUG(printf("probe success\n"));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void de_first_init(dpeth_t *dep)
|
static void de_init_buf(dpeth_t *dep)
|
||||||
{
|
{
|
||||||
int i,j,r;
|
int i,j,r;
|
||||||
vir_bytes descr_vir = (vir_bytes)dep->sendrecv_descr_buf;
|
vir_bytes descr_vir = (vir_bytes)dep->sendrecv_descr_buf;
|
||||||
@ -585,7 +295,6 @@ static void de_first_init(dpeth_t *dep)
|
|||||||
de_loc_descr_t *loc_descr;
|
de_loc_descr_t *loc_descr;
|
||||||
phys_bytes temp;
|
phys_bytes temp;
|
||||||
|
|
||||||
|
|
||||||
for(i=0;i<2;i++){
|
for(i=0;i<2;i++){
|
||||||
loc_descr = &dep->descr[i][0];
|
loc_descr = &dep->descr[i][0];
|
||||||
for(j=0; j < (i==DESCR_RECV ? DE_NB_RECV_DESCR : DE_NB_SEND_DESCR); j++){
|
for(j=0; j < (i==DESCR_RECV ? DE_NB_RECV_DESCR : DE_NB_SEND_DESCR); j++){
|
||||||
@ -627,11 +336,11 @@ static void de_first_init(dpeth_t *dep)
|
|||||||
/* record physical location of two first descriptor */
|
/* record physical location of two first descriptor */
|
||||||
r = sys_umap(SELF, VM_D, (vir_bytes)dep->descr[DESCR_RECV][0].descr,
|
r = sys_umap(SELF, VM_D, (vir_bytes)dep->descr[DESCR_RECV][0].descr,
|
||||||
sizeof(de_descr_t), &dep->sendrecv_descr_phys_addr[DESCR_RECV]);
|
sizeof(de_descr_t), &dep->sendrecv_descr_phys_addr[DESCR_RECV]);
|
||||||
if(r != OK) panic("%s %d", str_UmapErrMsg, r);
|
if(r != OK) panic("sys_umap failed: %d", r);
|
||||||
|
|
||||||
r = sys_umap(SELF, VM_D, (vir_bytes)dep->descr[DESCR_TRAN][0].descr,
|
r = sys_umap(SELF, VM_D, (vir_bytes)dep->descr[DESCR_TRAN][0].descr,
|
||||||
sizeof(de_descr_t), &dep->sendrecv_descr_phys_addr[DESCR_TRAN]);
|
sizeof(de_descr_t), &dep->sendrecv_descr_phys_addr[DESCR_TRAN]);
|
||||||
if(r != OK) panic("%s %d", str_UmapErrMsg, r);
|
if(r != OK) panic("sys_umap failed: %d", r);
|
||||||
|
|
||||||
DEBUG(printf("Descr: head tran=[%08X] head recv=[%08X]\n",
|
DEBUG(printf("Descr: head tran=[%08X] head recv=[%08X]\n",
|
||||||
dep->sendrecv_descr_phys_addr[DESCR_TRAN],
|
dep->sendrecv_descr_phys_addr[DESCR_TRAN],
|
||||||
@ -643,13 +352,12 @@ static void de_first_init(dpeth_t *dep)
|
|||||||
for(j=0;j< (i==DESCR_RECV?DE_NB_RECV_DESCR:DE_NB_SEND_DESCR);j++){
|
for(j=0;j< (i==DESCR_RECV?DE_NB_RECV_DESCR:DE_NB_SEND_DESCR);j++){
|
||||||
r = sys_umap(SELF, VM_D, (vir_bytes)&(loc_descr->descr),
|
r = sys_umap(SELF, VM_D, (vir_bytes)&(loc_descr->descr),
|
||||||
sizeof(de_descr_t), &temp);
|
sizeof(de_descr_t), &temp);
|
||||||
if(r != OK)
|
if(r != OK) panic("sys_umap failed: %d", r);
|
||||||
panic("%s %d", str_UmapErrMsg, r);
|
|
||||||
|
|
||||||
if( ((loc_descr->descr->des[DES_BUF1] & 0x3) != 0) ||
|
if( ((loc_descr->descr->des[DES_BUF1] & 0x3) != 0) ||
|
||||||
((loc_descr->descr->des[DES_BUF2] & 0x3) != 0) ||
|
((loc_descr->descr->des[DES_BUF2] & 0x3) != 0) ||
|
||||||
((temp&0x3)!=0) )
|
((temp&0x3)!=0) )
|
||||||
panic("%s 0x%lx", str_AlignErrMsg, temp);
|
panic("alignment error: 0x%lx", temp);
|
||||||
|
|
||||||
loc_descr++;
|
loc_descr++;
|
||||||
}
|
}
|
||||||
@ -658,43 +366,45 @@ static void de_first_init(dpeth_t *dep)
|
|||||||
/* Init default values */
|
/* Init default values */
|
||||||
dep->cur_descr[DESCR_TRAN]=1;
|
dep->cur_descr[DESCR_TRAN]=1;
|
||||||
dep->cur_descr[DESCR_RECV]=0;
|
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void do_interrupt(const dpeth_t *dep){
|
static void do_intr(unsigned int __unused mask)
|
||||||
|
{
|
||||||
|
dpeth_t *dep;
|
||||||
u32_t val;
|
u32_t val;
|
||||||
|
|
||||||
|
dep = &de_state;
|
||||||
|
|
||||||
val = io_inl(CSR_ADDR(dep, CSR5));
|
val = io_inl(CSR_ADDR(dep, CSR5));
|
||||||
|
|
||||||
if(val & CSR5_AIS){
|
if(val & CSR5_AIS){
|
||||||
panic("Abnormal Int CSR5=: %d", val);
|
panic("Abnormal Int CSR5=: %d", val);
|
||||||
}
|
}
|
||||||
|
|
||||||
if( (dep->de_flags & DEF_READING) && (val & CSR5_RI) ){
|
if (val & CSR5_RI)
|
||||||
do_vread_s(&dep->rx_return_msg, TRUE);
|
netdriver_recv();
|
||||||
}
|
|
||||||
|
|
||||||
if( (dep->de_flags & DEF_SENDING) && (val & CSR5_TI) ){
|
if (val & CSR5_TI)
|
||||||
do_vwrite_s(&dep->tx_return_msg, TRUE);
|
netdriver_send();
|
||||||
}
|
|
||||||
|
|
||||||
/* ack and reset interrupts */
|
/* ack and reset interrupts */
|
||||||
io_outl(CSR_ADDR(dep, CSR5), 0xFFFFFFFF);
|
io_outl(CSR_ADDR(dep, CSR5), 0xFFFFFFFF);
|
||||||
return;
|
|
||||||
|
sys_irqenable(&dep->de_hook);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void de_reset(const dpeth_t *dep){
|
static void de_reset(const dpeth_t *dep)
|
||||||
|
{
|
||||||
io_outl(CSR_ADDR(dep, CSR0), CSR0_SWR);
|
io_outl(CSR_ADDR(dep, CSR0), CSR0_SWR);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void de_hw_conf(const dpeth_t *dep){
|
static void do_stop(void)
|
||||||
|
{
|
||||||
|
de_reset(&de_state);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void de_hw_conf(const dpeth_t *dep)
|
||||||
|
{
|
||||||
u32_t val;
|
u32_t val;
|
||||||
|
|
||||||
/* CSR0 - global host bus prop */
|
/* CSR0 - global host bus prop */
|
||||||
@ -719,13 +429,15 @@ static void de_hw_conf(const dpeth_t *dep){
|
|||||||
io_outl(CSR_ADDR(dep, CSR6), val);
|
io_outl(CSR_ADDR(dep, CSR6), val);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void de_start(const dpeth_t *dep){
|
static void de_start(const dpeth_t *dep)
|
||||||
|
{
|
||||||
u32_t val;
|
u32_t val;
|
||||||
val = io_inl(CSR_ADDR(dep, CSR6)) | CSR6_ST | CSR6_SR;
|
val = io_inl(CSR_ADDR(dep, CSR6)) | CSR6_ST | CSR6_SR;
|
||||||
io_outl(CSR_ADDR(dep, CSR6), val);
|
io_outl(CSR_ADDR(dep, CSR6), val);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void de_setup_frame(const dpeth_t *dep){
|
static void de_setup_frame(const dpeth_t *dep, const ether_addr_t *addr)
|
||||||
|
{
|
||||||
int i;
|
int i;
|
||||||
u32_t val;
|
u32_t val;
|
||||||
|
|
||||||
@ -739,12 +451,12 @@ static void de_setup_frame(const dpeth_t *dep){
|
|||||||
dep->descr[DESCR_TRAN][0].buf1[9] = 0xFF;
|
dep->descr[DESCR_TRAN][0].buf1[9] = 0xFF;
|
||||||
for(i=1;i<16;i++){
|
for(i=1;i<16;i++){
|
||||||
memset(&(dep->descr[DESCR_TRAN][0].buf1[12*i]), 0, 12);
|
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+0] = addr->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+1] = addr->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+4] = addr->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+5] = addr->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+8] = addr->ea_addr[4];
|
||||||
dep->descr[DESCR_TRAN][0].buf1[12*i+9] = dep->de_address.ea_addr[5];
|
dep->descr[DESCR_TRAN][0].buf1[12*i+9] = addr->ea_addr[5];
|
||||||
}
|
}
|
||||||
|
|
||||||
dep->descr[DESCR_TRAN][0].descr->des[DES0] = DES0_OWN;
|
dep->descr[DESCR_TRAN][0].descr->des[DES0] = DES0_OWN;
|
||||||
@ -755,107 +467,30 @@ static void de_setup_frame(const dpeth_t *dep){
|
|||||||
val = io_inl(CSR_ADDR(dep, CSR6)) | CSR6_ST;
|
val = io_inl(CSR_ADDR(dep, CSR6)) | CSR6_ST;
|
||||||
io_outl(CSR_ADDR(dep, CSR6), val);
|
io_outl(CSR_ADDR(dep, CSR6), val);
|
||||||
io_outl(CSR_ADDR(dep, CSR1), 0xFFFFFFFF);
|
io_outl(CSR_ADDR(dep, CSR1), 0xFFFFFFFF);
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int de_calc_iov_size(iovec_dat_s_t * iovp){
|
static int do_send(struct netdriver_data *data, size_t size)
|
||||||
int size, ix;
|
{
|
||||||
size = ix = 0;
|
static int setup_done = 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
static 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);
|
|
||||||
if (rc != OK)
|
|
||||||
panic("%s %d", str_CopyErrMsg, rc);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
static 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void do_vwrite_s(const message * mp, int from_int){
|
|
||||||
static u8_t setupDone = 0;
|
|
||||||
int size, r, bytes, ix, totalsize;
|
|
||||||
dpeth_t *dep;
|
dpeth_t *dep;
|
||||||
iovec_dat_s_t *iovp = NULL;
|
|
||||||
de_loc_descr_t *descr = NULL;
|
de_loc_descr_t *descr = NULL;
|
||||||
u8_t *buffer = NULL;
|
|
||||||
|
|
||||||
dep = &de_state;
|
dep = &de_state;
|
||||||
|
|
||||||
dep->de_client = mp->m_source;
|
|
||||||
|
|
||||||
if (dep->de_mode == DEM_ENABLED) {
|
|
||||||
|
|
||||||
if (!from_int && (dep->de_flags & DEF_SENDING))
|
|
||||||
panic("%s", str_BusyErrMsg);
|
|
||||||
|
|
||||||
descr = &dep->descr[DESCR_TRAN][dep->cur_descr[DESCR_TRAN]];
|
descr = &dep->descr[DESCR_TRAN][dep->cur_descr[DESCR_TRAN]];
|
||||||
|
|
||||||
if(( descr->descr->des[DES0] & DES0_OWN)!=0)
|
if(( descr->descr->des[DES0] & DES0_OWN)!=0)
|
||||||
goto suspend;
|
return SUSPEND;
|
||||||
|
|
||||||
if(!setupDone && (dep->cur_descr[DESCR_TRAN] == 0) ){
|
if(!setup_done && (dep->cur_descr[DESCR_TRAN] == 0) ){
|
||||||
dep->descr[DESCR_TRAN][0].descr->des[DES0] = 0;
|
dep->descr[DESCR_TRAN][0].descr->des[DES0] = 0;
|
||||||
setupDone=1;
|
setup_done=1;
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer = descr->buf1;
|
netdriver_copyin(data, 0, descr->buf1, size);
|
||||||
iovp = &dep->de_write_iovec;
|
|
||||||
iovp->iod_proc_nr = mp->m_source;
|
|
||||||
de_get_userdata_s(mp->m_source, mp->m_net_netdrv_dl_writev_s.grant, 0,
|
|
||||||
mp->m_net_netdrv_dl_writev_s.count, iovp->iod_iovec);
|
|
||||||
iovp->iod_iovec_s = mp->m_net_netdrv_dl_writev_s.count;
|
|
||||||
iovp->iod_grant = mp->m_net_netdrv_dl_writev_s.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("%s %d", 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);
|
|
||||||
if (r != OK)
|
|
||||||
panic("%s %d", 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) |
|
descr->descr->des[DES1] = (descr->descr->des[DES1]&DES1_ER) |
|
||||||
DES1_FS | DES1_LS | DES1_IC | totalsize;
|
DES1_FS | DES1_LS | DES1_IC | size;
|
||||||
descr->descr->des[DES0] = DES0_OWN;
|
descr->descr->des[DES0] = DES0_OWN;
|
||||||
|
|
||||||
dep->cur_descr[DESCR_TRAN]++;
|
dep->cur_descr[DESCR_TRAN]++;
|
||||||
@ -863,41 +498,24 @@ static void do_vwrite_s(const message * mp, int from_int){
|
|||||||
dep->cur_descr[DESCR_TRAN] = 0;
|
dep->cur_descr[DESCR_TRAN] = 0;
|
||||||
|
|
||||||
io_outl(CSR_ADDR(dep, CSR1), 0xFFFFFFFF);
|
io_outl(CSR_ADDR(dep, CSR1), 0xFFFFFFFF);
|
||||||
|
|
||||||
|
dep->de_stat.ets_packetT++;
|
||||||
|
|
||||||
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
dep->de_flags |= DEF_ACK_SEND;
|
static u32_t io_inl(u16_t port)
|
||||||
if(from_int){
|
{
|
||||||
dep->de_flags &= NOT(DEF_SENDING);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
do_reply(dep);
|
|
||||||
return;
|
|
||||||
|
|
||||||
suspend:
|
|
||||||
if(from_int)
|
|
||||||
panic("should not happen: %d", 0);
|
|
||||||
|
|
||||||
dep->de_stat.ets_transDef++;
|
|
||||||
dep->de_flags |= DEF_SENDING;
|
|
||||||
dep->de_stat.ets_transDef++;
|
|
||||||
dep->tx_return_msg = *mp;
|
|
||||||
do_reply(dep);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void warning(const char *type, int err){
|
|
||||||
printf("Warning: %s sys_%s failed (%d)\n", str_DevName, type, err);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
static u32_t io_inl(u16_t port){
|
|
||||||
u32_t value;
|
u32_t value;
|
||||||
int rc;
|
int rc;
|
||||||
if ((rc = sys_inl(port, &value)) != OK) warning("inl", rc);
|
if ((rc = sys_inl(port, &value)) != OK)
|
||||||
|
panic("sys_inl failed: %d", rc);
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void io_outl(u16_t port, u32_t value){
|
static void io_outl(u16_t port, u32_t value)
|
||||||
|
{
|
||||||
int rc;
|
int rc;
|
||||||
if ((rc = sys_outl(port, value)) != OK) warning("outl", rc);
|
if ((rc = sys_outl(port, value)) != OK)
|
||||||
return;
|
panic("sys_outl failed: %d", rc);
|
||||||
}
|
}
|
||||||
|
@ -11,37 +11,21 @@ Created: 09/01/2009 Nicolas Tittley (first.last @ gmail DOT com)
|
|||||||
|
|
||||||
#include <sys/null.h>
|
#include <sys/null.h>
|
||||||
|
|
||||||
#define DE_FKEY 7 /* Shift+ this value will dump info on console */
|
|
||||||
|
|
||||||
#define NOT(x) (~(x))
|
|
||||||
|
|
||||||
#if debug == 1
|
#if debug == 1
|
||||||
# define DEBUG(statm) statm
|
# define DEBUG(statm) statm
|
||||||
#else
|
#else
|
||||||
# define DEBUG(statm)
|
# define DEBUG(statm)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#define SA_ADDR_LEN sizeof(ether_addr_t)
|
|
||||||
|
|
||||||
#define DE_NB_SEND_DESCR 32
|
#define DE_NB_SEND_DESCR 32
|
||||||
#define DE_SEND_BUF_SIZE (ETH_MAX_PACK_SIZE+2)
|
#define DE_SEND_BUF_SIZE (ETH_MAX_PACK_SIZE+2)
|
||||||
#define DE_NB_RECV_DESCR 32
|
#define DE_NB_RECV_DESCR 32
|
||||||
#define DE_RECV_BUF_SIZE (ETH_MAX_PACK_SIZE+2)
|
#define DE_RECV_BUF_SIZE (ETH_MAX_PACK_SIZE+2)
|
||||||
#define IOVEC_NR 16
|
|
||||||
#define DE_MIN_BASE_ADDR 0x0400
|
#define DE_MIN_BASE_ADDR 0x0400
|
||||||
#define DE_SROM_EA_OFFSET 20
|
#define DE_SROM_EA_OFFSET 20
|
||||||
#define DE_SETUP_FRAME_SIZE 192
|
#define DE_SETUP_FRAME_SIZE 192
|
||||||
|
|
||||||
|
|
||||||
typedef struct iovec_dat_s {
|
|
||||||
iovec_s_t iod_iovec[IOVEC_NR];
|
|
||||||
int iod_iovec_s;
|
|
||||||
endpoint_t iod_proc_nr;
|
|
||||||
cp_grant_id_t iod_grant;
|
|
||||||
vir_bytes iod_iovec_offset;
|
|
||||||
} iovec_dat_s_t;
|
|
||||||
|
|
||||||
typedef struct de_descr {
|
typedef struct de_descr {
|
||||||
u32_t des[4];
|
u32_t des[4];
|
||||||
} de_descr_t;
|
} de_descr_t;
|
||||||
@ -53,9 +37,6 @@ typedef struct de_local_descr {
|
|||||||
} de_loc_descr_t;
|
} de_loc_descr_t;
|
||||||
|
|
||||||
typedef struct dpeth {
|
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 */
|
char de_name[32]; /* Name of this interface */
|
||||||
port_t de_base_port; /* Base port, for multiple card instance */
|
port_t de_base_port; /* Base port, for multiple card instance */
|
||||||
int de_irq; /* IRQ line number */
|
int de_irq; /* IRQ line number */
|
||||||
@ -63,10 +44,7 @@ typedef struct dpeth {
|
|||||||
|
|
||||||
int de_type; /* What kind of hardware */
|
int de_type; /* What kind of hardware */
|
||||||
|
|
||||||
ether_addr_t de_address; /* Ethernet Address */
|
|
||||||
eth_stat_t de_stat; /* Stats */
|
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.
|
/* 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 */
|
here we just make sure we have the space we need at compile time */
|
||||||
@ -81,42 +59,11 @@ typedef struct dpeth {
|
|||||||
#define DESCR_RECV 0
|
#define DESCR_RECV 0
|
||||||
#define DESCR_TRAN 1
|
#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 */
|
/* Serial ROM */
|
||||||
#define SROM_BITWIDTH 6
|
#define SROM_BITWIDTH 6
|
||||||
|
|
||||||
u8_t srom[((1<<SROM_BITWIDTH)-1)*2]; /* Space to read in
|
u8_t srom[((1<<SROM_BITWIDTH)-1)*2]; /* Space to read in
|
||||||
all the configuration ROM */
|
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;
|
|
||||||
endpoint_t de_client;
|
|
||||||
|
|
||||||
} dpeth_t;
|
} dpeth_t;
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user