2 * Network buffer code based on the MCF523x examples from Freescale.
4 * File: $Id: nbuf.c,v 1.2 2006/08/31 22:28:21 wolti Exp $
7 /* ------------------------ Platform includes ----------------------------- */
13 /* ------------------------ Static variables ------------------------------ */
15 /* Buffer descriptor indexes */
16 static uint8 tx_bd_idx;
17 static uint8 rx_bd_idx;
19 /* Buffer Descriptors -- must be aligned on a 4-byte boundary but a
20 * 16-byte boundary is recommended. */
21 static nbuf_t tx_nbuf[sizeof( nbuf_t ) * NUM_TXBDS] ATTR_FECMEM;
22 static nbuf_t rx_nbuf[sizeof( nbuf_t ) * NUM_RXBDS] ATTR_FECMEM;
24 /* Data Buffers -- must be aligned on a 16-byte boundary. */
25 static uint8 tx_buf[TX_BUFFER_SIZE * NUM_TXBDS] ATTR_FECMEM;
26 static uint8 rx_buf[RX_BUFFER_SIZE * NUM_RXBDS] ATTR_FECMEM;
28 /* ------------------------ Start implementation -------------------------- */
35 /* Initialize receive descriptor ring */
36 for( i = 0; i < NUM_RXBDS; i++ )
38 rx_nbuf[i].status = RX_BD_E;
39 rx_nbuf[i].length = 0;
40 rx_nbuf[i].data = &rx_buf[i * RX_BUFFER_SIZE];
43 /* Set the Wrap bit on the last one in the ring */
44 rx_nbuf[NUM_RXBDS - 1].status |= RX_BD_W;
46 /* Initialize transmit descriptor ring */
47 for( i = 0; i < NUM_TXBDS; i++ )
49 tx_nbuf[i].status = TX_BD_L | TX_BD_TC;
50 tx_nbuf[i].length = 0;
51 tx_nbuf[i].data = &tx_buf[i * TX_BUFFER_SIZE];
54 /* Set the Wrap bit on the last one in the ring */
55 tx_nbuf[NUM_TXBDS - 1].status |= TX_BD_W;
57 /* Initialize the buffer descriptor indexes */
58 tx_bd_idx = rx_bd_idx = 0;
64 /********************************************************************/
66 nbuf_get_start( uint8 direction )
69 * Return the address of the first buffer descriptor in the ring.
70 * This routine is needed by the FEC of the MPC860T , MCF5282, and MCF523x
71 * in order to write the Rx/Tx descriptor ring start registers
76 return ( uint32 ) rx_nbuf;
79 return ( uint32 ) tx_nbuf;
84 /********************************************************************/
88 /* This routine alters shared data. Disable interrupts! */
89 int old_ipl = asm_set_ipl( 6 );
91 /* Return a pointer to the next empty Rx Buffer Descriptor */
95 /* Check to see if the ring of BDs is full */
96 if( rx_nbuf[i].status & RX_BD_INUSE )
99 /* Mark the buffer as in use */
100 rx_nbuf[i].status |= RX_BD_INUSE;
102 /* increment the circular index */
103 rx_bd_idx = ( uint8 ) ( ( rx_bd_idx + 1 ) % NUM_RXBDS );
105 /* Restore previous IPL */
106 asm_set_ipl( old_ipl );
112 /********************************************************************/
116 /* This routine alters shared data. Disable interrupts! */
117 int old_ipl = asm_set_ipl( 6 );
119 /* Return a pointer to the next empty Tx Buffer Descriptor */
122 /* Check to see if ring of BDs is full */
123 if( ( tx_nbuf[i].status & TX_BD_INUSE ) || ( tx_nbuf[i].status & TX_BD_R ) )
126 /* Mark the buffer as Ready (in use) */
127 /* FEC must set R bit in transmit routine */
128 tx_nbuf[i].status |= TX_BD_INUSE;
130 /* increment the circular index */
131 tx_bd_idx = ( uint8 ) ( ( tx_bd_idx + 1 ) % NUM_TXBDS );
133 /* Restore previous IPL */
134 asm_set_ipl( old_ipl );
140 /********************************************************************/
142 nbuf_rx_release( nbuf_t * pNbuf )
144 /* This routine alters shared data. Disable interrupts! */
145 int old_ipl = asm_set_ipl( 6 );
147 /* Mark the buffer as empty and not in use */
148 pNbuf->status |= RX_BD_E;
149 pNbuf->status &= ~RX_BD_INUSE;
151 /* Restore previous IPL */
152 asm_set_ipl( old_ipl );
155 /********************************************************************/
157 nbuf_tx_release( nbuf_t * pNbuf )
159 /* This routine alters shared data. Disable interrupts! */
160 int old_ipl = asm_set_ipl( 6 );
162 /* Mark the buffer as not in use */
163 pNbuf->status &= ~TX_BD_INUSE;
165 /* Restore previous IPL */
166 asm_set_ipl( old_ipl );
169 /********************************************************************/
171 nbuf_rx_next_ready( )
173 /****************************************************************
174 This function checks the EMPTY bit of the next Rx buffer to be
175 allocated. If the EMPTY bit is cleared, then the next buffer in
176 the ring has been filled by the FEC and has not already been
177 allocated and passed up the stack. In this case, the next buffer
178 in the ring is ready to be allocated. Otherwise, the buffer is
179 either empty or not empty but still in use by a higher level
180 protocol. The FEC receive routine uses this function to determine
181 if multiple buffers where filled by the FEC during a single
183 ****************************************************************/
185 return ( !( rx_nbuf[rx_bd_idx].status & RX_BD_E ) );