📄 receive.c
字号:
/* * $QNXLicenseC: * Copyright 2007, QNX Software Systems. * * Licensed under the Apache License, Version 2.0 (the "License"). You * may not reproduce, modify or distribute this software except in * compliance with the License. You may obtain a copy of the License * at: http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTIES OF ANY KIND, either express or implied. * * This file may contain contributions from others, either as * contributors under the License or as licensors under other terms. * Please review this entire file for other proprietary rights or license * notices, as well as the QNX Development Suite License Guide at * http://licensing.qnx.com/license-guide/ for other information. * $ */#include <crys8900.h>#ifdef __X86__int cs8900_copy_data( void *handle, char *dst, int xoff, int xlen ){ int iobase; cs8900_dev_t *cs8900 = (cs8900_dev_t *)handle; iobase = cs8900->iobase; if (cs8900->mode & (CS8900_DMA | CS8900_SHARED)) { int rlen; char *src; if (cs8900->mode & CS8900_DMA) src = cs8900->dmem_cptr + xoff; else src = cs8900->smem + CS8900_RX_FRAME + xoff; if (cs8900->mode & CS8900_DMA) { rlen = ( cs8900->dmem + cs8900->dmem_size ) - src; if (xlen > rlen) { /* handle wrap */ if (rlen) memcpy( dst, src, rlen ); xlen -= rlen; src = cs8900->dmem; dst += rlen; } } else { src = cs8900->smem + CS8900_RX_FRAME; } memcpy( dst, src, xlen ); } else { in16s(dst, xlen >> 1, iobase + CS8900_PORT_RXTX); if (xlen & 1) dst[xlen-1] = in8(iobase + CS8900_PORT_RXTX); } return( EOK );}#endifint cs8900_receive( void *handle ){ cs8900_dev_t *cs8900 = (cs8900_dev_t *)handle; nic_stats_t *gstats; nic_ethernet_stats_t *estats; npkt_t *npkt, *new; ushort_t status; ushort_t pkt_len;#ifdef __X86__ int frame_cnt;#endif uint32_t iobase; net_buf_t *buf; net_iov_t *iov; iobase = cs8900->iobase; gstats = &cs8900->stats; estats = &cs8900->stats.un.estats;#ifdef __X86__ frame_cnt = ( cs8900->mode & CS8900_DMA ) ? cs8900_rpktpage( iobase, CS8900_DMA_FC ) : 1; while( frame_cnt ) { if( cs8900->mode & ( CS8900_DMA | CS8900_SHARED ) ) { cs8900_copy_data( cs8900, (char *)&status, 0, 2 ); cs8900_copy_data( cs8900, (char *)&pkt_len, 2, 2 ); } else { status = inle16( iobase + CS8900_PORT_RXTX ); pkt_len = inle16( iobase + CS8900_PORT_RXTX ); }#else status = inle16( iobase + CS8900_PORT_RXTX ); pkt_len = inle16( iobase + CS8900_PORT_RXTX );#endif if( status & RXEVENT_RXOK ) { /* grab a free pkt */ new = NULL; npkt = cs8900->rx_pktq[cs8900->rx_cidx]; cs8900->rx_pktq[cs8900->rx_cidx] = NULL; cs8900->rx_cidx = (cs8900->rx_cidx + 1) % cs8900->num_rx_pkts; cs8900->stats.octets_rxed_ok += pkt_len; npkt->framelen = pkt_len; buf = TAILQ_FIRST(&npkt->buffers); iov = buf->net_iov;#ifdef __X86__ cs8900_copy_data(cs8900, iov->iov_base, (cs8900->mode & CS8900_DMA) ? 4 : 0, pkt_len );#else { uint16_t *src = (uint16_t *)iov->iov_base; while (pkt_len > 1) { *src++ = inle16(iobase + CS8900_PORT_RXTX); pkt_len -= 2; } if (pkt_len) *(uint8_t *)src = inle16(iobase + CS8900_PORT_RXTX); }#endif gstats->rxed_ok++; iov->iov_len = npkt->framelen; if ((cs8900->rx_active + 1) < cs8900->rx_max) { if(new = cs8900_alloc_npkt(cs8900, 1518)) { atomic_add(&cs8900->rx_active, 1); } else { npkt->flags |= _NPKT_NO_RES; } } else { npkt->flags |= _NPKT_NO_RES; } npkt->iface = 0; if (cs8900->cfg.flags & NIC_FLAG_PROMISCUOUS) npkt->flags |= _NPKT_PROMISC; pthread_mutex_unlock( &cs8900->mutex ); if (ion_add_done(cs8900->reg_hdl, npkt, cs8900) == -1) { pthread_mutex_lock( &cs8900->mutex ); cs8900_receive_complete(npkt, cs8900, NULL); } else { if(ion_rx_packets( cs8900->reg_hdl, npkt, 0, 0, cs8900->cell, cs8900->cfg.lan, 0 ) == 0) { ion_tx_complete( cs8900->reg_hdl, npkt) ; } pthread_mutex_lock( &cs8900->mutex ); } if (new) { npkt = new; } else { npkt->flags = _NPKT_UP; npkt->ref_cnt = 1; npkt->req_complete = 0; } cs8900->rx_pktq[cs8900->rx_pidx] = npkt; cs8900->rx_pidx = (cs8900->rx_pidx + 1) % cs8900->num_rx_pkts; } else { pkt_len = 0; if (status & RXEVENT_RUNT) estats->short_packets++; if (status & RXEVENT_EXTRADATA) estats->oversized_packets++; if (status & RXEVENT_CRCERR) { if (!( status & (RXEVENT_EXTRADATA | RXEVENT_RUNT))) estats->fcs_errors++; } if (status & RXEVENT_DRIBBLE) estats->align_errors++; }#ifdef __X86__ frame_cnt--; if( cs8900->mode & CS8900_DMA ) { cs8900->dmem_cptr += ( ( pkt_len + 3 + RBUF_HEAD_LEN ) & ~3 ); cs8900->dmem_cptr = cs8900->dmem + ( ( cs8900->dmem_cptr - cs8900->dmem ) % cs8900->dmem_size ); if( !frame_cnt ) { /* release commited DMA memory */ frame_cnt = cs8900_rpktpage( iobase, CS8900_DMA_FC ); } } }#endif return (1);}intcs8900_receive_complete(npkt_t *npkt, void *done_hdl, void *func_hdl){ cs8900_dev_t *cs8900 = (cs8900_dev_t *)done_hdl; if (npkt == NULL) if ( cs8900->cfg.verbose ) nic_slogf (_SLOGC_NETWORK, _SLOG_ERROR, "devn-crys8900: npkt is NULL"); if (npkt->org_data == NULL) if ( cs8900->cfg.verbose ) nic_slogf (_SLOGC_NETWORK, _SLOG_ERROR, "devn-crys8900: org_data is NULL"); /* Actual Rx Buffer "npkts", Only free if not low on resources */ if(!(npkt->flags & _NPKT_NO_RES)) { ion_free(npkt->org_data); ion_free(npkt); atomic_sub(&cs8900->rx_active, 1); } return (0);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -