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++; } }
_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 */
/*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); } }