Line 267... |
Line 267... |
}
|
}
|
|
|
/* stay in this state if (TXEN && !READY) */
|
/* stay in this state if (TXEN && !READY) */
|
break;
|
break;
|
case ETH_TXSTATE_READFIFO:
|
case ETH_TXSTATE_READFIFO:
|
if (eth->tx.bytes_sent < eth->tx.packet_length)
|
//if (eth->tx.bytes_sent < eth->tx.packet_length)
|
|
while (eth->tx.bytes_sent < eth->tx.packet_length)
|
{
|
{
|
read_word =
|
read_word =
|
eval_direct32 (eth->tx.bytes_sent + eth->tx.bd_addr, 0, 0);
|
eval_direct32 (eth->tx.bytes_sent + eth->tx.bd_addr, 0, 0);
|
eth->tx_buff[eth->tx.bytes_sent] =
|
eth->tx_buff[eth->tx.bytes_sent] =
|
(unsigned char) (read_word >> 24);
|
(unsigned char) (read_word >> 24);
|
Line 280... |
Line 281... |
eth->tx_buff[eth->tx.bytes_sent + 2] =
|
eth->tx_buff[eth->tx.bytes_sent + 2] =
|
(unsigned char) (read_word >> 8);
|
(unsigned char) (read_word >> 8);
|
eth->tx_buff[eth->tx.bytes_sent + 3] = (unsigned char) (read_word);
|
eth->tx_buff[eth->tx.bytes_sent + 3] = (unsigned char) (read_word);
|
eth->tx.bytes_sent += 4;
|
eth->tx.bytes_sent += 4;
|
}
|
}
|
else
|
//else
|
{
|
// {
|
eth->tx.state = ETH_TXSTATE_TRANSMIT;
|
eth->tx.state = ETH_TXSTATE_TRANSMIT;
|
}
|
// }
|
break;
|
break;
|
case ETH_TXSTATE_TRANSMIT:
|
case ETH_TXSTATE_TRANSMIT:
|
/* send packet */
|
/* send packet */
|
switch (eth->rtx_type)
|
switch (eth->rtx_type)
|
{
|
{
|
case ETH_RTX_FILE:
|
case ETH_RTX_FILE:
|
nwritten = write (eth->txfd, eth->tx_buff, eth->tx.packet_length);
|
nwritten = write (eth->txfd, eth->tx_buff, eth->tx.packet_length);
|
break;
|
break;
|
case ETH_RTX_TAP:
|
case ETH_RTX_TAP:
|
printf ("Writing TAP\n");
|
/*
|
|
printf ("Writing TAP\n");
|
|
|
|
printf("packet %d bytes:",(int) eth->tx.packet_length );
|
|
int j; for (j=0;j<eth->tx.packet_length;j++)
|
|
{ if (j%16==0)printf("\n");
|
|
else if (j%8==0) printf(" ");
|
|
printf("%.2x ", eth->tx_buff[j]);
|
|
}
|
|
printf("\nend packet:\n");
|
|
*/
|
nwritten = write (eth->rtx_fd, eth->tx_buff, eth->tx.packet_length);
|
nwritten = write (eth->rtx_fd, eth->tx_buff, eth->tx.packet_length);
|
break;
|
break;
|
}
|
}
|
|
|
/* set BD status */
|
/* set BD status */
|
Line 324... |
Line 335... |
if (TEST_FLAG (eth->regs.int_mask, ETH_INT_MASK, TXE_M) ||
|
if (TEST_FLAG (eth->regs.int_mask, ETH_INT_MASK, TXE_M) ||
|
TEST_FLAG (eth->regs.int_mask, ETH_INT_MASK, TXB_M))
|
TEST_FLAG (eth->regs.int_mask, ETH_INT_MASK, TXB_M))
|
{
|
{
|
if (TEST_FLAG (eth->tx.bd, ETH_TX_BD, IRQ))
|
if (TEST_FLAG (eth->tx.bd, ETH_TX_BD, IRQ))
|
{
|
{
|
printf ("ETH_TXSTATE_TRANSMIT interrupt\n");
|
//printf ("ETH_TXSTATE_TRANSMIT interrupt\n");
|
report_interrupt (eth->mac_int);
|
report_interrupt (eth->mac_int);
|
}
|
}
|
}
|
}
|
|
|
/* advance to next BD */
|
/* advance to next BD */
|
Line 402... |
Line 413... |
{
|
{
|
eth->rx.fd = eth->rxfd;
|
eth->rx.fd = eth->rxfd;
|
eth->rx.offset = 0;
|
eth->rx.offset = 0;
|
}
|
}
|
eth->rx.state = ETH_RXSTATE_RECV;
|
eth->rx.state = ETH_RXSTATE_RECV;
|
|
//printf("rx_clk: going to ETH_RXSTATE_RECV\n");
|
}
|
}
|
else if (!TEST_FLAG (eth->regs.moder, ETH_MODER, RXEN))
|
else if (!TEST_FLAG (eth->regs.moder, ETH_MODER, RXEN))
|
{
|
{
|
eth->rx.state = ETH_RXSTATE_IDLE;
|
eth->rx.state = ETH_RXSTATE_IDLE;
|
}
|
}
|
Line 424... |
Line 436... |
fprintf (stderr, "Warning: Poll of WAIT4BD failed %s: ignored.\n",
|
fprintf (stderr, "Warning: Poll of WAIT4BD failed %s: ignored.\n",
|
strerror (errno));
|
strerror (errno));
|
}
|
}
|
else if ((n > 0) && ((fds[0].revents & POLLIN) == POLLIN))
|
else if ((n > 0) && ((fds[0].revents & POLLIN) == POLLIN))
|
{
|
{
|
printf ("Reading TAP\n");
|
printf ("Reading TAP and all BDs full = BUSY\n");
|
nread = read (eth->rtx_fd, eth->rx_buff, ETH_MAXPL);
|
nread = read (eth->rtx_fd, eth->rx_buff, ETH_MAXPL);
|
|
|
if (nread < 0)
|
if (nread < 0)
|
{
|
{
|
fprintf (stderr,
|
fprintf (stderr,
|
Line 439... |
Line 451... |
{
|
{
|
SET_FLAG (eth->regs.int_source, ETH_INT_SOURCE, BUSY);
|
SET_FLAG (eth->regs.int_source, ETH_INT_SOURCE, BUSY);
|
|
|
if (TEST_FLAG (eth->regs.int_mask, ETH_INT_MASK, BUSY_M))
|
if (TEST_FLAG (eth->regs.int_mask, ETH_INT_MASK, BUSY_M))
|
{
|
{
|
printf ("ETH_RXSTATE_WAIT4BD interrupt\n");
|
printf ("ETH_RXSTATE_WAIT4BD BUSY interrupt\n");
|
report_interrupt (eth->mac_int);
|
report_interrupt (eth->mac_int);
|
}
|
}
|
}
|
}
|
}
|
}
|
}
|
}
|
Line 507... |
Line 519... |
"Warning: Poll of RXTATE_RECV failed %s: ignored.\n",
|
"Warning: Poll of RXTATE_RECV failed %s: ignored.\n",
|
strerror (errno));
|
strerror (errno));
|
}
|
}
|
else if ((n > 0) && ((fds[0].revents & POLLIN) == POLLIN))
|
else if ((n > 0) && ((fds[0].revents & POLLIN) == POLLIN))
|
{
|
{
|
printf ("Reading TAP\n");
|
//printf ("Reading TAP. ");
|
nread = read (eth->rtx_fd, eth->rx_buff, ETH_MAXPL);
|
nread = read (eth->rtx_fd, eth->rx_buff, ETH_MAXPL);
|
|
//printf ("%d bytes read.\n",(int) nread);
|
if (nread < 0)
|
if (nread < 0)
|
{
|
{
|
fprintf (stderr,
|
fprintf (stderr,
|
"Warning: Read of RXTATE_RECV failed %s: ignored\n",
|
"Warning: Read of RXTATE_RECV failed %s: ignored\n",
|
strerror (errno));
|
strerror (errno));
|
}
|
|
else if (nread > 0)
|
|
{
|
|
SET_FLAG (eth->regs.int_source, ETH_INT_SOURCE, BUSY);
|
|
|
|
if (TEST_FLAG (eth->regs.int_mask, ETH_INT_MASK, BUSY_M))
|
if (TEST_FLAG (eth->regs.int_mask, ETH_INT_MASK, RXE_M))
|
{
|
{
|
printf ("ETH_RXTATE_RECV interrupt\n");
|
SET_FLAG (eth->regs.int_source, ETH_INT_SOURCE, RXE);
|
|
printf ("ETH_RXTATE_RECV RXE interrupt\n");
|
report_interrupt (eth->mac_int);
|
report_interrupt (eth->mac_int);
|
}
|
}
|
}
|
}
|
|
|
}
|
}
|
|
|
/* If not promiscouos mode, check the destination address */
|
/* If not promiscouos mode, check the destination address */
|
if (!TEST_FLAG (eth->regs.moder, ETH_MODER, PRO))
|
if (!TEST_FLAG (eth->regs.moder, ETH_MODER, PRO) && nread)
|
{
|
{
|
if (TEST_FLAG (eth->regs.moder, ETH_MODER, IAM)
|
if (TEST_FLAG (eth->regs.moder, ETH_MODER, IAM)
|
&& (eth->rx_buff[0] & 1))
|
&& (eth->rx_buff[0] & 1))
|
{
|
{
|
/* Nothing for now */
|
/* Nothing for now */
|
}
|
}
|
|
|
if (eth->mac_address[5] != eth->rx_buff[0] ||
|
|
eth->mac_address[4] != eth->rx_buff[1] ||
|
if (((eth->mac_address[5] != eth->rx_buff[0]) &&
|
eth->mac_address[3] != eth->rx_buff[2] ||
|
(eth->rx_buff[5] != 0xff) ) ||
|
eth->mac_address[2] != eth->rx_buff[3] ||
|
((eth->mac_address[4] != eth->rx_buff[1]) &&
|
eth->mac_address[1] != eth->rx_buff[4] ||
|
(eth->rx_buff[4] != 0xff) ) ||
|
eth->mac_address[0] != eth->rx_buff[5])
|
((eth->mac_address[3] != eth->rx_buff[2]) &&
|
|
(eth->rx_buff[3] != 0xff) ) ||
|
|
((eth->mac_address[2] != eth->rx_buff[3]) &&
|
|
(eth->rx_buff[2] != 0xff) ) ||
|
|
((eth->mac_address[1] != eth->rx_buff[4]) &&
|
|
(eth->rx_buff[1] != 0xff) ) ||
|
|
((eth->mac_address[0] != eth->rx_buff[5]) &&
|
|
(eth->rx_buff[0] != 0xff)))
|
|
|
|
{
|
|
/*
|
|
printf("ETH_RXSTATE dropping packet for %.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n",
|
|
eth->rx_buff[0],
|
|
eth->rx_buff[1],
|
|
eth->rx_buff[2],
|
|
eth->rx_buff[3],
|
|
eth->rx_buff[4],
|
|
eth->rx_buff[5]);
|
|
*/
|
break;
|
break;
|
}
|
}
|
|
}
|
|
|
eth->rx.packet_length = nread;
|
eth->rx.packet_length = nread;
|
eth->rx.bytes_left = nread;
|
eth->rx.bytes_left = nread;
|
eth->rx.bytes_read = 0;
|
eth->rx.bytes_read = 0;
|
|
|
|
if (nread)
|
eth->rx.state = ETH_RXSTATE_WRITEFIFO;
|
eth->rx.state = ETH_RXSTATE_WRITEFIFO;
|
|
|
break;
|
break;
|
case ETH_RTX_VAPI:
|
case ETH_RTX_VAPI:
|
break;
|
break;
|
}
|
}
|
break;
|
break;
|
|
|
case ETH_RXSTATE_WRITEFIFO:
|
case ETH_RXSTATE_WRITEFIFO:
|
|
//printf("ETH_RXSTATE_WRITEFIFO: writing to %d bytes 0x%.8x\n",(int)eth->rx.bytes_left, (unsigned int)eth->rx.bd_addr);
|
|
if (eth->rx.bytes_left > 0){
|
|
while((int) eth->rx.bytes_left){
|
send_word = ((unsigned long) eth->rx_buff[eth->rx.bytes_read] << 24) |
|
send_word = ((unsigned long) eth->rx_buff[eth->rx.bytes_read] << 24) |
|
((unsigned long) eth->rx_buff[eth->rx.bytes_read + 1] << 16) |
|
((unsigned long) eth->rx_buff[eth->rx.bytes_read + 1] << 16) |
|
((unsigned long) eth->rx_buff[eth->rx.bytes_read + 2] << 8) |
|
((unsigned long) eth->rx_buff[eth->rx.bytes_read + 2] << 8) |
|
((unsigned long) eth->rx_buff[eth->rx.bytes_read + 3]);
|
((unsigned long) eth->rx_buff[eth->rx.bytes_read + 3]);
|
set_direct32 (eth->rx.bd_addr + eth->rx.bytes_read, send_word, 0, 0);
|
set_direct32 (eth->rx.bd_addr + eth->rx.bytes_read, send_word, 0, 0);
|
/* update counters */
|
/* update counters */
|
|
if (eth->rx.bytes_left >= 4)
|
|
{
|
eth->rx.bytes_left -= 4;
|
eth->rx.bytes_left -= 4;
|
eth->rx.bytes_read += 4;
|
eth->rx.bytes_read += 4;
|
|
}
|
|
else
|
|
{
|
|
eth->rx.bytes_read += eth->rx.bytes_left;
|
|
eth->rx.bytes_left = 0;
|
|
}
|
|
}
|
|
|
|
}
|
|
//printf("ETH_RXSTATE_WRITEFIFO: bytes read: 0x%.8x\n",(unsigned int)eth->rx.bytes_read);
|
if (eth->rx.bytes_left <= 0)
|
if (eth->rx.bytes_left <= 0)
|
{
|
{
|
/* Write result to bd */
|
/* Write result to bd */
|
SET_FIELD (eth->rx.bd, ETH_RX_BD, LENGTH, eth->rx.packet_length);
|
SET_FIELD (eth->rx.bd, ETH_RX_BD, LENGTH, eth->rx.packet_length+4);
|
CLEAR_FLAG (eth->rx.bd, ETH_RX_BD, READY);
|
CLEAR_FLAG (eth->rx.bd, ETH_RX_BD, READY);
|
SET_FLAG (eth->regs.int_source, ETH_INT_SOURCE, RXB);
|
SET_FLAG (eth->regs.int_source, ETH_INT_SOURCE, RXB);
|
|
/*
|
if (eth->rx.packet_length <
|
if (eth->rx.packet_length <
|
(GET_FIELD (eth->regs.packetlen, ETH_PACKETLEN, MINFL) - 4))
|
(GET_FIELD (eth->regs.packetlen, ETH_PACKETLEN, MINFL) - 4))
|
SET_FLAG (eth->rx.bd, ETH_RX_BD, TOOSHORT);
|
SET_FLAG (eth->rx.bd, ETH_RX_BD, TOOSHORT);
|
if (eth->rx.packet_length >
|
if (eth->rx.packet_length >
|
GET_FIELD (eth->regs.packetlen, ETH_PACKETLEN, MAXFL))
|
GET_FIELD (eth->regs.packetlen, ETH_PACKETLEN, MAXFL))
|
SET_FLAG (eth->rx.bd, ETH_RX_BD, TOOBIG);
|
SET_FLAG (eth->rx.bd, ETH_RX_BD, TOOBIG);
|
|
*/
|
eth->regs.bd_ram[eth->rx.bd_index] = eth->rx.bd;
|
eth->regs.bd_ram[eth->rx.bd_index] = eth->rx.bd;
|
|
|
/* advance to next BD */
|
/* advance to next BD */
|
if (TEST_FLAG (eth->rx.bd, ETH_RX_BD, WRAP)
|
if (TEST_FLAG (eth->rx.bd, ETH_RX_BD, WRAP)
|
|| eth->rx.bd_index >= ETH_BD_COUNT)
|
|| eth->rx.bd_index >= ETH_BD_COUNT)
|
Line 594... |
Line 638... |
eth->rx.bd_index += 2;
|
eth->rx.bd_index += 2;
|
|
|
if ((TEST_FLAG (eth->regs.int_mask, ETH_INT_MASK, RXB_M)) &&
|
if ((TEST_FLAG (eth->regs.int_mask, ETH_INT_MASK, RXB_M)) &&
|
(TEST_FLAG (eth->rx.bd, ETH_RX_BD, IRQ)))
|
(TEST_FLAG (eth->rx.bd, ETH_RX_BD, IRQ)))
|
{
|
{
|
printf ("ETH_RXSTATE_WRITEFIFO interrupt\n");
|
//printf ("ETH_RXSTATE_WRITEFIFO interrupt\n");
|
report_interrupt (eth->mac_int);
|
report_interrupt (eth->mac_int);
|
}
|
}
|
|
|
/* ready to receive next packet */
|
/* ready to receive next packet */
|
eth->rx.state = ETH_RXSTATE_IDLE;
|
eth->rx.state = ETH_RXSTATE_IDLE;
|
Line 743... |
Line 787... |
|
|
/* Turn it into a specific TAP device. If we haven't specified a
|
/* Turn it into a specific TAP device. If we haven't specified a
|
specific (persistent) device, one will be created, but that requires
|
specific (persistent) device, one will be created, but that requires
|
superuser, or at least CAP_NET_ADMIN capabilities. */
|
superuser, or at least CAP_NET_ADMIN capabilities. */
|
memset (&ifr, 0, sizeof(ifr));
|
memset (&ifr, 0, sizeof(ifr));
|
ifr.ifr_flags = IFF_TAP;
|
ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
|
strncpy (ifr.ifr_name, eth->tap_dev, IFNAMSIZ);
|
strncpy (ifr.ifr_name, eth->tap_dev, IFNAMSIZ);
|
|
|
if (ioctl (eth->rtx_fd, TUNSETIFF, (void *) &ifr) < 0)
|
if (ioctl (eth->rtx_fd, TUNSETIFF, (void *) &ifr) < 0)
|
{
|
{
|
fprintf (stderr, "Warning: Failed to set TAP device: %s\n",
|
fprintf (stderr, "Warning: Failed to set TAP device: %s\n",
|
Line 777... |
Line 821... |
|
|
/* Clear TX/RX status and initialize buffer descriptor index. */
|
/* Clear TX/RX status and initialize buffer descriptor index. */
|
memset (&(eth->tx), 0, sizeof (eth->tx));
|
memset (&(eth->tx), 0, sizeof (eth->tx));
|
memset (&(eth->rx), 0, sizeof (eth->rx));
|
memset (&(eth->rx), 0, sizeof (eth->rx));
|
|
|
|
/* Reset TX/RX BD indexes */
|
|
eth->tx.bd_index = 0;
|
eth->rx.bd_index = eth->regs.tx_bd_num << 1;
|
eth->rx.bd_index = eth->regs.tx_bd_num << 1;
|
|
|
/* Initialize VAPI */
|
/* Initialize VAPI */
|
if (eth->base_vapi_id)
|
if (eth->base_vapi_id)
|
{
|
{
|
Line 906... |
Line 952... |
{
|
{
|
case ETH_MODER:
|
case ETH_MODER:
|
|
|
if (!TEST_FLAG (eth->regs.moder, ETH_MODER, RXEN) &&
|
if (!TEST_FLAG (eth->regs.moder, ETH_MODER, RXEN) &&
|
TEST_FLAG (value, ETH_MODER, RXEN))
|
TEST_FLAG (value, ETH_MODER, RXEN))
|
|
{
|
|
// Reset RX BD index
|
|
eth->rx.bd_index = eth->regs.tx_bd_num << 1;
|
SCHED_ADD (eth_controller_rx_clock, dat, 1);
|
SCHED_ADD (eth_controller_rx_clock, dat, 1);
|
|
}
|
else if (!TEST_FLAG (value, ETH_MODER, RXEN))
|
else if (!TEST_FLAG (value, ETH_MODER, RXEN))
|
SCHED_FIND_REMOVE (eth_controller_rx_clock, dat);
|
SCHED_FIND_REMOVE (eth_controller_rx_clock, dat);
|
|
|
if (!TEST_FLAG (eth->regs.moder, ETH_MODER, TXEN) &&
|
if (!TEST_FLAG (eth->regs.moder, ETH_MODER, TXEN) &&
|
TEST_FLAG (value, ETH_MODER, TXEN))
|
TEST_FLAG (value, ETH_MODER, TXEN))
|
|
{
|
|
eth->tx.bd_index = 0;
|
SCHED_ADD (eth_controller_tx_clock, dat, 1);
|
SCHED_ADD (eth_controller_tx_clock, dat, 1);
|
|
}
|
else if (!TEST_FLAG (value, ETH_MODER, TXEN))
|
else if (!TEST_FLAG (value, ETH_MODER, TXEN))
|
SCHED_FIND_REMOVE (eth_controller_tx_clock, dat);
|
SCHED_FIND_REMOVE (eth_controller_tx_clock, dat);
|
|
|
eth->regs.moder = value;
|
eth->regs.moder = value;
|
|
|
if (TEST_FLAG (value, ETH_MODER, RST))
|
if (TEST_FLAG (value, ETH_MODER, RST))
|
eth_reset (dat);
|
eth_reset (dat);
|
return;
|
return;
|
case ETH_INT_SOURCE:
|
case ETH_INT_SOURCE:
|
if (!(eth->regs.int_source & ~value) && eth->regs.int_source)
|
// Clear interrupt if all interrupt sources have been dealt with
|
clear_interrupt (eth->mac_int);
|
|
eth->regs.int_source &= ~value;
|
eth->regs.int_source &= ~value;
|
|
if (!eth->regs.int_source)
|
|
clear_interrupt (eth->mac_int);
|
|
|
return;
|
return;
|
case ETH_INT_MASK:
|
case ETH_INT_MASK:
|
eth->regs.int_mask = value;
|
eth->regs.int_mask = value;
|
|
if (eth->regs.int_source & eth->regs.int_mask)
|
|
report_interrupt (eth->mac_int);
|
|
else
|
|
clear_interrupt (eth->mac_int);
|
return;
|
return;
|
case ETH_IPGT:
|
case ETH_IPGT:
|
eth->regs.ipgt = value;
|
eth->regs.ipgt = value;
|
return;
|
return;
|
case ETH_IPGR1:
|
case ETH_IPGR1:
|
Line 1347... |
Line 1406... |
break;
|
break;
|
case MII_PHYSID2:
|
case MII_PHYSID2:
|
eth->regs.miirx_data = 0x1613; /* Micrel PHYID */
|
eth->regs.miirx_data = 0x1613; /* Micrel PHYID */
|
break;
|
break;
|
case MII_ADVERTISE:
|
case MII_ADVERTISE:
|
eth->regs.miirx_data = 0;
|
eth->regs.miirx_data = ADVERTISE_FULL;
|
break;
|
break;
|
case MII_LPA:
|
case MII_LPA:
|
eth->regs.miirx_data = LPA_DUPLEX | LPA_100;
|
eth->regs.miirx_data = LPA_DUPLEX | LPA_100;
|
break;
|
break;
|
case MII_EXPANSION:
|
case MII_EXPANSION:
|
Line 1456... |
Line 1515... |
new->dma = 0;
|
new->dma = 0;
|
new->mac_int = 0;
|
new->mac_int = 0;
|
new->rtx_type = ETH_RTX_FILE;
|
new->rtx_type = ETH_RTX_FILE;
|
new->rx_channel = 0;
|
new->rx_channel = 0;
|
new->tx_channel = 0;
|
new->tx_channel = 0;
|
|
new->rtx_fd = 0;
|
new->rxfile = strdup ("eth_rx");
|
new->rxfile = strdup ("eth_rx");
|
new->txfile = strdup ("eth_tx");
|
new->txfile = strdup ("eth_tx");
|
new->tap_dev = strdup ("");
|
new->tap_dev = strdup ("");
|
new->base_vapi_id = 0;
|
new->base_vapi_id = 0;
|
new->phy_addr = 0;
|
new->phy_addr = 0;
|