|
*******************************************************************************
* Copyright (C) 2005 Ben Ning
* rtl8019.c: Send & Receive Implementation for RTL8019AS
*
*******************************************************************************/
#pragma LARGE ORDER NOPRINT OPTIMIZE(2)
#include <stdlib.h>
#include <stdio.h>
#include <absacc.h>
#include <string.h>
#include "NetAPI.h"
#include "NET.H"
//#include "SERIAL.H"
#include "w78e58.h"
#include "rtl8019.h"
//-----------------------------------------------------------------------------
// select RTL8019AS register page
//-----------------------------------------------------------------------------
void rtl8019_page(UCHAR page_num)
{
UCHAR data temp;
temp = CR; //command register
temp=temp&0x3B ; // 0011 1011 bit2 = 0 for to disabel TXP
page_num = page_num << 6;
temp=temp | page_num;
CR = temp;
}
//-----------------------------------------------------------------------------
// reset RTL8019AS chip
//-----------------------------------------------------------------------------
void rtl8019_reset()
{
UCHAR i, j, temp;
// hardware reset
RTL8019_RESET = 1;
for (i=0; i<100; i++) for (j=0; j<255; j++);
RTL8019_RESET = 0;
for (i=0; i<100; i++) for (j=0; j<255; j++);
// software reset
temp = REST_PORT;
for (i=0; i<100; i++) for (j=0; j<255; j++);
REST_PORT = temp;
for (i=0; i<100; i++) for (j=0; j<255; j++);
}
//-----------------------------------------------------------------------------
// Initialize the RTL8019AS chip
//-----------------------------------------------------------------------------
extern UCHAR xdata my_hwaddr[6];
void rtl8019_init(void)
{
UCHAR i, j;
// for (i=0; i<255; i++);
rtl8019_reset();
CR = 0x21; // stop mode for setting registers and select page 0
for (i=0; i<10; i++)
for (j=0; j<255; j++); // delay about 10ms
DCR = 0xc8; // byte dma 8 bit dma mode
RBCR0 = 0x00;
RBCR1 = 0x00;
TCR = 0x02;
// RCR = 0xcc; //monitor mode (no packet receive)
RCR = 0xe0; //monitor mode (no packet receive)
PSTART = RXSTART_INIT;
// PSTOP = 0x80; // for 16 bit mode
PSTOP = RXSTOP_INIT; // for 8 bit mode
BNRY = RXSTART_INIT;
TPSR = TXSTART_INIT;
ISR = 0xff; // clear all interrupt flags
IMR = 0x00; // disable all interrupt
CR = 0x61; // select page 1
CURR = RXSTART_INIT;
// CR = 0x22; // Let chip to work
// TCR = 0xe0;
// CR = 0x62;
// set Mac address
PAR0 = my_hwaddr[0];
PAR1 = my_hwaddr[1];
PAR2 = my_hwaddr[2];
PAR3 = my_hwaddr[3];
PAR4 = my_hwaddr[4];
PAR5 = my_hwaddr[5];
// set muticast address
MAR0 = 0xFF;
MAR1 = 0xFF;
MAR2 = 0xFF;
MAR3 = 0xFF;
MAR4 = 0xFF;
MAR5 = 0xFF;
MAR6 = 0xFF;
MAR7 = 0xFF;
CR = 0x21; // select page 0
RCR = 0xcc; // normal mode
TCR = 0xe0;
CR = 0x22; // Normal work
ISR = 0xff; // clear all interrupt flags
}
//-----------------------------------------------------------------------------
// This functions checks RTL8019AS status then sends an ethernet frame to it.
//-----------------------------------------------------------------------------
void rtl8019_send_frame(UCHAR xdata * outbuf, UINT len)
{
UINT data i, j, n;
rtl8019_page(0);
if (len<60) n = 60; else n = len;
// set start address for sending
RSAR1 = TXSTART_INIT; // write dma address -- high byte
RSAR0 = 0x00; // write dma address -- low byte
// set the count of bytes that will be send out
RBCR1 = n >> 8;
RBCR0 = n & 0xff;
CR = 0x12; //write dma, page0
// Write data to dma
for (i=0; i<len; i++) DMA_PORT = *(outbuf+i);
// If necessary, to file some PAD bytes with 0x00
for (i=len; i<n; i++) DMA_PORT = 0x00;
// Disable DMA OP
RBCR1 = 0x00; // write count high
RBCR0 = 0x00; // write count low;
CR = 0x22; //complete dma page 0
for(i=0;i<16;i++) // Try to resend 16 times
{
for (j=0; j<1000; j++) {
if (!(CR & TXP)) break; // If has transmited, break.
}
if (TSR & PTX) break; // If sending has completed
CR = 0x3e;
}
ISR = 0xff;
TPSR = TXSTART_INIT; //txd packet start;
TBCR1 = n >> 8; //high byte counter
TBCR0 = n & 0xff; //low byte counter
ISR = 0xff;
CR = 0x3e; //to sendpacket;
// Release memory for re-use
// free(outbuf);
}
//------------------------------------------------------------------------
// This function gets an incoming Ethernet frame from the RTL8019AS.
// There may be more than 1 waiting but just allocate memory for
// one and read one in. Use the RTL8019AS to queue incoming packets.
//------------------------------------------------------------------------
//extern UCHAR idata rcve_buf_allocated;
UCHAR xdata * rtl8019_rcve_frame(void)
{
UINT data len, i;
UCHAR xdata * data buf;
UCHAR xdata * data p;
UCHAR data curr, bnry;
UCHAR data status, next_page, len_l, len_h;
rtl8019_page(0);
status = ISR;
// Check if buffer overflow
if (status & 0x90)
rtl8019_OverflowRecover();
status = RSR;
if (!(status & 0x01)) // no data received
return NULL;
bnry = BNRY; //bnry page have read
rtl8019_page(1);
curr = CURR; //curr write page
rtl8019_page(0);
if (bnry==curr) return NULL; // no arrived package
CRDA1 = bnry; // current read dma address high
CRDA0 = 0x00; // current read dma address low
RBCR1 = 0x00; // count high
RBCR0 = 0x04; // count low
CR = 0x0a; // begin to read dma
// read 8019 header
status = DMA_PORT;
next_page = DMA_PORT;
len_l = DMA_PORT;
len_h = DMA_PORT;
RBCR1 = 0x00; // to read a page (256 bytes)
RBCR0 = 0x00;
CR = 0x22; // DMA completed page0
// if boundary pointer is invalid
// if (!(status & 0x01) || (next_page>0x7f) || (next_page<0x4c) || (len_h>0x06) )
if (!(status & 0x01) || (next_page>=RXSTOP_INIT) || (next_page<RXSTART_INIT) || (len_h>0x06) )
{
rtl8019_page(1);
curr = CURR;
rtl8019_page(0);
bnry = curr;
BNRY = bnry;
ISR = 0xff;
return NULL;
}
len = ((UINT) len_h << 8) | (UINT) len_l;
len = len - 4; // subract 4 bytes for eth CRC
// Allocate enough memory to hold the incoming frame
buf = (UCHAR xdata *) malloc(len);
if (buf == NULL) {
return NULL;
}
p = buf;
CRDA1 = bnry; // read DMA address high
CRDA0 = 0x04; // read DMA address low, skip 4 byte that is 8019 header
RBCR1 = len >> 8; // count high
RBCR0 = len & 0x00ff; // count low
CR = 0x0a; // begin to read DMA
for (i=0; i<len; i++) {
*p++ = DMA_PORT;
}
RBCR1 = 0x00; // to read a page (256 bytes)
RBCR0 = 0x00;
CR = 0x22; // DMA completed page0
ISR = 0xff;
BNRY = next_page; //bnry; // Update BNRY
return (buf);
}
void rtl8019_OverflowRecover(void)
{
UCHAR data data_L, resend;
UCHAR idata i, j;
data_L = CR;
CR = 0x21; // stop mode for setting registers and select page 0
for (i=0; i<10; i++) for (j=0; j<255; j++); // delay about 10ms
RBCR0 = 0x00;
RBCR1 = 0x00;
if (data_L & TXP) {
data_L = ISR;
if((data_L & 0x02) || (data_L & 0x08))
resend = 0;
else
resend = 1;
}
else
resend = 0;
TCR = 0x02;
CR = 0x22;
BNRY = RXSTART_INIT;
CR = 0x62;
CURR = RXSTART_INIT;
CR = 0x22;
ISR = 0x10;
TCR = TCR_INIT;
if(resend)
CR = 0x26;
ISR = 0xFF;
}
/-------------------------------------------------------------
http://shallop.vicp.net |
阿莫论坛20周年了!感谢大家的支持与爱护!!
知道什么是神吗?其实神本来也是人,只不过神做了人做不到的事情 所以才成了神。 (头文字D, 杜汶泽)
|