📄 serial_au1000.c
字号:
/************************************************************************
*
* SERIAL_Au1000.c
*
* The 'SERIAL_Au1000' module implements the SERIAL-Au1000C
* 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
*
*
*
* ######################################################################
*
* Copyright (c) 1999-2000 MIPS Technologies, Inc. All rights reserved.
*
* Unpublished rights reserved under the Copyright Laws of the United States of
* America.
*
* This document contains information that is proprietary to MIPS Technologies,
* Inc. ("MIPS Technologies"). Any copying, modifying or use of this information
* (in whole or in part) which is not expressly permitted in writing by MIPS
* Technologies or a contractually-authorized third party is strictly
* prohibited. At a minimum, this information is protected under unfair
* competition laws and the expression of the information contained herein is
* protected under federal copyright laws. Violations thereof may result in
* criminal penalties and fines.
* MIPS Technologies or any contractually-authorized third party reserves the
* right to change the information contained in this document to improve
* function, design or otherwise. MIPS Technologies does not assume any
* liability arising out of the application or use of this information. Any
* license under patent rights or any other intellectual property rights owned
* by MIPS Technologies or third parties shall be conveyed by MIPS Technologies
* or any contractually-authorized third party in a separate license agreement
* between the parties.
* The information contained in this document constitutes one or more of the
* following: commercial computer software, commercial computer software
* documentation or other commercial items. If the user of this information, 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 information, 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 information 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 information from MIPS Technologies or any
* contractually-authorized third party.
*
************************************************************************/
/************************************************************************
* 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 <string.h>
#include <serial_au1000_api.h>
#include <excep_api.h>
#include <pb1000.h>
#include <uart.h>
/************************************************************************
* Definitions
*************************************************************************/
/*
* Alchemy UARTs:
* UART0 @ 0xB1100000
* UART1 @ 0xB1200000
* UART2 @ 0xB1300000
* UART3 @ 0xB1400000
*
* Au1000: 4 UARTs (UART0, UART1, UART2, UART3)
* Au1500: 2 UARTs (UART0, UART3)
* Au1100: 3 UARTs (UART0, UART1, UART3)
* Au1550: 3 UARTs (UART0, UART1, UART3)
* Au1200: 2 UARTS (UART0, UART1)
*/
#define SERIAL_MAX_AU1x00_DEVICES 4 /* max num Au1x00 async UARTs supported */
/************************************************************************
* Public variables
************************************************************************/
/* syscon_platform_tty.c */
extern UINT32 pb1000_major_tty0;
extern UINT32 pb1000_minor_tty0;
extern UINT32 pb1000_major_tty1;
extern UINT32 pb1000_minor_tty1;
//extern UINT32 intline_pb1000_tty0;
//extern UINT32 intline_pb1000_tty1;
#define PB1000_INTLINE_TTY0 0x02
#define PB1000_INTLINE_TTY1 0x03
/************************************************************************
* Static variables
************************************************************************/
/* Databit conversion table. */
static const UINT8 serial_databits[SERIAL_DATABITS_MAX] = {
SERIAL_ILLEGAL, /* 0, undefined */
UART_LINECTRL_WLS_7, /* 1, 7 databits */
UART_LINECTRL_WLS_8, /* 2, 8 databits */
};
/* Parity conversion table. */
static const UINT8 serial_parity[SERIAL_PARITY_MAX] = {
SERIAL_ILLEGAL, /* 0, undefined */
0x00, /* 1, none ~UART_LINECTRL_PE */
UART_LINECTRL_PE|UART_LINECTRL_PAR_O, /* 2, odd */
UART_LINECTRL_PE|UART_LINECTRL_PAR_E, /* 3, even */
};
/* Stopbits conversion table. */
static const UINT8 serial_stopbits[SERIAL_STOPBITS_MAX] = {
SERIAL_ILLEGAL, /* 0, undefined */
0x00, /* 1, 1 stopbit ~UART_LINECTRL_ST */
UART_LINECTRL_ST, /* 2, 1.5 stopbit */
UART_LINECTRL_ST, /* 3, 2 stopbit */
};
static t_UART_statistics uart_statistics[SERIAL_MAX_AU1x00_DEVICES];
static UINT32 poll_retcode[SERIAL_MAX_AU1x00_DEVICES];
static UINT32 shadow_ier[SERIAL_MAX_AU1x00_DEVICES];
static UINT32 shadow_mcr[SERIAL_MAX_AU1x00_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_AU1x00_DEVICES];
static UINT16 *recv_getptr[SERIAL_MAX_AU1x00_DEVICES];
static UINT16 *recv_flushptr[SERIAL_MAX_AU1x00_DEVICES];
static UINT16 recv_buffer[SERIAL_MAX_AU1x00_DEVICES][POLLSIZE];
//static UINT32 minor_numbers[SERIAL_MAX_AU1x00_DEVICES];
/* reverse-lookup table from t_SERIAL_baudrate_ids back to integer bps rates */
/* (this must match up with indexes to t_SERIAL_baudrate_ids typedef.) */
static UINT32 SERIAL_baudrate_rates[] =
{
0,
75,
110,
150,
300,
600,
1200,
1800,
2400,
4800,
7200,
9600,
14400,
19200,
38400,
57600,
115200,
230400,
460800,
921600
};
/* Boolean indicating whether interrupt handlers are registered or not.
* Initial value is 0 (FALSE) since data is in BSS.
*/
static bool registered[SERIAL_MAX_AU1x00_DEVICES];
/************************************************************************
* Static function prototypes
************************************************************************/
static INT32
SERIAL_Au1000_init(
UINT32 major, /* IN: major device number */
UINT32 minor, /* IN: minor device number */
UINT32 *port ); /* IN: port mapping */
static INT32
SERIAL_Au1000_read(
UINT32 major, /* IN: major device number */
UINT32 minor, /* IN: minor device number */
UINT8 *p_param ); /* OUT: character been read */
static UINT32
SERIAL_Au1000_irqpoll(
UINT32 minor );
static UINT32
SERIAL_Au1000_irq(
UINT32 minor,
UINT32 in_intrpt );
static INT32
SERIAL_Au1000_write(
UINT32 major, /* IN: major device number */
UINT32 minor, /* IN: minor device number */
UINT8 *p_param ); /* IN: character to write */
static INT32
SERIAL_Au1000_ctrl(
UINT32 major, /* IN: major device number */
UINT32 minor, /* IN: minor device number */
t_SERIAL_ctrl_descriptor *p_param );/* INOUT: IOCTL structure */
static void
serial_int_handler(
void *data ); /* Holds the minor device number */
/************************************************************************
* Implementation : Public functions
************************************************************************/
static AU1X00_UART *
minor2base( int minor )
{
AU1X00_UART *p;
switch (minor)
{
default:
case SERIAL_MINOR_AU1x00_UART0: p = (AU1X00_UART *)UART0_BASE; break;
case SERIAL_MINOR_AU1x00_UART1: p = (AU1X00_UART *)UART1_BASE; break;
case SERIAL_MINOR_AU1x00_UART2: p = (AU1X00_UART *)UART2_BASE; break;
case SERIAL_MINOR_AU1x00_UART3: p = (AU1X00_UART *)UART3_BASE; break;
}
return p;
}
/************************************************************************
*
* SERIAL_Au1000_install
* Description :
* -------------
*
* Installs the serial Au1000 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_AU1000_install( void )
{
UINT32 i;
UINT32 prid;
prid = CP0_prid_read();
/* FIX!!! need interrupt numbers also */
/*
* UART0 and UART3 are common to all Alchemy processors and are
* pinned out on all Alchemy development platforms. So use
* UART0 and UART3 as YAMON's TTY0 and TTY1.
* (Except on Au1200, TTY1 is UART1)
*/
pb1000_major_tty0 = SYS_MAJOR_SERIAL_AU1x00;
pb1000_major_tty1 = SYS_MAJOR_SERIAL_AU1x00;
pb1000_minor_tty0 = SERIAL_MINOR_AU1x00_UART0;
pb1000_minor_tty1 = SERIAL_MINOR_AU1x00_UART3;
#if 0
if ((prid & 0xFF000000) == 0x00000000 ) // Au1000
{
pb1000_minor_tty1 = SERIAL_MINOR_AU1x00_UART3;
}
else if( (prid & 0xff000000) == 0x01000000 ) // Au1500
{
pb1000_minor_tty1 = SERIAL_MINOR_AU1x00_UART3;
}
else if ((prid & 0xFF000000) == 0x02000000 ) // Au1100
{
pb1000_minor_tty1 = SERIAL_MINOR_AU1x00_UART3;
}
else if ((prid & 0xFF000000) == 0x03000000 ) // Au1550
{
pb1000_minor_tty1 = SERIAL_MINOR_AU1x00_UART3;
}
else
#endif
if ((prid & 0xFF000000) == 0x04000000 ) // Au1200
{
pb1000_minor_tty1 = SERIAL_MINOR_AU1x00_UART1;
}
/* Initialise variables */
for( i=0; i<SERIAL_MAX_AU1x00_DEVICES; i++ )
{
//minor_numbers[i] = i;
}
/* pre-initialize local variables and install device services */
return( IO_install( SYS_MAJOR_SERIAL_AU1x00, /* major device number */
(t_io_service) SERIAL_Au1000_init, /* 'init' service */
NULL, /* 'open' service na */
NULL, /* 'close' service na */
(t_io_service) SERIAL_Au1000_read, /* 'read' service */
(t_io_service) SERIAL_Au1000_write, /* 'write' service */
(t_io_service) SERIAL_Au1000_ctrl ) ); /* 'ctrl' service */
}
/************************************************************************
* Implementation : Static functions
************************************************************************/
/************************************************************************
* Implementation : Local helper functions
************************************************************************/
/************************************************************************
*
* SERIAL_Au1000_checkbaudrate
* Description :
* -------------
* This functions validates the specified baudrate for this type of device.
*
* Parameters :
* ------------
*
* 'baudrate', IN, baudrate to be validated.
*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -