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, ®val );
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, ®val );
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, ®val );
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, ®val );
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