📄 if_edb7xxx.c
字号:
// the hardware ready to send/receive packets.//static voidcs8900_start(struct eth_drv_sc *sc, unsigned char *enaddr, int flags){ unsigned short stat; put_reg(PP_BusCtl, PP_BusCtl_MemoryE); // Disable interrupts, memory mode put_reg(PP_IntReg, PP_IntReg_IRQ0); // Only possibility put_reg(PP_RxCFG, PP_RxCFG_RxOK | PP_RxCFG_CRC | PP_RxCFG_RUNT | PP_RxCFG_EXTRA); put_reg(PP_RxCTL, PP_RxCTL_RxOK | PP_RxCTL_Broadcast | PP_RxCTL_IA); put_reg(PP_TxCFG, PP_TxCFG_TxOK | PP_TxCFG_Collision | PP_TxCFG_CRS | PP_TxCFG_SQE | PP_TxCFG_Late | PP_TxCFG_Jabber | PP_TxCFG_16Collisions); put_reg(PP_BufCFG, PP_BufCFG_TxRDY | PP_BufCFG_TxUE | PP_BufCFG_RxMiss | PP_BufCFG_TxCol | PP_BufCFG_Miss | PP_BufCFG_SWI); put_reg(PP_IntReg, PP_IntReg_IRQ0); // Only possibility put_reg(PP_LineCTL, PP_LineCTL_Rx | PP_LineCTL_Tx); // Clear Interrupt Status Queue before enabling interrupts while ((stat = CS8900_ISQ) != 0) ; put_reg(PP_BusCtl, PP_BusCtl_EnableIRQ);}//// This routine is called to perform special "control" opertions//static intcs8900_control(struct eth_drv_sc *sc, unsigned long key, void *data, int data_length){ switch (key) { case ETH_DRV_SET_MAC_ADDRESS: return 0; break; default: return 1; break; }}//// This routine is called to see if it is possible to send another packet.// It will return non-zero if a transmit is possible, zero otherwise.//static intcs8900_can_send(struct eth_drv_sc *sc){ struct cs8900_priv_data *cpd = (struct cs8900_priv_data *)sc->driver_private; unsigned short stat; stat = get_reg(PP_LineStat); if ((stat & PP_LineStat_LinkOK) == 0) { return false; // Link not connected }#ifdef CYGPKG_NET // Horrible hack! if (cpd->txbusy > 0) { cyg_tick_count_t now = cyg_current_time(); if ((now - cpd->txstart) > 25) { // 250ms is more than enough to transmit one frame diag_printf("CS8900: Tx interrupt lost\n"); cpd->txbusy = 0; // Free up the buffer (with error indication) (sc->funs->eth_drv->tx_done)(sc, cpd->txkey, 1); } }#endif return (cpd->txbusy == 0);}//// This routine is called to send data to the hardware.static void cs8900_send(struct eth_drv_sc *sc, struct eth_drv_sg *sg_list, int sg_len, int total_len, unsigned long key){ struct cs8900_priv_data *cpd = (struct cs8900_priv_data *)sc->driver_private; int i; int len; unsigned char *data; unsigned short saved_data = 0, *sdata; unsigned short stat; bool odd_byte = false; // Mark xmitter busy cpd->txbusy = 1; cpd->txkey = key;#ifdef CYGPKG_NET cpd->txstart = cyg_current_time();#endif // Start the xmit sequence// Note: this can go back once the 'dump' is removed CS8900_TxCMD = PP_TxCmd_TxStart_5; // Start more-or-less immediately// CS8900_TxCMD = PP_TxCmd_TxStart_Full; // Start only when all data sent to chip CS8900_TxLEN = total_len; stat = get_reg(PP_BusStat); // This actually starts the xmit // Put data into buffer for (i = 0; i < sg_len; i++) { data = (unsigned char *)sg_list[i].buf; len = sg_list[i].len; if (len > 0) { /* Finish the last word. */ if (odd_byte) { saved_data |= (*data++ << 8); CS8900_RTDATA = saved_data; len--; odd_byte = false; } /* Output contiguous words. */ sdata = (unsigned short *)data; while (len > 1) { CS8900_RTDATA = *sdata++; len -= sizeof(unsigned short); } /* Save last byte, if necessary. */ if (len == 1) { data = (unsigned char *)sdata; saved_data = *data; odd_byte = true; } } } if (odd_byte) { CS8900_RTDATA = saved_data; }}//// This function is called when a packet has been received. It's job is// to prepare to unload the packet from the hardware. Once the length of// the packet is known, the upper layer of the driver can be told. When// the upper layer is ready to unload the packet, the internal function// 'cs8900_recv' will be called to actually fetch it from the hardware.//static voidcs8900_RxEvent(struct eth_drv_sc *sc){ unsigned short stat, len; stat = CS8900_RTDATA; len = CS8900_RTDATA; if (net_debug) { diag_printf("RxEvent - stat: %x, len: %d\n", stat, len); } (sc->funs->eth_drv->recv)(sc, len);}//// This function is called as a result of the "eth_drv_recv()" call above.// It's job is to actually fetch data for a packet from the hardware once// memory buffers have been allocated for the packet. Note that the buffers// may come in pieces, using a scatter-gather list. This allows for more// efficient processing in the upper layers of the stack.//static voidcs8900_recv(struct eth_drv_sc *sc, struct eth_drv_sg *sg_list, int sg_len){ int i, mlen; unsigned short *data, val; unsigned char *cp, cval; for (i = 0; i < sg_len; i++) { data = (unsigned short *)sg_list[i].buf; mlen = sg_list[i].len; while (mlen >= sizeof(*data)) { val = CS8900_RTDATA; if (data) { *data++ = val; } mlen -= sizeof(*data); } if (mlen) { // Fetch last odd byte cval = CS8900_RTDATA & 0xFF; if ((cp = (unsigned char *)data) != 0) { *cp = cval; } } }}static voidcs8900_TxEvent(struct eth_drv_sc *sc, int stat){ struct cs8900_priv_data *cpd = (struct cs8900_priv_data *)sc->driver_private; stat = get_reg(PP_TER); if (net_debug) { diag_printf("Tx event: %x\n", stat); } cpd->txbusy = 0; (sc->funs->eth_drv->tx_done)(sc, cpd->txkey, 0);}static voidcs8900_BufEvent(struct eth_drv_sc *sc, int stat){ if (stat & PP_BufCFG_RxMiss) { } if (stat & PP_BufCFG_TxUE) { }}static voidcs8900_int(struct eth_drv_sc *sc){ unsigned short event; while ((event = CS8900_ISQ) != 0) { switch (event & ISQ_EventMask) { case ISQ_RxEvent: cs8900_RxEvent(sc); break; case ISQ_TxEvent: cs8900_TxEvent(sc, event); break; case ISQ_BufEvent: cs8900_BufEvent(sc, event); break; case ISQ_RxMissEvent: // Receive miss counter has overflowed break; case ISQ_TxColEvent: // Transmit collision counter has overflowed break; default: diag_printf("%s: Unknown event: %x\n", __FUNCTION__, event); break; } }}#ifdef INTS_DONT_WORKvoidcs8900_fake_int(cyg_addrword_t param){ int s; while (true) { cyg_thread_delay(5); s = splnet(); cs8900_int(&edb7xxx_sc); splx(s); }}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -