From 2cf649db2ecc5f1f9d417c1b3aae5b9a0e4c62be Mon Sep 17 00:00:00 2001 From: Philip Homburg Date: Mon, 10 Jul 2006 12:43:38 +0000 Subject: [PATCH] Safecopy support in ethernet drivers. --- drivers/dp8390/Makefile | 2 +- drivers/dp8390/dp8390.c | 888 ++++++++++++++++++++++++++++++++++++-- drivers/dp8390/dp8390.h | 23 + drivers/dpeth/3c509.c | 11 +- drivers/dpeth/8390.c | 70 ++- drivers/dpeth/Makefile | 5 +- drivers/dpeth/devio.c | 4 +- drivers/dpeth/dp.c | 110 ++--- drivers/dpeth/dp.h | 18 +- drivers/dpeth/netbuff.c | 20 +- drivers/fxp/Makefile | 2 +- drivers/fxp/fxp.c | 497 ++++++++++++++++++--- drivers/lance/lance.c | 250 +++++------ drivers/lance/lance.h | 5 +- drivers/rtl8139/rtl8139.c | 824 +++++++++++++++++++++++++---------- 15 files changed, 2150 insertions(+), 579 deletions(-) diff --git a/drivers/dp8390/Makefile b/drivers/dp8390/Makefile index b60585fb5..7228d212c 100644 --- a/drivers/dp8390/Makefile +++ b/drivers/dp8390/Makefile @@ -21,7 +21,7 @@ OBJ = 3c503.o dp8390.o ne2000.o rtl8029.o wdeth.o all build: $(DRIVER) $(DRIVER): $(OBJ) $(CC) -o $@ $(LDFLAGS) $(OBJ) $(LIBS) - install -S 4096 $(DRIVER) + install -S 32k $(DRIVER) # install with other drivers install: /usr/sbin/$(DRIVER) diff --git a/drivers/dp8390/dp8390.c b/drivers/dp8390/dp8390.c index dc587b317..fdf636fcd 100644 --- a/drivers/dp8390/dp8390.c +++ b/drivers/dp8390/dp8390.c @@ -6,24 +6,30 @@ * * The valid messages and their parameters are: * - * m_type DL_PORT DL_PROC DL_COUNT DL_MODE DL_ADDR - * |------------+----------+---------+----------+---------+---------| - * | HARDINT | | | | | | - * |------------|----------|---------|----------|---------|---------| - * | DL_WRITE | port nr | proc nr | count | mode | address | - * |------------|----------|---------|----------|---------|---------| - * | DL_WRITEV | port nr | proc nr | count | mode | address | - * |------------|----------|---------|----------|---------|---------| - * | DL_READ | port nr | proc nr | count | | address | - * |------------|----------|---------|----------|---------|---------| - * | DL_READV | port nr | proc nr | count | | address | - * |------------|----------|---------|----------|---------|---------| - * | DL_INIT | port nr | proc nr | mode | | address | - * |------------|----------|---------|----------|---------|---------| - * | DL_GETSTAT | port nr | proc nr | | | address | - * |------------|----------|---------|----------|---------|---------| - * | DL_STOP | port_nr | | | | | - * |------------|----------|---------|----------|---------|---------| + * m_type DL_PORT DL_PROC DL_COUNT DL_MODE DL_ADDR DL_GRANT + * |------------+----------+---------+----------+---------+---------+---------| + * | HARDINT | | | | | | | + * |------------|----------|---------|----------|---------|---------|---------| + * | DL_WRITE | port nr | proc nr | count | mode | address | | + * |------------|----------|---------|----------|---------|---------|---------| + * | DL_WRITEV | port nr | proc nr | count | mode | address | | + * |------------|----------|---------|----------|---------|---------|---------| + * | DL_WRITEV_S| port nr | proc nr | count | mode | | grant | + * |------------|----------|---------|----------|---------|---------|---------| + * | DL_READ | port nr | proc nr | count | | address | | + * |------------|----------|---------|----------|---------|---------|---------| + * | DL_READV | port nr | proc nr | count | | address | | + * |------------|----------|---------|----------|---------|---------|---------| + * | DL_READV_S | port nr | proc nr | count | | | grant | + * |------------|----------|---------|----------|---------|---------|---------| + * | DL_CONF | port nr | proc nr | | mode | address | | + * |------------|----------|---------|----------|---------|---------|---------| + * | DL_GETSTAT | port nr | proc nr | | | address | | + * |------------|----------|---------|----------|---------|---------|---------| + * |DL_GETSTAT_S| port nr | proc nr | | | | grant | + * |------------|----------|---------|----------|---------|---------|---------| + * | DL_STOP | port_nr | | | | | | + * |------------|----------|---------|----------|---------|---------|---------| * * The messages sent are: * @@ -34,7 +40,7 @@ * * m_type m3_i1 m3_i2 m3_ca1 * |-------------+---------+-----------+---------------| - * |DL_INIT_REPLY| port nr | last port | ethernet addr | + * |DL_CONF_REPLY| port nr | last port | ethernet addr | * |-------------+---------+-----------+---------------| * * Created: before Dec 28, 1992 by Philip Homburg @@ -53,6 +59,7 @@ #include #include #include +#include #include "assert.h" #include "local.h" @@ -108,10 +115,13 @@ _PROTOTYPE( static void pci_conf, (void) ); #endif _PROTOTYPE( static void do_vwrite, (message *mp, int from_int, int vectored) ); +_PROTOTYPE( static void do_vwrite_s, (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 do_init, (message *mp) ); _PROTOTYPE( static void do_int, (dpeth_t *dep) ); _PROTOTYPE( static void do_getstat, (message *mp) ); +_PROTOTYPE( static void do_getstat_s, (message *mp) ); _PROTOTYPE( static void do_getname, (message *mp) ); _PROTOTYPE( static void do_stop, (message *mp) ); _PROTOTYPE( static void dp_init, (dpeth_t *dep) ); @@ -130,30 +140,54 @@ _PROTOTYPE( static void dp_pio16_getblock, (dpeth_t *dep, int page, size_t offset, size_t size, void *dst) ); _PROTOTYPE( static int dp_pkt2user, (dpeth_t *dep, int page, int length) ); +_PROTOTYPE( static int dp_pkt2user_s, (dpeth_t *dep, int page, + int length) ); _PROTOTYPE( static void dp_user2nic, (dpeth_t *dep, iovec_dat_t *iovp, vir_bytes offset, int nic_addr, vir_bytes count) ); +_PROTOTYPE( static void dp_user2nic_s, (dpeth_t *dep, iovec_dat_s_t *iovp, + vir_bytes offset, int nic_addr, vir_bytes count) ); _PROTOTYPE( static void dp_pio8_user2nic, (dpeth_t *dep, iovec_dat_t *iovp, vir_bytes offset, int nic_addr, vir_bytes count) ); +_PROTOTYPE( static void dp_pio8_user2nic_s, (dpeth_t *dep, + iovec_dat_s_t *iovp, vir_bytes offset, + int nic_addr, vir_bytes count) ); _PROTOTYPE( static void dp_pio16_user2nic, (dpeth_t *dep, iovec_dat_t *iovp, vir_bytes offset, int nic_addr, vir_bytes count) ); +_PROTOTYPE( static void dp_pio16_user2nic_s, (dpeth_t *dep, + iovec_dat_s_t *iovp, vir_bytes offset, + int nic_addr, vir_bytes count) ); _PROTOTYPE( static void dp_nic2user, (dpeth_t *dep, int nic_addr, iovec_dat_t *iovp, vir_bytes offset, vir_bytes count) ); +_PROTOTYPE( static void dp_nic2user_s, (dpeth_t *dep, int nic_addr, + iovec_dat_s_t *iovp, vir_bytes offset, vir_bytes count) ); _PROTOTYPE( static void dp_pio8_nic2user, (dpeth_t *dep, int nic_addr, iovec_dat_t *iovp, vir_bytes offset, vir_bytes count) ); +_PROTOTYPE( static void dp_pio8_nic2user_s, (dpeth_t *dep, int nic_addr, + iovec_dat_s_t *iovp, vir_bytes offset, vir_bytes count) ); _PROTOTYPE( static void dp_pio16_nic2user, (dpeth_t *dep, int nic_addr, iovec_dat_t *iovp, vir_bytes offset, vir_bytes count) ); +_PROTOTYPE( static void dp_pio16_nic2user_s, (dpeth_t *dep, int nic_addr, + iovec_dat_s_t *iovp, vir_bytes offset, vir_bytes count) ); _PROTOTYPE( static void dp_next_iovec, (iovec_dat_t *iovp) ); +_PROTOTYPE( static void dp_next_iovec_s, (iovec_dat_s_t *iovp) ); _PROTOTYPE( static void conf_hw, (dpeth_t *dep) ); _PROTOTYPE( static void update_conf, (dpeth_t *dep, dp_conf_t *dcp) ); +_PROTOTYPE( static void map_hw_buffer, (dpeth_t *dep) ); _PROTOTYPE( static int calc_iovec_size, (iovec_dat_t *iovp) ); +_PROTOTYPE( static int calc_iovec_size_s, (iovec_dat_s_t *iovp) ); _PROTOTYPE( static void reply, (dpeth_t *dep, int err, int may_block) ); _PROTOTYPE( static void mess_reply, (message *req, message *reply) ); _PROTOTYPE( static void get_userdata, (int user_proc, vir_bytes user_addr, vir_bytes count, void *loc_addr) ); +_PROTOTYPE( static void get_userdata_s, (int user_proc, + cp_grant_id_t grant, vir_bytes offset, vir_bytes count, + void *loc_addr) ); _PROTOTYPE( static void put_userdata, (int user_proc, vir_bytes user_addr, vir_bytes count, void *loc_addr) ); +_PROTOTYPE( static void put_userdata_s, (int user_proc, + cp_grant_id_t grant, size_t count, void *loc_addr) ); _PROTOTYPE( static void insb, (port_t port, void *buf, size_t size) ); _PROTOTYPE( static void insw, (port_t port, void *buf, size_t size) ); _PROTOTYPE( static void do_vir_insb, (port_t port, int proc, @@ -209,10 +243,13 @@ int main(int argc, char *argv[]) case DEV_PING: notify(m.m_source); continue; case DL_WRITE: do_vwrite(&m, FALSE, FALSE); break; case DL_WRITEV: do_vwrite(&m, FALSE, TRUE); break; + case DL_WRITEV_S: do_vwrite_s(&m, FALSE); break; case DL_READ: do_vread(&m, FALSE); break; case DL_READV: do_vread(&m, TRUE); break; - case DL_INIT: do_init(&m); break; + case DL_READV_S: do_vread_s(&m); break; + case DL_CONF: do_init(&m); break; case DL_GETSTAT: do_getstat(&m); break; + case DL_GETSTAT_S: do_getstat_s(&m); break; case DL_GETNAME: do_getname(&m); break; case DL_STOP: do_stop(&m); break; case HARD_INT: @@ -476,6 +513,96 @@ int vectored; assert(dep->de_flags & DEF_ENABLED); } +/*===========================================================================* + * do_vwrite_s * + *===========================================================================*/ +static void do_vwrite_s(mp, from_int) +message *mp; +int from_int; +{ + int port, count, size; + int sendq_head; + dpeth_t *dep; + + port = mp->DL_PORT; + count = mp->DL_COUNT; + if (port < 0 || port >= DE_PORT_NR) + panic("", "dp8390: illegal port", port); + dep= &de_table[port]; + dep->de_client= mp->DL_PROC; + + if (dep->de_mode == DEM_SINK) + { + assert(!from_int); + dep->de_flags |= DEF_PACK_SEND; + reply(dep, OK, FALSE); + return; + } + assert(dep->de_mode == DEM_ENABLED); + assert(dep->de_flags & DEF_ENABLED); + if (dep->de_flags & DEF_SEND_AVAIL) + panic("", "dp8390: send already in progress", NO_NUM); + + sendq_head= dep->de_sendq_head; + if (dep->de_sendq[sendq_head].sq_filled) + { + if (from_int) + panic("", "dp8390: should not be sending\n", NO_NUM); + dep->de_sendmsg= *mp; + dep->de_flags |= DEF_SEND_AVAIL; + reply(dep, OK, FALSE); + return; + } + assert(!(dep->de_flags & DEF_PACK_SEND)); + + get_userdata_s(mp->DL_PROC, mp->DL_GRANT, 0, + (count > IOVEC_NR ? IOVEC_NR : count) * + sizeof(dep->de_write_iovec_s.iod_iovec[0]), + dep->de_write_iovec_s.iod_iovec); + dep->de_write_iovec_s.iod_iovec_s = count; + dep->de_write_iovec_s.iod_proc_nr = mp->DL_PROC; + dep->de_write_iovec_s.iod_grant = mp->DL_GRANT; + dep->de_write_iovec_s.iod_iovec_offset = 0; + + dep->de_tmp_iovec_s = dep->de_write_iovec_s; + size = calc_iovec_size_s(&dep->de_tmp_iovec_s); + + if (size < ETH_MIN_PACK_SIZE || size > ETH_MAX_PACK_SIZE_TAGGED) + { + panic("", "dp8390: invalid packet size", size); + } + (dep->de_user2nicf_s)(dep, &dep->de_write_iovec_s, 0, + dep->de_sendq[sendq_head].sq_sendpage * DP_PAGESIZE, + size); + dep->de_sendq[sendq_head].sq_filled= TRUE; + if (dep->de_sendq_tail == sendq_head) + { + outb_reg0(dep, DP_TPSR, dep->de_sendq[sendq_head].sq_sendpage); + outb_reg0(dep, DP_TBCR1, size >> 8); + outb_reg0(dep, DP_TBCR0, size & 0xff); + outb_reg0(dep, DP_CR, CR_TXP | CR_EXTRA);/* there it goes.. */ + } + else + dep->de_sendq[sendq_head].sq_size= size; + + if (++sendq_head == dep->de_sendq_nr) + sendq_head= 0; + assert(sendq_head < SENDQ_NR); + dep->de_sendq_head= sendq_head; + + dep->de_flags |= DEF_PACK_SEND; + + /* 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(dep, OK, FALSE); + + assert(dep->de_mode == DEM_ENABLED); + assert(dep->de_flags & DEF_ENABLED); +} + /*===========================================================================* * do_vread * *===========================================================================*/ @@ -504,6 +631,8 @@ int vectored; if(dep->de_flags & DEF_READING) panic("", "dp8390: read already in progress", NO_NUM); + dep->de_safecopy_read= 0; + if (vectored) { get_userdata(mp->DL_PROC, (vir_bytes) mp->DL_ADDR, @@ -544,6 +673,64 @@ int vectored; reply(dep, OK, FALSE); } +/*===========================================================================* + * do_vread_s * + *===========================================================================*/ +static void do_vread_s(mp) +message *mp; +{ + int port, count; + int size; + dpeth_t *dep; + + port = mp->DL_PORT; + count = mp->DL_COUNT; + if (port < 0 || port >= DE_PORT_NR) + panic("", "dp8390: illegal port", port); + dep= &de_table[port]; + dep->de_client= mp->DL_PROC; + if (dep->de_mode == DEM_SINK) + { + reply(dep, OK, FALSE); + return; + } + assert(dep->de_mode == DEM_ENABLED); + assert(dep->de_flags & DEF_ENABLED); + + dep->de_safecopy_read= 1; + + if(dep->de_flags & DEF_READING) + panic("", "dp8390: read already in progress", NO_NUM); + + get_userdata_s(mp->DL_PROC, mp->DL_GRANT, 0, + (count > IOVEC_NR ? IOVEC_NR : count) * + sizeof(dep->de_read_iovec_s.iod_iovec[0]), + dep->de_read_iovec_s.iod_iovec); + dep->de_read_iovec_s.iod_iovec_s = count; + dep->de_read_iovec_s.iod_proc_nr = mp->DL_PROC; + dep->de_read_iovec_s.iod_grant = mp->DL_GRANT; + dep->de_read_iovec_s.iod_iovec_offset = 0; + + dep->de_tmp_iovec_s = dep->de_read_iovec_s; + size= calc_iovec_size_s(&dep->de_tmp_iovec_s); + + if (size < ETH_MAX_PACK_SIZE_TAGGED) + panic("", "dp8390: wrong packet size", size); + dep->de_flags |= DEF_READING; + + dp_recv(dep); + + if ((dep->de_flags & (DEF_READING|DEF_STOPPED)) == + (DEF_READING|DEF_STOPPED)) + { + /* The chip is stopped, and all arrived packets are + * delivered. + */ + dp_reset(dep); + } + reply(dep, OK, FALSE); +} + /*===========================================================================* * do_init * *===========================================================================*/ @@ -561,7 +748,7 @@ message *mp; port = mp->DL_PORT; if (port < 0 || port >= DE_PORT_NR) { - reply_mess.m_type= DL_INIT_REPLY; + reply_mess.m_type= DL_CONF_REPLY; reply_mess.m3_i1= ENXIO; mess_reply(mp, &reply_mess); return; @@ -574,7 +761,7 @@ message *mp; if (dep->de_mode == DEM_DISABLED) { /* Probe failed, or the device is configured off. */ - reply_mess.m_type= DL_INIT_REPLY; + reply_mess.m_type= DL_CONF_REPLY; reply_mess.m3_i1= ENXIO; mess_reply(mp, &reply_mess); return; @@ -588,7 +775,7 @@ message *mp; strncpy((char *) dep->de_address.ea_addr, "ZDP", 6); dep->de_address.ea_addr[5] = port; dp_confaddr(dep); - reply_mess.m_type = DL_INIT_REPLY; + reply_mess.m_type = DL_CONF_REPLY; reply_mess.m3_i1 = mp->DL_PORT; reply_mess.m3_i2 = DE_PORT_NR; *(ether_addr_t *) reply_mess.m3_ca1 = dep->de_address; @@ -610,7 +797,7 @@ message *mp; dep->de_client = mp->m_source; dp_reinit(dep); - reply_mess.m_type = DL_INIT_REPLY; + reply_mess.m_type = DL_CONF_REPLY; reply_mess.m3_i1 = mp->DL_PORT; reply_mess.m3_i2 = DE_PORT_NR; *(ether_addr_t *) reply_mess.m3_ca1 = dep->de_address; @@ -661,6 +848,39 @@ message *mp; reply(dep, OK, FALSE); } +/*===========================================================================* + * do_getstat_s * + *===========================================================================*/ +static void do_getstat_s(mp) +message *mp; +{ + int port; + dpeth_t *dep; + + port = mp->DL_PORT; + if (port < 0 || port >= DE_PORT_NR) + panic("", "dp8390: illegal port", port); + dep= &de_table[port]; + dep->de_client= mp->DL_PROC; + if (dep->de_mode == DEM_SINK) + { + put_userdata(mp->DL_PROC, (vir_bytes) mp->DL_ADDR, + (vir_bytes) sizeof(dep->de_stat), &dep->de_stat); + reply(dep, OK, FALSE); + return; + } + assert(dep->de_mode == DEM_ENABLED); + assert(dep->de_flags & DEF_ENABLED); + + dep->de_stat.ets_CRCerr += inb_reg0(dep, DP_CNTR0); + dep->de_stat.ets_frameAll += inb_reg0(dep, DP_CNTR1); + dep->de_stat.ets_missedP += inb_reg0(dep, DP_CNTR2); + + put_userdata_s(mp->DL_PROC, mp->DL_GRANT, + sizeof(dep->de_stat), &dep->de_stat); + reply(dep, OK, FALSE); +} + /*===========================================================================* * do_getname * *===========================================================================*/ @@ -727,6 +947,9 @@ dpeth_t *dep; i < 5 ? ':' : '\n'); } + /* Map buffer */ + map_hw_buffer(dep); + /* Initialization of the dp8390 following the mandatory procedure * in reference manual ("DP8390D/NS32490D NIC Network Interface * Controller", National Semiconductor, July 1995, Page 29). @@ -799,19 +1022,25 @@ dpeth_t *dep; if (!dep->de_prog_IO) { dep->de_user2nicf= dp_user2nic; + dep->de_user2nicf_s= dp_user2nic_s; dep->de_nic2userf= dp_nic2user; + dep->de_nic2userf_s= dp_nic2user_s; dep->de_getblockf= dp_getblock; } else if (dep->de_16bit) { dep->de_user2nicf= dp_pio16_user2nic; + dep->de_user2nicf_s= dp_pio16_user2nic_s; dep->de_nic2userf= dp_pio16_nic2user; + dep->de_nic2userf_s= dp_pio16_nic2user_s; dep->de_getblockf= dp_pio16_getblock; } else { dep->de_user2nicf= dp_pio8_user2nic; + dep->de_user2nicf_s= dp_pio8_user2nic_s; dep->de_nic2userf= dp_pio8_nic2user; + dep->de_nic2userf_s= dp_pio8_nic2user_s; dep->de_getblockf= dp_pio8_getblock; } @@ -1130,7 +1359,10 @@ dpeth_t *dep; else if ((header.dr_status & RSR_PRX) && (dep->de_flags & DEF_ENABLED)) { - r = dp_pkt2user(dep, pageno, length); + if (dep->de_safecopy_read) + r = dp_pkt2user_s(dep, pageno, length); + else + r = dp_pkt2user(dep, pageno, length); if (r != OK) return; @@ -1161,8 +1393,9 @@ dpeth_t *dep; { case DL_WRITE: do_vwrite(&dep->de_sendmsg, TRUE, FALSE); break; case DL_WRITEV: do_vwrite(&dep->de_sendmsg, TRUE, TRUE); break; + case DL_WRITEV_S: do_vwrite_s(&dep->de_sendmsg, TRUE); break; default: - panic("", "dp8390: wrong type:", dep->de_sendmsg.m_type); + panic("", "dp8390: wrong type", dep->de_sendmsg.m_type); break; } } @@ -1181,11 +1414,7 @@ void *dst; offset = page * DP_PAGESIZE + offset; - r = sys_vircopy(SELF, BIOS_SEG, dep->de_linmem + offset, - SELF, D, (vir_bytes)dst, size); - - if (r != OK) - panic("DP8390", "dp_getblock: sys_vircopy failed", r); + memcpy(dst, dep->de_locmem + offset, size); } /*===========================================================================* @@ -1267,6 +1496,44 @@ int page, length; return OK; } +/*===========================================================================* + * dp_pkt2user_s * + *===========================================================================*/ +static int dp_pkt2user_s(dep, page, length) +dpeth_t *dep; +int page, length; +{ + int last, count; + + if (!(dep->de_flags & DEF_READING)) + return EGENERIC; + + last = page + (length - 1) / DP_PAGESIZE; + if (last >= dep->de_stoppage) + { + count = (dep->de_stoppage - page) * DP_PAGESIZE - + sizeof(dp_rcvhdr_t); + + /* Save read_iovec since we need it twice. */ + dep->de_tmp_iovec_s = dep->de_read_iovec_s; + (dep->de_nic2userf_s)(dep, page * DP_PAGESIZE + + sizeof(dp_rcvhdr_t), &dep->de_tmp_iovec_s, 0, count); + (dep->de_nic2userf_s)(dep, dep->de_startpage * DP_PAGESIZE, + &dep->de_read_iovec_s, count, length - count); + } + else + { + (dep->de_nic2userf_s)(dep, page * DP_PAGESIZE + + sizeof(dp_rcvhdr_t), &dep->de_read_iovec_s, 0, length); + } + + dep->de_read_s = length; + dep->de_flags |= DEF_PACK_RECV; + dep->de_flags &= ~DEF_READING; + + return OK; +} + /*===========================================================================* * dp_user2nic * *===========================================================================*/ @@ -1280,7 +1547,7 @@ vir_bytes count; vir_bytes vir_hw, vir_user; int bytes, i, r; - vir_hw = dep->de_linmem + nic_addr; + vir_hw = (vir_bytes)dep->de_locmem + nic_addr; i= 0; while (count > 0) @@ -1304,7 +1571,7 @@ vir_bytes count; r= sys_vircopy(iovp->iod_proc_nr, D, iovp->iod_iovec[i].iov_addr + offset, - SELF, BIOS_SEG, vir_hw, bytes); + SELF, D, vir_hw, bytes); if (r != OK) panic("DP8390", "dp_user2nic: sys_vircopy failed", r); @@ -1315,6 +1582,57 @@ vir_bytes count; assert(count == 0); } +/*===========================================================================* + * dp_user2nic_s * + *===========================================================================*/ +static void dp_user2nic_s(dep, iovp, offset, nic_addr, count) +dpeth_t *dep; +iovec_dat_s_t *iovp; +vir_bytes offset; +int nic_addr; +vir_bytes count; +{ + vir_bytes vir_hw, vir_user; + int bytes, i, r; + + vir_hw = (vir_bytes)dep->de_locmem + nic_addr; + + i= 0; + while (count > 0) + { + if (i >= IOVEC_NR) + { + dp_next_iovec_s(iovp); + i= 0; + continue; + } + assert(i < iovp->iod_iovec_s); + if (offset >= iovp->iod_iovec[i].iov_size) + { + offset -= iovp->iod_iovec[i].iov_size; + i++; + continue; + } + bytes = iovp->iod_iovec[i].iov_size - offset; + if (bytes > count) + bytes = count; + + r= sys_safecopyfrom(iovp->iod_proc_nr, + iovp->iod_iovec[i].iov_grant, offset, + vir_hw, bytes, D); + if (r != OK) + { + panic("DP8390", + "dp_user2nic_s: sys_safecopyfrom failed", r); + } + + count -= bytes; + vir_hw += bytes; + offset += bytes; + } + assert(count == 0); +} + /*===========================================================================* * dp_pio8_user2nic * *===========================================================================*/ @@ -1374,6 +1692,71 @@ vir_bytes count; } } +/*===========================================================================* + * dp_pio8_user2nic_s * + *===========================================================================*/ +static void dp_pio8_user2nic_s(dep, iovp, offset, nic_addr, count) +dpeth_t *dep; +iovec_dat_s_t *iovp; +vir_bytes offset; +int nic_addr; +vir_bytes count; +{ + phys_bytes phys_user; + int bytes, i, r; + + outb_reg0(dep, DP_ISR, ISR_RDC); + + outb_reg0(dep, DP_RBCR0, count & 0xFF); + outb_reg0(dep, DP_RBCR1, count >> 8); + outb_reg0(dep, DP_RSAR0, nic_addr & 0xFF); + outb_reg0(dep, DP_RSAR1, nic_addr >> 8); + outb_reg0(dep, DP_CR, CR_DM_RW | CR_PS_P0 | CR_STA); + + i= 0; + while (count > 0) + { + if (i >= IOVEC_NR) + { + dp_next_iovec_s(iovp); + i= 0; + continue; + } + assert(i < iovp->iod_iovec_s); + if (offset >= iovp->iod_iovec[i].iov_size) + { + offset -= iovp->iod_iovec[i].iov_size; + i++; + continue; + } + bytes = iovp->iod_iovec[i].iov_size - offset; + if (bytes > count) + bytes = count; + + r= sys_safe_outsb(dep->de_data_port, iovp->iod_proc_nr, + iovp->iod_iovec[i].iov_grant, offset, bytes); + if (r != OK) + { + panic(__FILE__, + "dp_pio8_user2nic_s: sys_safe_outsb failed", + r); + } + count -= bytes; + offset += bytes; + } + assert(count == 0); + + for (i= 0; i<100; i++) + { + if (inb_reg0(dep, DP_ISR) & ISR_RDC) + break; + } + if (i == 100) + { + panic("", "dp8390: remote dma failed to complete", NO_NUM); + } +} + /*===========================================================================* * dp_pio16_user2nic * *===========================================================================*/ @@ -1485,6 +1868,120 @@ vir_bytes count; } } +/*===========================================================================* + * dp_pio16_user2nic_s * + *===========================================================================*/ +static void dp_pio16_user2nic_s(dep, iovp, offset, nic_addr, count) +dpeth_t *dep; +iovec_dat_s_t *iovp; +vir_bytes offset; +int nic_addr; +vir_bytes count; +{ + vir_bytes ecount; + cp_grant_id_t gid; + int i, r, bytes, user_proc; + u8_t two_bytes[2]; + int odd_byte; + + ecount= (count+1) & ~1; + odd_byte= 0; + + outb_reg0(dep, DP_ISR, ISR_RDC); + outb_reg0(dep, DP_RBCR0, ecount & 0xFF); + outb_reg0(dep, DP_RBCR1, ecount >> 8); + outb_reg0(dep, DP_RSAR0, nic_addr & 0xFF); + outb_reg0(dep, DP_RSAR1, nic_addr >> 8); + outb_reg0(dep, DP_CR, CR_DM_RW | CR_PS_P0 | CR_STA); + + i= 0; + while (count > 0) + { + if (i >= IOVEC_NR) + { + dp_next_iovec_s(iovp); + i= 0; + continue; + } + assert(i < iovp->iod_iovec_s); + if (offset >= iovp->iod_iovec[i].iov_size) + { + offset -= iovp->iod_iovec[i].iov_size; + i++; + continue; + } + bytes = iovp->iod_iovec[i].iov_size - offset; + if (bytes > count) + bytes = count; + + user_proc= iovp->iod_proc_nr; + gid= iovp->iod_iovec[i].iov_grant; + if (odd_byte) + { + r= sys_safecopyfrom(user_proc, gid, offset, + (vir_bytes)&two_bytes[1], 1, D); + if (r != OK) + { + panic("DP8390", + "dp_pio16_user2nic: sys_safecopyfrom failed", + r); + } + outw(dep->de_data_port, *(u16_t *)two_bytes); + count--; + offset++; + bytes--; + odd_byte= 0; + if (!bytes) + continue; + } + ecount= bytes & ~1; + if (ecount != 0) + { + r= sys_safe_outsw(dep->de_data_port, user_proc, + gid, offset, ecount); + if (r != OK) + { + panic("DP8390", + "dp_pio16_user2nic: sys_safe_outsw failed", + r); + } + count -= ecount; + offset += ecount; + bytes -= ecount; + } + if (bytes) + { + assert(bytes == 1); + r= sys_safecopyfrom(user_proc, gid, offset, + (vir_bytes)&two_bytes[0], 1, D); + if (r != OK) + { + panic("DP8390", + "dp_pio16_user2nic: sys_safecopyfrom failed", + r); + } + count--; + offset++; + bytes--; + odd_byte= 1; + } + } + assert(count == 0); + + if (odd_byte) + outw(dep->de_data_port, *(u16_t *)two_bytes); + + for (i= 0; i<100; i++) + { + if (inb_reg0(dep, DP_ISR) & ISR_RDC) + break; + } + if (i == 100) + { + panic("", "dp8390: remote dma failed to complete", NO_NUM); + } +} + /*===========================================================================* * dp_nic2user * *===========================================================================*/ @@ -1498,7 +1995,7 @@ vir_bytes count; vir_bytes vir_hw, vir_user; int bytes, i, r; - vir_hw = dep->de_linmem + nic_addr; + vir_hw = (vir_bytes)dep->de_locmem + nic_addr; i= 0; while (count > 0) @@ -1520,7 +2017,7 @@ vir_bytes count; if (bytes > count) bytes = count; - r= sys_vircopy(SELF, BIOS_SEG, vir_hw, + r= sys_vircopy(SELF, D, vir_hw, iovp->iod_proc_nr, D, iovp->iod_iovec[i].iov_addr + offset, bytes); if (r != OK) @@ -1533,6 +2030,55 @@ vir_bytes count; assert(count == 0); } +/*===========================================================================* + * dp_nic2user_s * + *===========================================================================*/ +static void dp_nic2user_s(dep, nic_addr, iovp, offset, count) +dpeth_t *dep; +int nic_addr; +iovec_dat_s_t *iovp; +vir_bytes offset; +vir_bytes count; +{ + vir_bytes vir_hw, vir_user; + int bytes, i, r; + + vir_hw = (vir_bytes)dep->de_locmem + nic_addr; + + i= 0; + while (count > 0) + { + if (i >= IOVEC_NR) + { + dp_next_iovec_s(iovp); + i= 0; + continue; + } + assert(i < iovp->iod_iovec_s); + if (offset >= iovp->iod_iovec[i].iov_size) + { + offset -= iovp->iod_iovec[i].iov_size; + i++; + continue; + } + bytes = iovp->iod_iovec[i].iov_size - offset; + if (bytes > count) + bytes = count; + + r= sys_safecopyto(iovp->iod_proc_nr, + iovp->iod_iovec[i].iov_grant, offset, + vir_hw, bytes, D); + if (r != OK) + panic("DP8390", + "dp_nic2user_s: sys_safecopyto failed", r); + + count -= bytes; + vir_hw += bytes; + offset += bytes; + } + assert(count == 0); +} + /*===========================================================================* * dp_pio8_nic2user * *===========================================================================*/ @@ -1580,6 +2126,58 @@ vir_bytes count; assert(count == 0); } +/*===========================================================================* + * dp_pio8_nic2user_s * + *===========================================================================*/ +static void dp_pio8_nic2user_s(dep, nic_addr, iovp, offset, count) +dpeth_t *dep; +int nic_addr; +iovec_dat_s_t *iovp; +vir_bytes offset; +vir_bytes count; +{ + phys_bytes phys_user; + int bytes, i, r; + + outb_reg0(dep, DP_RBCR0, count & 0xFF); + outb_reg0(dep, DP_RBCR1, count >> 8); + outb_reg0(dep, DP_RSAR0, nic_addr & 0xFF); + outb_reg0(dep, DP_RSAR1, nic_addr >> 8); + outb_reg0(dep, DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA); + + i= 0; + while (count > 0) + { + if (i >= IOVEC_NR) + { + dp_next_iovec_s(iovp); + i= 0; + continue; + } + assert(i < iovp->iod_iovec_s); + if (offset >= iovp->iod_iovec[i].iov_size) + { + offset -= iovp->iod_iovec[i].iov_size; + i++; + continue; + } + bytes = iovp->iod_iovec[i].iov_size - offset; + if (bytes > count) + bytes = count; + + r= sys_safe_insb(dep->de_data_port, iovp->iod_proc_nr, + iovp->iod_iovec[i].iov_grant, offset, bytes); + if (r != OK) + { + panic(__FILE__, + "dp_pio8_nic2user_s: sys_safe_insb failed", r); + } + count -= bytes; + offset += bytes; + } + assert(count == 0); +} + /*===========================================================================* * dp_pio16_nic2user * *===========================================================================*/ @@ -1678,7 +2276,107 @@ vir_bytes count; } /*===========================================================================* - * dp_next_iovec * + * dp_pio16_nic2user_s * + *===========================================================================*/ +static void dp_pio16_nic2user_s(dep, nic_addr, iovp, offset, count) +dpeth_t *dep; +int nic_addr; +iovec_dat_s_t *iovp; +vir_bytes offset; +vir_bytes count; +{ + vir_bytes ecount; + cp_grant_id_t gid; + int i, r, bytes, user_proc; + u8_t two_bytes[2]; + int odd_byte; + + ecount= (count+1) & ~1; + odd_byte= 0; + + outb_reg0(dep, DP_RBCR0, ecount & 0xFF); + outb_reg0(dep, DP_RBCR1, ecount >> 8); + outb_reg0(dep, DP_RSAR0, nic_addr & 0xFF); + outb_reg0(dep, DP_RSAR1, nic_addr >> 8); + outb_reg0(dep, DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA); + + i= 0; + while (count > 0) + { + if (i >= IOVEC_NR) + { + dp_next_iovec_s(iovp); + i= 0; + continue; + } + assert(i < iovp->iod_iovec_s); + if (offset >= iovp->iod_iovec[i].iov_size) + { + offset -= iovp->iod_iovec[i].iov_size; + i++; + continue; + } + bytes = iovp->iod_iovec[i].iov_size - offset; + if (bytes > count) + bytes = count; + + user_proc= iovp->iod_proc_nr; + gid= iovp->iod_iovec[i].iov_grant; + if (odd_byte) + { + r= sys_safecopyto(user_proc, gid, offset, + (vir_bytes)&two_bytes[1], 1, D); + if (r != OK) + { + panic("DP8390", + "dp_pio16_nic2user: sys_safecopyto failed", + r); + } + count--; + offset++; + bytes--; + odd_byte= 0; + if (!bytes) + continue; + } + ecount= bytes & ~1; + if (ecount != 0) + { + r= sys_safe_insw(dep->de_data_port, user_proc, gid, + offset, ecount); + if (r != OK) + { + panic("DP8390", + "dp_pio16_nic2user: sys_safe_insw failed", + r); + } + count -= ecount; + offset += ecount; + bytes -= ecount; + } + if (bytes) + { + assert(bytes == 1); + *(u16_t *)two_bytes= inw(dep->de_data_port); + r= sys_safecopyto(user_proc, gid, offset, + (vir_bytes)&two_bytes[0], 1, D); + if (r != OK) + { + panic("DP8390", + "dp_pio16_nic2user: sys_safecopyto failed", + r); + } + count--; + offset++; + bytes--; + odd_byte= 1; + } + } + assert(count == 0); +} + +/*===========================================================================* + * dp_next_iovec * *===========================================================================*/ static void dp_next_iovec(iovp) iovec_dat_t *iovp; @@ -1694,6 +2392,24 @@ iovec_dat_t *iovp; sizeof(iovec_t), iovp->iod_iovec); } +/*===========================================================================* + * dp_next_iovec_s * + *===========================================================================*/ +static void dp_next_iovec_s(iovp) +iovec_dat_s_t *iovp; +{ + assert(iovp->iod_iovec_s > IOVEC_NR); + + iovp->iod_iovec_s -= IOVEC_NR; + + iovp->iod_iovec_offset += IOVEC_NR * sizeof(iovec_t); + + get_userdata_s(iovp->iod_proc_nr, iovp->iod_grant, + iovp->iod_iovec_offset, + (iovp->iod_iovec_s > IOVEC_NR ? IOVEC_NR : iovp->iod_iovec_s) * + sizeof(iovp->iod_iovec[0]), iovp->iod_iovec); +} + /*===========================================================================* * conf_hw * *===========================================================================*/ @@ -1777,6 +2493,43 @@ dp_conf_t *dcp; dep->de_ramsize= v; } +/*===========================================================================* + * map_hw_buffer * + *===========================================================================*/ +static void map_hw_buffer(dep) +dpeth_t *dep; +{ + int r; + size_t o, size; + char *buf, *abuf; + + if (dep->de_prog_IO) + { +#if 0 + printf( + "map_hw_buffer: programmed I/O, no need to map buffer\n"); +#endif + dep->de_locmem = (char *)-dep->de_ramsize; /* trap errors */ + return; + } + + size = dep->de_ramsize + PAGE_SIZE; /* Add PAGE_SIZE for + * alignment + */ + buf= malloc(size); + if (buf == NULL) + panic(__FILE__, "map_hw_buffer: cannot malloc size", size); + o= PAGE_SIZE - ((vir_bytes)buf % PAGE_SIZE); + abuf= buf + o; + printf("buf at 0x%x, abuf at 0x%x\n", buf, abuf); + + r= sys_vm_map(SELF, 1 /* map */, (vir_bytes)abuf, + dep->de_ramsize, (phys_bytes)dep->de_linmem); + if (r != OK) + panic(__FILE__, "map_hw_buffer: sys_vm_map failed", r); + dep->de_locmem = abuf; +} + /*===========================================================================* * calc_iovec_size * *===========================================================================*/ @@ -1805,6 +2558,34 @@ iovec_dat_t *iovp; return size; } +/*===========================================================================* + * calc_iovec_size_s * + *===========================================================================*/ +static int calc_iovec_size_s(iovp) +iovec_dat_s_t *iovp; +{ + /* Calculate the size of a request. Note that the iovec_dat + * structure will be unusable after calc_iovec_size_s. + */ + int size; + int i; + + size= 0; + i= 0; + while (i < iovp->iod_iovec_s) + { + if (i >= IOVEC_NR) + { + dp_next_iovec_s(iovp); + i= 0; + continue; + } + size += iovp->iod_iovec[i].iov_size; + i++; + } + return size; +} + /*===========================================================================* * reply * *===========================================================================*/ @@ -1874,6 +2655,24 @@ void *loc_addr; panic("DP8390", "get_userdata: sys_vircopy failed", r); } +/*===========================================================================* + * get_userdata_s * + *===========================================================================*/ +static void get_userdata_s(user_proc, grant, offset, count, loc_addr) +int user_proc; +cp_grant_id_t grant; +vir_bytes offset; +vir_bytes count; +void *loc_addr; +{ + int r; + + r= sys_safecopyfrom(user_proc, grant, offset, + (vir_bytes)loc_addr, count, D); + if (r != OK) + panic("DP8390", "get_userdata: sys_safecopyfrom failed", r); +} + /*===========================================================================* * put_userdata * *===========================================================================*/ @@ -1891,6 +2690,23 @@ void *loc_addr; panic("DP8390", "put_userdata: sys_vircopy failed", r); } +/*===========================================================================* + * put_userdata_s * + *===========================================================================*/ +static void put_userdata_s(user_proc, grant, count, loc_addr) +int user_proc; +cp_grant_id_t grant; +size_t count; +void *loc_addr; +{ + int r; + + r= sys_safecopyto(user_proc, grant, 0, (vir_bytes)loc_addr, + count, D); + if (r != OK) + panic("DP8390", "put_userdata: sys_safecopyto failed", r); +} + u8_t inb(port_t port) { int r; diff --git a/drivers/dp8390/dp8390.h b/drivers/dp8390/dp8390.h index be889dbf4..083ddf630 100644 --- a/drivers/dp8390/dp8390.h +++ b/drivers/dp8390/dp8390.h @@ -172,14 +172,21 @@ typedef struct dp_rcvhdr struct dpeth; struct iovec_dat; +struct iovec_dat_s; _PROTOTYPE( typedef void (*dp_initf_t), (struct dpeth *dep) ); _PROTOTYPE( typedef void (*dp_stopf_t), (struct dpeth *dep) ); _PROTOTYPE( typedef void (*dp_user2nicf_t), (struct dpeth *dep, struct iovec_dat *iovp, vir_bytes offset, int nic_addr, vir_bytes count) ); +_PROTOTYPE( typedef void (*dp_user2nicf_s_t), (struct dpeth *dep, + struct iovec_dat_s *iovp, vir_bytes offset, + int nic_addr, vir_bytes count) ); _PROTOTYPE( typedef void (*dp_nic2userf_t), (struct dpeth *dep, int nic_addr, struct iovec_dat *iovp, vir_bytes offset, vir_bytes count) ); +_PROTOTYPE( typedef void (*dp_nic2userf_s_t), (struct dpeth *dep, + int nic_addr, struct iovec_dat_s *iovp, + vir_bytes offset, vir_bytes count) ); #if 0 _PROTOTYPE( typedef void (*dp_getheaderf_t), (struct dpeth *dep, int page, struct dp_rcvhdr *h, u16_t *eth_type) ); @@ -200,6 +207,15 @@ typedef struct iovec_dat vir_bytes iod_iovec_addr; } iovec_dat_t; +typedef struct iovec_dat_s +{ + iovec_s_t iod_iovec[IOVEC_NR]; + int iod_iovec_s; + int iod_proc_nr; + cp_grant_id_t iod_grant; + vir_bytes iod_iovec_offset; +} iovec_dat_s_t; + #define SENDQ_NR 2 /* Maximum size of the send queue */ #define SENDQ_PAGES 6 /* 6 * DP_PAGESIZE >= 1514 bytes */ @@ -215,6 +231,7 @@ typedef struct dpeth */ port_t de_base_port; phys_bytes de_linmem; + char *de_locmem; int de_irq; int de_int_pending; irq_hook_t de_hook; @@ -261,13 +278,19 @@ typedef struct dpeth int de_mode; eth_stat_t de_stat; iovec_dat_t de_read_iovec; + iovec_dat_s_t de_read_iovec_s; + int de_safecopy_read; iovec_dat_t de_write_iovec; + iovec_dat_s_t de_write_iovec_s; iovec_dat_t de_tmp_iovec; + iovec_dat_s_t de_tmp_iovec_s; vir_bytes de_read_s; int de_client; message de_sendmsg; dp_user2nicf_t de_user2nicf; + dp_user2nicf_s_t de_user2nicf_s; dp_nic2userf_t de_nic2userf; + dp_nic2userf_s_t de_nic2userf_s; dp_getblock_t de_getblockf; } dpeth_t; diff --git a/drivers/dpeth/3c509.c b/drivers/dpeth/3c509.c index 2510a51d0..14c89a526 100644 --- a/drivers/dpeth/3c509.c +++ b/drivers/dpeth/3c509.c @@ -122,16 +122,19 @@ static void el3_write_fifo(dpeth_t * dep, int pktsize) { phys_bytes phys_user; int bytes, ix = 0; - iovec_dat_t *iovp = &dep->de_write_iovec; - int padding = pktsize; + iovec_dat_s_t *iovp = &dep->de_write_iovec; + int r, padding = pktsize; do { /* Writes chuncks of packet from user buffers */ bytes = iovp->iod_iovec[ix].iov_size; /* Size of buffer */ if (bytes > pktsize) bytes = pktsize; /* Writes from user buffer to Tx FIFO */ - outsb(dep->de_data_port, iovp->iod_proc_nr, - (void*)(iovp->iod_iovec[ix].iov_addr), bytes); + r= sys_safe_insb(dep->de_data_port, iovp->iod_proc_nr, + iovp->iod_iovec[ix].iov_grant, 0, bytes); + if (r != OK) + panic(__FILE__, "el3_write_fifo: sys_safe_insb failed", r); + if (++ix >= IOVEC_NR) { /* Next buffer of IO vector */ dp_next_iovec(iovp); ix = 0; diff --git a/drivers/dpeth/8390.c b/drivers/dpeth/8390.c index c435e3945..9116d2fea 100644 --- a/drivers/dpeth/8390.c +++ b/drivers/dpeth/8390.c @@ -1,3 +1,4 @@ +#include /* ** File: 8390.c May 02, 2000 ** @@ -25,14 +26,18 @@ #include "8390.h" +#if 0 #define sys_nic2mem(srcOffs,dstProc,dstOffs,length) \ sys_vircopy(SELF,dep->de_memsegm,(vir_bytes)(srcOffs),\ (dstProc),D,(vir_bytes)(dstOffs),length) -#define sys_user2nic(srcProc,srcOffs,dstOffs,length) \ - sys_vircopy((srcProc),D,(vir_bytes)(srcOffs),\ - SELF,dep->de_memsegm,(vir_bytes)(dstOffs),length) +#endif +#if 0 +#define sys_user2nic_s(srcProc,grant,dstOffs,length) \ + sys_safecopyfrom((srcProc),(grant),0, \ + (vir_bytes)(dstOffs),length,dep->de_memsegm) +#endif -static const char RdmaErrMsg[] = "remote dma failed to complete"; +static char RdmaErrMsg[] = "remote dma failed to complete"; /* ** Name: void ns_rw_setup(dpeth_t *dep, int mode, int size, u16_t offset); @@ -72,9 +77,11 @@ static void ns_start_xmit(dpeth_t * dep, int size, int pageno) */ static void mem_getblock(dpeth_t *dep, u16_t offset, int size, void *dst) { - + panic(__FILE__, "mem_getblock: not converted to safecopies", NO_NUM); +#if 0 sys_nic2mem(dep->de_linmem + offset, SELF, dst, size); return; +#endif } /* @@ -84,9 +91,12 @@ static void mem_getblock(dpeth_t *dep, u16_t offset, int size, void *dst) static void mem_nic2user(dpeth_t * dep, int pageno, int pktsize) { phys_bytes offset, phys_user; - iovec_dat_t *iovp = &dep->de_read_iovec; + iovec_dat_s_t *iovp = &dep->de_read_iovec; int bytes, ix = 0; + panic(__FILE__, "mem_nic2user: not converted to safecopies", NO_NUM); +#if 0 + /* Computes shared memory address (skipping receive header) */ offset = pageno * DP_PAGESIZE + sizeof(dp_rcvhdr_t); @@ -100,16 +110,16 @@ static void mem_nic2user(dpeth_t * dep, int pageno, int pktsize) /* Circular buffer wrap-around */ bytes = dep->de_stoppage * DP_PAGESIZE - offset; - sys_nic2mem(dep->de_linmem + offset, iovp->iod_proc_nr, - iovp->iod_iovec[ix].iov_addr, bytes); + sys_nic2mem_s(dep->de_linmem + offset, iovp->iod_proc_nr, + iovp->iod_iovec[ix].iov_grant, bytes); pktsize -= bytes; phys_user += bytes; bytes = iovp->iod_iovec[ix].iov_size - bytes; if (bytes > pktsize) bytes = pktsize; offset = dep->de_startpage * DP_PAGESIZE; } - sys_nic2mem(dep->de_linmem + offset, iovp->iod_proc_nr, - iovp->iod_iovec[ix].iov_addr, bytes); + sys_nic2mem_s(dep->de_linmem + offset, iovp->iod_proc_nr, + iovp->iod_iovec[ix].iov_grant, bytes); offset += bytes; if (++ix >= IOVEC_NR) { /* Next buffer of IO vector */ @@ -119,6 +129,7 @@ static void mem_nic2user(dpeth_t * dep, int pageno, int pktsize) /* Till packet done */ } while ((pktsize -= bytes) > 0); return; +#endif } /* @@ -128,9 +139,12 @@ static void mem_nic2user(dpeth_t * dep, int pageno, int pktsize) static void mem_user2nic(dpeth_t *dep, int pageno, int pktsize) { phys_bytes offset, phys_user; - iovec_dat_t *iovp = &dep->de_write_iovec; + iovec_dat_s_t *iovp = &dep->de_write_iovec; int bytes, ix = 0; + panic(__FILE__, "mem_user2nic: not converted to safecopies", NO_NUM); +#if 0 + /* Computes shared memory address */ offset = pageno * DP_PAGESIZE; @@ -140,7 +154,7 @@ static void mem_user2nic(dpeth_t *dep, int pageno, int pktsize) if (bytes > pktsize) bytes = pktsize; /* Reads from user area to board (shared memory) */ - sys_user2nic(iovp->iod_proc_nr, iovp->iod_iovec[ix].iov_addr, + sys_user2nic_s(iovp->iod_proc_nr, iovp->iod_iovec[ix].iov_grant, dep->de_linmem + offset, bytes); offset += bytes; @@ -151,6 +165,7 @@ static void mem_user2nic(dpeth_t *dep, int pageno, int pktsize) /* Till packet done */ } while ((pktsize -= bytes) > 0); return; +#endif } /* @@ -183,8 +198,8 @@ static void pio_getblock(dpeth_t *dep, u16_t offset, int size, void *dst) static void pio_nic2user(dpeth_t *dep, int pageno, int pktsize) { phys_bytes phys_user; - iovec_dat_t *iovp = &dep->de_read_iovec; - unsigned offset; int bytes, ix = 0; + iovec_dat_s_t *iovp = &dep->de_read_iovec; + unsigned offset, iov_offset; int r, bytes, ix = 0; /* Computes memory address (skipping receive header) */ offset = pageno * DP_PAGESIZE + sizeof(dp_rcvhdr_t); @@ -192,6 +207,7 @@ static void pio_nic2user(dpeth_t *dep, int pageno, int pktsize) ns_rw_setup(dep, CR_DM_RR, ((offset + pktsize) > (dep->de_stoppage * DP_PAGESIZE)) ? (dep->de_stoppage * DP_PAGESIZE) - offset : pktsize, offset); + iov_offset= 0; do { /* Reads chuncks of packet into user area */ bytes = iovp->iod_iovec[ix].iov_size; /* Size of a chunck */ @@ -201,21 +217,31 @@ static void pio_nic2user(dpeth_t *dep, int pageno, int pktsize) /* Circular buffer wrap-around */ bytes = dep->de_stoppage * DP_PAGESIZE - offset; - insb(dep->de_data_port, iovp->iod_proc_nr, (void*)(iovp->iod_iovec[ix].iov_addr), bytes); + r= sys_safe_insb(dep->de_data_port, iovp->iod_proc_nr, + iovp->iod_iovec[ix].iov_grant, iov_offset, bytes); + if (r != OK) + { + panic(__FILE__, "pio_nic2user: sys_safe_insb failed", + r); + } pktsize -= bytes; - iovp->iod_iovec[ix].iov_addr += bytes; + iov_offset += bytes; bytes = iovp->iod_iovec[ix].iov_size - bytes; if (bytes > pktsize) bytes = pktsize; offset = dep->de_startpage * DP_PAGESIZE; ns_rw_setup(dep, CR_DM_RR, pktsize, offset); } - insb(dep->de_data_port, iovp->iod_proc_nr, (void*)(iovp->iod_iovec[ix].iov_addr), bytes); + r= sys_safe_insb(dep->de_data_port, iovp->iod_proc_nr, + iovp->iod_iovec[ix].iov_grant, iov_offset, bytes); + if (r != OK) + panic(__FILE__, "pio_nic2user: sys_safe_insb failed", r); offset += bytes; if (++ix >= IOVEC_NR) { /* Next buffer of IO vector */ dp_next_iovec(iovp); ix = 0; } + iov_offset= 0; /* Till packet done */ } while ((pktsize -= bytes) > 0); return; @@ -228,8 +254,8 @@ static void pio_nic2user(dpeth_t *dep, int pageno, int pktsize) static void pio_user2nic(dpeth_t *dep, int pageno, int pktsize) { phys_bytes phys_user; - iovec_dat_t *iovp = &dep->de_write_iovec; - int bytes, ix = 0; + iovec_dat_s_t *iovp = &dep->de_write_iovec; + int r, bytes, ix = 0; /* Sets up board for writing */ ns_rw_setup(dep, CR_DM_RW, pktsize, pageno * DP_PAGESIZE); @@ -238,8 +264,10 @@ static void pio_user2nic(dpeth_t *dep, int pageno, int pktsize) bytes = iovp->iod_iovec[ix].iov_size; /* Size of chunck */ if (bytes > pktsize) bytes = pktsize; - outsb(dep->de_data_port, iovp->iod_proc_nr, - (void*)(iovp->iod_iovec[ix].iov_addr), bytes); + r= sys_safe_outsb(dep->de_data_port, iovp->iod_proc_nr, + iovp->iod_iovec[ix].iov_grant, 0, bytes); + if (r != OK) + panic(__FILE__, "pio_user2nic: sys_safe_outsb failed", r); if (++ix >= IOVEC_NR) { /* Next buffer of I/O vector */ dp_next_iovec(iovp); diff --git a/drivers/dpeth/Makefile b/drivers/dpeth/Makefile index 8bc1107c7..49749a863 100644 --- a/drivers/dpeth/Makefile +++ b/drivers/dpeth/Makefile @@ -2,6 +2,9 @@ ## Makefile for ISA ethernet drivers May 02, 2000 ## ## $Log$ +## Revision 1.4 2006/07/10 12:43:38 philip +## Safecopy support in ethernet drivers. +## ## Revision 1.3 2005/07/19 13:21:48 jnherder ## Renamed src/lib/utils to src/lib/sysutil --- because of new src/lib/util ## @@ -26,7 +29,7 @@ debug = 0 CC = exec cc LD = $(CC) CPPFLAGS= -I.. -I/usr/include -Ddebug=$(debug) -CFLAGS = -ws $(CPPFLAGS) +CFLAGS = $(CPPFLAGS) LDFLAGS = -i -o $@ SRCS = 3c501.c 3c509.c 3c503.c ne.c wd.c 8390.c devio.c netbuff.c dp.c diff --git a/drivers/dpeth/devio.c b/drivers/dpeth/devio.c index 832270c62..b4c1ff5a5 100644 --- a/drivers/dpeth/devio.c +++ b/drivers/dpeth/devio.c @@ -29,7 +29,7 @@ static void warning(const char *type, int err) */ PUBLIC unsigned int inb(unsigned short port) { - unsigned int value; + unsigned long value; int rc; if ((rc = sys_inb(port, &value)) != OK) warning("inb", rc); @@ -42,7 +42,7 @@ PUBLIC unsigned int inb(unsigned short port) */ PUBLIC unsigned int inw(unsigned short port) { - unsigned int value; + unsigned long value; int rc; if ((rc = sys_inw(port, &value)) != OK) warning("inw", rc); diff --git a/drivers/dpeth/dp.c b/drivers/dpeth/dp.c index 8894b1396..73f6fa9a6 100644 --- a/drivers/dpeth/dp.c +++ b/drivers/dpeth/dp.c @@ -1,3 +1,4 @@ +#include /* ** File: eth.c Version 1.00, Jan. 14, 1997 ** @@ -29,7 +30,7 @@ ** +------------+---------+---------+--------+-------+---------+ ** | DL_READV | port nr | proc nr | count | | address | (6) ** +------------+---------+---------+--------+-------+---------+ -** | DL_INIT | port nr | proc nr | | mode | address | (7) +** | DL_CONF | port nr | proc nr | | mode | address | (7) ** +------------+---------+---------+--------+-------+---------+ ** | DL_STOP | port_nr | | | | | (8) ** +------------+---------+---------+--------+-------+---------+ @@ -45,7 +46,7 @@ ** ** m_type m3_i1 m3_i2 m3_ca1 ** +------------+---------+---------+---------------+ -** |DL_INIT_REPL| port nr |last port| ethernet addr | (20) +** |DL_CONF_REPL| port nr |last port| ethernet addr | (20) ** +------------+---------+---------+---------------+ ** ** $Id$ @@ -80,13 +81,13 @@ static dp_conf_t dp_conf[DE_PORT_NR] = { { 0x280, 10, 0xCC000, "DPETH1", }, }; -static const char CopyErrMsg[] = "unable to read/write user data"; -static const char PortErrMsg[] = "illegal port"; -static const char RecvErrMsg[] = "receive failed"; -static const char SendErrMsg[] = "send failed"; -static const char SizeErrMsg[] = "illegal packet size"; -static const char TypeErrMsg[] = "illegal message type"; -static const char DevName[] = "eth#?"; +static char CopyErrMsg[] = "unable to read/write user data"; +static char PortErrMsg[] = "illegal port"; +static char RecvErrMsg[] = "receive failed"; +static char SendErrMsg[] = "send failed"; +static char SizeErrMsg[] = "illegal packet size"; +static char TypeErrMsg[] = "illegal message type"; +static char DevName[] = "eth#?"; static void do_getname(message *mp); @@ -223,16 +224,17 @@ static void do_dump(message *mp) } /* -** Name: void get_userdata(int user_proc, vir_bytes user_addr, int count, void *loc_addr) +** Name: void get_userdata_s(int user_proc, vir_bytes user_addr, int count, void *loc_addr) ** Function: Copies data from user area. */ -static void get_userdata(int user_proc, vir_bytes user_addr, int count, void *loc_addr) +static void get_userdata_s(int user_proc, cp_grant_id_t grant, + vir_bytes offset, int count, void *loc_addr) { int rc; vir_bytes len; len = (count > IOVEC_NR ? IOVEC_NR : count) * sizeof(iovec_t); - if ((rc = sys_datacopy(user_proc, user_addr, SELF, (vir_bytes)loc_addr, len)) != OK) + if ((rc = sys_safecopyfrom(user_proc, grant, 0, (vir_bytes)loc_addr, len, D)) != OK) panic(DevName, CopyErrMsg, rc); return; } @@ -339,7 +341,7 @@ static void do_init(message * mp) } else /* Port number is out of range */ port = ENXIO; - reply_mess.m_type = DL_INIT_REPLY; + reply_mess.m_type = DL_CONF_REPLY; reply_mess.m3_i1 = port; reply_mess.m3_i2 = DE_PORT_NR; DEBUG(printf("\t reply %d\n", reply_mess.m_type)); @@ -353,12 +355,12 @@ static void do_init(message * mp) ** Name: void dp_next_iovec(iovec_dat_t *iovp) ** Function: Retrieves data from next iovec element. */ -PUBLIC void dp_next_iovec(iovec_dat_t * iovp) +PUBLIC void dp_next_iovec(iovec_dat_s_t * iovp) { iovp->iod_iovec_s -= IOVEC_NR; - iovp->iod_iovec_addr += IOVEC_NR * sizeof(iovec_t); - get_userdata(iovp->iod_proc_nr, iovp->iod_iovec_addr, + iovp->iod_iovec_offset += IOVEC_NR * sizeof(iovec_t); + get_userdata_s(iovp->iod_proc_nr, iovp->iod_grant, iovp->iod_iovec_offset, iovp->iod_iovec_s, iovp->iod_iovec); return; } @@ -367,7 +369,7 @@ PUBLIC void dp_next_iovec(iovec_dat_t * iovp) ** Name: int calc_iovec_size(iovec_dat_t *iovp) ** Function: Compute the size of a request. */ -static int calc_iovec_size(iovec_dat_t * iovp) +static int calc_iovec_size(iovec_dat_s_t * iovp) { int size, ix; @@ -385,10 +387,10 @@ static int calc_iovec_size(iovec_dat_t * iovp) } /* -** Name: void do_vwrite(message *mp, int vectored) +** Name: void do_vwrite_s(message *mp, int vectored) ** Function: */ -static void do_vwrite(message * mp, int vectored) +static void do_vwrite_s(message * mp) { int port, size; dpeth_t *dep; @@ -406,18 +408,12 @@ static void do_vwrite(message * mp, int vectored) panic(dep->de_name, "send already in progress ", NO_NUM); dep->de_write_iovec.iod_proc_nr = mp->DL_PROC; - if (vectored) { - get_userdata(mp->DL_PROC, (vir_bytes) mp->DL_ADDR, - mp->DL_COUNT, dep->de_write_iovec.iod_iovec); - dep->de_write_iovec.iod_iovec_s = mp->DL_COUNT; - dep->de_write_iovec.iod_iovec_addr = (vir_bytes) mp->DL_ADDR; - size = calc_iovec_size(&dep->de_write_iovec); - } else { - dep->de_write_iovec.iod_iovec[0].iov_addr = (vir_bytes) mp->DL_ADDR; - dep->de_write_iovec.iod_iovec[0].iov_size = size = mp->DL_COUNT; - dep->de_write_iovec.iod_iovec_s = 1; - dep->de_write_iovec.iod_iovec_addr = 0; - } + get_userdata_s(mp->DL_PROC, mp->DL_GRANT, 0, + mp->DL_COUNT, dep->de_write_iovec.iod_iovec); + dep->de_write_iovec.iod_iovec_s = mp->DL_COUNT; + dep->de_write_iovec.iod_grant = (vir_bytes) mp->DL_GRANT; + dep->de_write_iovec.iod_iovec_offset = 0; + size = calc_iovec_size(&dep->de_write_iovec); if (size < ETH_MIN_PACK_SIZE || size > ETH_MAX_PACK_SIZE) panic(dep->de_name, SizeErrMsg, size); @@ -432,10 +428,10 @@ static void do_vwrite(message * mp, int vectored) } /* -** Name: void do_vread(message *mp, int vectored) +** Name: void do_vread_s(message *mp, int vectored) ** Function: */ -static void do_vread(message * mp, int vectored) +static void do_vread_s(message * mp) { int port, size; dpeth_t *dep; @@ -453,18 +449,12 @@ static void do_vread(message * mp, int vectored) panic(dep->de_name, "read already in progress", NO_NUM); dep->de_read_iovec.iod_proc_nr = mp->DL_PROC; - if (vectored) { - get_userdata(mp->DL_PROC, (vir_bytes) mp->DL_ADDR, - mp->DL_COUNT, dep->de_read_iovec.iod_iovec); - dep->de_read_iovec.iod_iovec_s = mp->DL_COUNT; - dep->de_read_iovec.iod_iovec_addr = (vir_bytes) mp->DL_ADDR; - size = calc_iovec_size(&dep->de_read_iovec); - } else { - dep->de_read_iovec.iod_iovec[0].iov_addr = (vir_bytes) mp->DL_ADDR; - dep->de_read_iovec.iod_iovec[0].iov_size = size = mp->DL_COUNT; - dep->de_read_iovec.iod_iovec_s = 1; - dep->de_read_iovec.iod_iovec_addr = 0; - } + get_userdata_s(mp->DL_PROC, (vir_bytes) mp->DL_GRANT, 0, + mp->DL_COUNT, dep->de_read_iovec.iod_iovec); + dep->de_read_iovec.iod_iovec_s = mp->DL_COUNT; + dep->de_read_iovec.iod_grant = (vir_bytes) mp->DL_GRANT; + dep->de_read_iovec.iod_iovec_offset = 0; + size = calc_iovec_size(&dep->de_read_iovec); if (size < ETH_MAX_PACK_SIZE) panic(dep->de_name, SizeErrMsg, size); dep->de_flags |= DEF_READING; @@ -481,10 +471,10 @@ static void do_vread(message * mp, int vectored) } /* -** Name: void do_getstat(message *mp) +** Name: void do_getstat_s(message *mp) ** Function: Reports device statistics. */ -static void do_getstat(message * mp) +static void do_getstat_s(message * mp) { int port, rc; dpeth_t *dep; @@ -497,9 +487,9 @@ static void do_getstat(message * mp) dep->de_client = mp->DL_PROC; if (dep->de_mode == DEM_ENABLED) (*dep->de_getstatsf) (dep); - if ((rc = sys_datacopy(SELF, (vir_bytes)&dep->de_stat, - mp->DL_PROC, (vir_bytes)mp->DL_ADDR, - (vir_bytes) sizeof(dep->de_stat))) != OK) + if ((rc = sys_safecopyto(mp->DL_PROC, mp->DL_GRANT, 0, + (vir_bytes)&dep->de_stat, + (vir_bytes) sizeof(dep->de_stat), 0)) != OK) panic(DevName, CopyErrMsg, rc); reply(dep, OK); return; @@ -592,23 +582,17 @@ PUBLIC int main(int argc, char **argv) case DEV_PING: /* Status request from RS */ notify(m.m_source); continue; - case DL_WRITE: /* Write message to device */ - do_vwrite(&m, FALSE); + case DL_WRITEV_S: /* Write message to device */ + do_vwrite_s(&m); break; - case DL_WRITEV: /* Write message to device */ - do_vwrite(&m, TRUE); + case DL_READV_S: /* Read message from device */ + do_vread_s(&m); break; - case DL_READ: /* Read message from device */ - do_vread(&m, FALSE); - break; - case DL_READV: /* Read message from device */ - do_vread(&m, TRUE); - break; - case DL_INIT: /* Initialize device */ + case DL_CONF: /* Initialize device */ do_init(&m); break; - case DL_GETSTAT: /* Get device statistics */ - do_getstat(&m); + case DL_GETSTAT_S: /* Get device statistics */ + do_getstat_s(&m); break; case DL_GETNAME: do_getname(&m); diff --git a/drivers/dpeth/dp.h b/drivers/dpeth/dp.h index d88cf674d..a18f9240c 100644 --- a/drivers/dpeth/dp.h +++ b/drivers/dpeth/dp.h @@ -6,6 +6,9 @@ ** Interface description for ethernet device driver ** ** $Log$ +** Revision 1.5 2006/07/10 12:43:38 philip +** Safecopy support in ethernet drivers. +** ** Revision 1.4 2005/09/04 18:52:16 beng ** Giovanni's fixes to dpeth: ** Date: Sat, 03 Sep 2005 11:05:22 +0200 @@ -83,12 +86,13 @@ typedef void (*dp_getblock_t) (struct dpeth *, u16_t, int, void *); #define SENDQ_NR 2 /* Size of the send queue */ #define IOVEC_NR 16 /* Number of IOVEC entries at a time */ -typedef struct iovec_dat { - iovec_t iod_iovec[IOVEC_NR]; +typedef struct iovec_dat_s { + iovec_s_t iod_iovec[IOVEC_NR]; int iod_iovec_s; int iod_proc_nr; - vir_bytes iod_iovec_addr; -} iovec_dat_t; + cp_grant_id_t iod_grant; + vir_bytes iod_iovec_offset; +} iovec_dat_s_t; typedef struct dpeth { /* The de_base_port field is the starting point of the probe. The @@ -161,8 +165,8 @@ typedef struct dpeth { #define DEM_ENABLED 0x0002 /* Temporary storage for RECV/SEND requests */ - iovec_dat_t de_read_iovec; - iovec_dat_t de_write_iovec; + iovec_dat_s_t de_read_iovec; + iovec_dat_s_t de_write_iovec; vir_bytes de_read_s; vir_bytes de_send_s; int de_client; @@ -216,7 +220,7 @@ typedef struct dpeth { */ /* dp.c */ -void dp_next_iovec(iovec_dat_t * iovp); +void dp_next_iovec(iovec_dat_s_t * iovp); /* devio.c */ #if defined USE_IOPL diff --git a/drivers/dpeth/netbuff.c b/drivers/dpeth/netbuff.c index 8b1d97d5a..91cf20f2c 100644 --- a/drivers/dpeth/netbuff.c +++ b/drivers/dpeth/netbuff.c @@ -111,8 +111,8 @@ PUBLIC void mem2user(dpeth_t *dep, buff_t *rxbuff) { phys_bytes phys_user; int bytes, ix = 0; - iovec_dat_t *iovp = &dep->de_read_iovec; - int pktsize = rxbuff->size; + iovec_dat_s_t *iovp = &dep->de_read_iovec; + int r, pktsize = rxbuff->size; char *buffer = rxbuff->buffer; do { /* Reads chuncks of packet into user buffers */ @@ -121,8 +121,10 @@ PUBLIC void mem2user(dpeth_t *dep, buff_t *rxbuff) if (bytes > pktsize) bytes = pktsize; /* Reads from Rx buffer to user area */ - sys_datacopy(SELF, (vir_bytes)buffer, iovp->iod_proc_nr, - iovp->iod_iovec[ix].iov_addr, bytes); + r= sys_safecopyto(iovp->iod_proc_nr, iovp->iod_iovec[ix].iov_grant, 0, + (vir_bytes)buffer, bytes, D); + if (r != OK) + panic(__FILE__, "mem2user: sys_safecopyto failed", r); buffer += bytes; if (++ix >= IOVEC_NR) { /* Next buffer of IO vector */ @@ -142,16 +144,18 @@ PUBLIC void user2mem(dpeth_t *dep, buff_t *txbuff) { phys_bytes phys_user; int bytes, ix = 0; - iovec_dat_t *iovp = &dep->de_write_iovec; - int pktsize = txbuff->size; + iovec_dat_s_t *iovp = &dep->de_write_iovec; + int r, pktsize = txbuff->size; char *buffer = txbuff->buffer; do { /* Reads chuncks of packet from user buffers */ bytes = iovp->iod_iovec[ix].iov_size; /* Size of buffer */ if (bytes > pktsize) bytes = pktsize; - sys_datacopy(iovp->iod_proc_nr, iovp->iod_iovec[ix].iov_addr, - SELF, (vir_bytes)buffer, bytes); + r= sys_safecopyfrom(iovp->iod_proc_nr, iovp->iod_iovec[ix].iov_grant, + 0, (vir_bytes)buffer, bytes, D); + if (r != OK) + panic(__FILE__, "user2mem: sys_safecopyfrom failed", r); buffer += bytes; if (++ix >= IOVEC_NR) { /* Next buffer of IO vector */ diff --git a/drivers/fxp/Makefile b/drivers/fxp/Makefile index 827da511f..e72c71fdd 100644 --- a/drivers/fxp/Makefile +++ b/drivers/fxp/Makefile @@ -21,7 +21,7 @@ OBJ = fxp.o mii.o all build: $(DRIVER) $(DRIVER): $(OBJ) $(CC) -o $@ $(LDFLAGS) $(OBJ) $(LIBS) - install -S 4096 $(DRIVER) + install -S 8k $(DRIVER) # install with other drivers install: /usr/sbin/$(DRIVER) diff --git a/drivers/fxp/fxp.c b/drivers/fxp/fxp.c index 223cb81b6..cb7f152af 100644 --- a/drivers/fxp/fxp.c +++ b/drivers/fxp/fxp.c @@ -6,24 +6,30 @@ * * The valid messages and their parameters are: * - * m_type DL_PORT DL_PROC DL_COUNT DL_MODE DL_ADDR - * |------------+----------+---------+----------+---------+---------| - * | HARDINT | | | | | | - * |------------|----------|---------|----------|---------|---------| - * | DL_WRITE | port nr | proc nr | count | mode | address | - * |------------|----------|---------|----------|---------|---------| - * | DL_WRITEV | port nr | proc nr | count | mode | address | - * |------------|----------|---------|----------|---------|---------| - * | DL_READ | port nr | proc nr | count | | address | - * |------------|----------|---------|----------|---------|---------| - * | DL_READV | port nr | proc nr | count | | address | - * |------------|----------|---------|----------|---------|---------| - * | DL_INIT | port nr | proc nr | mode | | address | - * |------------|----------|---------|----------|---------|---------| - * | DL_GETSTAT | port nr | proc nr | | | address | - * |------------|----------|---------|----------|---------|---------| - * | DL_STOP | port_nr | | | | | - * |------------|----------|---------|----------|---------|---------| + * m_type DL_PORT DL_PROC DL_COUNT DL_MODE DL_ADDR DL_GRANT + * |------------+----------+---------+----------+---------+---------+---------| + * | HARDINT | | | | | | | + * |------------|----------|---------|----------|---------|---------|---------| + * | DL_WRITE | port nr | proc nr | count | mode | address | | + * |------------|----------|---------|----------|---------|---------|---------| + * | DL_WRITEV | port nr | proc nr | count | mode | address | | + * |------------|----------|---------|----------|---------|---------|---------| + * | DL_WRITEV_S| port nr | proc nr | count | mode | | grant | + * |------------|----------|---------|----------|---------|---------|---------| + * | DL_READ | port nr | proc nr | count | | address | | + * |------------|----------|---------|----------|---------|---------|---------| + * | DL_READV | port nr | proc nr | count | | address | | + * |------------|----------|---------|----------|---------|---------|---------| + * | DL_READV_S | port nr | proc nr | count | | | grant | + * |------------|----------|---------|----------|---------|---------|---------| + * | DL_CONF | port nr | proc nr | | mode | address | | + * |------------|----------|---------|----------|---------|---------|---------| + * | DL_GETSTAT | port nr | proc nr | | | address | | + * |------------|----------|---------|----------|---------|---------|---------| + * |DL_GETSTAT_S| port nr | proc nr | | | | grant | + * |------------|----------|---------|----------|---------|---------|---------| + * | DL_STOP | port_nr | | | | | | + * |------------|----------|---------|----------|---------|---------|---------| * * The messages sent are: * @@ -34,7 +40,7 @@ * * m_type m3_i1 m3_i2 m3_ca1 * |-------------+---------+-----------+---------------| - * |DL_INIT_REPLY| port nr | last port | ethernet addr | + * |DL_CONF_REPLY| port nr | last port | ethernet addr | * |-------------+---------+-----------+---------------| * * Created: Nov 2004 by Philip Homburg @@ -169,6 +175,7 @@ typedef struct fxp u8_t fxp_conf_bytes[CC_BYTES_NR]; char fxp_name[sizeof("fxp#n")]; iovec_t fxp_iovec[IOVEC_NR]; + iovec_s_t fxp_iovec_s[IOVEC_NR]; } fxp_t; @@ -223,8 +230,10 @@ _PROTOTYPE( static void fxp_confaddr, (fxp_t *fp) ); _PROTOTYPE( static void fxp_rec_mode, (fxp_t *fp) ); _PROTOTYPE( static void fxp_writev, (message *mp, int from_int, int vectored) ); +_PROTOTYPE( static void fxp_writev_s, (message *mp, int from_int) ); _PROTOTYPE( static void fxp_readv, (message *mp, int from_int, int vectored) ); +_PROTOTYPE( static void fxp_readv_s, (message *mp, int from_int) ); _PROTOTYPE( static void fxp_do_conf, (fxp_t *fp) ); _PROTOTYPE( static void fxp_cu_ptr_cmd, (fxp_t *fp, int cmd, phys_bytes bus_addr, int check_idle) ); @@ -232,6 +241,7 @@ _PROTOTYPE( static void fxp_ru_ptr_cmd, (fxp_t *fp, int cmd, phys_bytes bus_addr, int check_idle) ); _PROTOTYPE( static void fxp_restart_ru, (fxp_t *fp) ); _PROTOTYPE( static void fxp_getstat, (message *mp) ); +_PROTOTYPE( static void fxp_getstat_s, (message *mp) ); _PROTOTYPE( static void fxp_getname, (message *mp) ); _PROTOTYPE( static int fxp_handler, (fxp_t *fp) ); _PROTOTYPE( static void fxp_check_ints, (fxp_t *fp) ); @@ -241,8 +251,6 @@ _PROTOTYPE( static void fxp_report_link, (fxp_t *fp) ); _PROTOTYPE( static void fxp_stop, (void)); _PROTOTYPE( static void reply, (fxp_t *fp, int err, int may_block) ); _PROTOTYPE( static void mess_reply, (message *req, message *reply) ); -_PROTOTYPE( static void put_userdata, (int user_proc, - vir_bytes user_addr, vir_bytes count, void *loc_addr) ); _PROTOTYPE( static u16_t eeprom_read, (fxp_t *fp, int reg) ); _PROTOTYPE( static void eeprom_addrsize, (fxp_t *fp) ); _PROTOTYPE( static u16_t mii_read, (fxp_t *fp, int reg) ); @@ -298,12 +306,13 @@ int main(int argc, char *argv[]) case DEV_PING: notify(m.m_source); continue; case DL_WRITEV: fxp_writev(&m, FALSE, TRUE); break; case DL_WRITE: fxp_writev(&m, FALSE, FALSE); break; -#if 0 - case DL_READ: fxp_vread(&m, FALSE); break; -#endif + case DL_WRITEV_S: fxp_writev_s(&m, FALSE); break; + case DL_READ: fxp_readv(&m, FALSE, FALSE); break; case DL_READV: fxp_readv(&m, FALSE, TRUE); break; - case DL_INIT: fxp_init(&m); break; + case DL_READV_S: fxp_readv_s(&m, FALSE); break; + case DL_CONF: fxp_init(&m); break; case DL_GETSTAT: fxp_getstat(&m); break; + case DL_GETSTAT_S: fxp_getstat_s(&m); break; case DL_GETNAME: fxp_getname(&m); break; case HARD_INT: for (i= 0, fp= &fxp_table[0]; iDL_PORT; if (port < 0 || port >= FXP_PORT_NR) { - reply_mess.m_type= DL_INIT_REPLY; + reply_mess.m_type= DL_CONF_REPLY; reply_mess.m3_i1= ENXIO; mess_reply(mp, &reply_mess); return; @@ -374,7 +383,7 @@ message *mp; if (fp->fxp_mode == FM_DISABLED) { /* Probe failed, or the device is configured off. */ - reply_mess.m_type= DL_INIT_REPLY; + reply_mess.m_type= DL_CONF_REPLY; reply_mess.m3_i1= ENXIO; mess_reply(mp, &reply_mess); return; @@ -399,7 +408,7 @@ message *mp; fp->fxp_client = mp->m_source; fxp_rec_mode(fp); - reply_mess.m_type = DL_INIT_REPLY; + reply_mess.m_type = DL_CONF_REPLY; reply_mess.m3_i1 = mp->DL_PORT; reply_mess.m3_i2 = FXP_PORT_NR; *(ether_addr_t *) reply_mess.m3_ca1 = fp->fxp_address; @@ -1194,6 +1203,152 @@ suspend: reply(fp, OK, FALSE); } +/*===========================================================================* + * fxp_writev_s * + *===========================================================================*/ +static void fxp_writev_s(mp, from_int) +message *mp; +int from_int; +{ + cp_grant_id_t iov_grant; + vir_bytes iov_offset; + int i, j, n, o, r, s, dl_port, count, size, prev_head; + int fxp_client, fxp_tx_nbuf, fxp_tx_head; + u16_t tx_command; + fxp_t *fp; + iovec_s_t *iovp; + struct tx *txp, *prev_txp; + + dl_port = mp->DL_PORT; + count = mp->DL_COUNT; + if (dl_port < 0 || dl_port >= FXP_PORT_NR) + panic("FXP","fxp_writev: illegal port", dl_port); + fp= &fxp_table[dl_port]; + fxp_client= mp->DL_PROC; + fp->fxp_client= fxp_client; + + assert(fp->fxp_mode == FM_ENABLED); + assert(fp->fxp_flags & FF_ENABLED); + + if (from_int) + { + assert(fp->fxp_flags & FF_SEND_AVAIL); + fp->fxp_flags &= ~FF_SEND_AVAIL; + fp->fxp_tx_alive= TRUE; + } + + if (fp->fxp_tx_idle) + { + txp= fp->fxp_tx_buf; + fxp_tx_head= 0; /* lint */ + prev_txp= NULL; /* lint */ + } + else + { + fxp_tx_nbuf= fp->fxp_tx_nbuf; + prev_head= fp->fxp_tx_head; + fxp_tx_head= prev_head+1; + if (fxp_tx_head == fxp_tx_nbuf) + fxp_tx_head= 0; + assert(fxp_tx_head < fxp_tx_nbuf); + + if (fxp_tx_head == fp->fxp_tx_tail) + { + /* Send queue is full */ + assert(!(fp->fxp_flags & FF_SEND_AVAIL)); + fp->fxp_flags |= FF_SEND_AVAIL; + goto suspend; + } + + prev_txp= &fp->fxp_tx_buf[prev_head]; + txp= &fp->fxp_tx_buf[fxp_tx_head]; + } + + assert(!(fp->fxp_flags & FF_SEND_AVAIL)); + assert(!(fp->fxp_flags & FF_PACK_SENT)); + + iov_grant= mp->DL_GRANT; + + size= 0; + o= 0; + iov_offset= 0; + for (i= 0; ifxp_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; jiov_size; + if (size + s > ETH_MAX_PACK_SIZE_TAGGED) + { + panic("FXP","fxp_writev: invalid packet size", + size + s); + } + + r= sys_safecopyfrom(fxp_client, iovp->iov_grant, + 0, (vir_bytes)(txp->tx_buf+o), s, D); + if (r != OK) + { + panic("FXP", + "fxp_writev_s: sys_safecopyfrom failed", + r); + } + size += s; + o += s; + } + } + if (size < ETH_MIN_PACK_SIZE) + panic("FXP","fxp_writev: invalid packet size", size); + + txp->tx_status= 0; + txp->tx_command= TXC_EL | CBL_XMIT; + txp->tx_tbda= TX_TBDA_NIL; + txp->tx_size= TXSZ_EOF | size; + txp->tx_tthresh= fp->fxp_tx_threshold; + txp->tx_ntbd= 0; + if (fp->fxp_tx_idle) + { + fp->fxp_tx_idle= 0; + fp->fxp_tx_head= fp->fxp_tx_tail= 0; + + fxp_cu_ptr_cmd(fp, SC_CU_START, fp->fxp_tx_busaddr, + TRUE /* check idle */); + } + else + { + /* Link new request in transmit list */ + tx_command= prev_txp->tx_command; + assert(tx_command == (TXC_EL | CBL_XMIT)); + prev_txp->tx_command= CBL_XMIT; + fp->fxp_tx_head= fxp_tx_head; + } + + fp->fxp_flags |= FF_PACK_SENT; + + /* If the interrupt handler called, don't send a reply. The reply + * will be sent after all interrupts are handled. + */ + if (from_int) + return; + reply(fp, OK, FALSE); + return; + +suspend: + if (from_int) + panic("FXP","fxp: should not be sending\n", NO_NUM); + + fp->fxp_tx_mess= *mp; + reply(fp, OK, FALSE); +} + /*===========================================================================* * fxp_readv * *===========================================================================*/ @@ -1374,6 +1529,179 @@ suspend: reply(fp, OK, FALSE); } +/*===========================================================================* + * fxp_readv_s * + *===========================================================================*/ +static void fxp_readv_s(mp, from_int) +message *mp; +int from_int; +{ + int i, j, n, o, r, s, dl_port, fxp_client, count, size, + fxp_rx_head, fxp_rx_nbuf; + cp_grant_id_t iov_grant; + port_t port; + unsigned packlen; + vir_bytes iov_offset; + u16_t rfd_status; + u16_t rfd_res; + u8_t scb_status; + fxp_t *fp; + iovec_s_t *iovp; + struct rfd *rfdp, *prev_rfdp; + + dl_port = mp->DL_PORT; + count = mp->DL_COUNT; + if (dl_port < 0 || dl_port >= FXP_PORT_NR) + panic("FXP","fxp_readv: illegal port", dl_port); + fp= &fxp_table[dl_port]; + fxp_client= mp->DL_PROC; + fp->fxp_client= fxp_client; + + assert(fp->fxp_mode == FM_ENABLED); + assert(fp->fxp_flags & FF_ENABLED); + + port= fp->fxp_base_port; + + fxp_rx_head= fp->fxp_rx_head; + rfdp= &fp->fxp_rx_buf[fxp_rx_head]; + + rfd_status= rfdp->rfd_status; + if (!(rfd_status & RFDS_C)) + { + /* Receive buffer is empty, suspend */ + goto suspend; + } + + if (!rfd_status & RFDS_OK) + { + /* Not OK? What happened? */ + assert(0); + } + else + { + assert(!(rfd_status & (RFDS_CRCERR | RFDS_ALIGNERR | + RFDS_OUTOFBUF | RFDS_DMAOVR | RFDS_TOOSHORT | + RFDS_RXERR))); + } + rfd_res= rfdp->rfd_res; + assert(rfd_res & RFDR_EOF); + assert(rfd_res & RFDR_F); + + packlen= rfd_res & RFDSZ_SIZE; + + iov_grant = mp->DL_GRANT; + + size= 0; + o= 0; + iov_offset= 0; + for (i= 0; ifxp_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; jiov_size; + if (size + s > packlen) + { + assert(packlen > size); + s= packlen-size; + } + + r= sys_safecopyto(fxp_client, iovp->iov_grant, + 0, (vir_bytes)(rfdp->rfd_buf+o), s, D); + if (r != OK) + { + panic("FXP","fxp_readv: sys_safecopyto failed", + r); + } + + size += s; + if (size == packlen) + break; + o += s; + } + if (size == packlen) + break; + } + if (size < packlen) + { + assert(0); + } + + fp->fxp_read_s= packlen; + fp->fxp_flags= (fp->fxp_flags & ~FF_READING) | FF_PACK_RECV; + + /* Re-init the current buffer */ + rfdp->rfd_status= 0; + rfdp->rfd_command= RFDC_EL; + rfdp->rfd_reserved= 0; + rfdp->rfd_res= 0; + rfdp->rfd_size= sizeof(rfdp->rfd_buf); + + fxp_rx_nbuf= fp->fxp_rx_nbuf; + if (fxp_rx_head == 0) + { + prev_rfdp= &fp->fxp_rx_buf[fxp_rx_nbuf-1]; + } + else + prev_rfdp= &rfdp[-1]; + + assert(prev_rfdp->rfd_command & RFDC_EL); + prev_rfdp->rfd_command &= ~RFDC_EL; + + fxp_rx_head++; + if (fxp_rx_head == fxp_rx_nbuf) + fxp_rx_head= 0; + assert(fxp_rx_head < fxp_rx_nbuf); + fp->fxp_rx_head= fxp_rx_head; + + if (!from_int) + reply(fp, OK, FALSE); + + return; + +suspend: + if (fp->fxp_rx_need_restart) + { + fp->fxp_rx_need_restart= 0; + + /* Check the status of the RU */ + scb_status= fxp_inb(port, SCB_STATUS); + if ((scb_status & SS_RUS_MASK) != SS_RU_NORES) + { + /* Race condition? */ + printf("fxp_readv: restart race: 0x%x\n", + scb_status); + assert((scb_status & SS_RUS_MASK) == SS_RU_READY); + } + else + { + fxp_restart_ru(fp); + } + } + if (from_int) + { + assert(fp->fxp_flags & FF_READING); + + /* No need to store any state */ + return; + } + + fp->fxp_rx_mess= *mp; + assert(!(fp->fxp_flags & FF_READING)); + fp->fxp_flags |= FF_READING; + + reply(fp, OK, FALSE); +} + /*===========================================================================* * fxp_do_conf * *===========================================================================*/ @@ -1529,7 +1857,7 @@ static void fxp_getstat(mp) message *mp; { clock_t t0,t1; - int dl_port; + int r, dl_port; port_t port; fxp_t *fp; u32_t *p; @@ -1592,8 +1920,88 @@ message *mp; stats.ets_CDheartbeat= 0; stats.ets_OWC= fp->fxp_stat.sc_tx_latecol; - put_userdata(mp->DL_PROC, (vir_bytes) mp->DL_ADDR, - (vir_bytes) sizeof(stats), &stats); + r= sys_vircopy(SELF, D, (vir_bytes)&stats, + mp->DL_PROC, D, (vir_bytes) mp->DL_ADDR, sizeof(stats)); + if (r != OK) + panic(__FILE__,"fxp_getstat: sys_vircopy failed", r); + reply(fp, OK, FALSE); +} + + +/*===========================================================================* + * fxp_getstat_s * + *===========================================================================*/ +static void fxp_getstat_s(mp) +message *mp; +{ + clock_t t0,t1; + int r, dl_port; + port_t port; + fxp_t *fp; + u32_t *p; + eth_stat_t stats; + + dl_port = mp->DL_PORT; + if (dl_port < 0 || dl_port >= FXP_PORT_NR) + panic("FXP","fxp_getstat: illegal port", dl_port); + fp= &fxp_table[dl_port]; + fp->fxp_client= mp->DL_PROC; + + assert(fp->fxp_mode == FM_ENABLED); + assert(fp->fxp_flags & FF_ENABLED); + + port= fp->fxp_base_port; + + p= &fp->fxp_stat.sc_tx_fcp; + *p= 0; + + /* The dump commmand doesn't take a pointer. Setting a pointer + * doesn't hurt though. + */ + fxp_cu_ptr_cmd(fp, SC_CU_DUMP_SC, 0, FALSE /* do not check idle */); + + getuptime(&t0); + do { + /* Wait for CU command to complete */ + if (*p != 0) + break; + } while (getuptime(&t1)==OK && (t1-t0) < MICROS_TO_TICKS(1000)); + + if (*p == 0) + panic("FXP","fxp_getstat: CU command failed to complete", NO_NUM); + if (*p != SCM_DSC) + panic("FXP","fxp_getstat: bad magic", NO_NUM); + + stats.ets_recvErr= + fp->fxp_stat.sc_rx_crc + + fp->fxp_stat.sc_rx_align + + fp->fxp_stat.sc_rx_resource + + fp->fxp_stat.sc_rx_overrun + + fp->fxp_stat.sc_rx_cd + + fp->fxp_stat.sc_rx_short; + stats.ets_sendErr= + fp->fxp_stat.sc_tx_maxcol + + fp->fxp_stat.sc_tx_latecol + + fp->fxp_stat.sc_tx_crs; + stats.ets_OVW= fp->fxp_stat.sc_rx_overrun; + stats.ets_CRCerr= fp->fxp_stat.sc_rx_crc; + stats.ets_frameAll= fp->fxp_stat.sc_rx_align; + stats.ets_missedP= fp->fxp_stat.sc_rx_resource; + stats.ets_packetR= fp->fxp_stat.sc_rx_good; + stats.ets_packetT= fp->fxp_stat.sc_tx_good; + stats.ets_transDef= fp->fxp_stat.sc_tx_defered; + stats.ets_collision= fp->fxp_stat.sc_tx_totcol; + stats.ets_transAb= fp->fxp_stat.sc_tx_maxcol; + stats.ets_carrSense= fp->fxp_stat.sc_tx_crs; + stats.ets_fifoUnder= fp->fxp_stat.sc_tx_underrun; + stats.ets_fifoOver= fp->fxp_stat.sc_rx_overrun; + stats.ets_CDheartbeat= 0; + stats.ets_OWC= fp->fxp_stat.sc_tx_latecol; + + r= sys_safecopyto(mp->DL_PROC, mp->DL_GRANT, 0, (vir_bytes)&stats, + sizeof(stats), D); + if (r != OK) + panic(__FILE__,"fxp_getstat_s: sys_safecopyto failed", r); reply(fp, OK, FALSE); } @@ -1697,6 +2105,11 @@ fxp_t *fp; fxp_readv(&fp->fxp_rx_mess, TRUE /* from int */, TRUE /* vectored */); } + else if (fp->fxp_rx_mess.m_type == DL_READV_S) + { + fxp_readv_s(&fp->fxp_rx_mess, TRUE /* from int */); + + } else { assert(fp->fxp_rx_mess.m_type == DL_READ); @@ -1803,6 +2216,11 @@ fxp_t *fp; TRUE /* from int */, TRUE /* vectored */); } + else if (fp->fxp_tx_mess.m_type == DL_WRITEV_S) + { + fxp_writev_s(&fp->fxp_tx_mess, + TRUE /* from int */); + } else { assert(fp->fxp_tx_mess.m_type == @@ -2212,23 +2630,6 @@ message *reply_mess; panic("FXP","fxp: unable to mess_reply", NO_NUM); } -/*===========================================================================* - * put_userdata * - *===========================================================================*/ -static void put_userdata(user_proc, user_addr, count, loc_addr) -int user_proc; -vir_bytes user_addr; -vir_bytes count; -void *loc_addr; -{ - int r; - - r= sys_vircopy(SELF, D, (vir_bytes)loc_addr, - user_proc, D, user_addr, count); - if (r != OK) - panic("FXP","put_userdata: sys_vircopy failed", r); -} - /*===========================================================================* * eeprom_read * *===========================================================================*/ diff --git a/drivers/lance/lance.c b/drivers/lance/lance.c index c60c5b66f..9b31a326c 100644 --- a/drivers/lance/lance.c +++ b/drivers/lance/lance.c @@ -6,24 +6,30 @@ * * The valid messages and their parameters are: * - * m_type DL_PORT DL_PROC DL_COUNT DL_MODE DL_ADDR - * |------------+----------+---------+----------+---------+---------| - * | HARDINT | | | | | | - * |------------|----------|---------|----------|---------|---------| - * | DL_WRITE | port nr | proc nr | count | mode | address | - * |------------|----------|---------|----------|---------|---------| - * | DL_WRITEV | port nr | proc nr | count | mode | address | - * |------------|----------|---------|----------|---------|---------| - * | DL_READ | port nr | proc nr | count | | address | - * |------------|----------|---------|----------|---------|---------| - * | DL_READV | port nr | proc nr | count | | address | - * |------------|----------|---------|----------|---------|---------| - * | DL_INIT | port nr | proc nr | mode | | address | - * |------------|----------|---------|----------|---------|---------| - * | DL_GETSTAT | port nr | proc nr | | | address | - * |------------|----------|---------|----------|---------|---------| - * | DL_STOP | port_nr | | | | | - * |------------|----------|---------|----------|---------|---------| + * m_type DL_PORT DL_PROC DL_COUNT DL_MODE DL_ADDR DL_GRANT + * |------------+----------+---------+----------+---------+---------+---------| + * | HARDINT | | | | | | | + * |------------|----------|---------|----------|---------|---------|---------| + * | DL_WRITE | port nr | proc nr | count | mode | address | | + * |------------|----------|---------|----------|---------|---------|---------| + * | DL_WRITEV | port nr | proc nr | count | mode | address | | + * |------------|----------|---------|----------|---------|---------|---------| + * | DL_WRITEV_S| port nr | proc nr | count | mode | | grant | + * |------------|----------|---------|----------|---------|---------|---------| + * | DL_READ | port nr | proc nr | count | | address | | + * |------------|----------|---------|----------|---------|---------|---------| + * | DL_READV | port nr | proc nr | count | | address | | + * |------------|----------|---------|----------|---------|---------|---------| + * | DL_READV_S | port nr | proc nr | count | | | grant | + * |------------|----------|---------|----------|---------|---------|---------| + * | DL_CONF | port nr | proc nr | | mode | address | | + * |------------|----------|---------|----------|---------|---------|---------| + * | DL_GETSTAT | port nr | proc nr | | | address | | + * |------------|----------|---------|----------|---------|---------|---------| + * |DL_GETSTAT_S| port nr | proc nr | | | | grant | + * |------------|----------|---------|----------|---------|---------|---------| + * | DL_STOP | port_nr | | | | | | + * |------------|----------|---------|----------|---------|---------|---------| * * The messages sent are: * @@ -34,7 +40,7 @@ * * m_type m3_i1 m3_i2 m3_ca1 * |------------+---------+-----------+---------------| - * |DL_INIT_REPL| port nr | last port | ethernet addr | + * |DL_CONF_REPL| port nr | last port | ethernet addr | * |------------|---------|-----------|---------------| * * Created: Jul 27, 2002 by Kazuya Kodama @@ -144,11 +150,11 @@ _PROTOTYPE( static void reply, _PROTOTYPE( static void ec_reset, (ether_card_t *ec) ); _PROTOTYPE( static void ec_send, (ether_card_t *ec) ); _PROTOTYPE( static void ec_recv, (ether_card_t *ec) ); -_PROTOTYPE( static void do_vwrite, - (message *mp, int from_int, int vectored) ); -_PROTOTYPE( static void do_vread, (message *mp, int vectored) ); -_PROTOTYPE( static void get_userdata, - (int user_proc, vir_bytes user_addr, +_PROTOTYPE( static void do_vwrite_s, + (message *mp, int from_int) ); +_PROTOTYPE( static void do_vread_s, (message *mp) ); +_PROTOTYPE( static void get_userdata_s, + (int user_proc, cp_grant_id_t grant, vir_bytes offset, vir_bytes count, void *loc_addr) ); _PROTOTYPE( static void ec_user2nic, (ether_card_t *dep, iovec_dat_t *iovp, @@ -160,11 +166,10 @@ _PROTOTYPE( static void ec_nic2user, vir_bytes count) ); _PROTOTYPE( static int calc_iovec_size, (iovec_dat_t *iovp) ); _PROTOTYPE( static void ec_next_iovec, (iovec_dat_t *iovp) ); -_PROTOTYPE( static void do_getstat, (message *mp) ); -_PROTOTYPE( static void put_userdata, - (int user_proc, - vir_bytes user_addr, vir_bytes count, - void *loc_addr) ); +_PROTOTYPE( static void do_getstat_s, (message *mp) ); +_PROTOTYPE( static void put_userdata_s, + (int user_proc, cp_grant_id_t grant, + void *loc_addr, vir_bytes count) ); _PROTOTYPE( static void do_stop, (message *mp) ); _PROTOTYPE( static void do_getname, (message *mp) ); @@ -356,14 +361,12 @@ void main( int argc, char **argv ) switch (m.m_type){ case DEV_PING: notify(m.m_source); continue; - case DL_WRITE: do_vwrite(&m, FALSE, FALSE); break; - case DL_WRITEV: do_vwrite(&m, FALSE, TRUE); break; - case DL_READ: do_vread(&m, FALSE); break; - case DL_READV: do_vread(&m, TRUE); break; - case DL_INIT: do_init(&m); break; - case DL_GETSTAT: do_getstat(&m); break; + case DL_WRITEV_S: do_vwrite_s(&m, FALSE); break; + case DL_READV_S: do_vread_s(&m); break; + case DL_CONF: do_init(&m); break; + case DL_GETSTAT_S: do_getstat_s(&m); break; case DL_STOP: do_stop(&m); break; - case DL_GETNAME: do_getname(&m); break; + case DL_GETNAME: do_getname(&m); break; case FKEY_PRESSED: lance_dump(); break; /*case HARD_STOP: lance_stop(); break;*/ case SYS_SIG: @@ -493,7 +496,7 @@ pci_init(); port = mp->DL_PORT; if (port < 0 || port >= EC_PORT_NR_MAX) { - reply_mess.m_type= DL_INIT_REPLY; + reply_mess.m_type= DL_CONF_REPLY; reply_mess.m3_i1= ENXIO; mess_reply(mp, &reply_mess); return; @@ -517,7 +520,7 @@ pci_init(); if (ec->mode == EC_DISABLED) { /* Probe failed, or the device is configured off. */ - reply_mess.m_type= DL_INIT_REPLY; + reply_mess.m_type= DL_CONF_REPLY; reply_mess.m3_i1= ENXIO; mess_reply(mp, &reply_mess); return; @@ -535,7 +538,7 @@ pci_init(); ec->mac_address.ea_addr[4] = ec->mac_address.ea_addr[5] = 0; ec_confaddr(ec); - reply_mess.m_type = DL_INIT_REPLY; + reply_mess.m_type = DL_CONF_REPLY; reply_mess.m3_i1 = mp->DL_PORT; reply_mess.m3_i2 = EC_PORT_NR_MAX; *(ether_addr_t *) reply_mess.m3_ca1 = ec->mac_address; @@ -557,7 +560,7 @@ pci_init(); ec->client = mp->m_source; ec_reinit(ec); - reply_mess.m_type = DL_INIT_REPLY; + reply_mess.m_type = DL_CONF_REPLY; reply_mess.m3_i1 = mp->DL_PORT; reply_mess.m3_i2 = EC_PORT_NR_MAX; *(ether_addr_t *) reply_mess.m3_ca1 = ec->mac_address; @@ -1071,8 +1074,7 @@ ether_card_t *ec; ec->flags &= ~ECF_SEND_AVAIL; switch(ec->sendmsg.m_type) { - case DL_WRITE: do_vwrite(&ec->sendmsg, TRUE, FALSE); break; - case DL_WRITEV: do_vwrite(&ec->sendmsg, TRUE, TRUE); break; + case DL_WRITEV_S: do_vwrite_s(&ec->sendmsg, TRUE); break; default: panic( "lance", "wrong type:", ec->sendmsg.m_type); break; @@ -1080,11 +1082,10 @@ ether_card_t *ec; } /*===========================================================================* - * do_vread * + * do_vread_s * *===========================================================================*/ -static void do_vread(mp, vectored) +static void do_vread_s(mp) message *mp; -int vectored; { int port, count, size; ether_card_t *ec; @@ -1094,28 +1095,17 @@ int vectored; ec= &ec_table[port]; ec->client= mp->DL_PROC; - if (vectored) - { - get_userdata(mp->DL_PROC, (vir_bytes) mp->DL_ADDR, - (count > IOVEC_NR ? IOVEC_NR : count) * - sizeof(iovec_t), ec->read_iovec.iod_iovec); - ec->read_iovec.iod_iovec_s = count; - ec->read_iovec.iod_proc_nr = mp->DL_PROC; - ec->read_iovec.iod_iovec_addr = (vir_bytes) mp->DL_ADDR; - - ec->tmp_iovec = ec->read_iovec; - size= calc_iovec_size(&ec->tmp_iovec); - } - else - { - ec->read_iovec.iod_iovec[0].iov_addr = (vir_bytes) mp->DL_ADDR; - ec->read_iovec.iod_iovec[0].iov_size = mp->DL_COUNT; - ec->read_iovec.iod_iovec_s = 1; - ec->read_iovec.iod_proc_nr = mp->DL_PROC; - ec->read_iovec.iod_iovec_addr = 0; + get_userdata_s(mp->DL_PROC, (vir_bytes) mp->DL_GRANT, 0, + (count > IOVEC_NR ? IOVEC_NR : count) * + sizeof(iovec_s_t), ec->read_iovec.iod_iovec); + ec->read_iovec.iod_iovec_s = count; + ec->read_iovec.iod_proc_nr = mp->DL_PROC; + ec->read_iovec.iod_grant = (vir_bytes) mp->DL_GRANT; + ec->read_iovec.iod_iovec_offset = 0; + + ec->tmp_iovec = ec->read_iovec; + size= calc_iovec_size(&ec->tmp_iovec); - size= count; - } ec->flags |= ECF_READING; ec_recv(ec); @@ -1195,12 +1185,11 @@ ether_card_t *ec; } /*===========================================================================* - * do_vwrite * + * do_vwrite_s * *===========================================================================*/ -static void do_vwrite(mp, from_int, vectored) +static void do_vwrite_s(mp, from_int) message *mp; int from_int; -int vectored; { int port, count, check; ether_card_t *ec; @@ -1221,30 +1210,17 @@ int vectored; } /* convert the message to write_iovec */ - if (vectored) - { - get_userdata(mp->DL_PROC, (vir_bytes) mp->DL_ADDR, - (count > IOVEC_NR ? IOVEC_NR : count) * - sizeof(iovec_t), ec->write_iovec.iod_iovec); + get_userdata_s(mp->DL_PROC, mp->DL_GRANT, 0, + (count > IOVEC_NR ? IOVEC_NR : count) * + sizeof(iovec_s_t), ec->write_iovec.iod_iovec); - ec->write_iovec.iod_iovec_s = count; - ec->write_iovec.iod_proc_nr = mp->DL_PROC; - ec->write_iovec.iod_iovec_addr = (vir_bytes) mp->DL_ADDR; + ec->write_iovec.iod_iovec_s = count; + ec->write_iovec.iod_proc_nr = mp->DL_PROC; + ec->write_iovec.iod_grant = mp->DL_GRANT; + ec->write_iovec.iod_iovec_offset = 0; - ec->tmp_iovec = ec->write_iovec; - ec->write_s = calc_iovec_size(&ec->tmp_iovec); - } - else - { - ec->write_iovec.iod_iovec[0].iov_addr = (vir_bytes) mp->DL_ADDR; - ec->write_iovec.iod_iovec[0].iov_size = mp->DL_COUNT; - - ec->write_iovec.iod_iovec_s = 1; - ec->write_iovec.iod_proc_nr = mp->DL_PROC; - ec->write_iovec.iod_iovec_addr = 0; - - ec->write_s = mp->DL_COUNT; - } + ec->tmp_iovec = ec->write_iovec; + ec->write_s = calc_iovec_size(&ec->tmp_iovec); /* copy write_iovec to the slot on DMA address */ ec_user2nic(ec, &ec->write_iovec, 0, @@ -1279,26 +1255,21 @@ int vectored; /*===========================================================================* - * get_userdata * + * get_userdata_s * *===========================================================================*/ -static void get_userdata(user_proc, user_addr, count, loc_addr) +static void get_userdata_s(user_proc, grant, offset, count, loc_addr) int user_proc; -vir_bytes user_addr; +cp_grant_id_t grant; +vir_bytes offset; vir_bytes count; void *loc_addr; { - /* - phys_bytes src; - - src = numap_local(user_proc, user_addr, count); - if (!src) - panic( "lance", "umap failed", NO_NUM); - - phys_copy(src, vir2phys(loc_addr), (phys_bytes) count); - */ int cps; - cps = sys_datacopy(user_proc, user_addr, SELF, (vir_bytes) loc_addr, count); - if (cps != OK) printf("lance: warning, scopy failed: %d\n", cps); + cps = sys_safecopyfrom(user_proc, grant, offset, + (vir_bytes)loc_addr, count, D); + if (cps != OK) + panic(__FILE__, + "get_userdata_s: sys_safecopyfrom failed: %d\n", cps); } /*===========================================================================* @@ -1311,12 +1282,8 @@ vir_bytes offset; int nic_addr; vir_bytes count; { - /*phys_bytes phys_hw, phys_user;*/ int bytes, i, r; - /* - phys_hw = vir2phys(nic_addr); - */ i= 0; while (count > 0) { @@ -1336,15 +1303,10 @@ vir_bytes count; if (bytes > count) bytes = count; - /* - phys_user = numap_local(iovp->iod_proc_nr, - iovp->iod_iovec[i].iov_addr + offset, bytes); - - phys_copy(phys_user, phys_hw, (phys_bytes) bytes); - */ - if ( (r=sys_datacopy(iovp->iod_proc_nr, iovp->iod_iovec[i].iov_addr + offset, - SELF, nic_addr, count )) != OK ) - panic( "lance", "sys_datacopy failed", r ); + if ( (r=sys_safecopyfrom(iovp->iod_proc_nr, + iovp->iod_iovec[i].iov_grant, offset, + nic_addr, bytes, D )) != OK ) + panic( __FILE__, "ec_user2nic: sys_safecopyfrom failed", r ); count -= bytes; nic_addr += bytes; @@ -1362,11 +1324,8 @@ iovec_dat_t *iovp; vir_bytes offset; vir_bytes count; { - /*phys_bytes phys_hw, phys_user;*/ int bytes, i, r; - /*phys_hw = vir2phys(nic_addr);*/ - i= 0; while (count > 0) { @@ -1385,14 +1344,9 @@ vir_bytes count; bytes = iovp->iod_iovec[i].iov_size - offset; if (bytes > count) bytes = count; - /* - phys_user = numap_local(iovp->iod_proc_nr, - iovp->iod_iovec[i].iov_addr + offset, bytes); - - phys_copy(phys_hw, phys_user, (phys_bytes) bytes); - */ - if ( (r=sys_datacopy( SELF, nic_addr, iovp->iod_proc_nr, iovp->iod_iovec[i].iov_addr + offset, bytes )) != OK ) - panic( "lance", "sys_datacopy failed: ", r ); + if ( (r=sys_safecopyto( iovp->iod_proc_nr, iovp->iod_iovec[i].iov_grant, + offset, nic_addr, bytes, D )) != OK ) + panic( __FILE__, "ec_nic2user: sys_safecopyto failed: ", r ); count -= bytes; nic_addr += bytes; @@ -1433,19 +1387,20 @@ static void ec_next_iovec(iovp) iovec_dat_t *iovp; { iovp->iod_iovec_s -= IOVEC_NR; - iovp->iod_iovec_addr += IOVEC_NR * sizeof(iovec_t); + iovp->iod_iovec_offset += IOVEC_NR * sizeof(iovec_s_t); - get_userdata(iovp->iod_proc_nr, iovp->iod_iovec_addr, + get_userdata_s(iovp->iod_proc_nr, iovp->iod_grant, + iovp->iod_iovec_offset, (iovp->iod_iovec_s > IOVEC_NR ? - IOVEC_NR : iovp->iod_iovec_s) * sizeof(iovec_t), + IOVEC_NR : iovp->iod_iovec_s) * sizeof(iovec_s_t), iovp->iod_iovec); } /*===========================================================================* - * do_getstat * + * do_getstat_s * *===========================================================================*/ -static void do_getstat(mp) +static void do_getstat_s(mp) message *mp; { int port; @@ -1458,31 +1413,26 @@ message *mp; ec= &ec_table[port]; ec->client= mp->DL_PROC; - put_userdata(mp->DL_PROC, (vir_bytes) mp->DL_ADDR, - (vir_bytes) sizeof(ec->eth_stat), &ec->eth_stat); + put_userdata_s(mp->DL_PROC, mp->DL_GRANT, + &ec->eth_stat, sizeof(ec->eth_stat)); reply(ec, OK, FALSE); } /*===========================================================================* - * put_userdata * + * put_userdata_s * *===========================================================================*/ -static void put_userdata(user_proc, user_addr, count, loc_addr) +static void put_userdata_s(user_proc, grant, loc_addr, count) int user_proc; -vir_bytes user_addr; -vir_bytes count; +cp_grant_id_t grant; void *loc_addr; +vir_bytes count; { - /*phys_bytes dst; - - dst = numap_local(user_proc, user_addr, count); - if (!dst) - panic( "lance", "umap failed", NO_NUM); - - phys_copy(vir2phys(loc_addr), dst, (phys_bytes) count); - */ int cps; - cps = sys_datacopy(SELF, (vir_bytes) loc_addr, user_proc, user_addr, count); - if (cps != OK) printf("lance: warning, scopy failed: %d\n", cps); + cps = sys_safecopyto(user_proc, grant, 0, + (vir_bytes) loc_addr, count, D); + if (cps != OK) + panic(__FILE__, + "put_userdata_s: sys_safecopyto failed: %d\n", cps); } /*===========================================================================* diff --git a/drivers/lance/lance.h b/drivers/lance/lance.h index f6b93ecdb..8f6d00f96 100644 --- a/drivers/lance/lance.h +++ b/drivers/lance/lance.h @@ -53,10 +53,11 @@ #define IOVEC_NR 16 typedef struct iovec_dat { - iovec_t iod_iovec[IOVEC_NR]; + iovec_s_t iod_iovec[IOVEC_NR]; int iod_iovec_s; int iod_proc_nr; - vir_bytes iod_iovec_addr; + cp_grant_id_t iod_grant; + vir_bytes iod_iovec_offset; } iovec_dat_t; #define ETH0_SELECTOR 0x61 diff --git a/drivers/rtl8139/rtl8139.c b/drivers/rtl8139/rtl8139.c index 2d7c81e8a..3944036e8 100755 --- a/drivers/rtl8139/rtl8139.c +++ b/drivers/rtl8139/rtl8139.c @@ -6,26 +6,30 @@ * * The valid messages and their parameters are: * - * m_type DL_PORT DL_PROC DL_COUNT DL_MODE DL_ADDR - * |------------+----------+---------+----------+---------+---------| - * | HARD_INT | | | | | | - * |------------|----------|---------|----------|---------|---------| - * | DL_WRITE | port nr | proc nr | count | mode | address | - * |------------|----------|---------|----------|---------|---------| - * | DL_WRITEV | port nr | proc nr | count | mode | address | - * |------------|----------|---------|----------|---------|---------| - * | DL_READ | port nr | proc nr | count | | address | - * |------------|----------|---------|----------|---------|---------| - * | DL_READV | port nr | proc nr | count | | address | - * |------------|----------|---------|----------|---------|---------| - * | DL_INIT | port nr | proc nr | mode | | address | - * |------------|----------|---------|----------|---------|---------| - * | DL_GETSTAT | port nr | proc nr | | | address | - * |------------|----------|---------|----------|---------|---------| - * | DL_GETNAME | | | | | | - * |------------|----------|---------|----------|---------|---------| - * | DL_STOP | port_nr | | | | | - * |------------|----------|---------|----------|---------|---------| + * m_type DL_PORT DL_PROC DL_COUNT DL_MODE DL_ADDR DL_GRANT + * |------------+----------+---------+----------+---------+---------+---------| + * | HARDINT | | | | | | | + * |------------|----------|---------|----------|---------|---------|---------| + * | DL_WRITE | port nr | proc nr | count | mode | address | | + * |------------|----------|---------|----------|---------|---------|---------| + * | DL_WRITEV | port nr | proc nr | count | mode | address | | + * |------------|----------|---------|----------|---------|---------|---------| + * | DL_WRITEV_S| port nr | proc nr | count | mode | | grant | + * |------------|----------|---------|----------|---------|---------|---------| + * | DL_READ | port nr | proc nr | count | | address | | + * |------------|----------|---------|----------|---------|---------|---------| + * | DL_READV | port nr | proc nr | count | | address | | + * |------------|----------|---------|----------|---------|---------|---------| + * | DL_READV_S | port nr | proc nr | count | | | grant | + * |------------|----------|---------|----------|---------|---------|---------| + * | DL_CONF | port nr | proc nr | | mode | address | | + * |------------|----------|---------|----------|---------|---------|---------| + * | DL_GETSTAT | port nr | proc nr | | | address | | + * |------------|----------|---------|----------|---------|---------|---------| + * |DL_GETSTAT_S| port nr | proc nr | | | | grant | + * |------------|----------|---------|----------|---------|---------|---------| + * | DL_STOP | port_nr | | | | | | + * |------------|----------|---------|----------|---------|---------|---------| * * The messages sent are: * @@ -36,7 +40,7 @@ * * m_type m3_i1 m3_i2 m3_ca1 * |------------+---------+-----------+---------------| - * |DL_INIT_REPL| port nr | last port | ethernet addr | + * |DL_CONF_REPL| port nr | last port | ethernet addr | * |------------|---------|-----------|---------------| * * Created: Aug 2003 by Philip Homburg @@ -155,6 +159,7 @@ typedef struct re message re_tx_mess; char re_name[sizeof("rtl8139#n")]; iovec_t re_iovec[IOVEC_NR]; + iovec_s_t re_iovec_s[IOVEC_NR]; } re_t; @@ -238,8 +243,10 @@ _PROTOTYPE( static void rl_confaddr, (re_t *rep) ); _PROTOTYPE( static void rl_rec_mode, (re_t *rep) ); _PROTOTYPE( static void rl_readv, (message *mp, int from_int, int vectored) ); +_PROTOTYPE( static void rl_readv_s, (message *mp, int from_int) ); _PROTOTYPE( static void rl_writev, (message *mp, int from_int, int vectored) ); +_PROTOTYPE( static void rl_writev_s, (message *mp, int from_int) ); _PROTOTYPE( static void rl_check_ints, (re_t *rep) ); _PROTOTYPE( static void rl_report_link, (re_t *rep) ); _PROTOTYPE( static void mii_print_techab, (U16_t techab) ); @@ -248,11 +255,10 @@ _PROTOTYPE( static void mii_print_stat_speed, (U16_t stat, _PROTOTYPE( static void rl_clear_rx, (re_t *rep) ); _PROTOTYPE( static void rl_do_reset, (re_t *rep) ); _PROTOTYPE( static void rl_getstat, (message *mp) ); +_PROTOTYPE( static void rl_getstat_s, (message *mp) ); _PROTOTYPE( static void rl_getname, (message *mp) ); _PROTOTYPE( static void reply, (re_t *rep, int err, int may_block) ); _PROTOTYPE( static void mess_reply, (message *req, message *reply) ); -_PROTOTYPE( static void put_userdata, (int user_proc, - vir_bytes user_addr, vir_bytes count, void *loc_addr) ); _PROTOTYPE( static void rtl8139_stop, (void) ); _PROTOTYPE( static void check_int_events, (void) ); _PROTOTYPE( static int do_hard_int, (void) ); @@ -314,15 +320,16 @@ int main(int argc, char *argv[]) switch (m.m_type) { - case DEV_PING: notify(m.m_source); continue; - case DL_WRITEV: rl_writev(&m, FALSE, TRUE); break; + case DEV_PING: notify(m.m_source); break; case DL_WRITE: rl_writev(&m, FALSE, FALSE); break; -#if 0 - case DL_READ: do_vread(&m, FALSE); break; -#endif + case DL_WRITEV: rl_writev(&m, FALSE, TRUE); break; + case DL_WRITEV_S: rl_writev_s(&m, FALSE); break; + case DL_READ: rl_readv(&m, FALSE, FALSE); break; case DL_READV: rl_readv(&m, FALSE, TRUE); break; - case DL_INIT: rl_init(&m); break; + case DL_READV_S: rl_readv_s(&m, FALSE); break; + case DL_CONF: rl_init(&m); break; case DL_GETSTAT: rl_getstat(&m); break; + case DL_GETSTAT_S: rl_getstat_s(&m); break; case DL_GETNAME: rl_getname(&m); break; #if 0 case DL_STOP: do_stop(&m); break; @@ -490,7 +497,7 @@ message *mp; port = mp->DL_PORT; if (port < 0 || port >= RE_PORT_NR) { - reply_mess.m_type= DL_INIT_REPLY; + reply_mess.m_type= DL_CONF_REPLY; reply_mess.m3_i1= ENXIO; mess_reply(mp, &reply_mess); return; @@ -503,7 +510,7 @@ message *mp; if (rep->re_mode == REM_DISABLED) { /* Probe failed, or the device is configured off. */ - reply_mess.m_type= DL_INIT_REPLY; + reply_mess.m_type= DL_CONF_REPLY; reply_mess.m3_i1= ENXIO; mess_reply(mp, &reply_mess); return; @@ -530,7 +537,7 @@ message *mp; rep->re_client = mp->m_source; rl_rec_mode(rep); - reply_mess.m_type = DL_INIT_REPLY; + reply_mess.m_type = DL_CONF_REPLY; reply_mess.m3_i1 = mp->DL_PORT; reply_mess.m3_i2 = RE_PORT_NR; *(ether_addr_t *) reply_mess.m3_ca1 = rep->re_address; @@ -1058,14 +1065,6 @@ int vectored; rxstat = *(u32_t *) (rep->v_re_rx_buf + d_start); -#if DEAD_CODE - src_phys= rep->re_rx_buf + d_start; - cps = sys_physcopy( - NONE, PHYS_SEG, src_phys, - SELF, D, (vir_bytes) &rxstat, sizeof(rxstat)); - if (cps != OK) printf("RTL8139: warning, sys_abscopy failed: %d\n", cps); -#endif - if (rep->re_clear_rx) { #if 0 @@ -1113,11 +1112,6 @@ int vectored; if (vectored) { int iov_offset = 0; -#if 0 - if ((cps = sys_umap(re_client, D, (vir_bytes) mp->DL_ADDR, - count * sizeof(rep->re_iovec[0]), &iov_src)) != OK) - printf("sys_umap failed: %d\n", cps); -#endif size= 0; o= d_start+4; @@ -1129,15 +1123,15 @@ int vectored; n= IOVEC_NR; if (i+n > count) n= count-i; -#if 0 - cps = sys_physcopy(NONE, PHYS_SEG, iov_src, SELF, D, (vir_bytes) rep->re_iovec, + + cps = sys_vircopy(re_client, D, + (vir_bytes) mp->DL_ADDR + iov_offset, + SELF, D, (vir_bytes) rep->re_iovec, n * sizeof(rep->re_iovec[0])); - if (cps != OK) printf("RTL8139: warning, sys_abscopy failed: %d\n", cps); -#else - cps = sys_vircopy(re_client, D, (vir_bytes) mp->DL_ADDR + iov_offset, - SELF, D, (vir_bytes) rep->re_iovec, n * sizeof(rep->re_iovec[0])); - if (cps != OK) printf("RTL8139: warning, sys_vircopy failed: %d (%d)\n", cps, __LINE__); -#endif + if (cps != OK) + printf( + "RTL8139: warning, sys_vircopy failed: %d (%d)\n", + cps, __LINE__); for (j= 0, iovp= rep->re_iovec; jiov_addr, s, &dst_phys) != OK) - panic("rtl8139","umap_local failed\n", NO_NUM); -#endif - if (o >= RX_BUFSIZE) { o -= RX_BUFSIZE; @@ -1164,30 +1153,33 @@ int vectored; assert(ov_re_rx_buf+o, - re_client, D, iovp->iov_addr, s1); - if (cps != OK) printf("RTL8139: warning, sys_vircopy failed: %d (%d)\n", cps, __LINE__); - cps = sys_vircopy(SELF, D, (vir_bytes) rep->v_re_rx_buf, - re_client, D, iovp->iov_addr+s1, s-s1); - if (cps != OK) printf("RTL8139: warning, sys_vircopy failed: %d (%d)\n", cps, __LINE__); -#endif + cps = sys_vircopy(SELF, D, + (vir_bytes) rep->v_re_rx_buf+o, + re_client, D, iovp->iov_addr, + s1); + if (cps != OK) + printf( + "RTL8139: warning, sys_vircopy failed: %d (%d)\n", + cps, __LINE__); + cps = sys_vircopy(SELF, D, + (vir_bytes) rep->v_re_rx_buf, + re_client, D, + iovp->iov_addr+s1, s-s1); + if (cps != OK) + printf( + "RTL8139: warning, sys_vircopy failed: %d (%d)\n", + cps, __LINE__); } else { -#if 0 - cps = sys_abscopy(src_phys+o, dst_phys, s); - if (cps != OK) printf("RTL8139: warning, sys_abscopy failed: %d\n", cps); -#else - cps = sys_vircopy(SELF, D, (vir_bytes) rep->v_re_rx_buf+o, - re_client, D, iovp->iov_addr, s); - if (cps != OK) printf("RTL8139: warning, sys_vircopy failed: %d (%d)\n", cps, __LINE__); -#endif + cps = sys_vircopy(SELF, D, + (vir_bytes) rep->v_re_rx_buf+o, + re_client, D, iovp->iov_addr, + s); + if (cps != OK) + printf( + "RTL8139: warning, sys_vircopy failed: %d (%d)\n", + cps, __LINE__); } size += s; @@ -1217,146 +1209,368 @@ int vectored; cps = sys_abscopy(phys_user, p, size); if (cps != OK) printf("RTL8139: warning, sys_abscopy failed: %d\n", cps); #endif - } - - if (rep->re_clear_rx) - { - /* For some reason the receiver FIFO is not stopped when - * the buffer is full. - */ - #if 0 - printf("rl_readv: later buffer overflow\n"); - #endif - goto suspend; /* Buffer overflow */ - } - - rep->re_stat.ets_packetR++; - rep->re_read_s= packlen; - rep->re_flags= (rep->re_flags & ~REF_READING) | REF_PACK_RECV; - - /* Avoid overflow in 16-bit computations */ - l= d_start; - l += totlen+4; - l= (l+3) & ~3; /* align */ - if (l >= RX_BUFSIZE) - { - l -= RX_BUFSIZE; - assert(l < RX_BUFSIZE); - } - rl_outw(port, RL_CAPR, l-RL_CAPR_DATA_OFF); - - if (!from_int) - reply(rep, OK, FALSE); - - return; - - suspend: - if (from_int) - { - assert(rep->re_flags & REF_READING); - - /* No need to store any state */ - return; - } - - rep->re_rx_mess= *mp; - assert(!(rep->re_flags & REF_READING)); - rep->re_flags |= REF_READING; - - reply(rep, OK, FALSE); } - /*===========================================================================* - * rl_writev * - *===========================================================================*/ - static void rl_writev(mp, from_int, vectored) - message *mp; - int from_int; - int vectored; + if (rep->re_clear_rx) { - phys_bytes p, iov_src, phys_user; - int i, j, n, s, port, count, size; - int tx_head, re_client; - re_t *rep; - iovec_t *iovp; - char *ret; - int cps; + /* For some reason the receiver FIFO is not stopped when + * the buffer is full. + */ +#if 0 + printf("rl_readv: later buffer overflow\n"); +#endif + goto suspend; /* Buffer overflow */ + } - port = mp->DL_PORT; - count = mp->DL_COUNT; - if (port < 0 || port >= RE_PORT_NR) - panic("rtl8139","illegal port", port); - rep= &re_table[port]; - re_client= mp->DL_PROC; - rep->re_client= re_client; + rep->re_stat.ets_packetR++; + rep->re_read_s= packlen; + rep->re_flags= (rep->re_flags & ~REF_READING) | REF_PACK_RECV; - assert(rep->re_mode == REM_ENABLED); - assert(rep->re_flags & REF_ENABLED); + /* Avoid overflow in 16-bit computations */ + l= d_start; + l += totlen+4; + l= (l+3) & ~3; /* align */ + if (l >= RX_BUFSIZE) + { + l -= RX_BUFSIZE; + assert(l < RX_BUFSIZE); + } + rl_outw(port, RL_CAPR, l-RL_CAPR_DATA_OFF); - if (from_int) - { - assert(rep->re_flags & REF_SEND_AVAIL); - rep->re_flags &= ~REF_SEND_AVAIL; - rep->re_send_int= FALSE; - rep->re_tx_alive= TRUE; - } + if (!from_int) + reply(rep, OK, FALSE); - tx_head= rep->re_tx_head; - if (rep->re_tx[tx_head].ret_busy) - { - assert(!(rep->re_flags & REF_SEND_AVAIL)); - rep->re_flags |= REF_SEND_AVAIL; - if (rep->re_tx[tx_head].ret_busy) - goto suspend; + return; - /* Race condition, the interrupt handler may clear re_busy - * before we got a chance to set REF_SEND_AVAIL. Checking - * ret_busy twice should be sufficient. - */ - #if 0 - printf("rl_writev: race detected\n"); - #endif - rep->re_flags &= ~REF_SEND_AVAIL; - rep->re_send_int= FALSE; - } +suspend: + if (from_int) + { + assert(rep->re_flags & REF_READING); - assert(!(rep->re_flags & REF_SEND_AVAIL)); - assert(!(rep->re_flags & REF_PACK_SENT)); + /* No need to store any state */ + return; + } - if (vectored) - { - int iov_offset = 0; + rep->re_rx_mess= *mp; + assert(!(rep->re_flags & REF_READING)); + rep->re_flags |= REF_READING; + + reply(rep, OK, FALSE); +} + +/*===========================================================================* + * rl_readv_s * + *===========================================================================*/ +static void rl_readv_s(mp, from_int) +message *mp; +int from_int; +{ + int i, j, n, o, s, s1, dl_port, re_client, count, size; + port_t port; + unsigned amount, totlen, packlen; + phys_bytes src_phys, dst_phys, iov_src; + u16_t d_start, d_end; + u32_t l, rxstat = 0x12345678; + re_t *rep; + iovec_s_t *iovp; + int cps; + int iov_offset = 0; + + dl_port = mp->DL_PORT; + count = mp->DL_COUNT; + if (dl_port < 0 || dl_port >= RE_PORT_NR) + panic("rtl8139"," illegal port", dl_port); + rep= &re_table[dl_port]; + re_client= mp->DL_PROC; + rep->re_client= re_client; + + if (rep->re_clear_rx) + goto suspend; /* Buffer overflow */ + + assert(rep->re_mode == REM_ENABLED); + assert(rep->re_flags & REF_ENABLED); + + port= rep->re_base_port; + + /* Assume that the RL_CR_BUFE check was been done by rl_checks_ints + */ + if (!from_int && (rl_inb(port, RL_CR) & RL_CR_BUFE)) + { + /* Receive buffer is empty, suspend */ + goto suspend; + } + + d_start= rl_inw(port, RL_CAPR) + RL_CAPR_DATA_OFF; + d_end= rl_inw(port, RL_CBR) % RX_BUFSIZE; + + if (d_start >= RX_BUFSIZE) + { + printf("rl_readv: strange value in RL_CAPR: 0x%x\n", + rl_inw(port, RL_CAPR)); + d_start %= RX_BUFSIZE; + } + + if (d_end > d_start) + amount= d_end-d_start; + else + amount= d_end+RX_BUFSIZE - d_start; + + rxstat = *(u32_t *) (rep->v_re_rx_buf + d_start); + + if (rep->re_clear_rx) + { +#if 0 + printf("rl_readv: late buffer overflow\n"); +#endif + goto suspend; /* Buffer overflow */ + } + + /* Should convert from little endian to host byte order */ + + if (!(rxstat & RL_RXS_ROK)) + { + printf("rxstat = 0x%08lx\n", rxstat); + printf("d_start: 0x%x, d_end: 0x%x, rxstat: 0x%lx\n", + d_start, d_end, rxstat); + panic("rtl8139","received packet not OK", NO_NUM); + } + totlen= (rxstat >> RL_RXS_LEN_S); + if (totlen < 8 || totlen > 2*ETH_MAX_PACK_SIZE) + { + /* Someting went wrong */ + printf( + "rl_readv: bad length (%u) in status 0x%08lx at offset 0x%x\n", + totlen, rxstat, d_start); + printf( + "d_start: 0x%x, d_end: 0x%x, totlen: %d, rxstat: 0x%lx\n", + d_start, d_end, totlen, rxstat); + panic(NULL, NULL, NO_NUM); + } #if 0 - if (OK != sys_umap(re_client, D, (vir_bytes)mp->DL_ADDR, - count * sizeof(rep->re_iovec[0]), &iov_src)) - panic("rtl8139","umap_local failed", NO_NUM); + printf("d_start: 0x%x, d_end: 0x%x, totlen: %d, rxstat: 0x%x\n", + d_start, d_end, totlen, rxstat); #endif - size= 0; -#if 0 - p= rep->re_tx[tx_head].ret_buf; -#else - ret = rep->re_tx[tx_head].v_ret_buf; -#endif - for (i= 0; ire_iovec[0]), - iov_offset += IOVEC_NR * sizeof(rep->re_iovec[0])) + if (totlen+4 > amount) + { + printf("rl_readv: packet not yet ready\n"); + goto suspend; + } + + /* Should subtract the CRC */ + packlen= totlen - ETH_CRC_SIZE; + + size= 0; + o= d_start+4; + src_phys= rep->re_rx_buf; + for (i= 0; ire_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; jiov_size; + if (size + s > packlen) { - n= IOVEC_NR; - if (i+n > count) - n= count-i; + assert(packlen > size); + s= packlen-size; + } + #if 0 - cps = sys_physcopy(NONE, PHYS_SEG, iov_src, SELF, D, (vir_bytes) rep->re_iovec, - n * sizeof(rep->re_iovec[0])); - if (cps != OK) printf("RTL8139: warning, sys_abscopy failed: %d\n", cps); -#else - cps = sys_vircopy(re_client, D, ((vir_bytes) mp->DL_ADDR) + iov_offset, - SELF, D, (vir_bytes) rep->re_iovec, - n * sizeof(rep->re_iovec[0])); - if (cps != OK) printf("RTL8139: warning, sys_vircopy failed: %d\n", cps); + if (sys_umap(re_client, D, iovp->iov_addr, s, &dst_phys) != OK) + panic("rtl8139","umap_local failed\n", NO_NUM); #endif + if (o >= RX_BUFSIZE) + { + o -= RX_BUFSIZE; + assert(o < RX_BUFSIZE); + } + + if (o+s > RX_BUFSIZE) + { + assert(oiov_grant, 0, + (vir_bytes) rep->v_re_rx_buf+o, s1, D); + if (cps != OK) + { + panic(__FILE__, + "rl_readv_s: sys_safecopyto failed", + cps); + } + cps = sys_safecopyto(re_client, + iovp->iov_grant, s1, + (vir_bytes) rep->v_re_rx_buf, s-s1, S); + if (cps != OK) + { + panic(__FILE__, + "rl_readv_s: sys_safecopyto failed", + cps); + } + } + else + { + cps = sys_safecopyto(re_client, + iovp->iov_grant, 0, + (vir_bytes) rep->v_re_rx_buf+o, s, D); + if (cps != OK) + panic(__FILE__, + "rl_readv_s: sys_vircopy failed", + cps); + } + + size += s; + if (size == packlen) + break; + o += s; + } + if (size == packlen) + break; + } + if (size < packlen) + { + assert(0); + } + + if (rep->re_clear_rx) + { + /* For some reason the receiver FIFO is not stopped when + * the buffer is full. + */ +#if 0 + printf("rl_readv: later buffer overflow\n"); +#endif + goto suspend; /* Buffer overflow */ + } + + rep->re_stat.ets_packetR++; + rep->re_read_s= packlen; + rep->re_flags= (rep->re_flags & ~REF_READING) | REF_PACK_RECV; + + /* Avoid overflow in 16-bit computations */ + l= d_start; + l += totlen+4; + l= (l+3) & ~3; /* align */ + if (l >= RX_BUFSIZE) + { + l -= RX_BUFSIZE; + assert(l < RX_BUFSIZE); + } + rl_outw(port, RL_CAPR, l-RL_CAPR_DATA_OFF); + + if (!from_int) + reply(rep, OK, FALSE); + + return; + +suspend: + if (from_int) + { + assert(rep->re_flags & REF_READING); + + /* No need to store any state */ + return; + } + + rep->re_rx_mess= *mp; + assert(!(rep->re_flags & REF_READING)); + rep->re_flags |= REF_READING; + + reply(rep, OK, FALSE); +} + +/*===========================================================================* + * rl_writev * + *===========================================================================*/ +static void rl_writev(mp, from_int, vectored) +message *mp; +int from_int; +int vectored; +{ + phys_bytes iov_src, phys_user; + int i, j, n, s, port, count, size; + int tx_head, re_client; + re_t *rep; + iovec_t *iovp; + char *ret; + int cps; + + port = mp->DL_PORT; + count = mp->DL_COUNT; + if (port < 0 || port >= RE_PORT_NR) + panic("rtl8139","illegal port", port); + rep= &re_table[port]; + re_client= mp->DL_PROC; + rep->re_client= re_client; + + assert(rep->re_mode == REM_ENABLED); + assert(rep->re_flags & REF_ENABLED); + + if (from_int) + { + assert(rep->re_flags & REF_SEND_AVAIL); + rep->re_flags &= ~REF_SEND_AVAIL; + rep->re_send_int= FALSE; + rep->re_tx_alive= TRUE; + } + + tx_head= rep->re_tx_head; + if (rep->re_tx[tx_head].ret_busy) + { + assert(!(rep->re_flags & REF_SEND_AVAIL)); + rep->re_flags |= REF_SEND_AVAIL; + if (rep->re_tx[tx_head].ret_busy) + goto suspend; + + /* Race condition, the interrupt handler may clear re_busy + * before we got a chance to set REF_SEND_AVAIL. Checking + * ret_busy twice should be sufficient. + */ +#if 0 + printf("rl_writev: race detected\n"); +#endif + rep->re_flags &= ~REF_SEND_AVAIL; + rep->re_send_int= FALSE; + } + + assert(!(rep->re_flags & REF_SEND_AVAIL)); + assert(!(rep->re_flags & REF_PACK_SENT)); + + if (vectored) + { + int iov_offset = 0; + + size= 0; + ret = rep->re_tx[tx_head].v_ret_buf; + for (i= 0; ire_iovec[0]), + iov_offset += IOVEC_NR * sizeof(rep->re_iovec[0])) + { + n= IOVEC_NR; + if (i+n > count) + n= count-i; + cps = sys_vircopy(re_client, D, ((vir_bytes) mp->DL_ADDR) + iov_offset, + SELF, D, (vir_bytes) rep->re_iovec, + n * sizeof(rep->re_iovec[0])); +if (cps != OK) printf("RTL8139: warning, sys_vircopy failed: %d\n", cps); + for (j= 0, iovp= rep->re_iovec; jiov_size; @@ -1369,18 +1583,10 @@ int vectored; if (OK != sys_umap(re_client, D, iovp->iov_addr, s, &phys_user)) panic("rtl8139","umap_local failed\n", NO_NUM); -#if 0 - cps = sys_abscopy(phys_user, p, s); - if (cps != OK) printf("RTL8139: warning, sys_abscopy failed: %d\n", cps); -#else cps = sys_vircopy(re_client, D, iovp->iov_addr, SELF, D, (vir_bytes) ret, s); if (cps != OK) printf("RTL8139: warning, sys_vircopy failed: %d\n", cps); -#endif size += s; -#if 0 - p += s; -#endif ret += s; } } @@ -1392,19 +1598,10 @@ int vectored; size= mp->DL_COUNT; if (size < ETH_MIN_PACK_SIZE || size > ETH_MAX_PACK_SIZE_TAGGED) panic("rtl8139","invalid packet size", size); -#if 0 - if (OK != sys_umap(re_client, D, (vir_bytes)mp->DL_ADDR, size, &phys_user)) - panic("rtl8139","umap_local failed\n", NO_NUM); - - p= rep->re_tx[tx_head].ret_buf; - cps = sys_abscopy(phys_user, p, size); - if (cps != OK) printf("RTL8139: warning, sys_abscopy failed: %d\n", cps); -#else ret = rep->re_tx[tx_head].v_ret_buf; cps = sys_vircopy(re_client, D, (vir_bytes)mp->DL_ADDR, SELF, D, (vir_bytes) ret, size); if (cps != OK) printf("RTL8139: warning, sys_abscopy failed: %d\n", cps); -#endif } rl_outl(rep->re_base_port, RL_TSD0+tx_head*4, @@ -1446,6 +1643,143 @@ suspend: reply(rep, OK, FALSE); } +/*===========================================================================* + * rl_writev_s * + *===========================================================================*/ +static void rl_writev_s(mp, from_int) +message *mp; +int from_int; +{ + phys_bytes iov_src; + int i, j, n, s, port, count, size; + int tx_head, re_client; + re_t *rep; + iovec_s_t *iovp; + char *ret; + int cps; + int iov_offset = 0; + + port = mp->DL_PORT; + count = mp->DL_COUNT; + if (port < 0 || port >= RE_PORT_NR) + panic("rtl8139","illegal port", port); + rep= &re_table[port]; + re_client= mp->DL_PROC; + rep->re_client= re_client; + + assert(rep->re_mode == REM_ENABLED); + assert(rep->re_flags & REF_ENABLED); + + if (from_int) + { + assert(rep->re_flags & REF_SEND_AVAIL); + rep->re_flags &= ~REF_SEND_AVAIL; + rep->re_send_int= FALSE; + rep->re_tx_alive= TRUE; + } + + tx_head= rep->re_tx_head; + if (rep->re_tx[tx_head].ret_busy) + { + assert(!(rep->re_flags & REF_SEND_AVAIL)); + rep->re_flags |= REF_SEND_AVAIL; + if (rep->re_tx[tx_head].ret_busy) + goto suspend; + + /* Race condition, the interrupt handler may clear re_busy + * before we got a chance to set REF_SEND_AVAIL. Checking + * ret_busy twice should be sufficient. + */ +#if 0 + printf("rl_writev: race detected\n"); +#endif + rep->re_flags &= ~REF_SEND_AVAIL; + rep->re_send_int= FALSE; + } + + assert(!(rep->re_flags & REF_SEND_AVAIL)); + assert(!(rep->re_flags & REF_PACK_SENT)); + + size= 0; + ret = rep->re_tx[tx_head].v_ret_buf; + for (i= 0; ire_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; jiov_size; + if (size + s > ETH_MAX_PACK_SIZE_TAGGED) + { + panic("rtl8139","invalid packet size", + NO_NUM); + } + cps = sys_safecopyfrom(re_client, iovp->iov_grant, 0, + (vir_bytes) ret, s, D); + if (cps != OK) + { + panic(__FILE__, + "rl_writev_s: sys_safecopyfrom failed", + cps); + } + size += s; + ret += s; + } + } + if (size < ETH_MIN_PACK_SIZE) + panic("rtl8139","invalid packet size", size); + + rl_outl(rep->re_base_port, RL_TSD0+tx_head*4, + rep->re_ertxth | size); + rep->re_tx[tx_head].ret_busy= TRUE; + + if (++tx_head == N_TX_BUF) + tx_head= 0; + assert(tx_head < RL_N_TX); + rep->re_tx_head= tx_head; + + rep->re_flags |= REF_PACK_SENT; + + /* If the interrupt handler called, don't send a reply. The reply + * will be sent after all interrupts are handled. + */ + if (from_int) + return; + reply(rep, OK, FALSE); + return; + +suspend: +#if 0 + printf("rl_writev: head %d, tail %d, busy: %d %d %d %d\n", + tx_head, rep->re_tx_tail, + rep->re_tx[0].ret_busy, rep->re_tx[1].ret_busy, + rep->re_tx[2].ret_busy, rep->re_tx[3].ret_busy); + printf("rl_writev: TSD: 0x%x, 0x%x, 0x%x, 0x%x\n", + rl_inl(rep->re_base_port, RL_TSD0+0*4), + rl_inl(rep->re_base_port, RL_TSD0+1*4), + rl_inl(rep->re_base_port, RL_TSD0+2*4), + rl_inl(rep->re_base_port, RL_TSD0+3*4)); +#endif + + if (from_int) + panic("rtl8139","should not be sending\n", NO_NUM); + + rep->re_tx_mess= *mp; + reply(rep, OK, FALSE); +} + /*===========================================================================* * rl_check_ints * *===========================================================================*/ @@ -1503,6 +1837,10 @@ re_t *rep; rl_readv(&rep->re_rx_mess, TRUE /* from int */, TRUE /* vectored */); } + else if (rep->re_rx_mess.m_type == DL_READV_S) + { + rl_readv_s(&rep->re_rx_mess, TRUE /* from int */); + } else { assert(rep->re_rx_mess.m_type == DL_READ); @@ -1898,7 +2236,7 @@ re_t *rep; static void rl_getstat(mp) message *mp; { - int port; + int r, port; eth_stat_t stats; re_t *rep; @@ -1913,8 +2251,38 @@ message *mp; stats= rep->re_stat; - put_userdata(mp->DL_PROC, (vir_bytes) mp->DL_ADDR, - (vir_bytes) sizeof(stats), &stats); + r = sys_datacopy(SELF, (vir_bytes) &stats, mp->DL_PROC, + (vir_bytes) mp->DL_ADDR, sizeof(stats)); + if (r != OK) + panic(__FILE__, "rl_getstat: sys_datacopy failed", r); + reply(rep, OK, FALSE); +} + +/*===========================================================================* + * rl_getstat_s * + *===========================================================================*/ +static void rl_getstat_s(mp) +message *mp; +{ + int r, port; + eth_stat_t stats; + re_t *rep; + + port = mp->DL_PORT; + if (port < 0 || port >= RE_PORT_NR) + panic("rtl8139","illegal port", port); + rep= &re_table[port]; + rep->re_client= mp->DL_PROC; + + assert(rep->re_mode == REM_ENABLED); + assert(rep->re_flags & REF_ENABLED); + + stats= rep->re_stat; + + r = sys_safecopyto(mp->DL_PROC, mp->DL_GRANT, 0, + (vir_bytes) &stats, sizeof(stats), D); + if (r != OK) + panic(__FILE__, "rl_getstat_s: sys_safecopyto failed", r); reply(rep, OK, FALSE); } @@ -1994,20 +2362,6 @@ message *reply_mess; panic("rtl8139","unable to mess_reply", NO_NUM); } -/*===========================================================================* - * put_userdata * - *===========================================================================*/ -static void put_userdata(user_proc, user_addr, count, loc_addr) -int user_proc; -vir_bytes user_addr; -vir_bytes count; -void *loc_addr; -{ - int cps; - cps = sys_datacopy(SELF, (vir_bytes) loc_addr, user_proc, user_addr, count); - if (cps != OK) printf("RTL8139: warning, scopy failed: %d\n", cps); -} - #if 0 static void dump_phy(rep) re_t *rep;