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
|
static rtems_isr
|
||||||
wd8003Enet_interrupt_handler (rtems_vector_number v)
|
wd8003Enet_interrupt_handler (rtems_vector_number v)
|
||||||
{
|
{
|
||||||
unsigned int tport, nowTicks, bootTicks;
|
unsigned int tport;
|
||||||
unsigned char status, status2;
|
unsigned char status, status2;
|
||||||
|
|
||||||
tport = wd_softc[0].port ;
|
tport = wd_softc[0].port ;
|
||||||
@@ -146,9 +146,7 @@ wd8003Enet_interrupt_handler (rtems_vector_number v)
|
|||||||
|
|
||||||
if (status & MSK_OVW){
|
if (status & MSK_OVW){
|
||||||
outport_byte(tport+CMDR, MSK_STP + MSK_RD2); /* stop 8390 */
|
outport_byte(tport+CMDR, MSK_STP + MSK_RD2); /* stop 8390 */
|
||||||
rtems_clock_get(RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &bootTicks );
|
Wait_X_ms(2);
|
||||||
while(nowTicks < bootTicks+loopc) /* 2ms delay */
|
|
||||||
rtems_clock_get(RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &nowTicks );
|
|
||||||
outport_byte(tport+RBCR0, 0); /* clear byte count */
|
outport_byte(tport+RBCR0, 0); /* clear byte count */
|
||||||
outport_byte(tport+RBCR1, 0);
|
outport_byte(tport+RBCR1, 0);
|
||||||
inport_byte(tport+ISR, status2);
|
inport_byte(tport+ISR, status2);
|
||||||
@@ -361,11 +359,16 @@ sendpacket (struct ifnet *ifp, struct mbuf *m)
|
|||||||
struct wd_softc *dp = ifp->if_softc;
|
struct wd_softc *dp = ifp->if_softc;
|
||||||
struct mbuf *n;
|
struct mbuf *n;
|
||||||
unsigned int len, tport;
|
unsigned int len, tport;
|
||||||
char *shp;
|
char *shp, txReady;
|
||||||
|
|
||||||
tport = dp->port;
|
tport = dp->port;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Waiting for Transmitter ready
|
||||||
|
*/
|
||||||
|
inport_byte(tport+CMDR, txReady);
|
||||||
|
while(txReady & MSK_TXP)
|
||||||
|
inport_byte(tport+CMDR, txReady);
|
||||||
|
|
||||||
len = 0;
|
len = 0;
|
||||||
shp = dp->base + (SHAPAGE * OUTPAGE);
|
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)
|
if (ifp->if_snd.ifq_maxlen == 0)
|
||||||
ifp->if_snd.ifq_maxlen = ifqmaxlen;
|
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
|
* init some variables
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -146,6 +146,12 @@ void bsp_pretasking_hook(void)
|
|||||||
+--------------------------------------------------------------------------*/
|
+--------------------------------------------------------------------------*/
|
||||||
void bsp_start( void )
|
void bsp_start( void )
|
||||||
{
|
{
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Calibrate variable for 1ms-loop (see timer.c)
|
||||||
|
*/
|
||||||
|
Calibrate_loop_1ms();
|
||||||
|
|
||||||
rtemsFreeMemStart = (rtems_unsigned32)&_end + _stack_size;
|
rtemsFreeMemStart = (rtems_unsigned32)&_end + _stack_size;
|
||||||
/* set the value of start of free memory. */
|
/* set the value of start of free memory. */
|
||||||
|
|
||||||
|
|||||||
@@ -45,12 +45,19 @@
|
|||||||
+--------------------------------------------------------------------------*/
|
+--------------------------------------------------------------------------*/
|
||||||
#define AVG_OVERHEAD 0 /* 0.1 microseconds to start/stop timer. */
|
#define AVG_OVERHEAD 0 /* 0.1 microseconds to start/stop timer. */
|
||||||
#define LEAST_VALID 1 /* Don't trust a value lower than this. */
|
#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
|
| Global Variables
|
||||||
+--------------------------------------------------------------------------*/
|
+--------------------------------------------------------------------------*/
|
||||||
volatile rtems_unsigned32 Ttimer_val;
|
volatile rtems_unsigned32 Ttimer_val;
|
||||||
rtems_boolean Timer_driver_Find_average_overhead = TRUE;
|
rtems_boolean Timer_driver_Find_average_overhead = TRUE;
|
||||||
|
unsigned int loop1ms;
|
||||||
|
|
||||||
/*-------------------------------------------------------------------------+
|
/*-------------------------------------------------------------------------+
|
||||||
| External Prototypes
|
| External Prototypes
|
||||||
@@ -293,3 +300,95 @@ Set_find_average_overhead(rtems_boolean find_flag)
|
|||||||
{
|
{
|
||||||
Timer_driver_Find_average_overhead = find_flag;
|
Timer_driver_Find_average_overhead = find_flag;
|
||||||
} /* Set_find_average_overhead */
|
} /* 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