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

📄 if_ne2kd.c

📁 一个简单的TCP IP协议栈程序
💻 C
📖 第 1 页 / 共 4 页
字号:
        // ***** 10. Take the NIC out of loopback mode (that means normal operation)        OUTPORTB(PG0W_TCR, 0x00);        PAUSE;        // ***** 11. IF Resend = 1 THEN reissue a transmit        if (Resend)        {            // Reissue transmit            OUTPORTB(NIC_CR, CR_START | CR_NO_DMA | CR_TXP);            PAUSE;        }    }else{        PAUSE;    }    // ***** Restore NIC IMR    OUTPORTB(PG0W_IMR, Imr);    PAUSE;    // ***** RETURN Success    return rtn;}static u_short Ne2kTransmitReady(void){  // ***** IF transmitting THEN RETURN FALSE  if (INPORTB(NIC_CR) & CR_TXP) return FALSE;  // ***** RETURN TRUE  return TRUE;}int Ne2kTransmit(const u_char *packet, u_short length){  int Timeout, Count;  u_char Imr;  u_char CrdaLow, CrdaHigh;//    printf("Ne2kTransmit\n");  // ***** IF transmitting THEN RETURN FALSE  if (!Ne2kTransmitReady()) return FALSE;  // ***** IF (length < 14) OR (length > 1514) THEN RETURN FALSE  if ((length < 14) || (length > 1514)) return FALSE;  // ***** Remember NIC IMR and disable interrupt from NIC (ATOMIC OPERATION!)  DISABLE_INTERRUPTS;  // Select PAGE 2  OUTPORTB(NIC_CR, CR_PAGE2 | CR_NO_DMA | CR_START);  PAUSE;  // Read IMR register  Imr = INPORTB(PG2R_IMR);  PAUSE;  // Select PAGE 0 again  OUTPORTB(NIC_CR, CR_PAGE0 | CR_NO_DMA | CR_START);  PAUSE;  // Disable interrupts from NIC  OUTPORTB(PG0W_IMR, 0x00);  PAUSE;  ENABLE_INTERRUPTS;  // ***** Clear REMOTE DMA COMPLETE bit in ISR  OUTPORTB(PG0W_ISR, ISR_RDC);  PAUSE;  // ***********************************************************************************  // ***** Due to two non synchronized state machines in the NIC, you should always do a   // ***** Remote Read (called a dummy read) before a Remote Write.  // ***** This is stated in the datasheet DP8390D/NS32490D NIC Network Interface Controller  // ***** (July 1995) from National  Semiconductor.   // ***** 1. Set Remote Byte Count to a value > 0 and Remote Start Address to unused RAM   //          (like transmit start page - 1) (REMEMBER THESE VALUES!)  CrdaLow = 0;  CrdaHigh = TSTART_PG - 1;  OUTPORTB(PG0W_RBCR0, 1);  PAUSE;  OUTPORTB(PG0W_RBCR1, 0);  PAUSE;  OUTPORTB(PG0W_RSAR0, CrdaLow);  PAUSE;  OUTPORTB(PG0W_RSAR1, CrdaHigh);  PAUSE;  // ***** 2. Issue the "dummy" Remote Read command  OUTPORTB(NIC_CR, CR_START | CR_DMA_READ);  PAUSE;  // ***** 3. Read the current remote DMA address (CRDA) (both bytes)  // ***** 4. Compare to previous CRDA value, if different go to step 6  // ***** 5. Delay and go to step 3.  // timeout < 100 === leave us with appr. 200us timeout (which is a lot)  // (this timeout is not impl. in NS' datasheet, but it's better to be on the safe side)  for (Timeout = 0; Timeout < 50; Timeout++)  {    if (CrdaLow != INPORTB(PG0R_CRDA0)) break;    PAUSE;    if (CrdaHigh != INPORTB(PG0R_CRDA1)) break;    PAUSE;  }  // ***** 6. Setup for the Remote Write command  // *****     Stop REMOTE DMA   OUTPORTB(NIC_CR, CR_START | CR_NO_DMA);  PAUSE;  // *****     Initialize Transmit Byte Count Registers to packet length and MIN. MIN_PACKET_SIZE bytes   if (length < MIN_PACKET_SIZE)  {     // Padding required    OUTPORTB(PG0W_TBCR0, MIN_PACKET_SIZE);    PAUSE;    OUTPORTB(PG0W_TBCR1, 0);    PAUSE;  }  else  {     // No padding required    OUTPORTB(PG0W_TBCR0, (length & 0xFF));    PAUSE;    OUTPORTB(PG0W_TBCR1, ((length >> 8) & 0xFF) );    PAUSE;  }  // ***** Update statistics (before making length an even value!)  Statistics.BytesTransmitted += length;  Statistics.PacketsTransmitted++;  // *****     We use word transfer mode, so make length an even value  length &= 0xfffe;  length++;  // *****     Initialize Remote Byte Count Register (DMA) to packet length   OUTPORTB(PG0W_RBCR0, (length & 0xFF));  PAUSE;  OUTPORTB(PG0W_RBCR1, ((length >> 8) & 0xFF));  PAUSE;  // *****     Initialize  Remote Start Address Register to address of NIC transmit buffer    OUTPORTB(PG0W_RSAR0, 0);  PAUSE;  OUTPORTB(PG0W_RSAR1, TSTART_PG);  PAUSE;  // ***** 7. Issue the Remote DMA WRITE   // *****     Start DMA Write  OUTPORTB(NIC_CR, CR_START | CR_DMA_WRITE);  PAUSE;  // *****     Write data to NIC  for (Count = 0; Count < length; Count += 2) OUTPORTW(NIC_DATAPORT, packet[Count] | (packet[Count+1] << 8));  // ***** Wait for Remote DMA to complete (should be instantly, but we have to wait anyway)  // timeout < 200 === leave us with appr. 200us timeout (which is a lot)  // (this timeout is not impl. in NS' datasheet, but it's better to be on the safe side)  for (Timeout = 0; Timeout < 200; Timeout++)  {    if (INPORTB(PG0R_ISR) & ISR_RDC) break;    PAUSE;  }  // ***** Clear REMOTE DMA COMPLETE bit in ISR  OUTPORTB(PG0W_ISR, ISR_RDC);  PAUSE;  // ***** Initialize Transmit Page Start Register  OUTPORTB(PG0W_TPSR, TSTART_PG);  PAUSE;  // ***** Start transmission  OUTPORTB(NIC_CR, CR_START | CR_NO_DMA | CR_TXP);  PAUSE;  // ***** Restore NIC IMR  OUTPORTB(PG0W_IMR, Imr);  PAUSE;  // ***** RETURN TRUE  return TRUE;}static void Ne2kTxNBuf(NBuf *pNBuf){    u_short d;    unsigned char *p_d;    long l;    int i;    NBuf *n;//    printf("TxNBuf:\n");    n=pNBuf;    l=pNBuf->len;    p_d=pNBuf->data;    i=0;    while(n)    {        if(l==0)        {            // next nBuf            n=n->nextBuf;            if(n)            {                l=n->len;                p_d=n->data;            }        }else{            d=(d<<8)|*p_d++;            l--;            if(++i==2)            {                i=0;                OUTPORTW(NIC_DATAPORT, d);//                printf("0x%lx\n",d);            }        }    }    if(i)    {        // as we were writing words, we might have a single trailling byte, so just send it...        d<<=8;        OUTPORTW(NIC_DATAPORT, d);//        printf("odd 0x%lx\n",d);    }}//static u_char dbgseq=1;static u_char Ne2kTxPacket(NBuf *pNBuf){  int Timeout;//  int Count;  u_char Imr;  u_char CrdaLow, CrdaHigh;    u_short length;//,padding,lTx;//    printf("Ne2kTxPacket\n");    // ***** IF transmitting THEN RETURN FALSE  if (!Ne2kTransmitReady()) return FALSE;    length=nChainLen(pNBuf);//    printf("Ne2kTxPacket: length=%d\n",length);  // ***** IF (length < 14) OR (length > 1514) THEN RETURN FALSE  if ((length < 14) || (length > 1514)) return FALSE;  // ***** Remember NIC IMR and disable interrupt from NIC (ATOMIC OPERATION!)  DISABLE_INTERRUPTS;  // Select PAGE 2  OUTPORTB(NIC_CR, CR_PAGE2 | CR_NO_DMA | CR_START);  PAUSE;  // Read IMR register  Imr = INPORTB(PG2R_IMR);  PAUSE;  // Select PAGE 0 again  OUTPORTB(NIC_CR, CR_PAGE0 | CR_NO_DMA | CR_START);  PAUSE;  // Disable interrupts from NIC  OUTPORTB(PG0W_IMR, 0x00);  PAUSE;  ENABLE_INTERRUPTS;  // ***** Clear REMOTE DMA COMPLETE bit in ISR  OUTPORTB(PG0W_ISR, ISR_RDC);  PAUSE;  // ***********************************************************************************  // ***** Due to two non synchronized state machines in the NIC, you should always do a  // ***** Remote Read (called a dummy read) before a Remote Write.  // ***** This is stated in the datasheet DP8390D/NS32490D NIC Network Interface Controller  // ***** (July 1995) from National  Semiconductor.  // ***** 1. Set Remote Byte Count to a value > 0 and Remote Start Address to unused RAM  //          (like transmit start page - 1) (REMEMBER THESE VALUES!)  CrdaLow = 0;  CrdaHigh = TSTART_PG - 1;  OUTPORTB(PG0W_RBCR0, 1);  PAUSE;  OUTPORTB(PG0W_RBCR1, 0);  PAUSE;  OUTPORTB(PG0W_RSAR0, CrdaLow);  PAUSE;  OUTPORTB(PG0W_RSAR1, CrdaHigh);  PAUSE;  // ***** 2. Issue the "dummy" Remote Read command  OUTPORTB(NIC_CR, CR_START | CR_DMA_READ);  PAUSE;  // ***** 3. Read the current remote DMA address (CRDA) (both bytes)  // ***** 4. Compare to previous CRDA value, if different go to step 6  // ***** 5. Delay and go to step 3.  // timeout < 100 === leave us with appr. 200us timeout (which is a lot)  // (this timeout is not impl. in NS' datasheet, but it's better to be on the safe side)  for (Timeout = 0; Timeout < 50; Timeout++)  {    if (CrdaLow != INPORTB(PG0R_CRDA0)) break;    PAUSE;    if (CrdaHigh != INPORTB(PG0R_CRDA1)) break;    PAUSE;  }  // ***** 6. Setup for the Remote Write command  // *****     Stop REMOTE DMA  OUTPORTB(NIC_CR, CR_START | CR_NO_DMA);  PAUSE;  // *****     Initialize Transmit Byte Count Registers to packet length and MIN. MIN_PACKET_SIZE bytes  if (length < MIN_PACKET_SIZE)  {//        printf("padding: length=%d, actual sent packet=%d\n",length,MIN_PACKET_SIZE);//        padding=MIN_PACKET_SIZE-length;//        length=MIN_PACKET_SIZE;    // Padding required    OUTPORTB(PG0W_TBCR0, MIN_PACKET_SIZE);    PAUSE;    OUTPORTB(PG0W_TBCR1, 0);    PAUSE;  }else{//        padding=0;//    }    // No padding required    OUTPORTB(PG0W_TBCR0, (length & 0xFF));    PAUSE;    OUTPORTB(PG0W_TBCR1, ((length >> 8) & 0xFF) );    PAUSE;  }  // ***** Update statistics (before making length an even value!)  Statistics.BytesTransmitted += length;  Statistics.PacketsTransmitted++;  // *****     We use word transfer mode, so make length an even value  length += length&1;  // *****     Initialize Remote Byte Count Register (DMA) to packet length  OUTPORTB(PG0W_RBCR0, (length & 0xFF));  PAUSE;  OUTPORTB(PG0W_RBCR1, ((length >> 8) & 0xFF));  PAUSE;  // *****     Initialize  Remote Start Address Register to address of NIC transmit buffer  OUTPORTB(PG0W_RSAR0, 0);  PAUSE;  OUTPORTB(PG0W_RSAR1, TSTART_PG);  PAUSE;  // ***** 7. Issue the Remote DMA WRITE  // *****     Start DMA Write  OUTPORTB(NIC_CR, CR_START | CR_DMA_WRITE);  PAUSE;  // *****     Write data to NIC    Ne2kTxNBuf(pNBuf);    // send padding/*    while(padding>0)    {        padding-=2;        OUTPORTW(NIC_DATAPORT,dbgseq);    }    dbgseq++;*/  // ***** Wait for Remote DMA to complete (should be instantly, but we have to wait anyway)  // timeout < 200 === leave us with appr. 200us timeout (which is a lot)  // (this timeout is not impl. in NS' datasheet, but it's better to be on the safe side)  for (Timeout = 0; Timeout < 200; Timeout++)  {    if (INPORTB(PG0R_ISR) & ISR_RDC) break;    PAUSE;  }  // ***** Clear REMOTE DMA COMPLETE bit in ISR  OUTPORTB(PG0W_ISR, ISR_RDC);  PAUSE;  // ***** Initialize Transmit Page Start Register  OUTPORTB(PG0W_TPSR, TSTART_PG);  PAUSE;  // ***** Start transmission  OUTPORTB(NIC_CR, CR_START | CR_NO_DMA | CR_TXP);  PAUSE;  // ***** Restore NIC IMR  OUTPORTB(PG0W_IMR, Imr);  PAUSE;  // ***** RETURN TRUE  return TRUE;}void Ne2kGetStatistics(Ne2kStatistics *statistics)

⌨️ 快捷键说明

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