Safecopy support in ethernet drivers.
This commit is contained in:
parent
9392742cc4
commit
2cf649db2e
|
|
@ -21,7 +21,7 @@ OBJ = 3c503.o dp8390.o ne2000.o rtl8029.o wdeth.o
|
||||||
all build: $(DRIVER)
|
all build: $(DRIVER)
|
||||||
$(DRIVER): $(OBJ)
|
$(DRIVER): $(OBJ)
|
||||||
$(CC) -o $@ $(LDFLAGS) $(OBJ) $(LIBS)
|
$(CC) -o $@ $(LDFLAGS) $(OBJ) $(LIBS)
|
||||||
install -S 4096 $(DRIVER)
|
install -S 32k $(DRIVER)
|
||||||
|
|
||||||
# install with other drivers
|
# install with other drivers
|
||||||
install: /usr/sbin/$(DRIVER)
|
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 dpeth;
|
||||||
struct iovec_dat;
|
struct iovec_dat;
|
||||||
|
struct iovec_dat_s;
|
||||||
_PROTOTYPE( typedef void (*dp_initf_t), (struct dpeth *dep) );
|
_PROTOTYPE( typedef void (*dp_initf_t), (struct dpeth *dep) );
|
||||||
_PROTOTYPE( typedef void (*dp_stopf_t), (struct dpeth *dep) );
|
_PROTOTYPE( typedef void (*dp_stopf_t), (struct dpeth *dep) );
|
||||||
_PROTOTYPE( typedef void (*dp_user2nicf_t), (struct dpeth *dep,
|
_PROTOTYPE( typedef void (*dp_user2nicf_t), (struct dpeth *dep,
|
||||||
struct iovec_dat *iovp, vir_bytes offset,
|
struct iovec_dat *iovp, vir_bytes offset,
|
||||||
int nic_addr, vir_bytes count) );
|
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,
|
_PROTOTYPE( typedef void (*dp_nic2userf_t), (struct dpeth *dep,
|
||||||
int nic_addr, struct iovec_dat *iovp,
|
int nic_addr, struct iovec_dat *iovp,
|
||||||
vir_bytes offset, vir_bytes count) );
|
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
|
#if 0
|
||||||
_PROTOTYPE( typedef void (*dp_getheaderf_t), (struct dpeth *dep,
|
_PROTOTYPE( typedef void (*dp_getheaderf_t), (struct dpeth *dep,
|
||||||
int page, struct dp_rcvhdr *h, u16_t *eth_type) );
|
int page, struct dp_rcvhdr *h, u16_t *eth_type) );
|
||||||
|
|
@ -200,6 +207,15 @@ typedef struct iovec_dat
|
||||||
vir_bytes iod_iovec_addr;
|
vir_bytes iod_iovec_addr;
|
||||||
} iovec_dat_t;
|
} 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_NR 2 /* Maximum size of the send queue */
|
||||||
#define SENDQ_PAGES 6 /* 6 * DP_PAGESIZE >= 1514 bytes */
|
#define SENDQ_PAGES 6 /* 6 * DP_PAGESIZE >= 1514 bytes */
|
||||||
|
|
||||||
|
|
@ -215,6 +231,7 @@ typedef struct dpeth
|
||||||
*/
|
*/
|
||||||
port_t de_base_port;
|
port_t de_base_port;
|
||||||
phys_bytes de_linmem;
|
phys_bytes de_linmem;
|
||||||
|
char *de_locmem;
|
||||||
int de_irq;
|
int de_irq;
|
||||||
int de_int_pending;
|
int de_int_pending;
|
||||||
irq_hook_t de_hook;
|
irq_hook_t de_hook;
|
||||||
|
|
@ -261,13 +278,19 @@ typedef struct dpeth
|
||||||
int de_mode;
|
int de_mode;
|
||||||
eth_stat_t de_stat;
|
eth_stat_t de_stat;
|
||||||
iovec_dat_t de_read_iovec;
|
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_t de_write_iovec;
|
||||||
|
iovec_dat_s_t de_write_iovec_s;
|
||||||
iovec_dat_t de_tmp_iovec;
|
iovec_dat_t de_tmp_iovec;
|
||||||
|
iovec_dat_s_t de_tmp_iovec_s;
|
||||||
vir_bytes de_read_s;
|
vir_bytes de_read_s;
|
||||||
int de_client;
|
int de_client;
|
||||||
message de_sendmsg;
|
message de_sendmsg;
|
||||||
dp_user2nicf_t de_user2nicf;
|
dp_user2nicf_t de_user2nicf;
|
||||||
|
dp_user2nicf_s_t de_user2nicf_s;
|
||||||
dp_nic2userf_t de_nic2userf;
|
dp_nic2userf_t de_nic2userf;
|
||||||
|
dp_nic2userf_s_t de_nic2userf_s;
|
||||||
dp_getblock_t de_getblockf;
|
dp_getblock_t de_getblockf;
|
||||||
} dpeth_t;
|
} dpeth_t;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -122,16 +122,19 @@ static void el3_write_fifo(dpeth_t * dep, int pktsize)
|
||||||
{
|
{
|
||||||
phys_bytes phys_user;
|
phys_bytes phys_user;
|
||||||
int bytes, ix = 0;
|
int bytes, ix = 0;
|
||||||
iovec_dat_t *iovp = &dep->de_write_iovec;
|
iovec_dat_s_t *iovp = &dep->de_write_iovec;
|
||||||
int padding = pktsize;
|
int r, padding = pktsize;
|
||||||
|
|
||||||
do { /* Writes chuncks of packet from user buffers */
|
do { /* Writes chuncks of packet from user buffers */
|
||||||
|
|
||||||
bytes = iovp->iod_iovec[ix].iov_size; /* Size of buffer */
|
bytes = iovp->iod_iovec[ix].iov_size; /* Size of buffer */
|
||||||
if (bytes > pktsize) bytes = pktsize;
|
if (bytes > pktsize) bytes = pktsize;
|
||||||
/* Writes from user buffer to Tx FIFO */
|
/* Writes from user buffer to Tx FIFO */
|
||||||
outsb(dep->de_data_port, iovp->iod_proc_nr,
|
r= sys_safe_insb(dep->de_data_port, iovp->iod_proc_nr,
|
||||||
(void*)(iovp->iod_iovec[ix].iov_addr), bytes);
|
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 */
|
if (++ix >= IOVEC_NR) { /* Next buffer of IO vector */
|
||||||
dp_next_iovec(iovp);
|
dp_next_iovec(iovp);
|
||||||
ix = 0;
|
ix = 0;
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
#include <assert.h>
|
||||||
/*
|
/*
|
||||||
** File: 8390.c May 02, 2000
|
** File: 8390.c May 02, 2000
|
||||||
**
|
**
|
||||||
|
|
@ -25,14 +26,18 @@
|
||||||
|
|
||||||
#include "8390.h"
|
#include "8390.h"
|
||||||
|
|
||||||
|
#if 0
|
||||||
#define sys_nic2mem(srcOffs,dstProc,dstOffs,length) \
|
#define sys_nic2mem(srcOffs,dstProc,dstOffs,length) \
|
||||||
sys_vircopy(SELF,dep->de_memsegm,(vir_bytes)(srcOffs),\
|
sys_vircopy(SELF,dep->de_memsegm,(vir_bytes)(srcOffs),\
|
||||||
(dstProc),D,(vir_bytes)(dstOffs),length)
|
(dstProc),D,(vir_bytes)(dstOffs),length)
|
||||||
#define sys_user2nic(srcProc,srcOffs,dstOffs,length) \
|
#endif
|
||||||
sys_vircopy((srcProc),D,(vir_bytes)(srcOffs),\
|
#if 0
|
||||||
SELF,dep->de_memsegm,(vir_bytes)(dstOffs),length)
|
#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);
|
** 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)
|
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);
|
sys_nic2mem(dep->de_linmem + offset, SELF, dst, size);
|
||||||
return;
|
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)
|
static void mem_nic2user(dpeth_t * dep, int pageno, int pktsize)
|
||||||
{
|
{
|
||||||
phys_bytes offset, phys_user;
|
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;
|
int bytes, ix = 0;
|
||||||
|
|
||||||
|
panic(__FILE__, "mem_nic2user: not converted to safecopies", NO_NUM);
|
||||||
|
#if 0
|
||||||
|
|
||||||
/* Computes shared memory address (skipping receive header) */
|
/* Computes shared memory address (skipping receive header) */
|
||||||
offset = pageno * DP_PAGESIZE + sizeof(dp_rcvhdr_t);
|
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 */
|
/* Circular buffer wrap-around */
|
||||||
bytes = dep->de_stoppage * DP_PAGESIZE - offset;
|
bytes = dep->de_stoppage * DP_PAGESIZE - offset;
|
||||||
sys_nic2mem(dep->de_linmem + offset, iovp->iod_proc_nr,
|
sys_nic2mem_s(dep->de_linmem + offset, iovp->iod_proc_nr,
|
||||||
iovp->iod_iovec[ix].iov_addr, bytes);
|
iovp->iod_iovec[ix].iov_grant, bytes);
|
||||||
pktsize -= bytes;
|
pktsize -= bytes;
|
||||||
phys_user += bytes;
|
phys_user += bytes;
|
||||||
bytes = iovp->iod_iovec[ix].iov_size - bytes;
|
bytes = iovp->iod_iovec[ix].iov_size - bytes;
|
||||||
if (bytes > pktsize) bytes = pktsize;
|
if (bytes > pktsize) bytes = pktsize;
|
||||||
offset = dep->de_startpage * DP_PAGESIZE;
|
offset = dep->de_startpage * DP_PAGESIZE;
|
||||||
}
|
}
|
||||||
sys_nic2mem(dep->de_linmem + offset, iovp->iod_proc_nr,
|
sys_nic2mem_s(dep->de_linmem + offset, iovp->iod_proc_nr,
|
||||||
iovp->iod_iovec[ix].iov_addr, bytes);
|
iovp->iod_iovec[ix].iov_grant, bytes);
|
||||||
offset += bytes;
|
offset += bytes;
|
||||||
|
|
||||||
if (++ix >= IOVEC_NR) { /* Next buffer of IO vector */
|
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 */
|
/* Till packet done */
|
||||||
} while ((pktsize -= bytes) > 0);
|
} while ((pktsize -= bytes) > 0);
|
||||||
return;
|
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)
|
static void mem_user2nic(dpeth_t *dep, int pageno, int pktsize)
|
||||||
{
|
{
|
||||||
phys_bytes offset, phys_user;
|
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;
|
int bytes, ix = 0;
|
||||||
|
|
||||||
|
panic(__FILE__, "mem_user2nic: not converted to safecopies", NO_NUM);
|
||||||
|
#if 0
|
||||||
|
|
||||||
/* Computes shared memory address */
|
/* Computes shared memory address */
|
||||||
offset = pageno * DP_PAGESIZE;
|
offset = pageno * DP_PAGESIZE;
|
||||||
|
|
||||||
|
|
@ -140,7 +154,7 @@ static void mem_user2nic(dpeth_t *dep, int pageno, int pktsize)
|
||||||
if (bytes > pktsize) bytes = pktsize;
|
if (bytes > pktsize) bytes = pktsize;
|
||||||
|
|
||||||
/* Reads from user area to board (shared memory) */
|
/* 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);
|
dep->de_linmem + offset, bytes);
|
||||||
offset += bytes;
|
offset += bytes;
|
||||||
|
|
||||||
|
|
@ -151,6 +165,7 @@ static void mem_user2nic(dpeth_t *dep, int pageno, int pktsize)
|
||||||
/* Till packet done */
|
/* Till packet done */
|
||||||
} while ((pktsize -= bytes) > 0);
|
} while ((pktsize -= bytes) > 0);
|
||||||
return;
|
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)
|
static void pio_nic2user(dpeth_t *dep, int pageno, int pktsize)
|
||||||
{
|
{
|
||||||
phys_bytes phys_user;
|
phys_bytes phys_user;
|
||||||
iovec_dat_t *iovp = &dep->de_read_iovec;
|
iovec_dat_s_t *iovp = &dep->de_read_iovec;
|
||||||
unsigned offset; int bytes, ix = 0;
|
unsigned offset, iov_offset; int r, bytes, ix = 0;
|
||||||
|
|
||||||
/* Computes memory address (skipping receive header) */
|
/* Computes memory address (skipping receive header) */
|
||||||
offset = pageno * DP_PAGESIZE + sizeof(dp_rcvhdr_t);
|
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)) ?
|
ns_rw_setup(dep, CR_DM_RR, ((offset + pktsize) > (dep->de_stoppage * DP_PAGESIZE)) ?
|
||||||
(dep->de_stoppage * DP_PAGESIZE) - offset : pktsize, offset);
|
(dep->de_stoppage * DP_PAGESIZE) - offset : pktsize, offset);
|
||||||
|
|
||||||
|
iov_offset= 0;
|
||||||
do { /* Reads chuncks of packet into user area */
|
do { /* Reads chuncks of packet into user area */
|
||||||
|
|
||||||
bytes = iovp->iod_iovec[ix].iov_size; /* Size of a chunck */
|
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 */
|
/* Circular buffer wrap-around */
|
||||||
bytes = dep->de_stoppage * DP_PAGESIZE - offset;
|
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;
|
pktsize -= bytes;
|
||||||
iovp->iod_iovec[ix].iov_addr += bytes;
|
iov_offset += bytes;
|
||||||
bytes = iovp->iod_iovec[ix].iov_size - bytes;
|
bytes = iovp->iod_iovec[ix].iov_size - bytes;
|
||||||
if (bytes > pktsize) bytes = pktsize;
|
if (bytes > pktsize) bytes = pktsize;
|
||||||
offset = dep->de_startpage * DP_PAGESIZE;
|
offset = dep->de_startpage * DP_PAGESIZE;
|
||||||
ns_rw_setup(dep, CR_DM_RR, pktsize, offset);
|
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;
|
offset += bytes;
|
||||||
|
|
||||||
if (++ix >= IOVEC_NR) { /* Next buffer of IO vector */
|
if (++ix >= IOVEC_NR) { /* Next buffer of IO vector */
|
||||||
dp_next_iovec(iovp);
|
dp_next_iovec(iovp);
|
||||||
ix = 0;
|
ix = 0;
|
||||||
}
|
}
|
||||||
|
iov_offset= 0;
|
||||||
/* Till packet done */
|
/* Till packet done */
|
||||||
} while ((pktsize -= bytes) > 0);
|
} while ((pktsize -= bytes) > 0);
|
||||||
return;
|
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)
|
static void pio_user2nic(dpeth_t *dep, int pageno, int pktsize)
|
||||||
{
|
{
|
||||||
phys_bytes phys_user;
|
phys_bytes phys_user;
|
||||||
iovec_dat_t *iovp = &dep->de_write_iovec;
|
iovec_dat_s_t *iovp = &dep->de_write_iovec;
|
||||||
int bytes, ix = 0;
|
int r, bytes, ix = 0;
|
||||||
|
|
||||||
/* Sets up board for writing */
|
/* Sets up board for writing */
|
||||||
ns_rw_setup(dep, CR_DM_RW, pktsize, pageno * DP_PAGESIZE);
|
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 */
|
bytes = iovp->iod_iovec[ix].iov_size; /* Size of chunck */
|
||||||
if (bytes > pktsize) bytes = pktsize;
|
if (bytes > pktsize) bytes = pktsize;
|
||||||
outsb(dep->de_data_port, iovp->iod_proc_nr,
|
r= sys_safe_outsb(dep->de_data_port, iovp->iod_proc_nr,
|
||||||
(void*)(iovp->iod_iovec[ix].iov_addr), bytes);
|
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 */
|
if (++ix >= IOVEC_NR) { /* Next buffer of I/O vector */
|
||||||
dp_next_iovec(iovp);
|
dp_next_iovec(iovp);
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,9 @@
|
||||||
## Makefile for ISA ethernet drivers May 02, 2000
|
## Makefile for ISA ethernet drivers May 02, 2000
|
||||||
##
|
##
|
||||||
## $Log$
|
## $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
|
## Revision 1.3 2005/07/19 13:21:48 jnherder
|
||||||
## Renamed src/lib/utils to src/lib/sysutil --- because of new src/lib/util
|
## Renamed src/lib/utils to src/lib/sysutil --- because of new src/lib/util
|
||||||
##
|
##
|
||||||
|
|
@ -26,7 +29,7 @@ debug = 0
|
||||||
CC = exec cc
|
CC = exec cc
|
||||||
LD = $(CC)
|
LD = $(CC)
|
||||||
CPPFLAGS= -I.. -I/usr/include -Ddebug=$(debug)
|
CPPFLAGS= -I.. -I/usr/include -Ddebug=$(debug)
|
||||||
CFLAGS = -ws $(CPPFLAGS)
|
CFLAGS = $(CPPFLAGS)
|
||||||
LDFLAGS = -i -o $@
|
LDFLAGS = -i -o $@
|
||||||
|
|
||||||
SRCS = 3c501.c 3c509.c 3c503.c ne.c wd.c 8390.c devio.c netbuff.c dp.c
|
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)
|
PUBLIC unsigned int inb(unsigned short port)
|
||||||
{
|
{
|
||||||
unsigned int value;
|
unsigned long value;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
if ((rc = sys_inb(port, &value)) != OK) warning("inb", 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)
|
PUBLIC unsigned int inw(unsigned short port)
|
||||||
{
|
{
|
||||||
unsigned int value;
|
unsigned long value;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
if ((rc = sys_inw(port, &value)) != OK) warning("inw", 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
|
** File: eth.c Version 1.00, Jan. 14, 1997
|
||||||
**
|
**
|
||||||
|
|
@ -29,7 +30,7 @@
|
||||||
** +------------+---------+---------+--------+-------+---------+
|
** +------------+---------+---------+--------+-------+---------+
|
||||||
** | DL_READV | port nr | proc nr | count | | address | (6)
|
** | 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)
|
** | DL_STOP | port_nr | | | | | (8)
|
||||||
** +------------+---------+---------+--------+-------+---------+
|
** +------------+---------+---------+--------+-------+---------+
|
||||||
|
|
@ -45,7 +46,7 @@
|
||||||
**
|
**
|
||||||
** m_type m3_i1 m3_i2 m3_ca1
|
** 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$
|
** $Id$
|
||||||
|
|
@ -80,13 +81,13 @@ static dp_conf_t dp_conf[DE_PORT_NR] = {
|
||||||
{ 0x280, 10, 0xCC000, "DPETH1", },
|
{ 0x280, 10, 0xCC000, "DPETH1", },
|
||||||
};
|
};
|
||||||
|
|
||||||
static const char CopyErrMsg[] = "unable to read/write user data";
|
static char CopyErrMsg[] = "unable to read/write user data";
|
||||||
static const char PortErrMsg[] = "illegal port";
|
static char PortErrMsg[] = "illegal port";
|
||||||
static const char RecvErrMsg[] = "receive failed";
|
static char RecvErrMsg[] = "receive failed";
|
||||||
static const char SendErrMsg[] = "send failed";
|
static char SendErrMsg[] = "send failed";
|
||||||
static const char SizeErrMsg[] = "illegal packet size";
|
static char SizeErrMsg[] = "illegal packet size";
|
||||||
static const char TypeErrMsg[] = "illegal message type";
|
static char TypeErrMsg[] = "illegal message type";
|
||||||
static const char DevName[] = "eth#?";
|
static char DevName[] = "eth#?";
|
||||||
|
|
||||||
static void do_getname(message *mp);
|
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.
|
** 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;
|
int rc;
|
||||||
vir_bytes len;
|
vir_bytes len;
|
||||||
|
|
||||||
len = (count > IOVEC_NR ? IOVEC_NR : count) * sizeof(iovec_t);
|
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);
|
panic(DevName, CopyErrMsg, rc);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -339,7 +341,7 @@ static void do_init(message * mp)
|
||||||
} else /* Port number is out of range */
|
} else /* Port number is out of range */
|
||||||
port = ENXIO;
|
port = ENXIO;
|
||||||
|
|
||||||
reply_mess.m_type = DL_INIT_REPLY;
|
reply_mess.m_type = DL_CONF_REPLY;
|
||||||
reply_mess.m3_i1 = port;
|
reply_mess.m3_i1 = port;
|
||||||
reply_mess.m3_i2 = DE_PORT_NR;
|
reply_mess.m3_i2 = DE_PORT_NR;
|
||||||
DEBUG(printf("\t reply %d\n", reply_mess.m_type));
|
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)
|
** Name: void dp_next_iovec(iovec_dat_t *iovp)
|
||||||
** Function: Retrieves data from next iovec element.
|
** 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_s -= IOVEC_NR;
|
||||||
iovp->iod_iovec_addr += IOVEC_NR * sizeof(iovec_t);
|
iovp->iod_iovec_offset += IOVEC_NR * sizeof(iovec_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, iovp->iod_iovec);
|
iovp->iod_iovec_s, iovp->iod_iovec);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -367,7 +369,7 @@ PUBLIC void dp_next_iovec(iovec_dat_t * iovp)
|
||||||
** Name: int calc_iovec_size(iovec_dat_t *iovp)
|
** Name: int calc_iovec_size(iovec_dat_t *iovp)
|
||||||
** Function: Compute the size of a request.
|
** 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;
|
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:
|
** Function:
|
||||||
*/
|
*/
|
||||||
static void do_vwrite(message * mp, int vectored)
|
static void do_vwrite_s(message * mp)
|
||||||
{
|
{
|
||||||
int port, size;
|
int port, size;
|
||||||
dpeth_t *dep;
|
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);
|
panic(dep->de_name, "send already in progress ", NO_NUM);
|
||||||
|
|
||||||
dep->de_write_iovec.iod_proc_nr = mp->DL_PROC;
|
dep->de_write_iovec.iod_proc_nr = mp->DL_PROC;
|
||||||
if (vectored) {
|
get_userdata_s(mp->DL_PROC, mp->DL_GRANT, 0,
|
||||||
get_userdata(mp->DL_PROC, (vir_bytes) mp->DL_ADDR,
|
|
||||||
mp->DL_COUNT, dep->de_write_iovec.iod_iovec);
|
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_s = mp->DL_COUNT;
|
||||||
dep->de_write_iovec.iod_iovec_addr = (vir_bytes) mp->DL_ADDR;
|
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);
|
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;
|
|
||||||
}
|
|
||||||
if (size < ETH_MIN_PACK_SIZE || size > ETH_MAX_PACK_SIZE)
|
if (size < ETH_MIN_PACK_SIZE || size > ETH_MAX_PACK_SIZE)
|
||||||
panic(dep->de_name, SizeErrMsg, 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:
|
** Function:
|
||||||
*/
|
*/
|
||||||
static void do_vread(message * mp, int vectored)
|
static void do_vread_s(message * mp)
|
||||||
{
|
{
|
||||||
int port, size;
|
int port, size;
|
||||||
dpeth_t *dep;
|
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);
|
panic(dep->de_name, "read already in progress", NO_NUM);
|
||||||
|
|
||||||
dep->de_read_iovec.iod_proc_nr = mp->DL_PROC;
|
dep->de_read_iovec.iod_proc_nr = mp->DL_PROC;
|
||||||
if (vectored) {
|
get_userdata_s(mp->DL_PROC, (vir_bytes) mp->DL_GRANT, 0,
|
||||||
get_userdata(mp->DL_PROC, (vir_bytes) mp->DL_ADDR,
|
|
||||||
mp->DL_COUNT, dep->de_read_iovec.iod_iovec);
|
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_s = mp->DL_COUNT;
|
||||||
dep->de_read_iovec.iod_iovec_addr = (vir_bytes) mp->DL_ADDR;
|
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);
|
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;
|
|
||||||
}
|
|
||||||
if (size < ETH_MAX_PACK_SIZE) panic(dep->de_name, SizeErrMsg, size);
|
if (size < ETH_MAX_PACK_SIZE) panic(dep->de_name, SizeErrMsg, size);
|
||||||
|
|
||||||
dep->de_flags |= DEF_READING;
|
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.
|
** Function: Reports device statistics.
|
||||||
*/
|
*/
|
||||||
static void do_getstat(message * mp)
|
static void do_getstat_s(message * mp)
|
||||||
{
|
{
|
||||||
int port, rc;
|
int port, rc;
|
||||||
dpeth_t *dep;
|
dpeth_t *dep;
|
||||||
|
|
@ -497,9 +487,9 @@ static void do_getstat(message * mp)
|
||||||
dep->de_client = mp->DL_PROC;
|
dep->de_client = mp->DL_PROC;
|
||||||
|
|
||||||
if (dep->de_mode == DEM_ENABLED) (*dep->de_getstatsf) (dep);
|
if (dep->de_mode == DEM_ENABLED) (*dep->de_getstatsf) (dep);
|
||||||
if ((rc = sys_datacopy(SELF, (vir_bytes)&dep->de_stat,
|
if ((rc = sys_safecopyto(mp->DL_PROC, mp->DL_GRANT, 0,
|
||||||
mp->DL_PROC, (vir_bytes)mp->DL_ADDR,
|
(vir_bytes)&dep->de_stat,
|
||||||
(vir_bytes) sizeof(dep->de_stat))) != OK)
|
(vir_bytes) sizeof(dep->de_stat), 0)) != OK)
|
||||||
panic(DevName, CopyErrMsg, rc);
|
panic(DevName, CopyErrMsg, rc);
|
||||||
reply(dep, OK);
|
reply(dep, OK);
|
||||||
return;
|
return;
|
||||||
|
|
@ -592,23 +582,17 @@ PUBLIC int main(int argc, char **argv)
|
||||||
case DEV_PING: /* Status request from RS */
|
case DEV_PING: /* Status request from RS */
|
||||||
notify(m.m_source);
|
notify(m.m_source);
|
||||||
continue;
|
continue;
|
||||||
case DL_WRITE: /* Write message to device */
|
case DL_WRITEV_S: /* Write message to device */
|
||||||
do_vwrite(&m, FALSE);
|
do_vwrite_s(&m);
|
||||||
break;
|
break;
|
||||||
case DL_WRITEV: /* Write message to device */
|
case DL_READV_S: /* Read message from device */
|
||||||
do_vwrite(&m, TRUE);
|
do_vread_s(&m);
|
||||||
break;
|
break;
|
||||||
case DL_READ: /* Read message from device */
|
case DL_CONF: /* Initialize device */
|
||||||
do_vread(&m, FALSE);
|
|
||||||
break;
|
|
||||||
case DL_READV: /* Read message from device */
|
|
||||||
do_vread(&m, TRUE);
|
|
||||||
break;
|
|
||||||
case DL_INIT: /* Initialize device */
|
|
||||||
do_init(&m);
|
do_init(&m);
|
||||||
break;
|
break;
|
||||||
case DL_GETSTAT: /* Get device statistics */
|
case DL_GETSTAT_S: /* Get device statistics */
|
||||||
do_getstat(&m);
|
do_getstat_s(&m);
|
||||||
break;
|
break;
|
||||||
case DL_GETNAME:
|
case DL_GETNAME:
|
||||||
do_getname(&m);
|
do_getname(&m);
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,9 @@
|
||||||
** Interface description for ethernet device driver
|
** Interface description for ethernet device driver
|
||||||
**
|
**
|
||||||
** $Log$
|
** $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
|
** Revision 1.4 2005/09/04 18:52:16 beng
|
||||||
** Giovanni's fixes to dpeth:
|
** Giovanni's fixes to dpeth:
|
||||||
** Date: Sat, 03 Sep 2005 11:05:22 +0200
|
** 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 SENDQ_NR 2 /* Size of the send queue */
|
||||||
#define IOVEC_NR 16 /* Number of IOVEC entries at a time */
|
#define IOVEC_NR 16 /* Number of IOVEC entries at a time */
|
||||||
|
|
||||||
typedef struct iovec_dat {
|
typedef struct iovec_dat_s {
|
||||||
iovec_t iod_iovec[IOVEC_NR];
|
iovec_s_t iod_iovec[IOVEC_NR];
|
||||||
int iod_iovec_s;
|
int iod_iovec_s;
|
||||||
int iod_proc_nr;
|
int iod_proc_nr;
|
||||||
vir_bytes iod_iovec_addr;
|
cp_grant_id_t iod_grant;
|
||||||
} iovec_dat_t;
|
vir_bytes iod_iovec_offset;
|
||||||
|
} iovec_dat_s_t;
|
||||||
|
|
||||||
typedef struct dpeth {
|
typedef struct dpeth {
|
||||||
/* The de_base_port field is the starting point of the probe. The
|
/* The de_base_port field is the starting point of the probe. The
|
||||||
|
|
@ -161,8 +165,8 @@ typedef struct dpeth {
|
||||||
#define DEM_ENABLED 0x0002
|
#define DEM_ENABLED 0x0002
|
||||||
|
|
||||||
/* Temporary storage for RECV/SEND requests */
|
/* Temporary storage for RECV/SEND requests */
|
||||||
iovec_dat_t de_read_iovec;
|
iovec_dat_s_t de_read_iovec;
|
||||||
iovec_dat_t de_write_iovec;
|
iovec_dat_s_t de_write_iovec;
|
||||||
vir_bytes de_read_s;
|
vir_bytes de_read_s;
|
||||||
vir_bytes de_send_s;
|
vir_bytes de_send_s;
|
||||||
int de_client;
|
int de_client;
|
||||||
|
|
@ -216,7 +220,7 @@ typedef struct dpeth {
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* dp.c */
|
/* dp.c */
|
||||||
void dp_next_iovec(iovec_dat_t * iovp);
|
void dp_next_iovec(iovec_dat_s_t * iovp);
|
||||||
|
|
||||||
/* devio.c */
|
/* devio.c */
|
||||||
#if defined USE_IOPL
|
#if defined USE_IOPL
|
||||||
|
|
|
||||||
|
|
@ -111,8 +111,8 @@ PUBLIC void mem2user(dpeth_t *dep, buff_t *rxbuff)
|
||||||
{
|
{
|
||||||
phys_bytes phys_user;
|
phys_bytes phys_user;
|
||||||
int bytes, ix = 0;
|
int bytes, ix = 0;
|
||||||
iovec_dat_t *iovp = &dep->de_read_iovec;
|
iovec_dat_s_t *iovp = &dep->de_read_iovec;
|
||||||
int pktsize = rxbuff->size;
|
int r, pktsize = rxbuff->size;
|
||||||
char *buffer = rxbuff->buffer;
|
char *buffer = rxbuff->buffer;
|
||||||
|
|
||||||
do { /* Reads chuncks of packet into user buffers */
|
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;
|
if (bytes > pktsize) bytes = pktsize;
|
||||||
|
|
||||||
/* Reads from Rx buffer to user area */
|
/* Reads from Rx buffer to user area */
|
||||||
sys_datacopy(SELF, (vir_bytes)buffer, iovp->iod_proc_nr,
|
r= sys_safecopyto(iovp->iod_proc_nr, iovp->iod_iovec[ix].iov_grant, 0,
|
||||||
iovp->iod_iovec[ix].iov_addr, bytes);
|
(vir_bytes)buffer, bytes, D);
|
||||||
|
if (r != OK)
|
||||||
|
panic(__FILE__, "mem2user: sys_safecopyto failed", r);
|
||||||
buffer += bytes;
|
buffer += bytes;
|
||||||
|
|
||||||
if (++ix >= IOVEC_NR) { /* Next buffer of IO vector */
|
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;
|
phys_bytes phys_user;
|
||||||
int bytes, ix = 0;
|
int bytes, ix = 0;
|
||||||
iovec_dat_t *iovp = &dep->de_write_iovec;
|
iovec_dat_s_t *iovp = &dep->de_write_iovec;
|
||||||
int pktsize = txbuff->size;
|
int r, pktsize = txbuff->size;
|
||||||
char *buffer = txbuff->buffer;
|
char *buffer = txbuff->buffer;
|
||||||
|
|
||||||
do { /* Reads chuncks of packet from user buffers */
|
do { /* Reads chuncks of packet from user buffers */
|
||||||
|
|
||||||
bytes = iovp->iod_iovec[ix].iov_size; /* Size of buffer */
|
bytes = iovp->iod_iovec[ix].iov_size; /* Size of buffer */
|
||||||
if (bytes > pktsize) bytes = pktsize;
|
if (bytes > pktsize) bytes = pktsize;
|
||||||
sys_datacopy(iovp->iod_proc_nr, iovp->iod_iovec[ix].iov_addr,
|
r= sys_safecopyfrom(iovp->iod_proc_nr, iovp->iod_iovec[ix].iov_grant,
|
||||||
SELF, (vir_bytes)buffer, bytes);
|
0, (vir_bytes)buffer, bytes, D);
|
||||||
|
if (r != OK)
|
||||||
|
panic(__FILE__, "user2mem: sys_safecopyfrom failed", r);
|
||||||
buffer += bytes;
|
buffer += bytes;
|
||||||
|
|
||||||
if (++ix >= IOVEC_NR) { /* Next buffer of IO vector */
|
if (++ix >= IOVEC_NR) { /* Next buffer of IO vector */
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@ OBJ = fxp.o mii.o
|
||||||
all build: $(DRIVER)
|
all build: $(DRIVER)
|
||||||
$(DRIVER): $(OBJ)
|
$(DRIVER): $(OBJ)
|
||||||
$(CC) -o $@ $(LDFLAGS) $(OBJ) $(LIBS)
|
$(CC) -o $@ $(LDFLAGS) $(OBJ) $(LIBS)
|
||||||
install -S 4096 $(DRIVER)
|
install -S 8k $(DRIVER)
|
||||||
|
|
||||||
# install with other drivers
|
# install with other drivers
|
||||||
install: /usr/sbin/$(DRIVER)
|
install: /usr/sbin/$(DRIVER)
|
||||||
|
|
|
||||||
|
|
@ -6,24 +6,30 @@
|
||||||
*
|
*
|
||||||
* The valid messages and their parameters are:
|
* The valid messages and their parameters are:
|
||||||
*
|
*
|
||||||
* m_type DL_PORT DL_PROC DL_COUNT DL_MODE DL_ADDR
|
* m_type DL_PORT DL_PROC DL_COUNT DL_MODE DL_ADDR DL_GRANT
|
||||||
* |------------+----------+---------+----------+---------+---------|
|
* |------------+----------+---------+----------+---------+---------+---------|
|
||||||
* | HARDINT | | | | | |
|
* | HARDINT | | | | | | |
|
||||||
* |------------|----------|---------|----------|---------|---------|
|
* |------------|----------|---------|----------|---------|---------|---------|
|
||||||
* | DL_WRITE | port nr | proc nr | count | mode | address |
|
* | DL_WRITE | port nr | proc nr | count | mode | address | |
|
||||||
* |------------|----------|---------|----------|---------|---------|
|
* |------------|----------|---------|----------|---------|---------|---------|
|
||||||
* | DL_WRITEV | 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_WRITEV_S| port nr | proc nr | count | mode | | grant |
|
||||||
* |------------|----------|---------|----------|---------|---------|
|
* |------------|----------|---------|----------|---------|---------|---------|
|
||||||
* | DL_READV | port nr | proc nr | count | | address |
|
* | DL_READ | port nr | proc nr | count | | address | |
|
||||||
* |------------|----------|---------|----------|---------|---------|
|
* |------------|----------|---------|----------|---------|---------|---------|
|
||||||
* | DL_INIT | port nr | proc nr | mode | | address |
|
* | DL_READV | port nr | proc nr | count | | address | |
|
||||||
* |------------|----------|---------|----------|---------|---------|
|
* |------------|----------|---------|----------|---------|---------|---------|
|
||||||
* | DL_GETSTAT | port nr | proc nr | | | address |
|
* | DL_READV_S | port nr | proc nr | count | | | grant |
|
||||||
* |------------|----------|---------|----------|---------|---------|
|
* |------------|----------|---------|----------|---------|---------|---------|
|
||||||
* | DL_STOP | port_nr | | | | |
|
* | 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:
|
* The messages sent are:
|
||||||
*
|
*
|
||||||
|
|
@ -34,7 +40,7 @@
|
||||||
*
|
*
|
||||||
* m_type m3_i1 m3_i2 m3_ca1
|
* 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>
|
* 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];
|
u8_t fxp_conf_bytes[CC_BYTES_NR];
|
||||||
char fxp_name[sizeof("fxp#n")];
|
char fxp_name[sizeof("fxp#n")];
|
||||||
iovec_t fxp_iovec[IOVEC_NR];
|
iovec_t fxp_iovec[IOVEC_NR];
|
||||||
|
iovec_s_t fxp_iovec_s[IOVEC_NR];
|
||||||
}
|
}
|
||||||
fxp_t;
|
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_rec_mode, (fxp_t *fp) );
|
||||||
_PROTOTYPE( static void fxp_writev, (message *mp, int from_int,
|
_PROTOTYPE( static void fxp_writev, (message *mp, int from_int,
|
||||||
int vectored) );
|
int vectored) );
|
||||||
|
_PROTOTYPE( static void fxp_writev_s, (message *mp, int from_int) );
|
||||||
_PROTOTYPE( static void fxp_readv, (message *mp, int from_int,
|
_PROTOTYPE( static void fxp_readv, (message *mp, int from_int,
|
||||||
int vectored) );
|
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_do_conf, (fxp_t *fp) );
|
||||||
_PROTOTYPE( static void fxp_cu_ptr_cmd, (fxp_t *fp, int cmd,
|
_PROTOTYPE( static void fxp_cu_ptr_cmd, (fxp_t *fp, int cmd,
|
||||||
phys_bytes bus_addr, int check_idle) );
|
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) );
|
phys_bytes bus_addr, int check_idle) );
|
||||||
_PROTOTYPE( static void fxp_restart_ru, (fxp_t *fp) );
|
_PROTOTYPE( static void fxp_restart_ru, (fxp_t *fp) );
|
||||||
_PROTOTYPE( static void fxp_getstat, (message *mp) );
|
_PROTOTYPE( static void fxp_getstat, (message *mp) );
|
||||||
|
_PROTOTYPE( static void fxp_getstat_s, (message *mp) );
|
||||||
_PROTOTYPE( static void fxp_getname, (message *mp) );
|
_PROTOTYPE( static void fxp_getname, (message *mp) );
|
||||||
_PROTOTYPE( static int fxp_handler, (fxp_t *fp) );
|
_PROTOTYPE( static int fxp_handler, (fxp_t *fp) );
|
||||||
_PROTOTYPE( static void fxp_check_ints, (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 fxp_stop, (void));
|
||||||
_PROTOTYPE( static void reply, (fxp_t *fp, int err, int may_block) );
|
_PROTOTYPE( static void reply, (fxp_t *fp, int err, int may_block) );
|
||||||
_PROTOTYPE( static void mess_reply, (message *req, message *reply) );
|
_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 u16_t eeprom_read, (fxp_t *fp, int reg) );
|
||||||
_PROTOTYPE( static void eeprom_addrsize, (fxp_t *fp) );
|
_PROTOTYPE( static void eeprom_addrsize, (fxp_t *fp) );
|
||||||
_PROTOTYPE( static u16_t mii_read, (fxp_t *fp, int reg) );
|
_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 DEV_PING: notify(m.m_source); continue;
|
||||||
case DL_WRITEV: fxp_writev(&m, FALSE, TRUE); break;
|
case DL_WRITEV: fxp_writev(&m, FALSE, TRUE); break;
|
||||||
case DL_WRITE: fxp_writev(&m, FALSE, FALSE); break;
|
case DL_WRITE: fxp_writev(&m, FALSE, FALSE); break;
|
||||||
#if 0
|
case DL_WRITEV_S: fxp_writev_s(&m, FALSE); break;
|
||||||
case DL_READ: fxp_vread(&m, FALSE); break;
|
case DL_READ: fxp_readv(&m, FALSE, FALSE); break;
|
||||||
#endif
|
|
||||||
case DL_READV: fxp_readv(&m, FALSE, TRUE); 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: fxp_getstat(&m); break;
|
||||||
|
case DL_GETSTAT_S: fxp_getstat_s(&m); break;
|
||||||
case DL_GETNAME: fxp_getname(&m); break;
|
case DL_GETNAME: fxp_getname(&m); break;
|
||||||
case HARD_INT:
|
case HARD_INT:
|
||||||
for (i= 0, fp= &fxp_table[0]; i<FXP_PORT_NR; i++, fp++)
|
for (i= 0, fp= &fxp_table[0]; i<FXP_PORT_NR; i++, fp++)
|
||||||
|
|
@ -361,7 +370,7 @@ message *mp;
|
||||||
port = mp->DL_PORT;
|
port = mp->DL_PORT;
|
||||||
if (port < 0 || port >= FXP_PORT_NR)
|
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;
|
reply_mess.m3_i1= ENXIO;
|
||||||
mess_reply(mp, &reply_mess);
|
mess_reply(mp, &reply_mess);
|
||||||
return;
|
return;
|
||||||
|
|
@ -374,7 +383,7 @@ message *mp;
|
||||||
if (fp->fxp_mode == FM_DISABLED)
|
if (fp->fxp_mode == FM_DISABLED)
|
||||||
{
|
{
|
||||||
/* Probe failed, or the device is configured off. */
|
/* 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;
|
reply_mess.m3_i1= ENXIO;
|
||||||
mess_reply(mp, &reply_mess);
|
mess_reply(mp, &reply_mess);
|
||||||
return;
|
return;
|
||||||
|
|
@ -399,7 +408,7 @@ message *mp;
|
||||||
fp->fxp_client = mp->m_source;
|
fp->fxp_client = mp->m_source;
|
||||||
fxp_rec_mode(fp);
|
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_i1 = mp->DL_PORT;
|
||||||
reply_mess.m3_i2 = FXP_PORT_NR;
|
reply_mess.m3_i2 = FXP_PORT_NR;
|
||||||
*(ether_addr_t *) reply_mess.m3_ca1 = fp->fxp_address;
|
*(ether_addr_t *) reply_mess.m3_ca1 = fp->fxp_address;
|
||||||
|
|
@ -1194,6 +1203,152 @@ suspend:
|
||||||
reply(fp, OK, FALSE);
|
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 *
|
* fxp_readv *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
|
|
@ -1374,6 +1529,179 @@ suspend:
|
||||||
reply(fp, OK, FALSE);
|
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 *
|
* fxp_do_conf *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
|
|
@ -1529,7 +1857,7 @@ static void fxp_getstat(mp)
|
||||||
message *mp;
|
message *mp;
|
||||||
{
|
{
|
||||||
clock_t t0,t1;
|
clock_t t0,t1;
|
||||||
int dl_port;
|
int r, dl_port;
|
||||||
port_t port;
|
port_t port;
|
||||||
fxp_t *fp;
|
fxp_t *fp;
|
||||||
u32_t *p;
|
u32_t *p;
|
||||||
|
|
@ -1592,8 +1920,88 @@ message *mp;
|
||||||
stats.ets_CDheartbeat= 0;
|
stats.ets_CDheartbeat= 0;
|
||||||
stats.ets_OWC= fp->fxp_stat.sc_tx_latecol;
|
stats.ets_OWC= fp->fxp_stat.sc_tx_latecol;
|
||||||
|
|
||||||
put_userdata(mp->DL_PROC, (vir_bytes) mp->DL_ADDR,
|
r= sys_vircopy(SELF, D, (vir_bytes)&stats,
|
||||||
(vir_bytes) sizeof(stats), &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);
|
reply(fp, OK, FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1697,6 +2105,11 @@ fxp_t *fp;
|
||||||
fxp_readv(&fp->fxp_rx_mess, TRUE /* from int */,
|
fxp_readv(&fp->fxp_rx_mess, TRUE /* from int */,
|
||||||
TRUE /* vectored */);
|
TRUE /* vectored */);
|
||||||
}
|
}
|
||||||
|
else if (fp->fxp_rx_mess.m_type == DL_READV_S)
|
||||||
|
{
|
||||||
|
fxp_readv_s(&fp->fxp_rx_mess, TRUE /* from int */);
|
||||||
|
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
assert(fp->fxp_rx_mess.m_type == DL_READ);
|
assert(fp->fxp_rx_mess.m_type == DL_READ);
|
||||||
|
|
@ -1803,6 +2216,11 @@ fxp_t *fp;
|
||||||
TRUE /* from int */,
|
TRUE /* from int */,
|
||||||
TRUE /* vectored */);
|
TRUE /* vectored */);
|
||||||
}
|
}
|
||||||
|
else if (fp->fxp_tx_mess.m_type == DL_WRITEV_S)
|
||||||
|
{
|
||||||
|
fxp_writev_s(&fp->fxp_tx_mess,
|
||||||
|
TRUE /* from int */);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
assert(fp->fxp_tx_mess.m_type ==
|
assert(fp->fxp_tx_mess.m_type ==
|
||||||
|
|
@ -2212,23 +2630,6 @@ message *reply_mess;
|
||||||
panic("FXP","fxp: unable to mess_reply", NO_NUM);
|
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 *
|
* eeprom_read *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
|
|
|
||||||
|
|
@ -6,24 +6,30 @@
|
||||||
*
|
*
|
||||||
* The valid messages and their parameters are:
|
* The valid messages and their parameters are:
|
||||||
*
|
*
|
||||||
* m_type DL_PORT DL_PROC DL_COUNT DL_MODE DL_ADDR
|
* m_type DL_PORT DL_PROC DL_COUNT DL_MODE DL_ADDR DL_GRANT
|
||||||
* |------------+----------+---------+----------+---------+---------|
|
* |------------+----------+---------+----------+---------+---------+---------|
|
||||||
* | HARDINT | | | | | |
|
* | HARDINT | | | | | | |
|
||||||
* |------------|----------|---------|----------|---------|---------|
|
* |------------|----------|---------|----------|---------|---------|---------|
|
||||||
* | DL_WRITE | port nr | proc nr | count | mode | address |
|
* | DL_WRITE | port nr | proc nr | count | mode | address | |
|
||||||
* |------------|----------|---------|----------|---------|---------|
|
* |------------|----------|---------|----------|---------|---------|---------|
|
||||||
* | DL_WRITEV | 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_WRITEV_S| port nr | proc nr | count | mode | | grant |
|
||||||
* |------------|----------|---------|----------|---------|---------|
|
* |------------|----------|---------|----------|---------|---------|---------|
|
||||||
* | DL_READV | port nr | proc nr | count | | address |
|
* | DL_READ | port nr | proc nr | count | | address | |
|
||||||
* |------------|----------|---------|----------|---------|---------|
|
* |------------|----------|---------|----------|---------|---------|---------|
|
||||||
* | DL_INIT | port nr | proc nr | mode | | address |
|
* | DL_READV | port nr | proc nr | count | | address | |
|
||||||
* |------------|----------|---------|----------|---------|---------|
|
* |------------|----------|---------|----------|---------|---------|---------|
|
||||||
* | DL_GETSTAT | port nr | proc nr | | | address |
|
* | DL_READV_S | port nr | proc nr | count | | | grant |
|
||||||
* |------------|----------|---------|----------|---------|---------|
|
* |------------|----------|---------|----------|---------|---------|---------|
|
||||||
* | DL_STOP | port_nr | | | | |
|
* | 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:
|
* The messages sent are:
|
||||||
*
|
*
|
||||||
|
|
@ -34,7 +40,7 @@
|
||||||
*
|
*
|
||||||
* m_type m3_i1 m3_i2 m3_ca1
|
* 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>
|
* 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_reset, (ether_card_t *ec) );
|
||||||
_PROTOTYPE( static void ec_send, (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 ec_recv, (ether_card_t *ec) );
|
||||||
_PROTOTYPE( static void do_vwrite,
|
_PROTOTYPE( static void do_vwrite_s,
|
||||||
(message *mp, int from_int, int vectored) );
|
(message *mp, int from_int) );
|
||||||
_PROTOTYPE( static void do_vread, (message *mp, int vectored) );
|
_PROTOTYPE( static void do_vread_s, (message *mp) );
|
||||||
_PROTOTYPE( static void get_userdata,
|
_PROTOTYPE( static void get_userdata_s,
|
||||||
(int user_proc, vir_bytes user_addr,
|
(int user_proc, cp_grant_id_t grant, vir_bytes offset,
|
||||||
vir_bytes count, void *loc_addr) );
|
vir_bytes count, void *loc_addr) );
|
||||||
_PROTOTYPE( static void ec_user2nic,
|
_PROTOTYPE( static void ec_user2nic,
|
||||||
(ether_card_t *dep, iovec_dat_t *iovp,
|
(ether_card_t *dep, iovec_dat_t *iovp,
|
||||||
|
|
@ -160,11 +166,10 @@ _PROTOTYPE( static void ec_nic2user,
|
||||||
vir_bytes count) );
|
vir_bytes count) );
|
||||||
_PROTOTYPE( static int calc_iovec_size, (iovec_dat_t *iovp) );
|
_PROTOTYPE( static int calc_iovec_size, (iovec_dat_t *iovp) );
|
||||||
_PROTOTYPE( static void ec_next_iovec, (iovec_dat_t *iovp) );
|
_PROTOTYPE( static void ec_next_iovec, (iovec_dat_t *iovp) );
|
||||||
_PROTOTYPE( static void do_getstat, (message *mp) );
|
_PROTOTYPE( static void do_getstat_s, (message *mp) );
|
||||||
_PROTOTYPE( static void put_userdata,
|
_PROTOTYPE( static void put_userdata_s,
|
||||||
(int user_proc,
|
(int user_proc, cp_grant_id_t grant,
|
||||||
vir_bytes user_addr, vir_bytes count,
|
void *loc_addr, vir_bytes count) );
|
||||||
void *loc_addr) );
|
|
||||||
_PROTOTYPE( static void do_stop, (message *mp) );
|
_PROTOTYPE( static void do_stop, (message *mp) );
|
||||||
_PROTOTYPE( static void do_getname, (message *mp) );
|
_PROTOTYPE( static void do_getname, (message *mp) );
|
||||||
|
|
||||||
|
|
@ -356,12 +361,10 @@ void main( int argc, char **argv )
|
||||||
|
|
||||||
switch (m.m_type){
|
switch (m.m_type){
|
||||||
case DEV_PING: notify(m.m_source); continue;
|
case DEV_PING: notify(m.m_source); continue;
|
||||||
case DL_WRITE: do_vwrite(&m, FALSE, FALSE); break;
|
case DL_WRITEV_S: do_vwrite_s(&m, FALSE); break;
|
||||||
case DL_WRITEV: do_vwrite(&m, FALSE, TRUE); break;
|
case DL_READV_S: do_vread_s(&m); break;
|
||||||
case DL_READ: do_vread(&m, FALSE); break;
|
case DL_CONF: do_init(&m); break;
|
||||||
case DL_READV: do_vread(&m, TRUE); break;
|
case DL_GETSTAT_S: do_getstat_s(&m); break;
|
||||||
case DL_INIT: do_init(&m); break;
|
|
||||||
case DL_GETSTAT: do_getstat(&m); break;
|
|
||||||
case DL_STOP: do_stop(&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 FKEY_PRESSED: lance_dump(); break;
|
||||||
|
|
@ -493,7 +496,7 @@ pci_init();
|
||||||
port = mp->DL_PORT;
|
port = mp->DL_PORT;
|
||||||
if (port < 0 || port >= EC_PORT_NR_MAX)
|
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;
|
reply_mess.m3_i1= ENXIO;
|
||||||
mess_reply(mp, &reply_mess);
|
mess_reply(mp, &reply_mess);
|
||||||
return;
|
return;
|
||||||
|
|
@ -517,7 +520,7 @@ pci_init();
|
||||||
if (ec->mode == EC_DISABLED)
|
if (ec->mode == EC_DISABLED)
|
||||||
{
|
{
|
||||||
/* Probe failed, or the device is configured off. */
|
/* 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;
|
reply_mess.m3_i1= ENXIO;
|
||||||
mess_reply(mp, &reply_mess);
|
mess_reply(mp, &reply_mess);
|
||||||
return;
|
return;
|
||||||
|
|
@ -535,7 +538,7 @@ pci_init();
|
||||||
ec->mac_address.ea_addr[4] =
|
ec->mac_address.ea_addr[4] =
|
||||||
ec->mac_address.ea_addr[5] = 0;
|
ec->mac_address.ea_addr[5] = 0;
|
||||||
ec_confaddr(ec);
|
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_i1 = mp->DL_PORT;
|
||||||
reply_mess.m3_i2 = EC_PORT_NR_MAX;
|
reply_mess.m3_i2 = EC_PORT_NR_MAX;
|
||||||
*(ether_addr_t *) reply_mess.m3_ca1 = ec->mac_address;
|
*(ether_addr_t *) reply_mess.m3_ca1 = ec->mac_address;
|
||||||
|
|
@ -557,7 +560,7 @@ pci_init();
|
||||||
ec->client = mp->m_source;
|
ec->client = mp->m_source;
|
||||||
ec_reinit(ec);
|
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_i1 = mp->DL_PORT;
|
||||||
reply_mess.m3_i2 = EC_PORT_NR_MAX;
|
reply_mess.m3_i2 = EC_PORT_NR_MAX;
|
||||||
*(ether_addr_t *) reply_mess.m3_ca1 = ec->mac_address;
|
*(ether_addr_t *) reply_mess.m3_ca1 = ec->mac_address;
|
||||||
|
|
@ -1071,8 +1074,7 @@ ether_card_t *ec;
|
||||||
ec->flags &= ~ECF_SEND_AVAIL;
|
ec->flags &= ~ECF_SEND_AVAIL;
|
||||||
switch(ec->sendmsg.m_type)
|
switch(ec->sendmsg.m_type)
|
||||||
{
|
{
|
||||||
case DL_WRITE: do_vwrite(&ec->sendmsg, TRUE, FALSE); break;
|
case DL_WRITEV_S: do_vwrite_s(&ec->sendmsg, TRUE); break;
|
||||||
case DL_WRITEV: do_vwrite(&ec->sendmsg, TRUE, TRUE); break;
|
|
||||||
default:
|
default:
|
||||||
panic( "lance", "wrong type:", ec->sendmsg.m_type);
|
panic( "lance", "wrong type:", ec->sendmsg.m_type);
|
||||||
break;
|
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;
|
message *mp;
|
||||||
int vectored;
|
|
||||||
{
|
{
|
||||||
int port, count, size;
|
int port, count, size;
|
||||||
ether_card_t *ec;
|
ether_card_t *ec;
|
||||||
|
|
@ -1094,28 +1095,17 @@ int vectored;
|
||||||
ec= &ec_table[port];
|
ec= &ec_table[port];
|
||||||
ec->client= mp->DL_PROC;
|
ec->client= mp->DL_PROC;
|
||||||
|
|
||||||
if (vectored)
|
get_userdata_s(mp->DL_PROC, (vir_bytes) mp->DL_GRANT, 0,
|
||||||
{
|
|
||||||
get_userdata(mp->DL_PROC, (vir_bytes) mp->DL_ADDR,
|
|
||||||
(count > IOVEC_NR ? IOVEC_NR : count) *
|
(count > IOVEC_NR ? IOVEC_NR : count) *
|
||||||
sizeof(iovec_t), ec->read_iovec.iod_iovec);
|
sizeof(iovec_s_t), ec->read_iovec.iod_iovec);
|
||||||
ec->read_iovec.iod_iovec_s = count;
|
ec->read_iovec.iod_iovec_s = count;
|
||||||
ec->read_iovec.iod_proc_nr = mp->DL_PROC;
|
ec->read_iovec.iod_proc_nr = mp->DL_PROC;
|
||||||
ec->read_iovec.iod_iovec_addr = (vir_bytes) mp->DL_ADDR;
|
ec->read_iovec.iod_grant = (vir_bytes) mp->DL_GRANT;
|
||||||
|
ec->read_iovec.iod_iovec_offset = 0;
|
||||||
|
|
||||||
ec->tmp_iovec = ec->read_iovec;
|
ec->tmp_iovec = ec->read_iovec;
|
||||||
size= calc_iovec_size(&ec->tmp_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;
|
|
||||||
|
|
||||||
size= count;
|
|
||||||
}
|
|
||||||
ec->flags |= ECF_READING;
|
ec->flags |= ECF_READING;
|
||||||
|
|
||||||
ec_recv(ec);
|
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;
|
message *mp;
|
||||||
int from_int;
|
int from_int;
|
||||||
int vectored;
|
|
||||||
{
|
{
|
||||||
int port, count, check;
|
int port, count, check;
|
||||||
ether_card_t *ec;
|
ether_card_t *ec;
|
||||||
|
|
@ -1221,30 +1210,17 @@ int vectored;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* convert the message to write_iovec */
|
/* convert the message to write_iovec */
|
||||||
if (vectored)
|
get_userdata_s(mp->DL_PROC, mp->DL_GRANT, 0,
|
||||||
{
|
|
||||||
get_userdata(mp->DL_PROC, (vir_bytes) mp->DL_ADDR,
|
|
||||||
(count > IOVEC_NR ? IOVEC_NR : count) *
|
(count > IOVEC_NR ? IOVEC_NR : count) *
|
||||||
sizeof(iovec_t), ec->write_iovec.iod_iovec);
|
sizeof(iovec_s_t), ec->write_iovec.iod_iovec);
|
||||||
|
|
||||||
ec->write_iovec.iod_iovec_s = count;
|
ec->write_iovec.iod_iovec_s = count;
|
||||||
ec->write_iovec.iod_proc_nr = mp->DL_PROC;
|
ec->write_iovec.iod_proc_nr = mp->DL_PROC;
|
||||||
ec->write_iovec.iod_iovec_addr = (vir_bytes) mp->DL_ADDR;
|
ec->write_iovec.iod_grant = mp->DL_GRANT;
|
||||||
|
ec->write_iovec.iod_iovec_offset = 0;
|
||||||
|
|
||||||
ec->tmp_iovec = ec->write_iovec;
|
ec->tmp_iovec = ec->write_iovec;
|
||||||
ec->write_s = calc_iovec_size(&ec->tmp_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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* copy write_iovec to the slot on DMA address */
|
/* copy write_iovec to the slot on DMA address */
|
||||||
ec_user2nic(ec, &ec->write_iovec, 0,
|
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;
|
int user_proc;
|
||||||
vir_bytes user_addr;
|
cp_grant_id_t grant;
|
||||||
|
vir_bytes offset;
|
||||||
vir_bytes count;
|
vir_bytes count;
|
||||||
void *loc_addr;
|
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;
|
int cps;
|
||||||
cps = sys_datacopy(user_proc, user_addr, SELF, (vir_bytes) loc_addr, count);
|
cps = sys_safecopyfrom(user_proc, grant, offset,
|
||||||
if (cps != OK) printf("lance: warning, scopy failed: %d\n", cps);
|
(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;
|
int nic_addr;
|
||||||
vir_bytes count;
|
vir_bytes count;
|
||||||
{
|
{
|
||||||
/*phys_bytes phys_hw, phys_user;*/
|
|
||||||
int bytes, i, r;
|
int bytes, i, r;
|
||||||
|
|
||||||
/*
|
|
||||||
phys_hw = vir2phys(nic_addr);
|
|
||||||
*/
|
|
||||||
i= 0;
|
i= 0;
|
||||||
while (count > 0)
|
while (count > 0)
|
||||||
{
|
{
|
||||||
|
|
@ -1336,15 +1303,10 @@ vir_bytes count;
|
||||||
if (bytes > count)
|
if (bytes > count)
|
||||||
bytes = count;
|
bytes = count;
|
||||||
|
|
||||||
/*
|
if ( (r=sys_safecopyfrom(iovp->iod_proc_nr,
|
||||||
phys_user = numap_local(iovp->iod_proc_nr,
|
iovp->iod_iovec[i].iov_grant, offset,
|
||||||
iovp->iod_iovec[i].iov_addr + offset, bytes);
|
nic_addr, bytes, D )) != OK )
|
||||||
|
panic( __FILE__, "ec_user2nic: sys_safecopyfrom failed", r );
|
||||||
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 );
|
|
||||||
|
|
||||||
count -= bytes;
|
count -= bytes;
|
||||||
nic_addr += bytes;
|
nic_addr += bytes;
|
||||||
|
|
@ -1362,11 +1324,8 @@ iovec_dat_t *iovp;
|
||||||
vir_bytes offset;
|
vir_bytes offset;
|
||||||
vir_bytes count;
|
vir_bytes count;
|
||||||
{
|
{
|
||||||
/*phys_bytes phys_hw, phys_user;*/
|
|
||||||
int bytes, i, r;
|
int bytes, i, r;
|
||||||
|
|
||||||
/*phys_hw = vir2phys(nic_addr);*/
|
|
||||||
|
|
||||||
i= 0;
|
i= 0;
|
||||||
while (count > 0)
|
while (count > 0)
|
||||||
{
|
{
|
||||||
|
|
@ -1385,14 +1344,9 @@ vir_bytes count;
|
||||||
bytes = iovp->iod_iovec[i].iov_size - offset;
|
bytes = iovp->iod_iovec[i].iov_size - offset;
|
||||||
if (bytes > count)
|
if (bytes > count)
|
||||||
bytes = count;
|
bytes = count;
|
||||||
/*
|
if ( (r=sys_safecopyto( iovp->iod_proc_nr, iovp->iod_iovec[i].iov_grant,
|
||||||
phys_user = numap_local(iovp->iod_proc_nr,
|
offset, nic_addr, bytes, D )) != OK )
|
||||||
iovp->iod_iovec[i].iov_addr + offset, bytes);
|
panic( __FILE__, "ec_nic2user: sys_safecopyto failed: ", r );
|
||||||
|
|
||||||
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 );
|
|
||||||
|
|
||||||
count -= bytes;
|
count -= bytes;
|
||||||
nic_addr += bytes;
|
nic_addr += bytes;
|
||||||
|
|
@ -1433,19 +1387,20 @@ static void ec_next_iovec(iovp)
|
||||||
iovec_dat_t *iovp;
|
iovec_dat_t *iovp;
|
||||||
{
|
{
|
||||||
iovp->iod_iovec_s -= IOVEC_NR;
|
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 ?
|
(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);
|
iovp->iod_iovec);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* do_getstat *
|
* do_getstat_s *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
static void do_getstat(mp)
|
static void do_getstat_s(mp)
|
||||||
message *mp;
|
message *mp;
|
||||||
{
|
{
|
||||||
int port;
|
int port;
|
||||||
|
|
@ -1458,31 +1413,26 @@ message *mp;
|
||||||
ec= &ec_table[port];
|
ec= &ec_table[port];
|
||||||
ec->client= mp->DL_PROC;
|
ec->client= mp->DL_PROC;
|
||||||
|
|
||||||
put_userdata(mp->DL_PROC, (vir_bytes) mp->DL_ADDR,
|
put_userdata_s(mp->DL_PROC, mp->DL_GRANT,
|
||||||
(vir_bytes) sizeof(ec->eth_stat), &ec->eth_stat);
|
&ec->eth_stat, sizeof(ec->eth_stat));
|
||||||
reply(ec, OK, FALSE);
|
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;
|
int user_proc;
|
||||||
vir_bytes user_addr;
|
cp_grant_id_t grant;
|
||||||
vir_bytes count;
|
|
||||||
void *loc_addr;
|
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;
|
int cps;
|
||||||
cps = sys_datacopy(SELF, (vir_bytes) loc_addr, user_proc, user_addr, count);
|
cps = sys_safecopyto(user_proc, grant, 0,
|
||||||
if (cps != OK) printf("lance: warning, scopy failed: %d\n", cps);
|
(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
|
#define IOVEC_NR 16
|
||||||
typedef struct iovec_dat
|
typedef struct iovec_dat
|
||||||
{
|
{
|
||||||
iovec_t iod_iovec[IOVEC_NR];
|
iovec_s_t iod_iovec[IOVEC_NR];
|
||||||
int iod_iovec_s;
|
int iod_iovec_s;
|
||||||
int iod_proc_nr;
|
int iod_proc_nr;
|
||||||
vir_bytes iod_iovec_addr;
|
cp_grant_id_t iod_grant;
|
||||||
|
vir_bytes iod_iovec_offset;
|
||||||
} iovec_dat_t;
|
} iovec_dat_t;
|
||||||
|
|
||||||
#define ETH0_SELECTOR 0x61
|
#define ETH0_SELECTOR 0x61
|
||||||
|
|
|
||||||
|
|
@ -6,26 +6,30 @@
|
||||||
*
|
*
|
||||||
* The valid messages and their parameters are:
|
* The valid messages and their parameters are:
|
||||||
*
|
*
|
||||||
* m_type DL_PORT DL_PROC DL_COUNT DL_MODE DL_ADDR
|
* m_type DL_PORT DL_PROC DL_COUNT DL_MODE DL_ADDR DL_GRANT
|
||||||
* |------------+----------+---------+----------+---------+---------|
|
* |------------+----------+---------+----------+---------+---------+---------|
|
||||||
* | HARD_INT | | | | | |
|
* | HARDINT | | | | | | |
|
||||||
* |------------|----------|---------|----------|---------|---------|
|
* |------------|----------|---------|----------|---------|---------|---------|
|
||||||
* | DL_WRITE | port nr | proc nr | count | mode | address |
|
* | DL_WRITE | port nr | proc nr | count | mode | address | |
|
||||||
* |------------|----------|---------|----------|---------|---------|
|
* |------------|----------|---------|----------|---------|---------|---------|
|
||||||
* | DL_WRITEV | 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_WRITEV_S| port nr | proc nr | count | mode | | grant |
|
||||||
* |------------|----------|---------|----------|---------|---------|
|
* |------------|----------|---------|----------|---------|---------|---------|
|
||||||
* | DL_READV | port nr | proc nr | count | | address |
|
* | DL_READ | port nr | proc nr | count | | address | |
|
||||||
* |------------|----------|---------|----------|---------|---------|
|
* |------------|----------|---------|----------|---------|---------|---------|
|
||||||
* | DL_INIT | port nr | proc nr | mode | | address |
|
* | DL_READV | port nr | proc nr | count | | address | |
|
||||||
* |------------|----------|---------|----------|---------|---------|
|
* |------------|----------|---------|----------|---------|---------|---------|
|
||||||
* | DL_GETSTAT | port nr | proc nr | | | address |
|
* | DL_READV_S | port nr | proc nr | count | | | grant |
|
||||||
* |------------|----------|---------|----------|---------|---------|
|
* |------------|----------|---------|----------|---------|---------|---------|
|
||||||
* | DL_GETNAME | | | | | |
|
* | DL_CONF | port nr | proc nr | | mode | address | |
|
||||||
* |------------|----------|---------|----------|---------|---------|
|
* |------------|----------|---------|----------|---------|---------|---------|
|
||||||
* | DL_STOP | port_nr | | | | |
|
* | DL_GETSTAT | port nr | proc nr | | | address | |
|
||||||
* |------------|----------|---------|----------|---------|---------|
|
* |------------|----------|---------|----------|---------|---------|---------|
|
||||||
|
* |DL_GETSTAT_S| port nr | proc nr | | | | grant |
|
||||||
|
* |------------|----------|---------|----------|---------|---------|---------|
|
||||||
|
* | DL_STOP | port_nr | | | | | |
|
||||||
|
* |------------|----------|---------|----------|---------|---------|---------|
|
||||||
*
|
*
|
||||||
* The messages sent are:
|
* The messages sent are:
|
||||||
*
|
*
|
||||||
|
|
@ -36,7 +40,7 @@
|
||||||
*
|
*
|
||||||
* m_type m3_i1 m3_i2 m3_ca1
|
* 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>
|
* Created: Aug 2003 by Philip Homburg <philip@cs.vu.nl>
|
||||||
|
|
@ -155,6 +159,7 @@ typedef struct re
|
||||||
message re_tx_mess;
|
message re_tx_mess;
|
||||||
char re_name[sizeof("rtl8139#n")];
|
char re_name[sizeof("rtl8139#n")];
|
||||||
iovec_t re_iovec[IOVEC_NR];
|
iovec_t re_iovec[IOVEC_NR];
|
||||||
|
iovec_s_t re_iovec_s[IOVEC_NR];
|
||||||
}
|
}
|
||||||
re_t;
|
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_rec_mode, (re_t *rep) );
|
||||||
_PROTOTYPE( static void rl_readv, (message *mp, int from_int,
|
_PROTOTYPE( static void rl_readv, (message *mp, int from_int,
|
||||||
int vectored) );
|
int vectored) );
|
||||||
|
_PROTOTYPE( static void rl_readv_s, (message *mp, int from_int) );
|
||||||
_PROTOTYPE( static void rl_writev, (message *mp, int from_int,
|
_PROTOTYPE( static void rl_writev, (message *mp, int from_int,
|
||||||
int vectored) );
|
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_check_ints, (re_t *rep) );
|
||||||
_PROTOTYPE( static void rl_report_link, (re_t *rep) );
|
_PROTOTYPE( static void rl_report_link, (re_t *rep) );
|
||||||
_PROTOTYPE( static void mii_print_techab, (U16_t techab) );
|
_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_clear_rx, (re_t *rep) );
|
||||||
_PROTOTYPE( static void rl_do_reset, (re_t *rep) );
|
_PROTOTYPE( static void rl_do_reset, (re_t *rep) );
|
||||||
_PROTOTYPE( static void rl_getstat, (message *mp) );
|
_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 rl_getname, (message *mp) );
|
||||||
_PROTOTYPE( static void reply, (re_t *rep, int err, int may_block) );
|
_PROTOTYPE( static void reply, (re_t *rep, int err, int may_block) );
|
||||||
_PROTOTYPE( static void mess_reply, (message *req, message *reply) );
|
_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 rtl8139_stop, (void) );
|
||||||
_PROTOTYPE( static void check_int_events, (void) );
|
_PROTOTYPE( static void check_int_events, (void) );
|
||||||
_PROTOTYPE( static int do_hard_int, (void) );
|
_PROTOTYPE( static int do_hard_int, (void) );
|
||||||
|
|
@ -314,15 +320,16 @@ int main(int argc, char *argv[])
|
||||||
|
|
||||||
switch (m.m_type)
|
switch (m.m_type)
|
||||||
{
|
{
|
||||||
case DEV_PING: notify(m.m_source); continue;
|
case DEV_PING: notify(m.m_source); break;
|
||||||
case DL_WRITEV: rl_writev(&m, FALSE, TRUE); break;
|
|
||||||
case DL_WRITE: rl_writev(&m, FALSE, FALSE); break;
|
case DL_WRITE: rl_writev(&m, FALSE, FALSE); break;
|
||||||
#if 0
|
case DL_WRITEV: rl_writev(&m, FALSE, TRUE); break;
|
||||||
case DL_READ: do_vread(&m, FALSE); break;
|
case DL_WRITEV_S: rl_writev_s(&m, FALSE); break;
|
||||||
#endif
|
case DL_READ: rl_readv(&m, FALSE, FALSE); break;
|
||||||
case DL_READV: rl_readv(&m, FALSE, TRUE); 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: rl_getstat(&m); break;
|
||||||
|
case DL_GETSTAT_S: rl_getstat_s(&m); break;
|
||||||
case DL_GETNAME: rl_getname(&m); break;
|
case DL_GETNAME: rl_getname(&m); break;
|
||||||
#if 0
|
#if 0
|
||||||
case DL_STOP: do_stop(&m); break;
|
case DL_STOP: do_stop(&m); break;
|
||||||
|
|
@ -490,7 +497,7 @@ message *mp;
|
||||||
port = mp->DL_PORT;
|
port = mp->DL_PORT;
|
||||||
if (port < 0 || port >= RE_PORT_NR)
|
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;
|
reply_mess.m3_i1= ENXIO;
|
||||||
mess_reply(mp, &reply_mess);
|
mess_reply(mp, &reply_mess);
|
||||||
return;
|
return;
|
||||||
|
|
@ -503,7 +510,7 @@ message *mp;
|
||||||
if (rep->re_mode == REM_DISABLED)
|
if (rep->re_mode == REM_DISABLED)
|
||||||
{
|
{
|
||||||
/* Probe failed, or the device is configured off. */
|
/* 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;
|
reply_mess.m3_i1= ENXIO;
|
||||||
mess_reply(mp, &reply_mess);
|
mess_reply(mp, &reply_mess);
|
||||||
return;
|
return;
|
||||||
|
|
@ -530,7 +537,7 @@ message *mp;
|
||||||
rep->re_client = mp->m_source;
|
rep->re_client = mp->m_source;
|
||||||
rl_rec_mode(rep);
|
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_i1 = mp->DL_PORT;
|
||||||
reply_mess.m3_i2 = RE_PORT_NR;
|
reply_mess.m3_i2 = RE_PORT_NR;
|
||||||
*(ether_addr_t *) reply_mess.m3_ca1 = rep->re_address;
|
*(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);
|
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 (rep->re_clear_rx)
|
||||||
{
|
{
|
||||||
#if 0
|
#if 0
|
||||||
|
|
@ -1113,11 +1112,6 @@ int vectored;
|
||||||
if (vectored)
|
if (vectored)
|
||||||
{
|
{
|
||||||
int iov_offset = 0;
|
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;
|
size= 0;
|
||||||
o= d_start+4;
|
o= d_start+4;
|
||||||
|
|
@ -1129,15 +1123,15 @@ int vectored;
|
||||||
n= IOVEC_NR;
|
n= IOVEC_NR;
|
||||||
if (i+n > count)
|
if (i+n > count)
|
||||||
n= count-i;
|
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]));
|
n * sizeof(rep->re_iovec[0]));
|
||||||
if (cps != OK) printf("RTL8139: warning, sys_abscopy failed: %d\n", cps);
|
if (cps != OK)
|
||||||
#else
|
printf(
|
||||||
cps = sys_vircopy(re_client, D, (vir_bytes) mp->DL_ADDR + iov_offset,
|
"RTL8139: warning, sys_vircopy failed: %d (%d)\n",
|
||||||
SELF, D, (vir_bytes) rep->re_iovec, n * sizeof(rep->re_iovec[0]));
|
cps, __LINE__);
|
||||||
if (cps != OK) printf("RTL8139: warning, sys_vircopy failed: %d (%d)\n", cps, __LINE__);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
for (j= 0, iovp= rep->re_iovec; j<n; j++, iovp++)
|
for (j= 0, iovp= rep->re_iovec; j<n; j++, iovp++)
|
||||||
{
|
{
|
||||||
|
|
@ -1148,11 +1142,6 @@ int vectored;
|
||||||
s= packlen-size;
|
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)
|
if (o >= RX_BUFSIZE)
|
||||||
{
|
{
|
||||||
o -= RX_BUFSIZE;
|
o -= RX_BUFSIZE;
|
||||||
|
|
@ -1164,30 +1153,33 @@ int vectored;
|
||||||
assert(o<RX_BUFSIZE);
|
assert(o<RX_BUFSIZE);
|
||||||
s1= RX_BUFSIZE-o;
|
s1= RX_BUFSIZE-o;
|
||||||
|
|
||||||
#if 0
|
cps = sys_vircopy(SELF, D,
|
||||||
cps = sys_abscopy(src_phys+o, dst_phys, s1);
|
(vir_bytes) rep->v_re_rx_buf+o,
|
||||||
if (cps != OK) printf("RTL8139: warning, sys_abscopy failed: %d\n", cps);
|
re_client, D, iovp->iov_addr,
|
||||||
cps = sys_abscopy(src_phys, dst_phys+s1, s-s1);
|
s1);
|
||||||
if (cps != OK) printf("RTL8139: warning, sys_abscopy failed: %d\n", cps);
|
if (cps != OK)
|
||||||
#else
|
printf(
|
||||||
cps = sys_vircopy(SELF, D, (vir_bytes) rep->v_re_rx_buf+o,
|
"RTL8139: warning, sys_vircopy failed: %d (%d)\n",
|
||||||
re_client, D, iovp->iov_addr, s1);
|
cps, __LINE__);
|
||||||
if (cps != OK) printf("RTL8139: warning, sys_vircopy failed: %d (%d)\n", cps, __LINE__);
|
cps = sys_vircopy(SELF, D,
|
||||||
cps = sys_vircopy(SELF, D, (vir_bytes) rep->v_re_rx_buf,
|
(vir_bytes) rep->v_re_rx_buf,
|
||||||
re_client, D, iovp->iov_addr+s1, s-s1);
|
re_client, D,
|
||||||
if (cps != OK) printf("RTL8139: warning, sys_vircopy failed: %d (%d)\n", cps, __LINE__);
|
iovp->iov_addr+s1, s-s1);
|
||||||
#endif
|
if (cps != OK)
|
||||||
|
printf(
|
||||||
|
"RTL8139: warning, sys_vircopy failed: %d (%d)\n",
|
||||||
|
cps, __LINE__);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
#if 0
|
cps = sys_vircopy(SELF, D,
|
||||||
cps = sys_abscopy(src_phys+o, dst_phys, s);
|
(vir_bytes) rep->v_re_rx_buf+o,
|
||||||
if (cps != OK) printf("RTL8139: warning, sys_abscopy failed: %d\n", cps);
|
re_client, D, iovp->iov_addr,
|
||||||
#else
|
s);
|
||||||
cps = sys_vircopy(SELF, D, (vir_bytes) rep->v_re_rx_buf+o,
|
if (cps != OK)
|
||||||
re_client, D, iovp->iov_addr, s);
|
printf(
|
||||||
if (cps != OK) printf("RTL8139: warning, sys_vircopy failed: %d (%d)\n", cps, __LINE__);
|
"RTL8139: warning, sys_vircopy failed: %d (%d)\n",
|
||||||
#endif
|
cps, __LINE__);
|
||||||
}
|
}
|
||||||
|
|
||||||
size += s;
|
size += s;
|
||||||
|
|
@ -1224,9 +1216,9 @@ int vectored;
|
||||||
/* For some reason the receiver FIFO is not stopped when
|
/* For some reason the receiver FIFO is not stopped when
|
||||||
* the buffer is full.
|
* the buffer is full.
|
||||||
*/
|
*/
|
||||||
#if 0
|
#if 0
|
||||||
printf("rl_readv: later buffer overflow\n");
|
printf("rl_readv: later buffer overflow\n");
|
||||||
#endif
|
#endif
|
||||||
goto suspend; /* Buffer overflow */
|
goto suspend; /* Buffer overflow */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1250,7 +1242,7 @@ int vectored;
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
suspend:
|
suspend:
|
||||||
if (from_int)
|
if (from_int)
|
||||||
{
|
{
|
||||||
assert(rep->re_flags & REF_READING);
|
assert(rep->re_flags & REF_READING);
|
||||||
|
|
@ -1264,17 +1256,255 @@ int vectored;
|
||||||
rep->re_flags |= REF_READING;
|
rep->re_flags |= REF_READING;
|
||||||
|
|
||||||
reply(rep, OK, FALSE);
|
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
|
||||||
|
printf("d_start: 0x%x, d_end: 0x%x, totlen: %d, rxstat: 0x%x\n",
|
||||||
|
d_start, d_end, totlen, rxstat);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
assert(packlen > size);
|
||||||
|
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;
|
||||||
|
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 *
|
* rl_writev *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
static void rl_writev(mp, from_int, vectored)
|
static void rl_writev(mp, from_int, vectored)
|
||||||
message *mp;
|
message *mp;
|
||||||
int from_int;
|
int from_int;
|
||||||
int vectored;
|
int vectored;
|
||||||
{
|
{
|
||||||
phys_bytes p, iov_src, phys_user;
|
phys_bytes iov_src, phys_user;
|
||||||
int i, j, n, s, port, count, size;
|
int i, j, n, s, port, count, size;
|
||||||
int tx_head, re_client;
|
int tx_head, re_client;
|
||||||
re_t *rep;
|
re_t *rep;
|
||||||
|
|
@ -1313,9 +1543,9 @@ int vectored;
|
||||||
* before we got a chance to set REF_SEND_AVAIL. Checking
|
* before we got a chance to set REF_SEND_AVAIL. Checking
|
||||||
* ret_busy twice should be sufficient.
|
* ret_busy twice should be sufficient.
|
||||||
*/
|
*/
|
||||||
#if 0
|
#if 0
|
||||||
printf("rl_writev: race detected\n");
|
printf("rl_writev: race detected\n");
|
||||||
#endif
|
#endif
|
||||||
rep->re_flags &= ~REF_SEND_AVAIL;
|
rep->re_flags &= ~REF_SEND_AVAIL;
|
||||||
rep->re_send_int= FALSE;
|
rep->re_send_int= FALSE;
|
||||||
}
|
}
|
||||||
|
|
@ -1327,18 +1557,8 @@ int vectored;
|
||||||
{
|
{
|
||||||
int iov_offset = 0;
|
int iov_offset = 0;
|
||||||
|
|
||||||
#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);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
size= 0;
|
size= 0;
|
||||||
#if 0
|
|
||||||
p= rep->re_tx[tx_head].ret_buf;
|
|
||||||
#else
|
|
||||||
ret = rep->re_tx[tx_head].v_ret_buf;
|
ret = rep->re_tx[tx_head].v_ret_buf;
|
||||||
#endif
|
|
||||||
for (i= 0; i<count; i += IOVEC_NR,
|
for (i= 0; i<count; i += IOVEC_NR,
|
||||||
iov_src += IOVEC_NR * sizeof(rep->re_iovec[0]),
|
iov_src += IOVEC_NR * sizeof(rep->re_iovec[0]),
|
||||||
iov_offset += IOVEC_NR * sizeof(rep->re_iovec[0]))
|
iov_offset += IOVEC_NR * sizeof(rep->re_iovec[0]))
|
||||||
|
|
@ -1346,16 +1566,10 @@ int vectored;
|
||||||
n= IOVEC_NR;
|
n= IOVEC_NR;
|
||||||
if (i+n > count)
|
if (i+n > count)
|
||||||
n= count-i;
|
n= count-i;
|
||||||
#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,
|
cps = sys_vircopy(re_client, D, ((vir_bytes) mp->DL_ADDR) + iov_offset,
|
||||||
SELF, D, (vir_bytes) rep->re_iovec,
|
SELF, D, (vir_bytes) rep->re_iovec,
|
||||||
n * sizeof(rep->re_iovec[0]));
|
n * sizeof(rep->re_iovec[0]));
|
||||||
if (cps != OK) printf("RTL8139: warning, sys_vircopy failed: %d\n", cps);
|
if (cps != OK) printf("RTL8139: warning, sys_vircopy failed: %d\n", cps);
|
||||||
#endif
|
|
||||||
|
|
||||||
for (j= 0, iovp= rep->re_iovec; j<n; j++, iovp++)
|
for (j= 0, iovp= rep->re_iovec; j<n; j++, iovp++)
|
||||||
{
|
{
|
||||||
|
|
@ -1369,18 +1583,10 @@ int vectored;
|
||||||
if (OK != sys_umap(re_client, D, iovp->iov_addr, s, &phys_user))
|
if (OK != sys_umap(re_client, D, iovp->iov_addr, s, &phys_user))
|
||||||
panic("rtl8139","umap_local failed\n", NO_NUM);
|
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,
|
cps = sys_vircopy(re_client, D, iovp->iov_addr,
|
||||||
SELF, D, (vir_bytes) ret, s);
|
SELF, D, (vir_bytes) ret, s);
|
||||||
if (cps != OK) printf("RTL8139: warning, sys_vircopy failed: %d\n", cps);
|
if (cps != OK) printf("RTL8139: warning, sys_vircopy failed: %d\n", cps);
|
||||||
#endif
|
|
||||||
size += s;
|
size += s;
|
||||||
#if 0
|
|
||||||
p += s;
|
|
||||||
#endif
|
|
||||||
ret += s;
|
ret += s;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1392,19 +1598,10 @@ int vectored;
|
||||||
size= mp->DL_COUNT;
|
size= mp->DL_COUNT;
|
||||||
if (size < ETH_MIN_PACK_SIZE || size > ETH_MAX_PACK_SIZE_TAGGED)
|
if (size < ETH_MIN_PACK_SIZE || size > ETH_MAX_PACK_SIZE_TAGGED)
|
||||||
panic("rtl8139","invalid packet size", size);
|
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;
|
ret = rep->re_tx[tx_head].v_ret_buf;
|
||||||
cps = sys_vircopy(re_client, D, (vir_bytes)mp->DL_ADDR,
|
cps = sys_vircopy(re_client, D, (vir_bytes)mp->DL_ADDR,
|
||||||
SELF, D, (vir_bytes) ret, size);
|
SELF, D, (vir_bytes) ret, size);
|
||||||
if (cps != OK) printf("RTL8139: warning, sys_abscopy failed: %d\n", cps);
|
if (cps != OK) printf("RTL8139: warning, sys_abscopy failed: %d\n", cps);
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
rl_outl(rep->re_base_port, RL_TSD0+tx_head*4,
|
rl_outl(rep->re_base_port, RL_TSD0+tx_head*4,
|
||||||
|
|
@ -1446,6 +1643,143 @@ suspend:
|
||||||
reply(rep, OK, FALSE);
|
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 *
|
* rl_check_ints *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
|
|
@ -1503,6 +1837,10 @@ re_t *rep;
|
||||||
rl_readv(&rep->re_rx_mess, TRUE /* from int */,
|
rl_readv(&rep->re_rx_mess, TRUE /* from int */,
|
||||||
TRUE /* vectored */);
|
TRUE /* vectored */);
|
||||||
}
|
}
|
||||||
|
else if (rep->re_rx_mess.m_type == DL_READV_S)
|
||||||
|
{
|
||||||
|
rl_readv_s(&rep->re_rx_mess, TRUE /* from int */);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
assert(rep->re_rx_mess.m_type == DL_READ);
|
assert(rep->re_rx_mess.m_type == DL_READ);
|
||||||
|
|
@ -1898,7 +2236,7 @@ re_t *rep;
|
||||||
static void rl_getstat(mp)
|
static void rl_getstat(mp)
|
||||||
message *mp;
|
message *mp;
|
||||||
{
|
{
|
||||||
int port;
|
int r, port;
|
||||||
eth_stat_t stats;
|
eth_stat_t stats;
|
||||||
re_t *rep;
|
re_t *rep;
|
||||||
|
|
||||||
|
|
@ -1913,8 +2251,38 @@ message *mp;
|
||||||
|
|
||||||
stats= rep->re_stat;
|
stats= rep->re_stat;
|
||||||
|
|
||||||
put_userdata(mp->DL_PROC, (vir_bytes) mp->DL_ADDR,
|
r = sys_datacopy(SELF, (vir_bytes) &stats, mp->DL_PROC,
|
||||||
(vir_bytes) sizeof(stats), &stats);
|
(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);
|
reply(rep, OK, FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1994,20 +2362,6 @@ message *reply_mess;
|
||||||
panic("rtl8139","unable to mess_reply", NO_NUM);
|
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
|
#if 0
|
||||||
static void dump_phy(rep)
|
static void dump_phy(rep)
|
||||||
re_t *rep;
|
re_t *rep;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user