阅读:751回复:0
请教高手一个关于8139驱动开发的问题,本人在此先谢了
大家看看我的问题
我在做8139的驱动,因为没有操作系统,所以不知道中断如何实现.没有办法我只有改成polling,但用示波器跟踪,发现有中断发生,就是接收不到数据,经查好像也没有发送什么数据.我的源代码是参考linux下的8139too.c的,不知道有什么地方有错,请高手指教,下面是我的源代码 1,初始化 int rtl8139_open (struct net_device *dev) { struct rtl8139_private *tp = dev->priv; #if 0 tp->tx_bufs=(unsigned char *)(dev->virt_base | 0xa0000000); tp->tx_bufs_dma=&(dev->sdram_base); tp->rx_ring=tp->tx_bufs+TX_BUF_TOT_LEN; tp->rx_ring_dma=tp->tx_bufs_dma+TX_BUF_TOT_LEN; tp->tx_flag = (TX_FIFO_THRESH << 11) & 0x003f0000; #endif //if 0 #if 1 tp->tx_bufs=(unsigned char *)(dev->virt_base | 0xa0000000); tp->tx_bufs_dma=*(unsigned char *)virt_to_phys(tp->tx_bufs); tp->rx_ring=(unsigned char *)tp->tx_bufs+TX_BUF_TOT_LEN; tp->rx_ring_dma=*(unsigned char *)virt_to_phys(tp->rx_ring); tp->tx_flag = (TX_FIFO_THRESH << 11) & 0x003f0000; #endif //if 0 rtl8139_init_ring (dev); rtl8139_hw_start (dev); return 0; } /* Start the hardware at open or resume. */ void rtl8139_hw_start (struct net_device *dev) { struct rtl8139_private *tp = dev->priv; u32 i; u8 tmp; rtl8139_chip_reset (); /* unlock Config[01234] and BMCR register writes */ RTL_W8_F (Cfg9346, Cfg9346_Unlock); #if 1 /* Restore our idea of the MAC address. */ { MACaddr[0]=0x0;MACaddr[1]=0x4;MACaddr[2]=0x2;MACaddr[3]=0x10; MACaddr[4]=0x01;MACaddr[5]=0x1b;MACaddr[6]=0x0;MACaddr[7]=0x0; } RTL_W32_F (MAC0 + 0, cpu_to_le32 (*(u32 *) (MACaddr+ 0))); RTL_W32_F (MAC0 + 4, cpu_to_le32 (*(u32 *) (MACaddr+ 4))); #endif /* Must enable Tx/Rx before setting transfer thresholds! */ RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb); tp->rx_config = rtl8139_rx_config | AcceptBroadcast | AcceptMyPhys; RTL_W32 (RxConfig, tp->rx_config); /* Check this value: the documentation for IFG contradicts ifself. */ RTL_W32 (TxConfig, rtl8139_tx_config); tp->cur_rx = 0; RTL_W8 (Config3, RTL_R8 (Config3) & ~Cfg3_Magic); /* Lock Config[01234] and BMCR register writes */ RTL_W8 (Cfg9346, Cfg9346_Lock); /* init Rx ring buffer DMA address */ RTL_W32_F (RxBuf, tp->rx_ring_dma); /* init Tx buffer DMA addresses */ for (i = 0; i < NUM_TX_DESC; i++) RTL_W32_F (TxAddr0 + (i * 4), tp->tx_bufs_dma + (tp->tx_buf - tp->tx_bufs)); RTL_W32 (RxMissed, 0); RTL_W8(Config0,0); // rtl8139_set_rx_mode (dev); /* no early-rx interrupts */ RTL_W16 (MultiIntr, RTL_R16 (MultiIntr) & MultiIntrClear); /* make sure RxTx has started */ tmp = RTL_R8 (ChipCmd); if ((!(tmp & CmdRxEnb)) || (!(tmp & CmdTxEnb))) RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb); /* Enable all known interrupts by setting the interrupt mask. */ RTL_W16 (IntrMask, rtl8139_intr_mask); } 2,将中断改成了polling /* The interrupt handler does all of the Rx thread work and cleans up after the Tx thread. */ int rtl8139_polling (struct net_device *dev) { struct rtl8139_private *tp = dev->priv; int ackstat, status; int boguscnt = 20; int link_changed = 0; /* avoid bogus \"uninit\" warning */ int val=-1; do { status = RTL_R16 (IntrStatus); /* h/w no longer present (hotplug?) or major error, bail */ if (status == 0xFFFF) break; if ((status & (PCIErr | PCSTimeout | RxUnderrun | RxOverflow | RxFIFOOver | TxErr | TxOK | RxErr | RxOK)) == 0) break; /* Acknowledge all of the current interrupt sources ASAP, but an first get an additional status bit from CSCR. */ if (status & RxUnderrun) link_changed = RTL_R16 (CSCR) & CSCR_LinkChangeBit; /* The chip takes special action when we clear RxAckBits, * so we clear them later in rtl8139_rx_interrupt */ ackstat = status & ~(RxAckBits | TxErr); RTL_W16 (IntrStatus, ackstat); if (status & RxAckBits) val=rtl8139_rx_interrupt (dev, tp); if (status & (PCIErr | PCSTimeout | RxUnderrun | RxOverflow |RxFIFOOver | RxErr)) RTL_W32 (RxMissed, 0); if (status & (TxOK | TxErr)) { val=rtl8139_tx_interrupt (dev, tp); if (status & TxErr) RTL_W16 (IntrStatus, TxErr); } boguscnt--; } while (boguscnt > 0); if (boguscnt <= 0) { /* Clear all interrupt sources. */ RTL_W16 (IntrStatus, 0xffff); } if (val==-1) _delay(10); return val; } 3.发送 int rtl8139_send_pkt (struct net_device *dev, char* buf, int len) { struct rtl8139_private *tp = dev->priv; unsigned int entry; int i; int maxlen; unsigned char *buf_ptr; /* Calculate the next Tx descriptor entry. */ entry = tp->cur_tx % NUM_TX_DESC; #define ETH_ZLEN 60 if (len < TX_BUF_SIZE) { if(len < ETH_ZLEN) memset(tp->tx_buf[entry], 0, ETH_ZLEN); buf_ptr=tp->tx_buf[entry]; for(i=0;i<len;i++) buf_ptr=buf; } else return -1; if (len>ETH_ZLEN) maxlen=len; else maxlen=ETH_ZLEN; RTL_W32_F (TxStatus0 + (entry * sizeof (u32)), tp->tx_flag |maxlen); if (rtl8139_polling(dev)==-1) return -1; tp->cur_tx++; return 0; } int rtl8139_tx_interrupt (struct net_device *dev, struct rtl8139_private *tp) { unsigned long dirty_tx, tx_left; int val=-1; dirty_tx = tp->dirty_tx; tx_left = tp->cur_tx - dirty_tx; while (tx_left > 0) { int entry = dirty_tx % NUM_TX_DESC; int txstatus; txstatus = RTL_R32 (TxStatus0 + (entry * sizeof (u32))); if (!(txstatus & (TxStatOK | TxUnderrun | TxAborted))) break; /* It still hasn\'t been Txed */ /* Note: TxCarrierLost is always asserted at 100mbps. */ if (txstatus & (TxOutOfWindow | TxAborted)) { if (txstatus & TxAborted) { RTL_W32 (TxConfig, TxClearAbt); RTL_W16 (IntrStatus, TxErr); } } else { if (txstatus & TxUnderrun) { /* Add 64 to the Tx FIFO threshold. */ if (tp->tx_flag < 0x00300000) tp->tx_flag += 0x00020000; } else val=0; } dirty_tx++; tx_left--; } /* only wake the queue if we did work, and the queue is stopped */ if (tp->dirty_tx != dirty_tx) { tp->dirty_tx = dirty_tx; } return val; } 4,接收 int rtl8139_rx_interrupt (struct net_device *dev, struct rtl8139_private *tp) { unsigned char *rx_ring; u16 cur_rx; int val=-1; int i; rx_ring = tp->rx_ring; cur_rx = tp->cur_rx; while ((RTL_R8 (ChipCmd) & RxBufEmpty) == 0) { int ring_offset = cur_rx % RX_BUF_LEN; u32 rx_status; unsigned int rx_size; unsigned int pkt_size; /* read size+status of next frame from DMA ring buffer */ rx_status = *(u32 *) (rx_ring + ring_offset); rx_size = rx_status >> 16; pkt_size = rx_size - 4; // xxxpputs(\"running\"); psprintf (printf_buf1,\"rtl8139_rx() status %x, size %x, cur %x.\\n\",rx_status,rx_size, cur_rx);xxxpputs(printf_buf1); #if 0 { int i; for (i = 0; i < 70; i++) { psprintf(printf_buf1,\" %x\",rx_ring[ring_offset + i]); xxxpputs(printf_buf1); } } #endif /* Packet copy from FIFO still in progress. * Theoretically, this should never happen * since EarlyRx is disabled. */ if (rx_size == 0xfff0) { break; } /* If Rx err or invalid rx_size/rx_status received * (which happens if we get lost in the ring), * Rx process gets reset, so we abort any further * Rx processing. */ if ((rx_size > (MAX_ETH_FRAME_SIZE+4)) || (rx_size < 8) || (!(rx_status & RxStatusOK))) { xxxpputs(\"Out from 2...\"); rtl8139_rx_err (rx_status, dev, tp); return -1; } /* Malloc up new buffer, compatible with net-2e. */ /* Omit the four octet CRC from the length. */ /* TODO: consider allocating skb\'s outside of * interrupt context, both to speed interrupt processing, * and also to reduce the chances of having to * drop packets here under memory pressure. */ for(i=0;i<pkt_size;i++) buff=rx_ring[ring_offset+4+i]; val=pkt_size; cur_rx = (cur_rx + rx_size + 4 + 3) & ~3; RTL_W16 (RxBufPtr, cur_rx - 16); if (RTL_R16 (IntrStatus) & RxAckBits) RTL_W16_F (IntrStatus, RxAckBits); } tp->cur_rx = cur_rx; return val; } int rtl8139_recv_pkt (struct net_device *net) { int length; volatile u8* ptr; int i = 0,j; while(i == 0) { if ((length=rtl8139_polling(net))!=-1) { if (length==0) continue; length = (length & (0x7ff << 16)) >> 16 ; for(j=0;j<length;j++) ptr[j]=buff[j]; if (receive_upcall (0, 0, length) == 0) //have enough space in ring buffer? { xxxpputs(\"not enought space\"); return -1;//no space in ring buf } if (receive_upcall (0, (void*)ptr, length) == 0) { xxxpputs(\"not data\"); return -1; // put data to ring buff fail } i++; } } return 0; } |
|