diff options
Diffstat (limited to 'c/src/lib/libbsp/m68k/ods68302/startup/m68302scc.c')
-rw-r--r-- | c/src/lib/libbsp/m68k/ods68302/startup/m68302scc.c | 159 |
1 files changed, 159 insertions, 0 deletions
diff --git a/c/src/lib/libbsp/m68k/ods68302/startup/m68302scc.c b/c/src/lib/libbsp/m68k/ods68302/startup/m68302scc.c new file mode 100644 index 0000000000..77d7867a21 --- /dev/null +++ b/c/src/lib/libbsp/m68k/ods68302/startup/m68302scc.c @@ -0,0 +1,159 @@ +/*****************************************************************************/ +/* + $Id$ + + M68302 SCC Polled Driver + + */ +/*****************************************************************************/ + + +#include <bsp.h> +#include <m68302.h> +#include <m68302scc.h> + +#define M68302_SCC_COUNT (3) + +static volatile m302_SCC_t *scc[M68302_SCC_COUNT] = { 0, 0, 0 }; +static volatile m302_SCC_Registers_t *scc_reg[M68302_SCC_COUNT] = { 0, 0, 0 }; +static int scc_translate[M68302_SCC_COUNT] = { 0, 0, 0 }; + +static const rtems_unsigned16 baud_clocks[] = +{ + (SYSTEM_CLOCK / ( 4800 * 16)), + (SYSTEM_CLOCK / ( 9600 * 16)), + (SYSTEM_CLOCK / ( 19200 * 16)), + (SYSTEM_CLOCK / ( 38400 * 16)), + (SYSTEM_CLOCK / ( 57600 * 16)), + (SYSTEM_CLOCK / (115700 * 16)) +}; + +void scc_initialise(int channel, int baud, int translate) +{ + rtems_unsigned16 scon; + + if (channel < M68302_SCC_COUNT) + { + scc[channel] = &m302.scc1 + channel; + scc_reg[channel] = &m302.reg.scc[channel]; + scc_translate[channel] = translate; + + scon = (baud_clocks[baud] & 0xF800) == 0 ? 0 : 1; + scon |= (((baud_clocks[baud] / (1 + scon * 3)) - 1) << 1) & 0x0FFE; + + scc_reg[channel]->scon = scon; + scc_reg[channel]->scm = 0x0171; + + scc[channel]->bd.tx[0].status = 0x2000; + scc[channel]->bd.tx[0].length = 0; + scc[channel]->bd.tx[0].buffer = + (rtems_unsigned8*) &(scc[channel]->bd.tx[1].buffer); + + scc[channel]->bd.rx[0].status = 0x2000; + scc[channel]->bd.rx[0].length = 0; + scc[channel]->bd.rx[0].buffer = + (rtems_unsigned8*) &(scc[channel]->bd.rx[1].buffer); + + scc[channel]->parm.rfcr = 0x50; + scc[channel]->parm.tfcr = 0x50; + + scc[channel]->parm.mrblr = 0x0001; + scc[channel]->prot.uart.max_idl = 0x0004; + scc[channel]->prot.uart.brkcr = 1; + scc[channel]->prot.uart.parec = 0; + scc[channel]->prot.uart.frmec = 0; + scc[channel]->prot.uart.nosec = 0; + scc[channel]->prot.uart.brkec = 0; + scc[channel]->prot.uart.uaddr1 = 0; + scc[channel]->prot.uart.uaddr2 = 0; + scc[channel]->prot.uart.character[0] = 0x0003; + scc[channel]->prot.uart.character[1] = 0x8000; + + scc_reg[channel]->scce = 0xFF; + scc_reg[channel]->sccm = 0x15; + + scc_reg[channel]->scm = 0x17d; + } +} + +unsigned char scc_status(int channel, unsigned char status) +{ + rtems_unsigned16 rx_status; + + m302.reg.wcn = 0; + + if ((channel < M68302_SCC_COUNT) && scc[channel]) + { + rx_status = scc[channel]->bd.rx[0].status; + + if ((rx_status & 0x8000) == 0) + { + if (rx_status & 0x003B) + { + return 2; + } + if (status == 0) + { + return 1; + } + } + } + + return 0; +} + +unsigned char scc_in(int channel) +{ + m302.reg.wcn = 0; + + if ((channel < M68302_SCC_COUNT) && scc[channel]) + { + if ((scc[channel]->bd.rx[0].status & 0x8000) == 0) + { + unsigned char c; + + c = *(scc[channel]->bd.rx[0].buffer); + + scc[channel]->bd.rx[0].status = 0xa000; + + return c; + } + } + + return 0; +} + +void scc_out(int channel, unsigned char character) +{ + if ((channel < M68302_SCC_COUNT) && scc[channel]) + { + do + { + m302.reg.wcn = 0; + } + while (scc[channel]->bd.tx[0].status & 0x8000); + + *(scc[channel]->bd.tx[0].buffer) = character; + + scc[channel]->bd.tx[0].length = 1; + scc[channel]->bd.tx[0].status = 0xa000; + + if (scc_translate[channel]) + { + if (character == '\n') + { + scc_out(channel, '\r'); + } + } + } +} + + + + + + + + + + |