From d7d66d7d4523b904c8ccc6aea3709dc0d5aa5bdc Mon Sep 17 00:00:00 2001 From: Sebastian Huber Date: Thu, 19 Apr 2018 06:28:01 +0200 Subject: bsps: Move console drivers to bsps This patch is a part of the BSP source reorganization. Update #3285. --- c/src/lib/libbsp/powerpc/tqm8xx/Makefile.am | 2 +- c/src/lib/libbsp/powerpc/tqm8xx/console/console.c | 1115 --------------------- 2 files changed, 1 insertion(+), 1116 deletions(-) delete mode 100644 c/src/lib/libbsp/powerpc/tqm8xx/console/console.c (limited to 'c/src/lib/libbsp/powerpc/tqm8xx') diff --git a/c/src/lib/libbsp/powerpc/tqm8xx/Makefile.am b/c/src/lib/libbsp/powerpc/tqm8xx/Makefile.am index 9589d38e8d..1c0dfe5da3 100644 --- a/c/src/lib/libbsp/powerpc/tqm8xx/Makefile.am +++ b/c/src/lib/libbsp/powerpc/tqm8xx/Makefile.am @@ -32,7 +32,7 @@ librtemsbsp_a_SOURCES +=../../../../../../bsps/powerpc/shared/clock/clock.c librtemsbsp_a_SOURCES +=../../../../../../bsps/powerpc/tqm8xx/clock/p_clock.c # console -librtemsbsp_a_SOURCES += console/console.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/powerpc/tqm8xx/console/console.c # spi librtemsbsp_a_SOURCES += spi/spi.c # timer diff --git a/c/src/lib/libbsp/powerpc/tqm8xx/console/console.c b/c/src/lib/libbsp/powerpc/tqm8xx/console/console.c deleted file mode 100644 index 5a681b19fb..0000000000 --- a/c/src/lib/libbsp/powerpc/tqm8xx/console/console.c +++ /dev/null @@ -1,1115 +0,0 @@ -/*===============================================================*\ -| Project: RTEMS TQM8xx BSP | -+-----------------------------------------------------------------+ -| This file has been adapted to MPC8xx by | -| Thomas Doerfler | -| Copyright (c) 2008 | -| Embedded Brains GmbH | -| Obere Lagerstr. 30 | -| D-82178 Puchheim | -| Germany | -| rtems@embedded-brains.de | -| | -| See the other copyright notice below for the original parts. | -+-----------------------------------------------------------------+ -| The license and distribution terms for this file may be | -| found in the file LICENSE in this distribution or at | -| | -| http://www.rtems.org/license/LICENSE. | -| | -+-----------------------------------------------------------------+ -| this file contains the console driver | -\*===============================================================*/ -/* derived from: */ -/* - * SMC1/2 SCC1..4 raw console serial I/O. - * adapted to work with up to 4 SCC and 2 SMC - * - * This driver is an example of `TASK DRIVEN' `POLLING' or `INTERRUPT' I/O. - * - * To run with interrupt-driven I/O, ensure m8xx_smc1_interrupt - * is set before calling the initialization routine. - * - * Author: - * W. Eric Norum - * Saskatchewan Accelerator Laboratory - * University of Saskatchewan - * Saskatoon, Saskatchewan, CANADA - * eric@skatter.usask.ca - * - * 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. - */ - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -/* - * Interrupt-driven input buffer - */ -#define RXBUFSIZE 16 - -#define M8xx_SICR_BRG1 (0) -#define M8xx_SICR_BRG2 (1) -#define M8xx_SICR_BRG3 (2) -#define M8xx_SICR_BRG4 (3) - -#define M8xx_SICR_SCCRX_MSK(scc) (( 7) << (((scc))*8+3)) -#define M8xx_SICR_SCCRX(scc,clk) ((clk) << (((scc))*8+3)) - -#define M8xx_SICR_SCCTX_MSK(scc) (( 7) << (((scc))*8+0)) -#define M8xx_SICR_SCCTX(scc,clk) ((clk) << (((scc))*8+0)) - -#define M8xx_SIMODE_SMCCS(smc,clk) ((clk) << ((smc)*16+12)) -#define M8xx_SIMODE_SMCCS_MSK(smc) M8xx_SIMODE_SMCCS(smc,7) - -#define CONS_CHN_CNT 6 -#define CONS_CHN_SCC1 0 -#define CONS_CHN_SCC2 1 -#define CONS_CHN_SCC3 2 -#define CONS_CHN_SCC4 3 -#define CONS_CHN_SMC1 4 -#define CONS_CHN_SMC2 5 -#define CONS_CHN_NONE -1 - -/* - * possible identifiers for bspopts.h: CONS_SxCy_MODE - */ -#define CONS_MODE_UNUSED -1 -#define CONS_MODE_POLLED TERMIOS_POLLED -#define CONS_MODE_IRQ TERMIOS_IRQ_DRIVEN - -#define CHN_IS_SCC(chan) ((chan) < CONS_CHN_SMC1) - -#define BRG_CNT 4 - -#define MAX_IDL_DEFAULT 10 -#define DEVICEPREFIX "tty" - -/* - * Interrupt-driven callback - */ -static int m8xx_scc_mode[CONS_CHN_CNT]; -static void *sccttyp[CONS_CHN_CNT]; -typedef struct m8xx_console_chan_desc_s { - bool is_scc; /* true for SCC */ - struct { - volatile m8xxSCCparms_t *sccp; - volatile m8xxSMCparms_t *smcp; - } parms; - struct { - volatile m8xxSCCRegisters_t *sccr; - volatile m8xxSMCRegisters_t *smcr; - } regs; - int ivec_src; - int cr_chan_code; - int brg_used; -} m8xx_console_chan_desc_t; - -m8xx_console_chan_desc_t m8xx_console_chan_desc[CONS_CHN_CNT] = { - /* SCC1 */ - {TRUE, - {(m8xxSCCparms_t *)&(m8xx.scc1p),NULL}, - {&(m8xx.scc1),NULL}, - BSP_CPM_IRQ_SCC1, - M8xx_CR_CHAN_SCC1, - -1}, - /* SCC2 */ - {TRUE, - {&(m8xx.scc2p),NULL}, - {&(m8xx.scc2),NULL}, - BSP_CPM_IRQ_SCC2, - M8xx_CR_CHAN_SCC2, - -1}, - /* SCC3 */ - {TRUE, - {&(m8xx.scc3p),NULL}, - {&(m8xx.scc3),NULL}, - BSP_CPM_IRQ_SCC3, - M8xx_CR_CHAN_SCC3, - -1}, - /* SCC4 */ - {TRUE, - {&(m8xx.scc4p),NULL}, - {&(m8xx.scc4),NULL}, - BSP_CPM_IRQ_SCC4, - M8xx_CR_CHAN_SCC4, - -1}, - /* SMC1 */ - {FALSE, - {NULL,&(m8xx.smc1p)}, - {NULL,&(m8xx.smc1)}, - BSP_CPM_IRQ_SMC1, - M8xx_CR_CHAN_SMC1, - -1}, - /* SMC2 */ - {FALSE, - {NULL,&(m8xx.smc2p)}, - {NULL,&(m8xx.smc2)}, - BSP_CPM_IRQ_SMC2_OR_PIP, - M8xx_CR_CHAN_SMC2, - -1}}; - -#define CHN_PARAM_GET(chan,param) \ - (m8xx_console_chan_desc[chan].is_scc \ - ? m8xx_console_chan_desc[chan].parms.sccp->param \ - : m8xx_console_chan_desc[chan].parms.smcp->param) - -#define CHN_PARAM_SET(chan,param,value) \ - do {if (m8xx_console_chan_desc[chan].is_scc) \ - m8xx_console_chan_desc[chan].parms.sccp->param = value; \ - else \ - m8xx_console_chan_desc[chan].parms.smcp->param = value; \ - } while (0) - -#define CHN_EVENT_GET(chan) \ - (m8xx_console_chan_desc[chan].is_scc \ - ? m8xx_console_chan_desc[chan].regs.sccr->scce \ - : m8xx_console_chan_desc[chan].regs.smcr->smce) - -#define CHN_EVENT_CLR(chan,mask) \ - do { \ - if (m8xx_console_chan_desc[chan].is_scc) \ - m8xx_console_chan_desc[chan].regs.sccr->scce = (mask); \ - else \ - m8xx_console_chan_desc[chan].regs.smcr->smce = (mask); \ - }while (0) - -#define CHN_MASK_GET(chan) \ - (m8xx_console_chan_desc[chan].is_scc \ - ? m8xx_console_chan_desc[chan].regs.sccr->sccm \ - : m8xx_console_chan_desc[chan].regs.smcr->smcm) - -#define CHN_MASK_SET(chan,mask) \ - do { \ - if (m8xx_console_chan_desc[chan].is_scc) \ - m8xx_console_chan_desc[chan].regs.sccr->sccm = (mask); \ - else \ - m8xx_console_chan_desc[chan].regs.smcr->smcm = (mask); \ - }while (0) - - -/* - * I/O buffers and pointers to buffer descriptors - */ -#define SCC_RXBD_CNT 4 -#define SCC_TXBD_CNT 4 -typedef volatile char sccRxBuf_t[SCC_RXBD_CNT][RXBUFSIZE]; -static sccRxBuf_t *rxBuf[CONS_CHN_CNT]; - -static volatile m8xxBufferDescriptor_t *sccFrstRxBd[CONS_CHN_CNT]; -static volatile m8xxBufferDescriptor_t *sccCurrRxBd[CONS_CHN_CNT]; -static volatile m8xxBufferDescriptor_t *sccFrstTxBd[CONS_CHN_CNT]; -static volatile m8xxBufferDescriptor_t *sccPrepTxBd[CONS_CHN_CNT]; -static volatile m8xxBufferDescriptor_t *sccDequTxBd[CONS_CHN_CNT]; - -/* - * Compute baud-rate-generator configuration register value - */ -static uint32_t -sccBRGval (int baud) -{ - int divisor; - int div16 = 0; - - divisor = ((BSP_bus_frequency / 16) + (baud / 2)) / baud; - if (divisor > 4096) { - div16 = 1; - divisor = (divisor + 8) / 16; - } - return M8xx_BRG_EN | M8xx_BRG_EXTC_BRGCLK | ((divisor - 1) << 1) | div16; -} - -typedef struct { - uint32_t reg_content; - int link_cnt; -}brg_state_t; -brg_state_t scc_brg_state[BRG_CNT]; - -/* - * initialize brg_state - */ -static void sccBRGinit(void) -{ - int brg_idx; - - for (brg_idx = 0;brg_idx < BRG_CNT;brg_idx++) { - scc_brg_state[brg_idx].reg_content = 0; - scc_brg_state[brg_idx].link_cnt = 0; - } -#ifndef MDE360 - /* - * on ZEM40, init CLK4/5 inputs - */ - m8xx.papar |= ((1 << 11) | (1 << 12)); - m8xx.padir &= ~((1 << 11) | (1 << 12)); -#endif -} - -#if CONS_USE_EXT_CLK -/* - * input clock frq for CPM clock inputs - */ -static uint32_t clkin_frq[2][4] = { -#ifdef MDE360 - {0,0,0,0}, - {0,0,0,0} -#else - {0,0,0,1843000}, - {1843000,0,0,0} -#endif -}; -#endif - -/* - * allocate, set and connect baud rate generators - * FIXME: or clock input - * FIXME: set pin to be clock input - */ - -static int sccBRGalloc(int chan,int baud) -{ - rtems_interrupt_level level; - m8xx_console_chan_desc_t *chan_desc = &(m8xx_console_chan_desc[chan]); - uint32_t reg_val; - int old_brg; - int new_brg = -1; - int brg_idx; -#if CONS_USE_EXT_CLK - int clk_group; - int clk_sel; -#endif - - old_brg = chan_desc->brg_used; - /* compute brg register contents needed */ - reg_val = sccBRGval(baud); - -#if CONS_EXT_CLK - /* search for clock input with this frq */ - clk_group = ((chan == CONS_CHN_SCC3) || - (chan == CONS_CHN_SCC4) || - (chan == CONS_CHN_SMC2)) ? 1 : 0; - - for (clk_sel = 0, new_brg = -1; - (clk_sel < 4) && (new_brg < 0); - clk_sel++) { - if (baud == (clkin_frq[clk_group][clk_sel] / 16)) { - new_brg = clk_sel + 4; - } - } -#endif - - rtems_interrupt_disable(level); - - if (new_brg < 0) { - /* search for brg with this settings */ - for (brg_idx = 0; - (new_brg < 0) && (brg_idx < BRG_CNT); - brg_idx++) { - if (scc_brg_state[brg_idx].reg_content == reg_val) { - new_brg = brg_idx; - } - } - /* - * if not found: check, whether brg currently in use - * is linked only from our channel - */ - if ((new_brg < 0) && - (old_brg >= 0) && - (scc_brg_state[old_brg].link_cnt == 1)) { - new_brg = old_brg; - } - /* if not found: search for unused brg, set it */ - for (brg_idx = 0; - (new_brg < 0) && (brg_idx < BRG_CNT); - brg_idx++) { - if (scc_brg_state[brg_idx].link_cnt == 0) { - new_brg = brg_idx; - } - } - } - - /* decrease old link count */ - if ((old_brg >= 0) && - (old_brg < 4)) { - scc_brg_state[old_brg].link_cnt--; - } - /* increase new brg link count, set brg */ - if ((new_brg >= 0) && - (new_brg < 4)) { - scc_brg_state[new_brg].link_cnt++; - scc_brg_state[new_brg].reg_content = reg_val; - (&m8xx.brgc1)[new_brg] = reg_val; - } - rtems_interrupt_enable(level); - - /* connect to scc/smc */ - if (new_brg >= 0) { - m8xx_console_chan_desc[chan].brg_used = new_brg; - /* - * Put SCC in NMSI mode, connect SCC to BRG or CLKx - */ - if (m8xx_console_chan_desc[chan].is_scc) { - m8xx.sicr = ((m8xx.sicr & ~(M8xx_SICR_SCCRX_MSK(chan) | - M8xx_SICR_SCCTX_MSK(chan))) | - M8xx_SICR_SCCRX(chan,new_brg)| - M8xx_SICR_SCCTX(chan,new_brg)); - } - else { - /* connect SMC to BRGx or CLKx... */ - m8xx.simode = ((m8xx.simode & ~(M8xx_SIMODE_SMCCS_MSK(chan - CONS_CHN_SMC1)))| - M8xx_SIMODE_SMCCS(chan - CONS_CHN_SMC1,new_brg)); - } - } - return (new_brg < 0); -} - - -/* - * Hardware-dependent portion of tcsetattr(). - */ -static int -sccSetAttributes (int minor, const struct termios *t) -{ - int baud; - - switch (t->c_ospeed) { - default: baud = -1; break; - case B50: baud = 50; break; - case B75: baud = 75; break; - case B110: baud = 110; break; - case B134: baud = 134; break; - case B150: baud = 150; break; - case B200: baud = 200; break; - case B300: baud = 300; break; - case B600: baud = 600; break; - case B1200: baud = 1200; break; - case B1800: baud = 1800; break; - case B2400: baud = 2400; break; - case B4800: baud = 4800; break; - case B9600: baud = 9600; break; - case B19200: baud = 19200; break; - case B38400: baud = 38400; break; - case B57600: baud = 57600; break; - case B115200: baud = 115200; break; - case B230400: baud = 230400; break; - case B460800: baud = 460800; break; - } - return sccBRGalloc(minor,baud); - return 0; -} - -/* - * Interrupt handler - */ -static rtems_isr -sccInterruptHandler (void *arg) -{ - int chan = (int)arg; - - /* - * Buffer received? - */ - if (CHN_EVENT_GET(chan) & 0x1) { - /* - * clear SCC event flag - */ - CHN_EVENT_CLR(chan,0x01); - /* - * process event - */ - while ((sccCurrRxBd[chan]->status & M8xx_BD_EMPTY) == 0) { - if (sccttyp[chan] != NULL) { - rtems_cache_invalidate_multiple_data_lines((void *)sccCurrRxBd[chan]->buffer, - sccCurrRxBd[chan]->length); - rtems_termios_enqueue_raw_characters (sccttyp[chan], - (char *)sccCurrRxBd[chan]->buffer, - sccCurrRxBd[chan]->length); - } - /* - * clear status - */ - sccCurrRxBd[chan]->status = - (sccCurrRxBd[chan]->status - & (M8xx_BD_WRAP | M8xx_BD_INTERRUPT)) - | M8xx_BD_EMPTY; - /* - * advance to next BD - */ - if ((sccCurrRxBd[chan]->status & M8xx_BD_WRAP) != 0) { - sccCurrRxBd[chan] = sccFrstRxBd[chan]; - } - else { - sccCurrRxBd[chan]++; - } - } - } - /* - * Buffer transmitted? - */ - if (CHN_EVENT_GET(chan) & 0x2) { - /* - * then clear interrupt event bit - */ - CHN_EVENT_CLR(chan,0x2); - /* - * and signal successful transmit to termios - */ - /* - * FIXME: multiple dequeue calls for multiple buffers - */ - while((sccDequTxBd[chan] != sccPrepTxBd[chan]) && - ((sccDequTxBd[chan]->status & M8xx_BD_READY) == 0)) { - if (sccttyp[chan] != NULL) { - rtems_termios_dequeue_characters (sccttyp[chan], - sccDequTxBd[chan]->length); - } - /* - * advance to next BD - */ - if ((sccDequTxBd[chan]->status & M8xx_BD_WRAP) != 0) { - sccDequTxBd[chan] = sccFrstTxBd[chan]; - } - else { - sccDequTxBd[chan]++; - } - } - } -} - -static void -mpc8xx_console_irq_on(const rtems_irq_connect_data *irq) -{ - CHN_MASK_SET(irq->name - BSP_CPM_IRQ_LOWEST_OFFSET, - 3); /* Enable TX and RX interrupts */ -} - -static void -mpc8xx_console_irq_off(const rtems_irq_connect_data *irq) -{ - CHN_MASK_SET(irq->name - BSP_CPM_IRQ_LOWEST_OFFSET, - 0); /* Disable TX and RX interrupts */ -} - -static int -mpc8xx_console_irq_isOn(const rtems_irq_connect_data *irq) -{ - return (0 != CHN_MASK_GET(irq->name - BSP_CPM_IRQ_LOWEST_OFFSET)); /* Check TX and RX interrupts */ -} - -static void -sccInitialize (int chan) -{ - int i; - /* - * allocate buffers - * FIXME: use a cache-line size boundary alloc here - */ - rxBuf[chan] = malloc(sizeof(*rxBuf[chan]) + 2*PPC_CACHE_ALIGNMENT); - if (rxBuf[chan] == NULL) { - rtems_panic("Cannot allocate console rx buffer\n"); - } - else { - /* - * round up rxBuf[chan] to start at a cache line size - */ - rxBuf[chan] = (sccRxBuf_t *) - (((uint32_t)rxBuf[chan]) + - (PPC_CACHE_ALIGNMENT - - ((uint32_t)rxBuf[chan]) % PPC_CACHE_ALIGNMENT)); - } - /* - * Allocate buffer descriptors - */ - sccCurrRxBd[chan] = - sccFrstRxBd[chan] = m8xx_bd_allocate(SCC_RXBD_CNT); - sccPrepTxBd[chan] = - sccDequTxBd[chan] = - sccFrstTxBd[chan] = m8xx_bd_allocate(SCC_TXBD_CNT); - switch(chan) { - case CONS_CHN_SCC1: - /* - * Configure port A pins to enable TXD1 and RXD1 pins - * FIXME: add setup for modem control lines.... - */ - m8xx.papar |= 0x03; - m8xx.padir &= ~0x03; - - /* - * Configure port C pins to enable RTS1 pins (static active low) - */ - m8xx.pcpar &= ~0x01; - m8xx.pcso &= ~0x01; - m8xx.pcdir |= 0x01; - m8xx.pcdat &= ~0x01; - break; - case CONS_CHN_SCC2: - /* - * Configure port A pins to enable TXD2 and RXD2 pins - * FIXME: add setup for modem control lines.... - */ - m8xx.papar |= 0x0C; - m8xx.padir &= ~0x0C; - - /* - * Configure port C pins to enable RTS2 pins (static active low) - */ - m8xx.pcpar &= ~0x02; - m8xx.pcso &= ~0x02; - m8xx.pcdir |= 0x02; - m8xx.pcdat &= ~0x02; - break; - case CONS_CHN_SCC3: - /* - * Configure port A pins to enable TXD3 and RXD3 pins - * FIXME: add setup for modem control lines.... - */ - m8xx.papar |= 0x30; - m8xx.padir &= ~0x30; - - /* - * Configure port C pins to enable RTS3 (static active low) - */ - m8xx.pcpar &= ~0x04; - m8xx.pcso &= ~0x04; - m8xx.pcdir |= 0x04; - m8xx.pcdat &= ~0x04; - break; - case CONS_CHN_SCC4: - /* - * Configure port A pins to enable TXD4 and RXD4 pins - * FIXME: add setup for modem control lines.... - */ - m8xx.papar |= 0xC0; - m8xx.padir &= ~0xC0; - - /* - * Configure port C pins to enable RTS4 pins (static active low) - */ - m8xx.pcpar &= ~0x08; - m8xx.pcso &= ~0x08; - m8xx.pcdir |= 0x08; - m8xx.pcdat &= ~0x08; - break; - case CONS_CHN_SMC1: - /* - * Configure port B pins to enable SMTXD1 and SMRXD1 pins - */ - m8xx.pbpar |= 0xC0; - m8xx.pbdir &= ~0xC0; - break; - case CONS_CHN_SMC2: - /* - * Configure port B pins to enable SMTXD2 and SMRXD2 pins - */ - m8xx.pbpar |= 0xC00; - m8xx.pbdir &= ~0xC00; - break; - } - /* - * allocate and connect BRG - */ - sccBRGalloc(chan,9600); - - - /* - * Set up SCCx parameter RAM common to all protocols - */ - CHN_PARAM_SET(chan,rbase,(char *)sccFrstRxBd[chan] - (char *)&m8xx); - CHN_PARAM_SET(chan,tbase,(char *)sccFrstTxBd[chan] - (char *)&m8xx); - CHN_PARAM_SET(chan,rfcr ,M8xx_RFCR_MOT | M8xx_RFCR_DMA_SPACE(0)); - CHN_PARAM_SET(chan,tfcr ,M8xx_TFCR_MOT | M8xx_TFCR_DMA_SPACE(0)); - if (m8xx_scc_mode[chan] != TERMIOS_POLLED) - CHN_PARAM_SET(chan,mrblr,RXBUFSIZE); - else - CHN_PARAM_SET(chan,mrblr,1); - - /* - * Set up SCCx parameter RAM UART-specific parameters - */ - CHN_PARAM_SET(chan,un.uart.max_idl ,MAX_IDL_DEFAULT); - CHN_PARAM_SET(chan,un.uart.brkln ,0); - CHN_PARAM_SET(chan,un.uart.brkec ,0); - CHN_PARAM_SET(chan,un.uart.brkcr ,0); - if (m8xx_console_chan_desc[chan].is_scc) { - m8xx_console_chan_desc[chan].parms.sccp->un.uart.character[0]=0x8000; /* no char filter */ - m8xx_console_chan_desc[chan].parms.sccp->un.uart.rccm=0x80FF; /* control character mask */ - } - - /* - * Set up the Receive Buffer Descriptors - */ - for (i = 0;i < SCC_RXBD_CNT;i++) { - sccFrstRxBd[chan][i].status = M8xx_BD_EMPTY | M8xx_BD_INTERRUPT; - if (i == SCC_RXBD_CNT-1) { - sccFrstRxBd[chan][i].status |= M8xx_BD_WRAP; - } - sccFrstRxBd[chan][i].length = 0; - sccFrstRxBd[chan][i].buffer = (*rxBuf[chan])[i]; - } - /* - * Setup the Transmit Buffer Descriptor - */ - for (i = 0;i < SCC_TXBD_CNT;i++) { - sccFrstTxBd[chan][i].status = M8xx_BD_INTERRUPT; - if (i == SCC_TXBD_CNT-1) { - sccFrstTxBd[chan][i].status |= M8xx_BD_WRAP; - } - sccFrstTxBd[chan][i].length = 0; - sccFrstTxBd[chan][i].buffer = NULL; - } - - /* - * Set up SCC general and protocol-specific mode registers - */ - CHN_EVENT_CLR(chan,~0); /* Clear any pending events */ - CHN_MASK_SET(chan,0); /* Mask all interrupt/event sources */ - - if (m8xx_console_chan_desc[chan].is_scc) { - m8xx_console_chan_desc[chan].regs.sccr->psmr = 0xb000; /* 8N1, CTS flow control */ - m8xx_console_chan_desc[chan].regs.sccr->gsmr_h = 0x00000000; - m8xx_console_chan_desc[chan].regs.sccr->gsmr_l = 0x00028004; /* UART mode */ - } - else { - m8xx_console_chan_desc[chan].regs.smcr->smcmr = 0x4820; - } - /* - * Send "Init parameters" command - */ - m8xx_cp_execute_cmd(M8xx_CR_OP_INIT_RX_TX - | m8xx_console_chan_desc[chan].cr_chan_code); - - /* - * Enable receiver and transmitter - */ - if (m8xx_console_chan_desc[chan].is_scc) { - m8xx_console_chan_desc[chan].regs.sccr->gsmr_l |= 0x00000030; - } - else { - m8xx_console_chan_desc[chan].regs.smcr->smcmr |= 0x0003; - } - - if (m8xx_scc_mode[chan] != TERMIOS_POLLED) { - - rtems_irq_connect_data irq_conn_data = { - m8xx_console_chan_desc[chan].ivec_src, - sccInterruptHandler, /* rtems_irq_hdl */ - (rtems_irq_hdl_param)chan, /* (rtems_irq_hdl_param) */ - mpc8xx_console_irq_on, /* (rtems_irq_enable) */ - mpc8xx_console_irq_off, /* (rtems_irq_disable) */ - mpc8xx_console_irq_isOn /* (rtems_irq_is_enabled) */ - }; - if (!BSP_install_rtems_irq_handler (&irq_conn_data)) { - rtems_panic("console: cannot install IRQ handler"); - } - } -} - -/* - * polled scc read function - */ -static int -sccPollRead (int minor) -{ - int c = -1; - int chan = minor; - - while(1) { - if ((sccCurrRxBd[chan]->status & M8xx_BD_EMPTY) != 0) { - return -1; - } - - if (0 == (sccCurrRxBd[chan]->status & (M8xx_BD_OVERRUN - | M8xx_BD_PARITY_ERROR - | M8xx_BD_FRAMING_ERROR - | M8xx_BD_BREAK - | M8xx_BD_IDLE))) { - /* character received and no error detected */ - rtems_cache_invalidate_multiple_data_lines((void *)sccCurrRxBd[chan]->buffer, - sccCurrRxBd[chan]->length); - c = (unsigned)*((char *)sccCurrRxBd[chan]->buffer); - /* - * clear status - */ - } - sccCurrRxBd[chan]->status = - (sccCurrRxBd[chan]->status - & (M8xx_BD_WRAP | M8xx_BD_INTERRUPT)) - | M8xx_BD_EMPTY; - /* - * advance to next BD - */ - if ((sccCurrRxBd[chan]->status & M8xx_BD_WRAP) != 0) { - sccCurrRxBd[chan] = sccFrstRxBd[chan]; - } - else { - sccCurrRxBd[chan]++; - } - if (c >= 0) { - return c; - } - } -} - - -/* - * Device-dependent write routine - * Interrupt-driven devices: - * Begin transmission of as many characters as possible (minimum is 1). - * Polling devices: - * Transmit all characters. - */ -static ssize_t -sccInterruptWrite (int minor, const char *buf, size_t len) -{ - if (len > 0) { - int chan = minor; - - if ((sccPrepTxBd[chan]->status & M8xx_BD_READY) == 0) { - sccPrepTxBd[chan]->buffer = (char *)buf; - sccPrepTxBd[chan]->length = len; - rtems_cache_flush_multiple_data_lines((const void *)buf,len); - /* - * clear status, set ready bit - */ - sccPrepTxBd[chan]->status = - (sccPrepTxBd[chan]->status - & M8xx_BD_WRAP) - | M8xx_BD_READY | M8xx_BD_INTERRUPT; - if ((sccPrepTxBd[chan]->status & M8xx_BD_WRAP) != 0) { - sccPrepTxBd[chan] = sccFrstTxBd[chan]; - } - else { - sccPrepTxBd[chan]++; - } - } - } - - return 0; -} - -static ssize_t -sccPollWrite (int minor, const char *buf, size_t len) -{ - static char txBuf[CONS_CHN_CNT][SCC_TXBD_CNT]; - int chan = minor; - int bd_used; - size_t retval = len; - - while (len--) { - while (sccPrepTxBd[chan]->status & M8xx_BD_READY) - continue; - bd_used = sccPrepTxBd[chan]-sccFrstTxBd[chan]; - txBuf[chan][bd_used] = *buf++; - rtems_cache_flush_multiple_data_lines((const void *)&txBuf[chan][bd_used], - sizeof(txBuf[chan][bd_used])); - sccPrepTxBd[chan]->buffer = &(txBuf[chan][bd_used]); - sccPrepTxBd[chan]->length = 1; - sccPrepTxBd[chan]->status = - (sccPrepTxBd[chan]->status - & M8xx_BD_WRAP) - | M8xx_BD_READY; - if ((sccPrepTxBd[chan]->status & M8xx_BD_WRAP) != 0) { - sccPrepTxBd[chan] = sccFrstTxBd[chan]; - } - else { - sccPrepTxBd[chan]++; - } - } - return retval; -} - -/* - * printk basic support - */ -int BSP_output_chan = CONS_CHN_NONE; /* channel used for printk operation */ - -static void console_debug_putc_onlcr(const char c) -{ - rtems_interrupt_level irq_level; - - if (BSP_output_chan != CONS_CHN_NONE) { - rtems_interrupt_disable(irq_level); - - sccPollWrite (BSP_output_chan,&c,1); - rtems_interrupt_enable(irq_level); - } -} - -BSP_output_char_function_type BSP_output_char = console_debug_putc_onlcr; -BSP_polling_getchar_function_type BSP_poll_char = NULL; - - -/* -*************** -* BOILERPLATE * -*************** -*/ - -struct { - rtems_device_minor_number minor; - int driver_mode; -} channel_list[] = { - {CONS_CHN_SMC1,CONS_SMC1_MODE}, - {CONS_CHN_SMC2,CONS_SMC2_MODE}, - {CONS_CHN_SCC1,CONS_SCC1_MODE}, - {CONS_CHN_SCC2,CONS_SCC2_MODE}, - {CONS_CHN_SCC3,CONS_SCC3_MODE}, - {CONS_CHN_SCC4,CONS_SCC4_MODE} -}; - - -/* - * Initialize and register the device - */ -rtems_device_driver console_initialize(rtems_device_major_number major, - rtems_device_minor_number minor,/* ignored */ - void *arg - ) -{ - rtems_status_code status = RTEMS_SUCCESSFUL; - int chan,entry,ttynum; - char tty_name[] = "/dev/tty00"; - - /* - * Set up TERMIOS - */ - rtems_termios_initialize (); - /* - * init BRG allocataion - */ - sccBRGinit(); - ttynum = 0; - for (entry = 0; - (entry < sizeof(channel_list)/sizeof(channel_list[0])) - && (status == RTEMS_SUCCESSFUL); - entry++) { - if (channel_list[entry].driver_mode != CONS_MODE_UNUSED) { - /* - * Do device-specific initialization - */ - chan = channel_list[entry].minor; - m8xx_scc_mode[chan] = channel_list[entry].driver_mode; - sccInitialize (chan); - - /* - * build device name - */ - tty_name[sizeof(tty_name)-2] = '0'+ttynum; - ttynum++; - /* - * Register the device - */ - status = rtems_io_register_name (tty_name, - major, - channel_list[entry].minor); - if (status != RTEMS_SUCCESSFUL) { - rtems_fatal_error_occurred (status); - } - } - } - /* - * register /dev/console - */ - status = rtems_io_register_name ("/dev/console", - major, - CONSOLE_CHN); - if (status != RTEMS_SUCCESSFUL) { - rtems_fatal_error_occurred (status); - } - /* - * enable printk support - */ - BSP_output_chan = PRINTK_CHN; - - return RTEMS_SUCCESSFUL; -} - -/* - * Open the device - */ -rtems_device_driver console_open( - rtems_device_major_number major, - rtems_device_minor_number minor, - void * arg - ) -{ - rtems_status_code status; - int chan = minor; - rtems_libio_open_close_args_t *args = (rtems_libio_open_close_args_t *)arg; - static const rtems_termios_callbacks interruptCallbacks = { - NULL, /* firstOpen */ - NULL, /* lastClose */ - NULL, /* pollRead */ - sccInterruptWrite, /* write */ - sccSetAttributes, /* setAttributes */ - NULL, /* stopRemoteTx */ - NULL, /* startRemoteTx */ - TERMIOS_IRQ_DRIVEN /* outputUsesInterrupts */ - }; - static const rtems_termios_callbacks pollCallbacks = { - NULL, /* firstOpen */ - NULL, /* lastClose */ - sccPollRead, /* pollRead */ - sccPollWrite, /* write */ - sccSetAttributes, /* setAttributes */ - NULL, /* stopRemoteTx */ - NULL, /* startRemoteTx */ - 0 /* outputUsesInterrupts */ - }; - - if (m8xx_scc_mode[chan] == TERMIOS_IRQ_DRIVEN) { - status = rtems_termios_open (major, minor, arg, &interruptCallbacks); - sccttyp[chan] = args->iop->data1; - } - else { - status = rtems_termios_open (major, minor, arg, &pollCallbacks); - sccttyp[chan] = args->iop->data1; - } - return status; -} - -/* - * Close the device - */ -rtems_device_driver console_close( - rtems_device_major_number major, - rtems_device_minor_number minor, - void * arg - ) -{ - rtems_status_code rc; - - rc = rtems_termios_close (arg); - sccttyp[minor] = NULL; - - return rc; - -} - -/* - * Read from the device - */ -rtems_device_driver console_read( - rtems_device_major_number major, - rtems_device_minor_number minor, - void * arg - ) -{ - return rtems_termios_read (arg); -} - -/* - * Write to the device - */ -rtems_device_driver console_write( - rtems_device_major_number major, - rtems_device_minor_number minor, - void * arg - ) -{ - return rtems_termios_write (arg); -} - -#if 0 -static int scc_io_set_trm_char(rtems_device_minor_number minor, - rtems_libio_ioctl_args_t *ioa) -{ - rtems_status_code rc = RTEMS_SUCCESSFUL; - con360_io_trm_char_t *trm_char_info = ioa->buffer; - - /* - * check, that parameter is non-NULL - */ - if ((rc == RTEMS_SUCCESSFUL) && - (trm_char_info == NULL)) { - rc = RTEMS_INVALID_ADDRESS; - } - /* - * transfer max_idl - */ - if (rc == RTEMS_SUCCESSFUL) { - if (trm_char_info->max_idl >= 0x10000) { - rc = RTEMS_INVALID_NUMBER; - } - else if (trm_char_info->max_idl > 0) { - CHN_PARAM_SET(minor,un.uart.max_idl ,trm_char_info->max_idl); - } - else if (trm_char_info->max_idl == 0) { - CHN_PARAM_SET(minor,un.uart.max_idl ,MAX_IDL_DEFAULT); - } - } - /* - * transfer characters - */ - if (rc == RTEMS_SUCCESSFUL) { - if (trm_char_info->char_cnt > CON8XX_TRM_CHAR_CNT) { - rc = RTEMS_TOO_MANY; - } - else if (trm_char_info->char_cnt >= 0) { - /* - * check, whether device is a SCC - */ - if ((rc == RTEMS_SUCCESSFUL) && - !m8xx_console_chan_desc[minor].is_scc) { - rc = RTEMS_UNSATISFIED; - } - else { - int idx = 0; - for(idx = 0;idx < trm_char_info->char_cnt;idx++) { - m8xx_console_chan_desc[minor].parms.sccp->un.uart.character[idx] = - trm_char_info->character[idx] & 0x00ff; - } - if (trm_char_info->char_cnt < CON8XX_TRM_CHAR_CNT) { - m8xx_console_chan_desc[minor].parms.sccp - ->un.uart.character[trm_char_info->char_cnt] = 0x8000; - } - } - } - } - - return rc; -} -#endif - -/* - * Handle ioctl request. - */ -rtems_device_driver console_control( - rtems_device_major_number major, - rtems_device_minor_number minor, - void * arg - ) -{ - rtems_libio_ioctl_args_t *ioa=arg; - - switch (ioa->command) { -#if 0 - case CON8XX_IO_SET_TRM_CHAR: - return scc_io_set_trm_char(minor, ioa); -#endif - default: - return rtems_termios_ioctl (arg); - break; - } -} - -- cgit v1.2.3