📄 adam.c
字号:
// move onto the next
eth->tx_desc_done = *(volatile ULONG *)(eth->tx_desc_done + 0x00);
}
else return 1; // busy
}
return 0;
}
int eth_receive(type_eth_descriptors *eth, rx_callback_proc rx_callback, void *context)
{
int err;
int i;
ULONG next;
ULONG stat;
ULONG ctl;
int buffer_count;
ULONG rptr;
int rlen;
int rlen1;
ULONG rbuf1;
int rerror;
readtimeus();
err = 0;
// check the rx Q
if (!((*(volatile ULONG *)(eth->rx_fda_desc+0x0c)) & 0x80000000))
{
// if q nearly full - do a pause ...
// how do we know how far the controller has got ???
// .. just check the own bit of the rx_fda_desc at the required threshold
// this is a bad way - just chase up the fda descriptor list, counting how far
// behind we are - if the q is nearly full do a pause.
ULONG own;
int count;
ULONG fda;
// race up the fda q
fda = eth->rx_fda_desc;
count = 0;
own = 0;
while(!own && (count < 0x200))
{
own = (*(volatile ULONG *)(fda+0x0c)) & 0x80000000;
fda = *(volatile ULONG *)(fda+0x00);
count++;
}
// if not yet freed, then we're getting full
// we have ~0x200 descs
if ((count > 0x1c0))
{
eth_pause(eth, 16000); // 200 = ~ 1ms
}
next = *(volatile ULONG *)(eth->rx_fda_desc+0x00);
ctl = (*(volatile ULONG *)(eth->rx_fda_desc+0x0c) >> 16) & 0x1f;
// if the rx packet is spread across several buffers
buffer_count = ((*(volatile ULONG *)(eth->rx_fda_desc+0x0c)) >> 16) & 0x1f;
if (buffer_count == 1)
{
rptr = (*(volatile ULONG *)(eth->rx_fda_desc+0x10+(0*0x8)));
rlen = (*(volatile ULONG *)(eth->rx_fda_desc+0x14+(0*0x8))) & 0xffff;
}
else
{
// if the rx packet its fragmented
// copy the rxpacket into a single buffer
rbuf1 = (ULONG)rbuf;
rlen = 0;
for (i=0; i<buffer_count; i++)
{
rptr = (*(volatile ULONG *)(eth->rx_fda_desc+0x10+(i*0x8)));
rlen1 = (*(volatile ULONG *)(eth->rx_fda_desc+0x14+(i*0x8))) & 0xffff;
memcpy((UCHAR *)rbuf1, (UCHAR *)rptr, rlen1);
rbuf1 += rlen1;
rlen += rlen1;
}
rptr = (ULONG)rbuf;
}
// this is a good place to check for errors
// any 'late' errors, such as fcs, overflow will already have transferred to
// memory, so should be discarded, and freed
stat = *(volatile ULONG *)(eth->rx_fda_desc+0x08);
rerror = 0;
if (stat & 0x0f10)
{
printf("\n*** rx error ***\n");
printf("MAC_RX_STAT = %08lx\n", stat);
if (stat & 0x0010) printf("*** lenerr ***\n");
if (stat & 0x0100) printf("*** alignment error ***\n");
if (stat & 0x0200) printf("*** crc error ***\n");
if (stat & 0x0400) printf("*** overflow ***\n");
if (stat & 0x0800) printf("*** long error ***\n");
rerror = 1;
}
if (eth->debug & 0x01) printf("R");
if (eth->debug & 0x02) printf("R: rbuf = 0x%08lx, rlen = 0x%x, eth->rx_fda_desc = 0x%08lx\n",(ULONG)rptr, rlen, eth->rx_fda_desc);
if (eth->debug & 0x04) dump_pkt((pkt_type *)rptr, rlen);
if (eth->debug & 0x08) decode_pkt((pkt_type *)rptr, rlen);
// this can be the original buffer - unless it is fragmented
if (rlen && !rerror)
{
// this is the call to the users ip stack
if (rx_callback)
err = (rx_callback)((void *)rptr, rlen, context);
}
// now free the rx
// return the buffer list descriptors
// how do we know the address of the buffer list ???
// actually, the packet may be split accross more than 1 bl_desc
// and the fdsystem points to the LAST bl_desc used
// should only free up the bl's that are actually used ...
// now just free them all
for (i=0; i<ctl; i=i+1)
{
ULONG buff;
ULONG desc;
ULONG offset;
// free buffer
// buffer address should not have changed
// calculate the rx_bl_desc for each buffer, and the offset ...
buff = (*(volatile ULONG *)(eth->rx_fda_desc+0x10+(8*i)) - eth->rx_buffer_base) / eth->rx_buffer_length;
desc = buff / eth->rx_num_buffs;
offset = buff % eth->rx_num_buffs;
eth->rx_bl_desc = eth->rx_bl_desc_base + (0x10 + (8*eth->rx_num_buffs)) * desc;
*(volatile ULONG *)(eth->rx_bl_desc+0x14+(8*offset)) = 0x80000000 | eth->rx_buffer_length; // set OWN bit + length
}
// return fda descriptor
*(volatile ULONG *)(eth->rx_fda_desc+0x00) = 0xffffffff;
*(volatile ULONG *)(eth->rx_fda_desc+0x04) = 0xffffffff;
*(volatile ULONG *)(eth->rx_fda_desc+0x08) = 0xffffffff;
*(volatile ULONG *)(eth->rx_fda_desc+0x0c) = 0xffffffff;
for (i=0; i<buffer_count; i++)
{
*(volatile ULONG *)(eth->rx_fda_desc+(i*8)+0x10) = 0xffffffff;
*(volatile ULONG *)(eth->rx_fda_desc+(i*8)+0x14) = 0xffffffff;
}
// move on eth->rx_fda_desc ptr
eth->rx_fda_desc = next;
return err;
}
return -1;
}
// issue a pause command for slots (1 slot = 5.12us/51.2us)
int eth_pause(type_eth_descriptors *eth, USHORT slots)
{
ULONG tx_ctl;
// skip if previous not yet completed
if (read_csr(MAC_TX_CTL) & 0x40) return 1;
// set the pause duration
eth->macaddr[0x7c] = (slots >> 8) & 0xff; // pause duration
eth->macaddr[0x7d] = slots & 0xff;
// set up ARC
write_csr(MAC_ARC_ADDR, 0x7c);
write_csr(MAC_ARC_DATA, ((eth->macaddr[0x7c+0] & 0xff) << 24) | ((eth->macaddr[0x7c+1] & 0xff) << 16) | ((eth->macaddr[0x7c+2] & 0xff) << 8) | ((eth->macaddr[0x7c+3] & 0xff) << 0));
// issue the pause command
tx_ctl = read_csr(MAC_TX_CTL);
write_csr(MAC_TX_CTL, tx_ctl | 0x40);
return 0;
}
// phy stuff
int eth_mdread(int addr, int reg)
{
int rdata;
// ensure busy not set
do
{
rdata = read_csr(MAC_MD_CA);
} while (rdata & 0x0800);
// read md, phy_addr:addr, phy_reg:reg
write_csr(MAC_MD_CA, 0x00000800 | ((addr & 0x1f) << 5) | ((reg & 0x1f) << 0));
// wait while busy set
do
{
rdata = read_csr(MAC_MD_CA);
} while (rdata & 0x0800);
rdata = read_csr(MAC_MD_DATA);
return rdata;
}
int eth_mdwrite(int addr, int reg, int wdata)
{
int rdata;
// ensure busy not set
do
{
rdata = read_csr(MAC_MD_CA);
} while (rdata & 0x0800);
// write md, phy_addr:addr, phy_reg:reg
write_csr(MAC_MD_DATA, wdata);
write_csr(MAC_MD_CA, 0x00000c00 | ((addr & 0x1f) << 5) | ((reg & 0x1f) << 0));
// wait while busy set
do
{
rdata = read_csr(MAC_MD_CA);
} while (rdata & 0x0800);
return 0;
}
// read bank n
// if bank n is currently being written, do a bankswap first
int eth_rmon_getstats(int banksel, ULONG *sdata, int clear, int view)
{
ULONG rdata;
ULONG addr;
int bank;
rdata = read_csr(RMON_COUNT_ACCESS);
bank = (rdata >> 11) & 1; // this is the bank currently being written
if (bank == banksel)
{
// bankswap
write_csr(RMON_COUNT_ACCESS, RMON_CMD_BANKSWAP);
// wait til done
rdata = read_csr(RMON_COUNT_ACCESS);
while(rdata & RMON_STATUS_BANKBSY)
{
rdata = read_csr(RMON_COUNT_ACCESS);
}
}
for (addr=0; addr<0x40; addr=addr+1)
{
if (clear)
write_csr(RMON_COUNT_ACCESS, RMON_CMD_READCLR | addr);
else
write_csr(RMON_COUNT_ACCESS, RMON_CMD_READ | addr);
sdata[addr] = read_csr(RMON_COUNT_DATA);
}
if (view)
{
printf("\n");
printf("bank :%d\n",bank);
printf("Transmit\n");
printf("00 CollisionFrames0 = %ld\n",sdata[0x00]);
printf("01 CollisionFrames1 = %ld\n",sdata[0x01]);
printf(" ...\n");
printf("10 CollisionFrames16 = %ld\n",sdata[0x10]);
printf("11 FramesWithDeferredXmissions = %ld\n",sdata[0x11]);
printf("12 LateCollisions = %ld\n",sdata[0x12]);
printf("13 FramesLostDueToIntMACXmitError = %ld\n",sdata[0x13]);
printf("14 CarrierSenseError = %ld\n",sdata[0x14]);
printf("15 FramesWithExcessiveDeferral = %ld\n",sdata[0x15]);
printf("16 UnicastFramesXmittedOK = %ld\n",sdata[0x16]);
printf("17 MulticastFramesXmittedOK = %ld\n",sdata[0x17]);
printf("18 BroadcastFramesXmittedOK = %ld\n",sdata[0x18]);
printf("19 SQETestErrors = %ld\n",sdata[0x19]);
printf("1a PAUSEMACCtlFramesTransmitted = %ld\n",sdata[0x1a]);
printf("1b MACCtlFramesTransmitted = %ld\n",sdata[0x1b]);
printf("1c VLANFramesTransmitted = %ld\n",sdata[0x1c]);
printf("1d OctetsTransmittedOK = %ld\n",sdata[0x1d]);
printf("1e OctetsTransmittedOKHi = %ld\n",sdata[0x1e]);
printf("\n");
printf("Receive\n");
printf("20 ReceivePacketSize0 (0-63) = %ld\n",sdata[0x20]);
printf("21 ReceivePacketSize1 (64) = %ld\n",sdata[0x21]);
printf("22 ReceivePacketSize2 (65-127) = %ld\n",sdata[0x22]);
printf("23 ReceivePacketSize3 (128-255) = %ld\n",sdata[0x23]);
printf("24 ReceivePacketSize4 (256-511) = %ld\n",sdata[0x24]);
printf("25 ReceivePacketSize5 (512-1023) = %ld\n",sdata[0x25]);
printf("26 ReceivePacketSize6 (1024-1518) = %ld\n",sdata[0x26]);
printf("27 ReceivePacketSize7 (>1518) = %ld\n",sdata[0x27]);
printf("28 FrameCheckSequenceErrors = %ld\n",sdata[0x28]);
printf("29 AlignmentErrors = %ld\n",sdata[0x29]);
printf("2a Fragments = %ld\n",sdata[0x2a]);
printf("2b Jabbers = %ld\n",sdata[0x2b]);
printf("2c FramesLostDueToIntMACRcvError = %ld\n",sdata[0x2c]);
printf("2d UnicastFramesReceivedOK = %ld\n",sdata[0x2d]);
printf("2e MulticastFramesReceivedOK = %ld\n",sdata[0x2e]);
printf("2f BroadcastFramesReceivedOK = %ld\n",sdata[0x2f]);
printf("30 InRangeLengthErrors = %ld\n",sdata[0x30]);
printf("31 OutOfRangeLengthErrors = %ld\n",sdata[0x31]);
printf("32 VLANFramesReceived = %ld\n",sdata[0x32]);
printf("33 PAUSEMACCtlFramesReceived = %ld\n",sdata[0x33]);
printf("34 MACCtlFramesReceived = %ld\n",sdata[0x34]);
printf("35 OctetsReceivedOK = %ld\n",sdata[0x35]);
printf("36 OctetsReceivedOKHi = %ld\n",sdata[0x36]);
printf("37 OctetsReceivedOther = %ld\n",sdata[0x37]);
printf("38 OctetsReceivedOtherHi = %ld\n",sdata[0x38]);
}
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -