📄 dp8390.c
字号:
message *mp;
{
int port;
dpeth_t *dep;
message reply_mess;
port = mp->DL_PORT;
if (port < 0 || port >= DE_PORT_NR)
{
reply_mess.m_type= DL_INIT_REPLY;
reply_mess.m3_i1= ENXIO;
mess_reply(mp, &reply_mess);
return;
}
dep= &de_table[port];
if (dep->de_mode == DEM_DISABLED)
{
/* This is the default, try to (re)locate the device. */
conf_hw(dep);
if (dep->de_mode == DEM_DISABLED)
{
/* Probe failed, or the device is configured off. */
reply_mess.m_type= DL_INIT_REPLY;
reply_mess.m3_i1= ENXIO;
mess_reply(mp, &reply_mess);
return;
}
if (dep->de_mode == DEM_ENABLED)
dp_init(dep);
}
if (dep->de_mode == DEM_SINK)
{
dep->de_address.ea_addr[0] =
dep->de_address.ea_addr[1] =
dep->de_address.ea_addr[2] =
dep->de_address.ea_addr[3] =
dep->de_address.ea_addr[4] =
dep->de_address.ea_addr[5] = 0;
dp_confaddr(dep);
reply_mess.m_type = DL_INIT_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;
mess_reply(mp, &reply_mess);
return;
}
assert(dep->de_mode == DEM_ENABLED);
assert(dep->de_flags & DEF_ENABLED);
dep->de_flags &= ~(DEF_PROMISC | DEF_MULTI | DEF_BROAD);
if (mp->DL_MODE & DL_PROMISC_REQ)
dep->de_flags |= DEF_PROMISC | DEF_MULTI | DEF_BROAD;
if (mp->DL_MODE & DL_MULTI_REQ)
dep->de_flags |= DEF_MULTI;
if (mp->DL_MODE & DL_BROAD_REQ)
dep->de_flags |= DEF_BROAD;
dep->de_client = mp->m_source;
dp_reinit(dep);
reply_mess.m_type = DL_INIT_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;
mess_reply(mp, &reply_mess);
}
/*===========================================================================*
* do_int *
*===========================================================================*/
static void do_int(dep)
dpeth_t *dep;
{
if (dep->de_flags & (DEF_PACK_SEND | DEF_PACK_RECV))
reply(dep, OK, TRUE);
}
/*===========================================================================*
* do_getstat *
*===========================================================================*/
static void do_getstat(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(mp->DL_PROC, (vir_bytes) mp->DL_ADDR,
(vir_bytes) sizeof(dep->de_stat), &dep->de_stat);
reply(dep, OK, FALSE);
}
/*===========================================================================*
* do_stop *
*===========================================================================*/
static void do_stop(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];
if (dep->de_mode == DEM_SINK)
return;
assert(dep->de_mode == DEM_ENABLED);
if (!(dep->de_flags & DEF_ENABLED))
return;
outb_reg0(dep, DP_CR, CR_STP | CR_DM_ABORT);
(dep->de_stopf)(dep);
dep->de_flags= DEF_EMPTY;
}
/*===========================================================================*
* dp_init *
*===========================================================================*/
static void dp_init(dep)
dpeth_t *dep;
{
int dp_rcr_reg;
int i;
/* General initialization */
dep->de_flags = DEF_EMPTY;
(*dep->de_initf)(dep);
dp_confaddr(dep);
/* Initialization of the dp8390 */
outb_reg0(dep, DP_CR, CR_PS_P0 | CR_STP | CR_DM_ABORT);
outb_reg0(dep, DP_IMR, 0);
outb_reg0(dep, DP_PSTART, dep->de_startpage);
outb_reg0(dep, DP_PSTOP, dep->de_stoppage);
outb_reg0(dep, DP_BNRY, dep->de_startpage);
outb_reg0(dep, DP_RCR, RCR_MON);
outb_reg0(dep, DP_TCR, TCR_NORMAL);
if (dep->de_16bit)
outb_reg0(dep, DP_DCR, DCR_WORDWIDE | DCR_8BYTES | DCR_BMS);
else
outb_reg0(dep, DP_DCR, DCR_BYTEWIDE | DCR_8BYTES | DCR_BMS);
outb_reg0(dep, DP_RBCR0, 0);
outb_reg0(dep, DP_RBCR1, 0);
outb_reg0(dep, DP_ISR, 0xFF);
outb_reg0(dep, DP_CR, CR_PS_P1 | CR_DM_ABORT);
outb_reg1(dep, DP_PAR0, dep->de_address.ea_addr[0]);
outb_reg1(dep, DP_PAR1, dep->de_address.ea_addr[1]);
outb_reg1(dep, DP_PAR2, dep->de_address.ea_addr[2]);
outb_reg1(dep, DP_PAR3, dep->de_address.ea_addr[3]);
outb_reg1(dep, DP_PAR4, dep->de_address.ea_addr[4]);
outb_reg1(dep, DP_PAR5, dep->de_address.ea_addr[5]);
outb_reg1(dep, DP_MAR0, 0xff);
outb_reg1(dep, DP_MAR1, 0xff);
outb_reg1(dep, DP_MAR2, 0xff);
outb_reg1(dep, DP_MAR3, 0xff);
outb_reg1(dep, DP_MAR4, 0xff);
outb_reg1(dep, DP_MAR5, 0xff);
outb_reg1(dep, DP_MAR6, 0xff);
outb_reg1(dep, DP_MAR7, 0xff);
outb_reg1(dep, DP_CURR, dep->de_startpage + 1);
outb_reg1(dep, DP_CR, CR_PS_P0 | CR_DM_ABORT);
dp_rcr_reg = 0;
if (dep->de_flags & DEF_PROMISC)
dp_rcr_reg |= RCR_AB | RCR_PRO | RCR_AM;
if (dep->de_flags & DEF_BROAD)
dp_rcr_reg |= RCR_AB;
if (dep->de_flags & DEF_MULTI)
dp_rcr_reg |= RCR_AM;
outb_reg0(dep, DP_RCR, dp_rcr_reg);
inb_reg0(dep, DP_CNTR0); /* reset counters by reading */
inb_reg0(dep, DP_CNTR1);
inb_reg0(dep, DP_CNTR2);
outb_reg0(dep, DP_IMR, IMR_PRXE | IMR_PTXE | IMR_RXEE | IMR_TXEE |
IMR_OVWE | IMR_CNTE);
outb_reg0(dep, DP_CR, CR_STA | CR_DM_ABORT);
/* Finish the initialization. */
dep->de_flags |= DEF_ENABLED;
for (i= 0; i<dep->de_sendq_nr; i++)
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;
dep->de_nic2userf= dp_nic2user;
dep->de_getblockf= dp_getblock;
}
else if (dep->de_16bit)
{
dep->de_user2nicf= dp_pio16_user2nic;
dep->de_nic2userf= dp_pio16_nic2user;
dep->de_getblockf= dp_pio16_getblock;
}
else
{
dep->de_user2nicf= dp_pio8_user2nic;
dep->de_nic2userf= dp_pio8_nic2user;
dep->de_getblockf= dp_pio8_getblock;
}
/* set the interrupt handler */
put_irq_handler(dep->de_irq, dp_handler);
enable_irq(dep->de_irq);
}
/*===========================================================================*
* dp_confaddr *
*===========================================================================*/
static void dp_confaddr(dep)
dpeth_t *dep;
{
int i;
char eakey[16];
static char eafmt[]= "x:x:x:x:x:x";
long v;
/* User defined ethernet address? */
strcpy(eakey, dp_conf[dep-de_table].dpc_envvar);
strcat(eakey, "_EA");
for (i= 0; i < 6; i++)
{
v= dep->de_address.ea_addr[i];
if (env_parse(eakey, eafmt, i, &v, 0x00L, 0xFFL) != EP_SET)
break;
dep->de_address.ea_addr[i]= v;
}
if (i != 0 && i != 6)
{
/* It's all or nothing; force a panic. */
(void) env_parse(eakey, "?", 0, &v, 0L, 0L);
}
}
/*===========================================================================*
* dp_reinit *
*===========================================================================*/
static void dp_reinit(dep)
dpeth_t *dep;
{
int dp_rcr_reg;
outb_reg0(dep, DP_CR, CR_PS_P0);
dp_rcr_reg = 0;
if (dep->de_flags & DEF_PROMISC)
dp_rcr_reg |= RCR_AB | RCR_PRO | RCR_AM;
if (dep->de_flags & DEF_BROAD)
dp_rcr_reg |= RCR_AB;
if (dep->de_flags & DEF_MULTI)
dp_rcr_reg |= RCR_AM;
outb_reg0(dep, DP_RCR, dp_rcr_reg);
}
/*===========================================================================*
* dp_reset *
*===========================================================================*/
static void dp_reset(dep)
dpeth_t *dep;
{
int i;
/* Stop chip */
outb_reg0(dep, DP_CR, CR_STP | CR_DM_ABORT);
outb_reg0(dep, DP_RBCR0, 0);
outb_reg0(dep, DP_RBCR1, 0);
for (i= 0; i < 0x1000 && ((inb_reg0(dep, DP_ISR) & ISR_RST) == 0); i++)
; /* Do nothing */
outb_reg0(dep, DP_TCR, TCR_1EXTERNAL|TCR_OFST);
outb_reg0(dep, DP_CR, CR_STA|CR_DM_ABORT);
outb_reg0(dep, DP_TCR, TCR_NORMAL|TCR_OFST);
/* Acknowledge the ISR_RDC (remote dma) interrupt. */
for (i= 0; i < 0x1000 && ((inb_reg0(dep, DP_ISR) & ISR_RDC) == 0); i++)
; /* Do nothing */
outb_reg0(dep, DP_ISR, inb_reg0(dep, DP_ISR) & ~ISR_RDC);
/* Reset the transmit ring. If we were transmitting a packet, we
* pretend that the packet is processed. Higher layers will
* retransmit if the packet wasn't actually sent.
*/
dep->de_sendq_head= dep->de_sendq_tail= 0;
for (i= 0; i<dep->de_sendq_nr; i++)
dep->de_sendq[i].sq_filled= 0;
dp_send(dep);
dep->de_flags &= ~DEF_STOPPED;
}
/*===========================================================================*
* dp_check_ints *
*===========================================================================*/
static void dp_check_ints(dep)
dpeth_t *dep;
{
int isr, tsr;
int size, sendq_tail;
if (!(dep->de_flags & DEF_ENABLED))
panic("dp8390: got premature interrupt", NO_NUM);
for(;;)
{
isr = inb_reg0(dep, DP_ISR);
if (!isr)
break;
outb_reg0(dep, DP_ISR, isr);
if (isr & (ISR_PTX|ISR_TXE))
{
if (isr & ISR_TXE)
{
#if DEBUG
{ printf("dp8390: got send Error\n"); }
#endif
dep->de_stat.ets_sendErr++;
}
else
{
tsr = inb_reg0(dep, DP_TSR);
if (tsr & TSR_PTX) dep->de_stat.ets_packetT++;
if (tsr & TSR_DFR) dep->de_stat.ets_transDef++;
if (tsr & TSR_COL) dep->de_stat.ets_collision++;
if (tsr & TSR_ABT) dep->de_stat.ets_transAb++;
if (tsr & TSR_CRS) dep->de_stat.ets_carrSense++;
if (tsr & TSR_FU
&& ++dep->de_stat.ets_fifoUnder <= 10)
{
printf("dp8390: fifo underrun\n");
}
if (tsr & TSR_CDH
&& ++dep->de_stat.ets_CDheartbeat <= 10)
{
printf(
"dp8390: CD heart beat failure\n");
}
if (tsr & TSR_OWC) dep->de_stat.ets_OWC++;
}
sendq_tail= dep->de_sendq_tail;
if (!(dep->de_sendq[sendq_tail].sq_filled))
{
/* Software bug? */
assert(!debug);
/* Or hardware bug? */
printf(
"dp8390: transmit interrupt, but not sending\n");
continue;
}
dep->de_sendq[sendq_tail].sq_filled= 0;
if (++sendq_tail == dep->de_sendq_nr)
sendq_tail= 0;
dep->de_sendq_tail= sendq_tail;
if (dep->de_sendq[sendq_tail].sq_filled)
{
size= dep->de_sendq[sendq_tail].sq_size;
outb_reg0(dep, DP_TPSR,
dep->de_sendq[sendq_tail].sq_sendpage);
outb_reg0(dep, DP_TBCR1, size >> 8);
outb_reg0(dep, DP_TBCR0, size & 0xff);
outb_reg0(dep, DP_CR, CR_TXP); /* there is goes.. */
}
if (dep->de_flags & DEF_SEND_AVAIL)
dp_send(dep);
}
if (isr & ISR_PRX)
dp_recv(dep);
if (isr & ISR_RXE) dep->de_stat.ets_recvErr++;
if (isr & ISR_CNT)
{
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);
}
if (isr & ISR_OVW)
{
#if DEBUG
{ printW(); printf("dp8390: got overwrite warning\n"); }
#endif
}
if (isr & ISR_RDC)
{
/* Nothing to do */
}
if (isr & ISR_RST)
{
/* this means we got an interrupt but the ethernet
* chip is shutdown. We set the flag DEF_STOPPED,
* and continue processing arrived packets. When the
* receive buffer is empty, we reset the dp8390.
*/
#if DEBUG
{ printW(); printf("dp8390: NIC stopped\n"); }
#endif
dep->de_flags |= DEF_STOPPED;
break;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -