📄 serial_ti16550.c
字号:
/************************************************************************ * * SERIAL_TI16550.c * * The 'SERIAL_TI16550' module implements the SERIAL-TI16550C * device driver as an IO device with following services: * * 1) init device: configure and initialize serial driver * 2) open device: not used * 3) close device: not used * 4) read device: read character from serial device * 5) write device: write character to serial device * 6) ctrl device: statistics and poll for ctrl/c * * * ###################################################################### * * mips_start_of_legal_notice * * Copyright (c) 2004 MIPS Technologies, Inc. All rights reserved. * * * Unpublished rights (if any) reserved under the copyright laws of the * United States of America and other countries. * * This code is proprietary to MIPS Technologies, Inc. ("MIPS * Technologies"). Any copying, reproducing, modifying or use of this code * (in whole or in part) that is not expressly permitted in writing by MIPS * Technologies or an authorized third party is strictly prohibited. At a * minimum, this code is protected under unfair competition and copyright * laws. Violations thereof may result in criminal penalties and fines. * * MIPS Technologies reserves the right to change this code to improve * function, design or otherwise. MIPS Technologies does not assume any * liability arising out of the application or use of this code, or of any * error or omission in such code. Any warranties, whether express, * statutory, implied or otherwise, including but not limited to the implied * warranties of merchantability or fitness for a particular purpose, are * excluded. Except as expressly provided in any written license agreement * from MIPS Technologies or an authorized third party, the furnishing of * this code does not give recipient any license to any intellectual * property rights, including any patent rights, that cover this code. * * This code shall not be exported, reexported, transferred, or released, * directly or indirectly, in violation of the law of any country or * international law, regulation, treaty, Executive Order, statute, * amendments or supplements thereto. Should a conflict arise regarding the * export, reexport, transfer, or release of this code, the laws of the * United States of America shall be the governing law. * * This code constitutes one or more of the following: commercial computer * software, commercial computer software documentation or other commercial * items. If the user of this code, or any related documentation of any * kind, including related technical data or manuals, is an agency, * department, or other entity of the United States government * ("Government"), the use, duplication, reproduction, release, * modification, disclosure, or transfer of this code, or any related * documentation of any kind, is restricted in accordance with Federal * Acquisition Regulation 12.212 for civilian agencies and Defense Federal * Acquisition Regulation Supplement 227.7202 for military agencies. The use * of this code by the Government is further restricted in accordance with * the terms of the license agreement(s) and/or applicable contract terms * and conditions covering this code from MIPS Technologies or an authorized * third party. * * * * * mips_end_of_legal_notice * * ************************************************************************//************************************************************************ * Include files ************************************************************************/#include <sysdefs.h>#include <syserror.h>#include <sysdev.h>#include <io_api.h>#include <syscon_api.h>#include <sys_api.h>#include <serial_api.h>#include <serial_ti16550_api.h>#include <excep_api.h>#include <string.h>/************************************************************************ * Definitions*************************************************************************/#define SET_ADDR( offset ) \ sys_reg_addr( bigend, spacing, ti16550base, offset )/* Register access *//* #define PHY_RBR_W(minor, data) SETREG(minor, data, rbr) */#define PHY_THR_W(minor, data) if (size[minor] == sizeof(UINT8)) \ REG8(phy_thr[minor]) = (data); \ else *(phy_thr[minor]) = (data);#define PHY_IER_W(minor, data) if (size[minor] == sizeof(UINT8)) \ REG8(phy_ier[minor]) = (data); \ else *(phy_ier[minor]) = (data);#define PHY_FCR_W(minor, data) if (size[minor] == sizeof(UINT8)) \ REG8(phy_fcr[minor]) = (data); \ else *(phy_fcr[minor]) = (data);#define PHY_LCR_W(minor, data) if (size[minor] == sizeof(UINT8)) \ REG8(phy_lcr[minor]) = (data); \ else *(phy_lcr[minor]) = (data);#define PHY_MCR_W(minor, data) if (size[minor] == sizeof(UINT8)) \ REG8(phy_mcr[minor]) = (data); \ else *(phy_mcr[minor]) = (data);#define PHY_DLL_W(minor, data) if (size[minor] == sizeof(UINT8)) \ REG8(phy_dll[minor]) = (data); \ else *(phy_dll[minor]) = (data);#define PHY_DLM_W(minor, data) if (size[minor] == sizeof(UINT8)) \ REG8(phy_dlm[minor]) = (data); \ else *(phy_dlm[minor]) = (data);#define PHY_RBR_R(minor) ( size[minor] == sizeof(UINT8) ? \ REG8(phy_rbr[minor]) : \ *(phy_rbr[minor]) )#define PHY_LSR_R(minor) ( size[minor] == sizeof(UINT8) ? \ REG8(phy_lsr[minor]) : \ *(phy_lsr[minor]) )#define PHY_MSR_R(minor) ( size[minor] == sizeof(UINT8) ? \ REG8(phy_msr[minor]) : \ *(phy_msr[minor]) )/************************************************************************ * Public variables ************************************************************************//************************************************************************ * Static variables ************************************************************************//* Is UART Big endian device or not */static bool bigend;/* Base address of controller */static void *ti16550base;/* Spacing of register */static UINT8 spacing;/* Size of registers (number of bytes) */static UINT8 size[SERIAL_MAX_16550_DEVICES];static volatile UINT32 *phy_rbr[SERIAL_MAX_16550_DEVICES]; /* '0', RO, receive buffer, */static volatile UINT32 *phy_thr[SERIAL_MAX_16550_DEVICES]; /* '0', WO, trans. holding, */static volatile UINT32 *phy_ier[SERIAL_MAX_16550_DEVICES]; /* '1', RW, int. enable, */static volatile UINT32 *phy_iir[SERIAL_MAX_16550_DEVICES]; /* '2', RO, int. ident, */static volatile UINT32 *phy_fcr[SERIAL_MAX_16550_DEVICES]; /* '2', WO, FIFO control, */static volatile UINT32 *phy_lcr[SERIAL_MAX_16550_DEVICES]; /* '3', RW, line control, */static volatile UINT32 *phy_mcr[SERIAL_MAX_16550_DEVICES]; /* '4', RW, modem control, */static volatile UINT32 *phy_lsr[SERIAL_MAX_16550_DEVICES]; /* '5', RW, line status, */static volatile UINT32 *phy_msr[SERIAL_MAX_16550_DEVICES]; /* '6', RW, modem status, */static volatile UINT32 *phy_scr[SERIAL_MAX_16550_DEVICES]; /* '7', RW, scratch */static volatile UINT32 *phy_dll[SERIAL_MAX_16550_DEVICES]; /* '0', RW, divisor latch LSB */static volatile UINT32 *phy_dlm[SERIAL_MAX_16550_DEVICES]; /* '1', RW, divisor latch MSB *//* Databit conversion table. * EEPROM-encoding to device control */static const UINT8 serial_databits[SERIAL_DATABITS_MAX] = { SERIAL_ILLEGAL, /* 0, undefined */ SERIAL_LCR_DATA7, /* 1, 7 databits */ SERIAL_LCR_DATA8 /* 2, 8 databits */};/* Parity conversion table. * EEPROM-encoding to device control */static const UINT8 serial_parity[SERIAL_PARITY_MAX] = { SERIAL_ILLEGAL, /* 0, undefined */ SERIAL_LCR_PARITYNONE, /* 1, none */ SERIAL_LCR_PARITYODD, /* 2, odd */ SERIAL_LCR_PARITYEVEN /* 3, even */};/* Stopbits conversion table. * EEPROM-encoding to device control */static const UINT8 serial_stopbits[SERIAL_STOPBITS_MAX] = { SERIAL_ILLEGAL, /* 0, undefined */ SERIAL_LCR_STOP1, /* 1, 1 stopbit */ SERIAL_LCR_STOP15, /* 2, 1.5 stopbit */ SERIAL_LCR_STOP2 /* 3, 2 stopbit */};static t_UART_statistics uart_statistics[SERIAL_MAX_16550_DEVICES];static UINT32 poll_retcode[SERIAL_MAX_16550_DEVICES];static UINT32 shadow_ier[SERIAL_MAX_16550_DEVICES];static UINT32 shadow_mcr[SERIAL_MAX_16550_DEVICES];static UINT32 shadow_flow[SERIAL_MAX_16550_DEVICES];/* Receive buffer operation: * * putptr points to the next free location * When a byte is polled from the uart, it is stored by putptr, * which is then cyclic incremented UNLESS it gets equal to getptr. * * That way, getptr == putptr means buffer empty, and * the buffer can hold POLLSIZE-1 bytes. */ #define POLLSIZE 0x800 /* Must be power of 2 and at least 128 */#define HW_LIMIT_STOP (POLLSIZE-64) /* RTS OFF when 64 chars in buf */#define HW_LIMIT_START (POLLSIZE-32) /* RTS ON when 32 chars in buf */static UINT16 *recv_putptr[SERIAL_MAX_16550_DEVICES];static UINT16 *recv_getptr[SERIAL_MAX_16550_DEVICES];static UINT16 *recv_flushptr[SERIAL_MAX_16550_DEVICES];static UINT16 recv_buffer[SERIAL_MAX_16550_DEVICES][POLLSIZE];static UINT32 minor_numbers[SERIAL_MAX_16550_DEVICES];/* Available baudrates */static t_SERIAL_baudrate_div *serial_baudrate;/* Boolean indicating whether interrupt handlers are registered or not. * Initial value is 0 (FALSE) since data is in BSS. */static bool registered[SERIAL_MAX_16550_DEVICES];/************************************************************************ * Static function prototypes ************************************************************************/static INT32 SERIAL_TI16550_init( UINT32 major, /* IN: major device number */ UINT32 minor, /* IN: minor device number */ UINT32 *port ); /* IN: port mapping */static INT32 SERIAL_TI16550_read( UINT32 major, /* IN: major device number */ UINT32 minor, /* IN: minor device number */ UINT8 *p_param ); /* OUT: character been read */static UINT32 SERIAL_TI16550_irqpoll( UINT32 minor );static UINT32 SERIAL_TI16550_irq( UINT32 minor, UINT32 in_intrpt );static INT32 SERIAL_TI16550_write( UINT32 major, /* IN: major device number */ UINT32 minor, /* IN: minor device number */ UINT8 *p_param ); /* IN: character to write */static INT32 SERIAL_TI16550_ctrl( UINT32 major, /* IN: major device number */ UINT32 minor, /* IN: minor device number */ t_SERIAL_ctrl_descriptor *p_param );/* INOUT: IOCTL structure */static voidserial_int_handler( void *data ); /* Holds the minor device number *//************************************************************************ * Implementation : Public functions ************************************************************************//************************************************************************ * * SERIAL_TI16550_install * Description : * ------------- * * Installs the serial TI16550 serial device drivers services in * the IO system at the reserved device slot, found in the * 'sysdev.h' file, which defines all major device numbers. * * Note: * This service is the only public declared interface function; all * provided device driver services are static declared, but this * function installs the function pointers in the io-system to * enable the provided public driver services. * * Parameters : * ------------ * * None * * Return values : * --------------- * * 'OK'(=0) * 'ERROR_IO_ILLEGAL_MAJOR': Illegal major device number * 'ERROR_IO_NO_SPACE': Device slot already allocated * ************************************************************************/INT32 SERIAL_TI16550_install( void ){ UINT32 i; UINT32 tty; UINT32 major, minor; /* Initialise variables */ for( i=0; i<SERIAL_MAX_16550_DEVICES; i++ ) { minor_numbers[i] = i; shadow_mcr[i] = SERIAL_MCR_DTR | SERIAL_MCR_OUT2; } /* pre-initialize local variables and install device services */ IO_install( SYS_MAJOR_SERIAL_TI16550, /* major device number */ (t_io_service) SERIAL_TI16550_init, /* 'init' service */ NULL, /* 'open' service na */ NULL, /* 'close' service na */ (t_io_service) SERIAL_TI16550_read, /* 'read' service */ (t_io_service) SERIAL_TI16550_write, /* 'write' service */ (t_io_service) SERIAL_TI16550_ctrl ); /* 'ctrl' service */ /* call our own 'init' service */ /* TTY0 */ tty = PORT_TTY0; SYSCON_read( SYSCON_COM_TTY0_MAJOR, (void *)(&major), sizeof(UINT32) ); if (major == SYS_MAJOR_SERIAL_TI16550) { SYSCON_read(SYSCON_COM_TTY0_MINOR, (void *)(&minor), sizeof(UINT32)); IO_init( SYS_MAJOR_SERIAL_TI16550, minor, &tty );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -