Update MAC drivers so they use a uIP specific zero copy mechanism.

pull/4/head
Richard Barry 14 years ago
parent 5fbf3ab27e
commit c1d000b654

@ -9,6 +9,11 @@
*
******************************************************************************/
/*
* NOTE: This driver has been roughly modified specifically for use with the
* uIP stack. It is no longer a generic driver.
*/
#ifdef __cplusplus
extern "C" {
#endif
@ -54,11 +59,11 @@ extern "C" {
/* Allocating this many buffers will always ensure there is one free as, even
though TX_RING_SIZE is set to two, the two Tx descriptors will only ever point
to the same buffer. */
#define macNUM_BUFFERS RX_RING_SIZE + TX_RING_SIZE + 1
#define macNUM_BUFFERS RX_RING_SIZE + TX_RING_SIZE + 2
#define macBUFFER_SIZE 1488
/***************************************************************/
MAC_instance_t g_mss_mac __attribute__((aligned(4)));
MAC_instance_t g_mss_mac;
/**************************** INTERNAL DATA ***********************************/
#define ERROR_MESSAGE_COUNT 8
@ -78,15 +83,16 @@ static const int8_t ErrorMessages[][MAX_ERROR_MESSAGE_WIDTH] = {
/*
* Null variables
*/
static MAC_instance_t* NULL_instance;
static uint8_t* NULL_buffer;
static MSS_MAC_callback_t NULL_callback;
/* Declare the uip_buf as a pointer, rather than the traditional array, as this
is a zero copy driver. uip_buf just gets set to whichever buffer is being
processed. */
unsigned char *uip_buf = NULL;
/**************************** INTERNAL FUNCTIONS ******************************/
static int32_t MAC_test_instance( void );
static int32_t MAC_dismiss_bad_frames( void );
static int32_t MAC_send_setup_frame( void );
@ -109,11 +115,16 @@ static void MAC_release_buffer( unsigned char *pcBufferToRelease );
#error This uIP Ethernet driver required TX_RING_SIZE to be set to 2
#endif
/* Buffers that will dynamically be allocated to/from the Tx and Rx descriptors. */
static unsigned char ucMACBuffers[ macNUM_BUFFERS ][ macBUFFER_SIZE ] __attribute__((aligned(4)));
/* Buffers that will dynamically be allocated to/from the Tx and Rx descriptors.
The union is used for alignment only. */
static union xMAC_BUFFERS
{
unsigned long ulAlignmentVariable; /* For alignment only, not used anywhere. */
unsigned char ucBuffer[ macNUM_BUFFERS ][ macBUFFER_SIZE ];
} xMACBuffers;
/* Each array position indicated whether or not the buffer of the same index
is currently allocated to a descriptor (pdFALSE) or is free for use (pdTRUE). */
/* Each array position indicates whether or not the buffer of the same index
is currently allocated to a descriptor (pdTRUE) or is free for use (pdFALSE). */
static unsigned char ucMACBufferInUse[ macNUM_BUFFERS ] = { 0 };
/***************************************************************************//**
@ -169,7 +180,7 @@ MSS_MAC_init
/* Allocate a buffer to the descriptor, then mark the buffer as in use
(not free). */
g_mss_mac.rx_descriptors[a].buffer_1 = ( unsigned long ) &( ucMACBuffers[ a ][ 0 ] );
g_mss_mac.rx_descriptors[a].buffer_1 = ( unsigned long ) &( xMACBuffers.ucBuffer[ a ][ 0 ] );
ucMACBufferInUse[ a ] = pdTRUE;
}
g_mss_mac.rx_descriptors[RX_RING_SIZE-1].descriptor_1 |= RDES1_RER;
@ -189,8 +200,6 @@ MSS_MAC_init
MAC_BITBAND->CSR0_BAR = (uint32_t)BUS_ARBITRATION_SCHEME;
/* Fixed settings */
/* No automatic polling */
MAC->CSR0 = MAC->CSR0 &~ CSR0_TAP_MASK;
/* No space between descriptors */
MAC->CSR0 = MAC->CSR0 &~ CSR0_DSL_MASK;
/* General-purpose timer works in continuous mode */
@ -198,11 +207,13 @@ MSS_MAC_init
/* Start general-purpose */
MAC->CSR11 = (MAC->CSR11 & ~CSR11_TIM_MASK) | (0x0000FFFFuL << CSR11_TIM_SHIFT);
/* Disable promiscuous mode */
MAC_BITBAND->CSR6_PR = 0u;
/* Disable transmit interrupt mitigation. */
MAC->CSR11 = ( MAC->CSR11 & ~CSR11_TT_MASK );
MAC->CSR11 = ( MAC->CSR11 & ~CSR11_NTP_MASK );
/* Enable store and forward */
MAC_BITBAND->CSR6_SF = 1u;
/* Automatic Tx descriptor polling. */
MAC->CSR0 = ( MAC->CSR0 & ~CSR0_TAP_MASK );
MAC->CSR0 = ( MAC->CSR0 | ( 0x01 << CSR0_TAP_SHIFT ) );
/* Set descriptors */
MAC->CSR3 = (uint32_t)&(g_mss_mac.rx_descriptors[0].descriptor_0);
@ -211,6 +222,10 @@ MSS_MAC_init
/* enable normal interrupts */
MAC_BITBAND->CSR7_NIE = 1u;
/* Set default MAC address and reset mac filters */
MAC_memcpy( g_mss_mac.mac_address, mac_address, 6u );
MSS_MAC_set_mac_address((uint8_t *)mac_address);
/* Detect PHY */
if( g_mss_mac.phy_address > MSS_PHY_ADDRESS_MAX )
{
@ -221,19 +236,9 @@ MSS_MAC_init
/* Reset PHY */
PHY_reset();
/* Set flags */
g_mss_mac.flags = FLAG_MAC_INIT_DONE | FLAG_PERFECT_FILTERING;
/* Configure chip according to PHY status */
MSS_MAC_auto_setup_link();
/* Set default MAC address and reset mac filters */
MAC_memcpy( g_mss_mac.mac_address, mac_address, 6u );
MSS_MAC_set_mac_filters( 0u, NULL_buffer );
MAC_BITBAND->CSR6_RA = 1; /* Receive all. */
MAC_BITBAND->CSR6_PR = 1; /* Promiscuous mode. */
MSS_MAC_set_mac_address((uint8_t *)mac_address);
/* Ensure uip_buf starts by pointing somewhere. */
uip_buf = MAC_obtain_buffer();
}
@ -264,8 +269,6 @@ MSS_MAC_configure
{
int32_t ret;
configASSERT( MAC_test_instance() == MAC_OK );
ret = MAC_stop_transmission();
configASSERT( ret == MAC_OK );
@ -327,8 +330,6 @@ MSS_MAC_get_configuration( void )
{
uint32_t configuration;
configASSERT( MAC_test_instance() == MAC_OK );
configuration = 0u;
if( MAC_BITBAND->CSR6_RA != 0u ) {
configuration |= MSS_MAC_CFG_RECEIVE_ALL;
@ -404,9 +405,6 @@ MSS_MAC_tx_packet
uint32_t desc;
unsigned long ulDescriptor;
int32_t error = MAC_OK;
extern unsigned char *uip_buf;
configASSERT( MAC_test_instance() == MAC_OK );
configASSERT( uip_buf != NULL_buffer );
@ -419,28 +417,34 @@ MSS_MAC_tx_packet
/* Check if second descriptor is free, if it is then the first must
also be free. */
if(((g_mss_mac.tx_descriptors[ 1 ].descriptor_0) & TDES0_OWN) == TDES0_OWN )
if( ( ( (g_mss_mac.tx_descriptors[ 0 ].descriptor_0) & TDES0_OWN) == TDES0_OWN ) || ( ( (g_mss_mac.tx_descriptors[ 1 ].descriptor_0) & TDES0_OWN) == TDES0_OWN ) )
{
error = MAC_BUFFER_IS_FULL;
/* Check the buffers pointed to by the Tx descriptors, just in case a Tx
interrupt has been missed and a free buffer remains marked as in use. */
MSS_MAC_CheckTxBufferStatus();
}
if( error == MAC_OK )
{
/* Assumed TX_RING_SIZE == 2. */
/* Assumed TX_RING_SIZE == 2. A #error directive checks this is the
case. */
for( ulDescriptor = 0; ulDescriptor < TX_RING_SIZE; ulDescriptor++ )
{
g_mss_mac.tx_descriptors[ ulDescriptor ].descriptor_1 = 0u;
g_mss_mac.tx_descriptors[ g_mss_mac.tx_desc_index ].descriptor_1 = 0u;
if( (g_mss_mac.flags & FLAG_CRC_DISABLE) != 0u ) {
g_mss_mac.tx_descriptors[ ulDescriptor ].descriptor_1 |= TDES1_AC;
g_mss_mac.tx_descriptors[ g_mss_mac.tx_desc_index ].descriptor_1 |= TDES1_AC;
}
/* Every buffer can hold a full frame so they are always first and last
descriptor */
g_mss_mac.tx_descriptors[ ulDescriptor ].descriptor_1 |= TDES1_LS | TDES1_FS | TDES1_IC;
g_mss_mac.tx_descriptors[ g_mss_mac.tx_desc_index ].descriptor_1 |= TDES1_LS | TDES1_FS | TDES1_IC;
/* set data size */
g_mss_mac.tx_descriptors[ ulDescriptor ].descriptor_1 |= usLength;
g_mss_mac.tx_descriptors[ g_mss_mac.tx_desc_index ].descriptor_1 |= usLength;
/* reset end of ring */
g_mss_mac.tx_descriptors[TX_RING_SIZE-1].descriptor_1 |= TDES1_TER;
@ -451,10 +455,10 @@ MSS_MAC_tx_packet
}
/* The data buffer is assigned to the Tx descriptor. */
g_mss_mac.tx_descriptors[ ulDescriptor ].buffer_1 = ( unsigned long ) uip_buf;
g_mss_mac.tx_descriptors[ g_mss_mac.tx_desc_index ].buffer_1 = ( unsigned long ) uip_buf;
/* update counters */
desc = g_mss_mac.tx_descriptors[ ulDescriptor ].descriptor_0;
desc = g_mss_mac.tx_descriptors[ g_mss_mac.tx_desc_index ].descriptor_0;
if( (desc & TDES0_LO) != 0u ) {
g_mss_mac.statistics.tx_loss_of_carrier++;
}
@ -474,25 +478,22 @@ MSS_MAC_tx_packet
(desc >> TDES0_CC_OFFSET) & TDES0_CC_MASK;
/* Give ownership of descriptor to the MAC */
g_mss_mac.tx_descriptors[ ulDescriptor ].descriptor_0 = RDES0_OWN;
}
/* Start transmission */
MAC_start_transmission();
g_mss_mac.tx_desc_index = 0;
/* transmit poll demand */
MAC->CSR1 = 1u;
}
g_mss_mac.tx_descriptors[ g_mss_mac.tx_desc_index ].descriptor_0 = RDES0_OWN;
g_mss_mac.tx_desc_index = (g_mss_mac.tx_desc_index + 1u) % (uint32_t)TX_RING_SIZE;
MAC_start_transmission();
MAC->CSR1 = 1u;
}
}
if (error == MAC_OK)
{
/* The buffer uip_buf was pointing to is now under the control of the
MAC (it is being transmitted). Set uip_buf to point to a free buffer. */
uip_buf = MAC_obtain_buffer();
error = (int32_t)usLength;
/* The buffer pointed to by uip_buf is now assigned to a Tx descriptor.
Find anothere free buffer for uip_buf. */
uip_buf = MAC_obtain_buffer();
}
else
{
@ -517,8 +518,6 @@ MSS_MAC_rx_pckt_size
)
{
int32_t retval;
configASSERT( MAC_test_instance() == MAC_OK );
MAC_dismiss_bad_frames();
if( (g_mss_mac.rx_descriptors[ g_mss_mac.rx_desc_index ].descriptor_0 & RDES0_OWN) != 0u )
@ -554,8 +553,6 @@ MSS_MAC_rx_packet
{
uint16_t frame_length=0u;
configASSERT( MAC_test_instance() == MAC_OK );
MAC_dismiss_bad_frames();
if( (g_mss_mac.rx_descriptors[ g_mss_mac.rx_desc_index ].descriptor_0 & RDES0_OWN) == 0u )
@ -619,8 +616,6 @@ MSS_MAC_rx_packet_ptrset
uint16_t frame_length = 0u;
int8_t exit = 0;
configASSERT( MAC_test_instance() == MAC_OK );
configASSERT( (time_out == MSS_MAC_BLOCKING) ||
(time_out == MSS_MAC_NONBLOCKING) ||
((time_out >= 1) && (time_out <= 0x01000000UL)) );
@ -684,8 +679,6 @@ MSS_MAC_link_status
{
uint32_t link;
configASSERT( MAC_test_instance() == MAC_OK );
link = PHY_link_status();
if( link == MSS_MAC_LINK_STATUS_LINK ) {
link |= PHY_link_type();
@ -711,7 +704,6 @@ MSS_MAC_auto_setup_link
)
{
int32_t link;
configASSERT( MAC_test_instance() == MAC_OK );
PHY_auto_negotiate();
@ -746,7 +738,6 @@ MSS_MAC_set_mac_address
const uint8_t *new_address
)
{
configASSERT( MAC_test_instance() == MAC_OK );
/* Check if the new address is unicast */
configASSERT( (new_address[0]&1) == 0 );
@ -782,8 +773,6 @@ MSS_MAC_get_mac_address
uint8_t *address
)
{
configASSERT( MAC_test_instance() == MAC_OK );
MAC_memcpy( address, g_mss_mac.mac_address, 6u );
}
@ -801,7 +790,6 @@ MSS_MAC_set_mac_filters
const uint8_t *filters
)
{
configASSERT( MAC_test_instance() == MAC_OK );
configASSERT( (filter_count==0) || (filters != NULL_buffer) );
/* Check if the mac addresses is multicast */
{
@ -857,8 +845,6 @@ void EthernetMAC_IRQHandler( void )
uint32_t events;
uint32_t intr_status;
configASSERT( MAC_test_instance() == MAC_OK );
events = 0u;
intr_status = MAC->CSR5;
@ -901,8 +887,6 @@ MSS_MAC_set_callback
MSS_MAC_callback_t listener
)
{
configASSERT( MAC_test_instance() == MAC_OK );
/* disable tx and rx interrupts */
MAC_BITBAND->CSR7_RIE = 0u;
MAC_BITBAND->CSR7_TIE = 0u;
@ -935,8 +919,6 @@ MSS_MAC_last_error
int8_t error_msg_nb;
const int8_t* returnvalue;
configASSERT( MAC_test_instance() == MAC_OK );
error_msg_nb = -(g_mss_mac.last_error);
if( error_msg_nb >= ERROR_MESSAGE_COUNT ) {
returnvalue = unknown_error;
@ -962,7 +944,6 @@ MSS_MAC_get_statistics
)
{
uint32_t returnval = 0u;
configASSERT( MAC_test_instance() == MAC_OK );
switch( stat_id ) {
case MSS_MAC_RX_INTERRUPTS:
@ -1029,31 +1010,6 @@ MSS_MAC_get_statistics
/**************************** INTERNAL FUNCTIONS ******************************/
/***************************************************************************//**
* Checks if instace is valid.
*/
static int32_t
MAC_test_instance
(
void
)
{
uint32_t val1;
uint32_t val2;
int32_t retval = MAC_WRONG_PARAMETER;
val1 = MAC->CSR3;
val2 = MAC->CSR4;
if( (&g_mss_mac != NULL_instance) &&
((g_mss_mac.flags & FLAG_MAC_INIT_DONE) != 0u) &&
( val1 == (uint32_t)g_mss_mac.rx_descriptors) &&
(val2 == (uint32_t)g_mss_mac.tx_descriptors ) )
{
retval = MAC_OK;
}
return retval;
}
/***************************************************************************//**
* Prepares current rx descriptor for receiving.
@ -1414,10 +1370,6 @@ static void MAC_memset_All(MAC_instance_t *s, uint32_t c)
MAC_memset( s->mac_address, (uint8_t)c, 6u );
MAC_memset( s->mac_filter_data, (uint8_t)c, 90u );
s->phy_address = (uint8_t)c;
// for(count = 0; count<RX_RING_SIZE ;count++)
// {
// MAC_memset(s->rx_buffers[count], (uint8_t)c, (MSS_RX_BUFF_SIZE + 4u) );
// }
s->rx_desc_index =c;
for(count = 0; count<RX_RING_SIZE ;count++)
{
@ -1445,10 +1397,6 @@ static void MAC_memset_All(MAC_instance_t *s, uint32_t c)
s->statistics.tx_no_carrier = c;
s->statistics.tx_underflow_error = c;
s->time_out_value = c;
// for(count = 0; count < TX_RING_SIZE ;count++)
// {
// MAC_memset( s->tx_buffers[count], (uint8_t)c, MSS_TX_BUFF_SIZE );
// }
s->tx_desc_index = c;
for(count = 0; count < TX_RING_SIZE ;count++)
{
@ -1475,25 +1423,42 @@ static void MAC_memcpy(uint8_t *dest, const uint8_t *src, uint32_t n)
}
}
void MSS_MAC_TxBufferCompleted( void )
/***************************************************************************//**
* Check the buffers assigned to the Tx descriptors to ensure that none remain
* marked as in use even though the Tx has completed. This could happen if a
* Tx interrupt was missed.
*
*/
void MSS_MAC_CheckTxBufferStatus( void )
{
unsigned char *pxTransmittedBuffer;
long lDescriptor, lIndex;
/* Was it the second transmission that has completed? */
if( ( g_mss_mac.tx_descriptors[ 1 ].descriptor_0 & TDES0_OWN ) == 0UL )
for( lDescriptor = 1; lDescriptor < TX_RING_SIZE; lDescriptor++ )
{
pxTransmittedBuffer = ( unsigned char * ) g_mss_mac.tx_descriptors[ 1 ].buffer_1;
if( ( g_mss_mac.tx_descriptors[ lDescriptor ].descriptor_0 & TDES0_OWN ) == 0UL )
{
pxTransmittedBuffer = ( unsigned char * ) g_mss_mac.tx_descriptors[ lDescriptor ].buffer_1;
/* The buffer has been transmitted and is no longer in use. */
MAC_release_buffer( pxTransmittedBuffer );
}
else
{
// configASSERT( 0 );
for( lIndex = 0; lIndex < macNUM_BUFFERS; lIndex++ )
{
if( pxTransmittedBuffer == &( xMACBuffers.ucBuffer[ lIndex ][ 0 ] ) )
{
ucMACBufferInUse[ lIndex ] = pdFALSE;
}
}
}
}
}
static unsigned char *MAC_obtain_buffer( void )
/***************************************************************************//**
* Look through the array of buffers until one is found that is free for use -
* that is, not currently assigned to an Rx or a Tx descriptor. Mark the buffer
* as in use, then return its address.
*
* @return a pointer to a free buffer.
*/
unsigned char *MAC_obtain_buffer( void )
{
long lIndex;
unsigned char *pcReturn = NULL;
@ -1504,7 +1469,7 @@ unsigned char *pcReturn = NULL;
{
if( ucMACBufferInUse[ lIndex ] == pdFALSE )
{
pcReturn = &( ucMACBuffers[ lIndex ][ 0 ] );
pcReturn = &( xMACBuffers.ucBuffer[ lIndex ][ 0 ] );
ucMACBufferInUse[ lIndex ] = pdTRUE;
break;
}
@ -1514,6 +1479,10 @@ unsigned char *pcReturn = NULL;
return pcReturn;
}
/***************************************************************************//**
* Return a buffer to the list of free buffers, it was in use, but is not now.
*
*/
void MAC_release_buffer( unsigned char *pucBufferToRelease )
{
long lIndex;
@ -1522,7 +1491,7 @@ long lIndex;
it is currently pointing to is marked as being free again. */
for( lIndex = 0; lIndex < macNUM_BUFFERS; lIndex++ )
{
if( pucBufferToRelease == &( ucMACBuffers[ lIndex ][ 0 ] ) )
if( pucBufferToRelease == &( xMACBuffers.ucBuffer[ lIndex ][ 0 ] ) )
{
/* This is the buffer in use, mark it as being free. */
ucMACBufferInUse[ lIndex ] = pdFALSE;
@ -1530,6 +1499,10 @@ long lIndex;
}
}
/* Check the buffers pointed to by the Tx descriptors, just in case a Tx
interrupt has been missed and a free buffer remains marked as in use. */
MSS_MAC_CheckTxBufferStatus();
configASSERT( lIndex < macNUM_BUFFERS );
}

@ -560,23 +560,11 @@ MSS_MAC_get_statistics
mss_mac_statistics_id_t stat_id
);
/*
* Ensure uip_buf is pointing to a valid and free buffer before any transmissions
* initiated by the uIP stack occur.
*/
unsigned char *MSS_MAC_GetTxDescriptor( void );
/*
* A buffer is no longer required by the application. Hand it back to the
* control of the MAC hardware.
*/
void MSS_MAC_ReleaseBuffer( unsigned char *pucBuffer );
/*
* The double Tx has completed. Hand back the Tx buffer to the control of
* the MAC hardware.
*/
void MSS_MAC_TxBufferCompleted( void );
void MSS_MAC_CheckTxBufferStatus( void );
#ifdef __cplusplus
}
#endif

@ -66,12 +66,10 @@ typedef struct {
/* transmit related info: */
uint32_t tx_desc_index; /**< index of the transmit descriptor getting used*/
// uint8_t tx_buffers[TX_RING_SIZE][MSS_TX_BUFF_SIZE];/**< array of transmit buffers*/
MAC_descriptor_t tx_descriptors[TX_RING_SIZE];/**< array of transmit descriptors*/
/* receive related info: */
uint32_t rx_desc_index; /**< index of the receive descriptor getting used*/
// uint8_t rx_buffers[RX_RING_SIZE][MSS_RX_BUFF_SIZE+4];/**< array of receive buffers*/
MAC_descriptor_t rx_descriptors[RX_RING_SIZE];/**< array of receive descriptors*/
uint8_t phy_address; /**< MII address of the connected PHY*/

Loading…
Cancel
Save