Esempio n. 1
0
static void MACNET_process_tx_bds
   (
         /* [IN] the Ethernet state structure */
      ENET_CONTEXT_STRUCT_PTR  enet_ptr
   )
{ 
   MACNET_CONTEXT_STRUCT_PTR   macnet_context_ptr = (MACNET_CONTEXT_STRUCT_PTR) enet_ptr->MAC_CONTEXT_PTR;
   uint_16                     tx_status;
   

   /* Dequeue all transmitted frames */
   while (macnet_context_ptr->AvailableTxBDs < macnet_context_ptr->NumTxBDs) {
      VENET_BD_STRUCT_PTR bd_ptr = &macnet_context_ptr->MACNET_TX_RING_PTR[macnet_context_ptr->LastTxBD];

      _DCACHE_INVALIDATE_MBYTES((pointer)bd_ptr, sizeof(ENET_BD_STRUCT));  

      if (bd_ptr->CONTROL & HOST_TO_BE_SHORT_CONST(ENET_BD_ETHER_TX_READY)) {
         break;
      } /* Endif */

      macnet_context_ptr->TxErrors |= SHORT_BE_TO_HOST(bd_ptr->CONTROL);
      tx_status = macnet_context_ptr->TxErrors;

      /* Record statistics for each frame (not each buffer) */
      if (tx_status & ENET_BD_ETHER_TX_LAST) {
         PCB_PTR pcb_ptr;
         macnet_context_ptr->TxErrors = 0;

         ENET_INC_STATS(COMMON.ST_TX_TOTAL);

         pcb_ptr = macnet_context_ptr->TxPCBS_PTR[macnet_context_ptr->LastTxBD];
         PCB_free(pcb_ptr);
      } 

      if (macnet_context_ptr->FREE_TX_SMALL & (1<<macnet_context_ptr->LastTxBD)) {
         ENET_Enqueue_Buffer((pointer *) &macnet_context_ptr->SMALL_BUFFERS, (pointer)LONG_BE_TO_HOST((uint_32)(bd_ptr->BUFFER)));
         macnet_context_ptr->FREE_TX_SMALL &= ~(1<<macnet_context_ptr->LastTxBD);
      } else if (macnet_context_ptr->FREE_TX & (1<<macnet_context_ptr->LastTxBD)) {
         ENET_Enqueue_Buffer((pointer *) &macnet_context_ptr->TX_BUFFERS, (pointer)LONG_BE_TO_HOST((uint_32)(bd_ptr->BUFFER)));
         macnet_context_ptr->FREE_TX &= ~(1<<macnet_context_ptr->LastTxBD);
      }      
      BD_INC(macnet_context_ptr->LastTxBD,macnet_context_ptr->NumTxBDs);
      macnet_context_ptr->AvailableTxBDs++;

   } 
} 
Esempio n. 2
0
_mqx_int _io_usb_mfs_open_internal
   (
   IO_USB_MFS_STRUCT_PTR            info_ptr,
   CLASS_CALL_STRUCT_PTR            ccs_ptr 
   )
{ /* Body */
   uint_32     i;
   USB_STATUS error;
   REQ_SENSE_DATA_FORMAT sense;


   error = usb_mass_ufi_inquiry(&info_ptr->COMMAND, (uchar_ptr) &info_ptr->INQUIRY_DATA, sizeof(INQUIRY_DATA_FORMAT));

   if ((error!=MQX_OK) && (error!=USB_STATUS_TRANSFER_QUEUED)) {
      return IO_ERROR_INQUIRE;
   } /* Endif */

   if (_lwsem_wait_ticks(&info_ptr->COMMAND_DONE, USBCFG_MFS_LWSEM_TIMEOUT) != MQX_OK) {

   /* Send the call now */

      /* Wait for the completion */
      usb_mass_ufi_cancel(&info_ptr->COMMAND);
      return IO_ERROR_TIMEOUT;
   } /* Endif */


   if (info_ptr->COMMAND_STATUS != MQX_OK) {
      return IO_ERROR_INQUIRE;
   } /* Endif */

   for (i = 0; i < USBCFG_MFS_MAX_RETRIES; i++)
   {
      if (i) {
         /* Delay for a user-specified amount of time */
         _time_delay_ticks(USBCFG_MFS_OPEN_READ_CAPACITY_RETRY_DELAY);
      }
      
      /* Send the call now */
      error = usb_mass_ufi_read_capacity(&info_ptr->COMMAND, (uchar_ptr) &info_ptr->CAPACITY,
         sizeof(MASS_STORAGE_READ_CAPACITY_CMD_STRUCT_INFO));

      if ((error!=MQX_OK) && (error!=USB_STATUS_TRANSFER_QUEUED)) {
         return IO_ERROR_READ;
      } /* Endif */

      if (_lwsem_wait_ticks(&info_ptr->COMMAND_DONE, USBCFG_MFS_LWSEM_TIMEOUT) != MQX_OK) {
         usb_mass_ufi_cancel(&info_ptr->COMMAND);
         return IO_ERROR_TIMEOUT;
      } /* Endif */
      
      if (info_ptr->COMMAND_STATUS == MQX_OK)
         break;
      
      
      error = usb_mass_ufi_request_sense(&info_ptr->COMMAND, (char_ptr)&sense, sizeof(REQ_SENSE_DATA_FORMAT));

      if ((error!=MQX_OK) && (error!=USB_STATUS_TRANSFER_QUEUED)) {
         return IO_ERROR_READ;
      }

      if (_lwsem_wait_ticks(&info_ptr->COMMAND_DONE, USBCFG_MFS_LWSEM_TIMEOUT) != MQX_OK) {
         usb_mass_ufi_cancel(&info_ptr->COMMAND);
         return IO_ERROR_TIMEOUT;
      }
   }
   
   if (info_ptr->COMMAND_STATUS == MQX_OK) {
      info_ptr->BCOUNT = LONG_BE_TO_HOST(*(uint_32*)&info_ptr->CAPACITY.BLLBA);
      info_ptr->BLENGTH = LONG_BE_TO_HOST(*(uint_32*)&info_ptr->CAPACITY.BLENGTH);

      /* should read this to support  low level format */
      info_ptr->NUMBER_OF_HEADS   = 0;
      info_ptr->NUMBER_OF_TRACKS  = 0;
      info_ptr->SECTORS_PER_TRACK = 0;

      info_ptr->SIZE_BYTES = info_ptr->BLENGTH * info_ptr->BCOUNT;
   } /* Endif */
   
   return (_mqx_int)info_ptr->COMMAND_STATUS;
} /* Endbody */
Esempio n. 3
0
/*FUNCTION*-------------------------------------------------------------
*
*  Function Name  : MACNET_process_rx_bds
*  Returned Value : void
*  Comments       :
*        Processes received buffers.
*
* NOTE: For MACNET, a frame consists of one or more buffers.
*       For ENET, a packet consists of one or more fragments
*        Therefore, a frame = a packet, and a buffer = a fragment.
*
*
*END*-----------------------------------------------------------------*/
static void MACNET_process_rx_bds
   (
         /* [IN] the Ethernet state structure */
      ENET_CONTEXT_STRUCT_PTR    enet_ptr
   )
{ /* Body */
   MACNET_CONTEXT_STRUCT_PTR  macnet_context_ptr = (MACNET_CONTEXT_STRUCT_PTR) enet_ptr->MAC_CONTEXT_PTR;
   VENET_BD_STRUCT_PTR        bd_ptr;
   PCB_PTR                    pcb_ptr=NULL;
   uint_16                    rx_status;
   uint_32                    i,length;
   int_32                     ilength;
   uchar_ptr                  buffer, small_packet, large_packet;
   boolean                    buffer_is_valid, consumed, first, last;
   
   //_DCACHE_INVALIDATE();    // temporary - I can't find fast actual part of memory for cache invalidation

   /* Dequeue all received buffers (fragments) */
   while (macnet_context_ptr->ActiveRxBDs > 0) {

      bd_ptr = &macnet_context_ptr->MACNET_RX_RING_PTR[macnet_context_ptr->NextRxBD];
      _DCACHE_INVALIDATE_MBYTES((pointer)bd_ptr, sizeof(ENET_BD_STRUCT));  

      if ((bd_ptr->CONTROL & HOST_TO_BE_SHORT_CONST(ENET_BD_ETHER_RX_EMPTY)) != 0) {
         break; // Currently being written to by MII
      }  

      BD_INC(macnet_context_ptr->NextRxBD,macnet_context_ptr->NumRxBDs);
      macnet_context_ptr->ActiveRxBDs--;

      ENET_INC_STATS(COMMON.ST_RX_TOTAL);
      rx_status = SHORT_BE_TO_HOST(bd_ptr->CONTROL);
      length = SHORT_BE_TO_HOST(bd_ptr->LENGTH);
      buffer = (uchar_ptr)LONG_BE_TO_HOST((uint_32)(bd_ptr->BUFFER));
      //buffer = LONG_BE_TO_HOST(bd_ptr->BUFFER);
      
      consumed = FALSE;
      first = macnet_context_ptr->CurrentRxFrag == 0;
      last = TRUE;
      
      // Start by validating the received buffer 
      // a buffer is valid if:
      //   (it is error free) AND ( (it is the first buffer in a frame) OR (it is a subsequent buffer in a frame we want ) )
      // 
      buffer_is_valid = FALSE;
      if (rx_status & ENET_BD_ETHER_RX_TRUNCATED) {
      
         ENET_INC_STATS(ST_RX_RUNT);
     
      } else if (rx_status & ENET_BD_ETHER_RX_LAST_FRAME) {
         
         // Some error bits can only be checked on the last buffer
         
         // Overrun needs to be checked first,  If this bit is 
         // set, the other status bits, M, LG, NO, CR, and CL lose their normal meaning and are zero. This bit 
         // is valid only if the L-bit is set.
         if (rx_status & ENET_BD_ETHER_RX_OVERRUN) {
            ENET_INC_STATS(ST_RX_OVERRUN);
         
         } else if (rx_status & ENET_BD_ETHER_RX_LENGTH_VIOLATION) {
            ENET_INC_STATS(ST_RX_GIANT);
            
         } else if (rx_status & ENET_BD_ETHER_RX_NON_OCTET) {
            ENET_INC_STATS(ST_RX_ALIGN);
            
         } else if (rx_status & ENET_BD_ETHER_RX_CRC_ERROR) {
            ENET_INC_STATS(ST_RX_FCS);
         } else {
            #if BSPCFG_ENABLE_ENET_HISTOGRAM
               uint_32 index = length>> ENET_HISTOGRAM_SHIFT;
               
               if (index < ENET_HISTOGRAM_ENTRIES) {
                  ENET_INC_STATS(RX_HISTOGRAM[index]);
               }
            #endif
         
         
            // Good buffer (with Last bit set). 
            buffer_is_valid = TRUE;
            // Remove CRC and compute buffer length
            ilength = length - (ENET_FRAMESIZE_TAIL + (macnet_context_ptr->CurrentRxFrag * enet_ptr->PARAM_PTR->RX_BUFFER_SIZE));
            
            // The last fragment may contain nothing but part of the CRC. If this is the case, length will be <= 0,
            // and if length < 0, the previous fragment contains part of the CRC, which needs to be removed.
            if (ilength < 0) {
               length = 0;
               if (!first) {
                  macnet_context_ptr->FRAGS[macnet_context_ptr->CurrentRxFrag-1].LENGTH += ilength;
               } else {
                  // Should never get here - would mean we received a really small packet which should have already been
                  // caught above. But if we do, discard it.
                  buffer_is_valid = TRUE;
               }
            } else {
               length = (uint_32) ilength;
            }
                  
         }
         
      }  else {
         // Good buffer (without Last bit set). Can only be processed if we are not currently discarding.
         buffer_is_valid = TRUE;
         last = FALSE;
      }   
      
      
         
      if (!buffer_is_valid) {
         // Was a buffer with an error
         ENET_INC_STATS(COMMON.ST_RX_ERRORS);
         MACNET_discard_current_rx(enet_ptr,macnet_context_ptr,last);
         
      } else {
         // If it is the first buffer in the frame, we have to see if the frame is of interest. 
         if (first) {
            // make sure we don't examine a cached copy of the buffer
            _DCACHE_INVALIDATE_MBYTES(buffer, length);  

            // the frame is of interest if there is a receiver registered for the destination and protocol. We can do this on the first buffer
            // of the frame, since  the ethernet header information always fits in  the first buffer of a frame.
            macnet_context_ptr->CurrentRxECB = ENET_find_receiver(enet_ptr, (ENET_HEADER_PTR) buffer, &length);
         }

         
         // If we have an Rx ECB, it means we want this packet
         if (macnet_context_ptr->CurrentRxECB ) {
            if (!first) {
               // If it is not the first packet, the cache is still valid. We could have put the invalidate before the first "if (first)",
               // but that would mean we may invalidate the cache on buffers that we know we are discarding.
               _DCACHE_INVALIDATE_MBYTES(buffer, length);  
            }            
            
            // Add the packet to the list of fragments in the PCB               
            macnet_context_ptr->FRAGS[macnet_context_ptr->CurrentRxFrag].FRAGMENT = buffer;
            macnet_context_ptr->FRAGS[macnet_context_ptr->CurrentRxFrag].LENGTH = length;
            macnet_context_ptr->CurrentRxFrag++;

            consumed = TRUE;

            // Now, there are three cases:
            //  !l - start or mid frame buffer - store it for later coalecing into a large buffer
            //  !f, l - end of multi-buffer packet - coalece into a large buffer
            //   f, l - single buffer packet - ready to process 
            
            if (!last) { 

               // Not the last frame in the packet. Have to make sure there is room for at least one
               // more fragment. If not, the packet is too large
               if (macnet_context_ptr->CurrentRxFrag >= MACNET_MAX_FRAGS) {
                  MACNET_discard_current_rx(enet_ptr,macnet_context_ptr,last);
                  ENET_INC_STATS(RX_FRAGS_EXCEEDED);
               }                     

            } else {  
               // last buffer (may or may not also be the first buffer) so process it

               // There is a receiver, so need to allocate a receive PCB
               QGET(macnet_context_ptr->RxPCBHead, macnet_context_ptr->RxPCBTail, pcb_ptr);
               if (pcb_ptr) {
                  // allocation successful, initialize new receive PCB
                  pcb_ptr->PRIVATE = (pointer)enet_ptr;
                  pcb_ptr->FREE = MACNET_rx_free;
                  
                  // Check to see if it is a large packet
                  if (!first) {
                     // Coalese
                     large_packet = ENET_Dequeue_Buffer((pointer *)&macnet_context_ptr->LARGE_BUFFERS);
                     
                     if (large_packet) {
                        // need to compute the length of this fragment, because the length on a BD with the L bit set
                        // is not the length of the buffer, it is the length of the frame.
                        pcb_ptr->FRAG[0].FRAGMENT = large_packet;
                        pcb_ptr->FRAG[0].LENGTH = 0;
                        pcb_ptr->FREE = MACNET_rx_free_large;

                        for (i=0;i<macnet_context_ptr->CurrentRxFrag;i++) {
                           if (macnet_context_ptr->FRAGS[i].LENGTH ) {
                              _mem_copy(macnet_context_ptr->FRAGS[i].FRAGMENT, large_packet, macnet_context_ptr->FRAGS[i].LENGTH  );
                              large_packet += macnet_context_ptr->FRAGS[i].LENGTH;
                              pcb_ptr->FRAG[0].LENGTH += macnet_context_ptr->FRAGS[i].LENGTH;
                           }
                           ENET_Enqueue_Buffer((pointer*)&macnet_context_ptr->RX_BUFFERS, macnet_context_ptr->FRAGS[i].FRAGMENT);
                           macnet_context_ptr->FRAGS[i].FRAGMENT = NULL;
                        }
                  
                        ENET_INC_STATS(ST_RX_COPY_LARGE);
                     } else {
                        ENET_INC_STATS(RX_LARGE_BUFFERS_EXHAUSTED);
                     
                        MACNET_discard_current_rx(enet_ptr,macnet_context_ptr,last);
                        QADD(macnet_context_ptr->RxPCBHead, macnet_context_ptr->RxPCBTail, pcb_ptr);
                        pcb_ptr=NULL;
                     }                     
                  
                  // Check to see if it is a small packet
                  } else { 
                     pcb_ptr->FRAG[0].LENGTH = length;
                     pcb_ptr->FRAG[0].FRAGMENT = buffer;
                     if (length < MACNET_SMALL_PACKET_SIZE) {
 
                        small_packet = ENET_Dequeue_Buffer((pointer *)&macnet_context_ptr->SMALL_BUFFERS);
                        
                        if (small_packet) {
                           _mem_copy( macnet_context_ptr->FRAGS[0].FRAGMENT, small_packet, length );

                           pcb_ptr->FRAG[0].FRAGMENT = small_packet;
                           pcb_ptr->FREE = MACNET_rx_free_small;

                           consumed = FALSE;

                           ENET_INC_STATS(ST_RX_COPY_SMALL);
                        }
                     }
                  }
                  
                                    
                  if (pcb_ptr) {  
                     pcb_ptr->FRAG[1].LENGTH = 0;
                     pcb_ptr->FRAG[1].FRAGMENT = NULL;

#if ENETCFG_SUPPORT_PTP
                     if (macnet_context_ptr->PTP_PRIV->PTIMER_PRESENT) 
                     {
                        MACNET_ptp_store_rxstamp(enet_ptr, pcb_ptr, bd_ptr);
                     }
#endif /* ENETCFG_SUPPORT_PTP */
                     // Call the receiver's service function to pass the PCB to the receiver
                     macnet_context_ptr->CurrentRxECB->SERVICE(pcb_ptr, macnet_context_ptr->CurrentRxECB->PRIVATE);

                     // and clear the current ECB and PCB info, as it's gone to the receiver now.
                     macnet_context_ptr->CurrentRxECB = NULL;
                     macnet_context_ptr->CurrentRxFrag = 0;
                  }                  
                  
                  
               } else {

                  // Couldn't get a Receive PCB, so need to discard buffers until last buffer in frame.
                  MACNET_discard_current_rx(enet_ptr,macnet_context_ptr,last);
                  ENET_INC_STATS(RX_PCBS_EXHAUSTED);
               }
            }
         }         
      }
      
      
      if (!consumed) {
         ENET_INC_STATS(COMMON.ST_RX_DISCARDED);
         ENET_Enqueue_Buffer((pointer*)&macnet_context_ptr->RX_BUFFERS, buffer);
      }
   }