mirror of
https://gitlab.rtems.org/rtems/rtos/rtems.git
synced 2025-12-05 15:15:44 +00:00
Patch from Emmanuel Raguet <raguet@crf.canon.fr>:
After some good comments from Eric Norum [thanks, Eric !],
I have added some modifications to my previous driver patch :
- wait for transmitter ready before sending a packet,
- new delay management in case of ring-overwritting.
This commit is contained in:
@@ -129,7 +129,7 @@ static struct wd_softc wd_softc[NWDDRIVER];
|
||||
static rtems_isr
|
||||
wd8003Enet_interrupt_handler (rtems_vector_number v)
|
||||
{
|
||||
unsigned int tport, nowTicks, bootTicks;
|
||||
unsigned int tport;
|
||||
unsigned char status, status2;
|
||||
|
||||
tport = wd_softc[0].port ;
|
||||
@@ -146,9 +146,7 @@ wd8003Enet_interrupt_handler (rtems_vector_number v)
|
||||
|
||||
if (status & MSK_OVW){
|
||||
outport_byte(tport+CMDR, MSK_STP + MSK_RD2); /* stop 8390 */
|
||||
rtems_clock_get(RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &bootTicks );
|
||||
while(nowTicks < bootTicks+loopc) /* 2ms delay */
|
||||
rtems_clock_get(RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &nowTicks );
|
||||
Wait_X_ms(2);
|
||||
outport_byte(tport+RBCR0, 0); /* clear byte count */
|
||||
outport_byte(tport+RBCR1, 0);
|
||||
inport_byte(tport+ISR, status2);
|
||||
@@ -361,11 +359,16 @@ sendpacket (struct ifnet *ifp, struct mbuf *m)
|
||||
struct wd_softc *dp = ifp->if_softc;
|
||||
struct mbuf *n;
|
||||
unsigned int len, tport;
|
||||
char *shp;
|
||||
char *shp, txReady;
|
||||
|
||||
tport = dp->port;
|
||||
|
||||
|
||||
/*
|
||||
* Waiting for Transmitter ready
|
||||
*/
|
||||
inport_byte(tport+CMDR, txReady);
|
||||
while(txReady & MSK_TXP)
|
||||
inport_byte(tport+CMDR, txReady);
|
||||
|
||||
len = 0;
|
||||
shp = dp->base + (SHAPAGE * OUTPAGE);
|
||||
@@ -639,10 +642,6 @@ rtems_wd_driver_attach (struct rtems_bsdnet_ifconfig *config)
|
||||
if (ifp->if_snd.ifq_maxlen == 0)
|
||||
ifp->if_snd.ifq_maxlen = ifqmaxlen;
|
||||
|
||||
/* calibrate a delay loop for 2 milliseconds */
|
||||
rtems_clock_get(RTEMS_CLOCK_GET_TICKS_PER_SECOND, &loopc );
|
||||
loopc /= 500;
|
||||
|
||||
/*
|
||||
* init some variables
|
||||
*/
|
||||
|
||||
@@ -146,6 +146,12 @@ void bsp_pretasking_hook(void)
|
||||
+--------------------------------------------------------------------------*/
|
||||
void bsp_start( void )
|
||||
{
|
||||
|
||||
/*
|
||||
* Calibrate variable for 1ms-loop (see timer.c)
|
||||
*/
|
||||
Calibrate_loop_1ms();
|
||||
|
||||
rtemsFreeMemStart = (rtems_unsigned32)&_end + _stack_size;
|
||||
/* set the value of start of free memory. */
|
||||
|
||||
|
||||
@@ -45,12 +45,19 @@
|
||||
+--------------------------------------------------------------------------*/
|
||||
#define AVG_OVERHEAD 0 /* 0.1 microseconds to start/stop timer. */
|
||||
#define LEAST_VALID 1 /* Don't trust a value lower than this. */
|
||||
#define SLOW_DOWN_IO 0x80 /* io which does nothing */
|
||||
|
||||
#define TWO_MS (rtems_unsigned32)(2000) /* TWO_MS = 2000us (sic!) */
|
||||
|
||||
#define MSK_NULL_COUNT 0x40 /* bit counter available for reading */
|
||||
|
||||
#define CMD_READ_BACK_STATUS 0xE2 /* command read back status */
|
||||
/*-------------------------------------------------------------------------+
|
||||
| Global Variables
|
||||
+--------------------------------------------------------------------------*/
|
||||
volatile rtems_unsigned32 Ttimer_val;
|
||||
rtems_boolean Timer_driver_Find_average_overhead = TRUE;
|
||||
unsigned int loop1ms;
|
||||
|
||||
/*-------------------------------------------------------------------------+
|
||||
| External Prototypes
|
||||
@@ -293,3 +300,95 @@ Set_find_average_overhead(rtems_boolean find_flag)
|
||||
{
|
||||
Timer_driver_Find_average_overhead = find_flag;
|
||||
} /* Set_find_average_overhead */
|
||||
|
||||
/*-------------------------------------------------------------------------+
|
||||
| Function: Calibrate_loop_1ms
|
||||
| Description: Set loop variable to calibrate a 1ms loop
|
||||
| Global Variables: loop1ms
|
||||
| Arguments: none
|
||||
| Returns: Nothing.
|
||||
+--------------------------------------------------------------------------*/
|
||||
void
|
||||
Calibrate_loop_1ms(void){
|
||||
unsigned int i;
|
||||
unsigned short loadedValue, offset;
|
||||
unsigned int timerValue;
|
||||
rtems_interrupt_level level;
|
||||
unsigned short lsb, msb;
|
||||
unsigned char status;
|
||||
|
||||
|
||||
loop1ms = 100 ;
|
||||
timerValue = 2000;
|
||||
loadedValue = US_TO_TICK(2000);
|
||||
|
||||
rtems_interrupt_disable(level);
|
||||
|
||||
/*
|
||||
* Compute the offset to apply due to read counter register
|
||||
*/
|
||||
outport_byte(TIMER_MODE, TIMER_SEL0|TIMER_16BIT|TIMER_RATEGEN);
|
||||
outport_byte(TIMER_CNTR0, loadedValue >> 0 & 0xff);
|
||||
outport_byte(TIMER_CNTR0, loadedValue >> 8 & 0xff);
|
||||
|
||||
outport_byte(TIMER_MODE, CMD_READ_BACK_STATUS); /* read Status counter 0 */
|
||||
inport_byte(TIMER_CNTR0, status);
|
||||
while (status & MSK_NULL_COUNT){ /* wait for counter ready */
|
||||
outport_byte(TIMER_MODE, CMD_READ_BACK_STATUS);
|
||||
inport_byte(TIMER_CNTR0, status);
|
||||
}
|
||||
|
||||
outport_byte(TIMER_MODE, TIMER_SEL0|TIMER_LATCH);
|
||||
inport_byte(TIMER_CNTR0, lsb);
|
||||
inport_byte(TIMER_CNTR0, msb);
|
||||
offset = loadedValue - (unsigned short)((msb << 8) | lsb);
|
||||
|
||||
while (timerValue > 1000){
|
||||
loop1ms++;
|
||||
|
||||
/* load timer for 2ms+offset period */
|
||||
outport_byte(TIMER_MODE, TIMER_SEL0|TIMER_16BIT|TIMER_RATEGEN);
|
||||
outport_byte(TIMER_CNTR0, (loadedValue+offset) >> 0 & 0xff);
|
||||
outport_byte(TIMER_CNTR0, (loadedValue+offset) >> 8 & 0xff);
|
||||
|
||||
outport_byte(TIMER_MODE, CMD_READ_BACK_STATUS); /* read Status counter 0 */
|
||||
inport_byte(TIMER_CNTR0, status);
|
||||
while (status & MSK_NULL_COUNT) { /* wait for counter ready */
|
||||
outport_byte(TIMER_MODE, CMD_READ_BACK_STATUS);
|
||||
inport_byte(TIMER_CNTR0, status);
|
||||
}
|
||||
|
||||
for (i=0; i<loop1ms; i++)
|
||||
outport_byte(SLOW_DOWN_IO, 0); /* write is # 1us */
|
||||
|
||||
outport_byte(TIMER_MODE, TIMER_SEL0|TIMER_LATCH);
|
||||
inport_byte(TIMER_CNTR0, lsb);
|
||||
inport_byte(TIMER_CNTR0, msb);
|
||||
timerValue = TICK_TO_US((msb << 8) | lsb);
|
||||
}
|
||||
|
||||
rtems_interrupt_enable(level);
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------+
|
||||
| Function: Wait_X_1ms
|
||||
| Description: loop which waits at least timeToWait ms
|
||||
| Global Variables: loop1ms
|
||||
| Arguments: timeToWait
|
||||
| Returns: Nothing.
|
||||
+--------------------------------------------------------------------------*/
|
||||
void
|
||||
Wait_X_ms( unsigned int timeToWait){
|
||||
|
||||
unsigned int i, j;
|
||||
|
||||
for (j=0; j<timeToWait ; j++)
|
||||
for (i=0; i<loop1ms; i++)
|
||||
outport_byte(SLOW_DOWN_IO, 0); /* write is # 1us */
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user