Subversion Repositories HelenOS

Compare Revisions

Ignore whitespace Rev 4191 → Rev 4192

/branches/network/uspace/srv/net/netif/dp8390/dp8390.c
21,7 → 21,7
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Changes:
* 2009 Lukas Medjrech ported to HelenOS
* 2009 Lukas Mejdrech ported to HelenOS
*/
 
/** @addtogroup dp8390
29,12 → 29,17
*/
 
#include <assert.h>
 
#include <errno.h>
 
#include "../../include/byteorder.h"
 
#include "../../structures/packet/packet.h"
#include "../../structures/packet/packet_client.h"
 
#include "../netif.h"
 
#include "dp8390_drv.h"
#include "dp8390_module.h"
#include "dp8390_port.h"
 
/*
52,6 → 57,10
#include "local.h"
#include "dp8390.h"
 
int queue_packet( dpeth_t * dep, packet_t packet );
static void outsb( port_t port, void * buf, size_t size );
static void outsw( port_t port, void * buf, size_t size );
 
//static u16_t eth_ign_proto;
//static char *progname;
 
118,27 → 127,27
//_PROTOTYPE( static void dp8390_stop, (void) );
_PROTOTYPE( static void dp_getblock, (dpeth_t *dep, int page,
size_t offset, size_t size, void *dst) );
//_PROTOTYPE( static void dp_pio8_getblock, (dpeth_t *dep, int page,
// size_t offset, size_t size, void *dst) );
//_PROTOTYPE( static void dp_pio16_getblock, (dpeth_t *dep, int page,
// size_t offset, size_t size, void *dst) );
_PROTOTYPE( static void dp_pio8_getblock, (dpeth_t *dep, int page,
size_t offset, size_t size, void *dst) );
_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, (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, (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, (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) );
146,15 → 155,15
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, (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, (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, (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) );
163,8 → 172,8
//_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, (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) );
172,8 → 181,8
// 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 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,
// vir_bytes buf, size_t size) );
//_PROTOTYPE( static void do_vir_insw, (port_t port, int proc,
258,7 → 267,136
}
}
 
int queue_packet( dpeth_t * dep, packet_t packet ){
packet_t tmp;
 
if( dep->packet_count > 1 ){
if( ! pq_add( pq_previous( dep->packet_queue ), packet, 0, 0 )){
return EINVAL;
}
}else{
tmp = pq_add( dep->packet_queue, packet, 0, 0 );
if( ! tmp ) return EINVAL;
dep->packet_queue = tmp;
}
++ dep->packet_count;
return EBUSY;
}
 
/*===========================================================================*
* based on do_vwrite *
*===========================================================================*/
int do_pwrite( dpeth_t * dep, packet_t packet, int from_int )
{
// int port, count, size;
int 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;
return EOK;
}
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);
return queue_packet( dep, packet );
}
 
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;
return queue_packet( dep, packet );
}
assert(!(dep->de_flags & DEF_PACK_SEND));
 
/* if (vectored)
{
get_userdata(mp->DL_PROC, (vir_bytes) mp->DL_ADDR,
(count > IOVEC_NR ? IOVEC_NR : count) *
sizeof(iovec_t), dep->de_write_iovec.iod_iovec);
dep->de_write_iovec.iod_iovec_s = count;
dep->de_write_iovec.iod_proc_nr = mp->DL_PROC;
dep->de_write_iovec.iod_iovec_addr = (vir_bytes) mp->DL_ADDR;
 
dep->de_tmp_iovec = dep->de_write_iovec;
size = calc_iovec_size(&dep->de_tmp_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 =
mp->DL_COUNT;
dep->de_write_iovec.iod_iovec_s = 1;
dep->de_write_iovec.iod_proc_nr = mp->DL_PROC;
dep->de_write_iovec.iod_iovec_addr = 0;
size= mp->DL_COUNT;
}
*/
size = packet_get_data_length( packet );
dep->de_write_iovec.iod_iovec[0].iov_addr = ( vir_bytes ) packet_get_data( packet );
dep->de_write_iovec.iod_iovec[0].iov_size = size;
dep->de_write_iovec.iod_iovec_s = 1;
dep->de_write_iovec.iod_iovec_addr = NULL;
 
if (size < ETH_MIN_PACK_SIZE || size > ETH_MAX_PACK_SIZE_TAGGED)
{
panic("", "dp8390: invalid packet size", size);
return EINVAL;
}
(dep->de_user2nicf)(dep, &dep->de_write_iovec, 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 EOK;
reply(dep, OK, FALSE);
 
assert(dep->de_mode == DEM_ENABLED);
assert(dep->de_flags & DEF_ENABLED);
return EOK;
}
 
/*===========================================================================*
* dp_init *
*===========================================================================*/
void dp_init(dep)
353,30 → 491,30
dep->de_sendq[i].sq_filled= 0;
dep->de_sendq_head= 0;
dep->de_sendq_tail= 0;
// if (!dep->de_prog_IO)
// {
// dep->de_user2nicf= dp_user2nic;
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;
}
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= 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_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= dp_pio8_nic2user;
// dep->de_nic2userf_s= dp_pio8_nic2user_s;
// dep->de_getblockf= dp_pio8_getblock;
// }
dep->de_getblockf= dp_pio8_getblock;
}
 
/* Set the interrupt handler and policy. Do not automatically
* reenable interrupts. Return the IRQ line number on interrupts.
692,11 → 830,20
static void dp_send(dep)
dpeth_t *dep;
{
/* if (!(dep->de_flags & DEF_SEND_AVAIL))
packet_t packet;
 
if (!(dep->de_flags & DEF_SEND_AVAIL))
return;
 
dep->de_flags &= ~DEF_SEND_AVAIL;
switch(dep->de_sendmsg.m_type)
while( dep->packet_queue ){
packet = dep->packet_queue;
dep->packet_queue = pq_detach( packet );
do_pwrite( dep, packet, TRUE );
netif_pq_release( packet_get_id( packet ));
-- dep->packet_count;
}
/* switch(dep->de_sendmsg.m_type)
{
case DL_WRITE: do_vwrite(&dep->de_sendmsg, TRUE, FALSE); break;
case DL_WRITEV: do_vwrite(&dep->de_sendmsg, TRUE, TRUE); break;
726,6 → 873,47
}
 
/*===========================================================================*
* dp_pio8_getblock *
*===========================================================================*/
static void dp_pio8_getblock(dep, page, offset, size, dst)
dpeth_t *dep;
int page;
size_t offset;
size_t size;
void *dst;
{
offset = page * DP_PAGESIZE + offset;
outb_reg0(dep, DP_RBCR0, size & 0xFF);
outb_reg0(dep, DP_RBCR1, size >> 8);
outb_reg0(dep, DP_RSAR0, offset & 0xFF);
outb_reg0(dep, DP_RSAR1, offset >> 8);
outb_reg0(dep, DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA);
 
insb(dep->de_data_port, dst, size);
}
 
/*===========================================================================*
* dp_pio16_getblock *
*===========================================================================*/
static void dp_pio16_getblock(dep, page, offset, size, dst)
dpeth_t *dep;
int page;
size_t offset;
size_t size;
void *dst;
{
offset = page * DP_PAGESIZE + offset;
outb_reg0(dep, DP_RBCR0, size & 0xFF);
outb_reg0(dep, DP_RBCR1, size >> 8);
outb_reg0(dep, DP_RSAR0, offset & 0xFF);
outb_reg0(dep, DP_RSAR1, offset >> 8);
outb_reg0(dep, DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA);
 
assert (!(size & 1));
insw(dep->de_data_port, dst, size);
}
 
/*===========================================================================*
* dp_pkt2user *
*===========================================================================*/
static int dp_pkt2user(dep, page, length)
733,10 → 921,18
int page, length;
{
int last, count;
packet_t packet;
 
if (!(dep->de_flags & DEF_READING))
return EGENERIC;
 
packet = netif_packet_get_1( length );
if( ! packet ) return ENOMEM;
dep->de_read_iovec.iod_iovec[0].iov_addr = ( vir_bytes ) packet_suffix( packet, length );
dep->de_read_iovec.iod_iovec[0].iov_size = length;
dep->de_read_iovec.iod_iovec_s = 1;
dep->de_read_iovec.iod_iovec_addr = NULL;
 
last = page + (length - 1) / DP_PAGESIZE;
if (last >= dep->de_stoppage)
{
760,10 → 956,231
dep->de_flags |= DEF_PACK_RECV;
dep->de_flags &= ~DEF_READING;
 
if( netif_send_packet( dep, packet ) != EOK ){
netif_pq_release( packet_get_id( packet ));
}
return OK;
}
 
/*===========================================================================*
* dp_user2nic *
*===========================================================================*/
static void dp_user2nic(dep, iovp, offset, nic_addr, count)
dpeth_t *dep;
iovec_dat_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(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_vircopy(iovp->iod_proc_nr, D,
iovp->iod_iovec[i].iov_addr + offset,
SELF, D, vir_hw, bytes);
if (r != OK)
panic("DP8390", "dp_user2nic: sys_vircopy failed", r);
 
count -= bytes;
vir_hw += bytes;
offset += bytes;
}
assert(count == 0);
}
 
/*===========================================================================*
* dp_pio8_user2nic *
*===========================================================================*/
static void dp_pio8_user2nic(dep, iovp, offset, nic_addr, count)
dpeth_t *dep;
iovec_dat_t *iovp;
vir_bytes offset;
int nic_addr;
vir_bytes count;
{
// phys_bytes phys_user;
int bytes, i;
 
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(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;
 
do_vir_outsb(dep->de_data_port, iovp->iod_proc_nr,
iovp->iod_iovec[i].iov_addr + offset, bytes);
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 *
*===========================================================================*/
static void dp_pio16_user2nic(dep, iovp, offset, nic_addr, count)
dpeth_t *dep;
iovec_dat_t *iovp;
vir_bytes offset;
int nic_addr;
vir_bytes count;
{
vir_bytes vir_user;
vir_bytes ecount;
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(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;
vir_user= iovp->iod_iovec[i].iov_addr + offset;
if (odd_byte)
{
r= sys_vircopy(user_proc, D, vir_user,
SELF, D, (vir_bytes)&two_bytes[1], 1);
if (r != OK)
{
panic("DP8390",
"dp_pio16_user2nic: sys_vircopy failed",
r);
}
outw(dep->de_data_port, *(u16_t *)two_bytes);
count--;
offset++;
bytes--;
vir_user++;
odd_byte= 0;
if (!bytes)
continue;
}
ecount= bytes & ~1;
if (ecount != 0)
{
do_vir_outsw(dep->de_data_port, user_proc, vir_user,
ecount);
count -= ecount;
offset += ecount;
bytes -= ecount;
vir_user += ecount;
}
if (bytes)
{
assert(bytes == 1);
r= sys_vircopy(user_proc, D, vir_user,
SELF, D, (vir_bytes)&two_bytes[0], 1);
if (r != OK)
{
panic("DP8390",
"dp_pio16_user2nic: sys_vircopy failed",
r);
}
count--;
offset++;
bytes--;
vir_user++;
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 *
*===========================================================================*/
static void dp_nic2user(dep, nic_addr, iovp, offset, count)
773,7 → 1190,7
vir_bytes offset;
vir_bytes count;
{
/* vir_bytes vir_hw, vir_user;
vir_bytes vir_hw;//, vir_user;
int bytes, i, r;
 
vir_hw = (vir_bytes)dep->de_locmem + nic_addr;
809,11 → 1226,170
offset += bytes;
}
assert(count == 0);
*/
printf("n2u");
}
 
/*===========================================================================*
* dp_pio8_nic2user *
*===========================================================================*/
static void dp_pio8_nic2user(dep, nic_addr, iovp, offset, count)
dpeth_t *dep;
int nic_addr;
iovec_dat_t *iovp;
vir_bytes offset;
vir_bytes count;
{
// phys_bytes phys_user;
int bytes, i;
 
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(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;
 
do_vir_insb(dep->de_data_port, iovp->iod_proc_nr,
iovp->iod_iovec[i].iov_addr + offset, bytes);
count -= bytes;
offset += bytes;
}
assert(count == 0);
}
 
/*===========================================================================*
* dp_pio16_nic2user *
*===========================================================================*/
static void dp_pio16_nic2user(dep, nic_addr, iovp, offset, count)
dpeth_t *dep;
int nic_addr;
iovec_dat_t *iovp;
vir_bytes offset;
vir_bytes count;
{
vir_bytes vir_user;
vir_bytes ecount;
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(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;
vir_user= iovp->iod_iovec[i].iov_addr + offset;
if (odd_byte)
{
r= sys_vircopy(SELF, D, (vir_bytes)&two_bytes[1],
user_proc, D, vir_user, 1);
if (r != OK)
{
panic("DP8390",
"dp_pio16_nic2user: sys_vircopy failed",
r);
}
count--;
offset++;
bytes--;
vir_user++;
odd_byte= 0;
if (!bytes)
continue;
}
ecount= bytes & ~1;
if (ecount != 0)
{
do_vir_insw(dep->de_data_port, user_proc, vir_user,
ecount);
count -= ecount;
offset += ecount;
bytes -= ecount;
vir_user += ecount;
}
if (bytes)
{
assert(bytes == 1);
*(u16_t *)two_bytes= inw(dep->de_data_port);
r= sys_vircopy(SELF, D, (vir_bytes)&two_bytes[0],
user_proc, D, vir_user, 1);
if (r != OK)
{
panic("DP8390",
"dp_pio16_nic2user: sys_vircopy failed",
r);
}
count--;
offset++;
bytes--;
vir_user++;
odd_byte= 1;
}
}
assert(count == 0);
}
 
/*===========================================================================*
* dp_next_iovec *
*===========================================================================*/
static void dp_next_iovec(iovp)
iovec_dat_t *iovp;
{
assert(iovp->iod_iovec_s > IOVEC_NR);
 
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_s > IOVEC_NR ? IOVEC_NR : iovp->iod_iovec_s) *
sizeof(iovec_t), iovp->iod_iovec);
}
 
/*===========================================================================*
* conf_hw *
*===========================================================================*/
static void conf_hw(dep)
859,14 → 1435,16
 
if (dep->de_prog_IO)
{
//#if 0
#if 0
if(debug){
printf(
"map_hw_buffer: programmed I/O, no need to map buffer\n");
}
//#endif
#endif
dep->de_locmem = (char *)-dep->de_ramsize; /* trap errors */
return;
}else{
printf( "map_hw_buffer: no buffer!" );
}
 
// size = dep->de_ramsize + PAGE_SIZE; /* Add PAGE_SIZE for
927,6 → 1505,59
*/ dep->de_flags &= ~(DEF_PACK_SEND | DEF_PACK_RECV);
}
 
/*===========================================================================*
* get_userdata *
*===========================================================================*/
static void get_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(user_proc, D, user_addr,
SELF, D, (vir_bytes)loc_addr, count);
if (r != OK)
panic("DP8390", "get_userdata: sys_vircopy failed", r);
}
 
static void insb(port_t port, void *buf, size_t size)
{
int i;
 
for( i = 0; i < size; ++ i ){
*(( uint8_t * )( buf + i )) = inb( port );
}
}
 
static void insw(port_t port, void *buf, size_t size)
{
int i;
 
for( i = 0; i < size; i += 2 ){
*(( uint16_t * )( buf + i )) = inw( port );
}
}
 
static void outsb(port_t port, void *buf, size_t size)
{
int i;
 
for( i = 0; i < size; ++ i ){
outb( port, *(( uint8_t * )( buf + i )));
}
}
 
static void outsw(port_t port, void *buf, size_t size)
{
int i;
 
for( i = 0; i < size; i += 2 ){
outw( port, *(( uint16_t * )( buf + i )));
}
}
 
/*
* $PchId: dp8390.c,v 1.25 2005/02/10 17:32:07 philip Exp $
*/