l1.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:71k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

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