File: /usr/src/linux/arch/ia64/sn/io/l1.c

1     /* $Id$
2      *
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
5      * for more details.
6      *
7      * Copyright (C) 1992 - 1997, 2000 Silicon Graphics, Inc.
8      * Copyright (C) 2000 by Colin Ngam
9      */
10     
11     /* In general, this file is organized in a hierarchy from lower-level
12      * to higher-level layers, as follows:
13      *
14      *	UART routines
15      *	Bedrock/L1 "PPP-like" protocol implementation
16      *	System controller "message" interface (allows multiplexing
17      *		of various kinds of requests and responses with
18      *		console I/O)
19      *	Console interfaces (there are two):
20      *	  (1) "elscuart", used in the IP35prom and (maybe) some
21      *		debugging situations elsewhere, and
22      *	  (2) "l1_cons", the glue that allows the L1 to act
23      *		as the system console for the stdio libraries
24      *
25      * Routines making use of the system controller "message"-style interface
26      * can be found in l1_command.c.  Their names are leftover from early SN0, 
27      * when the "module system controller" (msc) was known as the "entry level
28      * system controller" (elsc).  The names and signatures of those functions 
29      * remain unchanged in order to keep the SN0 -> SN1 system controller
30      * changes fairly localized.
31      */
32     
33     
34     #include <linux/types.h>
35     #include <linux/config.h>
36     #include <linux/slab.h>
37     #include <linux/spinlock.h>
38     #include <asm/sn/sgi.h>
39     #include <asm/sn/iograph.h>
40     #include <asm/sn/invent.h>
41     #include <asm/sn/hcl.h>
42     #include <asm/sn/hcl_util.h>
43     #include <asm/sn/labelcl.h>
44     #include <asm/sn/eeprom.h>
45     #include <asm/sn/ksys/i2c.h>
46     #include <asm/sn/router.h>
47     #include <asm/sn/module.h>
48     #include <asm/sn/ksys/l1.h>
49     #include <asm/sn/nodepda.h>
50     #include <asm/sn/clksupport.h>
51     
52     #include <asm/sn/sn1/uart16550.h>
53     
54     /*
55      * Delete this when atomic_clear is part of atomic.h.
56      */
57     static __inline__ int
58     atomic_clear (int i, atomic_t *v)
59     {
60     	__s32 old, new;
61     
62     	do {
63     		old = atomic_read(v);
64     		new = old & ~i;
65     	} while (ia64_cmpxchg("acq", v, old, new, sizeof(atomic_t)) != old);
66     	return new;
67     }
68     
69     #if defined(EEPROM_DEBUG)
70     #define db_printf(x) printk x
71     #else
72     #define db_printf(x)
73     #endif
74     
75     // From irix/kern/sys/SN/SN1/bdrkhspecregs.h
76     #define    HSPEC_UART_0              0x00000080    /* UART Registers         */
77     
78     /*********************************************************************
79      * Hardware-level (UART) driver routines.
80      */
81     
82     /* macros for reading/writing registers */
83     
84     #define LD(x)		(*(volatile uint64_t *)(x))
85     #define SD(x, v)        (LD(x) = (uint64_t) (v))
86     
87     /* location of uart receive/xmit data register */
88     #define L1_UART_BASE(n)	((ulong)REMOTE_HSPEC_ADDR((n), HSPEC_UART_0))
89     #define LOCAL_HUB	LOCAL_HUB_ADDR
90     #define LOCK_HUB	REMOTE_HUB_ADDR
91     
92     #define ADDR_L1_REG(n, r)	\
93         (L1_UART_BASE(n) | ( (r) << 3 ))
94     
95     #define READ_L1_UART_REG(n, r) \
96         ( LD(ADDR_L1_REG((n), (r))) )
97     
98     #define WRITE_L1_UART_REG(n, r, v) \
99         ( SD(ADDR_L1_REG((n), (r)), (v)) )
100     
101     
102     /* UART-related #defines */
103     
104     #define UART_BAUD_RATE		57600
105     #define UART_FIFO_DEPTH		0xf0
106     #define UART_DELAY_SPAN		10
107     #define UART_PUTC_TIMEOUT	50000
108     #define UART_INIT_TIMEOUT	100000
109     
110     /* error codes */
111     #define UART_SUCCESS		  0
112     #define UART_TIMEOUT		(-1)
113     #define UART_LINK		(-2)
114     #define UART_NO_CHAR		(-3)
115     #define UART_VECTOR		(-4)
116     
117     #ifdef BRINGUP
118     #define UART_DELAY(x)	{ int i; i = x * 1000; while (--i); }
119     #else
120     #define UART_DELAY(x)	us_delay(x)
121     #endif
122     
123     /*
124      *	Some macros for handling Endian-ness
125      */
126     
127     #ifdef	LITTLE_ENDIAN
128     #define COPY_INT_TO_BUFFER(_b, _i, _n)		\
129     	{					\
130     		_b[_i++] = (_n >> 24) & 0xff;	\
131     		_b[_i++] = (_n >> 16) & 0xff;	\
132     		_b[_i++] = (_n >>  8) & 0xff;	\
133     		_b[_i++] =  _n        & 0xff;	\
134     	}
135     
136     #define COPY_BUFFER_TO_INT(_b, _i, _n)		\
137     	{					\
138     		_n  = (_b[_i++] << 24) & 0xff;	\
139     		_n |= (_b[_i++] << 16) & 0xff;	\
140     		_n |= (_b[_i++] <<  8) & 0xff;	\
141     		_n |=  _b[_i++]        & 0xff;	\
142     	}
143     
144     #define COPY_BUFFER_TO_BUFFER(_b, _i, _bn)	\
145     	{					\
146     	    char *_xyz = (char *)_bn;		\
147     	    _xyz[3] = _b[_i++];			\
148     	    _xyz[2] = _b[_i++];			\
149     	    _xyz[1] = _b[_i++];			\
150     	    _xyz[0] = _b[_i++];			\
151     	}
152     #else	/* BIG_ENDIAN */
153     
154     extern char *bcopy(const char * src, char * dest, int count);
155     
156     #define COPY_INT_TO_BUFFER(_b, _i, _n)			\
157     	{						\
158     		bcopy((char *)&_n, _b, sizeof(_n));	\
159     		_i += sizeof(_n);			\
160     	}
161     
162     #define COPY_BUFFER_TO_INT(_b, _i, _n)			\
163     	{						\
164     		bcopy(&_b[_i], &_n, sizeof(_n));	\
165     		_i += sizeof(_n);			\
166     	}
167     
168     #define COPY_BUFFER_TO_BUFFER(_b, _i, _bn)		\
169     	{						\
170                 bcopy(&(_b[_i]), _bn, sizeof(int));		\
171                 _i += sizeof(int);				\
172     	}
173     #endif	/* LITTLE_ENDIAN */
174     
175     void kmem_free(void *where, int size);
176     
177     #define BCOPY(x,y,z)	memcpy(y,x,z)
178     
179     /*
180      * Console locking defines and functions.
181      *
182      */
183     
184     #ifdef BRINGUP
185     #define FORCE_CONSOLE_NASID
186     #endif
187     
188     #define HUB_LOCK		16
189     
190     #define PRIMARY_LOCK_TIMEOUT    10000000
191     #define HUB_LOCK_REG(n)         LOCK_HUB(n, MD_PERF_CNT0)
192     
193     #define SET_BITS(reg, bits)     SD(reg, LD(reg) |  (bits))
194     #define CLR_BITS(reg, bits)     SD(reg, LD(reg) & ~(bits))
195     #define TST_BITS(reg, bits)     ((LD(reg) & (bits)) != 0)
196     
197     #define HUB_TEST_AND_SET(n)	LD(LOCK_HUB(n,LB_SCRATCH_REG3_RZ))
198     #define HUB_CLEAR(n)		SD(LOCK_HUB(n,LB_SCRATCH_REG3),0)
199     
200     #define RTC_TIME_MAX		((rtc_time_t) ~0ULL)
201     
202     
203     /*
204      * primary_lock
205      *
206      *   Allows CPU's 0-3  to mutually exclude the hub from one another by
207      *   obtaining a blocking lock.  Does nothing if only one CPU is active.
208      *
209      *   This lock should be held just long enough to set or clear a global
210      *   lock bit.  After a relatively short timeout period, this routine
211      *   figures something is wrong, and steals the lock. It does not set
212      *   any other CPU to "dead".
213      */
214     inline void
215     primary_lock(nasid_t nasid)
216     {
217     	rtc_time_t          expire;
218     
219     	expire = rtc_time() + PRIMARY_LOCK_TIMEOUT;
220     
221     	while (HUB_TEST_AND_SET(nasid)) {
222     		if (rtc_time() > expire) {
223     			HUB_CLEAR(nasid);
224     		}
225     	}
226     }
227     
228     /*
229      * primary_unlock (internal)
230      *
231      *   Counterpart to primary_lock
232      */
233     
234     inline void
235     primary_unlock(nasid_t nasid)
236     {
237     	HUB_CLEAR(nasid);
238     }
239     
240     /*
241      * hub_unlock
242      *
243      *   Counterpart to hub_lock_timeout and hub_lock
244      */
245     
246     inline void
247     hub_unlock(nasid_t nasid, int level)
248     {
249     	uint64_t mask = 1ULL << level;
250     
251     	primary_lock(nasid);
252     	CLR_BITS(HUB_LOCK_REG(nasid), mask);
253     	primary_unlock(nasid);
254     }
255     
256     /*
257      * hub_lock_timeout
258      *
259      *   Uses primary_lock to implement multiple lock levels.
260      *
261      *   There are 20 lock levels from 0 to 19 (limited by the number of bits
262      *   in HUB_LOCK_REG).  To prevent deadlock, multiple locks should be
263      *   obtained in order of increasingly higher level, and released in the
264      *   reverse order.
265      *
266      *   A timeout value of 0 may be used for no timeout.
267      *
268      *   Returns 0 if successful, -1 if lock times out.
269      */
270     
271     inline int
272     hub_lock_timeout(nasid_t nasid, int level, rtc_time_t timeout)
273     {
274     	uint64_t mask = 1ULL << level;
275     	rtc_time_t expire = (timeout ?  rtc_time() + timeout : RTC_TIME_MAX);
276     	int done    = 0;
277     
278     	while (! done) {
279     		while (TST_BITS(HUB_LOCK_REG(nasid), mask)) {
280     			if (rtc_time() > expire)
281     				return -1;
282     		}
283     
284     		primary_lock(nasid);
285     
286     		if (! TST_BITS(HUB_LOCK_REG(nasid), mask)) {
287     			SET_BITS(HUB_LOCK_REG(nasid), mask);
288     			done = 1;
289     		}
290     		primary_unlock(nasid);
291     	}
292     	return 0;
293     }
294     
295     
296     #define LOCK_TIMEOUT	(0x1500000 * 1) /* 0x1500000 is ~30 sec */
297     
298     inline void
299     lock_console(nasid_t nasid)
300     {
301     	int ret;
302     
303     	ret = hub_lock_timeout(nasid, HUB_LOCK, (rtc_time_t)LOCK_TIMEOUT);
304     	if ( ret != 0 ) {
305     		/* timeout */
306     		hub_unlock(nasid, HUB_LOCK);
307     		/* If the 2nd lock fails, just pile ahead.... */
308     		hub_lock_timeout(nasid, HUB_LOCK, (rtc_time_t)LOCK_TIMEOUT);
309     	}
310     }
311     
312     inline void
313     unlock_console(nasid_t nasid)
314     {
315     	hub_unlock(nasid, HUB_LOCK);
316     }
317     
318     
319     int 
320     get_L1_baud(void)
321     {
322         return UART_BAUD_RATE;
323     }
324     
325     
326     /* uart driver functions */
327     
328     static void
329     uart_delay( rtc_time_t delay_span )
330     {
331         UART_DELAY( delay_span );
332     }
333     
334     #define UART_PUTC_READY(n)      ( (READ_L1_UART_REG((n), REG_LSR) & LSR_XHRE) && (READ_L1_UART_REG((n), REG_MSR) & MSR_CTS) )
335     
336     static int
337     uart_putc( l1sc_t *sc ) 
338     {
339     #ifdef BRINGUP
340         /* need a delay to avoid dropping chars */
341         UART_DELAY(57);
342     #endif
343     #ifdef FORCE_CONSOLE_NASID
344         /* We need this for the console write path _elscuart_flush() -> brl1_send() */
345         sc->nasid = 0;
346     #endif
347         WRITE_L1_UART_REG( sc->nasid, REG_DAT,
348     		       sc->send[sc->sent] );
349         return UART_SUCCESS;
350     }
351     
352     
353     static int
354     uart_getc( l1sc_t *sc )
355     {
356         u_char lsr_reg = 0;
357         nasid_t nasid = sc->nasid;
358     
359     #ifdef FORCE_CONSOLE_NASID
360         nasid = sc->nasid = 0;
361     #endif
362     
363         if( (lsr_reg = READ_L1_UART_REG( nasid, REG_LSR )) & 
364     	(LSR_RCA | LSR_PARERR | LSR_FRMERR) ) 
365         {
366     	if( lsr_reg & LSR_RCA ) 
367     	    return( (u_char)READ_L1_UART_REG( nasid, REG_DAT ) );
368     	else if( lsr_reg & (LSR_PARERR | LSR_FRMERR) ) {
369     	    return UART_LINK;
370     	}
371         }
372     
373         return UART_NO_CHAR;
374     }
375     
376     
377     #define PROM_SER_CLK_SPEED	12000000
378     #define PROM_SER_DIVISOR(x)	(PROM_SER_CLK_SPEED / ((x) * 16))
379     
380     static void
381     uart_init( l1sc_t *sc, int baud )
382     {
383         rtc_time_t expire;
384         int clkdiv;
385         nasid_t nasid;
386     
387         clkdiv = PROM_SER_DIVISOR(baud);
388         expire = rtc_time() + UART_INIT_TIMEOUT;
389         nasid = sc->nasid;
390         
391         /* make sure the transmit FIFO is empty */
392         while( !(READ_L1_UART_REG( nasid, REG_LSR ) & LSR_XSRE) ) {
393     	uart_delay( UART_DELAY_SPAN );
394     	if( rtc_time() > expire ) {
395     	    break;
396     	}
397         }
398     
399         if ( sc->uart == BRL1_LOCALUART )
400     	lock_console(nasid);
401     
402         WRITE_L1_UART_REG( nasid, REG_LCR, LCR_DLAB );
403     	uart_delay( UART_DELAY_SPAN );
404         WRITE_L1_UART_REG( nasid, REG_DLH, (clkdiv >> 8) & 0xff );
405     	uart_delay( UART_DELAY_SPAN );
406         WRITE_L1_UART_REG( nasid, REG_DLL, clkdiv & 0xff );
407     	uart_delay( UART_DELAY_SPAN );
408     
409         /* set operating parameters and set DLAB to 0 */
410         WRITE_L1_UART_REG( nasid, REG_LCR, LCR_BITS8 | LCR_STOP1 );
411     	uart_delay( UART_DELAY_SPAN );
412         WRITE_L1_UART_REG( nasid, REG_MCR, MCR_RTS | MCR_AFE );
413     	uart_delay( UART_DELAY_SPAN );
414     
415         /* disable interrupts */
416         WRITE_L1_UART_REG( nasid, REG_ICR, 0x0 );
417     	uart_delay( UART_DELAY_SPAN );
418     
419         /* enable FIFO mode and reset both FIFOs */
420         WRITE_L1_UART_REG( nasid, REG_FCR, FCR_FIFOEN );
421     	uart_delay( UART_DELAY_SPAN );
422         WRITE_L1_UART_REG( nasid, REG_FCR,
423     	FCR_FIFOEN | FCR_RxFIFO | FCR_TxFIFO );
424     
425         if ( sc->uart == BRL1_LOCALUART )
426     	unlock_console(nasid);
427     }
428     
429     /* This requires the console lock */
430     static void
431     uart_intr_enable( l1sc_t *sc, u_char mask )
432     {
433         u_char lcr_reg, icr_reg;
434         nasid_t nasid = sc->nasid;
435     
436         /* make sure that the DLAB bit in the LCR register is 0
437          */
438         lcr_reg = READ_L1_UART_REG( nasid, REG_LCR );
439         lcr_reg &= ~(LCR_DLAB);
440         WRITE_L1_UART_REG( nasid, REG_LCR, lcr_reg );
441     
442         /* enable indicated interrupts
443          */
444         icr_reg = READ_L1_UART_REG( nasid, REG_ICR );
445         icr_reg |= mask;
446         WRITE_L1_UART_REG( nasid, REG_ICR, icr_reg /*(ICR_RIEN | ICR_TIEN)*/ );
447     }
448     
449     /* This requires the console lock */
450     static void
451     uart_intr_disable( l1sc_t *sc, u_char mask )
452     {
453         u_char lcr_reg, icr_reg;
454         nasid_t nasid = sc->nasid;
455     
456         /* make sure that the DLAB bit in the LCR register is 0
457          */
458         lcr_reg = READ_L1_UART_REG( nasid, REG_LCR );
459         lcr_reg &= ~(LCR_DLAB);
460         WRITE_L1_UART_REG( nasid, REG_LCR, lcr_reg );
461     
462         /* enable indicated interrupts
463          */
464         icr_reg = READ_L1_UART_REG( nasid, REG_ICR );
465         icr_reg &= mask;
466         WRITE_L1_UART_REG( nasid, REG_ICR, icr_reg /*(ICR_RIEN | ICR_TIEN)*/ );
467     }
468     
469     #define uart_enable_xmit_intr(sc) \
470     	uart_intr_enable((sc), ICR_TIEN)
471     
472     #define uart_disable_xmit_intr(sc) \
473             uart_intr_disable((sc), ~(ICR_TIEN))
474     
475     #define uart_enable_recv_intr(sc) \
476             uart_intr_enable((sc), ICR_RIEN)
477     
478     #define uart_disable_recv_intr(sc) \
479             uart_intr_disable((sc), ~(ICR_RIEN))
480     
481     
482     /*********************************************************************
483      * Routines for accessing a remote (router) UART
484      */
485     
486     #define READ_RTR_L1_UART_REG(p, n, r, v)		\
487         {							\
488     	if( vector_read_node( (p), (n), 0,		\
489     			      RR_JBUS1(r), (v) ) ) {	\
490     	    return UART_VECTOR;				\
491     	}						\
492         }
493     
494     #define WRITE_RTR_L1_UART_REG(p, n, r, v)		\
495         {							\
496     	if( vector_write_node( (p), (n), 0,		\
497     			       RR_JBUS1(r), (v) ) ) {	\
498     	    return UART_VECTOR;				\
499     	}						\
500         }
501     
502     #define RTR_UART_PUTC_TIMEOUT	UART_PUTC_TIMEOUT*10
503     #define RTR_UART_DELAY_SPAN	UART_DELAY_SPAN
504     #define RTR_UART_INIT_TIMEOUT	UART_INIT_TIMEOUT*10
505     
506     static int
507     rtr_uart_putc( l1sc_t *sc )
508     {
509         uint64_t regval, c;
510         nasid_t nasid = sc->nasid;
511         net_vec_t path = sc->uart;
512         rtc_time_t expire = rtc_time() + RTR_UART_PUTC_TIMEOUT;
513     
514     #ifdef FORCE_CONSOLE_NASID
515         /* We need this for the console write path _elscuart_flush() -> brl1_send() */
516         nasid = sc->nasid = 0;
517     #endif
518         c = (sc->send[sc->sent] & 0xffULL);
519         
520         while( 1 ) 
521         {
522             /* Check for "tx hold reg empty" bit. */
523     	READ_RTR_L1_UART_REG( path, nasid, REG_LSR, &regval );
524     	if( regval & LSR_XHRE )
525     	{
526     	    WRITE_RTR_L1_UART_REG( path, nasid, REG_DAT, c );
527     	    return UART_SUCCESS;
528     	}
529     
530     	if( rtc_time() >= expire ) 
531     	{
532     	    return UART_TIMEOUT;
533     	}
534     	uart_delay( RTR_UART_DELAY_SPAN );
535         }
536     }
537     
538     
539     static int
540     rtr_uart_getc( l1sc_t *sc )
541     {
542         uint64_t regval;
543         nasid_t nasid = sc->nasid;
544         net_vec_t path = sc->uart;
545     
546     #ifdef FORCE_CONSOLE_NASID
547         nasid = sc->nasid = 0;
548     #endif
549     
550         READ_RTR_L1_UART_REG( path, nasid, REG_LSR, &regval );
551         if( regval & (LSR_RCA | LSR_PARERR | LSR_FRMERR) )
552         {
553     	if( regval & LSR_RCA )
554     	{
555     	    READ_RTR_L1_UART_REG( path, nasid, REG_DAT, &regval );
556     	    return( (int)regval );
557     	}
558     	else
559     	{
560     	    return UART_LINK;
561     	}
562         }
563     
564         return UART_NO_CHAR;
565     }
566     
567     
568     static int
569     rtr_uart_init( l1sc_t *sc, int baud )
570     {
571         rtc_time_t expire;
572         int clkdiv;
573         nasid_t nasid;
574         net_vec_t path;
575         uint64_t regval;
576     
577         clkdiv = PROM_SER_DIVISOR(baud);
578         expire = rtc_time() + RTR_UART_INIT_TIMEOUT;
579         nasid = sc->nasid;
580         path = sc->uart;
581     
582         /* make sure the transmit FIFO is empty */
583         while(1) {
584     	READ_RTR_L1_UART_REG( path, nasid, REG_LSR, &regval );
585     	if( regval & LSR_XSRE ) {
586     	    break;
587     	}
588     	if( rtc_time() > expire ) {
589     	    break;
590     	}
591     	uart_delay( RTR_UART_DELAY_SPAN );
592         }
593     
594         WRITE_RTR_L1_UART_REG( path, nasid, REG_LCR, LCR_DLAB  );
595     	uart_delay( UART_DELAY_SPAN );
596         WRITE_RTR_L1_UART_REG( path, nasid, REG_DLH, (clkdiv >> 8) & 0xff  );
597     	uart_delay( UART_DELAY_SPAN );
598         WRITE_RTR_L1_UART_REG( path, nasid, REG_DLL, clkdiv & 0xff  );
599     	uart_delay( UART_DELAY_SPAN );
600     
601         /* set operating parameters and set DLAB to 0 */
602         WRITE_RTR_L1_UART_REG( path, nasid, REG_LCR, LCR_BITS8 | LCR_STOP1  );
603     	uart_delay( UART_DELAY_SPAN );
604         WRITE_RTR_L1_UART_REG( path, nasid, REG_MCR, MCR_RTS | MCR_AFE  );
605     	uart_delay( UART_DELAY_SPAN );
606     
607         /* disable interrupts */
608         WRITE_RTR_L1_UART_REG( path, nasid, REG_ICR, 0x0  );
609     	uart_delay( UART_DELAY_SPAN );
610     
611         /* enable FIFO mode and reset both FIFOs */
612         WRITE_RTR_L1_UART_REG( path, nasid, REG_FCR, FCR_FIFOEN  );
613     	uart_delay( UART_DELAY_SPAN );
614         WRITE_RTR_L1_UART_REG( path, nasid, REG_FCR,
615     	FCR_FIFOEN | FCR_RxFIFO | FCR_TxFIFO );
616     
617         return 0;
618     }
619     
620     
621     /*********************************************************************
622      * subchannel manipulation 
623      *
624      * The SUBCH_[UN]LOCK macros are used to arbitrate subchannel
625      * allocation.  SUBCH_DATA_[UN]LOCK control access to data structures
626      * associated with particular subchannels (e.g., receive queues).
627      *
628      */
629     
630     #ifdef SPINLOCKS_WORK
631     #define SUBCH_LOCK(sc)			spin_lock_irq( &((sc)->subch_lock) )
632     #define SUBCH_UNLOCK(sc)		spin_unlock_irq( &((sc)->subch_lock) )
633     #define SUBCH_DATA_LOCK(sbch) 		spin_lock_irq( &((sbch)->data_lock) )
634     #define SUBCH_DATA_UNLOCK(sbch)		spin_unlock_irq( &((sbch)->data_lock) )
635     #else
636     #define SUBCH_LOCK(sc)
637     #define SUBCH_UNLOCK(sc)
638     #define SUBCH_DATA_LOCK(sbch)
639     #define SUBCH_DATA_UNLOCK(sbch)
640     #endif
641     
642     
643     /* get_myid is an internal function that reads the PI_CPU_NUM
644      * register of the local bedrock to determine which of the
645      * four possible CPU's "this" one is
646      */
647     static int
648     get_myid( void )
649     {
650         return( LD(LOCAL_HUB(PI_CPU_NUM)) );
651     }
652     
653     
654     
655     /*********************************************************************
656      * Queue manipulation macros
657      *
658      *
659      */
660     #define NEXT(p)         (((p) + 1) & (BRL1_QSIZE-1)) /* assume power of 2 */
661     
662     #define cq_init(q)      bzero((q), sizeof (*(q)))
663     #define cq_empty(q)     ((q)->ipos == (q)->opos)
664     #define cq_full(q)      (NEXT((q)->ipos) == (q)->opos)
665     #define cq_used(q)      ((q)->opos <= (q)->ipos ?                       \
666                              (q)->ipos - (q)->opos :                        \
667                              BRL1_QSIZE + (q)->ipos - (q)->opos)
668     #define cq_room(q)      ((q)->opos <= (q)->ipos ?                       \
669                              BRL1_QSIZE - 1 + (q)->opos - (q)->ipos :       \
670                              (q)->opos - (q)->ipos - 1)
671     #define cq_add(q, c)    ((q)->buf[(q)->ipos] = (u_char) (c),            \
672                              (q)->ipos = NEXT((q)->ipos))
673     #define cq_rem(q, c)    ((c) = (q)->buf[(q)->opos],                     \
674                              (q)->opos = NEXT((q)->opos))
675     #define cq_discard(q)	((q)->opos = NEXT((q)->opos))
676     
677     #define cq_tent_full(q)	(NEXT((q)->tent_next) == (q)->opos)
678     #define cq_tent_len(q)	((q)->ipos <= (q)->tent_next ?			\
679     			 (q)->tent_next - (q)->ipos :			\
680     			 BRL1_QSIZE + (q)->tent_next - (q)->ipos)
681     #define cq_tent_add(q, c)						\
682     			((q)->buf[(q)->tent_next] = (u_char) (c),	\
683     			 (q)->tent_next = NEXT((q)->tent_next))
684     #define cq_commit_tent(q)						\
685     			((q)->ipos = (q)->tent_next)
686     #define cq_discard_tent(q)						\
687     			((q)->tent_next = (q)->ipos)
688     
689     
690     
691     
692     /*********************************************************************
693      * CRC-16 (for checking bedrock/L1 packets).
694      *
695      * These are based on RFC 1662 ("PPP in HDLC-like framing").
696      */
697     
698     static unsigned short fcstab[256] = {
699           0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
700           0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
701           0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
702           0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
703           0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
704           0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
705           0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
706           0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
707           0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
708           0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
709           0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
710           0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
711           0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
712           0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
713           0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
714           0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
715           0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
716           0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
717           0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
718           0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
719           0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
720           0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
721           0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
722           0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
723           0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
724           0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
725           0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
726           0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
727           0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
728           0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
729           0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
730           0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
731     };
732     
733     #define INIT_CRC	0xFFFF	/* initial CRC value	  */
734     #define	GOOD_CRC	0xF0B8	/* "good" final CRC value */
735     
736     static unsigned short crc16_calc( unsigned short crc, u_char c )
737     {
738         return( (crc >> 8) ^ fcstab[(crc ^ c) & 0xff] );
739     }
740     
741     
742     /***********************************************************************
743      * The following functions implement the PPP-like bedrock/L1 protocol
744      * layer.
745      *
746      */
747     
748     #define BRL1_FLAG_CH	0x7e
749     #define BRL1_ESC_CH	0x7d
750     #define BRL1_XOR_CH	0x20
751     
752     /* L1<->Bedrock packet types */
753     #define BRL1_REQUEST    0x00
754     #define BRL1_RESPONSE   0x20
755     #define BRL1_EVENT      0x40
756     
757     #define BRL1_PKT_TYPE_MASK      0xE0
758     #define BRL1_SUBCH_MASK         0x1F
759     
760     #define PKT_TYPE(tsb)   ((tsb) & BRL1_PKT_TYPE_MASK)
761     #define SUBCH(tsb)	((tsb) & BRL1_SUBCH_MASK)
762     
763     /* timeouts */
764     #define BRL1_INIT_TIMEOUT	500000
765     
766     /*
767      * brl1_discard_packet is a dummy "receive callback" used to get rid
768      * of packets we don't want
769      */
770     void brl1_discard_packet( l1sc_t *sc, int ch )
771     {
772         brl1_sch_t *subch = &sc->subch[ch];
773         sc_cq_t *q = subch->iqp;
774         SUBCH_DATA_LOCK( subch );
775         q->opos = q->ipos;
776         atomic_clear( &(subch->packet_arrived), ~((unsigned)0) );
777         SUBCH_DATA_UNLOCK( subch );
778     }
779     
780     
781     /*
782      * brl1_send_chars sends the send buffer in the l1sc_t structure
783      * out through the uart.  Assumes that the caller has locked the
784      * UART (or send buffer in the kernel).
785      *
786      * This routine doesn't block-- if you want it to, call it in
787      * a loop.
788      */
789     static int
790     brl1_send_chars( l1sc_t *sc )
791     {
792         /* In the kernel, we track the depth of the C brick's UART's
793          * fifo in software, and only check if the UART is accepting
794          * characters when our count indicates that the fifo should
795          * be full.
796          *
797          * For remote (router) UARTs, and also for the local (C brick)
798          * UART in the prom, we check with the UART before sending every
799          * character.
800          */
801         if( sc->uart == BRL1_LOCALUART ) 
802         {
803     	if( !(sc->fifo_space) && UART_PUTC_READY( sc->nasid ) )
804     	    sc->fifo_space = UART_FIFO_DEPTH;
805     	
806     	while( (sc->sent < sc->send_len) && (sc->fifo_space) ) {
807     	    uart_putc( sc );
808     	    sc->fifo_space--;
809     	    sc->sent++;
810     	}
811         }
812     
813         else
814     
815         /* The following applies to all UARTs in the prom, and to remote
816          * (router) UARTs in the kernel...
817          */
818     
819     #define TIMEOUT_RETRIES	30
820     
821         {
822     	int result;
823     	int tries = 0;
824     
825     	while( sc->sent < sc->send_len ) {
826     	    result = sc->putc_f( sc );
827     	    if( result >= 0 ) {
828     		(sc->sent)++;
829     		continue;
830     	    }
831     	    if( result == UART_TIMEOUT ) {
832     		tries++;
833     		/* send this character in TIMEOUT_RETRIES... */
834     		if( tries < TIMEOUT_RETRIES ) {
835     		    continue;
836     		}
837     		/* ...or else... */
838     		else {
839     		    /* ...drop the packet. */
840     		    sc->sent = sc->send_len;
841     		    return sc->send_len;
842     		}
843     	    }
844     	    if( result < 0 ) {
845     		return result;
846     	    }
847     	}
848         }
849         return sc->sent;
850     }
851     
852     
853     /* brl1_send formats up a packet and (at least begins to) send it
854      * to the uart.  If the send buffer is in use when this routine obtains
855      * the lock, it will behave differently depending on the "wait" parameter.
856      * For wait == 0 (most I/O), it will return 0 (as in "zero bytes sent"),
857      * hopefully encouraging the caller to back off (unlock any high-level 
858      * spinlocks) and allow the buffer some time to drain.  For wait==1 (high-
859      * priority I/O along the lines of kernel error messages), we will flush
860      * the current contents of the send buffer and beat on the uart
861      * until our message has been completely transmitted.
862      */
863     
864     static int
865     brl1_send( l1sc_t *sc, char *msg, int len, u_char type_and_subch, int wait )
866     {
867         int index;
868         int pkt_len = 0;
869         unsigned short crc = INIT_CRC;
870         char *send_ptr = sc->send;
871     
872     #ifdef BRINGUP
873         /* We want to be sure that we are sending the entire packet before returning */
874         wait = 1;
875     #endif
876         if ( sc->uart == BRL1_LOCALUART )
877     	lock_console(sc->nasid);
878     
879         if( sc->send_in_use ) {
880     	if( !wait ) {
881         	    if ( sc->uart == BRL1_LOCALUART )
882     	    	unlock_console(sc->nasid);
883     	    return 0; /* couldn't send anything; wait for buffer to drain */
884     	}
885     	else {
886     	    /* buffer's in use, but we're synchronous I/O, so we're going
887     	     * to send whatever's in there right now and take the buffer
888     	     */
889     	    while( sc->sent < sc->send_len )
890     		brl1_send_chars( sc );
891     	}
892         }
893         else {
894     	sc->send_in_use = 1;
895         }
896         *send_ptr++ = BRL1_FLAG_CH;
897         *send_ptr++ = type_and_subch;
898         pkt_len += 2;
899         crc = crc16_calc( crc, type_and_subch );
900     
901         /* limit number of characters accepted to max payload size */
902         if( len > (BRL1_QSIZE - 1) )
903     	len = (BRL1_QSIZE - 1);
904     
905         /* copy in the message buffer (inserting PPP 
906          * framing info where necessary)
907          */
908         for( index = 0; index < len; index++ ) {
909     
910     	switch( *msg ) {
911     	    
912     	  case BRL1_FLAG_CH:
913     	    *send_ptr++ = BRL1_ESC_CH;
914     	    *send_ptr++ = (*msg) ^ BRL1_XOR_CH;
915     	    pkt_len += 2;
916     	    break;
917     	    
918     	  case BRL1_ESC_CH:
919     	    *send_ptr++ = BRL1_ESC_CH;
920     	    *send_ptr++ = (*msg) ^ BRL1_XOR_CH;
921     	    pkt_len += 2;
922     	    break;
923     	    
924     	  default:
925     	    *send_ptr++ = *msg;
926     	    pkt_len++;
927     	}
928     	crc = crc16_calc( crc, *msg );
929     	msg++;
930         }
931         crc ^= 0xffff;
932     
933         for( index = 0; index < sizeof(crc); index++ ) {
934     	char crc_char = (char)(crc & 0x00FF);
935     	if( (crc_char == BRL1_ESC_CH) || (crc_char == BRL1_FLAG_CH) ) {
936     	    *send_ptr++ = BRL1_ESC_CH;
937     	    pkt_len++;
938     	    crc_char ^= BRL1_XOR_CH;
939     	}
940     	*send_ptr++ = crc_char;
941     	pkt_len++;
942     	crc >>= 8;
943         }
944         
945         *send_ptr++ = BRL1_FLAG_CH;
946         pkt_len++;
947     
948         sc->send_len = pkt_len;
949         sc->sent = 0;
950     
951         do {
952     	brl1_send_chars( sc );
953         } while( (sc->sent < sc->send_len) && wait );
954     
955         if( sc->sent == sc->send_len ) {
956     	/* success! release the send buffer */
957     	sc->send_in_use = 0;
958         }
959         else if( !wait ) {
960     	/* enable low-water interrupts so buffer will be drained */
961     	uart_enable_xmit_intr(sc);
962         }
963         if ( sc->uart == BRL1_LOCALUART )
964     	unlock_console(sc->nasid);
965         return len;
966     }
967     
968     
969     /* internal function -- used by brl1_receive to read a character 
970      * from the uart and check whether errors occurred in the process.
971      */
972     static int
973     read_uart( l1sc_t *sc, int *c, int *result )
974     {
975         *c = sc->getc_f( sc );
976     
977         /* no character is available */
978         if( *c == UART_NO_CHAR ) {
979     	*result = BRL1_NO_MESSAGE;
980     	return 0;
981         }
982     
983         /* some error in UART */
984         if( *c < 0 ) {
985     	*result = BRL1_LINK;
986     	return 0;
987         }
988     
989         /* everything's fine */
990         *result = BRL1_VALID;
991         return 1;
992     }
993     
994     
995     /*
996      * brl1_receive
997      *
998      * This function reads a Bedrock-L1 protocol packet into the l1sc_t
999      * response buffer.
1000      *
1001      * The operation of this function can be expressed as a finite state
1002      * machine:
1003      *
1004     
1005     START STATE			INPUT		TRANSITION
1006     ==========================================================
1007     BRL1_IDLE (reset or error)	flag		BRL1_FLAG
1008     				other		BRL1_IDLE@
1009     
1010     BRL1_FLAG (saw a flag (0x7e))	flag		BRL1_FLAG
1011     				escape		BRL1_IDLE@
1012     				header byte	BRL1_HDR
1013     				other		BRL1_IDLE@
1014     
1015     BRL1_HDR (saw a type/subch byte)(see below)	BRL1_BODY
1016     						BRL1_HDR
1017     
1018     BRL1_BODY (reading packet body)	flag		BRL1_FLAG
1019     				escape		BRL1_ESC
1020     				other		BRL1_BODY
1021     
1022     BRL1_ESC (saw an escape (0x7d))	flag		BRL1_FLAG@
1023     				escape		BRL1_IDLE@
1024     				other		BRL1_BODY
1025     ==========================================================
1026     
1027     "@" denotes an error transition.
1028     
1029      * The BRL1_HDR state is a transient state which doesn't read input,
1030      * but just provides a way in to code which decides to whom an
1031      * incoming packet should be directed.
1032      *
1033      * brl1_receive can be used to poll for input from the L1, or as 
1034      * an interrupt service routine.  It reads as much data as is
1035      * ready from the junk bus UART and places into the appropriate
1036      * input queues according to subchannel.  The header byte is
1037      * stripped from console-type data, but is retained for message-
1038      * type data (L1 responses).  A length byte will also be
1039      * prepended to message-type packets.
1040      *
1041      * This routine is non-blocking; if the caller needs to block
1042      * for input, it must call brl1_receive in a loop.
1043      *
1044      * brl1_receive returns when there is no more input, the queue
1045      * for the current incoming message is full, or there is an
1046      * error (parity error, bad header, bad CRC, etc.).
1047      */
1048     
1049     #define STATE_SET(l,s)	((l)->brl1_state = (s))
1050     #define STATE_GET(l)	((l)->brl1_state)
1051     
1052     #define LAST_HDR_SET(l,h)	((l)->brl1_last_hdr = (h))
1053     #define LAST_HDR_GET(l)		((l)->brl1_last_hdr)
1054     
1055     #define SEQSTAMP_INCR(l)
1056     #define SEQSTAMP_GET(l)
1057     
1058     #define VALID_HDR(c)				\
1059         ( SUBCH((c)) <= SC_CONS_SYSTEM		\
1060     	? PKT_TYPE((c)) == BRL1_REQUEST		\
1061     	: ( PKT_TYPE((c)) == BRL1_RESPONSE ||	\
1062     	    PKT_TYPE((c)) == BRL1_EVENT ) )
1063     
1064     #define IS_TTY_PKT(l) \
1065              ( SUBCH(LAST_HDR_GET(l)) <= SC_CONS_SYSTEM ? 1 : 0 )
1066     
1067     
1068     int
1069     brl1_receive( l1sc_t *sc )
1070     {
1071         int result;		/* value to be returned by brl1_receive */
1072         int c;		/* most-recently-read character	     	*/
1073         int done;		/* set done to break out of recv loop	*/
1074         sc_cq_t *q;		/* pointer to queue we're working with	*/
1075     
1076         result = BRL1_NO_MESSAGE;
1077     
1078     #ifdef FORCE_CONSOLE_NASID
1079         sc->nasid = 0;
1080     #endif
1081         if ( sc->uart == BRL1_LOCALUART )
1082     	lock_console(sc->nasid);
1083     
1084         done = 0;
1085         while( !done )
1086         {
1087     	switch( STATE_GET(sc) )
1088     	{
1089     
1090     	  case BRL1_IDLE:
1091     	    /* Initial or error state.  Waiting for a flag character
1092                  * to resynchronize with the L1.
1093                  */
1094     
1095     	    if( !read_uart( sc, &c, &result ) ) {
1096     
1097     		/* error reading uart */
1098     		done = 1;
1099     		continue;
1100     	    }
1101     	    
1102     	    if( c == BRL1_FLAG_CH ) {
1103     		/* saw a flag character */
1104     		STATE_SET( sc, BRL1_FLAG );
1105     		continue;
1106     	    }
1107     	    break;
1108     	    
1109     	  case BRL1_FLAG:
1110     	    /* One or more flag characters have been read; look for
1111     	     * the beginning of a packet (header byte).
1112     	     */
1113     	    
1114     	    if( !read_uart( sc, &c, &result ) ) {
1115     
1116     		/* error reading uart */
1117     		if( c != UART_NO_CHAR )
1118     		    STATE_SET( sc, BRL1_IDLE );
1119     
1120     		done = 1;
1121     		continue;
1122     	    }
1123     	    
1124     	    if( c == BRL1_FLAG_CH ) {
1125     		/* multiple flags are OK */
1126     		continue;
1127     	    }
1128     
1129     	    if( !VALID_HDR( c ) ) {
1130     		/* if c isn't a flag it should have been
1131     		 * a valid header, so we have an error
1132     		 */
1133     		result = BRL1_PROTOCOL;
1134     		STATE_SET( sc, BRL1_IDLE );
1135     		done = 1;
1136     		continue;
1137     	    }
1138     
1139     	    /* we have a valid header byte */
1140     	    LAST_HDR_SET( sc, c );
1141     	    STATE_SET( sc, BRL1_HDR );
1142     
1143     	    break; 
1144     
1145     	  case BRL1_HDR:
1146     	    /* A header byte has been read. Do some bookkeeping. */
1147     	    q = sc->subch[ SUBCH( LAST_HDR_GET(sc) ) ].iqp;
1148     	    ASSERT(q);
1149     	    
1150     	    if( !IS_TTY_PKT(sc) ) {
1151     		/* if this is an event or command response rather
1152     		 * than console I/O, we need to reserve a couple
1153     		 * of extra spaces in the queue for the header
1154     		 * byte and a length byte; if we can't, stay in
1155     		 * the BRL1_HDR state.
1156     		 */
1157     		if( cq_room( q ) < 2 ) {
1158     		    result = BRL1_FULL_Q;
1159     		    done = 1;
1160     		    continue;
1161     		}
1162     		cq_tent_add( q, 0 );			/* reserve length byte */
1163     		cq_tent_add( q, LAST_HDR_GET( sc ) );	/* record header byte  */
1164     	    }
1165     	    STATE_SET( sc, BRL1_BODY );
1166     
1167     	    break;
1168     
1169     	  case BRL1_BODY:
1170     	    /* A header byte has been read.  We are now attempting
1171     	     * to receive the packet body.
1172     	     */
1173     
1174     	    q = sc->subch[ SUBCH( LAST_HDR_GET(sc) ) ].iqp;
1175     	    ASSERT(q);
1176     
1177     	    /* if the queue we want to write into is full, don't read from
1178     	     * the uart (this provides backpressure to the L1 side)
1179     	     */
1180     	    if( cq_tent_full( q ) ) {
1181     		result = BRL1_FULL_Q;
1182     		done = 1;
1183     		continue;
1184     	    }
1185     	    
1186     	    if( !read_uart( sc, &c, &result ) ) {
1187     
1188     		/* error reading uart */
1189     		if( c != UART_NO_CHAR )
1190     		    STATE_SET( sc, BRL1_IDLE );
1191     		done = 1;
1192     		continue;
1193     	    }
1194     
1195     	    if( c == BRL1_ESC_CH ) {
1196     		/* prepare to unescape the next character */
1197     		STATE_SET( sc, BRL1_ESC );
1198     		continue;
1199     	    }
1200     	    
1201     	    if( c == BRL1_FLAG_CH ) {
1202     		/* flag signifies the end of a packet */
1203     
1204     		unsigned short crc;	/* holds the crc as we calculate it */
1205     		int i;			/* index variable */
1206     		brl1_sch_t *subch;      /* subchannel for received packet */
1207     		brl1_notif_t callup;	/* "data ready" callup */
1208     
1209     		/* whatever else may happen, we've seen a flag and we're
1210     		 * starting a new packet
1211     		 */
1212     		STATE_SET( sc, BRL1_FLAG );
1213     		SEQSTAMP_INCR(sc); /* bump the packet sequence counter */
1214     		
1215     		/* if the packet body has less than 2 characters,
1216     		 * it can't be a well-formed packet.  Discard it.
1217     		 */
1218     		if( cq_tent_len( q ) < /* 2 + possible length byte */
1219     		    (2 + (IS_TTY_PKT(sc) ? 0 : 1)) )
1220     		{
1221     		    result = BRL1_PROTOCOL;
1222     		    cq_discard_tent( q );
1223     		    STATE_SET( sc, BRL1_FLAG );
1224     		    done = 1;
1225     		    continue;
1226     		}
1227     		
1228     		/* check CRC */
1229     
1230     		/* accumulate CRC, starting with the header byte and
1231     		 * ending with the transmitted CRC.  This should
1232     		 * result in a known good value.
1233     		 */
1234     		crc = crc16_calc( INIT_CRC, LAST_HDR_GET(sc) );
1235     		for( i = (q->ipos + (IS_TTY_PKT(sc) ? 0 : 2)) % BRL1_QSIZE;
1236     		     i != q->tent_next;
1237     		     i = (i + 1) % BRL1_QSIZE )
1238     		{
1239     		    crc = crc16_calc( crc, q->buf[i] );
1240     		}
1241     
1242     		/* verify the caclulated crc against the "good" crc value;
1243     		 * if we fail, discard the bad packet and return an error.
1244     		 */
1245     		if( crc != (unsigned short)GOOD_CRC ) {
1246     		    result = BRL1_CRC;
1247     		    cq_discard_tent( q );
1248     		    STATE_SET( sc, BRL1_FLAG );
1249     		    done = 1;
1250     		    continue;
1251     		}
1252     		
1253     		/* so the crc check was ok.  Now we discard the CRC
1254     		 * from the end of the received bytes.
1255     		 */
1256     		q->tent_next += (BRL1_QSIZE - 2);
1257     		q->tent_next %= BRL1_QSIZE;
1258     
1259     		/* get the subchannel and lock it */
1260     		subch = &(sc->subch[SUBCH( LAST_HDR_GET(sc) )]);
1261     		SUBCH_DATA_LOCK( subch );
1262     		
1263     		/* if this isn't a console packet, we need to record
1264     		 * a length byte
1265     		 */
1266     		if( !IS_TTY_PKT(sc) ) {
1267     		    q->buf[q->ipos] = cq_tent_len( q ) - 1;
1268     		}
1269     		
1270     		/* record packet for posterity */
1271     		cq_commit_tent( q );
1272     		result = BRL1_VALID;
1273     
1274     		/* notify subchannel owner that there's something
1275     		 * on the queue for them
1276     		 */
1277     		atomic_inc(&(subch->packet_arrived));
1278     		callup = subch->rx_notify;
1279     		SUBCH_DATA_UNLOCK( subch );
1280     
1281     		if( callup ) {
1282     		    if ( sc->uart == BRL1_LOCALUART )
1283     			unlock_console(sc->nasid);
1284     		    (*callup)( sc, SUBCH(LAST_HDR_GET(sc)) );
1285     		    if ( sc->uart == BRL1_LOCALUART )
1286     			lock_console(sc->nasid);
1287     		}
1288     		continue;	/* go back for more! */
1289     	    }
1290     	    
1291     	    /* none of the special cases applied; we've got a normal
1292     	     * body character
1293     	     */
1294     	    cq_tent_add( q, c );
1295     
1296     	    break;
1297     
1298     	  case BRL1_ESC:
1299     	    /* saw an escape character.  The next character will need
1300     	     * to be unescaped.
1301     	     */
1302     
1303     	    q = sc->subch[ SUBCH( LAST_HDR_GET(sc) ) ].iqp;
1304     	    ASSERT(q);
1305     
1306     	    /* if the queue we want to write into is full, don't read from
1307     	     * the uart (this provides backpressure to the L1 side)
1308     	     */
1309     	    if( cq_tent_full( q ) ) {
1310     		result = BRL1_FULL_Q;
1311     		done = 1;
1312     		continue;
1313     	    }
1314     	    
1315     	    if( !read_uart( sc, &c, &result ) ) {
1316     
1317     		/* error reading uart */
1318     		if( c != UART_NO_CHAR ) {
1319     		    cq_discard_tent( q );
1320     		    STATE_SET( sc, BRL1_IDLE );
1321     		}
1322     		done = 1;
1323     		continue;
1324     	    }
1325     	    
1326     	    if( c == BRL1_FLAG_CH ) {
1327     		/* flag after escape is an error */
1328     		STATE_SET( sc, BRL1_FLAG );
1329     		cq_discard_tent( q );
1330     		result = BRL1_PROTOCOL;
1331     		done = 1;
1332     		continue;
1333     	    }
1334     
1335     	    if( c == BRL1_ESC_CH ) {
1336     		/* two consecutive escapes is an error */
1337     		STATE_SET( sc, BRL1_IDLE );
1338     		cq_discard_tent( q );
1339     		result = BRL1_PROTOCOL;
1340     		done = 1;
1341     		continue;
1342     	    }
1343     	    
1344     	    /* otherwise, we've got a character that needs
1345     	     * to be unescaped
1346     	     */
1347     	    cq_tent_add( q, (c ^ BRL1_XOR_CH) );
1348     	    STATE_SET( sc, BRL1_BODY );
1349     
1350     	    break;
1351     
1352     	} /* end of switch( STATE_GET(sc) ) */
1353         } /* end of while(!done) */
1354         
1355         if ( sc->uart == BRL1_LOCALUART )
1356     	unlock_console(sc->nasid);
1357     
1358         return result;
1359     }	    
1360     
1361     
1362     /* brl1_init initializes the Bedrock/L1 protocol layer.  This includes
1363      * zeroing out the send and receive state information.
1364      */
1365     
1366     void
1367     brl1_init( l1sc_t *sc, nasid_t nasid, net_vec_t uart )
1368     {
1369         int i;
1370         brl1_sch_t *subch;
1371     
1372         bzero( sc, sizeof( *sc ) );
1373     #ifdef FORCE_CONSOLE_NASID
1374         nasid = (nasid_t)0;
1375     #endif
1376         sc->nasid = nasid;
1377         sc->uart = uart;
1378         sc->getc_f = (uart == BRL1_LOCALUART ? uart_getc : rtr_uart_getc);
1379         sc->putc_f = (uart == BRL1_LOCALUART ? uart_putc : rtr_uart_putc);
1380         sc->sol = 1;
1381         subch = sc->subch;
1382     
1383         /* initialize L1 subchannels
1384          */
1385     
1386         /* assign processor TTY channels */
1387         for( i = 0; i < CPUS_PER_NODE; i++, subch++ ) {
1388     	subch->use = BRL1_SUBCH_RSVD;
1389     	subch->packet_arrived = ATOMIC_INIT(0);
1390     	spin_lock_init( &(subch->data_lock) );
1391     	sv_init( &(subch->arrive_sv), &(subch->data_lock), SV_MON_SPIN | SV_ORDER_FIFO /* | SV_INTS */ );
1392     	subch->tx_notify = NULL;
1393     	/* (for now, drop elscuart packets in the kernel) */
1394     	subch->rx_notify = brl1_discard_packet;
1395     	subch->iqp = &sc->garbage_q;
1396         }
1397     
1398         /* assign system TTY channel (first free subchannel after each
1399          * processor's individual TTY channel has been assigned)
1400          */
1401         subch->use = BRL1_SUBCH_RSVD;
1402         subch->packet_arrived = ATOMIC_INIT(0);
1403         spin_lock_init( &(subch->data_lock) );
1404         sv_init( &(subch->arrive_sv), &subch->data_lock, SV_MON_SPIN | SV_ORDER_FIFO /* | SV_INTS */ );
1405         subch->tx_notify = NULL;
1406         if( sc->uart == BRL1_LOCALUART ) {
1407     	subch->iqp = kmem_zalloc_node( sizeof(sc_cq_t), KM_NOSLEEP,
1408     				       NASID_TO_COMPACT_NODEID(nasid) );
1409     	ASSERT( subch->iqp );
1410     	cq_init( subch->iqp );
1411     	subch->rx_notify = NULL;
1412         }
1413         else {
1414     	/* we shouldn't be getting console input from remote UARTs */
1415     	subch->iqp = &sc->garbage_q;
1416     	subch->rx_notify = brl1_discard_packet;
1417         }
1418         subch++; i++;
1419     
1420         /* "reserved" subchannels (0x05-0x0F); for now, throw away
1421          * incoming packets
1422          */
1423         for( ; i < 0x10; i++, subch++ ) {
1424     	subch->use = BRL1_SUBCH_FREE;
1425     	subch->packet_arrived = ATOMIC_INIT(0);
1426     	subch->tx_notify = NULL;
1427     	subch->rx_notify = brl1_discard_packet;
1428     	subch->iqp = &sc->garbage_q;
1429         }
1430     
1431         /* remaining subchannels are free */
1432         for( ; i < BRL1_NUM_SUBCHANS; i++, subch++ ) {
1433     	subch->use = BRL1_SUBCH_FREE;
1434     	subch->packet_arrived = ATOMIC_INIT(0);
1435     	subch->tx_notify = NULL;
1436     	subch->rx_notify = brl1_discard_packet;
1437     	subch->iqp = &sc->garbage_q;
1438         }
1439     
1440         /* initialize synchronization structures
1441          */
1442         spin_lock_init( &(sc->subch_lock) );
1443     
1444         if( sc->uart == BRL1_LOCALUART ) {
1445     	uart_init( sc, UART_BAUD_RATE );
1446         }
1447         else {
1448     	rtr_uart_init( sc, UART_BAUD_RATE );
1449         }
1450     
1451         /* Set up remaining fields using L1 command functions-- elsc_module_get
1452          * to read the module id, elsc_debug_get to see whether or not we're
1453          * in verbose mode.
1454          */
1455         {
1456     	extern int elsc_module_get(l1sc_t *);
1457     
1458     	sc->modid = elsc_module_get( sc );
1459     	sc->modid = (sc->modid < 0 ? INVALID_MODULE : sc->modid);
1460     	sc->verbose = 1;
1461         }
1462     }
1463     
1464     
1465     /* These are functions to use from serial_in/out when in protocol
1466      * mode to send and receive uart control regs. These are external
1467      * interfaces into the protocol driver.
1468      */
1469     void
1470     l1_control_out(int offset, int value)
1471     {
1472     	nasid_t nasid = 0; //(get_elsc())->nasid;
1473     	WRITE_L1_UART_REG(nasid, offset, value); 
1474     }
1475     
1476     int
1477     l1_control_in(int offset)
1478     {
1479     	nasid_t nasid = 0; //(get_elsc())->nasid;
1480     	return(READ_L1_UART_REG(nasid, offset)); 
1481     }
1482     
1483     #define PUTCHAR(ch) \
1484         { \
1485             while( (!(READ_L1_UART_REG( nasid, REG_LSR ) & LSR_XHRE)) || \
1486                     (!(READ_L1_UART_REG( nasid, REG_MSR ) & MSR_CTS)) ); \
1487             WRITE_L1_UART_REG( nasid, REG_DAT, (ch) ); \
1488         }
1489     
1490     int
1491     l1_serial_out( char *str, int len )
1492     {
1493         int sent = len;
1494         char crc_char;
1495         unsigned short crc = INIT_CRC;
1496         nasid_t nasid = 0; //(get_elsc())->nasid;
1497     
1498         lock_console(nasid);
1499     
1500         PUTCHAR( BRL1_FLAG_CH );
1501         PUTCHAR( BRL1_EVENT | SC_CONS_SYSTEM );
1502         crc = crc16_calc( crc, (BRL1_EVENT | SC_CONS_SYSTEM) );
1503     
1504         while( len ) {
1505     
1506     	if( (*str == BRL1_FLAG_CH) || (*str == BRL1_ESC_CH) ) {
1507     	    PUTCHAR( BRL1_ESC_CH );
1508     	    PUTCHAR( (*str) ^ BRL1_XOR_CH );
1509     	}
1510     	else {
1511     	    PUTCHAR( *str );
1512     	}
1513     	
1514     	crc = crc16_calc( crc, *str );
1515     
1516     	str++; len--;
1517         }
1518         
1519         crc ^= 0xffff;
1520         crc_char = crc & 0xff;
1521         if( (crc_char == BRL1_ESC_CH) || (crc_char == BRL1_FLAG_CH) ) {
1522     	crc_char ^= BRL1_XOR_CH;
1523     	PUTCHAR( BRL1_ESC_CH );
1524         }
1525         PUTCHAR( crc_char );
1526         crc_char = (crc >> 8) & 0xff;
1527         if( (crc_char == BRL1_ESC_CH) || (crc_char == BRL1_FLAG_CH) ) {
1528     	crc_char ^= BRL1_XOR_CH;
1529     	PUTCHAR( BRL1_ESC_CH );
1530         }
1531         PUTCHAR( crc_char );
1532         PUTCHAR( BRL1_FLAG_CH );
1533     
1534         unlock_console(nasid);
1535         return sent - len;
1536     }
1537     
1538     int
1539     l1_serial_in(void)
1540     {
1541     	static int l1_cons_getc( l1sc_t *sc );
1542     
1543     	return(l1_cons_getc(get_elsc()));
1544     }
1545     
1546     
1547     /*********************************************************************
1548      * l1_cons functions
1549      *
1550      * These allow the L1 to act as the system console.  They're intended
1551      * to abstract away most of the br/l1 internal details from the
1552      * _L1_cons_* functions (in the prom-- see "l1_console.c") and
1553      * l1_* functions (in the kernel-- see "sio_l1.c") that they support.
1554      *
1555      */
1556     
1557     static int
1558     l1_cons_poll( l1sc_t *sc )
1559     {
1560         /* in case this gets called before the l1sc_t structure for the module_t
1561          * struct for this node is initialized (i.e., if we're called with a
1562          * zero l1sc_t pointer)...
1563          */
1564         if( !sc ) {
1565     	return 0;
1566         }
1567     
1568         if( atomic_read(&sc->subch[SC_CONS_SYSTEM].packet_arrived) ) {
1569     	return 1;
1570         }
1571     
1572         brl1_receive( sc );
1573     
1574         if( atomic_read(&sc->subch[SC_CONS_SYSTEM].packet_arrived) ) {
1575     	return 1;
1576         }
1577         return 0;
1578     }
1579     
1580     
1581     /* pull a character off of the system console queue (if one is available)
1582      */
1583     static int
1584     l1_cons_getc( l1sc_t *sc )
1585     {
1586         int c;
1587     
1588         brl1_sch_t *subch = &(sc->subch[SC_CONS_SYSTEM]);
1589         sc_cq_t *q = subch->iqp;
1590     
1591         if( !l1_cons_poll( sc ) ) {
1592     	return 0;
1593         }
1594     
1595         SUBCH_DATA_LOCK( subch );
1596         if( cq_empty( q ) ) {
1597     	atomic_set(&subch->packet_arrived, 0);
1598     	SUBCH_DATA_UNLOCK( subch );
1599     	return 0;
1600         }
1601         cq_rem( q, c );
1602         if( cq_empty( q ) )
1603     	atomic_set(&subch->packet_arrived, 0);
1604         SUBCH_DATA_UNLOCK( subch );
1605     
1606         return c;
1607     }
1608     
1609     
1610     /* initialize the system console subchannel
1611      */
1612     void
1613     l1_cons_init( l1sc_t *sc )
1614     {
1615         brl1_sch_t *subch = &(sc->subch[SC_CONS_SYSTEM]);
1616     
1617         SUBCH_DATA_LOCK( subch );
1618         atomic_set(&subch->packet_arrived, 0);
1619         cq_init( subch->iqp );
1620         SUBCH_DATA_UNLOCK( subch );
1621     }
1622     
1623     
1624     /*********************************************************************
1625      * The following functions and definitions implement the "message"-
1626      * style interface to the L1 system controller.
1627      *
1628      * Note that throughout this file, "sc" generally stands for "system
1629      * controller", while "subchannels" tend to be represented by
1630      * variables with names like subch or ch.
1631      *
1632      */
1633     
1634     #ifdef L1_DEBUG
1635     #define L1_DBG_PRF(x) printf x
1636     #else
1637     #define L1_DBG_PRF(x)
1638     #endif
1639     
1640     /* sc_data_ready is called to signal threads that are blocked on 
1641      * l1 input.
1642      */
1643     void
1644     sc_data_ready( l1sc_t *sc, int ch )
1645     {
1646         brl1_sch_t *subch = &(sc->subch[ch]);
1647         SUBCH_DATA_LOCK( subch );
1648         sv_signal( &(subch->arrive_sv) );
1649         SUBCH_DATA_UNLOCK( subch );
1650     }
1651     
1652     /* sc_open reserves a subchannel to send a request to the L1 (the
1653      * L1's response will arrive on the same channel).  The number
1654      * returned by sc_open is the system controller subchannel
1655      * acquired.
1656      */
1657     int
1658     sc_open( l1sc_t *sc, uint target )
1659     {
1660         /* The kernel version implements a locking scheme to arbitrate
1661          * subchannel assignment.
1662          */
1663         int ch;
1664         brl1_sch_t *subch;
1665     
1666         SUBCH_LOCK( sc );
1667     
1668         /* Look for a free subchannel. Subchannels 0-15 are reserved
1669          * for other purposes.
1670          */
1671         for( subch = &(sc->subch[BRL1_CMD_SUBCH]), ch = BRL1_CMD_SUBCH; 
1672     			ch < BRL1_NUM_SUBCHANS; subch++, ch++ ) {
1673             if( subch->use == BRL1_SUBCH_FREE )
1674                 break;
1675         }
1676     
1677         if( ch == BRL1_NUM_SUBCHANS ) {
1678             /* there were no subchannels available! */
1679             SUBCH_UNLOCK( sc );
1680             return SC_NSUBCH;
1681         }
1682     
1683         subch->use = BRL1_SUBCH_RSVD;
1684         SUBCH_UNLOCK( sc );
1685     
1686         atomic_set(&subch->packet_arrived, 0);
1687         subch->target = target;
1688         spin_lock_init( &(subch->data_lock) );
1689         sv_init( &(subch->arrive_sv), &(subch->data_lock), SV_MON_SPIN | SV_ORDER_FIFO /* | SV_INTS */);
1690         subch->tx_notify = NULL;
1691         subch->rx_notify = sc_data_ready;
1692         subch->iqp = kmem_zalloc_node( sizeof(sc_cq_t), KM_NOSLEEP,
1693     				   NASID_TO_COMPACT_NODEID(sc->nasid) );
1694         ASSERT( subch->iqp );
1695         cq_init( subch->iqp );
1696     
1697         return ch;
1698     }
1699     
1700     
1701     /* sc_close frees a Bedrock<->L1 subchannel.
1702      */
1703     int
1704     sc_close( l1sc_t *sc, int ch )
1705     {
1706         brl1_sch_t *subch;
1707     
1708         SUBCH_LOCK( sc );
1709         subch = &(sc->subch[ch]);
1710         if( subch->use != BRL1_SUBCH_RSVD ) {
1711             /* we're trying to close a subchannel that's not open */
1712             return SC_NOPEN;
1713         }
1714     
1715         atomic_set(&subch->packet_arrived, 0);
1716         subch->use = BRL1_SUBCH_FREE;
1717     
1718         SUBCH_DATA_LOCK( subch );
1719         sv_broadcast( &(subch->arrive_sv) );
1720         sv_destroy( &(subch->arrive_sv) );
1721         SUBCH_DATA_UNLOCK( subch );
1722         spin_lock_destroy( &(subch->data_lock) );
1723     
1724         ASSERT( subch->iqp && (subch->iqp != &sc->garbage_q) );
1725         kmem_free( subch->iqp, sizeof(sc_cq_t) );
1726         subch->iqp = &sc->garbage_q;
1727     
1728         SUBCH_UNLOCK( sc );
1729     
1730         return SC_SUCCESS;
1731     }
1732     
1733     
1734     /* sc_construct_msg builds a bedrock-to-L1 request in the supplied
1735      * buffer.  Returns the length of the message.  The
1736      * safest course when passing a buffer to be filled in is to use
1737      * BRL1_QSIZE as the buffer size.
1738      *
1739      * Command arguments are passed as type/argument pairs, i.e., to
1740      * pass the number 5 as an argument to an L1 command, call
1741      * sc_construct_msg as follows:
1742      *
1743      *    char msg[BRL1_QSIZE];
1744      *    msg_len = sc_construct_msg( msg,
1745      *				  BRL1_QSIZE,
1746      *				  target_component,
1747      *                                L1_ADDR_TASK_BOGUSTASK,
1748      *                                L1_BOGUSTASK_REQ_BOGUSREQ,
1749      *                                2,
1750      *                                L1_ARG_INT, 5 );
1751      *
1752      * To pass an additional ASCII argument, you'd do the following:
1753      *
1754      *    char *str;
1755      *    ... str points to a null-terminated ascii string ...
1756      *    msg_len = sc_construct_msg( msg,
1757      *                                BRL1_QSIZE,
1758      *				  target_component,
1759      *                                L1_ADDR_TASK_BOGUSTASK,
1760      *                                L1_BOGUSTASK_REQ_BOGUSREQ,
1761      *                                4,
1762      *                                L1_ARG_INT, 5,
1763      *                                L1_ARG_ASCII, str );
1764      *
1765      * Finally, arbitrary data of unknown type is passed using the argtype
1766      * code L1_ARG_UNKNOWN, a data length, and a buffer pointer, e.g.
1767      *
1768      *    msg_len = sc_construct_msg( msg,
1769      *                                BRL1_QSIZE,
1770      *				  target_component,
1771      *                                L1_ADDR_TASK_BOGUSTASK,
1772      *                                L1_BOGUSTASK_REQ_BOGUSREQ,
1773      *                                3,
1774      *                                L1_ARG_UNKNOWN, 32, bufptr );
1775      *
1776      * ...passes 32 bytes of data starting at bufptr.  Note that no string or
1777      * "unknown"-type argument should be long enough to overflow the message
1778      * buffer.
1779      *
1780      * To construct a message for an L1 command that requires no arguments,
1781      * you'd use the following:
1782      *
1783      *    msg_len = sc_construct_msg( msg,
1784      *                                BRL1_QSIZE,
1785      *				  target_component,
1786      *                                L1_ADDR_TASK_BOGUSTASK,
1787      *                                L1_BOGUSTASK_REQ_BOGUSREQ,
1788      *                                0 );
1789      *
1790      * The final 0 means "no varargs".  Notice that this parameter is used to hold
1791      * the number of additional arguments to sc_construct_msg, _not_ the actual
1792      * number of arguments used by the L1 command (so 2 per L1_ARG_[INT,ASCII]
1793      * type argument, and 3 per L1_ARG_UNKOWN type argument).  A call to construct
1794      * an L1 command which required three integer arguments and two arguments of
1795      * some arbitrary (unknown) type would pass 12 as the value for this parameter.
1796      *
1797      * ENDIANNESS WARNING: The following code does a lot of copying back-and-forth
1798      * between byte arrays and four-byte big-endian integers.  Depending on the
1799      * system controller connection and endianness of future architectures, some
1800      * rewriting might be necessary.
1801      */
1802     int
1803     sc_construct_msg( l1sc_t  *sc,		/* system controller struct */
1804     		  int	   ch,           /* subchannel for this message */
1805     		  char    *msg,          /* message buffer */
1806     		  int      msg_len,      /* size of message buffer */
1807                       l1addr_t addr_task,    /* target system controller task */
1808                       short    req_code,     /* 16-bit request code */
1809                       int      req_nargs,    /* # of arguments (varargs) passed */
1810                       ... )                 /* any additional parameters */
1811     {
1812         uint32_t buf32;   /* 32-bit buffer used to bounce things around */
1813         void *bufptr;       /* used to hold command argument addresses */
1814         va_list al;         /* variable argument list */
1815         int index;          /* current index into msg buffer */
1816         int argno;          /* current position in varargs list */
1817         int l1_argno;       /* running total of arguments to l1 */
1818         int l1_arg_t;       /* argument type/length */
1819         int l1_argno_byte;  /* offset of argument count byte */
1820     
1821         index = argno = 0;
1822     
1823         /* set up destination address */
1824         if( (msg_len -= sizeof( buf32 )) < 0 )
1825     	return -1;
1826         L1_ADDRESS_TO_TASK( &buf32, sc->subch[ch].target, addr_task );
1827         COPY_INT_TO_BUFFER(msg, index, buf32);
1828     
1829         /* copy request code */
1830         if( (msg_len -= 2) < 0 )
1831     	return( -1 );
1832         msg[index++] = ((req_code >> 8) & 0xff);
1833         msg[index++] = (req_code & 0xff);
1834     
1835         if( !req_nargs ) {
1836             return index;
1837         }
1838     
1839         /* reserve a byte for the argument count */
1840         if( (msg_len -= 1) < 0 )
1841     	return( -1 );
1842         l1_argno_byte = index++;
1843         l1_argno = 0;
1844     
1845         /* copy additional arguments */
1846         va_start( al, req_nargs );
1847         while( argno < req_nargs ) {
1848             l1_argno++;
1849             l1_arg_t = va_arg( al, int ); argno++;
1850             switch( l1_arg_t )
1851             {
1852               case L1_ARG_INT:
1853     	    if( (msg_len -= (sizeof( buf32 ) + 1)) < 0 )
1854     		return( -1 );
1855                 msg[index++] = L1_ARG_INT;
1856                 buf32 = (unsigned)va_arg( al, int ); argno++;
1857     	    COPY_INT_TO_BUFFER(msg, index, buf32);
1858                 break;
1859     
1860               case L1_ARG_ASCII:
1861                 bufptr = va_arg( al, char* ); argno++;
1862     	    if( (msg_len -= (strlen( bufptr ) + 2)) < 0 )
1863     		return( -1 );
1864                 msg[index++] = L1_ARG_ASCII;
1865                 strcpy( (char *)&(msg[index]), (char *)bufptr );
1866                 index += (strlen( bufptr ) + 1); /* include terminating null */
1867                 break;
1868     
1869     	  case L1_ARG_UNKNOWN:
1870                   {
1871                       int arglen;
1872     		  
1873                       arglen = va_arg( al, int ); argno++;
1874                       bufptr = va_arg( al, void* ); argno++;
1875     		  if( (msg_len -= (arglen + 1)) < 0 )
1876     		      return( -1 );
1877                       msg[index++] = L1_ARG_UNKNOWN | arglen;
1878                       BCOPY( bufptr, &(msg[index]), arglen  );
1879                       index += arglen;
1880     		  break;
1881                   }
1882     	  
1883     	  default: /* unhandled argument type */
1884     	    return -1;
1885             }
1886         }
1887     
1888         va_end( al );
1889         msg[l1_argno_byte] = l1_argno;
1890     
1891         return index;
1892     }
1893     
1894     
1895     
1896     /* sc_interpret_resp verifies an L1 response to a bedrock request, and
1897      * breaks the response data up into the constituent parts.  If the
1898      * response message indicates error, or if a mismatch is found in the
1899      * expected number and type of arguments, an error is returned.  The
1900      * arguments to this function work very much like the arguments to
1901      * sc_construct_msg, above, except that L1_ARG_INTs must be followed
1902      * by a _pointer_ to an integer that can be filled in by this function.
1903      */
1904     int
1905     sc_interpret_resp( char *resp,          /* buffer received from L1 */
1906                        int   resp_nargs,    /* number of _varargs_ passed in */
1907                        ... )
1908     {
1909         uint32_t buf32;   /* 32-bit buffer used to bounce things around */
1910         void *bufptr;       /* used to hold response field addresses */
1911         va_list al;         /* variable argument list */
1912         int index;          /* current index into response buffer */
1913         int argno;          /* current position in varargs list */
1914         int l1_fldno;       /* number of resp fields received from l1 */
1915         int l1_fld_t;       /* field type/length */
1916     
1917         index = argno = 0;
1918     
1919     #if defined(L1_DEBUG)
1920     #define DUMP_RESP							  \
1921         {									  \
1922     	int ix;								  \
1923             char outbuf[512];						  \
1924             sprintf( outbuf, "sc_interpret_resp error line %d: ", __LINE__ ); \
1925     	for( ix = 0; ix < 16; ix++ ) {					  \
1926     	    sprintf( &outbuf[strlen(outbuf)], "%x ", resp[ix] );	  \
1927     	}								  \
1928     	printk( "%s\n", outbuf );					  \
1929         }
1930     #else
1931     #define DUMP_RESP
1932     #endif /* L1_DEBUG */
1933     
1934         /* check response code */
1935         COPY_BUFFER_TO_INT(resp, index, buf32);
1936         if( buf32 != L1_RESP_OK ) {
1937     	DUMP_RESP;
1938             return buf32;
1939         }
1940     
1941         /* get number of response fields */
1942         l1_fldno = resp[index++];
1943     
1944         va_start( al, resp_nargs );
1945     
1946         /* copy out response fields */
1947         while( argno < resp_nargs ) {
1948             l1_fldno--;
1949             l1_fld_t = va_arg( al, int ); argno++;
1950             switch( l1_fld_t )
1951             {
1952               case L1_ARG_INT:
1953                 if( resp[index++] != L1_ARG_INT ) {
1954                     /* type mismatch */
1955     		va_end( al );
1956     		DUMP_RESP;
1957     		return -1;
1958                 }
1959                 bufptr = va_arg( al, int* ); argno++;
1960     	    COPY_BUFFER_TO_BUFFER(resp, index, bufptr);
1961                 break;
1962     
1963               case L1_ARG_ASCII:
1964                 if( resp[index++] != L1_ARG_ASCII ) {
1965                     /* type mismatch */
1966     		va_end( al );
1967     		DUMP_RESP;
1968                     return -1;
1969                 }
1970                 bufptr = va_arg( al, char* ); argno++;
1971                 strcpy( (char *)bufptr, (char *)&(resp[index]) );
1972                 /* include terminating null */
1973                 index += (strlen( &(resp[index]) ) + 1);
1974                 break;
1975     
1976               default:
1977     	    if( (l1_fld_t & L1_ARG_UNKNOWN) == L1_ARG_UNKNOWN )
1978     	    {
1979     		int *arglen;
1980     		
1981     		arglen = va_arg( al, int* ); argno++;
1982     		bufptr = va_arg( al, void* ); argno++;
1983     		*arglen = ((resp[index++] & ~L1_ARG_UNKNOWN) & 0xff);
1984     		BCOPY( &(resp[index]), bufptr, *arglen  );
1985     		index += (*arglen);
1986     	    }
1987     	    
1988     	    else {
1989     		/* unhandled type */
1990     		va_end( al );
1991     		DUMP_RESP;
1992     		return -1;
1993     	    }
1994             }
1995         }
1996         va_end( al );
1997       
1998         if( (l1_fldno != 0) || (argno != resp_nargs) ) {
1999             /* wrong number of arguments */
2000     	DUMP_RESP;
2001             return -1;
2002         }
2003         return 0;
2004     }
2005     
2006     
2007     
2008     
2009     /* sc_send takes as arguments a system controller struct, a
2010      * buffer which contains a Bedrock<->L1 "request" message,
2011      * the message length, and the subchannel (presumably obtained
2012      * from an earlier invocation of sc_open) over which the
2013      * message is to be sent.  The final argument ("wait") indicates
2014      * whether the send is to be performed synchronously or not.
2015      *
2016      * sc_send returns either zero or an error value.  Synchronous sends 
2017      * (wait != 0) will not return until the data has actually been sent
2018      * to the UART.  Synchronous sends generally receive privileged
2019      * treatment.  The intent is that they be used sparingly, for such
2020      * purposes as kernel printf's (the "ducons" routines).  Run-of-the-mill
2021      * console output and L1 requests should NOT use a non-zero value
2022      * for wait.
2023      */
2024     int
2025     sc_send( l1sc_t *sc, int ch, char *msg, int len, int wait )
2026     {
2027         char type_and_subch;
2028         int result;
2029     
2030         if( (ch < 0) || ( ch >= BRL1_NUM_SUBCHANS) ) {
2031             return SC_BADSUBCH;
2032         }
2033     
2034         /* Verify that this is an open subchannel
2035          */
2036         if( sc->subch[ch].use == BRL1_SUBCH_FREE )
2037         {
2038             return SC_NOPEN;
2039         }
2040            
2041         type_and_subch = (BRL1_REQUEST | ((u_char)ch));
2042         result = brl1_send( sc, msg, len, type_and_subch, wait );
2043     
2044         /* If we sent as much as we asked to, return "ok". */
2045         if( result == len )
2046     	return( SC_SUCCESS );
2047     
2048         /* Or, if we sent less, than either the UART is busy or
2049          * we're trying to send too large a packet anyway.
2050          */
2051         else if( result >= 0 && result < len )
2052     	return( SC_BUSY );
2053     
2054         /* Or, if something else went wrong (result < 0), then
2055          * return that error value.
2056          */
2057         else
2058     	return( result );
2059     }
2060     
2061     
2062     
2063     /* subch_pull_msg pulls a message off the receive queue for subch
2064      * and places it the buffer pointed to by msg.  This routine should only
2065      * be called when the caller already knows a message is available on the
2066      * receive queue (and, in the kernel, only when the subchannel data lock
2067      * is held by the caller).
2068      */
2069     static void
2070     subch_pull_msg( brl1_sch_t *subch, char *msg, int *len )
2071     {
2072         sc_cq_t *q;         /* receive queue */
2073         int before_wrap,    /* packet may be split into two different       */
2074             after_wrap;     /*   pieces to acommodate queue wraparound      */
2075     
2076         /* pull message off the receive queue */
2077         q = subch->iqp;
2078     
2079         cq_rem( q, *len );   /* remove length byte and store */
2080         cq_discard( q );     /* remove type/subch byte and discard */
2081     
2082         if ( *len > 0 )
2083     	(*len)--;        /* don't count type/subch byte in length returned */
2084     
2085         if( (q->opos + (*len)) > BRL1_QSIZE ) {
2086             before_wrap = BRL1_QSIZE - q->opos;
2087             after_wrap = (*len) - before_wrap;
2088         }
2089         else {
2090             before_wrap = (*len);
2091             after_wrap = 0;
2092         }
2093     
2094         BCOPY( q->buf + q->opos, msg, before_wrap  );
2095         if( after_wrap ) {
2096             BCOPY( q->buf, msg + before_wrap, after_wrap  );
2097     	q->opos = after_wrap;
2098         }
2099         else {
2100     	q->opos = ((q->opos + before_wrap) & (BRL1_QSIZE - 1));
2101         }
2102         atomic_dec(&(subch->packet_arrived));
2103     }
2104     
2105     
2106     /* sc_recv_poll can be called as a blocking or non-blocking function;
2107      * it attempts to pull a message off of the subchannel specified
2108      * in the argument list (ch).
2109      *
2110      * The "block" argument, if non-zero, is interpreted as a timeout
2111      * delay (to avoid permanent waiting).
2112      */
2113     
2114     int
2115     sc_recv_poll( l1sc_t *sc, int ch, char *msg, int *len, uint64_t block )
2116     {
2117         int is_msg = 0;
2118         brl1_sch_t *subch = &(sc->subch[ch]);
2119     
2120         rtc_time_t exp_time = rtc_time() + block;
2121     
2122         /* sanity check-- make sure this is an open subchannel */
2123         if( subch->use == BRL1_SUBCH_FREE )
2124     	return( SC_NOPEN );
2125     
2126         do {
2127     
2128             /* kick the next lower layer and see if it pulls anything in
2129              */
2130     	brl1_receive( sc );
2131     	is_msg = atomic_read(&subch->packet_arrived);
2132     
2133         } while( block && !is_msg && (rtc_time() < exp_time) );
2134     
2135         if( !is_msg ) {
2136     	/* no message and we didn't care to wait for one */
2137     	return( SC_NMSG );
2138         }
2139     
2140         SUBCH_DATA_LOCK( subch );
2141         subch_pull_msg( subch, msg, len );
2142         SUBCH_DATA_UNLOCK( subch );
2143     
2144         return( SC_SUCCESS );
2145     }
2146         
2147     
2148     /* Like sc_recv_poll, sc_recv_intr can be called in either a blocking
2149      * or non-blocking mode.  Rather than polling until an appointed timeout,
2150      * however, sc_recv_intr sleeps on a syncrhonization variable until a
2151      * signal from the lower layer tells us that a packet has arrived.
2152      *
2153      * sc_recv_intr can't be used with remote (router) L1s.
2154      */
2155     int
2156     sc_recv_intr( l1sc_t *sc, int ch, char *msg, int *len, uint64_t block )
2157     {
2158         int is_msg = 0;
2159         brl1_sch_t *subch = &(sc->subch[ch]);
2160     
2161         do {
2162     	SUBCH_DATA_LOCK(subch);
2163     	is_msg = atomic_read(&subch->packet_arrived);
2164     	if( !is_msg && block ) {
2165     	    /* wake me when you've got something */
2166     	    subch->rx_notify = sc_data_ready;
2167     	    sv_wait( &(subch->arrive_sv), 0, 0);
2168     	    if( subch->use == BRL1_SUBCH_FREE ) {
2169     		/* oops-- somebody closed our subchannel while we were
2170     		 * sleeping!
2171     		 */
2172     
2173     		/* no need to unlock since the channel's closed anyhow */
2174     		return( SC_NOPEN );
2175     	    }
2176     	}
2177         } while( !is_msg && block );
2178     
2179         if( !is_msg ) {
2180     	/* no message and we didn't care to wait for one */
2181     	SUBCH_DATA_UNLOCK( subch );
2182     	return( SC_NMSG );
2183         }
2184     
2185         subch_pull_msg( subch, msg, len );
2186         SUBCH_DATA_UNLOCK( subch );
2187     
2188         return( SC_SUCCESS );
2189     }
2190     
2191     /* sc_command implements a (blocking) combination of sc_send and sc_recv.
2192      * It is intended to be the SN1 equivalent of SN0's "elsc_command", which
2193      * issued a system controller command and then waited for a response from
2194      * the system controller before returning.
2195      *
2196      * cmd points to the outgoing command; resp points to the buffer in
2197      * which the response is to be stored.  Both buffers are assumed to
2198      * be the same length; if there is any doubt as to whether the
2199      * response buffer is long enough to hold the L1's response, then
2200      * make it BRL1_QSIZE bytes-- no Bedrock<->L1 message can be any
2201      * bigger.
2202      *
2203      * Be careful using the same buffer for both cmd and resp; it could get
2204      * hairy if there were ever an L1 command reqeuest that spanned multiple
2205      * packets.  (On the other hand, that would require some additional
2206      * rewriting of the L1 command interface anyway.)
2207      */
2208     #define __RETRIES	50
2209     #define __WAIT_SEND	( sc->uart != BRL1_LOCALUART )
2210     #define __WAIT_RECV	10000000
2211     
2212     
2213     int
2214     sc_command( l1sc_t *sc, int ch, char *cmd, char *resp, int *len )
2215     {
2216     #ifndef CONFIG_SERIAL_SGI_L1_PROTOCOL
2217         return SC_NMSG;
2218     #else
2219         int result;
2220         int retries;
2221     
2222         if ( IS_RUNNING_ON_SIMULATOR() )
2223         	return SC_NMSG;
2224     
2225         retries = __RETRIES;
2226     
2227         while( (result = sc_send( sc, ch, cmd, *len, __WAIT_SEND )) < 0 ) {
2228     	if( result == SC_BUSY ) {
2229     	    retries--;
2230     	    if( retries <= 0 )
2231     		return result;
2232     	    uart_delay(500);
2233     	}
2234     	else {
2235     	    return result;
2236     	}
2237         }
2238         
2239         /* block on sc_recv_* */
2240     #ifdef LATER
2241         if( sc->uart == BRL1_LOCALUART ) {
2242     	return( sc_recv_intr( sc, ch, resp, len, __WAIT_RECV ) );
2243         }
2244         else
2245     #endif	/* LATER */
2246         {
2247     	return( sc_recv_poll( sc, ch, resp, len, __WAIT_RECV ) );
2248         }
2249     #endif /* CONFIG_SERIAL_SGI_L1_PROTOCOL */
2250     }
2251     
2252     /* sc_command_kern is a knuckle-dragging, no-patience version of sc_command
2253      * used in situations where the kernel has a command that shouldn't be
2254      * delayed until the send buffer clears.  sc_command should be used instead
2255      * under most circumstances.
2256      */
2257     int
2258     sc_command_kern( l1sc_t *sc, int ch, char *cmd, char *resp, int *len )
2259     {
2260     #ifndef CONFIG_SERIAL_SGI_L1_PROTOCOL
2261         return SC_NMSG;
2262     #else
2263         int result;
2264     
2265         if ( IS_RUNNING_ON_SIMULATOR() )
2266         	return SC_NMSG;
2267     
2268         if( (result = sc_send( sc, ch, cmd, *len, 1 )) < 0 ) {
2269     	return result;
2270         }
2271     
2272         return( sc_recv_poll( sc, ch, resp, len, __WAIT_RECV ) );
2273     #endif /* CONFIG_SERIAL_SGI_L1_PROTOCOL */
2274     }
2275     
2276     
2277     
2278     /* sc_poll checks the queue corresponding to the given
2279      * subchannel to see if there's anything available.  If
2280      * not, it kicks the brl1 layer and then checks again.
2281      *
2282      * Returns 1 if input is available on the given queue,
2283      * 0 otherwise.
2284      */
2285     int
2286     sc_poll( l1sc_t *sc, int ch )
2287     {
2288         brl1_sch_t *subch = &(sc->subch[ch]);
2289     
2290         if( atomic_read(&subch->packet_arrived) )
2291     	return 1;
2292     
2293         brl1_receive( sc );
2294     
2295         if( atomic_read(&subch->packet_arrived) )
2296     	return 1;
2297     
2298         return 0;
2299     }
2300     
2301     /* for now, sc_init just calls brl1_init
2302      */
2303     void
2304     sc_init( l1sc_t *sc, nasid_t nasid, net_vec_t uart )
2305     {
2306         if ( !IS_RUNNING_ON_SIMULATOR() )
2307         	brl1_init( sc, nasid, uart );
2308     }
2309     
2310     /* sc_dispatch_env_event handles events sent from the system control
2311      * network's environmental monitor tasks.
2312      */
2313     
2314     #ifdef LINUX_KERNEL_THREADS
2315     
2316     static void
2317     sc_dispatch_env_event( uint code, int argc, char *args, int maxlen )
2318     {
2319         int j, i = 0;
2320         uint32_t ESPcode;
2321     
2322         switch( code ) {
2323     	/* for now, all codes do the same thing: grab two arguments
2324     	 * and print a cmn_err_tag message */
2325           default:
2326     	/* check number of arguments */
2327     	if( argc != 2 ) {
2328     	    L1_DBG_PRF(( "sc_dispatch_env_event: "
2329     			 "expected 2 arguments, got %d\n", argc ));
2330     	    return;
2331     	}
2332     	
2333     	/* get ESP code (integer argument) */
2334     	if( args[i++] != L1_ARG_INT ) {
2335     	    L1_DBG_PRF(( "sc_dispatch_env_event: "
2336     			 "expected integer argument\n" ));
2337     	    return;
2338     	}
2339     	/* WARNING: highly endian */
2340     	COPY_BUFFER_TO_INT(args, i, ESPcode);
2341     
2342     	/* verify string argument */
2343     	if( args[i++] != L1_ARG_ASCII ) {
2344     	    L1_DBG_PRF(( "sc_dispatch_env_event: "
2345     			 "expected an ASCII string\n" ));
2346     	    return;
2347     	}
2348     	for( j = i; j < maxlen; j++ ) {
2349     	    if( args[j] == '\0' ) break; /* found string termination */
2350     	}
2351     	if( j == maxlen ) {
2352     	    j--;
2353     	    L1_DBG_PRF(( "sc_dispatch_env_event: "
2354     			 "message too long-- truncating\n" ));
2355     	}
2356     
2357     	/* strip out trailing cr/lf */
2358     	for( ; 
2359     	     j > 1 && ((args[j-1] == 0xd) || (args[j-1] == 0xa)); 
2360     	     j-- );
2361     	args[j] = '\0';
2362     	
2363     	/* strip out leading cr/lf */
2364     	for( ;
2365     	     i < j && ((args[i] == 0xd) || (args[i] == 0xa));
2366     	     i++ );
2367         }
2368     }
2369     #endif	/* LINUX_KERNEL_THREADS */
2370     
2371     
2372     /* sc_event waits for events to arrive from the system controller, and
2373      * prints appropriate messages to the syslog.
2374      */
2375     
2376     #ifdef LINUX_KERNEL_THREADS
2377     static void
2378     sc_event( l1sc_t *sc, int ch )
2379     {
2380         char event[BRL1_QSIZE];
2381         int i;
2382         int result;
2383         int event_len;
2384         uint32_t ev_src;
2385         uint32_t ev_code;
2386         int ev_argc;
2387     
2388         while(1) {
2389     	
2390     	bzero( event, BRL1_QSIZE );
2391     
2392     	/*
2393     	 * wait for an event 
2394     	 */
2395     	result = sc_recv_intr( sc, ch, event, &event_len, 1 );
2396     	if( result != SC_SUCCESS ) {
2397     	    PRINT_WARNING("Error receiving sysctl event on nasid %d\n",
2398     		     sc->nasid );
2399     	}
2400     	else {
2401     	    /*
2402     	     * an event arrived; break it down into useful pieces
2403     	     */
2404     #if defined(L1_DEBUG) && 0
2405     	    int ix;
2406     	    printf( "Event packet received:\n" );
2407     	    for (ix = 0; ix < 64; ix++) {
2408     		printf( "%x%x ", ((event[ix] >> 4) & ((uint64_t)0xf)),
2409     			(event[ix] & ((uint64_t)0xf)) );
2410     		if( (ix % 16) == 0xf ) printf( "\n" );
2411     	    }
2412     #endif /* L1_DEBUG */
2413     
2414     	    i = 0;
2415     
2416     	    /* get event source */
2417     	    COPY_BUFFER_TO_INT(event, i, ev_src);
2418     	    COPY_BUFFER_TO_INT(event, i, ev_code);
2419     
2420     	    /* get arg count */
2421     	    ev_argc = (event[i++] & 0xffUL);
2422     	    
2423     	    /* dispatch events by task */
2424     	    switch( (ev_src & L1_ADDR_TASK_MASK) >> L1_ADDR_TASK_SHFT )
2425     	    {
2426     	      case L1_ADDR_TASK_ENV: /* environmental monitor event */
2427     		sc_dispatch_env_event( ev_code, ev_argc, &(event[i]), 
2428     				       BRL1_QSIZE - i );
2429     		break;
2430     
2431     	      default: /* unhandled task type */
2432     		L1_DBG_PRF(( "Unhandled event type received from system "
2433     			     "controllers: source task %x\n",
2434     			     (ev_src & L1_ADDR_TASK_MASK) >> L1_ADDR_TASK_SHFT
2435     			   ));
2436     	    }
2437     	}
2438     	
2439         }			
2440     }
2441     #endif	/* LINUX_KERNEL_THREADS */
2442     
2443     /* sc_listen sets up a service thread to listen for incoming events.
2444      */
2445     void
2446     sc_listen( l1sc_t *sc )
2447     {
2448         int result;
2449         brl1_sch_t *subch;
2450     
2451         char        msg[BRL1_QSIZE];
2452         int         len;    /* length of message being sent */
2453         int         ch;     /* system controller subchannel used */
2454     
2455     #ifdef LINUX_KERNEL_THREADS
2456         extern int msc_shutdown_pri;
2457     #endif
2458     
2459         /* grab the designated "event subchannel" */
2460         SUBCH_LOCK( sc );
2461         subch = &(sc->subch[BRL1_EVENT_SUBCH]);
2462         if( subch->use != BRL1_SUBCH_FREE ) {
2463     	SUBCH_UNLOCK( sc );
2464     	PRINT_WARNING("sysctl event subchannel in use! "
2465     		 "Not monitoring sysctl events.\n" );
2466     	return;
2467         }
2468         subch->use = BRL1_SUBCH_RSVD;
2469         SUBCH_UNLOCK( sc );
2470     
2471         atomic_set(&subch->packet_arrived, 0);
2472         subch->target = BRL1_LOCALUART;
2473         spin_lock_init( &(subch->data_lock) );
2474         sv_init( &(subch->arrive_sv), &(subch->data_lock), SV_MON_SPIN | SV_ORDER_FIFO /* | SV_INTS */);
2475         subch->tx_notify = NULL;
2476         subch->rx_notify = sc_data_ready;
2477         subch->iqp = kmem_zalloc_node( sizeof(sc_cq_t), KM_NOSLEEP,
2478     				   NASID_TO_COMPACT_NODEID(sc->nasid) );
2479         ASSERT( subch->iqp );
2480         cq_init( subch->iqp );
2481     
2482     #ifdef LINUX_KERNEL_THREADS
2483         /* set up a thread to listen for events */
2484         sthread_create( "sysctl event handler", 0, 0, 0, msc_shutdown_pri,
2485     		    KT_PS, (st_func_t *) sc_event,
2486     		    (void *)sc, (void *)(uint64_t)BRL1_EVENT_SUBCH, 0, 0 );
2487     #endif
2488     
2489         /* signal the L1 to begin sending events */
2490         bzero( msg, BRL1_QSIZE );
2491         ch = sc_open( sc, L1_ADDR_LOCAL );
2492     
2493         if( (len = sc_construct_msg( sc, ch, msg, BRL1_QSIZE,
2494     				 L1_ADDR_TASK_GENERAL,
2495     				 L1_REQ_EVENT_SUBCH, 2,
2496     				 L1_ARG_INT, BRL1_EVENT_SUBCH )) < 0 )
2497         {
2498     	sc_close( sc, ch );
2499     	L1_DBG_PRF(( "Failure in sc_construct_msg (%d)\n", len ));
2500     	goto err_return;
2501         }
2502     
2503         result = sc_command_kern( sc, ch, msg, msg, &len );
2504         if( result < 0 )
2505         {
2506     	sc_close( sc, ch );
2507     	L1_DBG_PRF(( "Failure in sc_command_kern (%d)\n", result ));
2508     	goto err_return;
2509         }
2510     
2511         sc_close( sc, ch );
2512     
2513         result = sc_interpret_resp( msg, 0 );
2514         if( result < 0 )
2515         {
2516     	L1_DBG_PRF(( "Failure in sc_interpret_resp (%d)\n", result ));
2517     	goto err_return;
2518         }
2519     
2520         /* everything went fine; just return */
2521         return;
2522     	
2523     err_return:
2524         /* there was a problem; complain */
2525         PRINT_WARNING("failed to set sysctl event-monitoring subchannel.  "
2526     	     "Sysctl events will not be monitored.\n" );
2527     }
2528     
2529     
2530     /*********************************************************************
2531      * elscuart functions.  These provide a uart-like interface to the
2532      * bedrock/l1 protocol console channels.  They are similar in form
2533      * and intent to the elscuart_* functions defined for SN0 in elsc.c.
2534      *
2535      */
2536     
2537     int _elscuart_flush( l1sc_t *sc );
2538     
2539     /* Leave room in queue for CR/LF */
2540     #define ELSCUART_LINE_MAX       (BRL1_QSIZE - 2)
2541     
2542     
2543     /*
2544      * _elscuart_putc provides an entry point to the L1 interface driver;
2545      * writes a single character to the output queue.  Flushes at the
2546      * end of each line, and translates newlines into CR/LF.
2547      *
2548      * The kernel should generally use l1_cons_write instead, since it assumes
2549      * buffering, translation, prefixing, etc. are done at a higher
2550      * level.
2551      *
2552      */
2553     int
2554     _elscuart_putc( l1sc_t *sc, int c )
2555     {
2556         sc_cq_t *q;
2557         
2558         q = &(sc->oq[ MAP_OQ(L1_ELSCUART_SUBCH(get_myid())) ]);
2559     
2560         if( c != '\n' && c != '\r' && cq_used(q) >= ELSCUART_LINE_MAX ) {
2561             cq_add( q, '\r' );
2562             cq_add( q, '\n' );
2563              _elscuart_flush( sc );
2564             sc->sol = 1;
2565         }
2566     
2567         if( sc->sol && c != '\r' ) {
2568             char            prefix[16], *s;
2569     
2570             if( cq_room( q ) < 8 && _elscuart_flush(sc) < 0 )
2571             {
2572                 return -1;
2573             }
2574     	
2575     	if( sc->verbose )
2576     	{
2577     #ifdef  SUPPORT_PRINTING_M_FORMAT
2578     	    sprintf( prefix,
2579     		     "%c %d%d%d %M:",
2580     		     'A' + get_myid(),
2581     		     sc->nasid / 100,
2582     		     (sc->nasid / 10) % 10,
2583     		     sc->nasid / 10,
2584     		     sc->modid );
2585     #else
2586     	    sprintf( prefix,
2587     		     "%c %d%d%d 0x%x:",
2588     		     'A' + get_myid(),
2589     		     sc->nasid / 100,
2590     		     (sc->nasid / 10) % 10,
2591     		     sc->nasid / 10,
2592     		     sc->modid );
2593     #endif
2594     	    
2595     	    for( s = prefix; *s; s++ )
2596     		cq_add( q, *s );
2597     	}	    
2598     	sc->sol = 0;
2599     
2600         }
2601     
2602         if( cq_room( q ) < 2 && _elscuart_flush(sc) < 0 )
2603         {
2604             return -1;
2605         }
2606     
2607         if( c == '\n' ) {
2608             cq_add( q, '\r' );
2609             sc->sol = 1;
2610         }
2611     
2612         cq_add( q, (u_char) c );
2613     
2614         if( c == '\n' ) {
2615             /* flush buffered line */
2616             if( _elscuart_flush( sc ) < 0 )
2617             {
2618                 return -1;
2619             }
2620         }
2621     
2622         if( c== '\r' )
2623         {
2624             sc->sol = 1;
2625         }
2626     
2627         return 0;
2628     }
2629     
2630     
2631     /*
2632      * _elscuart_getc reads a character from the input queue.  This
2633      * routine blocks.
2634      */
2635     int
2636     _elscuart_getc( l1sc_t *sc )
2637     {
2638         int r;
2639     
2640         while( (r = _elscuart_poll( sc )) == 0 );
2641     
2642         if( r < 0 ) {
2643     	/* some error occurred */
2644     	return r;
2645         }
2646     
2647         return _elscuart_readc( sc );
2648     }
2649     
2650     
2651     
2652     /*
2653      * _elscuart_poll returns 1 if characters are ready for the
2654      * calling processor, 0 if they are not
2655      */
2656     int
2657     _elscuart_poll( l1sc_t *sc )
2658     {
2659         int result;
2660     
2661         if( sc->cons_listen ) {
2662             result = l1_cons_poll( sc );
2663             if( result )
2664                 return result;
2665         }
2666     
2667         return sc_poll( sc, L1_ELSCUART_SUBCH(get_myid()) );
2668     }
2669     
2670     
2671     
2672     /* _elscuart_readc is to be used only when _elscuart_poll has
2673      * indicated that a character is waiting.  Pulls a character
2674      * of this processor's console queue and returns it.
2675      *
2676      */
2677     int
2678     _elscuart_readc( l1sc_t *sc )
2679     {
2680         int c;
2681         sc_cq_t *q;
2682         brl1_sch_t *subch;
2683     
2684         if( sc->cons_listen ) {
2685     	subch = &(sc->subch[ SC_CONS_SYSTEM ]);
2686     	q = subch->iqp;
2687     	
2688     	SUBCH_DATA_LOCK( subch );
2689             if( !cq_empty( q ) ) {
2690                 cq_rem( q, c );
2691     	    if( cq_empty( q ) ) {
2692     		atomic_set(&subch->packet_arrived, 0);
2693     	    }
2694     	    SUBCH_DATA_UNLOCK( subch );
2695                 return c;
2696             }
2697     	SUBCH_DATA_UNLOCK( subch );
2698         }
2699     
2700         subch = &(sc->subch[ L1_ELSCUART_SUBCH(get_myid()) ]);
2701         q = subch->iqp;
2702     
2703         SUBCH_DATA_LOCK( subch );
2704         if( cq_empty( q ) ) {
2705     	SUBCH_DATA_UNLOCK( subch );
2706             return -1;
2707         }
2708     
2709         cq_rem( q, c );
2710         if( cq_empty ( q ) ) {
2711     	atomic_set(&subch->packet_arrived, 0);
2712         }
2713         SUBCH_DATA_UNLOCK( subch );
2714     
2715         return c;
2716     }
2717     
2718     
2719     /*
2720      * _elscuart_flush flushes queued output to the L1.
2721      * This routine blocks until the queue is flushed.
2722      */
2723     int
2724     _elscuart_flush( l1sc_t *sc )
2725     {
2726         int r, n;
2727         char buf[BRL1_QSIZE];
2728         sc_cq_t *q = &(sc->oq[ MAP_OQ(L1_ELSCUART_SUBCH(get_myid())) ]);
2729     
2730         while( (n = cq_used(q)) ) {
2731     
2732             /* buffer queue contents */
2733             r = BRL1_QSIZE - q->opos;
2734     
2735             if( n > r ) {
2736                 BCOPY( q->buf + q->opos, buf, r  );
2737                 BCOPY( q->buf, buf + r, n - r  );
2738             } else {
2739                 BCOPY( q->buf + q->opos, buf, n  );
2740             }
2741     
2742             /* attempt to send buffer contents */
2743             r = brl1_send( sc, buf, cq_used( q ), 
2744     		       (BRL1_EVENT | L1_ELSCUART_SUBCH(get_myid())), 1 );
2745     
2746             /* if no error, dequeue the sent characters; otherwise,
2747              * return the error
2748              */
2749             if( r >= SC_SUCCESS ) {
2750                 q->opos = (q->opos + r) % BRL1_QSIZE;
2751             }
2752             else {
2753                 return r;
2754             }
2755         }
2756     
2757         return 0;
2758     }
2759     
2760     
2761     
2762     /* _elscuart_probe returns non-zero if the L1 (and
2763      * consequently the elscuart) can be accessed
2764      */
2765     int
2766     _elscuart_probe( l1sc_t *sc )
2767     {
2768     #ifndef CONFIG_SERIAL_SGI_L1_PROTOCOL
2769         return 0;
2770     #else
2771         char ver[BRL1_QSIZE];
2772         extern int elsc_version( l1sc_t *, char * );
2773     
2774         if ( IS_RUNNING_ON_SIMULATOR() )
2775         	return 0;
2776         return( elsc_version(sc, ver) >= 0 );
2777     #endif /* CONFIG_SERIAL_SGI_L1_PROTOCOL */
2778     }
2779     
2780     
2781     
2782     /* _elscuart_init zeroes out the l1sc_t console
2783      * queues for this processor's console subchannel.
2784      */
2785     void
2786     _elscuart_init( l1sc_t *sc )
2787     {
2788         brl1_sch_t *subch = &sc->subch[L1_ELSCUART_SUBCH(get_myid())];
2789     
2790         SUBCH_DATA_LOCK(subch);
2791     
2792         atomic_set(&subch->packet_arrived, 0);
2793         cq_init( subch->iqp );
2794         cq_init( &sc->oq[MAP_OQ(L1_ELSCUART_SUBCH(get_myid()))] );
2795     
2796         SUBCH_DATA_UNLOCK(subch);
2797     }
2798