📄 cs8900a.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 + -