📄 ne2000.c
字号:
return(TRUE);
}
int ne2000_set_mac_addr (UINT8 *mac_addr)
{
int i;
UINT8 par[ETH_ALEN];
OUTBYTE(REF_REG_ADDR(nic_addr_NE2000_P0_CR), NE2000_CR_RD2 | NE2000_CR_PAGE_1 | NE2000_CR_STA);
/* Write into chip */
for (i = 0; i < ETH_ALEN; ++i) {
#if DATA_BUS_16BIT
OUTBYTE(REF_REG_ADDR(nic_addr_NE2000_P1_PAR0) + i*2, mac_addr[i]);
#else
OUTBYTE(REF_REG_ADDR(nic_addr_NE2000_P1_PAR0) + i, mac_addr[i]);
#endif
}
/* Check it */
for (i = 0; i < ETH_ALEN; ++i){
par[i] = 0;
#if DATA_BUS_16BIT
par[i] = INBYTE(REF_REG_ADDR(nic_addr_NE2000_P1_PAR0) + i*2);
#else
par[i] = INBYTE(REF_REG_ADDR(nic_addr_NE2000_P1_PAR0) + i);
#endif
if (par[i] != mac_addr[i])
return(FALSE);
}
return(TRUE);
}
int ne2000_test_reg(void)
{
int i;
UINT8 par[ETH_ALEN];
UINT8 hw_addr[ETH_ALEN*2];
UINT8 RTL8019id0, RTL8019id1;
PNE2000_SOFTC sc;
sc = off_to_softc();
/* read 8019ID0--1 */
OUTBYTE(REF_REG_ADDR(nic_addr_NE2000_P0_CR), NE2000_CR_RD2 | NE2000_CR_PAGE_0 | NE2000_CR_STA);
RTL8019id0 = INBYTE(REF_REG_ADDR(nic_addr_NE2000_P0_RBCR0));
RTL8019id1 = INBYTE(REF_REG_ADDR(nic_addr_NE2000_P0_RBCR1));
/* read PAR0---PAR5 */
OUTBYTE(REF_REG_ADDR(nic_addr_NE2000_P0_CR), NE2000_CR_RD2 | NE2000_CR_PAGE_1 | NE2000_CR_STA);
for (i = 0; i < ETH_ALEN; ++i){
par[i] = 0;
hw_addr[i] = 0;
#if DATA_BUS_16BIT
par[i] = INBYTE(REF_REG_ADDR(nic_addr_NE2000_P1_PAR0) + i*2);
#else
par[i] = INBYTE(REF_REG_ADDR(nic_addr_NE2000_P1_PAR0) + i);
#endif
}
/* read the ethernet address saved in SRAM */
ne2000_pio_readmem(sc, 0, hw_addr, ETH_ALEN*2);
return i+RTL8019id0+RTL8019id1;
}
/* Reset interface. */
void ne2000_reset(/*PIFACE pi, */PNE2000_SOFTC sc)
{
STATUS previous_int_value;
/* Lock out interrupts. */
previous_int_value = NU_Control_Interrupts(NU_DISABLE_INTERRUPTS);
ne2000_stop(sc);
ne2000_init(sc);
ne2000_test_reg();
NU_Control_Interrupts(previous_int_value);
}
/* Take interface offline. */
void ne2000_stop(PNE2000_SOFTC sc)
{
int n = 5000;
//int n = 100000;//pessia
/* Stop everything on the interface, and select page 0 registers. */
OUTBYTE(REF_REG_ADDR(nic_addr_NE2000_P0_CR), NE2000_CR_RD2 | NE2000_CR_PAGE_0 | NE2000_CR_STP);
/*
* Wait for interface to enter stopped state, but limit # of checks to
* 'n' (about 5ms). It shouldn't even take 5us on modern DS8390's, but
* just in case it's an old one.
*/
while (((INBYTE(REF_REG_ADDR(nic_addr_NE2000_P0_ISR)) & NE2000_ISR_RST) == 0) && --n);
}
/* Initialize device. */
void ne2000_init(PNE2000_SOFTC sc)
{
int i;
STATUS previous_int_value;
UINT8 mcaf[8]; /* multicast address filter */
UINT8 my_hw_addr[6];
tc_memset(my_hw_addr, 2, 6); //set the macaddress is all 2
tc_memset(mcaf, 1, 8); //accept all multicast packet
/*
* Initialize the NIC in the exact order outlined in the NS manual.
* This init procedure is "mandatory"...don't change what or when
* things happen.
*/
/* Lock out interrupts. */
previous_int_value = NU_Control_Interrupts(NU_DISABLE_INTERRUPTS);
/* This variable is used below - don't move this assignment. */
sc->next_packet = (UINT16) (sc->rec_page_start + 1);
/* Set interface for page 0, remote DMA complete, stopped. */
OUTBYTE(REF_REG_ADDR(nic_addr_NE2000_P0_CR), NE2000_CR_RD2 | NE2000_CR_PAGE_0 | NE2000_CR_STP);
if (sc->isa16bit)
{
/*
* Set FIFO threshold to 8, No auto-init Remote DMA, UINT8
* order=80x86, UINT16-wide DMA xfers,
*/
#if RTL8019_LOOPBACK_TEST
OUTBYTE(REF_REG_ADDR(nic_addr_NE2000_P0_DCR), NE2000_DCR_FT1 | NE2000_DCR_WTS | NE2000_DCR_BOS);
#else
/* Take interface out of loopback. */
OUTBYTE(REF_REG_ADDR(nic_addr_NE2000_P0_DCR), NE2000_DCR_FT1 | NE2000_DCR_WTS | NE2000_DCR_LS);
#endif
}
else
{
/* Same as above, but UINT8-wide DMA xfers. */
#if RTL8019_LOOPBACK_TEST
OUTBYTE(REF_REG_ADDR(nic_addr_NE2000_P0_DCR), NE2000_DCR_FT1);
#else
/* Take interface out of loopback. */
OUTBYTE(REF_REG_ADDR(nic_addr_NE2000_P0_DCR), NE2000_DCR_FT1 | NE2000_DCR_LS);
#endif
}
/* Clear remote UINT8 count registers. */
OUTBYTE(REF_REG_ADDR(nic_addr_NE2000_P0_RBCR0), 0);
OUTBYTE(REF_REG_ADDR(nic_addr_NE2000_P0_RBCR1), 0);
/* Tell RCR to do nothing for now. */
OUTBYTE(REF_REG_ADDR(nic_addr_NE2000_P0_RCR), NE2000_RCR_MON);
/* Place NIC in internal loopback mode. */
OUTBYTE(REF_REG_ADDR(nic_addr_NE2000_P0_TCR), NE2000_TCR_LB0);
/* Initialize transmit/receive (ring-buffer) page start. */
OUTBYTE(REF_REG_ADDR(nic_addr_NE2000_P0_TPSR), sc->tx_page_start);
OUTBYTE(REF_REG_ADDR(nic_addr_NE2000_P0_PSTART), sc->rec_page_start);
/* Initialize receiver (ring-buffer) page stop and boundary. */
OUTBYTE(REF_REG_ADDR(nic_addr_NE2000_P0_PSTOP), sc->rec_page_stop);
OUTBYTE(REF_REG_ADDR(nic_addr_NE2000_P0_BNRY), sc->rec_page_start);
/*
* Clear all interrupts. A '1' in each bit position clears the
* corresponding flag.
*/
OUTBYTE(REF_REG_ADDR(nic_addr_NE2000_P0_ISR), 0xff);
/*
* Enable the following interrupts: receive/transmit complete,
* receive/transmit error, and Receiver OverWrite.
*
* Counter overflow and Remote DMA complete are *not* enabled.
*/
OUTBYTE(REF_REG_ADDR(nic_addr_NE2000_P0_IMR), NORMAL_NE2000_INTS);
/* Program command register for page 1. */
OUTBYTE(REF_REG_ADDR(nic_addr_NE2000_P0_CR), NE2000_CR_RD2 | NE2000_CR_PAGE_1 | NE2000_CR_STP);
/* Copy out our station (ethernet) address. */
for (i = 0; i < ETH_ALEN; ++i) {
#if DATA_BUS_16BIT
OUTBYTE(REF_REG_ADDR(nic_addr_NE2000_P1_PAR0) + i*2, my_hw_addr[i]);
#else
OUTBYTE(REF_REG_ADDR(nic_addr_NE2000_P1_PAR0) + i, my_hw_addr[i]);
#endif
}
/* Set current page pointer to next_packet (initialized above). */
OUTBYTE(REF_REG_ADDR(nic_addr_NE2000_P1_CURR), sc->next_packet);
/* Set multicast filter on chip. */
/* If none needed lenmclist will be zero */
//ne2000_getmcaf((PFBYTE) pi->mcast.mclist, pi->mcast.lenmclist,
// mcaf);
OUTBYTE(REF_REG_ADDR(nic_addr_NE2000_P1_MAR0), mcaf[0]);
OUTBYTE(REF_REG_ADDR(nic_addr_NE2000_P1_MAR1), mcaf[1]);
OUTBYTE(REF_REG_ADDR(nic_addr_NE2000_P1_MAR2), mcaf[2]);
OUTBYTE(REF_REG_ADDR(nic_addr_NE2000_P1_MAR3), mcaf[3]);
OUTBYTE(REF_REG_ADDR(nic_addr_NE2000_P1_MAR4), mcaf[4]);
OUTBYTE(REF_REG_ADDR(nic_addr_NE2000_P1_MAR5), mcaf[5]);
OUTBYTE(REF_REG_ADDR(nic_addr_NE2000_P1_MAR6), mcaf[6]);
OUTBYTE(REF_REG_ADDR(nic_addr_NE2000_P1_MAR7), mcaf[7]);
/* ==================== */
/* Program command register for page 0. */
OUTBYTE(REF_REG_ADDR(nic_addr_NE2000_P1_CR), NE2000_CR_RD2 | NE2000_CR_PAGE_0 | NE2000_CR_STP);
/* set broadcast mode */
/* NOTE: promiscous mode is not supported */
/* i = NE2000_RCR_AB; */
/* Accept multicasts and broadcasts */
// i = NE2000_RCR_AB | NE2000_RCR_AM;
i = NE2000_RCR_AB | NE2000_RCR_AM | NE2000_RCR_PRO;
#if RTL8019_LOOPBACK_TEST
i = 0;
#endif
OUTBYTE(REF_REG_ADDR(nic_addr_NE2000_P0_RCR), i);
#if RTL8019_LOOPBACK_TEST
OUTBYTE(REF_REG_ADDR(nic_addr_NE2000_P0_TCR), LOOPBACK_TEST_MODE);
#else
/* Take interface out of loopback. */
OUTBYTE(REF_REG_ADDR(nic_addr_NE2000_P0_TCR), 0);
#endif
/* Fire up the interface. */
OUTBYTE(REF_REG_ADDR(nic_addr_NE2000_P0_CR), NE2000_CR_RD2 | NE2000_CR_PAGE_0 | NE2000_CR_STA);
NU_Control_Interrupts(previous_int_value);
}
/* ******************************************************************** */
/* INTERRUPT routines. */
/* ******************************************************************** */
void ENT_INT_RTL8019AS( void )
{
ent_int();
mask_irq(15);
*((volatile unsigned long*)PORTH_INTRCLR) = 0x6fUL;
ne2000_interrupt(0);
unmask_irq(15);
ret_int();
}
void Irq_8019_Handler(void)
{
UINT8 isr;
mask_irq(10);
OUTBYTE(REF_REG_ADDR(nic_addr_NE2000_P0_CR), NE2000_CR_RD2 | NE2000_CR_PAGE_0 | NE2000_CR_STA);
/* get interrupt status register */
isr = INBYTE(REF_REG_ADDR(nic_addr_NE2000_P0_ISR));
if ( isr )
ne2000_interrupt(0);
unmask_irq(10);
}
/* handle interrupts - this is the interrupt routine */
void ne2000_interrupt(int minor_no) /*__fn__*/
{
PNE2000_SOFTC sc;
UINT8 isr;
int error;
sc = off_to_softc();
if (!sc)
return;
//ks_enable();
/* Set NIC to page 0 registers. */
OUTBYTE(REF_REG_ADDR(nic_addr_NE2000_P0_CR), NE2000_CR_RD2 | NE2000_CR_PAGE_0 | NE2000_CR_STA);
/* get interrupt status register */
isr = INBYTE(REF_REG_ADDR(nic_addr_NE2000_P0_ISR));
/* Loop until there are no more new interrupts. */
while (isr)
{
/*
* Reset all the bits in the interrupt status register that we
* are 'acknowledging' by writing a '1' to each bit position
* that was set. (Writing a '1' *clears* the bit.)
*/
OUTBYTE(REF_REG_ADDR(nic_addr_NE2000_P0_ISR), isr);
/* ****** */
/*
* Handle transmitter interrupts. Handle these first because
* the receiver will reset the board under some conditions.
*/
if (isr & (NE2000_ISR_PTX | NE2000_ISR_TXE)) /* pkt xmit or xmit error */
{
int collisions = INBYTE(REF_REG_ADDR(nic_addr_NE2000_P0_NCR)) & 0x0f;
/*
* Check for transmit error. If a TX completed with an
* error, we end up throwing the packet away. Really
* the only error that is possible is excessive
* collisions, and in this case it is best to allow the
* automatic mechanisms of TCP to backoff the flow. Of
* course, with UDP we're screwed, but this is expected
* when a network is heavily loaded.
*/
error = INBYTE(REF_REG_ADDR(nic_addr_NE2000_P0_TSR));
if ( (isr & NE2000_ISR_TXE) ||
(error & (NE2000_TSR_CDH | NE2000_TSR_CRS)) )
{
/* if transmit aborted (NE2000_TSR_ABT) due to excessive collisions, */
/* if collisions is 0 it really is 16 (excessive collisions) */
if (error & NE2000_TSR_ABT)
{
sc->stats.collision_errors++;
}
/* Update output errors counter. */
sc->stats.errors_out++;
//pi->xmit_status = ENETDOWN;
}
else /* no transmit error */
{
/* check for out of window collsions */
if (INBYTE(REF_REG_ADDR(nic_addr_NE2000_P0_TSR)) & NE2000_TSR_OWC)
sc->stats.owc_collision++;
if (collisions == 1)
sc->stats.one_collision++;
else if (collisions >= 1)
sc->stats.multiple_collisions++;
if (INBYTE(REF_REG_ADDR(nic_addr_NE2000_P0_TSR)) & NE2000_TSR_CRS)
sc->stats.tx_carrier_errors++;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -