Safecopy support in ethernet drivers.
This commit is contained in:
parent
9392742cc4
commit
2cf649db2e
15 changed files with 2150 additions and 579 deletions
|
@ -21,7 +21,7 @@ OBJ = 3c503.o dp8390.o ne2000.o rtl8029.o wdeth.o
|
|||
all build: $(DRIVER)
|
||||
$(DRIVER): $(OBJ)
|
||||
$(CC) -o $@ $(LDFLAGS) $(OBJ) $(LIBS)
|
||||
install -S 4096 $(DRIVER)
|
||||
install -S 32k $(DRIVER)
|
||||
|
||||
# install with other drivers
|
||||
install: /usr/sbin/$(DRIVER)
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -172,14 +172,21 @@ typedef struct dp_rcvhdr
|
|||
|
||||
struct dpeth;
|
||||
struct iovec_dat;
|
||||
struct iovec_dat_s;
|
||||
_PROTOTYPE( typedef void (*dp_initf_t), (struct dpeth *dep) );
|
||||
_PROTOTYPE( typedef void (*dp_stopf_t), (struct dpeth *dep) );
|
||||
_PROTOTYPE( typedef void (*dp_user2nicf_t), (struct dpeth *dep,
|
||||
struct iovec_dat *iovp, vir_bytes offset,
|
||||
int nic_addr, vir_bytes count) );
|
||||
_PROTOTYPE( typedef void (*dp_user2nicf_s_t), (struct dpeth *dep,
|
||||
struct iovec_dat_s *iovp, vir_bytes offset,
|
||||
int nic_addr, vir_bytes count) );
|
||||
_PROTOTYPE( typedef void (*dp_nic2userf_t), (struct dpeth *dep,
|
||||
int nic_addr, struct iovec_dat *iovp,
|
||||
vir_bytes offset, vir_bytes count) );
|
||||
_PROTOTYPE( typedef void (*dp_nic2userf_s_t), (struct dpeth *dep,
|
||||
int nic_addr, struct iovec_dat_s *iovp,
|
||||
vir_bytes offset, vir_bytes count) );
|
||||
#if 0
|
||||
_PROTOTYPE( typedef void (*dp_getheaderf_t), (struct dpeth *dep,
|
||||
int page, struct dp_rcvhdr *h, u16_t *eth_type) );
|
||||
|
@ -200,6 +207,15 @@ typedef struct iovec_dat
|
|||
vir_bytes iod_iovec_addr;
|
||||
} iovec_dat_t;
|
||||
|
||||
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;
|
||||
|
||||
#define SENDQ_NR 2 /* Maximum size of the send queue */
|
||||
#define SENDQ_PAGES 6 /* 6 * DP_PAGESIZE >= 1514 bytes */
|
||||
|
||||
|
@ -215,6 +231,7 @@ typedef struct dpeth
|
|||
*/
|
||||
port_t de_base_port;
|
||||
phys_bytes de_linmem;
|
||||
char *de_locmem;
|
||||
int de_irq;
|
||||
int de_int_pending;
|
||||
irq_hook_t de_hook;
|
||||
|
@ -261,13 +278,19 @@ typedef struct dpeth
|
|||
int de_mode;
|
||||
eth_stat_t de_stat;
|
||||
iovec_dat_t de_read_iovec;
|
||||
iovec_dat_s_t de_read_iovec_s;
|
||||
int de_safecopy_read;
|
||||
iovec_dat_t de_write_iovec;
|
||||
iovec_dat_s_t de_write_iovec_s;
|
||||
iovec_dat_t de_tmp_iovec;
|
||||
iovec_dat_s_t de_tmp_iovec_s;
|
||||
vir_bytes de_read_s;
|
||||
int de_client;
|
||||
message de_sendmsg;
|
||||
dp_user2nicf_t de_user2nicf;
|
||||
dp_user2nicf_s_t de_user2nicf_s;
|
||||
dp_nic2userf_t de_nic2userf;
|
||||
dp_nic2userf_s_t de_nic2userf_s;
|
||||
dp_getblock_t de_getblockf;
|
||||
} dpeth_t;
|
||||
|
||||
|
|
|
@ -122,16 +122,19 @@ static void el3_write_fifo(dpeth_t * dep, int pktsize)
|
|||
{
|
||||
phys_bytes phys_user;
|
||||
int bytes, ix = 0;
|
||||
iovec_dat_t *iovp = &dep->de_write_iovec;
|
||||
int padding = pktsize;
|
||||
iovec_dat_s_t *iovp = &dep->de_write_iovec;
|
||||
int r, padding = pktsize;
|
||||
|
||||
do { /* Writes chuncks of packet from user buffers */
|
||||
|
||||
bytes = iovp->iod_iovec[ix].iov_size; /* Size of buffer */
|
||||
if (bytes > pktsize) bytes = pktsize;
|
||||
/* Writes from user buffer to Tx FIFO */
|
||||
outsb(dep->de_data_port, iovp->iod_proc_nr,
|
||||
(void*)(iovp->iod_iovec[ix].iov_addr), bytes);
|
||||
r= sys_safe_insb(dep->de_data_port, iovp->iod_proc_nr,
|
||||
iovp->iod_iovec[ix].iov_grant, 0, bytes);
|
||||
if (r != OK)
|
||||
panic(__FILE__, "el3_write_fifo: sys_safe_insb failed", r);
|
||||
|
||||
if (++ix >= IOVEC_NR) { /* Next buffer of IO vector */
|
||||
dp_next_iovec(iovp);
|
||||
ix = 0;
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
#include <assert.h>
|
||||
/*
|
||||
** File: 8390.c May 02, 2000
|
||||
**
|
||||
|
@ -25,14 +26,18 @@
|
|||
|
||||
#include "8390.h"
|
||||
|
||||
#if 0
|
||||
#define sys_nic2mem(srcOffs,dstProc,dstOffs,length) \
|
||||
sys_vircopy(SELF,dep->de_memsegm,(vir_bytes)(srcOffs),\
|
||||
(dstProc),D,(vir_bytes)(dstOffs),length)
|
||||
#define sys_user2nic(srcProc,srcOffs,dstOffs,length) \
|
||||
sys_vircopy((srcProc),D,(vir_bytes)(srcOffs),\
|
||||
SELF,dep->de_memsegm,(vir_bytes)(dstOffs),length)
|
||||
#endif
|
||||
#if 0
|
||||
#define sys_user2nic_s(srcProc,grant,dstOffs,length) \
|
||||
sys_safecopyfrom((srcProc),(grant),0, \
|
||||
(vir_bytes)(dstOffs),length,dep->de_memsegm)
|
||||
#endif
|
||||
|
||||
static const char RdmaErrMsg[] = "remote dma failed to complete";
|
||||
static char RdmaErrMsg[] = "remote dma failed to complete";
|
||||
|
||||
/*
|
||||
** Name: void ns_rw_setup(dpeth_t *dep, int mode, int size, u16_t offset);
|
||||
|
@ -72,9 +77,11 @@ static void ns_start_xmit(dpeth_t * dep, int size, int pageno)
|
|||
*/
|
||||
static void mem_getblock(dpeth_t *dep, u16_t offset, int size, void *dst)
|
||||
{
|
||||
|
||||
panic(__FILE__, "mem_getblock: not converted to safecopies", NO_NUM);
|
||||
#if 0
|
||||
sys_nic2mem(dep->de_linmem + offset, SELF, dst, size);
|
||||
return;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -84,9 +91,12 @@ static void mem_getblock(dpeth_t *dep, u16_t offset, int size, void *dst)
|
|||
static void mem_nic2user(dpeth_t * dep, int pageno, int pktsize)
|
||||
{
|
||||
phys_bytes offset, phys_user;
|
||||
iovec_dat_t *iovp = &dep->de_read_iovec;
|
||||
iovec_dat_s_t *iovp = &dep->de_read_iovec;
|
||||
int bytes, ix = 0;
|
||||
|
||||
panic(__FILE__, "mem_nic2user: not converted to safecopies", NO_NUM);
|
||||
#if 0
|
||||
|
||||
/* Computes shared memory address (skipping receive header) */
|
||||
offset = pageno * DP_PAGESIZE + sizeof(dp_rcvhdr_t);
|
||||
|
||||
|
@ -100,16 +110,16 @@ static void mem_nic2user(dpeth_t * dep, int pageno, int pktsize)
|
|||
|
||||
/* Circular buffer wrap-around */
|
||||
bytes = dep->de_stoppage * DP_PAGESIZE - offset;
|
||||
sys_nic2mem(dep->de_linmem + offset, iovp->iod_proc_nr,
|
||||
iovp->iod_iovec[ix].iov_addr, bytes);
|
||||
sys_nic2mem_s(dep->de_linmem + offset, iovp->iod_proc_nr,
|
||||
iovp->iod_iovec[ix].iov_grant, bytes);
|
||||
pktsize -= bytes;
|
||||
phys_user += bytes;
|
||||
bytes = iovp->iod_iovec[ix].iov_size - bytes;
|
||||
if (bytes > pktsize) bytes = pktsize;
|
||||
offset = dep->de_startpage * DP_PAGESIZE;
|
||||
}
|
||||
sys_nic2mem(dep->de_linmem + offset, iovp->iod_proc_nr,
|
||||
iovp->iod_iovec[ix].iov_addr, bytes);
|
||||
sys_nic2mem_s(dep->de_linmem + offset, iovp->iod_proc_nr,
|
||||
iovp->iod_iovec[ix].iov_grant, bytes);
|
||||
offset += bytes;
|
||||
|
||||
if (++ix >= IOVEC_NR) { /* Next buffer of IO vector */
|
||||
|
@ -119,6 +129,7 @@ static void mem_nic2user(dpeth_t * dep, int pageno, int pktsize)
|
|||
/* Till packet done */
|
||||
} while ((pktsize -= bytes) > 0);
|
||||
return;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -128,9 +139,12 @@ static void mem_nic2user(dpeth_t * dep, int pageno, int pktsize)
|
|||
static void mem_user2nic(dpeth_t *dep, int pageno, int pktsize)
|
||||
{
|
||||
phys_bytes offset, phys_user;
|
||||
iovec_dat_t *iovp = &dep->de_write_iovec;
|
||||
iovec_dat_s_t *iovp = &dep->de_write_iovec;
|
||||
int bytes, ix = 0;
|
||||
|
||||
panic(__FILE__, "mem_user2nic: not converted to safecopies", NO_NUM);
|
||||
#if 0
|
||||
|
||||
/* Computes shared memory address */
|
||||
offset = pageno * DP_PAGESIZE;
|
||||
|
||||
|
@ -140,7 +154,7 @@ static void mem_user2nic(dpeth_t *dep, int pageno, int pktsize)
|
|||
if (bytes > pktsize) bytes = pktsize;
|
||||
|
||||
/* Reads from user area to board (shared memory) */
|
||||
sys_user2nic(iovp->iod_proc_nr, iovp->iod_iovec[ix].iov_addr,
|
||||
sys_user2nic_s(iovp->iod_proc_nr, iovp->iod_iovec[ix].iov_grant,
|
||||
dep->de_linmem + offset, bytes);
|
||||
offset += bytes;
|
||||
|
||||
|
@ -151,6 +165,7 @@ static void mem_user2nic(dpeth_t *dep, int pageno, int pktsize)
|
|||
/* Till packet done */
|
||||
} while ((pktsize -= bytes) > 0);
|
||||
return;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -183,8 +198,8 @@ static void pio_getblock(dpeth_t *dep, u16_t offset, int size, void *dst)
|
|||
static void pio_nic2user(dpeth_t *dep, int pageno, int pktsize)
|
||||
{
|
||||
phys_bytes phys_user;
|
||||
iovec_dat_t *iovp = &dep->de_read_iovec;
|
||||
unsigned offset; int bytes, ix = 0;
|
||||
iovec_dat_s_t *iovp = &dep->de_read_iovec;
|
||||
unsigned offset, iov_offset; int r, bytes, ix = 0;
|
||||
|
||||
/* Computes memory address (skipping receive header) */
|
||||
offset = pageno * DP_PAGESIZE + sizeof(dp_rcvhdr_t);
|
||||
|
@ -192,6 +207,7 @@ static void pio_nic2user(dpeth_t *dep, int pageno, int pktsize)
|
|||
ns_rw_setup(dep, CR_DM_RR, ((offset + pktsize) > (dep->de_stoppage * DP_PAGESIZE)) ?
|
||||
(dep->de_stoppage * DP_PAGESIZE) - offset : pktsize, offset);
|
||||
|
||||
iov_offset= 0;
|
||||
do { /* Reads chuncks of packet into user area */
|
||||
|
||||
bytes = iovp->iod_iovec[ix].iov_size; /* Size of a chunck */
|
||||
|
@ -201,21 +217,31 @@ static void pio_nic2user(dpeth_t *dep, int pageno, int pktsize)
|
|||
|
||||
/* Circular buffer wrap-around */
|
||||
bytes = dep->de_stoppage * DP_PAGESIZE - offset;
|
||||
insb(dep->de_data_port, iovp->iod_proc_nr, (void*)(iovp->iod_iovec[ix].iov_addr), bytes);
|
||||
r= sys_safe_insb(dep->de_data_port, iovp->iod_proc_nr,
|
||||
iovp->iod_iovec[ix].iov_grant, iov_offset, bytes);
|
||||
if (r != OK)
|
||||
{
|
||||
panic(__FILE__, "pio_nic2user: sys_safe_insb failed",
|
||||
r);
|
||||
}
|
||||
pktsize -= bytes;
|
||||
iovp->iod_iovec[ix].iov_addr += bytes;
|
||||
iov_offset += bytes;
|
||||
bytes = iovp->iod_iovec[ix].iov_size - bytes;
|
||||
if (bytes > pktsize) bytes = pktsize;
|
||||
offset = dep->de_startpage * DP_PAGESIZE;
|
||||
ns_rw_setup(dep, CR_DM_RR, pktsize, offset);
|
||||
}
|
||||
insb(dep->de_data_port, iovp->iod_proc_nr, (void*)(iovp->iod_iovec[ix].iov_addr), bytes);
|
||||
r= sys_safe_insb(dep->de_data_port, iovp->iod_proc_nr,
|
||||
iovp->iod_iovec[ix].iov_grant, iov_offset, bytes);
|
||||
if (r != OK)
|
||||
panic(__FILE__, "pio_nic2user: sys_safe_insb failed", r);
|
||||
offset += bytes;
|
||||
|
||||
if (++ix >= IOVEC_NR) { /* Next buffer of IO vector */
|
||||
dp_next_iovec(iovp);
|
||||
ix = 0;
|
||||
}
|
||||
iov_offset= 0;
|
||||
/* Till packet done */
|
||||
} while ((pktsize -= bytes) > 0);
|
||||
return;
|
||||
|
@ -228,8 +254,8 @@ static void pio_nic2user(dpeth_t *dep, int pageno, int pktsize)
|
|||
static void pio_user2nic(dpeth_t *dep, int pageno, int pktsize)
|
||||
{
|
||||
phys_bytes phys_user;
|
||||
iovec_dat_t *iovp = &dep->de_write_iovec;
|
||||
int bytes, ix = 0;
|
||||
iovec_dat_s_t *iovp = &dep->de_write_iovec;
|
||||
int r, bytes, ix = 0;
|
||||
|
||||
/* Sets up board for writing */
|
||||
ns_rw_setup(dep, CR_DM_RW, pktsize, pageno * DP_PAGESIZE);
|
||||
|
@ -238,8 +264,10 @@ static void pio_user2nic(dpeth_t *dep, int pageno, int pktsize)
|
|||
|
||||
bytes = iovp->iod_iovec[ix].iov_size; /* Size of chunck */
|
||||
if (bytes > pktsize) bytes = pktsize;
|
||||
outsb(dep->de_data_port, iovp->iod_proc_nr,
|
||||
(void*)(iovp->iod_iovec[ix].iov_addr), bytes);
|
||||
r= sys_safe_outsb(dep->de_data_port, iovp->iod_proc_nr,
|
||||
iovp->iod_iovec[ix].iov_grant, 0, bytes);
|
||||
if (r != OK)
|
||||
panic(__FILE__, "pio_user2nic: sys_safe_outsb failed", r);
|
||||
|
||||
if (++ix >= IOVEC_NR) { /* Next buffer of I/O vector */
|
||||
dp_next_iovec(iovp);
|
||||
|
|
|
@ -2,6 +2,9 @@
|
|||
## Makefile for ISA ethernet drivers May 02, 2000
|
||||
##
|
||||
## $Log$
|
||||
## Revision 1.4 2006/07/10 12:43:38 philip
|
||||
## Safecopy support in ethernet drivers.
|
||||
##
|
||||
## Revision 1.3 2005/07/19 13:21:48 jnherder
|
||||
## Renamed src/lib/utils to src/lib/sysutil --- because of new src/lib/util
|
||||
##
|
||||
|
@ -26,7 +29,7 @@ debug = 0
|
|||
CC = exec cc
|
||||
LD = $(CC)
|
||||
CPPFLAGS= -I.. -I/usr/include -Ddebug=$(debug)
|
||||
CFLAGS = -ws $(CPPFLAGS)
|
||||
CFLAGS = $(CPPFLAGS)
|
||||
LDFLAGS = -i -o $@
|
||||
|
||||
SRCS = 3c501.c 3c509.c 3c503.c ne.c wd.c 8390.c devio.c netbuff.c dp.c
|
||||
|
|
|
@ -29,7 +29,7 @@ static void warning(const char *type, int err)
|
|||
*/
|
||||
PUBLIC unsigned int inb(unsigned short port)
|
||||
{
|
||||
unsigned int value;
|
||||
unsigned long value;
|
||||
int rc;
|
||||
|
||||
if ((rc = sys_inb(port, &value)) != OK) warning("inb", rc);
|
||||
|
@ -42,7 +42,7 @@ PUBLIC unsigned int inb(unsigned short port)
|
|||
*/
|
||||
PUBLIC unsigned int inw(unsigned short port)
|
||||
{
|
||||
unsigned int value;
|
||||
unsigned long value;
|
||||
int rc;
|
||||
|
||||
if ((rc = sys_inw(port, &value)) != OK) warning("inw", rc);
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
#include <assert.h>
|
||||
/*
|
||||
** File: eth.c Version 1.00, Jan. 14, 1997
|
||||
**
|
||||
|
@ -29,7 +30,7 @@
|
|||
** +------------+---------+---------+--------+-------+---------+
|
||||
** | DL_READV | port nr | proc nr | count | | address | (6)
|
||||
** +------------+---------+---------+--------+-------+---------+
|
||||
** | DL_INIT | port nr | proc nr | | mode | address | (7)
|
||||
** | DL_CONF | port nr | proc nr | | mode | address | (7)
|
||||
** +------------+---------+---------+--------+-------+---------+
|
||||
** | DL_STOP | port_nr | | | | | (8)
|
||||
** +------------+---------+---------+--------+-------+---------+
|
||||
|
@ -45,7 +46,7 @@
|
|||
**
|
||||
** m_type m3_i1 m3_i2 m3_ca1
|
||||
** +------------+---------+---------+---------------+
|
||||
** |DL_INIT_REPL| port nr |last port| ethernet addr | (20)
|
||||
** |DL_CONF_REPL| port nr |last port| ethernet addr | (20)
|
||||
** +------------+---------+---------+---------------+
|
||||
**
|
||||
** $Id$
|
||||
|
@ -80,13 +81,13 @@ static dp_conf_t dp_conf[DE_PORT_NR] = {
|
|||
{ 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 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);
|
||||
|
||||
|
@ -223,16 +224,17 @@ static void do_dump(message *mp)
|
|||
}
|
||||
|
||||
/*
|
||||
** Name: void get_userdata(int user_proc, vir_bytes user_addr, int count, void *loc_addr)
|
||||
** 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(int user_proc, vir_bytes user_addr, int count, void *loc_addr)
|
||||
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_datacopy(user_proc, user_addr, SELF, (vir_bytes)loc_addr, len)) != OK)
|
||||
if ((rc = sys_safecopyfrom(user_proc, grant, 0, (vir_bytes)loc_addr, len, D)) != OK)
|
||||
panic(DevName, CopyErrMsg, rc);
|
||||
return;
|
||||
}
|
||||
|
@ -339,7 +341,7 @@ static void do_init(message * mp)
|
|||
} else /* Port number is out of range */
|
||||
port = ENXIO;
|
||||
|
||||
reply_mess.m_type = DL_INIT_REPLY;
|
||||
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));
|
||||
|
@ -353,12 +355,12 @@ static void do_init(message * mp)
|
|||
** Name: void dp_next_iovec(iovec_dat_t *iovp)
|
||||
** Function: Retrieves data from next iovec element.
|
||||
*/
|
||||
PUBLIC void dp_next_iovec(iovec_dat_t * iovp)
|
||||
PUBLIC void dp_next_iovec(iovec_dat_s_t * iovp)
|
||||
{
|
||||
|
||||
iovp->iod_iovec_s -= IOVEC_NR;
|
||||
iovp->iod_iovec_addr += IOVEC_NR * sizeof(iovec_t);
|
||||
get_userdata(iovp->iod_proc_nr, iovp->iod_iovec_addr,
|
||||
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;
|
||||
}
|
||||
|
@ -367,7 +369,7 @@ PUBLIC void dp_next_iovec(iovec_dat_t * iovp)
|
|||
** Name: int calc_iovec_size(iovec_dat_t *iovp)
|
||||
** Function: Compute the size of a request.
|
||||
*/
|
||||
static int calc_iovec_size(iovec_dat_t * iovp)
|
||||
static int calc_iovec_size(iovec_dat_s_t * iovp)
|
||||
{
|
||||
int size, ix;
|
||||
|
||||
|
@ -385,10 +387,10 @@ static int calc_iovec_size(iovec_dat_t * iovp)
|
|||
}
|
||||
|
||||
/*
|
||||
** Name: void do_vwrite(message *mp, int vectored)
|
||||
** Name: void do_vwrite_s(message *mp, int vectored)
|
||||
** Function:
|
||||
*/
|
||||
static void do_vwrite(message * mp, int vectored)
|
||||
static void do_vwrite_s(message * mp)
|
||||
{
|
||||
int port, size;
|
||||
dpeth_t *dep;
|
||||
|
@ -406,18 +408,12 @@ static void do_vwrite(message * mp, int vectored)
|
|||
panic(dep->de_name, "send already in progress ", NO_NUM);
|
||||
|
||||
dep->de_write_iovec.iod_proc_nr = mp->DL_PROC;
|
||||
if (vectored) {
|
||||
get_userdata(mp->DL_PROC, (vir_bytes) mp->DL_ADDR,
|
||||
mp->DL_COUNT, dep->de_write_iovec.iod_iovec);
|
||||
dep->de_write_iovec.iod_iovec_s = mp->DL_COUNT;
|
||||
dep->de_write_iovec.iod_iovec_addr = (vir_bytes) mp->DL_ADDR;
|
||||
size = calc_iovec_size(&dep->de_write_iovec);
|
||||
} else {
|
||||
dep->de_write_iovec.iod_iovec[0].iov_addr = (vir_bytes) mp->DL_ADDR;
|
||||
dep->de_write_iovec.iod_iovec[0].iov_size = size = mp->DL_COUNT;
|
||||
dep->de_write_iovec.iod_iovec_s = 1;
|
||||
dep->de_write_iovec.iod_iovec_addr = 0;
|
||||
}
|
||||
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);
|
||||
|
||||
|
@ -432,10 +428,10 @@ static void do_vwrite(message * mp, int vectored)
|
|||
}
|
||||
|
||||
/*
|
||||
** Name: void do_vread(message *mp, int vectored)
|
||||
** Name: void do_vread_s(message *mp, int vectored)
|
||||
** Function:
|
||||
*/
|
||||
static void do_vread(message * mp, int vectored)
|
||||
static void do_vread_s(message * mp)
|
||||
{
|
||||
int port, size;
|
||||
dpeth_t *dep;
|
||||
|
@ -453,18 +449,12 @@ static void do_vread(message * mp, int vectored)
|
|||
panic(dep->de_name, "read already in progress", NO_NUM);
|
||||
|
||||
dep->de_read_iovec.iod_proc_nr = mp->DL_PROC;
|
||||
if (vectored) {
|
||||
get_userdata(mp->DL_PROC, (vir_bytes) mp->DL_ADDR,
|
||||
mp->DL_COUNT, dep->de_read_iovec.iod_iovec);
|
||||
dep->de_read_iovec.iod_iovec_s = mp->DL_COUNT;
|
||||
dep->de_read_iovec.iod_iovec_addr = (vir_bytes) mp->DL_ADDR;
|
||||
size = calc_iovec_size(&dep->de_read_iovec);
|
||||
} else {
|
||||
dep->de_read_iovec.iod_iovec[0].iov_addr = (vir_bytes) mp->DL_ADDR;
|
||||
dep->de_read_iovec.iod_iovec[0].iov_size = size = mp->DL_COUNT;
|
||||
dep->de_read_iovec.iod_iovec_s = 1;
|
||||
dep->de_read_iovec.iod_iovec_addr = 0;
|
||||
}
|
||||
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;
|
||||
|
@ -481,10 +471,10 @@ static void do_vread(message * mp, int vectored)
|
|||
}
|
||||
|
||||
/*
|
||||
** Name: void do_getstat(message *mp)
|
||||
** Name: void do_getstat_s(message *mp)
|
||||
** Function: Reports device statistics.
|
||||
*/
|
||||
static void do_getstat(message * mp)
|
||||
static void do_getstat_s(message * mp)
|
||||
{
|
||||
int port, rc;
|
||||
dpeth_t *dep;
|
||||
|
@ -497,9 +487,9 @@ static void do_getstat(message * mp)
|
|||
dep->de_client = mp->DL_PROC;
|
||||
|
||||
if (dep->de_mode == DEM_ENABLED) (*dep->de_getstatsf) (dep);
|
||||
if ((rc = sys_datacopy(SELF, (vir_bytes)&dep->de_stat,
|
||||
mp->DL_PROC, (vir_bytes)mp->DL_ADDR,
|
||||
(vir_bytes) sizeof(dep->de_stat))) != OK)
|
||||
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);
|
||||
return;
|
||||
|
@ -592,23 +582,17 @@ PUBLIC int main(int argc, char **argv)
|
|||
case DEV_PING: /* Status request from RS */
|
||||
notify(m.m_source);
|
||||
continue;
|
||||
case DL_WRITE: /* Write message to device */
|
||||
do_vwrite(&m, FALSE);
|
||||
case DL_WRITEV_S: /* Write message to device */
|
||||
do_vwrite_s(&m);
|
||||
break;
|
||||
case DL_WRITEV: /* Write message to device */
|
||||
do_vwrite(&m, TRUE);
|
||||
case DL_READV_S: /* Read message from device */
|
||||
do_vread_s(&m);
|
||||
break;
|
||||
case DL_READ: /* Read message from device */
|
||||
do_vread(&m, FALSE);
|
||||
break;
|
||||
case DL_READV: /* Read message from device */
|
||||
do_vread(&m, TRUE);
|
||||
break;
|
||||
case DL_INIT: /* Initialize device */
|
||||
case DL_CONF: /* Initialize device */
|
||||
do_init(&m);
|
||||
break;
|
||||
case DL_GETSTAT: /* Get device statistics */
|
||||
do_getstat(&m);
|
||||
case DL_GETSTAT_S: /* Get device statistics */
|
||||
do_getstat_s(&m);
|
||||
break;
|
||||
case DL_GETNAME:
|
||||
do_getname(&m);
|
||||
|
|
|
@ -6,6 +6,9 @@
|
|||
** Interface description for ethernet device driver
|
||||
**
|
||||
** $Log$
|
||||
** Revision 1.5 2006/07/10 12:43:38 philip
|
||||
** Safecopy support in ethernet drivers.
|
||||
**
|
||||
** Revision 1.4 2005/09/04 18:52:16 beng
|
||||
** Giovanni's fixes to dpeth:
|
||||
** Date: Sat, 03 Sep 2005 11:05:22 +0200
|
||||
|
@ -83,12 +86,13 @@ typedef void (*dp_getblock_t) (struct dpeth *, u16_t, int, void *);
|
|||
#define SENDQ_NR 2 /* Size of the send queue */
|
||||
#define IOVEC_NR 16 /* Number of IOVEC entries at a time */
|
||||
|
||||
typedef struct iovec_dat {
|
||||
iovec_t iod_iovec[IOVEC_NR];
|
||||
typedef struct iovec_dat_s {
|
||||
iovec_s_t iod_iovec[IOVEC_NR];
|
||||
int iod_iovec_s;
|
||||
int iod_proc_nr;
|
||||
vir_bytes iod_iovec_addr;
|
||||
} iovec_dat_t;
|
||||
cp_grant_id_t iod_grant;
|
||||
vir_bytes iod_iovec_offset;
|
||||
} iovec_dat_s_t;
|
||||
|
||||
typedef struct dpeth {
|
||||
/* The de_base_port field is the starting point of the probe. The
|
||||
|
@ -161,8 +165,8 @@ typedef struct dpeth {
|
|||
#define DEM_ENABLED 0x0002
|
||||
|
||||
/* Temporary storage for RECV/SEND requests */
|
||||
iovec_dat_t de_read_iovec;
|
||||
iovec_dat_t de_write_iovec;
|
||||
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;
|
||||
|
@ -216,7 +220,7 @@ typedef struct dpeth {
|
|||
*/
|
||||
|
||||
/* dp.c */
|
||||
void dp_next_iovec(iovec_dat_t * iovp);
|
||||
void dp_next_iovec(iovec_dat_s_t * iovp);
|
||||
|
||||
/* devio.c */
|
||||
#if defined USE_IOPL
|
||||
|
|
|
@ -111,8 +111,8 @@ PUBLIC void mem2user(dpeth_t *dep, buff_t *rxbuff)
|
|||
{
|
||||
phys_bytes phys_user;
|
||||
int bytes, ix = 0;
|
||||
iovec_dat_t *iovp = &dep->de_read_iovec;
|
||||
int pktsize = rxbuff->size;
|
||||
iovec_dat_s_t *iovp = &dep->de_read_iovec;
|
||||
int r, pktsize = rxbuff->size;
|
||||
char *buffer = rxbuff->buffer;
|
||||
|
||||
do { /* Reads chuncks of packet into user buffers */
|
||||
|
@ -121,8 +121,10 @@ PUBLIC void mem2user(dpeth_t *dep, buff_t *rxbuff)
|
|||
if (bytes > pktsize) bytes = pktsize;
|
||||
|
||||
/* Reads from Rx buffer to user area */
|
||||
sys_datacopy(SELF, (vir_bytes)buffer, iovp->iod_proc_nr,
|
||||
iovp->iod_iovec[ix].iov_addr, bytes);
|
||||
r= sys_safecopyto(iovp->iod_proc_nr, iovp->iod_iovec[ix].iov_grant, 0,
|
||||
(vir_bytes)buffer, bytes, D);
|
||||
if (r != OK)
|
||||
panic(__FILE__, "mem2user: sys_safecopyto failed", r);
|
||||
buffer += bytes;
|
||||
|
||||
if (++ix >= IOVEC_NR) { /* Next buffer of IO vector */
|
||||
|
@ -142,16 +144,18 @@ PUBLIC void user2mem(dpeth_t *dep, buff_t *txbuff)
|
|||
{
|
||||
phys_bytes phys_user;
|
||||
int bytes, ix = 0;
|
||||
iovec_dat_t *iovp = &dep->de_write_iovec;
|
||||
int pktsize = txbuff->size;
|
||||
iovec_dat_s_t *iovp = &dep->de_write_iovec;
|
||||
int r, pktsize = txbuff->size;
|
||||
char *buffer = txbuff->buffer;
|
||||
|
||||
do { /* Reads chuncks of packet from user buffers */
|
||||
|
||||
bytes = iovp->iod_iovec[ix].iov_size; /* Size of buffer */
|
||||
if (bytes > pktsize) bytes = pktsize;
|
||||
sys_datacopy(iovp->iod_proc_nr, iovp->iod_iovec[ix].iov_addr,
|
||||
SELF, (vir_bytes)buffer, bytes);
|
||||
r= sys_safecopyfrom(iovp->iod_proc_nr, iovp->iod_iovec[ix].iov_grant,
|
||||
0, (vir_bytes)buffer, bytes, D);
|
||||
if (r != OK)
|
||||
panic(__FILE__, "user2mem: sys_safecopyfrom failed", r);
|
||||
buffer += bytes;
|
||||
|
||||
if (++ix >= IOVEC_NR) { /* Next buffer of IO vector */
|
||||
|
|
|
@ -21,7 +21,7 @@ OBJ = fxp.o mii.o
|
|||
all build: $(DRIVER)
|
||||
$(DRIVER): $(OBJ)
|
||||
$(CC) -o $@ $(LDFLAGS) $(OBJ) $(LIBS)
|
||||
install -S 4096 $(DRIVER)
|
||||
install -S 8k $(DRIVER)
|
||||
|
||||
# install with other drivers
|
||||
install: /usr/sbin/$(DRIVER)
|
||||
|
|
|
@ -6,24 +6,30 @@
|
|||
*
|
||||
* The valid messages and their parameters are:
|
||||
*
|
||||
* m_type DL_PORT DL_PROC DL_COUNT DL_MODE DL_ADDR
|
||||
* |------------+----------+---------+----------+---------+---------|
|
||||
* | HARDINT | | | | | |
|
||||
* |------------|----------|---------|----------|---------|---------|
|
||||
* | DL_WRITE | port nr | proc nr | count | mode | address |
|
||||
* |------------|----------|---------|----------|---------|---------|
|
||||
* | DL_WRITEV | port nr | proc nr | count | mode | address |
|
||||
* |------------|----------|---------|----------|---------|---------|
|
||||
* | DL_READ | port nr | proc nr | count | | address |
|
||||
* |------------|----------|---------|----------|---------|---------|
|
||||
* | DL_READV | port nr | proc nr | count | | address |
|
||||
* |------------|----------|---------|----------|---------|---------|
|
||||
* | DL_INIT | port nr | proc nr | mode | | address |
|
||||
* |------------|----------|---------|----------|---------|---------|
|
||||
* | DL_GETSTAT | port nr | proc nr | | | address |
|
||||
* |------------|----------|---------|----------|---------|---------|
|
||||
* | DL_STOP | port_nr | | | | |
|
||||
* |------------|----------|---------|----------|---------|---------|
|
||||
* m_type DL_PORT DL_PROC DL_COUNT DL_MODE DL_ADDR DL_GRANT
|
||||
* |------------+----------+---------+----------+---------+---------+---------|
|
||||
* | HARDINT | | | | | | |
|
||||
* |------------|----------|---------|----------|---------|---------|---------|
|
||||
* | DL_WRITE | port nr | proc nr | count | mode | address | |
|
||||
* |------------|----------|---------|----------|---------|---------|---------|
|
||||
* | DL_WRITEV | port nr | proc nr | count | mode | address | |
|
||||
* |------------|----------|---------|----------|---------|---------|---------|
|
||||
* | DL_WRITEV_S| port nr | proc nr | count | mode | | grant |
|
||||
* |------------|----------|---------|----------|---------|---------|---------|
|
||||
* | DL_READ | port nr | proc nr | count | | address | |
|
||||
* |------------|----------|---------|----------|---------|---------|---------|
|
||||
* | DL_READV | port nr | proc nr | count | | address | |
|
||||
* |------------|----------|---------|----------|---------|---------|---------|
|
||||
* | DL_READV_S | port nr | proc nr | count | | | grant |
|
||||
* |------------|----------|---------|----------|---------|---------|---------|
|
||||
* | DL_CONF | port nr | proc nr | | mode | address | |
|
||||
* |------------|----------|---------|----------|---------|---------|---------|
|
||||
* | DL_GETSTAT | port nr | proc nr | | | address | |
|
||||
* |------------|----------|---------|----------|---------|---------|---------|
|
||||
* |DL_GETSTAT_S| port nr | proc nr | | | | grant |
|
||||
* |------------|----------|---------|----------|---------|---------|---------|
|
||||
* | DL_STOP | port_nr | | | | | |
|
||||
* |------------|----------|---------|----------|---------|---------|---------|
|
||||
*
|
||||
* The messages sent are:
|
||||
*
|
||||
|
@ -34,7 +40,7 @@
|
|||
*
|
||||
* m_type m3_i1 m3_i2 m3_ca1
|
||||
* |-------------+---------+-----------+---------------|
|
||||
* |DL_INIT_REPLY| port nr | last port | ethernet addr |
|
||||
* |DL_CONF_REPLY| port nr | last port | ethernet addr |
|
||||
* |-------------+---------+-----------+---------------|
|
||||
*
|
||||
* Created: Nov 2004 by Philip Homburg <philip@f-mnx.phicoh.com>
|
||||
|
@ -169,6 +175,7 @@ typedef struct fxp
|
|||
u8_t fxp_conf_bytes[CC_BYTES_NR];
|
||||
char fxp_name[sizeof("fxp#n")];
|
||||
iovec_t fxp_iovec[IOVEC_NR];
|
||||
iovec_s_t fxp_iovec_s[IOVEC_NR];
|
||||
}
|
||||
fxp_t;
|
||||
|
||||
|
@ -223,8 +230,10 @@ _PROTOTYPE( static void fxp_confaddr, (fxp_t *fp) );
|
|||
_PROTOTYPE( static void fxp_rec_mode, (fxp_t *fp) );
|
||||
_PROTOTYPE( static void fxp_writev, (message *mp, int from_int,
|
||||
int vectored) );
|
||||
_PROTOTYPE( static void fxp_writev_s, (message *mp, int from_int) );
|
||||
_PROTOTYPE( static void fxp_readv, (message *mp, int from_int,
|
||||
int vectored) );
|
||||
_PROTOTYPE( static void fxp_readv_s, (message *mp, int from_int) );
|
||||
_PROTOTYPE( static void fxp_do_conf, (fxp_t *fp) );
|
||||
_PROTOTYPE( static void fxp_cu_ptr_cmd, (fxp_t *fp, int cmd,
|
||||
phys_bytes bus_addr, int check_idle) );
|
||||
|
@ -232,6 +241,7 @@ _PROTOTYPE( static void fxp_ru_ptr_cmd, (fxp_t *fp, int cmd,
|
|||
phys_bytes bus_addr, int check_idle) );
|
||||
_PROTOTYPE( static void fxp_restart_ru, (fxp_t *fp) );
|
||||
_PROTOTYPE( static void fxp_getstat, (message *mp) );
|
||||
_PROTOTYPE( static void fxp_getstat_s, (message *mp) );
|
||||
_PROTOTYPE( static void fxp_getname, (message *mp) );
|
||||
_PROTOTYPE( static int fxp_handler, (fxp_t *fp) );
|
||||
_PROTOTYPE( static void fxp_check_ints, (fxp_t *fp) );
|
||||
|
@ -241,8 +251,6 @@ _PROTOTYPE( static void fxp_report_link, (fxp_t *fp) );
|
|||
_PROTOTYPE( static void fxp_stop, (void));
|
||||
_PROTOTYPE( static void reply, (fxp_t *fp, int err, int may_block) );
|
||||
_PROTOTYPE( static void mess_reply, (message *req, message *reply) );
|
||||
_PROTOTYPE( static void put_userdata, (int user_proc,
|
||||
vir_bytes user_addr, vir_bytes count, void *loc_addr) );
|
||||
_PROTOTYPE( static u16_t eeprom_read, (fxp_t *fp, int reg) );
|
||||
_PROTOTYPE( static void eeprom_addrsize, (fxp_t *fp) );
|
||||
_PROTOTYPE( static u16_t mii_read, (fxp_t *fp, int reg) );
|
||||
|
@ -298,12 +306,13 @@ int main(int argc, char *argv[])
|
|||
case DEV_PING: notify(m.m_source); continue;
|
||||
case DL_WRITEV: fxp_writev(&m, FALSE, TRUE); break;
|
||||
case DL_WRITE: fxp_writev(&m, FALSE, FALSE); break;
|
||||
#if 0
|
||||
case DL_READ: fxp_vread(&m, FALSE); break;
|
||||
#endif
|
||||
case DL_WRITEV_S: fxp_writev_s(&m, FALSE); break;
|
||||
case DL_READ: fxp_readv(&m, FALSE, FALSE); break;
|
||||
case DL_READV: fxp_readv(&m, FALSE, TRUE); break;
|
||||
case DL_INIT: fxp_init(&m); break;
|
||||
case DL_READV_S: fxp_readv_s(&m, FALSE); break;
|
||||
case DL_CONF: fxp_init(&m); break;
|
||||
case DL_GETSTAT: fxp_getstat(&m); break;
|
||||
case DL_GETSTAT_S: fxp_getstat_s(&m); break;
|
||||
case DL_GETNAME: fxp_getname(&m); break;
|
||||
case HARD_INT:
|
||||
for (i= 0, fp= &fxp_table[0]; i<FXP_PORT_NR; i++, fp++)
|
||||
|
@ -361,7 +370,7 @@ message *mp;
|
|||
port = mp->DL_PORT;
|
||||
if (port < 0 || port >= FXP_PORT_NR)
|
||||
{
|
||||
reply_mess.m_type= DL_INIT_REPLY;
|
||||
reply_mess.m_type= DL_CONF_REPLY;
|
||||
reply_mess.m3_i1= ENXIO;
|
||||
mess_reply(mp, &reply_mess);
|
||||
return;
|
||||
|
@ -374,7 +383,7 @@ message *mp;
|
|||
if (fp->fxp_mode == FM_DISABLED)
|
||||
{
|
||||
/* Probe failed, or the device is configured off. */
|
||||
reply_mess.m_type= DL_INIT_REPLY;
|
||||
reply_mess.m_type= DL_CONF_REPLY;
|
||||
reply_mess.m3_i1= ENXIO;
|
||||
mess_reply(mp, &reply_mess);
|
||||
return;
|
||||
|
@ -399,7 +408,7 @@ message *mp;
|
|||
fp->fxp_client = mp->m_source;
|
||||
fxp_rec_mode(fp);
|
||||
|
||||
reply_mess.m_type = DL_INIT_REPLY;
|
||||
reply_mess.m_type = DL_CONF_REPLY;
|
||||
reply_mess.m3_i1 = mp->DL_PORT;
|
||||
reply_mess.m3_i2 = FXP_PORT_NR;
|
||||
*(ether_addr_t *) reply_mess.m3_ca1 = fp->fxp_address;
|
||||
|
@ -1194,6 +1203,152 @@ suspend:
|
|||
reply(fp, OK, FALSE);
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* fxp_writev_s *
|
||||
*===========================================================================*/
|
||||
static void fxp_writev_s(mp, from_int)
|
||||
message *mp;
|
||||
int from_int;
|
||||
{
|
||||
cp_grant_id_t iov_grant;
|
||||
vir_bytes iov_offset;
|
||||
int i, j, n, o, r, s, dl_port, count, size, prev_head;
|
||||
int fxp_client, fxp_tx_nbuf, fxp_tx_head;
|
||||
u16_t tx_command;
|
||||
fxp_t *fp;
|
||||
iovec_s_t *iovp;
|
||||
struct tx *txp, *prev_txp;
|
||||
|
||||
dl_port = mp->DL_PORT;
|
||||
count = mp->DL_COUNT;
|
||||
if (dl_port < 0 || dl_port >= FXP_PORT_NR)
|
||||
panic("FXP","fxp_writev: illegal port", dl_port);
|
||||
fp= &fxp_table[dl_port];
|
||||
fxp_client= mp->DL_PROC;
|
||||
fp->fxp_client= fxp_client;
|
||||
|
||||
assert(fp->fxp_mode == FM_ENABLED);
|
||||
assert(fp->fxp_flags & FF_ENABLED);
|
||||
|
||||
if (from_int)
|
||||
{
|
||||
assert(fp->fxp_flags & FF_SEND_AVAIL);
|
||||
fp->fxp_flags &= ~FF_SEND_AVAIL;
|
||||
fp->fxp_tx_alive= TRUE;
|
||||
}
|
||||
|
||||
if (fp->fxp_tx_idle)
|
||||
{
|
||||
txp= fp->fxp_tx_buf;
|
||||
fxp_tx_head= 0; /* lint */
|
||||
prev_txp= NULL; /* lint */
|
||||
}
|
||||
else
|
||||
{
|
||||
fxp_tx_nbuf= fp->fxp_tx_nbuf;
|
||||
prev_head= fp->fxp_tx_head;
|
||||
fxp_tx_head= prev_head+1;
|
||||
if (fxp_tx_head == fxp_tx_nbuf)
|
||||
fxp_tx_head= 0;
|
||||
assert(fxp_tx_head < fxp_tx_nbuf);
|
||||
|
||||
if (fxp_tx_head == fp->fxp_tx_tail)
|
||||
{
|
||||
/* Send queue is full */
|
||||
assert(!(fp->fxp_flags & FF_SEND_AVAIL));
|
||||
fp->fxp_flags |= FF_SEND_AVAIL;
|
||||
goto suspend;
|
||||
}
|
||||
|
||||
prev_txp= &fp->fxp_tx_buf[prev_head];
|
||||
txp= &fp->fxp_tx_buf[fxp_tx_head];
|
||||
}
|
||||
|
||||
assert(!(fp->fxp_flags & FF_SEND_AVAIL));
|
||||
assert(!(fp->fxp_flags & FF_PACK_SENT));
|
||||
|
||||
iov_grant= mp->DL_GRANT;
|
||||
|
||||
size= 0;
|
||||
o= 0;
|
||||
iov_offset= 0;
|
||||
for (i= 0; i<count; i += IOVEC_NR,
|
||||
iov_offset += IOVEC_NR * sizeof(fp->fxp_iovec_s[0]))
|
||||
{
|
||||
n= IOVEC_NR;
|
||||
if (i+n > count)
|
||||
n= count-i;
|
||||
r= sys_safecopyfrom(fxp_client, iov_grant, iov_offset,
|
||||
(vir_bytes)fp->fxp_iovec_s,
|
||||
n * sizeof(fp->fxp_iovec_s[0]), D);
|
||||
if (r != OK)
|
||||
panic("FXP","fxp_writev: sys_safecopyfrom failed", r);
|
||||
|
||||
for (j= 0, iovp= fp->fxp_iovec_s; j<n; j++, iovp++)
|
||||
{
|
||||
s= iovp->iov_size;
|
||||
if (size + s > ETH_MAX_PACK_SIZE_TAGGED)
|
||||
{
|
||||
panic("FXP","fxp_writev: invalid packet size",
|
||||
size + s);
|
||||
}
|
||||
|
||||
r= sys_safecopyfrom(fxp_client, iovp->iov_grant,
|
||||
0, (vir_bytes)(txp->tx_buf+o), s, D);
|
||||
if (r != OK)
|
||||
{
|
||||
panic("FXP",
|
||||
"fxp_writev_s: sys_safecopyfrom failed",
|
||||
r);
|
||||
}
|
||||
size += s;
|
||||
o += s;
|
||||
}
|
||||
}
|
||||
if (size < ETH_MIN_PACK_SIZE)
|
||||
panic("FXP","fxp_writev: invalid packet size", size);
|
||||
|
||||
txp->tx_status= 0;
|
||||
txp->tx_command= TXC_EL | CBL_XMIT;
|
||||
txp->tx_tbda= TX_TBDA_NIL;
|
||||
txp->tx_size= TXSZ_EOF | size;
|
||||
txp->tx_tthresh= fp->fxp_tx_threshold;
|
||||
txp->tx_ntbd= 0;
|
||||
if (fp->fxp_tx_idle)
|
||||
{
|
||||
fp->fxp_tx_idle= 0;
|
||||
fp->fxp_tx_head= fp->fxp_tx_tail= 0;
|
||||
|
||||
fxp_cu_ptr_cmd(fp, SC_CU_START, fp->fxp_tx_busaddr,
|
||||
TRUE /* check idle */);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Link new request in transmit list */
|
||||
tx_command= prev_txp->tx_command;
|
||||
assert(tx_command == (TXC_EL | CBL_XMIT));
|
||||
prev_txp->tx_command= CBL_XMIT;
|
||||
fp->fxp_tx_head= fxp_tx_head;
|
||||
}
|
||||
|
||||
fp->fxp_flags |= FF_PACK_SENT;
|
||||
|
||||
/* If the interrupt handler called, don't send a reply. The reply
|
||||
* will be sent after all interrupts are handled.
|
||||
*/
|
||||
if (from_int)
|
||||
return;
|
||||
reply(fp, OK, FALSE);
|
||||
return;
|
||||
|
||||
suspend:
|
||||
if (from_int)
|
||||
panic("FXP","fxp: should not be sending\n", NO_NUM);
|
||||
|
||||
fp->fxp_tx_mess= *mp;
|
||||
reply(fp, OK, FALSE);
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* fxp_readv *
|
||||
*===========================================================================*/
|
||||
|
@ -1374,6 +1529,179 @@ suspend:
|
|||
reply(fp, OK, FALSE);
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* fxp_readv_s *
|
||||
*===========================================================================*/
|
||||
static void fxp_readv_s(mp, from_int)
|
||||
message *mp;
|
||||
int from_int;
|
||||
{
|
||||
int i, j, n, o, r, s, dl_port, fxp_client, count, size,
|
||||
fxp_rx_head, fxp_rx_nbuf;
|
||||
cp_grant_id_t iov_grant;
|
||||
port_t port;
|
||||
unsigned packlen;
|
||||
vir_bytes iov_offset;
|
||||
u16_t rfd_status;
|
||||
u16_t rfd_res;
|
||||
u8_t scb_status;
|
||||
fxp_t *fp;
|
||||
iovec_s_t *iovp;
|
||||
struct rfd *rfdp, *prev_rfdp;
|
||||
|
||||
dl_port = mp->DL_PORT;
|
||||
count = mp->DL_COUNT;
|
||||
if (dl_port < 0 || dl_port >= FXP_PORT_NR)
|
||||
panic("FXP","fxp_readv: illegal port", dl_port);
|
||||
fp= &fxp_table[dl_port];
|
||||
fxp_client= mp->DL_PROC;
|
||||
fp->fxp_client= fxp_client;
|
||||
|
||||
assert(fp->fxp_mode == FM_ENABLED);
|
||||
assert(fp->fxp_flags & FF_ENABLED);
|
||||
|
||||
port= fp->fxp_base_port;
|
||||
|
||||
fxp_rx_head= fp->fxp_rx_head;
|
||||
rfdp= &fp->fxp_rx_buf[fxp_rx_head];
|
||||
|
||||
rfd_status= rfdp->rfd_status;
|
||||
if (!(rfd_status & RFDS_C))
|
||||
{
|
||||
/* Receive buffer is empty, suspend */
|
||||
goto suspend;
|
||||
}
|
||||
|
||||
if (!rfd_status & RFDS_OK)
|
||||
{
|
||||
/* Not OK? What happened? */
|
||||
assert(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(!(rfd_status & (RFDS_CRCERR | RFDS_ALIGNERR |
|
||||
RFDS_OUTOFBUF | RFDS_DMAOVR | RFDS_TOOSHORT |
|
||||
RFDS_RXERR)));
|
||||
}
|
||||
rfd_res= rfdp->rfd_res;
|
||||
assert(rfd_res & RFDR_EOF);
|
||||
assert(rfd_res & RFDR_F);
|
||||
|
||||
packlen= rfd_res & RFDSZ_SIZE;
|
||||
|
||||
iov_grant = mp->DL_GRANT;
|
||||
|
||||
size= 0;
|
||||
o= 0;
|
||||
iov_offset= 0;
|
||||
for (i= 0; i<count; i += IOVEC_NR,
|
||||
iov_offset += IOVEC_NR * sizeof(fp->fxp_iovec_s[0]))
|
||||
{
|
||||
n= IOVEC_NR;
|
||||
if (i+n > count)
|
||||
n= count-i;
|
||||
r= sys_safecopyfrom(fxp_client, iov_grant, iov_offset,
|
||||
(vir_bytes)fp->fxp_iovec_s,
|
||||
n * sizeof(fp->fxp_iovec_s[0]), D);
|
||||
if (r != OK)
|
||||
panic("FXP","fxp_readv_s: sys_safecopyfrom failed", r);
|
||||
|
||||
for (j= 0, iovp= fp->fxp_iovec_s; j<n; j++, iovp++)
|
||||
{
|
||||
s= iovp->iov_size;
|
||||
if (size + s > packlen)
|
||||
{
|
||||
assert(packlen > size);
|
||||
s= packlen-size;
|
||||
}
|
||||
|
||||
r= sys_safecopyto(fxp_client, iovp->iov_grant,
|
||||
0, (vir_bytes)(rfdp->rfd_buf+o), s, D);
|
||||
if (r != OK)
|
||||
{
|
||||
panic("FXP","fxp_readv: sys_safecopyto failed",
|
||||
r);
|
||||
}
|
||||
|
||||
size += s;
|
||||
if (size == packlen)
|
||||
break;
|
||||
o += s;
|
||||
}
|
||||
if (size == packlen)
|
||||
break;
|
||||
}
|
||||
if (size < packlen)
|
||||
{
|
||||
assert(0);
|
||||
}
|
||||
|
||||
fp->fxp_read_s= packlen;
|
||||
fp->fxp_flags= (fp->fxp_flags & ~FF_READING) | FF_PACK_RECV;
|
||||
|
||||
/* Re-init the current buffer */
|
||||
rfdp->rfd_status= 0;
|
||||
rfdp->rfd_command= RFDC_EL;
|
||||
rfdp->rfd_reserved= 0;
|
||||
rfdp->rfd_res= 0;
|
||||
rfdp->rfd_size= sizeof(rfdp->rfd_buf);
|
||||
|
||||
fxp_rx_nbuf= fp->fxp_rx_nbuf;
|
||||
if (fxp_rx_head == 0)
|
||||
{
|
||||
prev_rfdp= &fp->fxp_rx_buf[fxp_rx_nbuf-1];
|
||||
}
|
||||
else
|
||||
prev_rfdp= &rfdp[-1];
|
||||
|
||||
assert(prev_rfdp->rfd_command & RFDC_EL);
|
||||
prev_rfdp->rfd_command &= ~RFDC_EL;
|
||||
|
||||
fxp_rx_head++;
|
||||
if (fxp_rx_head == fxp_rx_nbuf)
|
||||
fxp_rx_head= 0;
|
||||
assert(fxp_rx_head < fxp_rx_nbuf);
|
||||
fp->fxp_rx_head= fxp_rx_head;
|
||||
|
||||
if (!from_int)
|
||||
reply(fp, OK, FALSE);
|
||||
|
||||
return;
|
||||
|
||||
suspend:
|
||||
if (fp->fxp_rx_need_restart)
|
||||
{
|
||||
fp->fxp_rx_need_restart= 0;
|
||||
|
||||
/* Check the status of the RU */
|
||||
scb_status= fxp_inb(port, SCB_STATUS);
|
||||
if ((scb_status & SS_RUS_MASK) != SS_RU_NORES)
|
||||
{
|
||||
/* Race condition? */
|
||||
printf("fxp_readv: restart race: 0x%x\n",
|
||||
scb_status);
|
||||
assert((scb_status & SS_RUS_MASK) == SS_RU_READY);
|
||||
}
|
||||
else
|
||||
{
|
||||
fxp_restart_ru(fp);
|
||||
}
|
||||
}
|
||||
if (from_int)
|
||||
{
|
||||
assert(fp->fxp_flags & FF_READING);
|
||||
|
||||
/* No need to store any state */
|
||||
return;
|
||||
}
|
||||
|
||||
fp->fxp_rx_mess= *mp;
|
||||
assert(!(fp->fxp_flags & FF_READING));
|
||||
fp->fxp_flags |= FF_READING;
|
||||
|
||||
reply(fp, OK, FALSE);
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* fxp_do_conf *
|
||||
*===========================================================================*/
|
||||
|
@ -1529,7 +1857,7 @@ static void fxp_getstat(mp)
|
|||
message *mp;
|
||||
{
|
||||
clock_t t0,t1;
|
||||
int dl_port;
|
||||
int r, dl_port;
|
||||
port_t port;
|
||||
fxp_t *fp;
|
||||
u32_t *p;
|
||||
|
@ -1592,8 +1920,88 @@ message *mp;
|
|||
stats.ets_CDheartbeat= 0;
|
||||
stats.ets_OWC= fp->fxp_stat.sc_tx_latecol;
|
||||
|
||||
put_userdata(mp->DL_PROC, (vir_bytes) mp->DL_ADDR,
|
||||
(vir_bytes) sizeof(stats), &stats);
|
||||
r= sys_vircopy(SELF, D, (vir_bytes)&stats,
|
||||
mp->DL_PROC, D, (vir_bytes) mp->DL_ADDR, sizeof(stats));
|
||||
if (r != OK)
|
||||
panic(__FILE__,"fxp_getstat: sys_vircopy failed", r);
|
||||
reply(fp, OK, FALSE);
|
||||
}
|
||||
|
||||
|
||||
/*===========================================================================*
|
||||
* fxp_getstat_s *
|
||||
*===========================================================================*/
|
||||
static void fxp_getstat_s(mp)
|
||||
message *mp;
|
||||
{
|
||||
clock_t t0,t1;
|
||||
int r, dl_port;
|
||||
port_t port;
|
||||
fxp_t *fp;
|
||||
u32_t *p;
|
||||
eth_stat_t stats;
|
||||
|
||||
dl_port = mp->DL_PORT;
|
||||
if (dl_port < 0 || dl_port >= FXP_PORT_NR)
|
||||
panic("FXP","fxp_getstat: illegal port", dl_port);
|
||||
fp= &fxp_table[dl_port];
|
||||
fp->fxp_client= mp->DL_PROC;
|
||||
|
||||
assert(fp->fxp_mode == FM_ENABLED);
|
||||
assert(fp->fxp_flags & FF_ENABLED);
|
||||
|
||||
port= fp->fxp_base_port;
|
||||
|
||||
p= &fp->fxp_stat.sc_tx_fcp;
|
||||
*p= 0;
|
||||
|
||||
/* The dump commmand doesn't take a pointer. Setting a pointer
|
||||
* doesn't hurt though.
|
||||
*/
|
||||
fxp_cu_ptr_cmd(fp, SC_CU_DUMP_SC, 0, FALSE /* do not check idle */);
|
||||
|
||||
getuptime(&t0);
|
||||
do {
|
||||
/* Wait for CU command to complete */
|
||||
if (*p != 0)
|
||||
break;
|
||||
} while (getuptime(&t1)==OK && (t1-t0) < MICROS_TO_TICKS(1000));
|
||||
|
||||
if (*p == 0)
|
||||
panic("FXP","fxp_getstat: CU command failed to complete", NO_NUM);
|
||||
if (*p != SCM_DSC)
|
||||
panic("FXP","fxp_getstat: bad magic", NO_NUM);
|
||||
|
||||
stats.ets_recvErr=
|
||||
fp->fxp_stat.sc_rx_crc +
|
||||
fp->fxp_stat.sc_rx_align +
|
||||
fp->fxp_stat.sc_rx_resource +
|
||||
fp->fxp_stat.sc_rx_overrun +
|
||||
fp->fxp_stat.sc_rx_cd +
|
||||
fp->fxp_stat.sc_rx_short;
|
||||
stats.ets_sendErr=
|
||||
fp->fxp_stat.sc_tx_maxcol +
|
||||
fp->fxp_stat.sc_tx_latecol +
|
||||
fp->fxp_stat.sc_tx_crs;
|
||||
stats.ets_OVW= fp->fxp_stat.sc_rx_overrun;
|
||||
stats.ets_CRCerr= fp->fxp_stat.sc_rx_crc;
|
||||
stats.ets_frameAll= fp->fxp_stat.sc_rx_align;
|
||||
stats.ets_missedP= fp->fxp_stat.sc_rx_resource;
|
||||
stats.ets_packetR= fp->fxp_stat.sc_rx_good;
|
||||
stats.ets_packetT= fp->fxp_stat.sc_tx_good;
|
||||
stats.ets_transDef= fp->fxp_stat.sc_tx_defered;
|
||||
stats.ets_collision= fp->fxp_stat.sc_tx_totcol;
|
||||
stats.ets_transAb= fp->fxp_stat.sc_tx_maxcol;
|
||||
stats.ets_carrSense= fp->fxp_stat.sc_tx_crs;
|
||||
stats.ets_fifoUnder= fp->fxp_stat.sc_tx_underrun;
|
||||
stats.ets_fifoOver= fp->fxp_stat.sc_rx_overrun;
|
||||
stats.ets_CDheartbeat= 0;
|
||||
stats.ets_OWC= fp->fxp_stat.sc_tx_latecol;
|
||||
|
||||
r= sys_safecopyto(mp->DL_PROC, mp->DL_GRANT, 0, (vir_bytes)&stats,
|
||||
sizeof(stats), D);
|
||||
if (r != OK)
|
||||
panic(__FILE__,"fxp_getstat_s: sys_safecopyto failed", r);
|
||||
reply(fp, OK, FALSE);
|
||||
}
|
||||
|
||||
|
@ -1697,6 +2105,11 @@ fxp_t *fp;
|
|||
fxp_readv(&fp->fxp_rx_mess, TRUE /* from int */,
|
||||
TRUE /* vectored */);
|
||||
}
|
||||
else if (fp->fxp_rx_mess.m_type == DL_READV_S)
|
||||
{
|
||||
fxp_readv_s(&fp->fxp_rx_mess, TRUE /* from int */);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(fp->fxp_rx_mess.m_type == DL_READ);
|
||||
|
@ -1803,6 +2216,11 @@ fxp_t *fp;
|
|||
TRUE /* from int */,
|
||||
TRUE /* vectored */);
|
||||
}
|
||||
else if (fp->fxp_tx_mess.m_type == DL_WRITEV_S)
|
||||
{
|
||||
fxp_writev_s(&fp->fxp_tx_mess,
|
||||
TRUE /* from int */);
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(fp->fxp_tx_mess.m_type ==
|
||||
|
@ -2212,23 +2630,6 @@ message *reply_mess;
|
|||
panic("FXP","fxp: unable to mess_reply", NO_NUM);
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* put_userdata *
|
||||
*===========================================================================*/
|
||||
static void put_userdata(user_proc, user_addr, count, loc_addr)
|
||||
int user_proc;
|
||||
vir_bytes user_addr;
|
||||
vir_bytes count;
|
||||
void *loc_addr;
|
||||
{
|
||||
int r;
|
||||
|
||||
r= sys_vircopy(SELF, D, (vir_bytes)loc_addr,
|
||||
user_proc, D, user_addr, count);
|
||||
if (r != OK)
|
||||
panic("FXP","put_userdata: sys_vircopy failed", r);
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* eeprom_read *
|
||||
*===========================================================================*/
|
||||
|
|
|
@ -6,24 +6,30 @@
|
|||
*
|
||||
* The valid messages and their parameters are:
|
||||
*
|
||||
* m_type DL_PORT DL_PROC DL_COUNT DL_MODE DL_ADDR
|
||||
* |------------+----------+---------+----------+---------+---------|
|
||||
* | HARDINT | | | | | |
|
||||
* |------------|----------|---------|----------|---------|---------|
|
||||
* | DL_WRITE | port nr | proc nr | count | mode | address |
|
||||
* |------------|----------|---------|----------|---------|---------|
|
||||
* | DL_WRITEV | port nr | proc nr | count | mode | address |
|
||||
* |------------|----------|---------|----------|---------|---------|
|
||||
* | DL_READ | port nr | proc nr | count | | address |
|
||||
* |------------|----------|---------|----------|---------|---------|
|
||||
* | DL_READV | port nr | proc nr | count | | address |
|
||||
* |------------|----------|---------|----------|---------|---------|
|
||||
* | DL_INIT | port nr | proc nr | mode | | address |
|
||||
* |------------|----------|---------|----------|---------|---------|
|
||||
* | DL_GETSTAT | port nr | proc nr | | | address |
|
||||
* |------------|----------|---------|----------|---------|---------|
|
||||
* | DL_STOP | port_nr | | | | |
|
||||
* |------------|----------|---------|----------|---------|---------|
|
||||
* m_type DL_PORT DL_PROC DL_COUNT DL_MODE DL_ADDR DL_GRANT
|
||||
* |------------+----------+---------+----------+---------+---------+---------|
|
||||
* | HARDINT | | | | | | |
|
||||
* |------------|----------|---------|----------|---------|---------|---------|
|
||||
* | DL_WRITE | port nr | proc nr | count | mode | address | |
|
||||
* |------------|----------|---------|----------|---------|---------|---------|
|
||||
* | DL_WRITEV | port nr | proc nr | count | mode | address | |
|
||||
* |------------|----------|---------|----------|---------|---------|---------|
|
||||
* | DL_WRITEV_S| port nr | proc nr | count | mode | | grant |
|
||||
* |------------|----------|---------|----------|---------|---------|---------|
|
||||
* | DL_READ | port nr | proc nr | count | | address | |
|
||||
* |------------|----------|---------|----------|---------|---------|---------|
|
||||
* | DL_READV | port nr | proc nr | count | | address | |
|
||||
* |------------|----------|---------|----------|---------|---------|---------|
|
||||
* | DL_READV_S | port nr | proc nr | count | | | grant |
|
||||
* |------------|----------|---------|----------|---------|---------|---------|
|
||||
* | DL_CONF | port nr | proc nr | | mode | address | |
|
||||
* |------------|----------|---------|----------|---------|---------|---------|
|
||||
* | DL_GETSTAT | port nr | proc nr | | | address | |
|
||||
* |------------|----------|---------|----------|---------|---------|---------|
|
||||
* |DL_GETSTAT_S| port nr | proc nr | | | | grant |
|
||||
* |------------|----------|---------|----------|---------|---------|---------|
|
||||
* | DL_STOP | port_nr | | | | | |
|
||||
* |------------|----------|---------|----------|---------|---------|---------|
|
||||
*
|
||||
* The messages sent are:
|
||||
*
|
||||
|
@ -34,7 +40,7 @@
|
|||
*
|
||||
* m_type m3_i1 m3_i2 m3_ca1
|
||||
* |------------+---------+-----------+---------------|
|
||||
* |DL_INIT_REPL| port nr | last port | ethernet addr |
|
||||
* |DL_CONF_REPL| port nr | last port | ethernet addr |
|
||||
* |------------|---------|-----------|---------------|
|
||||
*
|
||||
* Created: Jul 27, 2002 by Kazuya Kodama <kazuya@nii.ac.jp>
|
||||
|
@ -144,11 +150,11 @@ _PROTOTYPE( static void reply,
|
|||
_PROTOTYPE( static void ec_reset, (ether_card_t *ec) );
|
||||
_PROTOTYPE( static void ec_send, (ether_card_t *ec) );
|
||||
_PROTOTYPE( static void ec_recv, (ether_card_t *ec) );
|
||||
_PROTOTYPE( static void do_vwrite,
|
||||
(message *mp, int from_int, int vectored) );
|
||||
_PROTOTYPE( static void do_vread, (message *mp, int vectored) );
|
||||
_PROTOTYPE( static void get_userdata,
|
||||
(int user_proc, vir_bytes user_addr,
|
||||
_PROTOTYPE( static void do_vwrite_s,
|
||||
(message *mp, int from_int) );
|
||||
_PROTOTYPE( static void do_vread_s, (message *mp) );
|
||||
_PROTOTYPE( static void get_userdata_s,
|
||||
(int user_proc, cp_grant_id_t grant, vir_bytes offset,
|
||||
vir_bytes count, void *loc_addr) );
|
||||
_PROTOTYPE( static void ec_user2nic,
|
||||
(ether_card_t *dep, iovec_dat_t *iovp,
|
||||
|
@ -160,11 +166,10 @@ _PROTOTYPE( static void ec_nic2user,
|
|||
vir_bytes count) );
|
||||
_PROTOTYPE( static int calc_iovec_size, (iovec_dat_t *iovp) );
|
||||
_PROTOTYPE( static void ec_next_iovec, (iovec_dat_t *iovp) );
|
||||
_PROTOTYPE( static void do_getstat, (message *mp) );
|
||||
_PROTOTYPE( static void put_userdata,
|
||||
(int user_proc,
|
||||
vir_bytes user_addr, vir_bytes count,
|
||||
void *loc_addr) );
|
||||
_PROTOTYPE( static void do_getstat_s, (message *mp) );
|
||||
_PROTOTYPE( static void put_userdata_s,
|
||||
(int user_proc, cp_grant_id_t grant,
|
||||
void *loc_addr, vir_bytes count) );
|
||||
_PROTOTYPE( static void do_stop, (message *mp) );
|
||||
_PROTOTYPE( static void do_getname, (message *mp) );
|
||||
|
||||
|
@ -356,14 +361,12 @@ void main( int argc, char **argv )
|
|||
|
||||
switch (m.m_type){
|
||||
case DEV_PING: notify(m.m_source); continue;
|
||||
case DL_WRITE: do_vwrite(&m, FALSE, FALSE); break;
|
||||
case DL_WRITEV: do_vwrite(&m, FALSE, TRUE); break;
|
||||
case DL_READ: do_vread(&m, FALSE); break;
|
||||
case DL_READV: do_vread(&m, TRUE); break;
|
||||
case DL_INIT: do_init(&m); break;
|
||||
case DL_GETSTAT: do_getstat(&m); break;
|
||||
case DL_WRITEV_S: do_vwrite_s(&m, FALSE); break;
|
||||
case DL_READV_S: do_vread_s(&m); break;
|
||||
case DL_CONF: do_init(&m); break;
|
||||
case DL_GETSTAT_S: do_getstat_s(&m); break;
|
||||
case DL_STOP: do_stop(&m); break;
|
||||
case DL_GETNAME: do_getname(&m); break;
|
||||
case DL_GETNAME: do_getname(&m); break;
|
||||
case FKEY_PRESSED: lance_dump(); break;
|
||||
/*case HARD_STOP: lance_stop(); break;*/
|
||||
case SYS_SIG:
|
||||
|
@ -493,7 +496,7 @@ pci_init();
|
|||
port = mp->DL_PORT;
|
||||
if (port < 0 || port >= EC_PORT_NR_MAX)
|
||||
{
|
||||
reply_mess.m_type= DL_INIT_REPLY;
|
||||
reply_mess.m_type= DL_CONF_REPLY;
|
||||
reply_mess.m3_i1= ENXIO;
|
||||
mess_reply(mp, &reply_mess);
|
||||
return;
|
||||
|
@ -517,7 +520,7 @@ pci_init();
|
|||
if (ec->mode == EC_DISABLED)
|
||||
{
|
||||
/* Probe failed, or the device is configured off. */
|
||||
reply_mess.m_type= DL_INIT_REPLY;
|
||||
reply_mess.m_type= DL_CONF_REPLY;
|
||||
reply_mess.m3_i1= ENXIO;
|
||||
mess_reply(mp, &reply_mess);
|
||||
return;
|
||||
|
@ -535,7 +538,7 @@ pci_init();
|
|||
ec->mac_address.ea_addr[4] =
|
||||
ec->mac_address.ea_addr[5] = 0;
|
||||
ec_confaddr(ec);
|
||||
reply_mess.m_type = DL_INIT_REPLY;
|
||||
reply_mess.m_type = DL_CONF_REPLY;
|
||||
reply_mess.m3_i1 = mp->DL_PORT;
|
||||
reply_mess.m3_i2 = EC_PORT_NR_MAX;
|
||||
*(ether_addr_t *) reply_mess.m3_ca1 = ec->mac_address;
|
||||
|
@ -557,7 +560,7 @@ pci_init();
|
|||
ec->client = mp->m_source;
|
||||
ec_reinit(ec);
|
||||
|
||||
reply_mess.m_type = DL_INIT_REPLY;
|
||||
reply_mess.m_type = DL_CONF_REPLY;
|
||||
reply_mess.m3_i1 = mp->DL_PORT;
|
||||
reply_mess.m3_i2 = EC_PORT_NR_MAX;
|
||||
*(ether_addr_t *) reply_mess.m3_ca1 = ec->mac_address;
|
||||
|
@ -1071,8 +1074,7 @@ ether_card_t *ec;
|
|||
ec->flags &= ~ECF_SEND_AVAIL;
|
||||
switch(ec->sendmsg.m_type)
|
||||
{
|
||||
case DL_WRITE: do_vwrite(&ec->sendmsg, TRUE, FALSE); break;
|
||||
case DL_WRITEV: do_vwrite(&ec->sendmsg, TRUE, TRUE); break;
|
||||
case DL_WRITEV_S: do_vwrite_s(&ec->sendmsg, TRUE); break;
|
||||
default:
|
||||
panic( "lance", "wrong type:", ec->sendmsg.m_type);
|
||||
break;
|
||||
|
@ -1080,11 +1082,10 @@ ether_card_t *ec;
|
|||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* do_vread *
|
||||
* do_vread_s *
|
||||
*===========================================================================*/
|
||||
static void do_vread(mp, vectored)
|
||||
static void do_vread_s(mp)
|
||||
message *mp;
|
||||
int vectored;
|
||||
{
|
||||
int port, count, size;
|
||||
ether_card_t *ec;
|
||||
|
@ -1094,28 +1095,17 @@ int vectored;
|
|||
ec= &ec_table[port];
|
||||
ec->client= mp->DL_PROC;
|
||||
|
||||
if (vectored)
|
||||
{
|
||||
get_userdata(mp->DL_PROC, (vir_bytes) mp->DL_ADDR,
|
||||
(count > IOVEC_NR ? IOVEC_NR : count) *
|
||||
sizeof(iovec_t), ec->read_iovec.iod_iovec);
|
||||
ec->read_iovec.iod_iovec_s = count;
|
||||
ec->read_iovec.iod_proc_nr = mp->DL_PROC;
|
||||
ec->read_iovec.iod_iovec_addr = (vir_bytes) mp->DL_ADDR;
|
||||
|
||||
ec->tmp_iovec = ec->read_iovec;
|
||||
size= calc_iovec_size(&ec->tmp_iovec);
|
||||
}
|
||||
else
|
||||
{
|
||||
ec->read_iovec.iod_iovec[0].iov_addr = (vir_bytes) mp->DL_ADDR;
|
||||
ec->read_iovec.iod_iovec[0].iov_size = mp->DL_COUNT;
|
||||
ec->read_iovec.iod_iovec_s = 1;
|
||||
ec->read_iovec.iod_proc_nr = mp->DL_PROC;
|
||||
ec->read_iovec.iod_iovec_addr = 0;
|
||||
get_userdata_s(mp->DL_PROC, (vir_bytes) mp->DL_GRANT, 0,
|
||||
(count > IOVEC_NR ? IOVEC_NR : count) *
|
||||
sizeof(iovec_s_t), ec->read_iovec.iod_iovec);
|
||||
ec->read_iovec.iod_iovec_s = count;
|
||||
ec->read_iovec.iod_proc_nr = mp->DL_PROC;
|
||||
ec->read_iovec.iod_grant = (vir_bytes) mp->DL_GRANT;
|
||||
ec->read_iovec.iod_iovec_offset = 0;
|
||||
|
||||
ec->tmp_iovec = ec->read_iovec;
|
||||
size= calc_iovec_size(&ec->tmp_iovec);
|
||||
|
||||
size= count;
|
||||
}
|
||||
ec->flags |= ECF_READING;
|
||||
|
||||
ec_recv(ec);
|
||||
|
@ -1195,12 +1185,11 @@ ether_card_t *ec;
|
|||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* do_vwrite *
|
||||
* do_vwrite_s *
|
||||
*===========================================================================*/
|
||||
static void do_vwrite(mp, from_int, vectored)
|
||||
static void do_vwrite_s(mp, from_int)
|
||||
message *mp;
|
||||
int from_int;
|
||||
int vectored;
|
||||
{
|
||||
int port, count, check;
|
||||
ether_card_t *ec;
|
||||
|
@ -1221,30 +1210,17 @@ int vectored;
|
|||
}
|
||||
|
||||
/* convert the message to write_iovec */
|
||||
if (vectored)
|
||||
{
|
||||
get_userdata(mp->DL_PROC, (vir_bytes) mp->DL_ADDR,
|
||||
(count > IOVEC_NR ? IOVEC_NR : count) *
|
||||
sizeof(iovec_t), ec->write_iovec.iod_iovec);
|
||||
get_userdata_s(mp->DL_PROC, mp->DL_GRANT, 0,
|
||||
(count > IOVEC_NR ? IOVEC_NR : count) *
|
||||
sizeof(iovec_s_t), ec->write_iovec.iod_iovec);
|
||||
|
||||
ec->write_iovec.iod_iovec_s = count;
|
||||
ec->write_iovec.iod_proc_nr = mp->DL_PROC;
|
||||
ec->write_iovec.iod_iovec_addr = (vir_bytes) mp->DL_ADDR;
|
||||
ec->write_iovec.iod_iovec_s = count;
|
||||
ec->write_iovec.iod_proc_nr = mp->DL_PROC;
|
||||
ec->write_iovec.iod_grant = mp->DL_GRANT;
|
||||
ec->write_iovec.iod_iovec_offset = 0;
|
||||
|
||||
ec->tmp_iovec = ec->write_iovec;
|
||||
ec->write_s = calc_iovec_size(&ec->tmp_iovec);
|
||||
}
|
||||
else
|
||||
{
|
||||
ec->write_iovec.iod_iovec[0].iov_addr = (vir_bytes) mp->DL_ADDR;
|
||||
ec->write_iovec.iod_iovec[0].iov_size = mp->DL_COUNT;
|
||||
|
||||
ec->write_iovec.iod_iovec_s = 1;
|
||||
ec->write_iovec.iod_proc_nr = mp->DL_PROC;
|
||||
ec->write_iovec.iod_iovec_addr = 0;
|
||||
|
||||
ec->write_s = mp->DL_COUNT;
|
||||
}
|
||||
ec->tmp_iovec = ec->write_iovec;
|
||||
ec->write_s = calc_iovec_size(&ec->tmp_iovec);
|
||||
|
||||
/* copy write_iovec to the slot on DMA address */
|
||||
ec_user2nic(ec, &ec->write_iovec, 0,
|
||||
|
@ -1279,26 +1255,21 @@ int vectored;
|
|||
|
||||
|
||||
/*===========================================================================*
|
||||
* get_userdata *
|
||||
* get_userdata_s *
|
||||
*===========================================================================*/
|
||||
static void get_userdata(user_proc, user_addr, count, loc_addr)
|
||||
static void get_userdata_s(user_proc, grant, offset, count, loc_addr)
|
||||
int user_proc;
|
||||
vir_bytes user_addr;
|
||||
cp_grant_id_t grant;
|
||||
vir_bytes offset;
|
||||
vir_bytes count;
|
||||
void *loc_addr;
|
||||
{
|
||||
/*
|
||||
phys_bytes src;
|
||||
|
||||
src = numap_local(user_proc, user_addr, count);
|
||||
if (!src)
|
||||
panic( "lance", "umap failed", NO_NUM);
|
||||
|
||||
phys_copy(src, vir2phys(loc_addr), (phys_bytes) count);
|
||||
*/
|
||||
int cps;
|
||||
cps = sys_datacopy(user_proc, user_addr, SELF, (vir_bytes) loc_addr, count);
|
||||
if (cps != OK) printf("lance: warning, scopy failed: %d\n", cps);
|
||||
cps = sys_safecopyfrom(user_proc, grant, offset,
|
||||
(vir_bytes)loc_addr, count, D);
|
||||
if (cps != OK)
|
||||
panic(__FILE__,
|
||||
"get_userdata_s: sys_safecopyfrom failed: %d\n", cps);
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
|
@ -1311,12 +1282,8 @@ vir_bytes offset;
|
|||
int nic_addr;
|
||||
vir_bytes count;
|
||||
{
|
||||
/*phys_bytes phys_hw, phys_user;*/
|
||||
int bytes, i, r;
|
||||
|
||||
/*
|
||||
phys_hw = vir2phys(nic_addr);
|
||||
*/
|
||||
i= 0;
|
||||
while (count > 0)
|
||||
{
|
||||
|
@ -1336,15 +1303,10 @@ vir_bytes count;
|
|||
if (bytes > count)
|
||||
bytes = count;
|
||||
|
||||
/*
|
||||
phys_user = numap_local(iovp->iod_proc_nr,
|
||||
iovp->iod_iovec[i].iov_addr + offset, bytes);
|
||||
|
||||
phys_copy(phys_user, phys_hw, (phys_bytes) bytes);
|
||||
*/
|
||||
if ( (r=sys_datacopy(iovp->iod_proc_nr, iovp->iod_iovec[i].iov_addr + offset,
|
||||
SELF, nic_addr, count )) != OK )
|
||||
panic( "lance", "sys_datacopy failed", r );
|
||||
if ( (r=sys_safecopyfrom(iovp->iod_proc_nr,
|
||||
iovp->iod_iovec[i].iov_grant, offset,
|
||||
nic_addr, bytes, D )) != OK )
|
||||
panic( __FILE__, "ec_user2nic: sys_safecopyfrom failed", r );
|
||||
|
||||
count -= bytes;
|
||||
nic_addr += bytes;
|
||||
|
@ -1362,11 +1324,8 @@ iovec_dat_t *iovp;
|
|||
vir_bytes offset;
|
||||
vir_bytes count;
|
||||
{
|
||||
/*phys_bytes phys_hw, phys_user;*/
|
||||
int bytes, i, r;
|
||||
|
||||
/*phys_hw = vir2phys(nic_addr);*/
|
||||
|
||||
i= 0;
|
||||
while (count > 0)
|
||||
{
|
||||
|
@ -1385,14 +1344,9 @@ vir_bytes count;
|
|||
bytes = iovp->iod_iovec[i].iov_size - offset;
|
||||
if (bytes > count)
|
||||
bytes = count;
|
||||
/*
|
||||
phys_user = numap_local(iovp->iod_proc_nr,
|
||||
iovp->iod_iovec[i].iov_addr + offset, bytes);
|
||||
|
||||
phys_copy(phys_hw, phys_user, (phys_bytes) bytes);
|
||||
*/
|
||||
if ( (r=sys_datacopy( SELF, nic_addr, iovp->iod_proc_nr, iovp->iod_iovec[i].iov_addr + offset, bytes )) != OK )
|
||||
panic( "lance", "sys_datacopy failed: ", r );
|
||||
if ( (r=sys_safecopyto( iovp->iod_proc_nr, iovp->iod_iovec[i].iov_grant,
|
||||
offset, nic_addr, bytes, D )) != OK )
|
||||
panic( __FILE__, "ec_nic2user: sys_safecopyto failed: ", r );
|
||||
|
||||
count -= bytes;
|
||||
nic_addr += bytes;
|
||||
|
@ -1433,19 +1387,20 @@ static void ec_next_iovec(iovp)
|
|||
iovec_dat_t *iovp;
|
||||
{
|
||||
iovp->iod_iovec_s -= IOVEC_NR;
|
||||
iovp->iod_iovec_addr += IOVEC_NR * sizeof(iovec_t);
|
||||
iovp->iod_iovec_offset += IOVEC_NR * sizeof(iovec_s_t);
|
||||
|
||||
get_userdata(iovp->iod_proc_nr, iovp->iod_iovec_addr,
|
||||
get_userdata_s(iovp->iod_proc_nr, iovp->iod_grant,
|
||||
iovp->iod_iovec_offset,
|
||||
(iovp->iod_iovec_s > IOVEC_NR ?
|
||||
IOVEC_NR : iovp->iod_iovec_s) * sizeof(iovec_t),
|
||||
IOVEC_NR : iovp->iod_iovec_s) * sizeof(iovec_s_t),
|
||||
iovp->iod_iovec);
|
||||
}
|
||||
|
||||
|
||||
/*===========================================================================*
|
||||
* do_getstat *
|
||||
* do_getstat_s *
|
||||
*===========================================================================*/
|
||||
static void do_getstat(mp)
|
||||
static void do_getstat_s(mp)
|
||||
message *mp;
|
||||
{
|
||||
int port;
|
||||
|
@ -1458,31 +1413,26 @@ message *mp;
|
|||
ec= &ec_table[port];
|
||||
ec->client= mp->DL_PROC;
|
||||
|
||||
put_userdata(mp->DL_PROC, (vir_bytes) mp->DL_ADDR,
|
||||
(vir_bytes) sizeof(ec->eth_stat), &ec->eth_stat);
|
||||
put_userdata_s(mp->DL_PROC, mp->DL_GRANT,
|
||||
&ec->eth_stat, sizeof(ec->eth_stat));
|
||||
reply(ec, OK, FALSE);
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* put_userdata *
|
||||
* put_userdata_s *
|
||||
*===========================================================================*/
|
||||
static void put_userdata(user_proc, user_addr, count, loc_addr)
|
||||
static void put_userdata_s(user_proc, grant, loc_addr, count)
|
||||
int user_proc;
|
||||
vir_bytes user_addr;
|
||||
vir_bytes count;
|
||||
cp_grant_id_t grant;
|
||||
void *loc_addr;
|
||||
vir_bytes count;
|
||||
{
|
||||
/*phys_bytes dst;
|
||||
|
||||
dst = numap_local(user_proc, user_addr, count);
|
||||
if (!dst)
|
||||
panic( "lance", "umap failed", NO_NUM);
|
||||
|
||||
phys_copy(vir2phys(loc_addr), dst, (phys_bytes) count);
|
||||
*/
|
||||
int cps;
|
||||
cps = sys_datacopy(SELF, (vir_bytes) loc_addr, user_proc, user_addr, count);
|
||||
if (cps != OK) printf("lance: warning, scopy failed: %d\n", cps);
|
||||
cps = sys_safecopyto(user_proc, grant, 0,
|
||||
(vir_bytes) loc_addr, count, D);
|
||||
if (cps != OK)
|
||||
panic(__FILE__,
|
||||
"put_userdata_s: sys_safecopyto failed: %d\n", cps);
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
|
|
|
@ -53,10 +53,11 @@
|
|||
#define IOVEC_NR 16
|
||||
typedef struct iovec_dat
|
||||
{
|
||||
iovec_t iod_iovec[IOVEC_NR];
|
||||
iovec_s_t iod_iovec[IOVEC_NR];
|
||||
int iod_iovec_s;
|
||||
int iod_proc_nr;
|
||||
vir_bytes iod_iovec_addr;
|
||||
cp_grant_id_t iod_grant;
|
||||
vir_bytes iod_iovec_offset;
|
||||
} iovec_dat_t;
|
||||
|
||||
#define ETH0_SELECTOR 0x61
|
||||
|
|
|
@ -6,26 +6,30 @@
|
|||
*
|
||||
* The valid messages and their parameters are:
|
||||
*
|
||||
* m_type DL_PORT DL_PROC DL_COUNT DL_MODE DL_ADDR
|
||||
* |------------+----------+---------+----------+---------+---------|
|
||||
* | HARD_INT | | | | | |
|
||||
* |------------|----------|---------|----------|---------|---------|
|
||||
* | DL_WRITE | port nr | proc nr | count | mode | address |
|
||||
* |------------|----------|---------|----------|---------|---------|
|
||||
* | DL_WRITEV | port nr | proc nr | count | mode | address |
|
||||
* |------------|----------|---------|----------|---------|---------|
|
||||
* | DL_READ | port nr | proc nr | count | | address |
|
||||
* |------------|----------|---------|----------|---------|---------|
|
||||
* | DL_READV | port nr | proc nr | count | | address |
|
||||
* |------------|----------|---------|----------|---------|---------|
|
||||
* | DL_INIT | port nr | proc nr | mode | | address |
|
||||
* |------------|----------|---------|----------|---------|---------|
|
||||
* | DL_GETSTAT | port nr | proc nr | | | address |
|
||||
* |------------|----------|---------|----------|---------|---------|
|
||||
* | DL_GETNAME | | | | | |
|
||||
* |------------|----------|---------|----------|---------|---------|
|
||||
* | DL_STOP | port_nr | | | | |
|
||||
* |------------|----------|---------|----------|---------|---------|
|
||||
* m_type DL_PORT DL_PROC DL_COUNT DL_MODE DL_ADDR DL_GRANT
|
||||
* |------------+----------+---------+----------+---------+---------+---------|
|
||||
* | HARDINT | | | | | | |
|
||||
* |------------|----------|---------|----------|---------|---------|---------|
|
||||
* | DL_WRITE | port nr | proc nr | count | mode | address | |
|
||||
* |------------|----------|---------|----------|---------|---------|---------|
|
||||
* | DL_WRITEV | port nr | proc nr | count | mode | address | |
|
||||
* |------------|----------|---------|----------|---------|---------|---------|
|
||||
* | DL_WRITEV_S| port nr | proc nr | count | mode | | grant |
|
||||
* |------------|----------|---------|----------|---------|---------|---------|
|
||||
* | DL_READ | port nr | proc nr | count | | address | |
|
||||
* |------------|----------|---------|----------|---------|---------|---------|
|
||||
* | DL_READV | port nr | proc nr | count | | address | |
|
||||
* |------------|----------|---------|----------|---------|---------|---------|
|
||||
* | DL_READV_S | port nr | proc nr | count | | | grant |
|
||||
* |------------|----------|---------|----------|---------|---------|---------|
|
||||
* | DL_CONF | port nr | proc nr | | mode | address | |
|
||||
* |------------|----------|---------|----------|---------|---------|---------|
|
||||
* | DL_GETSTAT | port nr | proc nr | | | address | |
|
||||
* |------------|----------|---------|----------|---------|---------|---------|
|
||||
* |DL_GETSTAT_S| port nr | proc nr | | | | grant |
|
||||
* |------------|----------|---------|----------|---------|---------|---------|
|
||||
* | DL_STOP | port_nr | | | | | |
|
||||
* |------------|----------|---------|----------|---------|---------|---------|
|
||||
*
|
||||
* The messages sent are:
|
||||
*
|
||||
|
@ -36,7 +40,7 @@
|
|||
*
|
||||
* m_type m3_i1 m3_i2 m3_ca1
|
||||
* |------------+---------+-----------+---------------|
|
||||
* |DL_INIT_REPL| port nr | last port | ethernet addr |
|
||||
* |DL_CONF_REPL| port nr | last port | ethernet addr |
|
||||
* |------------|---------|-----------|---------------|
|
||||
*
|
||||
* Created: Aug 2003 by Philip Homburg <philip@cs.vu.nl>
|
||||
|
@ -155,6 +159,7 @@ typedef struct re
|
|||
message re_tx_mess;
|
||||
char re_name[sizeof("rtl8139#n")];
|
||||
iovec_t re_iovec[IOVEC_NR];
|
||||
iovec_s_t re_iovec_s[IOVEC_NR];
|
||||
}
|
||||
re_t;
|
||||
|
||||
|
@ -238,8 +243,10 @@ _PROTOTYPE( static void rl_confaddr, (re_t *rep) );
|
|||
_PROTOTYPE( static void rl_rec_mode, (re_t *rep) );
|
||||
_PROTOTYPE( static void rl_readv, (message *mp, int from_int,
|
||||
int vectored) );
|
||||
_PROTOTYPE( static void rl_readv_s, (message *mp, int from_int) );
|
||||
_PROTOTYPE( static void rl_writev, (message *mp, int from_int,
|
||||
int vectored) );
|
||||
_PROTOTYPE( static void rl_writev_s, (message *mp, int from_int) );
|
||||
_PROTOTYPE( static void rl_check_ints, (re_t *rep) );
|
||||
_PROTOTYPE( static void rl_report_link, (re_t *rep) );
|
||||
_PROTOTYPE( static void mii_print_techab, (U16_t techab) );
|
||||
|
@ -248,11 +255,10 @@ _PROTOTYPE( static void mii_print_stat_speed, (U16_t stat,
|
|||
_PROTOTYPE( static void rl_clear_rx, (re_t *rep) );
|
||||
_PROTOTYPE( static void rl_do_reset, (re_t *rep) );
|
||||
_PROTOTYPE( static void rl_getstat, (message *mp) );
|
||||
_PROTOTYPE( static void rl_getstat_s, (message *mp) );
|
||||
_PROTOTYPE( static void rl_getname, (message *mp) );
|
||||
_PROTOTYPE( static void reply, (re_t *rep, int err, int may_block) );
|
||||
_PROTOTYPE( static void mess_reply, (message *req, message *reply) );
|
||||
_PROTOTYPE( static void put_userdata, (int user_proc,
|
||||
vir_bytes user_addr, vir_bytes count, void *loc_addr) );
|
||||
_PROTOTYPE( static void rtl8139_stop, (void) );
|
||||
_PROTOTYPE( static void check_int_events, (void) );
|
||||
_PROTOTYPE( static int do_hard_int, (void) );
|
||||
|
@ -314,15 +320,16 @@ int main(int argc, char *argv[])
|
|||
|
||||
switch (m.m_type)
|
||||
{
|
||||
case DEV_PING: notify(m.m_source); continue;
|
||||
case DL_WRITEV: rl_writev(&m, FALSE, TRUE); break;
|
||||
case DEV_PING: notify(m.m_source); break;
|
||||
case DL_WRITE: rl_writev(&m, FALSE, FALSE); break;
|
||||
#if 0
|
||||
case DL_READ: do_vread(&m, FALSE); break;
|
||||
#endif
|
||||
case DL_WRITEV: rl_writev(&m, FALSE, TRUE); break;
|
||||
case DL_WRITEV_S: rl_writev_s(&m, FALSE); break;
|
||||
case DL_READ: rl_readv(&m, FALSE, FALSE); break;
|
||||
case DL_READV: rl_readv(&m, FALSE, TRUE); break;
|
||||
case DL_INIT: rl_init(&m); break;
|
||||
case DL_READV_S: rl_readv_s(&m, FALSE); break;
|
||||
case DL_CONF: rl_init(&m); break;
|
||||
case DL_GETSTAT: rl_getstat(&m); break;
|
||||
case DL_GETSTAT_S: rl_getstat_s(&m); break;
|
||||
case DL_GETNAME: rl_getname(&m); break;
|
||||
#if 0
|
||||
case DL_STOP: do_stop(&m); break;
|
||||
|
@ -490,7 +497,7 @@ message *mp;
|
|||
port = mp->DL_PORT;
|
||||
if (port < 0 || port >= RE_PORT_NR)
|
||||
{
|
||||
reply_mess.m_type= DL_INIT_REPLY;
|
||||
reply_mess.m_type= DL_CONF_REPLY;
|
||||
reply_mess.m3_i1= ENXIO;
|
||||
mess_reply(mp, &reply_mess);
|
||||
return;
|
||||
|
@ -503,7 +510,7 @@ message *mp;
|
|||
if (rep->re_mode == REM_DISABLED)
|
||||
{
|
||||
/* Probe failed, or the device is configured off. */
|
||||
reply_mess.m_type= DL_INIT_REPLY;
|
||||
reply_mess.m_type= DL_CONF_REPLY;
|
||||
reply_mess.m3_i1= ENXIO;
|
||||
mess_reply(mp, &reply_mess);
|
||||
return;
|
||||
|
@ -530,7 +537,7 @@ message *mp;
|
|||
rep->re_client = mp->m_source;
|
||||
rl_rec_mode(rep);
|
||||
|
||||
reply_mess.m_type = DL_INIT_REPLY;
|
||||
reply_mess.m_type = DL_CONF_REPLY;
|
||||
reply_mess.m3_i1 = mp->DL_PORT;
|
||||
reply_mess.m3_i2 = RE_PORT_NR;
|
||||
*(ether_addr_t *) reply_mess.m3_ca1 = rep->re_address;
|
||||
|
@ -1058,14 +1065,6 @@ int vectored;
|
|||
|
||||
rxstat = *(u32_t *) (rep->v_re_rx_buf + d_start);
|
||||
|
||||
#if DEAD_CODE
|
||||
src_phys= rep->re_rx_buf + d_start;
|
||||
cps = sys_physcopy(
|
||||
NONE, PHYS_SEG, src_phys,
|
||||
SELF, D, (vir_bytes) &rxstat, sizeof(rxstat));
|
||||
if (cps != OK) printf("RTL8139: warning, sys_abscopy failed: %d\n", cps);
|
||||
#endif
|
||||
|
||||
if (rep->re_clear_rx)
|
||||
{
|
||||
#if 0
|
||||
|
@ -1113,11 +1112,6 @@ int vectored;
|
|||
if (vectored)
|
||||
{
|
||||
int iov_offset = 0;
|
||||
#if 0
|
||||
if ((cps = sys_umap(re_client, D, (vir_bytes) mp->DL_ADDR,
|
||||
count * sizeof(rep->re_iovec[0]), &iov_src)) != OK)
|
||||
printf("sys_umap failed: %d\n", cps);
|
||||
#endif
|
||||
|
||||
size= 0;
|
||||
o= d_start+4;
|
||||
|
@ -1129,15 +1123,15 @@ int vectored;
|
|||
n= IOVEC_NR;
|
||||
if (i+n > count)
|
||||
n= count-i;
|
||||
#if 0
|
||||
cps = sys_physcopy(NONE, PHYS_SEG, iov_src, SELF, D, (vir_bytes) rep->re_iovec,
|
||||
|
||||
cps = sys_vircopy(re_client, D,
|
||||
(vir_bytes) mp->DL_ADDR + iov_offset,
|
||||
SELF, D, (vir_bytes) rep->re_iovec,
|
||||
n * sizeof(rep->re_iovec[0]));
|
||||
if (cps != OK) printf("RTL8139: warning, sys_abscopy failed: %d\n", cps);
|
||||
#else
|
||||
cps = sys_vircopy(re_client, D, (vir_bytes) mp->DL_ADDR + iov_offset,
|
||||
SELF, D, (vir_bytes) rep->re_iovec, n * sizeof(rep->re_iovec[0]));
|
||||
if (cps != OK) printf("RTL8139: warning, sys_vircopy failed: %d (%d)\n", cps, __LINE__);
|
||||
#endif
|
||||
if (cps != OK)
|
||||
printf(
|
||||
"RTL8139: warning, sys_vircopy failed: %d (%d)\n",
|
||||
cps, __LINE__);
|
||||
|
||||
for (j= 0, iovp= rep->re_iovec; j<n; j++, iovp++)
|
||||
{
|
||||
|
@ -1148,11 +1142,6 @@ int vectored;
|
|||
s= packlen-size;
|
||||
}
|
||||
|
||||
#if 0
|
||||
if (sys_umap(re_client, D, iovp->iov_addr, s, &dst_phys) != OK)
|
||||
panic("rtl8139","umap_local failed\n", NO_NUM);
|
||||
#endif
|
||||
|
||||
if (o >= RX_BUFSIZE)
|
||||
{
|
||||
o -= RX_BUFSIZE;
|
||||
|
@ -1164,30 +1153,33 @@ int vectored;
|
|||
assert(o<RX_BUFSIZE);
|
||||
s1= RX_BUFSIZE-o;
|
||||
|
||||
#if 0
|
||||
cps = sys_abscopy(src_phys+o, dst_phys, s1);
|
||||
if (cps != OK) printf("RTL8139: warning, sys_abscopy failed: %d\n", cps);
|
||||
cps = sys_abscopy(src_phys, dst_phys+s1, s-s1);
|
||||
if (cps != OK) printf("RTL8139: warning, sys_abscopy failed: %d\n", cps);
|
||||
#else
|
||||
cps = sys_vircopy(SELF, D, (vir_bytes) rep->v_re_rx_buf+o,
|
||||
re_client, D, iovp->iov_addr, s1);
|
||||
if (cps != OK) printf("RTL8139: warning, sys_vircopy failed: %d (%d)\n", cps, __LINE__);
|
||||
cps = sys_vircopy(SELF, D, (vir_bytes) rep->v_re_rx_buf,
|
||||
re_client, D, iovp->iov_addr+s1, s-s1);
|
||||
if (cps != OK) printf("RTL8139: warning, sys_vircopy failed: %d (%d)\n", cps, __LINE__);
|
||||
#endif
|
||||
cps = sys_vircopy(SELF, D,
|
||||
(vir_bytes) rep->v_re_rx_buf+o,
|
||||
re_client, D, iovp->iov_addr,
|
||||
s1);
|
||||
if (cps != OK)
|
||||
printf(
|
||||
"RTL8139: warning, sys_vircopy failed: %d (%d)\n",
|
||||
cps, __LINE__);
|
||||
cps = sys_vircopy(SELF, D,
|
||||
(vir_bytes) rep->v_re_rx_buf,
|
||||
re_client, D,
|
||||
iovp->iov_addr+s1, s-s1);
|
||||
if (cps != OK)
|
||||
printf(
|
||||
"RTL8139: warning, sys_vircopy failed: %d (%d)\n",
|
||||
cps, __LINE__);
|
||||
}
|
||||
else
|
||||
{
|
||||
#if 0
|
||||
cps = sys_abscopy(src_phys+o, dst_phys, s);
|
||||
if (cps != OK) printf("RTL8139: warning, sys_abscopy failed: %d\n", cps);
|
||||
#else
|
||||
cps = sys_vircopy(SELF, D, (vir_bytes) rep->v_re_rx_buf+o,
|
||||
re_client, D, iovp->iov_addr, s);
|
||||
if (cps != OK) printf("RTL8139: warning, sys_vircopy failed: %d (%d)\n", cps, __LINE__);
|
||||
#endif
|
||||
cps = sys_vircopy(SELF, D,
|
||||
(vir_bytes) rep->v_re_rx_buf+o,
|
||||
re_client, D, iovp->iov_addr,
|
||||
s);
|
||||
if (cps != OK)
|
||||
printf(
|
||||
"RTL8139: warning, sys_vircopy failed: %d (%d)\n",
|
||||
cps, __LINE__);
|
||||
}
|
||||
|
||||
size += s;
|
||||
|
@ -1217,146 +1209,368 @@ int vectored;
|
|||
cps = sys_abscopy(phys_user, p, size);
|
||||
if (cps != OK) printf("RTL8139: warning, sys_abscopy failed: %d\n", cps);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (rep->re_clear_rx)
|
||||
{
|
||||
/* For some reason the receiver FIFO is not stopped when
|
||||
* the buffer is full.
|
||||
*/
|
||||
#if 0
|
||||
printf("rl_readv: later buffer overflow\n");
|
||||
#endif
|
||||
goto suspend; /* Buffer overflow */
|
||||
}
|
||||
|
||||
rep->re_stat.ets_packetR++;
|
||||
rep->re_read_s= packlen;
|
||||
rep->re_flags= (rep->re_flags & ~REF_READING) | REF_PACK_RECV;
|
||||
|
||||
/* Avoid overflow in 16-bit computations */
|
||||
l= d_start;
|
||||
l += totlen+4;
|
||||
l= (l+3) & ~3; /* align */
|
||||
if (l >= RX_BUFSIZE)
|
||||
{
|
||||
l -= RX_BUFSIZE;
|
||||
assert(l < RX_BUFSIZE);
|
||||
}
|
||||
rl_outw(port, RL_CAPR, l-RL_CAPR_DATA_OFF);
|
||||
|
||||
if (!from_int)
|
||||
reply(rep, OK, FALSE);
|
||||
|
||||
return;
|
||||
|
||||
suspend:
|
||||
if (from_int)
|
||||
{
|
||||
assert(rep->re_flags & REF_READING);
|
||||
|
||||
/* No need to store any state */
|
||||
return;
|
||||
}
|
||||
|
||||
rep->re_rx_mess= *mp;
|
||||
assert(!(rep->re_flags & REF_READING));
|
||||
rep->re_flags |= REF_READING;
|
||||
|
||||
reply(rep, OK, FALSE);
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* rl_writev *
|
||||
*===========================================================================*/
|
||||
static void rl_writev(mp, from_int, vectored)
|
||||
message *mp;
|
||||
int from_int;
|
||||
int vectored;
|
||||
if (rep->re_clear_rx)
|
||||
{
|
||||
phys_bytes p, iov_src, phys_user;
|
||||
int i, j, n, s, port, count, size;
|
||||
int tx_head, re_client;
|
||||
re_t *rep;
|
||||
iovec_t *iovp;
|
||||
char *ret;
|
||||
int cps;
|
||||
/* For some reason the receiver FIFO is not stopped when
|
||||
* the buffer is full.
|
||||
*/
|
||||
#if 0
|
||||
printf("rl_readv: later buffer overflow\n");
|
||||
#endif
|
||||
goto suspend; /* Buffer overflow */
|
||||
}
|
||||
|
||||
port = mp->DL_PORT;
|
||||
count = mp->DL_COUNT;
|
||||
if (port < 0 || port >= RE_PORT_NR)
|
||||
panic("rtl8139","illegal port", port);
|
||||
rep= &re_table[port];
|
||||
re_client= mp->DL_PROC;
|
||||
rep->re_client= re_client;
|
||||
rep->re_stat.ets_packetR++;
|
||||
rep->re_read_s= packlen;
|
||||
rep->re_flags= (rep->re_flags & ~REF_READING) | REF_PACK_RECV;
|
||||
|
||||
assert(rep->re_mode == REM_ENABLED);
|
||||
assert(rep->re_flags & REF_ENABLED);
|
||||
/* Avoid overflow in 16-bit computations */
|
||||
l= d_start;
|
||||
l += totlen+4;
|
||||
l= (l+3) & ~3; /* align */
|
||||
if (l >= RX_BUFSIZE)
|
||||
{
|
||||
l -= RX_BUFSIZE;
|
||||
assert(l < RX_BUFSIZE);
|
||||
}
|
||||
rl_outw(port, RL_CAPR, l-RL_CAPR_DATA_OFF);
|
||||
|
||||
if (from_int)
|
||||
{
|
||||
assert(rep->re_flags & REF_SEND_AVAIL);
|
||||
rep->re_flags &= ~REF_SEND_AVAIL;
|
||||
rep->re_send_int= FALSE;
|
||||
rep->re_tx_alive= TRUE;
|
||||
}
|
||||
if (!from_int)
|
||||
reply(rep, OK, FALSE);
|
||||
|
||||
tx_head= rep->re_tx_head;
|
||||
if (rep->re_tx[tx_head].ret_busy)
|
||||
{
|
||||
assert(!(rep->re_flags & REF_SEND_AVAIL));
|
||||
rep->re_flags |= REF_SEND_AVAIL;
|
||||
if (rep->re_tx[tx_head].ret_busy)
|
||||
goto suspend;
|
||||
return;
|
||||
|
||||
/* Race condition, the interrupt handler may clear re_busy
|
||||
* before we got a chance to set REF_SEND_AVAIL. Checking
|
||||
* ret_busy twice should be sufficient.
|
||||
*/
|
||||
#if 0
|
||||
printf("rl_writev: race detected\n");
|
||||
#endif
|
||||
rep->re_flags &= ~REF_SEND_AVAIL;
|
||||
rep->re_send_int= FALSE;
|
||||
}
|
||||
suspend:
|
||||
if (from_int)
|
||||
{
|
||||
assert(rep->re_flags & REF_READING);
|
||||
|
||||
assert(!(rep->re_flags & REF_SEND_AVAIL));
|
||||
assert(!(rep->re_flags & REF_PACK_SENT));
|
||||
/* No need to store any state */
|
||||
return;
|
||||
}
|
||||
|
||||
if (vectored)
|
||||
{
|
||||
int iov_offset = 0;
|
||||
rep->re_rx_mess= *mp;
|
||||
assert(!(rep->re_flags & REF_READING));
|
||||
rep->re_flags |= REF_READING;
|
||||
|
||||
reply(rep, OK, FALSE);
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* rl_readv_s *
|
||||
*===========================================================================*/
|
||||
static void rl_readv_s(mp, from_int)
|
||||
message *mp;
|
||||
int from_int;
|
||||
{
|
||||
int i, j, n, o, s, s1, dl_port, re_client, count, size;
|
||||
port_t port;
|
||||
unsigned amount, totlen, packlen;
|
||||
phys_bytes src_phys, dst_phys, iov_src;
|
||||
u16_t d_start, d_end;
|
||||
u32_t l, rxstat = 0x12345678;
|
||||
re_t *rep;
|
||||
iovec_s_t *iovp;
|
||||
int cps;
|
||||
int iov_offset = 0;
|
||||
|
||||
dl_port = mp->DL_PORT;
|
||||
count = mp->DL_COUNT;
|
||||
if (dl_port < 0 || dl_port >= RE_PORT_NR)
|
||||
panic("rtl8139"," illegal port", dl_port);
|
||||
rep= &re_table[dl_port];
|
||||
re_client= mp->DL_PROC;
|
||||
rep->re_client= re_client;
|
||||
|
||||
if (rep->re_clear_rx)
|
||||
goto suspend; /* Buffer overflow */
|
||||
|
||||
assert(rep->re_mode == REM_ENABLED);
|
||||
assert(rep->re_flags & REF_ENABLED);
|
||||
|
||||
port= rep->re_base_port;
|
||||
|
||||
/* Assume that the RL_CR_BUFE check was been done by rl_checks_ints
|
||||
*/
|
||||
if (!from_int && (rl_inb(port, RL_CR) & RL_CR_BUFE))
|
||||
{
|
||||
/* Receive buffer is empty, suspend */
|
||||
goto suspend;
|
||||
}
|
||||
|
||||
d_start= rl_inw(port, RL_CAPR) + RL_CAPR_DATA_OFF;
|
||||
d_end= rl_inw(port, RL_CBR) % RX_BUFSIZE;
|
||||
|
||||
if (d_start >= RX_BUFSIZE)
|
||||
{
|
||||
printf("rl_readv: strange value in RL_CAPR: 0x%x\n",
|
||||
rl_inw(port, RL_CAPR));
|
||||
d_start %= RX_BUFSIZE;
|
||||
}
|
||||
|
||||
if (d_end > d_start)
|
||||
amount= d_end-d_start;
|
||||
else
|
||||
amount= d_end+RX_BUFSIZE - d_start;
|
||||
|
||||
rxstat = *(u32_t *) (rep->v_re_rx_buf + d_start);
|
||||
|
||||
if (rep->re_clear_rx)
|
||||
{
|
||||
#if 0
|
||||
printf("rl_readv: late buffer overflow\n");
|
||||
#endif
|
||||
goto suspend; /* Buffer overflow */
|
||||
}
|
||||
|
||||
/* Should convert from little endian to host byte order */
|
||||
|
||||
if (!(rxstat & RL_RXS_ROK))
|
||||
{
|
||||
printf("rxstat = 0x%08lx\n", rxstat);
|
||||
printf("d_start: 0x%x, d_end: 0x%x, rxstat: 0x%lx\n",
|
||||
d_start, d_end, rxstat);
|
||||
panic("rtl8139","received packet not OK", NO_NUM);
|
||||
}
|
||||
totlen= (rxstat >> RL_RXS_LEN_S);
|
||||
if (totlen < 8 || totlen > 2*ETH_MAX_PACK_SIZE)
|
||||
{
|
||||
/* Someting went wrong */
|
||||
printf(
|
||||
"rl_readv: bad length (%u) in status 0x%08lx at offset 0x%x\n",
|
||||
totlen, rxstat, d_start);
|
||||
printf(
|
||||
"d_start: 0x%x, d_end: 0x%x, totlen: %d, rxstat: 0x%lx\n",
|
||||
d_start, d_end, totlen, rxstat);
|
||||
panic(NULL, NULL, NO_NUM);
|
||||
}
|
||||
|
||||
#if 0
|
||||
if (OK != sys_umap(re_client, D, (vir_bytes)mp->DL_ADDR,
|
||||
count * sizeof(rep->re_iovec[0]), &iov_src))
|
||||
panic("rtl8139","umap_local failed", NO_NUM);
|
||||
printf("d_start: 0x%x, d_end: 0x%x, totlen: %d, rxstat: 0x%x\n",
|
||||
d_start, d_end, totlen, rxstat);
|
||||
#endif
|
||||
|
||||
size= 0;
|
||||
#if 0
|
||||
p= rep->re_tx[tx_head].ret_buf;
|
||||
#else
|
||||
ret = rep->re_tx[tx_head].v_ret_buf;
|
||||
#endif
|
||||
for (i= 0; i<count; i += IOVEC_NR,
|
||||
iov_src += IOVEC_NR * sizeof(rep->re_iovec[0]),
|
||||
iov_offset += IOVEC_NR * sizeof(rep->re_iovec[0]))
|
||||
if (totlen+4 > amount)
|
||||
{
|
||||
printf("rl_readv: packet not yet ready\n");
|
||||
goto suspend;
|
||||
}
|
||||
|
||||
/* Should subtract the CRC */
|
||||
packlen= totlen - ETH_CRC_SIZE;
|
||||
|
||||
size= 0;
|
||||
o= d_start+4;
|
||||
src_phys= rep->re_rx_buf;
|
||||
for (i= 0; i<count; i += IOVEC_NR,
|
||||
iov_src += IOVEC_NR * sizeof(rep->re_iovec_s[0]),
|
||||
iov_offset += IOVEC_NR * sizeof(rep->re_iovec_s[0]))
|
||||
{
|
||||
n= IOVEC_NR;
|
||||
if (i+n > count)
|
||||
n= count-i;
|
||||
|
||||
cps = sys_safecopyfrom(re_client, mp->DL_GRANT, iov_offset,
|
||||
(vir_bytes) rep->re_iovec_s,
|
||||
n * sizeof(rep->re_iovec_s[0]), D);
|
||||
if (cps != OK)
|
||||
{
|
||||
panic(__FILE__, "rl_readv_s: sys_safecopyfrom failed",
|
||||
cps);
|
||||
}
|
||||
|
||||
for (j= 0, iovp= rep->re_iovec_s; j<n; j++, iovp++)
|
||||
{
|
||||
s= iovp->iov_size;
|
||||
if (size + s > packlen)
|
||||
{
|
||||
n= IOVEC_NR;
|
||||
if (i+n > count)
|
||||
n= count-i;
|
||||
assert(packlen > size);
|
||||
s= packlen-size;
|
||||
}
|
||||
|
||||
#if 0
|
||||
cps = sys_physcopy(NONE, PHYS_SEG, iov_src, SELF, D, (vir_bytes) rep->re_iovec,
|
||||
n * sizeof(rep->re_iovec[0]));
|
||||
if (cps != OK) printf("RTL8139: warning, sys_abscopy failed: %d\n", cps);
|
||||
#else
|
||||
cps = sys_vircopy(re_client, D, ((vir_bytes) mp->DL_ADDR) + iov_offset,
|
||||
SELF, D, (vir_bytes) rep->re_iovec,
|
||||
n * sizeof(rep->re_iovec[0]));
|
||||
if (cps != OK) printf("RTL8139: warning, sys_vircopy failed: %d\n", cps);
|
||||
if (sys_umap(re_client, D, iovp->iov_addr, s, &dst_phys) != OK)
|
||||
panic("rtl8139","umap_local failed\n", NO_NUM);
|
||||
#endif
|
||||
|
||||
if (o >= RX_BUFSIZE)
|
||||
{
|
||||
o -= RX_BUFSIZE;
|
||||
assert(o < RX_BUFSIZE);
|
||||
}
|
||||
|
||||
if (o+s > RX_BUFSIZE)
|
||||
{
|
||||
assert(o<RX_BUFSIZE);
|
||||
s1= RX_BUFSIZE-o;
|
||||
|
||||
cps = sys_safecopyto(re_client,
|
||||
iovp->iov_grant, 0,
|
||||
(vir_bytes) rep->v_re_rx_buf+o, s1, D);
|
||||
if (cps != OK)
|
||||
{
|
||||
panic(__FILE__,
|
||||
"rl_readv_s: sys_safecopyto failed",
|
||||
cps);
|
||||
}
|
||||
cps = sys_safecopyto(re_client,
|
||||
iovp->iov_grant, s1,
|
||||
(vir_bytes) rep->v_re_rx_buf, s-s1, S);
|
||||
if (cps != OK)
|
||||
{
|
||||
panic(__FILE__,
|
||||
"rl_readv_s: sys_safecopyto failed",
|
||||
cps);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
cps = sys_safecopyto(re_client,
|
||||
iovp->iov_grant, 0,
|
||||
(vir_bytes) rep->v_re_rx_buf+o, s, D);
|
||||
if (cps != OK)
|
||||
panic(__FILE__,
|
||||
"rl_readv_s: sys_vircopy failed",
|
||||
cps);
|
||||
}
|
||||
|
||||
size += s;
|
||||
if (size == packlen)
|
||||
break;
|
||||
o += s;
|
||||
}
|
||||
if (size == packlen)
|
||||
break;
|
||||
}
|
||||
if (size < packlen)
|
||||
{
|
||||
assert(0);
|
||||
}
|
||||
|
||||
if (rep->re_clear_rx)
|
||||
{
|
||||
/* For some reason the receiver FIFO is not stopped when
|
||||
* the buffer is full.
|
||||
*/
|
||||
#if 0
|
||||
printf("rl_readv: later buffer overflow\n");
|
||||
#endif
|
||||
goto suspend; /* Buffer overflow */
|
||||
}
|
||||
|
||||
rep->re_stat.ets_packetR++;
|
||||
rep->re_read_s= packlen;
|
||||
rep->re_flags= (rep->re_flags & ~REF_READING) | REF_PACK_RECV;
|
||||
|
||||
/* Avoid overflow in 16-bit computations */
|
||||
l= d_start;
|
||||
l += totlen+4;
|
||||
l= (l+3) & ~3; /* align */
|
||||
if (l >= RX_BUFSIZE)
|
||||
{
|
||||
l -= RX_BUFSIZE;
|
||||
assert(l < RX_BUFSIZE);
|
||||
}
|
||||
rl_outw(port, RL_CAPR, l-RL_CAPR_DATA_OFF);
|
||||
|
||||
if (!from_int)
|
||||
reply(rep, OK, FALSE);
|
||||
|
||||
return;
|
||||
|
||||
suspend:
|
||||
if (from_int)
|
||||
{
|
||||
assert(rep->re_flags & REF_READING);
|
||||
|
||||
/* No need to store any state */
|
||||
return;
|
||||
}
|
||||
|
||||
rep->re_rx_mess= *mp;
|
||||
assert(!(rep->re_flags & REF_READING));
|
||||
rep->re_flags |= REF_READING;
|
||||
|
||||
reply(rep, OK, FALSE);
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* rl_writev *
|
||||
*===========================================================================*/
|
||||
static void rl_writev(mp, from_int, vectored)
|
||||
message *mp;
|
||||
int from_int;
|
||||
int vectored;
|
||||
{
|
||||
phys_bytes iov_src, phys_user;
|
||||
int i, j, n, s, port, count, size;
|
||||
int tx_head, re_client;
|
||||
re_t *rep;
|
||||
iovec_t *iovp;
|
||||
char *ret;
|
||||
int cps;
|
||||
|
||||
port = mp->DL_PORT;
|
||||
count = mp->DL_COUNT;
|
||||
if (port < 0 || port >= RE_PORT_NR)
|
||||
panic("rtl8139","illegal port", port);
|
||||
rep= &re_table[port];
|
||||
re_client= mp->DL_PROC;
|
||||
rep->re_client= re_client;
|
||||
|
||||
assert(rep->re_mode == REM_ENABLED);
|
||||
assert(rep->re_flags & REF_ENABLED);
|
||||
|
||||
if (from_int)
|
||||
{
|
||||
assert(rep->re_flags & REF_SEND_AVAIL);
|
||||
rep->re_flags &= ~REF_SEND_AVAIL;
|
||||
rep->re_send_int= FALSE;
|
||||
rep->re_tx_alive= TRUE;
|
||||
}
|
||||
|
||||
tx_head= rep->re_tx_head;
|
||||
if (rep->re_tx[tx_head].ret_busy)
|
||||
{
|
||||
assert(!(rep->re_flags & REF_SEND_AVAIL));
|
||||
rep->re_flags |= REF_SEND_AVAIL;
|
||||
if (rep->re_tx[tx_head].ret_busy)
|
||||
goto suspend;
|
||||
|
||||
/* Race condition, the interrupt handler may clear re_busy
|
||||
* before we got a chance to set REF_SEND_AVAIL. Checking
|
||||
* ret_busy twice should be sufficient.
|
||||
*/
|
||||
#if 0
|
||||
printf("rl_writev: race detected\n");
|
||||
#endif
|
||||
rep->re_flags &= ~REF_SEND_AVAIL;
|
||||
rep->re_send_int= FALSE;
|
||||
}
|
||||
|
||||
assert(!(rep->re_flags & REF_SEND_AVAIL));
|
||||
assert(!(rep->re_flags & REF_PACK_SENT));
|
||||
|
||||
if (vectored)
|
||||
{
|
||||
int iov_offset = 0;
|
||||
|
||||
size= 0;
|
||||
ret = rep->re_tx[tx_head].v_ret_buf;
|
||||
for (i= 0; i<count; i += IOVEC_NR,
|
||||
iov_src += IOVEC_NR * sizeof(rep->re_iovec[0]),
|
||||
iov_offset += IOVEC_NR * sizeof(rep->re_iovec[0]))
|
||||
{
|
||||
n= IOVEC_NR;
|
||||
if (i+n > count)
|
||||
n= count-i;
|
||||
cps = sys_vircopy(re_client, D, ((vir_bytes) mp->DL_ADDR) + iov_offset,
|
||||
SELF, D, (vir_bytes) rep->re_iovec,
|
||||
n * sizeof(rep->re_iovec[0]));
|
||||
if (cps != OK) printf("RTL8139: warning, sys_vircopy failed: %d\n", cps);
|
||||
|
||||
for (j= 0, iovp= rep->re_iovec; j<n; j++, iovp++)
|
||||
{
|
||||
s= iovp->iov_size;
|
||||
|
@ -1369,18 +1583,10 @@ int vectored;
|
|||
if (OK != sys_umap(re_client, D, iovp->iov_addr, s, &phys_user))
|
||||
panic("rtl8139","umap_local failed\n", NO_NUM);
|
||||
|
||||
#if 0
|
||||
cps = sys_abscopy(phys_user, p, s);
|
||||
if (cps != OK) printf("RTL8139: warning, sys_abscopy failed: %d\n", cps);
|
||||
#else
|
||||
cps = sys_vircopy(re_client, D, iovp->iov_addr,
|
||||
SELF, D, (vir_bytes) ret, s);
|
||||
if (cps != OK) printf("RTL8139: warning, sys_vircopy failed: %d\n", cps);
|
||||
#endif
|
||||
size += s;
|
||||
#if 0
|
||||
p += s;
|
||||
#endif
|
||||
ret += s;
|
||||
}
|
||||
}
|
||||
|
@ -1392,19 +1598,10 @@ int vectored;
|
|||
size= mp->DL_COUNT;
|
||||
if (size < ETH_MIN_PACK_SIZE || size > ETH_MAX_PACK_SIZE_TAGGED)
|
||||
panic("rtl8139","invalid packet size", size);
|
||||
#if 0
|
||||
if (OK != sys_umap(re_client, D, (vir_bytes)mp->DL_ADDR, size, &phys_user))
|
||||
panic("rtl8139","umap_local failed\n", NO_NUM);
|
||||
|
||||
p= rep->re_tx[tx_head].ret_buf;
|
||||
cps = sys_abscopy(phys_user, p, size);
|
||||
if (cps != OK) printf("RTL8139: warning, sys_abscopy failed: %d\n", cps);
|
||||
#else
|
||||
ret = rep->re_tx[tx_head].v_ret_buf;
|
||||
cps = sys_vircopy(re_client, D, (vir_bytes)mp->DL_ADDR,
|
||||
SELF, D, (vir_bytes) ret, size);
|
||||
if (cps != OK) printf("RTL8139: warning, sys_abscopy failed: %d\n", cps);
|
||||
#endif
|
||||
}
|
||||
|
||||
rl_outl(rep->re_base_port, RL_TSD0+tx_head*4,
|
||||
|
@ -1446,6 +1643,143 @@ suspend:
|
|||
reply(rep, OK, FALSE);
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* rl_writev_s *
|
||||
*===========================================================================*/
|
||||
static void rl_writev_s(mp, from_int)
|
||||
message *mp;
|
||||
int from_int;
|
||||
{
|
||||
phys_bytes iov_src;
|
||||
int i, j, n, s, port, count, size;
|
||||
int tx_head, re_client;
|
||||
re_t *rep;
|
||||
iovec_s_t *iovp;
|
||||
char *ret;
|
||||
int cps;
|
||||
int iov_offset = 0;
|
||||
|
||||
port = mp->DL_PORT;
|
||||
count = mp->DL_COUNT;
|
||||
if (port < 0 || port >= RE_PORT_NR)
|
||||
panic("rtl8139","illegal port", port);
|
||||
rep= &re_table[port];
|
||||
re_client= mp->DL_PROC;
|
||||
rep->re_client= re_client;
|
||||
|
||||
assert(rep->re_mode == REM_ENABLED);
|
||||
assert(rep->re_flags & REF_ENABLED);
|
||||
|
||||
if (from_int)
|
||||
{
|
||||
assert(rep->re_flags & REF_SEND_AVAIL);
|
||||
rep->re_flags &= ~REF_SEND_AVAIL;
|
||||
rep->re_send_int= FALSE;
|
||||
rep->re_tx_alive= TRUE;
|
||||
}
|
||||
|
||||
tx_head= rep->re_tx_head;
|
||||
if (rep->re_tx[tx_head].ret_busy)
|
||||
{
|
||||
assert(!(rep->re_flags & REF_SEND_AVAIL));
|
||||
rep->re_flags |= REF_SEND_AVAIL;
|
||||
if (rep->re_tx[tx_head].ret_busy)
|
||||
goto suspend;
|
||||
|
||||
/* Race condition, the interrupt handler may clear re_busy
|
||||
* before we got a chance to set REF_SEND_AVAIL. Checking
|
||||
* ret_busy twice should be sufficient.
|
||||
*/
|
||||
#if 0
|
||||
printf("rl_writev: race detected\n");
|
||||
#endif
|
||||
rep->re_flags &= ~REF_SEND_AVAIL;
|
||||
rep->re_send_int= FALSE;
|
||||
}
|
||||
|
||||
assert(!(rep->re_flags & REF_SEND_AVAIL));
|
||||
assert(!(rep->re_flags & REF_PACK_SENT));
|
||||
|
||||
size= 0;
|
||||
ret = rep->re_tx[tx_head].v_ret_buf;
|
||||
for (i= 0; i<count; i += IOVEC_NR,
|
||||
iov_src += IOVEC_NR * sizeof(rep->re_iovec_s[0]),
|
||||
iov_offset += IOVEC_NR * sizeof(rep->re_iovec_s[0]))
|
||||
{
|
||||
n= IOVEC_NR;
|
||||
if (i+n > count)
|
||||
n= count-i;
|
||||
cps = sys_safecopyfrom(re_client, mp->DL_GRANT, iov_offset,
|
||||
(vir_bytes) rep->re_iovec_s,
|
||||
n * sizeof(rep->re_iovec_s[0]), D);
|
||||
if (cps != OK)
|
||||
{
|
||||
panic(__FILE__, "rl_writev_s: sys_safecopyfrom failed",
|
||||
cps);
|
||||
}
|
||||
|
||||
for (j= 0, iovp= rep->re_iovec_s; j<n; j++, iovp++)
|
||||
{
|
||||
s= iovp->iov_size;
|
||||
if (size + s > ETH_MAX_PACK_SIZE_TAGGED)
|
||||
{
|
||||
panic("rtl8139","invalid packet size",
|
||||
NO_NUM);
|
||||
}
|
||||
cps = sys_safecopyfrom(re_client, iovp->iov_grant, 0,
|
||||
(vir_bytes) ret, s, D);
|
||||
if (cps != OK)
|
||||
{
|
||||
panic(__FILE__,
|
||||
"rl_writev_s: sys_safecopyfrom failed",
|
||||
cps);
|
||||
}
|
||||
size += s;
|
||||
ret += s;
|
||||
}
|
||||
}
|
||||
if (size < ETH_MIN_PACK_SIZE)
|
||||
panic("rtl8139","invalid packet size", size);
|
||||
|
||||
rl_outl(rep->re_base_port, RL_TSD0+tx_head*4,
|
||||
rep->re_ertxth | size);
|
||||
rep->re_tx[tx_head].ret_busy= TRUE;
|
||||
|
||||
if (++tx_head == N_TX_BUF)
|
||||
tx_head= 0;
|
||||
assert(tx_head < RL_N_TX);
|
||||
rep->re_tx_head= tx_head;
|
||||
|
||||
rep->re_flags |= REF_PACK_SENT;
|
||||
|
||||
/* If the interrupt handler called, don't send a reply. The reply
|
||||
* will be sent after all interrupts are handled.
|
||||
*/
|
||||
if (from_int)
|
||||
return;
|
||||
reply(rep, OK, FALSE);
|
||||
return;
|
||||
|
||||
suspend:
|
||||
#if 0
|
||||
printf("rl_writev: head %d, tail %d, busy: %d %d %d %d\n",
|
||||
tx_head, rep->re_tx_tail,
|
||||
rep->re_tx[0].ret_busy, rep->re_tx[1].ret_busy,
|
||||
rep->re_tx[2].ret_busy, rep->re_tx[3].ret_busy);
|
||||
printf("rl_writev: TSD: 0x%x, 0x%x, 0x%x, 0x%x\n",
|
||||
rl_inl(rep->re_base_port, RL_TSD0+0*4),
|
||||
rl_inl(rep->re_base_port, RL_TSD0+1*4),
|
||||
rl_inl(rep->re_base_port, RL_TSD0+2*4),
|
||||
rl_inl(rep->re_base_port, RL_TSD0+3*4));
|
||||
#endif
|
||||
|
||||
if (from_int)
|
||||
panic("rtl8139","should not be sending\n", NO_NUM);
|
||||
|
||||
rep->re_tx_mess= *mp;
|
||||
reply(rep, OK, FALSE);
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* rl_check_ints *
|
||||
*===========================================================================*/
|
||||
|
@ -1503,6 +1837,10 @@ re_t *rep;
|
|||
rl_readv(&rep->re_rx_mess, TRUE /* from int */,
|
||||
TRUE /* vectored */);
|
||||
}
|
||||
else if (rep->re_rx_mess.m_type == DL_READV_S)
|
||||
{
|
||||
rl_readv_s(&rep->re_rx_mess, TRUE /* from int */);
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(rep->re_rx_mess.m_type == DL_READ);
|
||||
|
@ -1898,7 +2236,7 @@ re_t *rep;
|
|||
static void rl_getstat(mp)
|
||||
message *mp;
|
||||
{
|
||||
int port;
|
||||
int r, port;
|
||||
eth_stat_t stats;
|
||||
re_t *rep;
|
||||
|
||||
|
@ -1913,8 +2251,38 @@ message *mp;
|
|||
|
||||
stats= rep->re_stat;
|
||||
|
||||
put_userdata(mp->DL_PROC, (vir_bytes) mp->DL_ADDR,
|
||||
(vir_bytes) sizeof(stats), &stats);
|
||||
r = sys_datacopy(SELF, (vir_bytes) &stats, mp->DL_PROC,
|
||||
(vir_bytes) mp->DL_ADDR, sizeof(stats));
|
||||
if (r != OK)
|
||||
panic(__FILE__, "rl_getstat: sys_datacopy failed", r);
|
||||
reply(rep, OK, FALSE);
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* rl_getstat_s *
|
||||
*===========================================================================*/
|
||||
static void rl_getstat_s(mp)
|
||||
message *mp;
|
||||
{
|
||||
int r, port;
|
||||
eth_stat_t stats;
|
||||
re_t *rep;
|
||||
|
||||
port = mp->DL_PORT;
|
||||
if (port < 0 || port >= RE_PORT_NR)
|
||||
panic("rtl8139","illegal port", port);
|
||||
rep= &re_table[port];
|
||||
rep->re_client= mp->DL_PROC;
|
||||
|
||||
assert(rep->re_mode == REM_ENABLED);
|
||||
assert(rep->re_flags & REF_ENABLED);
|
||||
|
||||
stats= rep->re_stat;
|
||||
|
||||
r = sys_safecopyto(mp->DL_PROC, mp->DL_GRANT, 0,
|
||||
(vir_bytes) &stats, sizeof(stats), D);
|
||||
if (r != OK)
|
||||
panic(__FILE__, "rl_getstat_s: sys_safecopyto failed", r);
|
||||
reply(rep, OK, FALSE);
|
||||
}
|
||||
|
||||
|
@ -1994,20 +2362,6 @@ message *reply_mess;
|
|||
panic("rtl8139","unable to mess_reply", NO_NUM);
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* put_userdata *
|
||||
*===========================================================================*/
|
||||
static void put_userdata(user_proc, user_addr, count, loc_addr)
|
||||
int user_proc;
|
||||
vir_bytes user_addr;
|
||||
vir_bytes count;
|
||||
void *loc_addr;
|
||||
{
|
||||
int cps;
|
||||
cps = sys_datacopy(SELF, (vir_bytes) loc_addr, user_proc, user_addr, count);
|
||||
if (cps != OK) printf("RTL8139: warning, scopy failed: %d\n", cps);
|
||||
}
|
||||
|
||||
#if 0
|
||||
static void dump_phy(rep)
|
||||
re_t *rep;
|
||||
|
|
Loading…
Reference in a new issue