summaryrefslogtreecommitdiffstats
path: root/c/src/lib/libbsp/m68k/gen68340/console/m340uart.c
diff options
context:
space:
mode:
Diffstat (limited to 'c/src/lib/libbsp/m68k/gen68340/console/m340uart.c')
-rw-r--r--c/src/lib/libbsp/m68k/gen68340/console/m340uart.c409
1 files changed, 409 insertions, 0 deletions
diff --git a/c/src/lib/libbsp/m68k/gen68340/console/m340uart.c b/c/src/lib/libbsp/m68k/gen68340/console/m340uart.c
new file mode 100644
index 0000000000..a293f6c83c
--- /dev/null
+++ b/c/src/lib/libbsp/m68k/gen68340/console/m340uart.c
@@ -0,0 +1,409 @@
+/*
+ * M68340/349 uart management tools
+ *
+ * Author:
+ * Geoffroy Montel
+ * France Telecom - CNET/DSM/TAM/CAT
+ * 4, rue du Clos Courtel
+ * 35512 CESSON-SEVIGNE
+ * FRANCE
+ *
+ * e-mail: g_montel@yahoo.com
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ *
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <termios.h>
+#include <bsp.h>
+#include <rtems/libio.h>
+#include <m68340.h>
+#include <m340uart.h>
+#include <stdarg.h>
+
+/* this table shows compatible speed configurations for the MC68340:
+ the first row shows baud rates for baud speed set 1
+ the second row shows baud rates for baud speed set 2
+ look at Motorola's MC68340 Integrated Processor User's Manual
+ page 7-30 for more infos */
+
+float m340_Baud_Rates_Table[16][2] = {\
+ { 50, 75 }, \
+ { 110, 110 }, \
+ { 134.5, 134.5 }, \
+ { 200, 150 }, \
+ { 300, 300 }, \
+ { 600, 600 }, \
+ { 1200, 1200 }, \
+ { 1050, 2000 }, \
+ { 2400, 2400 }, \
+ { 4800, 4800 }, \
+ { 7200, 1800 }, \
+ { 9600, 9600 }, \
+ { 38400, 19200 }, \
+ { 76800, 38400 }, \
+ { SCLK/16, SCLK/16}, \
+ { SCLK, SCLK }, \
+};
+
+/* config on both 340 channels */
+uart_channel_config m340_uart_config[UART_NUMBER_OF_CHANNELS];
+
+/*
+ * Init UART table
+ */
+
+#define NOT_IMPLEMENTED_YET 0
+
+/******************************************************
+ Name: Init_UART_Table
+ Input parameters: -
+ Output parameters: -
+ Description: Init the m340_uart_config
+ THIS SHOULD NOT BE HERE!
+ Its aim was to let the user configure
+ UARTs for each application.
+ As we can't pass args to the console
+ driver initialisation routine at the
+ moment, this was not done.
+ ATTENTION: TERMIOS init presupposes that the channel
+ baud rates is 9600/9600.
+ -> risks when using IOCTL
+ *****************************************************/
+void Init_UART_Table(void)
+{
+ m340_uart_config[UART_CHANNEL_A].enable = TRUE;
+ strcpy(m340_uart_config[UART_CHANNEL_A].name, UART_CONSOLE_NAME);
+ m340_uart_config[UART_CHANNEL_A].parity_mode = m340_No_Parity;
+ m340_uart_config[UART_CHANNEL_A].bits_per_char = m340_8bpc;
+ m340_uart_config[UART_CHANNEL_A].rx_baudrate = 9600;
+ m340_uart_config[UART_CHANNEL_A].tx_baudrate = 9600;
+ m340_uart_config[UART_CHANNEL_A].rx_mode = UART_CRR;
+ m340_uart_config[UART_CHANNEL_A].mode = UART_POLLING;
+
+ m340_uart_config[UART_CHANNEL_A].termios.enable = TRUE;
+ m340_uart_config[UART_CHANNEL_A].termios.rx_buffer_size = NOT_IMPLEMENTED_YET;
+ m340_uart_config[UART_CHANNEL_A].termios.tx_buffer_size = NOT_IMPLEMENTED_YET;
+
+ m340_uart_config[UART_CHANNEL_B].enable = FALSE;
+ strcpy(m340_uart_config[UART_CHANNEL_B].name, UART_RAW_IO_NAME);
+ m340_uart_config[UART_CHANNEL_B].parity_mode = m340_No_Parity;
+ m340_uart_config[UART_CHANNEL_B].bits_per_char = m340_8bpc;
+ m340_uart_config[UART_CHANNEL_B].rx_baudrate = 38400;
+ m340_uart_config[UART_CHANNEL_B].tx_baudrate = 38400;
+ m340_uart_config[UART_CHANNEL_B].rx_mode = UART_CRR;
+ m340_uart_config[UART_CHANNEL_B].mode = UART_INTERRUPTS;
+
+ m340_uart_config[UART_CHANNEL_B].termios.enable = TRUE;
+ m340_uart_config[UART_CHANNEL_B].termios.rx_buffer_size = NOT_IMPLEMENTED_YET;
+ m340_uart_config[UART_CHANNEL_B].termios.tx_buffer_size = NOT_IMPLEMENTED_YET;
+}
+
+/******************************************************
+ Name: Find_Right_m340_UART_Channel_Config
+ Input parameters: Send/Receive baud rates for a
+ given channel
+ Output parameters: UART compatible configs for this
+ channel
+ Description: returns which uart configurations fit
+ Receiver Baud Rate and Transmitter Baud
+ Rate for a given channel
+ For instance, according to the
+ m340_Baud_Rates_Table:
+ - Output Speed = 50, Input Speed = 75
+ is not a correct config, because
+ 50 bauds implies set 1 and 75 bauds
+ implies set 2
+ - Output Speed = 9600, Input Speed = 9600
+ two correct configs for this:
+ RCS=11, TCS=11, Set=1 or 2
+ *****************************************************/
+t_baud_speed_table
+Find_Right_m340_UART_Channel_Config(float ReceiverBaudRate, float TransmitterBaudRate)
+{
+ t_baud_speed_table return_value;
+
+ struct {
+ int cs;
+ int set;
+ } Receiver[2], Transmitter[2];
+
+ int Receiver_nb_of_config = 0;
+ int Transmitter_nb_of_config = 0;
+
+ int i,j;
+
+ /* Receiver and Transmitter baud rates must be compatible, ie in the same set */
+
+ /* search for configurations for ReceiverBaudRate - there can't be more than two (only two sets) */
+ for (i=0;i<16;i++)
+ for (j=0;j<2;j++)
+ if (m340_Baud_Rates_Table[i][j]==ReceiverBaudRate) {
+ Receiver[Receiver_nb_of_config].cs=i;
+ Receiver[Receiver_nb_of_config].set=j;
+ Receiver_nb_of_config++;
+ }
+
+ /* search for configurations for TransmitterBaudRate - there can't be more than two (only two sets) */
+ for (i=0;i<16;i++)
+ for (j=0;j<2;j++)
+ if (m340_Baud_Rates_Table[i][j]==TransmitterBaudRate) {
+ Transmitter[Transmitter_nb_of_config].cs=i;
+ Transmitter[Transmitter_nb_of_config].set=j;
+ Transmitter_nb_of_config++;
+ }
+
+ /* now check if there's a compatible config */
+ return_value.nb=0;
+
+ for (i=0; i<Receiver_nb_of_config; i++)
+ for (j=0;j<Transmitter_nb_of_config;j++)
+ if (Receiver[i].set == Transmitter[j].set) {
+ return_value.baud_speed_table[return_value.nb].set = Receiver[i].set + 1; /* we want set 1 or set 2, not 0 or 1 */
+ return_value.baud_speed_table[return_value.nb].rcs = Receiver[i].cs;
+ return_value.baud_speed_table[return_value.nb].tcs = Transmitter[j].cs;
+ return_value.nb++;
+ }
+
+ return return_value;
+}
+
+/******************************************************
+ Name: Find_Right_m340_UART_Config
+ Input parameters: Send/Receive baud rates for both
+ channels
+ Output parameters: UART compatible configs for
+ BOTH channels
+ Description: returns which uart configurations fit
+ Receiver Baud Rate and Transmitter Baud
+ Rate for both channels
+ For instance, if we want 9600/38400 on
+ channel A and 9600/19200 on channel B,
+ this is not a good m340 uart config
+ (channel A needs set 1 and channel B
+ needs set 2)
+ *****************************************************/
+t_baud_speed_table
+Find_Right_m340_UART_Config(float ChannelA_ReceiverBaudRate, float ChannelA_TransmitterBaudRate, rtems_unsigned8 enableA,
+ float ChannelB_ReceiverBaudRate, float ChannelB_TransmitterBaudRate, rtems_unsigned8 enableB)
+{
+ t_baud_speed_table tableA, tableB;
+ t_baud_speed_table return_value, tmp;
+ int i,j;
+
+ return_value.nb=0;
+
+ if (enableA && enableB) {
+ tableA = Find_Right_m340_UART_Channel_Config(ChannelA_ReceiverBaudRate, ChannelA_TransmitterBaudRate);
+ tableB = Find_Right_m340_UART_Channel_Config(ChannelB_ReceiverBaudRate, ChannelB_TransmitterBaudRate);
+
+ for (i=0;i<tableA.nb;i++)
+ for (j=0;j<tableB.nb;j++)
+ if (tableA.baud_speed_table[i].set==tableB.baud_speed_table[j].set) {
+ return_value.baud_speed_table[UART_CHANNEL_A].set=tableA.baud_speed_table[i].set;
+ return_value.baud_speed_table[UART_CHANNEL_A].rcs=tableA.baud_speed_table[i].rcs;
+ return_value.baud_speed_table[UART_CHANNEL_A].tcs=tableA.baud_speed_table[i].tcs;
+ return_value.baud_speed_table[UART_CHANNEL_B].set=tableB.baud_speed_table[j].set;
+ return_value.baud_speed_table[UART_CHANNEL_B].rcs=tableB.baud_speed_table[j].rcs;
+ return_value.baud_speed_table[UART_CHANNEL_B].tcs=tableB.baud_speed_table[j].tcs;
+ return_value.nb=2;
+ break;
+ }
+ return return_value;
+ }
+
+ if (enableA) {
+ return_value = Find_Right_m340_UART_Channel_Config(ChannelA_ReceiverBaudRate, ChannelA_TransmitterBaudRate);
+ return return_value;
+ }
+
+ if (enableB) {
+ tmp = Find_Right_m340_UART_Channel_Config(ChannelB_ReceiverBaudRate, ChannelB_TransmitterBaudRate);
+ if (tmp.nb!=0) {
+ return_value.nb = 2;
+ return_value.baud_speed_table[1].set = tmp.baud_speed_table[0].set;
+ return_value.baud_speed_table[1].rcs = tmp.baud_speed_table[0].rcs;
+ return_value.baud_speed_table[1].tcs = tmp.baud_speed_table[0].tcs;
+ }
+ }
+ return return_value;
+}
+
+/******************************************************
+ Name: termios_baud_rates_equivalence
+ Input parameters: Termios coded speed
+ Output parameters: explicit speed
+ Description: ioctl calls return termios coded speed
+ we need to know real speed in order
+ to use the functions above
+ *****************************************************/
+float termios_baud_rates_equivalence ( int speed )
+{
+ switch (speed) {
+ default: return 0; break;
+ case B50: return 50; break;
+ case B75: return 75; break;
+ case B110: return 110; break;
+ case B134: return 134; break;
+ case B150: return 150; break;
+ case B200: return 200; break;
+ case B300: return 300; break;
+ case B600: return 600; break;
+ case B1200: return 1200; break;
+ case B1800: return 1800; break;
+ case B2400: return 2400; break;
+ case B4800: return 4800; break;
+ case B9600: return 9600; break;
+ case B19200: return 19200; break;
+ case B38400: return 38400; break;
+ case B57600: return 57600; break;
+ case B115200: return 115200; break;
+ case B230400: return 230400; break;
+ case B460800: return 460800; break;
+ }
+ return 0;
+}
+
+/****************************************************************************************************/
+
+/*
+ * very low level fmted output
+ */
+
+extern void dbug_out_char( int minor, int ch );
+extern int dbug_in_char( int minor );
+extern int dbug_char_present( int minor );
+
+/******************************************************
+ Name: dbugRead
+ Input parameters: channel
+ Output parameters: char read
+ Description: polled read
+ *****************************************************/
+int dbugRead (int minor)
+{
+ if (dbug_char_present(minor) == 0)
+ return -1;
+ return dbug_in_char(minor);
+}
+
+/******************************************************
+ Name: dbugWrite
+ Input parameters: channel, buffer and its length
+ Output parameters: always successfull
+ Description: polled write
+ *****************************************************/
+int dbugWrite (int minor, const char *buf, int len)
+{
+ static char txBuf;
+
+ while (len--) {
+ txBuf = *buf++;
+ dbug_out_char( minor, (int)txBuf );
+ }
+ return 0;
+}
+
+static void fmt_num( int minor, unsigned long, unsigned );
+static void fmt_str( int minor, const char* );
+
+/******************************************************
+ Name: RAW_GETC
+ Input parameters: channel, buffer and its length
+ Output parameters:
+ Description: a light blocking "getc"
+ *****************************************************/
+char RAW_GETC(int minor)
+{
+ while (!dbug_char_present(minor)) continue;
+ return dbug_in_char(minor);
+}
+
+/******************************************************
+ Name: RAW_FMT
+ Input parameters: channel, buffer and its length
+ Output parameters: always successfull
+ Description: a light polled "printf"
+ useful when there's a serious pb and
+ there are no more interrupts
+ *****************************************************/
+void RAW_FMT( int minor, const char* fmt, ... )
+{
+ int ch;
+ va_list va;
+
+ va_start( va, fmt );
+
+ while( (ch = *fmt++) )
+ if( ch != '%' || (ch = *fmt++) == '%' )
+ {
+ if( ch == '\n' )
+ dbug_out_char( minor, '\r' );
+ dbug_out_char( minor, ch );
+ }
+ else switch( ch )
+ {
+ case 'c':
+ dbug_out_char( minor, va_arg( va, int ) );
+ continue;
+ case 's':
+ fmt_str( minor, va_arg( va, char* ) );
+ continue;
+ case 'd':
+ ch = va_arg( va, int );
+ if( ch >= 0 )
+ fmt_num( minor, ch, 10 );
+ else
+ {
+ dbug_out_char( minor, '-' );
+ fmt_num( minor, -ch, 10 );
+ }
+ continue;
+ case 'u':
+ fmt_num( minor, va_arg( va, unsigned ), 10 );
+ continue;
+ case 'o':
+ fmt_num( minor, va_arg( va, unsigned ), 8 );
+ continue;
+ case 'x':
+ case 'p':
+ fmt_num( minor, va_arg( va, unsigned ), 16 );
+ continue;
+ default: continue;
+ return;
+ }
+ va_end( va );
+}
+
+static void fmt_num( int minor, unsigned long num, unsigned base )
+{
+ char buf[33];
+ int ib = sizeof(buf);
+
+ buf[--ib] = 0;
+ do
+ {
+ buf[--ib] = "0123456789ABCDEF"[num%base];
+ num /= base;
+ }
+ while( num != 0 );
+
+ fmt_str( minor, buf+ib );
+}
+
+static void fmt_str( int minor, const char* str )
+{
+ if( str )
+ while( *str )
+ dbug_out_char( minor, *str++ );
+}
+
+