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

📄 nnetdrv.c

📁 基于nucleus操作系统的GPRS无线数据传输终端全套源文件。包括支持ARM7的BSP,操作系统
💻 C
📖 第 1 页 / 共 5 页
字号:
    while (interrupt_level >= VNETPRIO) {
        Recv_Thread_Suspended++;
        SuspendThread(Recv_Thread_ID.thread_hdl);
        Recv_Thread_Suspended--;
        continue;
    }

    /* Higher priority ISRs are done.  Raise the priority level to that of the
       virtual network.
    */
    oldlevel = interrupt_level;
    interrupt_level = VNETPRIO;
    In_ISR++;

    /* Initialize the input to the NT network driver. */
    geteventInfo.MemPtr = NDISComMemStart;
    geteventInfo.RingPtr = ItoKval(
                MNT_Header_Ptr->MNT_hdr_cpuDesc[MNT_ID].MNT_cd_pInputRing,
                PMNT_RING,
                NDISComMemStart);

    geteventInfo.Id = MNT_ID;

    /* Retrieve packets until the application closes. */
    do {

        status = DeviceIoControl (hDriver,
                                   IOCTL_GETEVENT,
                                   &geteventInfo,
                                   sizeof(geteventInfo),
                                   NULL,
                                   0,
                                   &dwData,
                                   &ovl);

        /* If a status of success was returned there was a packet waiting.
           Get it.
        */
        if(status)
        {
            /* A packet had was waiting. Call the ISR to retrieve it. */
            (*VectorTable[VNETPRIO])(VNETPRIO);
        }
        /* If the IRP was marked as pending then wait. */
        else if (GetLastError() == ERROR_IO_PENDING)
        {
            In_ISR--;
            interrupt_level = oldlevel;

            /* Wait for a packet to arrive. */
            WaitForSingleObject (hEvt, INFINITE);

            /* Check to see if this thread was restarted because the application
               is closing.  If so get out of the loop. */
            if (VDRV_Driver_Closing)
                break;

            /* A packet has arrived.  Wait until higher priority ISRs are done
               before continueing. */
            while (interrupt_level >= VNETPRIO) {
                Recv_Thread_Suspended++;
                SuspendThread(Recv_Thread_ID.thread_hdl);
                Recv_Thread_Suspended--;
                continue;
            }

            oldlevel = interrupt_level;
            interrupt_level = VNETPRIO;
            In_ISR++;

            /* Invoke the ISR to process the new packet. */
            (*VectorTable[VNETPRIO])(VNETPRIO);

            ResetEvent (hEvt);
        }
        else {

            demo_exit (0);
        }
    } while (1);

} /* end NU_Recv_Packet */

/******************************************************************************
* FUNCTION                                                                   
*                                                                            
*    VDRV_Xmit_Packet                                                        
*                                                                            
* DESCRIPTION                                                                
*                                                                            
*    This function places a packet onto the "physical meduim".  In this case 
*    the physical medium is a common memory area.  Broadcast packets must    
*    be copied to the receive ring of every active MNT process.  Unicast     
*    packets are copied only to the receive ring of the destination MNT      
*    process.                                                                
*                                                                            
* AUTHOR
*
*   Glen Johnson
*
* INPUTS                                                                     
*                                                                            
*    UINT8 *  : pointer to the packet to be sent                             
*    UINT16   : size in bytes of the packet to be sent.                      
*                                                                            
* OUTPUTS                                                                    
*                                                                            
*    sshort   : Returns NU_SUCCESS if ok, else -1                            
*                                                                            
*                                                                            
******************************************************************************/
STATUS VDRV_Xmit_Packet (DV_DEVICE_ENTRY *device, NET_BUFFER *pack_addr)
{
    IOCTL_OUT_RINGGET       ringgetInfo;
    IOCTL_OUT_RINGPUT       ringputInfo;
    IOCTL_OUT_GENEVENT      geneventInfo;
    IOCTL_OUT_MULTI_RINGGET  mRinggetInfo;
    DLAYER                  *dlayer;
    DWORD                   cbReturned;
    LONG                    dest_id;
    INT                     bufferOffset = 0;
    INT                     ringputStatus;
    MNT_BUF_NODE            *buf_node_ptr;
    INT                     status;
    INT                     count = 0, bytes_copied;
    ULONG                   i, successCount;
    MNT_CPU_DESC            *mnt_cpu_ptr;
    NET_BUFFER              *buf_ptr = pack_addr;
   
#ifndef PACKET
    /* Note that the PACKET conditional compilation flag affects not only the
       driver but the Nucleus NET library, as well.  PACKET must be defined in
       the file TARGET.H.
    */
#error PACKET must be defined at compile time.
#endif

#if (INCLUDE_SNMP == NU_TRUE)
    /* Is this a unicast or a non-unicast packet. */
    if (buf_ptr->mem_flags & NET_BCAST)
        SNMP_ifOutNUcastPkts_Inc(device->dev_index);
    else
        SNMP_ifOutUcastPkts_Inc(device->dev_index);
#endif

    /*
     * Check to make sure that the message has the minimum of at least 60
     * bytes long. If not just set the new length, since hardware will do
     * the checksum for the whole block.
     */
    if (pack_addr->mem_total_data_len < 60)
        pack_addr->mem_total_data_len = pack_addr->data_len = 60;

    /* Make sure the packet will fit in a ring buffer. */
    if(pack_addr->mem_total_data_len > MNT_BUFFER_SIZE)
    {
          SNMP_ifOutDiscards_Inc(device->dev_index);

        return -1;
    }

    /* Is this a broadcast or multicast packet?  If so some extra work must be 
       done to make sure that everyone gets it.
    */
    dlayer = (DLAYER *)pack_addr->data_ptr;

    if ( (memcmp(dlayer->dest, NET_Ether_Broadaddr, 6) == 0) || 
          pack_addr->mem_flags & NET_MCAST )
    {


        /* This packet must be broadcast to all active nodes.  This includes
           each active virtual node and the NDIS driver.  The following count
           should include all nodes, including NDIS.  The MNT descriptor at
           index 0 will be NDIS.
        */
        mnt_cpu_ptr = MNT_Header_Ptr->MNT_hdr_cpuDesc;

        for (i = 0; i < VNET_Ncpu; i++)
        {
            /* If this descriptor is active and it is not ours, then count
               it.  Also go ahead and fill in part of the data structure that
               will be used as the output to Multi Ringput.  This will save some
               effort later.
            */
            if ((mnt_cpu_ptr->MNT_cd_active) && (i != MNT_ID))
            {
                /* Fill in the ring ptr field.  This will be used when a ringput
                   is performed. */
                mRingputInfo->Buf[count].RingPtr = ItoKval(
                            mnt_cpu_ptr->MNT_cd_pInputRing,
                            PMNT_RING,
                            NDISComMemStart);

                /* Store the ID for this MNT process.  This will be used later
                   to generate the event that will restart the MNT process. */
                mGeneventOut->MNTID[count] = i;

                count++;
            }

            /* Point to the next CPU descriptor. */
            mnt_cpu_ptr++;
        }

        mRinggetInfo.Count = count;
        mRinggetInfo.MemPtr = NDISComMemStart;
        mRinggetInfo.RingPtr = ItoKval(MNT_Header_Ptr->MNT_hdr_pFreeRing,
                                      PMNT_RING,
                                      NDISComMemStart);

        status = DeviceIoControl (hDriver,
                              (DWORD) IOCTL_MULTI_RINGGET,
                              &mRinggetInfo,
                              sizeof(IOCTL_OUT_MULTI_RINGGET),
                              mRinggetInput,
                              sizeof(ULONG) * (1 + mRinggetInfo.Count),
                              &cbReturned,
                              0);

        /* If a status of failure is returned and no buffers were allocated,
           then return failure.  Note that it is possible for failure to be
           returned and some (not all) buffers were also allocated.  In the
           later case we want to process those buffers that were allocated.
           Otherwise, they will be lost.
        */
        if ( (!status) && (!mRinggetInput->Count) )
        {
            SNMP_ifOutErrors_Inc(device->dev_index);

            /* This is a complete failure, no buffers were allocated. */
            NERRS_Log_Error (NERR_FATAL, __FILE__, __LINE__);
            return -1;
        }
        else if (mRinggetInput->Count < mRinggetInfo.Count)
        {
            /* This was a partial failure.  Some buffers were allocated.  Go
               ahead and process those that were allocated and log an error
               message.
            */
        }

        for (i=0; i < mRinggetInput->Count; i++)
        {
            buf_node_ptr = ItoKval(mRinggetInput->BuffOffset[i],
                                   PMNT_BUF_NODE,
                                   CommonMemPtr);

            /* Go ahead and fill in part of the structure that will be used as
               input to MULTI_RINGPUT.
            */
            mRingputInfo->Buf[i].BuffOffset = mRinggetInput->BuffOffset[i];

            /* Copy the packet into the buffer chain. */

            /* Do the parent buffer first */
            memcpy((CHAR *)CommonMemPtr + (ULONG)buf_node_ptr->MNT_b_addr,
                buf_ptr->data_ptr, buf_ptr->data_len);

            /* Update the bytes copied. */
            bytes_copied = buf_ptr->data_len;

            /* Loop through the chain if needed and copy all buffers. */
            while (buf_ptr->next_buffer != NU_NULL)
            {
                /* Move to the next buffer in the chain */
                buf_ptr = buf_ptr->next_buffer;

                /* Copy the data */
                memcpy((CHAR *)CommonMemPtr + (ULONG)buf_node_ptr->MNT_b_addr + bytes_copied,
                    buf_ptr->mem_packet, buf_ptr->data_len);

                /* Update the bytes copied. */
                bytes_copied += buf_ptr->data_len;

            } /* end while there are buffers in the chain */

            buf_node_ptr -> MNT_b_len = (UINT16) pack_addr->mem_total_data_len;

            /* Reset the buffer pointer */
            buf_ptr = pack_addr;
        }

        /* Initialize the output to MULTI_RINGPUT.  Recall that the array of MNT
           ID's and the array of MNT_RING ptrs were filled in up above.
        */
        mRingputInfo->MemPtr = NDISComMemStart;
        mRingputInfo->Count = mRinggetInput->Count;

        status = DeviceIoControl (hDriver,
                              (DWORD) IOCTL_MULTI_RINGPUT,
                              mRingputInfo,
                              sizeof(ULONG) * (2 + (2 * mRingputInfo->Count)),
                              &successCount,
                              sizeof(ULONG),
                              &cbReturned,
                              0);

        /* successCount now contains the number of buffers that were successfully
           put.  Make sure all of them were put back. */
        if(successCount < mRingputInfo->Count)
        {

⌨️ 快捷键说明

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