3 * This file is subject to the terms and conditions of the GNU General Public
4 * License. See the file "COPYING" in the main directory of this archive
7 * Copyright (C) 1992-1997, 2000-2003 Silicon Graphics, Inc. All rights reserved.
10 /* In general, this file is organized in a hierarchy from lower-level
11 * to higher-level layers, as follows:
14 * Bedrock/L1 "PPP-like" protocol implementation
15 * System controller "message" interface (allows multiplexing
16 * of various kinds of requests and responses with
19 * "l1_cons", the glue that allows the L1 to act
20 * as the system console for the stdio libraries
22 * Routines making use of the system controller "message"-style interface
23 * can be found in l1_command.c.
27 #include <linux/types.h>
28 #include <linux/config.h>
29 #include <linux/slab.h>
30 #include <linux/spinlock.h>
31 #include <linux/delay.h>
32 #include <linux/interrupt.h>
34 #include <asm/sn/sgi.h>
35 #include <asm/sn/io.h>
36 #include <asm/sn/iograph.h>
37 #include <asm/sn/invent.h>
38 #include <asm/sn/hcl.h>
39 #include <asm/sn/hcl_util.h>
40 #include <asm/sn/labelcl.h>
41 #include <asm/sn/router.h>
42 #include <asm/sn/module.h>
43 #include <asm/sn/ksys/l1.h>
44 #include <asm/sn/nodepda.h>
45 #include <asm/sn/clksupport.h>
46 #include <asm/sn/sn_sal.h>
47 #include <asm/sn/sn_cpuid.h>
48 #include <asm/sn/uart16550.h>
49 #include <asm/sn/simulator.h>
52 #define UART_BAUD_RATE 57600
54 static int L1_connected; /* non-zero when interrupts are enabled */
60 return UART_BAUD_RATE;
65 /* Return the current interrupt level */
67 l1_get_intr_value( void )
70 nasid_t console_nasid;
72 extern nasid_t get_console_nasid(void);
74 /* if it is an old prom, run in poll mode */
76 major = sn_sal_rev_major();
77 minor = sn_sal_rev_minor();
78 if ( (major < 1) || ((major == 1) && (minor < 10)) ) {
79 /* before version 1.10 doesn't work */
83 console_nasid = get_console_nasid();
84 intr_cpuid = NODEPDA(NASID_TO_COMPACT_NODEID(console_nasid))->node_first_cpu;
85 return CPU_VECTOR_TO_IRQ(intr_cpuid, SGI_UART_VECTOR);
88 /* Disconnect the callup functions - throw away interrupts */
91 l1_unconnect_intr(void)
95 /* Set up uart interrupt handling for this node's uart */
98 l1_connect_intr(void *intr_func, void *arg, struct pt_regs *ep)
101 nasid_t console_nasid;
102 unsigned int console_irq;
104 extern int intr_connect_level(cpuid_t, int, ilvl_t, intr_func_t);
105 extern nasid_t get_console_nasid(void);
108 /* don't call to connect multiple times - we DON'T support changing the handler */
110 if ( !L1_connected ) {
112 console_nasid = get_console_nasid();
113 intr_cpuid = NODEPDA(NASID_TO_COMPACT_NODEID(console_nasid))->node_first_cpu;
114 console_irq = CPU_VECTOR_TO_IRQ(intr_cpuid, SGI_UART_VECTOR);
115 result = intr_connect_level(intr_cpuid, SGI_UART_VECTOR,
116 0 /*not used*/, 0 /*not used*/);
117 if (result != SGI_UART_VECTOR) {
119 printk(KERN_WARNING "L1 console driver : intr_connect_level failed %d\n", result);
121 printk(KERN_WARNING "L1 console driver : intr_connect_level returns wrong bit %d\n", result);
125 result = request_irq(console_irq, intr_func, SA_INTERRUPT,
126 "SGI L1 console driver", (void *)arg);
128 printk(KERN_WARNING "L1 console driver : request_irq failed %d\n", result);
132 /* ask SAL to turn on interrupts in the UART itself */
133 ia64_sn_console_intr_enable(SAL_CONSOLE_INTR_RECV);
139 /* These are functions to use from serial_in/out when in protocol
140 * mode to send and receive uart control regs. These are external
141 * interfaces into the protocol driver.
145 l1_control_out(int offset, int value)
147 /* quietly ignore unless simulator */
148 if ( IS_RUNNING_ON_SIMULATOR() ) {
149 extern u64 master_node_bedrock_address;
150 if ( master_node_bedrock_address != (u64)0 ) {
151 writeb(value, (unsigned long)master_node_bedrock_address +
158 /* Console input exported interface. Return a register value. */
161 l1_control_in_polled(int offset)
163 static int l1_control_in_local(int);
165 return(l1_control_in_local(offset));
169 l1_control_in(int offset)
171 static int l1_control_in_local(int);
173 return(l1_control_in_local(offset));
177 l1_control_in_local(int offset)
179 int sal_call_status = 0, input;
182 if ( IS_RUNNING_ON_SIMULATOR() ) {
183 extern u64 master_node_bedrock_address;
184 ret = readb((unsigned long)master_node_bedrock_address +
188 if ( offset == REG_LSR ) {
189 ret = (LSR_XHRE | LSR_XSRE); /* can send anytime */
190 sal_call_status = ia64_sn_console_check(&input);
191 if ( !sal_call_status && input ) {
200 * Console input exported interface. Return a character (if one is available)
204 l1_serial_in_polled(void)
206 static int l1_serial_in_local(void);
208 return(l1_serial_in_local());
214 static int l1_serial_in_local(void);
216 if ( IS_RUNNING_ON_SIMULATOR() ) {
217 extern u64 master_node_bedrock_address;
218 return(readb((unsigned long)master_node_bedrock_address + (REG_DAT<< 3)));
220 return(l1_serial_in_local());
224 l1_serial_in_local(void)
228 if ( IS_RUNNING_ON_SIMULATOR() ) {
229 extern u64 master_node_bedrock_address;
230 return(readb((unsigned long)master_node_bedrock_address + (REG_DAT<< 3)));
233 if ( !(ia64_sn_console_getc(&ch)) )
239 /* Console output exported interface. Write message to the console. */
242 l1_serial_out( char *str, int len )
246 /* Ignore empty messages */
250 #if defined(CONFIG_IA64_EARLY_PRINTK)
251 /* Need to setup SAL calls so the PROM calls will work */
254 void early_sn_setup(void);
262 if ( IS_RUNNING_ON_SIMULATOR() ) {
263 extern u64 master_node_bedrock_address;
264 void early_sn_setup(void);
267 if (!master_node_bedrock_address)
269 if ( master_node_bedrock_address != (u64)0 ) {
270 #ifdef FLAG_DIRECT_CONSOLE_WRITES
271 /* This is an easy way to pre-pend the output to know whether the output
272 * was done via sal or directly */
273 writeb('[', (unsigned long)master_node_bedrock_address + (REG_DAT<< 3));
274 writeb('+', (unsigned long)master_node_bedrock_address + (REG_DAT<< 3));
275 writeb(']', (unsigned long)master_node_bedrock_address + (REG_DAT<< 3));
276 writeb(' ', (unsigned long)master_node_bedrock_address + (REG_DAT<< 3));
277 #endif /* FLAG_DIRECT_CONSOLE_WRITES */
278 while ( counter > 0 ) {
279 writeb(*str, (unsigned long)master_node_bedrock_address + (REG_DAT<< 3));
287 /* Attempt to write things out thru the sal */
289 tmp = ia64_sn_console_xmit_chars(str, len);
291 tmp = ia64_sn_console_putb(str, len);
292 return ((tmp < 0) ? 0 : tmp);