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

📄 ne2000.c

📁 最近在國外網站抓到的作業系統 以Arm為基礎去開發的
💻 C
📖 第 1 页 / 共 5 页
字号:

    do    
    {
        memcpy(FramePtr, buf_ptr->data_ptr, buf_ptr->data_len);
        length += buf_ptr->data_len;
        FramePtr += buf_ptr->data_len;

        /* Move on to the next buffer. */
        buf_ptr = buf_ptr->next_buffer;

    } while (buf_ptr != 0);   

    /* make sure packet is within legal size   */
    if (length < ETHER_MIN_LEN)   
        length = ETHER_MIN_LEN;   

    if (length > ETHERSIZE)
    {
        //DEBUG_ERROR("ne2000xmit - length is too large: length = ", 
        //    EBS_INT1, length, 0);
        length = ETHERSIZE;       /* what a terriable hack! */
    }
    
    
	/* Send requires interrupts disabled. So the ISR does not change
       the register back out from under us (particularly the dma
       pointer) */

    /* Disable interrupts */
    previous_int_value = NU_Control_Interrupts(NU_DISABLE_INTERRUPTS);
     
    /* Set NIC to page 0 registers.   */
    OUTBYTE(REF_REG_ADDR(nic_addr_NE2000_P0_CR), NE2000_CR_RD2 | NE2000_CR_PAGE_0 | NE2000_CR_STA);
    /* mask off all isr's   */
    OUTBYTE(REF_REG_ADDR(nic_addr_NE2000_P0_IMR), 0);
    NU_Control_Interrupts(previous_int_value);

    ret_val = 0;
    if (ne2000_pio_write_pkt(sc, (PFCBYTE)TEMP_BUF_T, length, sc->mem_start))
    {
        /* Set NIC for page 0 register access.   */
        OUTBYTE(REF_REG_ADDR(nic_addr_NE2000_P0_CR), NE2000_CR_RD2 | NE2000_CR_PAGE_0 | NE2000_CR_STA);
        /* Set TX buffer start page.   */
        OUTBYTE(REF_REG_ADDR(nic_addr_NE2000_P0_TPSR), sc->tx_page_start);
        /* Set TX length.   */
        OUTBYTE(REF_REG_ADDR(nic_addr_NE2000_P0_TBCR0), length);
        OUTBYTE(REF_REG_ADDR(nic_addr_NE2000_P0_TBCR1), length >> 8);
        /* Set page 0, remote DMA complete, transmit packet, and *start*.   */
        OUTBYTE(REF_REG_ADDR(nic_addr_NE2000_P0_CR), NE2000_CR_RD2 | NE2000_CR_PAGE_0 | NE2000_CR_TXP | NE2000_CR_STA);
    }
    else
    {
        //ret_val = ENETDOWN;
    }

    previous_int_value = NU_Control_Interrupts(NU_DISABLE_INTERRUPTS);     /* Disable interrupts */
    /* Set NIC to page 0 registers.   */
    OUTBYTE(REF_REG_ADDR(nic_addr_NE2000_P0_CR), NE2000_CR_RD2 | NE2000_CR_PAGE_0 | NE2000_CR_STA);
    /* Turn ints back on    */
    OUTBYTE(REF_REG_ADDR(nic_addr_NE2000_P0_IMR), NORMAL_NE2000_INTS);
    NU_Control_Interrupts(previous_int_value);

    return(ret_val);
}

/************************************************************************
* FUNCTION                                                             
*                                                                      
*        Rtl8019_Receive                                        
*                                                                      
* DESCRIPTION                                                          
*                                                                      
*        Processes a frame into Net buffers that can be used by the
*        upper layers. Once the frame is processed, the Ether_Rcv HISR
*        is activated, which will eventually let the upper layers know
*        about the new packets.
*                                                                      
* AUTHOR                                                               
*                                                                      
*        Meter Chen                                      
*                                                                      
* INPUTS                                                               
*                                                                      
*        DV_DEVICE_ENTRY    *device      Pointer to the device structure.
*                                                                      
* OUTPUTS                                                              
*                                                                      
*        None.                                    
*                                                                      
************************************************************************/

STATUS Rtl8019_Receive(DV_DEVICE_ENTRY *device)
{
    NET_BUFFER  *buf_ptr;
    UINT32      pkt_size, bytes_left;

    /* This function is responsible for moving received packets from 
    ** shared memory into the packet buffers.  Start by allocating a
    ** buffer (from the Free List) into which the received packet
    ** will be copied.
    *******************************************************************/

  
    /* Copy the Rx Packet into as many NET Buffers as it takes! */

    /* Get the packet size fron the RxFD & allocate buffer(s) for it! */
    pkt_size = et_data_len;

    /* Allocate a buffer (or a chain of buffers) into which the Rx
    ** packet can be copied! */
    if (pkt_size <= NET_PARENT_BUFFER_SIZE) /* One buffer case! */
    {
        buf_ptr = MEM_Buffer_Dequeue(&MEM_Buffer_Freelist);
    }
    else /* More than one buffer is needed! */
    {
        buf_ptr = MEM_Buffer_Chain_Dequeue(&MEM_Buffer_Freelist, pkt_size);
    }

    if (buf_ptr == NU_NULL)
    {
        //NU_Tcp_Log_Error (TCP_PARTITION_ERROR, TCP_RECOVERABLE,
        //                __FILE__, __LINE__);

        /* Return that there was an error with a packet reception */
        return(-1); 
    }  
    else 
    {
        /* Put the head of the chain (or only one) on the incoming 
        ** packet buffer list */
        MEM_Buffer_Enqueue (&MEM_Buffer_List, buf_ptr);

        /* Get the total number of bytes that must be copied */
        bytes_left = pkt_size;

        /* This sets Total Packet Length in the first (or only) buffer! */
        buf_ptr->mem_total_data_len = pkt_size;

        /* Set the device into the buffer header! */
        buf_ptr->mem_buf_device = device;

        /* Clear the flags field! */
        buf_ptr->mem_flags = 0;

        if (pkt_size <= NET_PARENT_BUFFER_SIZE) /* One buffer case. */
        {
            /* The MEM Buffer Dequeue function returns a Ptr to the Buffer's */
            /* Data area at the TOP of the Buffer. */
            buf_ptr->data_ptr = (UINT8 *) buf_ptr;
            
            /* Data in this buffer, same as total for this case. */
            buf_ptr->data_len = pkt_size;

            /* Do the copy. */
            memcpy(buf_ptr->data_ptr, (UINT8 *)et_data_ptr, pkt_size);
        }
        else /* More than one NET Buffer required!  Pack the first one and  */
        {    /* enter the while loop to fill the remaining ones needed.     */
        
             /* Data area in the first buffer is less than in the rest. */
             buf_ptr->data_len = NET_PARENT_BUFFER_SIZE;

             /* The Ptr is to the Buffer's Data area at the TOP of the */
             /* Buffer, so copy the buf_ptr to the Buffer's Data Ptr.  */
             buf_ptr->data_ptr = (UINT8 *) buf_ptr;

             /* Do the copy. */
             memcpy(buf_ptr->data_ptr, (UINT8 *)et_data_ptr,
                                       NET_PARENT_BUFFER_SIZE);

             bytes_left -= NET_PARENT_BUFFER_SIZE;
             
             /* Advance data ptr to next block start. */
             et_data_ptr += NET_PARENT_BUFFER_SIZE; 

             while (bytes_left > 0) 
             {
                /* Move to the next buffer in the chain  */
                buf_ptr = (NET_BUFFER *) buf_ptr->next_buffer;

                /* The Ptr is to the Buffer's Header start, NOT the Data area  */
                /* at the TOP of the Buffer, so copy the Adjusted Ptr to the   */
                /* Buffer's Data Ptr.                                          */
                buf_ptr->data_ptr = (UINT8 *) buf_ptr;

                /* See if a Full Buffer is needed!  Note that these buffers */    
                /* hold more data (0x218/536) since the me_bufhdr is not    */
                /* needed!                                                  */
                if (bytes_left > NET_MAX_BUFFER_SIZE)
                {
                    buf_ptr->data_len = NET_MAX_BUFFER_SIZE; 
                    bytes_left -= NET_MAX_BUFFER_SIZE;

                    /* Do the copy. */
                    memcpy(buf_ptr->data_ptr, (UINT8 *)et_data_ptr,
                           buf_ptr->data_len);

                    /* Advance data ptr to next block start! */
                    et_data_ptr += NET_MAX_BUFFER_SIZE; 
                }
                else
                {
                    buf_ptr->data_len = bytes_left; 
                    bytes_left = 0; 

                    /* Do the copy. */
                    memcpy(buf_ptr->data_ptr,
                           (UINT8 *)et_data_ptr,
                           buf_ptr->data_len);
                }

            } /* END:  while (bytes_left > 0)  */
        } /* END: else (more than one NET Buffer needed)   */

        if (!Hisr_Activated)
        {
            Hisr_Activated = 1;


            /* Activate the Receive HISR. */
            NU_Activate_HISR (&Ether_Rcv);
        }
        return (NU_SUCCESS);
    }
}  /* END */

/************************************************************************
* FUNCTION                                                             
*                                                                      
*        Rtl8019_Ioctl                                        
*                                                                      
* DESCRIPTION                                                          
*                                                                      
*        Called by group management functions to add or remove an
*        address from the CAM.                             
*                                                                      
* AUTHOR                                                               
*                                                                      
*        MeterChen                                      
*                                                                      
* INPUTS                                                               
*                                                                      
*        DV_DEVICE_ENTRY       *dev          Pointer to the device 
*                                            structure for this device.
*                                                                      
*        INT                   option        Option to perform (Add or
*                                             Delete).                                                              
*                                                                      
*        DV_REQ                *d_req        Pointer to request structure.
*                                                                      
* OUTPUTS                                                              
*                                                                      
*        STATUS                (0) NU_SUCCESS                                    
*                             (-1) CAM_FULL
*                                                                      
************************************************************************/

STATUS  Rtl8019_Ioctl(DV_DEVICE_ENTRY *dev, INT option, DV_REQ *d_req)
{
#if 0    
    STATUS          status = NU_SUCCESS;
    UINT32          slot = 0x00000002;
    UINT8           entry = 1;
    UINT8           multi_addr[6] = {0,0,0,0,0,0};
    UINT32          CamEnReg;
  

    /* Convert the IP address to a multicast ethernet address. */
    NET_MAP_IP_TO_ETHER_MULTI(&d_req->dvr_addr, multi_addr);
    
    switch (option) 
    {
    case DEV_ADDMULTI:
        CamEnReg = CAMEN;

        /* Compare each bit in the CAMEN to find an available entry. */
        while (CamEnReg & (slot & 0x000FFFFF))
        {
            slot <<= 1;
            entry++;
        }
            
        if (slot & 0x000FFFFE)
        {
            /* Join the ethernet multicast group. */
            status = NET_Add_Multi(dev, d_req);

            /* A status of NU_RESET means the operation was a success. */
            if (status == NU_RESET)
            {
                KS5_CamWrite(entry, multi_addr);
            }
            else
                break;
            
            /* Enable the new address. */
            CAMEN = (CamEnReg | slot);
            status = NU_SUCCESS;
        }
        else
            /* Only 21 entries allowed. */
            status = CAM_FULL;
        break;

    case DEV_DELMULTI :

        /* Convert the IP address to a multicast ethernet address. */
        NET_MAP_IP_TO_ETHER_MULTI(&d_req->dvr_addr, multi_addr);

        /* Delete the ethernet multicast group. */
        status = NET_Del_Multi(dev, d_req);

        /* A status of NU_RESET means the operation was a success. */
        if (status == NU_RESET)
        {
            /* Find the multicast entry in the CAM */
            for (entry = 1; memcmp(KS5_CamRead(entry), multi_addr, 6) != 0
                 && entry <= 20; entry++)
            {
                 slot <<= 1;
            }
        
            /* Address not found */
            if (entry > 20)
                break;
            else
            {
                /* Address found... just disable its CAMEN slot. */
                CAMEN = (CamEnReg & ~slot);
                status = NU_SUCCESS;
            }
            break;
        }

        /* Fall through if NET_Del_Multi() failed. */
                
    default :
        
        status = NU_INVAL;
        break;

    }
    return (status);
#endif

}


⌨️ 快捷键说明

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