diff options
Diffstat (limited to 'c/src/lib/libbsp/m68k/idp/console')
-rw-r--r-- | c/src/lib/libbsp/m68k/idp/console/console.c | 216 | ||||
-rw-r--r-- | c/src/lib/libbsp/m68k/idp/console/duart.c | 170 | ||||
-rw-r--r-- | c/src/lib/libbsp/m68k/idp/console/leds.c | 80 | ||||
-rw-r--r-- | c/src/lib/libbsp/m68k/idp/console/mc68ec.c | 18 |
4 files changed, 484 insertions, 0 deletions
diff --git a/c/src/lib/libbsp/m68k/idp/console/console.c b/c/src/lib/libbsp/m68k/idp/console/console.c new file mode 100644 index 0000000000..7bb720c120 --- /dev/null +++ b/c/src/lib/libbsp/m68k/idp/console/console.c @@ -0,0 +1,216 @@ +/* + * This file contains the Motorola IDP console IO package. + * + * Written by Doug McBride, Colorado Space Grant College + * Based off of the board support packages of RTEMS + * + * Updated to RTEMS 3.2.0 by Joel Sherrill. + * + * $Id$ + */ + +#define MIDP_INIT + +#include "rtems.h" +#include "console.h" +#include "bsp.h" + +#include "ringbuf.h" + +Ring_buffer_t Buffer[ 2 ]; + +rtems_isr C_Receive_ISR(rtems_vector_number vector); + + +/* console_initialize + * + * This routine initializes the console IO driver. + * + * Input parameters: NONE + * + * Output parameters: NONE + * + * Return values: + */ + +rtems_device_driver console_initialize( + rtems_device_major_number major, + rtems_device_minor_number minor, + void *arg, + rtems_id self, + rtems_unsigned32 *status +) +{ + + Ring_buffer_Initialize( &Buffer[ 0 ] ); + Ring_buffer_Initialize( &Buffer[ 1 ] ); + + init_pit(); + + *status = RTEMS_SUCCESSFUL; +} + + +/* is_character_ready + * + * This routine returns TRUE if a character is available. + * + * Input parameters: NONE + * + * Output parameters: NONE + * + * Return values: + */ + +rtems_boolean is_character_ready( + char *ch, + int port +) +{ + if ( Ring_buffer_Is_empty( &Buffer[ port ] ) ) + return FALSE; + + Ring_buffer_Remove_character( &Buffer[ port ], *ch ); + return TRUE; +} + +/* quick_char_check + * + * This routine returns TRUE if a character is available. + * It is different from above because it does not disturb the ring buffer + * + * Input parameters: NONE + * + * Output parameters: NONE + * + * Return values: + */ + +rtems_boolean quick_char_check( + int port +) +{ + if ( Ring_buffer_Is_empty( &Buffer[ port ] ) ) + return FALSE; + + return TRUE; +} + +/* inbyte + * + * This routine reads a character from the UART through a buffer. + * + * Input parameters: NONE + * + * Output parameters: NONE + * + * Return values: + * character read from UART + */ + +char inbyte( + int port +) +{ + unsigned char tmp_char; + + /* If you come into this routine without checking is_character_ready() first + and you want nonblocking code, then it's your own fault */ + + while ( !is_character_ready( &tmp_char, port ) ); + + return tmp_char; +} + + +/* outbyte + * + * This routine transmits a character out the M68681. It supports + * XON/XOFF flow control. + * + * Input parameters: + * ch - character to be transmitted + * + * Output parameters: NONE + */ + +void outbyte( + char ch, + int port +) +{ + switch ( port ) { + case 0: + transmit_char( ch ); + break; + case 1: + transmit_char_portb( ch ); + break; + } + +} + +/* + * __read -- read bytes from the serial port. Ignore fd, since + * we only have stdin. + */ + +int __read( + int fd, + char *buf, + int nbytes +) +{ + int i = 0; + int port; + + /* + * Map port A to stdin, stdout, and stderr. + * Map everything else to port B. + */ + + if ( fd <= 2 ) port = 0; + else port = 1; + + for (i = 0; i < nbytes; i++) { + *(buf + i) = inbyte( port ); + if ((*(buf + i) == '\n') || (*(buf + i) == '\r')) { + (*(buf + i++)) = '\n'; + (*(buf + i)) = 0; + break; + } + } + return (i); +} + +/* + * __write -- write bytes to the serial port. Ignore fd, since + * stdout and stderr are the same. Since we have no filesystem, + * open will only return an error. + */ + +int __write( + int fd, + char *buf, + int nbytes +) +{ + int i; + int port; + + /* + * Map port A to stdin, stdout, and stderr. + * Map everything else to port B. + */ + + if ( fd <= 2 ) port = 0; + else port = 1; + + for (i = 0; i < nbytes; i++) { + if (*(buf + i) == '\n') { + outbyte ('\r', port ); + } + outbyte (*(buf + i), port ); + } + return (nbytes); +} diff --git a/c/src/lib/libbsp/m68k/idp/console/duart.c b/c/src/lib/libbsp/m68k/idp/console/duart.c new file mode 100644 index 0000000000..c3ee92b75b --- /dev/null +++ b/c/src/lib/libbsp/m68k/idp/console/duart.c @@ -0,0 +1,170 @@ +/*######################################################### +# +# This code is a modified version of what you will find at the +# end of the IDP User's manual. The original code is copyrighted +# by Motorola and Motorola Semiconductor Products as well as +# Motorola Software products group. +# +# Modifications to the original IDP code by Doug McBride, Colorado +# Space Grant College. Modifications include a means of accessing +# port B of the duart as well as port A as well as modifications for +# buffering and RTEMS support. Modifications are provided +# as is and may not be correct. +# +# Rob Savoye provided the format for the mc68681 header file +# +# Joel Sherrill provided inspiration for recoding my original assembly +# for this file into C (a good idea) +# +##########################################################*/ + +#include "mc68230.h" +#include "mc68681.h" +#include "ringbuf.h" +#include "rtems.h" +#include "bsp.h" + +rtems_isr C_Receive_ISR(rtems_vector_number vector); +extern Ring_buffer_t Buffer[]; + +extern unsigned char inbuf[]; +extern unsigned char inbuf_portb[]; +extern unsigned tail; +extern unsigned tail_portb; +unsigned char Pit_initialized = 0; + +/*##################################################################### +# The volatile routine to initialize the duart -- port a and port b +######################################################################*/ +volatile void init_pit() +{ + /* Disable ports A & B while configuring PIT */ + MC68681_WRITE(DUART_IMR, 0x00); /* disable imr */ + MC68681_WRITE(DUART_CRA, 0x08); /* disable port a transmitter */ + MC68681_WRITE(DUART_CRA, 0x02); /* disable port a receiver */ + MC68681_WRITE(DUART_CRB, 0x08); /* disable port b transmitter */ + MC68681_WRITE(DUART_CRB, 0x02); /* disable port b receiver */ + + /* install ISR for ports A and B */ + set_vector(C_Receive_ISR, (VECT+H3VECT), 1); + + /* initialize pit */ + MC68230_WRITE(PGCR, 0x00); /* set mode to 0 -- disable all ports */ + MC68230_WRITE(PSRR, 0x18); /* set up pirq and piack */ + MC68230_WRITE(PBDDR, 0x00); /* all pins on port b are input */ + MC68230_WRITE(PBCR, 0x82); /* submode 1x, h3 interrupt enabled */ + MC68230_WRITE(PIVR, VECT); /* setup pivr */ + MC68230_WRITE(PGCR, 0x20); /* turn on all ports */ + + /* For some reason, the reset of receiver/transmitter only works for + the first time around -- it garbles the output otherwise (e.g., sp21) */ + if (!Pit_initialized) + { + /* now initialize the duart registers on port b */ + /* WARNING:OPTIMIZER MAY ONLY EXECUTE THIRD STATEMENT IF NOT VOLATILE */ + MC68681_WRITE(DUART_CRB, 0x30); /* reset tx, channel b */ + MC68681_WRITE(DUART_CRB, 0x20); /* reset rx, channel b */ + MC68681_WRITE(DUART_CRB, 0x10); /* reset mr pointer, channel b */ + + /* now initialize the duart registers on port a */ + /* WARNING:OPTIMIZER MAY ONLY EXECUTE THIRD STATEMENT IF NOT VOLATILE */ + MC68681_WRITE(DUART_CRA, 0x30); /* reset tx, channel a */ + MC68681_WRITE(DUART_CRA, 0x20); /* reset rx, channel a */ + MC68681_WRITE(DUART_CRA, 0x10); /* reset mr pointer, channel a */ + Pit_initialized = 1; + } + + /* init the general registers of the duart */ + MC68681_WRITE(DUART_IVR, 0x0f); /* init ivr */ + MC68681_WRITE(DUART_IMR, 0x22); /* init imr */ + MC68681_WRITE(DUART_ACR, 0x00); /* init acr */ + MC68681_WRITE(DUART_CTUR, 0x00); /* init ctur */ + MC68681_WRITE(DUART_CTLR, 0x02); /* init ctlr */ + MC68681_WRITE(DUART_OPCR, 0x00); /* init opcr */ + MC68681_WRITE(DUART_OPRSET, 0x01); /* init cts */ + + /* init the actual serial port for port a */ + MC68681_WRITE(DUART_CSRA, 0xbb); /* init csra -- 9600 baud */ + MC68681_WRITE(DUART_MR1A, 0x13); /* init mr1a */ + MC68681_WRITE(DUART_MR2A, 0x07); /* init mr2a */ + MC68681_WRITE(DUART_CRA, 0x05); /* init cra */ + + /* init the actual serial port for port b */ + MC68681_WRITE(DUART_CSRB, 0xbb); /* init csrb -- 9600 baud */ +#define EIGHT_BITS_NO_PARITY +#ifdef EIGHT_BITS_NO_PARITY + MC68681_WRITE(DUART_MR1B, 0x13); /* init mr1b */ +#else /* 7 bits, even parity */ + MC68681_WRITE(DUART_MR1B, 0x02); /* init mr1b */ +#endif + MC68681_WRITE(DUART_MR2B, 0x07); /* init mr2b -- one stop bit */ + MC68681_WRITE(DUART_CRB, 0x05); /* init crb */ +} + +/*##################################################################### +# interrupt handler for receive of character from duart on ports A & B +#####################################################################*/ +rtems_isr C_Receive_ISR(rtems_vector_number vector) +{ + volatile unsigned char *_addr; + + _addr = (unsigned char *) (PIT_ADDR + PITSR); + *_addr = 0x04; /* clear pit interrupt */ + + /* Let's check port A first for input */ + _addr = (unsigned char *) (DUART_ADDR + DUART_SRA); + if (*_addr & 0x01) /* extract rcvrdy on port A */ + { + /* Read input on port A */ + _addr = (unsigned char *) (DUART_ADDR + DUART_RBA); + Ring_buffer_Add_character( &Buffer[ 0 ], *_addr ); + } + else /* If not on port A, let's check port B */ + { + _addr = (unsigned char *) (DUART_ADDR + DUART_SRB); + if (*_addr & 0x01) /* extract rcvrdy on port B */ + { + /* Read input on port B */ + _addr = (unsigned char *) (DUART_ADDR + DUART_RBB); + Ring_buffer_Add_character( &Buffer[ 1 ], *_addr ); + } + /* if not ready on port A or port B, must be an error */ + /* if error, get out so that fifo is undisturbed */ + } +} + +/*##################################################################### +# This is the routine that actually transmits a character one at a time +# This routine transmits on port A of the IDP board +#####################################################################*/ +void transmit_char(char ch) +{ + volatile unsigned char *_addr; + + /* Get SRA (extract txrdy) */ + _addr = (unsigned char *) (DUART_ADDR + DUART_SRA); + while (!(*_addr & 0x04)) + { + } + + /* transmit character over port A */ + MC68681_WRITE(DUART_TBA, ch); +} + +/*##################################################################### +# This is the routine that actually transmits a character one at a time +# This routine transmits on port B of the IDP board +#####################################################################*/ +void transmit_char_portb(char ch) +{ + volatile unsigned char *_addr; + + /* Get SRB (extract txrdy) */ + _addr = (unsigned char *) (DUART_ADDR + DUART_SRB); + while (!(*_addr & 0x04)) + { + } + + /* transmit character over port B */ + MC68681_WRITE(DUART_TBB, ch); +} diff --git a/c/src/lib/libbsp/m68k/idp/console/leds.c b/c/src/lib/libbsp/m68k/idp/console/leds.c new file mode 100644 index 0000000000..4d7abaf93d --- /dev/null +++ b/c/src/lib/libbsp/m68k/idp/console/leds.c @@ -0,0 +1,80 @@ +/* + * leds.c -- control the led's on a Motorola mc68ec0x0 board. + * Written by rob@cygnus.com (Rob Savoye) + */ +#include "leds.h" + +void zylons(); +void led_putnum(); +void clear_leds(); + +/* + * led_putnum -- print a hex number on the LED. the value of num must be a char with + * the ascii value. ie... number 0 is '0', a is 'a', ' ' (null) clears + * the led display. + * Setting the bit to 0 turns it on, 1 turns it off. + * the LED's are controlled by setting the right bit mask in the base + * address. + * The bits are: + * [d.p | g | f | e | d | c | b | a ] is the byte. + * + * The locations are: + * + * a + * ----- + * f | | b + * | g | + * ----- + * | | + * e | | c + * ----- + * d . d.p (decimal point) + */ +void +led_putnum ( num ) +char num; +{ + static unsigned char *leds = (unsigned char *)LED_ADDR; + static unsigned char num_bits [18] = { + 0xff, /* clear all */ + 0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x98, /* numbers 0-9 */ + 0x98, 0x20, 0x3, 0x27, 0x21, 0x4, 0xe /* letters a-f */ + }; + + if (num >= '0' && num <= '9') + num = (num - '0') + 1; + + if (num >= 'a' && num <= 'f') + num = (num - 'a') + 12; + + if (num == ' ') + num = 0; + + *leds = num_bits[(int)num]; +} + +/* This procedure added by Doug McBride, Colorado Space Grant College -- + Probably should be a macro instead */ +void +clear_leds ( ) +{ + static unsigned char *leds = (unsigned char *)LED_ADDR; + *leds = 0xFF; +} + +/* + * zylons -- draw a rotating pattern. NOTE: this function never returns. + */ +void +zylons() +{ + unsigned char *leds = (unsigned char *)LED_ADDR; + unsigned char curled = 0xfe; + + while (1) + { + *leds = curled; + curled = (curled >> 1) | (curled << 7); + delay ( 8000 ); + } +} diff --git a/c/src/lib/libbsp/m68k/idp/console/mc68ec.c b/c/src/lib/libbsp/m68k/idp/console/mc68ec.c new file mode 100644 index 0000000000..dd6956c3e9 --- /dev/null +++ b/c/src/lib/libbsp/m68k/idp/console/mc68ec.c @@ -0,0 +1,18 @@ +/* + * mc68ec.c -- Low level support for the Motorola mc68ec0x0 board. + * Written by rob@cygnus.com (Rob Savoye) + */ +#include "leds.h" + +/* + * delay -- delay execution. This is an ugly hack. It should + * use the timer, but I'm waiting for docs. (sigh) + */ +void delay(num) +int num; +{ + while (num--) + { + asm ("nop"); + } +} |