⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cs8900a.c

📁 Bootload 程序
💻 C
字号:
/* * cs8900ac/h - porting from the device driver of the linux kernel. * direction: rx - outside -> cs8900a -> cpu / tx - outside <- cs8900a <- cpu */#include "dbldr_std.h"#include "dbldr_spec.h"#include "lib.h"#include "core_irq.h"#include "loop_buf.h"#include "cs8900a.h"#define _CS8900A_DEBUG_#ifdef _CS8900A_DEBUG_#define CS8900A_PRINT0(x0)                printf((x0))#define CS8900A_PRINT1(x0, x1)            printf((x0), (x1))#define CS8900A_PRINT2(x0, x1, x2)        printf((x0), (x1), (x2))#define CS8900A_PRINT3(x0, x1, x2, x3)    printf((x0), (x1), (x2), (x3))#else#define CS8900A_PRINT0(x0)#define CS8900A_PRINT1(x0, x1)#define CS8900A_PRINT2(x0, x1, x2)#define CS8900A_PRINT3(x0, x1, x2, x3)#endif /* _CS8900A_DEBUG_ */static VUINT8 _mac_addr[6] = { 0x08, 0x00, 0x3e, 0x26, 0x0a, 0x56 };/* direction: rx - outside -> cs8900a -> cpu / tx - outside <- cs8900a <- cpu */static void  *_rx_buf = NULL;static inline VUINT16 __cs8900a_rd_reg(VUINT16 addr){    *((VUINT16 *)(CS8900A_REG_BASE_ADDR + PP_Address)) = addr;    CS8900A_DELAY;    return *((VUINT16 *)(CS8900A_REG_BASE_ADDR + PP_Data));}static inline void __cs8900a_wr_reg(VUINT16 addr, VUINT16 val){    *((VUINT16 *)(CS8900A_REG_BASE_ADDR + PP_Address)) = addr;    CS8900A_DELAY;    *((VUINT16 *)(CS8900A_REG_BASE_ADDR + PP_Data)) = val;}static inline void __cs8900a_set(VUINT16 reg, VUINT16 val){    __cs8900a_wr_reg(reg, __cs8900a_rd_reg(reg) | val);}static inline void __cs8900a_clr(VUINT16 reg, VUINT16 val){    __cs8900a_wr_reg(reg, __cs8900a_rd_reg(reg) & ~val);}void cs8900a_disp_regs(void){    printf("cs8900a registers:\n");    printf("product id = 0x%04x\n", __cs8900a_rd_reg(PP_ProductID));    printf("interrupt number = 0x%04x\n", __cs8900a_rd_reg(PP_IntNum));}void __cs8900a_disp_mem(UINT8 *msg, UINT8 *buf, INT32 sz){    INT32 i;    CS8900A_PRINT1("%s", msg);    CS8900A_PRINT2("buf = 0x%08x sz = %d\n", buf, sz);    for (i = 0; i < sz; i++)    {        if (i && !(i % 16))        {            CS8900A_PRINT0("\n");        }        CS8900A_PRINT1("%02x ", buf[i]);    }    if ((i - 1) % 16)    {        CS8900A_PRINT0("\n");    }}/****************************************************************************** * NIC network device driver */static void __cs8900a_receive(void){    UINT16 status, length;    UINT16 tmp_buf, *tmp_ptr;    UINT32 ignored;    UINT32 i;    status = __cs8900a_rd_reg(PP_RxStatus);    length = __cs8900a_rd_reg(PP_RxLength);    if (!(status & RxOK))    {        CS8900A_PRINT0("ERROR - rx error in __cs8900a_receive()\n");        return;    }    if (_rx_buf)    {        tmp_ptr = (UINT16 *)CS8900A_REG_BASE_ADDR;        for (i = 0; i < (length >> 1); i++)        {            tmp_buf = *tmp_ptr;            if (OK != loop_buf_write(_rx_buf, (UINT8 *)&tmp_buf, 2, &ignored))            {                /* data loss if loop buf is full */                CS8900A_PRINT0("WARNING - rx data loss in __cs8900a_receive()\n");                return;            }        }    }}static void __cs8900a_send(void){    /* seems it is ok to be empty. */}static void __cs8900a_isr(void *param){    UINT16 status;    UINT16 tx_col;    while ((status = __cs8900a_rd_reg(PP_ISQ)))    {        switch (RegNum(status))        {        case RxEvent:            __cs8900a_receive();            break;        case TxEvent:            tx_col = ColCount(__cs8900a_rd_reg(PP_TxCOL));            if (tx_col)            {                CS8900A_PRINT1("WARNING - tx collison %d in __cs8900a_isr()\n", tx_col);            }            if (!(RegContent(status) & TxOK))            {                CS8900A_PRINT0("ERROR - tx error");                if (RegContent(status) & Out_of_window)                {                    CS8900A_PRINT0(": out of window");                }                if (RegContent(status) & Jabber)                {                    CS8900A_PRINT0(": jabber");                }                CS8900A_PRINT0(" in __cs8900a_isr()\n");            }            __cs8900a_send();            break;        case BufEvent:            if ((RegContent (status) & RxMiss))            {                CS8900A_PRINT1("WARNING - rx errors %d in __cs8900a_isr() 0\n",                    MissCount(__cs8900a_rd_reg(PP_RxMISS)));            }            if ((RegContent (status) & TxUnderrun))            {                CS8900A_PRINT0("WARNING - tx error in __cs8900a_isr()\n");            }            /* FIXME: if Rdy4Tx, transmit last sent packet (if any) */            break;        case TxCOL:            CS8900A_PRINT1("WARNING - collisions %d in __cs8900a_isr()\n",                ColCount(__cs8900a_rd_reg(PP_TxCOL)));            break;        case RxMISS:            CS8900A_PRINT1("WARNING - rx errors %d in __cs8900a_isr() 1\n",                MissCount(__cs8900a_rd_reg(PP_RxMISS)));            break;        default:            CS8900A_PRINT0("WARNING - unrecognized interrupt in __cs8900a_isr()\n");            return;        }    }}static INT32 __cs8900a_probe(UINT32 base_addr){    UINT16 value;    if (__cs8900a_rd_reg(PP_ProductID) != EISA_REG_CODE)    {        CS8900A_PRINT0("ERROR - invalid product id in cs8900a_init()\n");        return CS8900A_ERROR;    }    value = __cs8900a_rd_reg(PP_ProductID + 2);    if (VERSION(value) != CS8900A)    {        CS8900A_PRINT0("ERROR - invalid chip version in cs8900a_init()\n");        return CS8900A_ERROR;    }    __cs8900a_wr_reg(PP_IntNum, 0);    /* config mac addr here */    __cs8900a_wr_reg(PP_IA + 0, _mac_addr[0] | (_mac_addr[1] << 8));    __cs8900a_wr_reg(PP_IA + 2, _mac_addr[2] | (_mac_addr[3] << 8));    __cs8900a_wr_reg(PP_IA + 4, _mac_addr[4] | (_mac_addr[5] << 8));    /* where to destroy the loop buffer? in _stop()? */    _rx_buf = loop_buf_init(_2M,               BUF_TYPE_READ_EXIT_WHEN_FAILED              | BUF_TYPE_WRITE_EXIT_WHEN_FAILED              | BUF_TYPE_WRITE_HIGH_PRIORITY);    if (NULL == _rx_buf)    {        CS8900A_PRINT0("ERROR - init rx loop buf failed in cs8900a_init()\n");        goto FAILED;    }    return CS8900A_OK;FAILED:    if (_rx_buf)    {        loop_buf_destroy(_rx_buf);        _rx_buf = NULL;    }    return CS8900A_ERROR;}static INT32 __cs8900a_start(UINT32 base_addr){    set_ext_irq_type(IRQ_EINT8, IRQ_TYPE_RISING_EDGE);    __cs8900a_set(PP_RxCFG, RxOKiE | BufferCRC | CRCerroriE | RuntiE | ExtradataiE);    __cs8900a_set(PP_RxCTL, RxOKA | IndividualA | BroadcastA);    __cs8900a_set(PP_TxCFG, TxOKiE | Out_of_windowiE | JabberiE);    __cs8900a_set(PP_BufCFG, Rdy4TxiE | RxMissiE | TxUnderruniE | TxColOvfiE | MissOvfloiE);    __cs8900a_set(PP_LineCTL, SerRxON | SerTxON);    __cs8900a_set(PP_BusCTL, EnableRQ);    #ifdef CS8900A_FULL_DUPLEX    __cs8900a_set(PP_TestCTL, FDX);    #endif    /* wait for 200us */    DELAY(2);    request_irq(IRQ_EINT8, __cs8900a_isr, NULL);    enable_irq(IRQ_EINT8);    return CS8900A_OK;}static INT32 __cs8900a_stop(UINT32 base_addr){    __cs8900a_wr_reg(PP_BusCTL, 0);    __cs8900a_wr_reg(PP_TestCTL, 0);    __cs8900a_wr_reg(PP_SelfCTL, 0);    __cs8900a_wr_reg(PP_LineCTL, 0);    __cs8900a_wr_reg(PP_BufCFG, 0);    __cs8900a_wr_reg(PP_TxCFG, 0);    __cs8900a_wr_reg(PP_RxCTL, 0);    __cs8900a_wr_reg(PP_RxCFG, 0);    free_irq(IRQ_EINT8);    return CS8900A_OK;}/****************************************************************************** * interface to blob network protocal */static INT32 _cs8900a_init(UINT32 base_addr){    if (CS8900A_OK != __cs8900a_probe(base_addr))    {        return CS8900A_ERROR;    }    if (CS8900A_OK != __cs8900a_start(base_addr))    {        return CS8900A_ERROR;    }    return CS8900A_OK;}static INT32 _cs8900a_destroy(UINT32 base_addr){    if (CS8900A_OK != __cs8900a_stop(base_addr))    {        return CS8900A_ERROR;    }    loop_buf_destroy(_rx_buf);    return CS8900A_OK;}/* return value: actual_len/(-1) if failed */static INT32 _cs8900a_rx(UINT8 *buf, INT32 size){    UINT32 act_sz = 0;    if (!buf || size < 0)    {        CS8900A_PRINT0("ERROR - invalid parameter(s) in _cs8900a_rx()\n");        return CS8900A_ERROR;    }    if (!size)    {        return 0;    }    /* discard the return value */    loop_buf_read(_rx_buf, buf, size, &act_sz);    #if 0    if (act_sz)    {        __cs8900a_disp_mem("_cs8900a_rx: ", buf, act_sz);    }    #endif    return ((act_sz <= size) ? act_sz : 0);}static INT32 _cs8900a_tx(UINT8 *buf, INT32 size){    UINT16 status;    UINT16 *ptr;    UINT32 i;    #if 0    __cs8900a_disp_mem("_cs8900a_tx: ", buf, size);    #endif    __cs8900a_wr_reg(PP_TxCMD, TxStart(After5));    __cs8900a_wr_reg(PP_TxLength, size);    status = __cs8900a_rd_reg(PP_BusST);    if (status & TxBidErr)    {        CS8900A_PRINT0("WARNING - invalid frame length\n");        return CS8900A_ERROR;    }    if (!(status & Rdy4TxNOW))    {        CS8900A_PRINT0("WARNING - transmit buffer not free\n");        return CS8900A_ERROR;    }    for (i = 0; i < size; i += 2)    {        ptr = (UINT16 *)(buf + i);        *((UINT16 *)CS8900A_REG_BASE_ADDR) = *ptr;    }    if (size % 2)    {        ptr = (UINT16 *)(buf + size - 1);        *((UINT16 *)CS8900A_REG_BASE_ADDR) = (*ptr & 0xff00);    }    return CS8900A_OK;}static INT32 _cs8900a_set_addr(UINT8 dev_addr[6]){    return CS8900A_ERROR;}static INT32 _cs8900a_get_addr(UINT8 dev_addr[6]){    UINT32 i;    for (i = 0; i < 6; i++)    {        dev_addr[i] = _mac_addr[i];    }    return CS8900A_OK;}/********************************************************************** * export ethernet driver */ether_driver_t cs8900a_ether_driver = {    init:       _cs8900a_init,    destroy:    _cs8900a_destroy,    rcv:        _cs8900a_rx,    snd:        _cs8900a_tx,    set_addr:   _cs8900a_set_addr,    get_addr:   _cs8900a_get_addr,    name:       "cs8900a"};

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -