/*
* C-Brick Serial Port (and console) driver for SGI Altix machines.
*
* This driver is NOT suitable for talking to the l1-controller for
* anything other than 'console activities' --- please use the l1
* driver for that.
*
*
* Copyright (c) 2004-2005 Silicon Graphics, Inc. All Rights Reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it would be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*
* Further, this software is distributed without any warranty that it is
* free of the rightful claim of any third person regarding infringement
* or the like. Any license provided herein, whether implied or
* otherwise, applies only to this software file. Patent licenses, if
* any, provided herein do not apply to combinations of this program with
* other software, or any other product whatsoever.
*
* You should have received a copy of the GNU General Public
* License along with this program; if not, write the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
*
* Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
* Mountain View, CA 94043, or:
*
* http://www.sgi.com
*
* For further information regarding this notice, see:
*
* http://oss.sgi.com/projects/GenInfo/NoticeExplan
*/
#include <linux/config.h>
#include <linux/interrupt.h>
#include <linux/tty.h>
#include <linux/serial.h>
#include <linux/console.h>
#include <linux/module.h>
#include <linux/sysrq.h>
#include <linux/circ_buf.h>
#include <linux/serial_reg.h>
#include <linux/delay.h> /* for mdelay */
#include <linux/miscdevice.h>
#include <linux/serial_core.h>
#include <asm/io.h>
#include <asm/sn/simulator.h>
#include <asm/sn/sn_sal.h>
/* number of characters we can transmit to the SAL console at a time */
#define SN_SAL_MAX_CHARS 120
/* 64K, when we're asynch, it must be at least printk's LOG_BUF_LEN to
* avoid losing chars, (always has to be a power of 2) */
#define SN_SAL_BUFFER_SIZE (64 * (1 << 10))
#define SN_SAL_UART_FIFO_DEPTH 16
#define SN_SAL_UART_FIFO_SPEED_CPS 9600/10
/* sn_transmit_chars() calling args */
#define TRANSMIT_BUFFERED 0
#define TRANSMIT_RAW 1
/* To use dynamic numbers only and not use the assigned major and minor,
* define the following.. */
/* #define USE_DYNAMIC_MINOR 1 *//* use dynamic minor number */
#define USE_DYNAMIC_MINOR 0 /* Don't rely on misc_register dynamic minor */
/* Device name we're using */
#define DEVICE_NAME "ttySG"
#define DEVICE_NAME_DYNAMIC "ttySG0" /* need full name for misc_register */
/* The major/minor we are using, ignored for USE_DYNAMIC_MINOR */
#define DEVICE_MAJOR 204
#define DEVICE_MINOR 40
#ifdef CONFIG_MAGIC_SYSRQ
static char sysrq_serial_str[] = "\eSYS";
static char *sysrq_serial_ptr = sysrq_serial_str;
static unsigned long sysrq_requested;
#endif /* CONFIG_MAGIC_SYSRQ */
/*
* Port definition - this kinda drives it all
*/
struct sn_cons_port {
struct timer_list sc_timer;
struct uart_port sc_port;
struct sn_sal_ops {
int (*sal_puts_raw) (const char *s, int len);
int (*sal_puts) (const char *s, int len);
int (*sal_getc) (void);
int (*sal_input_pending) (void);
void (*sal_wakeup_transmit) (struct sn_cons_port *, int);
} *sc_ops;
unsigned long sc_interrupt_timeout;
int sc_is_asynch;
};
static struct sn_cons_port sal_console_port;
static int sn_process_input;
/* Only used if USE_DYNAMIC_MINOR is set to 1 */
static struct miscdevice misc; /* used with misc_register for dynamic */
extern void early_sn_setup(void);
#undef DEBUG
#ifdef DEBUG
static int sn_debug_printf(const char *fmt, ...);
#define DPRINTF(x...) sn_debug_printf(x)
#else
#define DPRINTF(x...) do { } while (0)
#endif
/* Prototypes */
static int snt_hw_puts_raw(const char *, int);
static int snt_hw_puts_buffered(const char *, int);
static int snt_poll_getc(void);
static int snt_poll_input_pending(void);
static int snt_intr_getc(void);
static int snt_intr_input_pending(void);
static void sn_transmit_chars(struct sn_cons_port *, int);
/* A table for polling:
*/
static struct sn_sal_ops poll_ops = {
.sal_puts_raw = snt_hw_puts_raw,
.sal_puts = snt_hw_puts_raw,
.sal_getc = snt_poll_getc,
.sal_input_pending = snt_poll_input_pending
};
/* A table for interrupts enabled */
static struct sn_sal_ops intr_ops = {
.sal_puts_raw = snt_hw_puts_raw,
.sal_puts = snt_hw_puts_buffered,
.sal_getc = snt_intr_getc,
.sal_input_pending = snt_intr_input_pending,
.sal_wakeup_transmit = sn_transmit_chars
};
/* the console does output in two distinctly different ways:
* synchronous (raw) and asynchronous (buffered). initally, early_printk
* does synchronous output. any data written goes directly to the SAL
* to be output (incidentally, it is internally buffered by the SAL)
* after interrupts and timers are initialized and available for use,
* the console init code switches to asynchronous output. this is
* also the earliest opportunity to begin polling for console input.
* after console initialization, console output and tty (serial port)
* output is buffered and sent to the SAL asynchronously (either by
* timer callback or by UART interrupt) */
/* routines for running the console in polling mode */
/**
* snt_poll_getc - Get a character from the console in polling mode
*
*/
static int snt_poll_getc(void)
{
int ch;
ia64_sn_console_getc(&ch);
return ch;
}
/**
* snt_poll_input_pending - Check if any input is waiting - polling mode.
*
*/
stati