📄 mc68681.c
字号:
/* * This file contains the termios TTY driver for the Motorola MC68681. * * This part is available from a number of secondary sources. * In particular, we know about the following: * * + Exar 88c681 and 68c681 * * COPYRIGHT (c) 1989-1999. * 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: mc68681.c,v 1.28.6.2 2003/09/26 20:15:47 joel Exp $ */#include <rtems.h>#include <rtems/libio.h>#include <stdlib.h>#include <libchip/serial.h>#include <libchip/mc68681.h>#include <libchip/sersupp.h>#include "mc68681_p.h"/* * Flow control is only supported when using interrupts */console_fns mc68681_fns ={ libchip_serial_default_probe, /* deviceProbe */ mc68681_open, /* deviceFirstOpen */ NULL, /* deviceLastClose */ NULL, /* deviceRead */ mc68681_write_support_int, /* deviceWrite */ mc68681_initialize_interrupts, /* deviceInitialize */ mc68681_write_polled, /* deviceWritePolled */ mc68681_set_attributes, /* deviceSetAttributes */ TRUE /* deviceOutputUsesInterrupts */};console_fns mc68681_fns_polled ={ libchip_serial_default_probe, /* deviceProbe */ mc68681_open, /* deviceFirstOpen */ mc68681_close, /* deviceLastClose */ mc68681_inbyte_nonblocking_polled, /* deviceRead */ mc68681_write_support_polled, /* deviceWrite */ mc68681_init, /* deviceInitialize */ mc68681_write_polled, /* deviceWritePolled */ mc68681_set_attributes, /* deviceSetAttributes */ FALSE, /* deviceOutputUsesInterrupts */};extern void set_vector( rtems_isr_entry, rtems_vector_number, int );/* * Console Device Driver Entry Points *//* * mc68681_baud_rate * * This routine returns the proper ACR bit and baud rate field values * based on the requested baud rate. The baud rate set to be used * must be configured by the user. */MC68681_STATIC int mc68681_baud_rate( int minor, int baud, unsigned int *baud_mask_p, unsigned int *acr_bit_p, unsigned int *command);/* * mc68681_set_attributes * * This function sets the DUART channel to reflect the requested termios * port settings. */MC68681_STATIC int mc68681_set_attributes( int minor, const struct termios *t){ unsigned32 pMC68681_port; unsigned32 pMC68681; unsigned int mode1; unsigned int mode2; unsigned int baud_mask; unsigned int acr_bit; unsigned int cmd; setRegister_f setReg; rtems_interrupt_level Irql; pMC68681 = Console_Port_Tbl[minor].ulCtrlPort1; pMC68681_port = Console_Port_Tbl[minor].ulCtrlPort2; setReg = Console_Port_Tbl[minor].setRegister; /* * Set the baud rate */ if (mc68681_baud_rate( minor, t->c_cflag, &baud_mask, &acr_bit, &cmd ) == -1) return -1; baud_mask |= baud_mask << 4; acr_bit <<= 7; /* * Parity */ mode1 = 0; mode2 = 0; if (t->c_cflag & PARENB) { if (t->c_cflag & PARODD) mode1 |= 0x04; /* else mode1 |= 0x04; */ } else { mode1 |= 0x10; } /* * Character Size */ if (t->c_cflag & CSIZE) { switch (t->c_cflag & CSIZE) { case CS5: break; case CS6: mode1 |= 0x01; break; case CS7: mode1 |= 0x02; break; case CS8: mode1 |= 0x03; break; } } else { mode1 |= 0x03; /* default to 9600,8,N,1 */ } /* * Stop Bits */ if (t->c_cflag & CSTOPB) { mode2 |= 0x0F; /* 2 stop bits */ } else { if ((t->c_cflag & CSIZE) == CS5) /* CS5 and 1 stop bits not supported */ return -1; mode2 |= 0x07; /* 1 stop bit */ } /* * Hardware Flow Control */ if(t->c_cflag & CRTSCTS) { mode1 |= 0x80; /* Enable Rx RTS Control */ mode2 |= 0x10; /* Enable CTS Enable Tx */ } rtems_interrupt_disable(Irql); (*setReg)( pMC68681, MC68681_AUX_CTRL_REG, acr_bit ); (*setReg)( pMC68681_port, MC68681_CLOCK_SELECT, baud_mask ); if ( cmd ) { (*setReg)( pMC68681_port, MC68681_COMMAND, cmd ); /* RX */ (*setReg)( pMC68681_port, MC68681_COMMAND, cmd | 0x20 ); /* TX */ } (*setReg)( pMC68681_port, MC68681_COMMAND, MC68681_MODE_REG_RESET_MR_PTR ); (*setReg)( pMC68681_port, MC68681_MODE, mode1 ); (*setReg)( pMC68681_port, MC68681_MODE, mode2 ); rtems_interrupt_enable(Irql); return 0;}/* * mc68681_initialize_context * * This function sets the default values of the per port context structure. */MC68681_STATIC void mc68681_initialize_context( int minor, mc68681_context *pmc68681Context){ int port; unsigned int pMC68681; unsigned int pMC68681_port; pMC68681 = Console_Port_Tbl[minor].ulCtrlPort1; pMC68681_port = Console_Port_Tbl[minor].ulCtrlPort2; pmc68681Context->mate = -1; for (port=0 ; port<Console_Port_Count ; port++ ) { if ( Console_Port_Tbl[port].ulCtrlPort1 == pMC68681 && Console_Port_Tbl[port].ulCtrlPort2 != pMC68681_port ) { pmc68681Context->mate = port; pmc68681Context->imr = 0; break; } }}/* * mc68681_init * * This function initializes the DUART to a quiecsent state. */MC68681_STATIC void mc68681_init(int minor){ unsigned32 pMC68681_port; unsigned32 pMC68681; mc68681_context *pmc68681Context; setRegister_f setReg; getRegister_f getReg; pmc68681Context = (mc68681_context *) malloc(sizeof(mc68681_context)); Console_Port_Data[minor].pDeviceContext = (void *)pmc68681Context; mc68681_initialize_context( minor, pmc68681Context ); pMC68681 = Console_Port_Tbl[minor].ulCtrlPort1; pMC68681_port = Console_Port_Tbl[minor].ulCtrlPort2; setReg = Console_Port_Tbl[minor].setRegister; getReg = Console_Port_Tbl[minor].getRegister; /* * Reset everything and leave this port disabled. */ (*setReg)( pMC68681_port, MC68681_COMMAND, MC68681_MODE_REG_RESET_RX ); (*setReg)( pMC68681_port, MC68681_COMMAND, MC68681_MODE_REG_RESET_TX ); (*setReg)( pMC68681_port, MC68681_COMMAND, MC68681_MODE_REG_RESET_ERROR ); (*setReg)( pMC68681_port, MC68681_COMMAND, MC68681_MODE_REG_RESET_BREAK ); (*setReg)( pMC68681_port, MC68681_COMMAND, MC68681_MODE_REG_STOP_BREAK ); (*setReg)( pMC68681_port, MC68681_COMMAND, MC68681_MODE_REG_DISABLE_TX ); (*setReg)( pMC68681_port, MC68681_COMMAND, MC68681_MODE_REG_DISABLE_RX ); (*setReg)( pMC68681_port, MC68681_MODE_REG_1A, 0x00 ); (*setReg)( pMC68681_port, MC68681_MODE_REG_2A, 0x02 ); /* * Disable interrupts on RX and TX for this port */ mc68681_enable_interrupts( minor, MC68681_IMR_DISABLE_ALL );}/* * mc68681_open * * This function opens a port for communication. * * Default state is 9600 baud, 8 bits, No parity, and 1 stop bit. */MC68681_STATIC int mc68681_open( int major, int minor, void *arg){ unsigned32 pMC68681; unsigned32 pMC68681_port; unsigned int baud; unsigned int acr_bit; unsigned int vector; unsigned int command; rtems_interrupt_level Irql; setRegister_f setReg; unsigned int status; pMC68681 = Console_Port_Tbl[minor].ulCtrlPort1; pMC68681_port = Console_Port_Tbl[minor].ulCtrlPort2; setReg = Console_Port_Tbl[minor].setRegister; vector = Console_Port_Tbl[minor].ulIntVector; /* XXX default baud rate should be from configuration table */ status = mc68681_baud_rate( minor, B9600, &baud, &acr_bit, &command ); if (status < 0) rtems_fatal_error_occurred (RTEMS_NOT_DEFINED); /* * Set the DUART channel to a default useable state */ rtems_interrupt_disable(Irql); (*setReg)( pMC68681, MC68681_AUX_CTRL_REG, acr_bit << 7 ); (*setReg)( pMC68681_port, MC68681_CLOCK_SELECT, baud ); if ( command ) { (*setReg)( pMC68681_port, MC68681_COMMAND, command ); /* RX */ (*setReg)( pMC68681_port, MC68681_COMMAND, command | 0x20 ); /* TX */ } (*setReg)( pMC68681_port, MC68681_COMMAND, MC68681_MODE_REG_RESET_MR_PTR ); (*setReg)( pMC68681_port, MC68681_MODE, 0x13 ); (*setReg)( pMC68681_port, MC68681_MODE, 0x07 ); rtems_interrupt_enable(Irql); (*setReg)( pMC68681_port, MC68681_COMMAND, MC68681_MODE_REG_ENABLE_TX ); (*setReg)( pMC68681_port, MC68681_COMMAND, MC68681_MODE_REG_ENABLE_RX ); (*setReg)( pMC68681, MC68681_INTERRUPT_VECTOR_REG, vector ); return RTEMS_SUCCESSFUL;}/* * mc68681_close * * This function shuts down the requested port. */MC68681_STATIC int mc68681_close( int major, int minor, void *arg){ unsigned32 pMC68681; unsigned32 pMC68681_port; setRegister_f setReg; pMC68681 = Console_Port_Tbl[minor].ulCtrlPort1; pMC68681_port = Console_Port_Tbl[minor].ulCtrlPort2; setReg = Console_Port_Tbl[minor].setRegister; /* * Disable interrupts from this channel and then disable it totally. */#if 0 (*setReg)( pMC68681_port, MC68681_COMMAND, MC68681_MODE_REG_DISABLE_TX ); (*setReg)( pMC68681_port, MC68681_COMMAND, MC68681_MODE_REG_DISABLE_RX );#endif return(RTEMS_SUCCESSFUL);}/* * mc68681_write_polled * * This routine polls out the requested character. */MC68681_STATIC void mc68681_write_polled( int minor, char cChar){ unsigned32 pMC68681_port; unsigned char ucLineStatus; int iTimeout; getRegister_f getReg; setRegister_f setReg; pMC68681_port = Console_Port_Tbl[minor].ulCtrlPort2; getReg = Console_Port_Tbl[minor].getRegister; setReg = Console_Port_Tbl[minor].setRegister; /* * wait for transmitter holding register to be empty */ iTimeout = 1000; ucLineStatus = (*getReg)(pMC68681_port, MC68681_STATUS); while ((ucLineStatus & (MC68681_TX_READY|MC68681_TX_EMPTY)) == 0) { if ((ucLineStatus & 0xF0)) (*setReg)( pMC68681_port, MC68681_COMMAND, MC68681_MODE_REG_RESET_ERROR ); /* * Yield while we wait */#if 0 if(_System_state_Is_up(_System_state_Get())) { rtems_task_wake_after(RTEMS_YIELD_PROCESSOR); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -