📄 mg5uart.c
字号:
/* * This file contains the termios TTY driver for the UART found * on the Synova Mongoose-V. * * COPYRIGHT (c) 1989-2001. * On-Line Applications Research Corporation (OAR). * * 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: mg5uart.c,v 1.4.6.1 2003/09/04 18:45:49 joel Exp $ */#include <rtems.h>#include <rtems/libio.h>#include <stdlib.h>#include <libchip/serial.h>#include <libchip/mg5uart.h>#include <libchip/sersupp.h>#include <libcpu/mongoose-v.h>extern void set_vector( rtems_isr_entry, rtems_vector_number, int );/* * Indices of registers *//* * Per chip context control */typedef struct _mg5uart_context{ int mate;} mg5uart_context;/* * Define MG5UART_STATIC to nothing while debugging so the entry points * will show up in the symbol table. */#define MG5UART_STATIC/* #define MG5UART_STATIC static */#define MG5UART_SETREG( _base, _register, _value ) \ MONGOOSEV_WRITE_REGISTER( _base, _register, _value )#define MG5UART_GETREG( _base, _register ) \ MONGOOSEV_READ_REGISTER( _base, _register )/* * Console Device Driver Support Functions */MG5UART_STATIC int mg5uart_baud_rate( int minor, int baud, unsigned int *code);MG5UART_STATIC void mg5uart_enable_interrupts( int minor, int mask);/* * mg5uart_set_attributes * * This function sets the UART channel to reflect the requested termios * port settings. */MG5UART_STATIC int mg5uart_set_attributes( int minor, const struct termios *t){ unsigned32 pMG5UART_port; unsigned32 pMG5UART; unsigned32 cmd, cmdSave; unsigned32 baudcmd; unsigned32 shift; rtems_interrupt_level Irql; pMG5UART = Console_Port_Tbl[minor].ulCtrlPort1; pMG5UART_port = Console_Port_Tbl[minor].ulCtrlPort2; /* * Set the baud rate */ if (mg5uart_baud_rate( minor, t->c_cflag, &baudcmd ) == -1) return -1; /* * Base settings */ /* * Base settings */ cmd = MONGOOSEV_UART_CMD_RX_ENABLE | MONGOOSEV_UART_CMD_TX_ENABLE; /* * Parity */ if (t->c_cflag & PARENB) { cmd |= MONGOOSEV_UART_CMD_PARITY_ENABLE; if (t->c_cflag & PARODD) cmd |= MONGOOSEV_UART_CMD_PARITY_ODD; else cmd |= MONGOOSEV_UART_CMD_PARITY_EVEN; } else { cmd |= MONGOOSEV_UART_CMD_PARITY_DISABLE; } /* * Character Size */ if (t->c_cflag & CSIZE) { switch (t->c_cflag & CSIZE) { case CS5: case CS6: case CS7: return -1; break; case CS8: /* Mongoose-V only supports CS8 */ break; } } /* else default to CS8 */ /* * Stop Bits */#if 0 if (t->c_cflag & CSTOPB) { /* 2 stop bits not supported by Mongoose-V uart */ return -1; }#endif /* * XXX what about CTS/RTS */ /* XXX */ /* * Now write the registers */ if ( Console_Port_Tbl[minor].ulDataPort == MG5UART_UART0 ) shift = MONGOOSEV_UART0_CMD_SHIFT; else shift = MONGOOSEV_UART1_CMD_SHIFT; rtems_interrupt_disable(Irql); cmdSave = MG5UART_GETREG( pMG5UART, MG5UART_COMMAND_REGISTER ); MG5UART_SETREG( pMG5UART, MG5UART_COMMAND_REGISTER, (cmdSave & ~(MONGOOSEV_UART_ALL_STATUS_BITS << shift)) | (cmd << shift) ); MG5UART_SETREG( pMG5UART_port, MG5UART_BAUD_RATE, baudcmd ); rtems_interrupt_enable(Irql); return 0;}/* * mg5uart_initialize_context * * This function sets the default values of the per port context structure. */MG5UART_STATIC void mg5uart_initialize_context( int minor, mg5uart_context *pmg5uartContext){ int port; unsigned int pMG5UART; unsigned int pMG5UART_port; pMG5UART = Console_Port_Tbl[minor].ulCtrlPort1; pMG5UART_port = Console_Port_Tbl[minor].ulCtrlPort2; pmg5uartContext->mate = -1; for (port=0 ; port<Console_Port_Count ; port++ ) { if ( Console_Port_Tbl[port].ulCtrlPort1 == pMG5UART && Console_Port_Tbl[port].ulCtrlPort2 != pMG5UART_port ) { pmg5uartContext->mate = port; break; } }}/* * mg5uart_init * * This function initializes the DUART to a quiecsent state. */MG5UART_STATIC void mg5uart_init(int minor){ unsigned32 pMG5UART_port; unsigned32 pMG5UART; unsigned32 cmdSave; unsigned32 shift; mg5uart_context *pmg5uartContext; pmg5uartContext = (mg5uart_context *) malloc(sizeof(mg5uart_context)); Console_Port_Data[minor].pDeviceContext = (void *)pmg5uartContext; mg5uart_initialize_context( minor, pmg5uartContext ); pMG5UART = Console_Port_Tbl[minor].ulCtrlPort1; pMG5UART_port = Console_Port_Tbl[minor].ulCtrlPort2; if ( Console_Port_Tbl[minor].ulDataPort == MG5UART_UART0 ) shift = MONGOOSEV_UART0_CMD_SHIFT; else shift = MONGOOSEV_UART1_CMD_SHIFT; /* * Disable the uart and leave this port disabled. */ cmdSave = MG5UART_GETREG(pMG5UART, MG5UART_COMMAND_REGISTER) & ~(MONGOOSEV_UART_ALL_STATUS_BITS << shift); MG5UART_SETREG( pMG5UART, MG5UART_COMMAND_REGISTER, cmdSave ); /* * Disable interrupts on RX and TX for this port */ mg5uart_enable_interrupts( minor, MG5UART_DISABLE_ALL );}/* * mg5uart_open * * This function opens a port for communication. * * Default state is 9600 baud, 8 bits, No parity, and 1 stop bit. */MG5UART_STATIC int mg5uart_open( int major, int minor, void *arg){ unsigned32 pMG5UART; unsigned32 pMG5UART_port; unsigned32 vector; unsigned32 cmd, cmdSave; unsigned32 baudcmd; unsigned32 shift; rtems_interrupt_level Irql; pMG5UART = Console_Port_Tbl[minor].ulCtrlPort1; pMG5UART_port = Console_Port_Tbl[minor].ulCtrlPort2; vector = Console_Port_Tbl[minor].ulIntVector; if ( Console_Port_Tbl[minor].ulDataPort == MG5UART_UART0 ) shift = MONGOOSEV_UART0_CMD_SHIFT; else shift = MONGOOSEV_UART1_CMD_SHIFT; /* XXX default baud rate could be from configuration table */ (void) mg5uart_baud_rate( minor, B19200, &baudcmd ); /* * Set the DUART channel to a default useable state * B19200, 8Nx since there is no stop bit control. */ cmd = MONGOOSEV_UART_CMD_TX_ENABLE | MONGOOSEV_UART_CMD_RX_ENABLE; rtems_interrupt_disable(Irql); cmdSave = MG5UART_GETREG( pMG5UART, MG5UART_COMMAND_REGISTER ); MG5UART_SETREG( pMG5UART_port, MG5UART_BAUD_RATE, baudcmd ); MG5UART_SETREG( pMG5UART, MG5UART_COMMAND_REGISTER, cmd = (cmdSave & ~(MONGOOSEV_UART_ALL_STATUS_BITS << shift)) | (cmd << shift) ); rtems_interrupt_enable(Irql); return RTEMS_SUCCESSFUL;}/* * mg5uart_close * * This function shuts down the requested port. */MG5UART_STATIC int mg5uart_close( int major, int minor, void *arg){ unsigned32 pMG5UART; unsigned32 pMG5UART_port; unsigned32 cmd, cmdSave; unsigned32 shift; rtems_interrupt_level Irql; pMG5UART = Console_Port_Tbl[minor].ulCtrlPort1; pMG5UART_port = Console_Port_Tbl[minor].ulCtrlPort2; /* * Disable interrupts from this channel and then disable it totally. */ /* XXX interrupts */ cmd = MONGOOSEV_UART_CMD_TX_DISABLE | MONGOOSEV_UART_CMD_RX_DISABLE; if ( Console_Port_Tbl[minor].ulDataPort == MG5UART_UART0 ) shift = MONGOOSEV_UART0_CMD_SHIFT; else shift = MONGOOSEV_UART1_CMD_SHIFT; rtems_interrupt_disable(Irql); cmdSave = MG5UART_GETREG( pMG5UART, MG5UART_COMMAND_REGISTER ); MG5UART_SETREG( pMG5UART, MG5UART_COMMAND_REGISTER, (cmdSave & ~(MONGOOSEV_UART_ALL_STATUS_BITS << shift)) | (cmd << shift) ); rtems_interrupt_enable(Irql); return(RTEMS_SUCCESSFUL);}/* * mg5uart_write_polled * * This routine polls out the requested character. */MG5UART_STATIC void mg5uart_write_polled( int minor, char c){ unsigned32 pMG5UART; unsigned32 pMG5UART_port; unsigned32 status; int shift; int timeout; pMG5UART = Console_Port_Tbl[minor].ulCtrlPort1; pMG5UART_port = Console_Port_Tbl[minor].ulCtrlPort2; if ( Console_Port_Tbl[minor].ulDataPort == MG5UART_UART0 ) shift = MONGOOSEV_UART0_IRQ_SHIFT; else shift = MONGOOSEV_UART1_IRQ_SHIFT; /* * wait for transmitter holding register to be empty */ timeout = 2000; while( --timeout ) { status = MG5UART_GETREG(pMG5UART, MG5UART_STATUS_REGISTER) >> shift; /* if ( (status & (MONGOOSEV_UART_TX_READY | MONGOOSEV_UART_TX_EMPTY)) == (MONGOOSEV_UART_TX_READY | MONGOOSEV_UART_TX_EMPTY) ) break; */ if( (status & (MONGOOSEV_UART_TX_READY | MONGOOSEV_UART_TX_EMPTY)) ) break; /* * Yield while we wait */#if 0 if(_System_state_Is_up(_System_state_Get())) { rtems_task_wake_after(RTEMS_YIELD_PROCESSOR); }#endif } /* * transmit character */ MG5UART_SETREG(pMG5UART_port, MG5UART_TX_BUFFER, c);}/* * mg5uart_isr_XXX * * This is the single interrupt entry point which parcels interrupts * out to the handlers for specific sources and makes sure that the * shared handler gets the right arguments. * * NOTE: Yes .. this is ugly but it provides 5 interrupt source
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -