From eff217e095ea1f77e0549a32e170e43b4e637eee Mon Sep 17 00:00:00 2001 From: Joel Sherrill Date: Thu, 10 Sep 1998 12:16:39 +0000 Subject: Patch from Emmanuel Raguet : 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. --- c/src/lib/libbsp/i386/pc386/network/network.c | 19 +++-- c/src/lib/libbsp/i386/pc386/startup/bspstart.c | 6 ++ c/src/lib/libbsp/i386/pc386/timer/timer.c | 99 ++++++++++++++++++++++++++ 3 files changed, 114 insertions(+), 10 deletions(-) (limited to 'c') diff --git a/c/src/lib/libbsp/i386/pc386/network/network.c b/c/src/lib/libbsp/i386/pc386/network/network.c index 1f937bc009..ab12f1c0e7 100644 --- a/c/src/lib/libbsp/i386/pc386/network/network.c +++ b/c/src/lib/libbsp/i386/pc386/network/network.c @@ -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 */ diff --git a/c/src/lib/libbsp/i386/pc386/startup/bspstart.c b/c/src/lib/libbsp/i386/pc386/startup/bspstart.c index 7ebcc60685..7927ef2c0b 100644 --- a/c/src/lib/libbsp/i386/pc386/startup/bspstart.c +++ b/c/src/lib/libbsp/i386/pc386/startup/bspstart.c @@ -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. */ diff --git a/c/src/lib/libbsp/i386/pc386/timer/timer.c b/c/src/lib/libbsp/i386/pc386/timer/timer.c index 8ae7f7c011..47e4894e00 100644 --- a/c/src/lib/libbsp/i386/pc386/timer/timer.c +++ b/c/src/lib/libbsp/i386/pc386/timer/timer.c @@ -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