📄 console-generic.c
字号:
/* * General Serial I/O functions. * * This file contains the functions for performing serial I/O. * The actual system calls (console_*) should be in the BSP part * of the source tree. That way different BSPs can use whichever * SMCs and SCCs they want. Originally, all the stuff was in * this file, and it caused problems with one BSP using SCC2 * as /dev/console, others using SMC1 for /dev/console, etc. * * On-chip resources used: * resource minor note * SMC1 0 * SMC2 1 * SCC1 2 N/A. Hardwired as ethernet port * SCC2 3 * SCC3 4 * SCC4 5 * BRG1 * BRG2 * BRG3 * BRG4 * Author: Jay Monkman (jmonkman@frasca.com) * Copyright (C) 1998 by Frasca International, Inc. * * Derived from c/src/lib/libbsp/m68k/gen360/console/console.c written by: * 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). * * Modifications by Darlene Stewart <Darlene.Stewart@iit.nrc.ca> * and Charles-Antoine Gauthier <charles.gauthier@iit.nrc.ca> * Copyright (c) 1999, National Research Council of Canada * * The license and distribution terms for this file may be * found in the file LICENSE in this distribution or at * * http://www.rtems.com/license/LICENSE. * * $Id: console-generic.c,v 1.14.2.1 2003/09/04 18:45:53 joel Exp $ */#include <rtems.h>#include <rtems/libio.h>#include <mpc8xx.h>#include <mpc8xx/console.h>#include <mpc8xx/cpm.h>#include <stdlib.h>#include <unistd.h>#include <termios.h>#include <bsp/irq.h>#include <rtems/bspIo.h> /* for printk */int BSP_irq_enabled_at_cpm(const rtems_irq_symbolic_name irqLine);extern rtems_cpu_table Cpu_table;/* BSP supplied routine */extern int mbx8xx_console_get_configuration();/* * Interrupt-driven input buffer */#define RXBUFSIZE 16/* * I/O buffers and pointers to buffer descriptors. * Currently, single buffered input is done. This will work only * if the Rx interrupts are serviced quickly. * * TODO: Add a least double buffering for safety. */static volatile char rxBuf[NUM_PORTS][RXBUFSIZE];static volatile char txBuf[NUM_PORTS];/* SCC/SMC buffer descriptors */static volatile m8xxBufferDescriptor_t *RxBd[NUM_PORTS], *TxBd[NUM_PORTS];/* Used to track the usage of the baud rate generators */static unsigned long brg_spd[4];static char brg_used[4];/* Used to track termios private data for callbacks */struct rtems_termios_tty *ttyp[NUM_PORTS];/* * Device-specific routines */static int m8xx_get_brg_cd(int);static unsigned char m8xx_get_brg_clk(int);void m8xx_console_reserve_resources(rtems_configuration_table *);static int m8xx_smc_set_attributes(int, const struct termios*);static int m8xx_scc_set_attributes(int, const struct termios*);static void m8xx_smc1_interrupt_handler(void);static void m8xx_smc2_interrupt_handler(void);static void m8xx_scc2_interrupt_handler(void);#if defined(mpc860)static void m8xx_scc3_interrupt_handler(void);static void m8xx_scc4_interrupt_handler(void);#endif/* * Compute baud-rate-generator configuration register value */static intm8xx_get_brg_cd (int baud){ int divisor; int div16 = 0; divisor = ((Cpu_table.clock_speed / 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;}/* * This function will fail if more that 4 baud rates have been selected * at any time since the OS started. It needs to be fixed. FIXME */static unsignedchar m8xx_get_brg_clk(int baud){ int i; /* first try to find a BRG that is already at the right speed */ for ( i = 0; i < 4; i++ ) { if ( brg_spd[i] == baud ) { break; } } if ( i == 4 ) { /* I guess we didn't find one */ for ( i = 0; i < 4; i++ ) { if ( brg_used[i] == 0 ) { break; } } } if (i != 4) { brg_used[i]++; brg_spd[i]=baud; switch (i) { case 0: m8xx.brgc1 = M8xx_BRG_RST; m8xx.brgc1 = m8xx_get_brg_cd(baud); break; case 1: m8xx.brgc2 = M8xx_BRG_RST; m8xx.brgc2 = m8xx_get_brg_cd(baud); break; case 2: m8xx.brgc3 = M8xx_BRG_RST; m8xx.brgc3 = m8xx_get_brg_cd(baud); break; case 3: m8xx.brgc4 = M8xx_BRG_RST; m8xx.brgc4 = m8xx_get_brg_cd(baud); break; } return i; } else return 0xff;}/* * Hardware-dependent portion of tcsetattr(). */static intm8xx_smc_set_attributes (int minor, const struct termios *t){ int baud, brg=0, csize=0, ssize, psize; rtems_unsigned16 clen=0, cstopb, parenb, parodd, cread; /* Baud rate */ switch (t->c_cflag & CBAUD) { 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; } if (baud > 0) brg = m8xx_get_brg_clk(baud); /* 4 BRGs, 6 serial ports - hopefully */ /* at least 2 ports will be the same */ /* Number of data bits */ switch ( t->c_cflag & CSIZE ) { case CS5: csize = 5; break; case CS6: csize = 6; break; case CS7: csize = 7; break; case CS8: csize = 8; break; } /* Stop bits */ if ( t->c_cflag & CSTOPB ) { cstopb = 0x0400; /* Two stop bits */ ssize = 2; } else { cstopb = 0x0000; /* One stop bit */ ssize = 1; } /* Parity */ if ( t->c_cflag & PARENB ) { parenb = 0x0200; /* Parity enabled on Tx and Rx */ psize = 1; } else { parenb = 0x0000; /* No parity on Tx and Rx */ psize = 0; } if ( t->c_cflag & PARODD ) parodd = 0x0000; /* Odd parity */ else parodd = 0x0100; /* * Character Length = start + data + parity + stop - 1 */ switch ( 1 + csize + psize + ssize - 1 ) { case 6: clen = 0x3000; break; case 7: clen = 0x3800; break; case 8: clen = 0x4000; break; case 9: clen = 0x4800; break; case 10: clen = 0x5000; break; case 11: clen = 0x5800; break; } if ( t->c_cflag & CREAD ) cread = 0x0023; /* UART normal operation, enable Rx and Tx */ else cread = 0x0021; /* UART normal operation, enable Tx */ /* Write the SIMODE/SMCMR registers */ switch (minor) { case SMC1_MINOR: m8xx.simode = ( (m8xx.simode & 0xffff8fff) | (brg << 12) ); m8xx.smc1.smcmr = clen | cstopb | parenb | parodd | cread; break; case SMC2_MINOR: m8xx.simode = ( (m8xx.simode & 0x8fffffff) | (brg << 28) ); m8xx.smc2.smcmr = clen | cstopb | parenb | parodd | cread; break; } return 0;}static intm8xx_scc_set_attributes (int minor, const struct termios *t){ int baud, brg=0; rtems_unsigned16 csize=0, cstopb, parenb, parodd; /* Baud rate */ switch (t->c_cflag & CBAUD) { 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; } if (baud > 0) brg = m8xx_get_brg_clk(baud); /* 4 BRGs, 5 serial ports - hopefully */ /* at least 2 ports will be the same */ /* Write the SICR register below */ /* Number of data bits */ switch ( t->c_cflag & CSIZE ) { case CS5: csize = 0x0000; break; case CS6: csize = 0x1000; break; case CS7: csize = 0x2000; break; case CS8: csize = 0x3000; break; } /* Stop bits */ if ( t->c_cflag & CSTOPB ) cstopb = 0x4000; /* Two stop bits */ else cstopb = 0x0000; /* One stop bit */ /* Parity */ if ( t->c_cflag & PARENB ) parenb = 0x0010; /* Parity enabled on Tx and Rx */ else parenb = 0x0000; /* No parity on Tx and Rx */ if ( t->c_cflag & PARODD ) parodd = 0x0000; /* Odd parity */ else parodd = 0x000a; /* Write the SICR/PSMR Registers */ switch (minor) { case SCC2_MINOR: m8xx.sicr = ( (m8xx.sicr & 0xffffc0ff) | (brg << 11) | (brg << 8) ); m8xx.scc2.psmr = ( (cstopb | csize | parenb | parodd) | (m8xx.scc2.psmr & 0x8fe0) ); break; #if defined(mpc860) case SCC3_MINOR: m8xx.sicr = ( (m8xx.sicr & 0xffc0ffff) | (brg << 19) | (brg << 16) ); m8xx.scc3.psmr = ( (cstopb | csize | parenb | parodd) | (m8xx.scc3.psmr & 0x8fe0) ); break; case SCC4_MINOR: m8xx.sicr = ( (m8xx.sicr & 0xc0ffffff) | (brg << 27) | (brg << 24) ); m8xx.scc4.psmr = ( (cstopb | csize | parenb | parodd) | (m8xx.scc4.psmr & 0x8fe0) ); break; #endif } return 0;}int m8xx_uart_setAttributes( int minor, const struct termios *t){ /* * Check that port number is valid */ if ( (minor < SMC1_MINOR) || (minor > NUM_PORTS-1) ) return 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -