patch-2.4.22 linux-2.4.22/arch/ia64/sn/io/sn1/l1_command.c
Next file: linux-2.4.22/arch/ia64/sn/io/sn1/mem_refcnt.c
Previous file: linux-2.4.22/arch/ia64/sn/io/sn1/l1.c
Back to the patch index
Back to the overall index
- Lines: 1410
- Date:
1969-12-31 16:00:00.000000000 -0800
- Orig file:
linux-2.4.21/arch/ia64/sn/io/sn1/l1_command.c
- Orig date:
2003-06-13 07:51:30.000000000 -0700
diff -urN linux-2.4.21/arch/ia64/sn/io/sn1/l1_command.c linux-2.4.22/arch/ia64/sn/io/sn1/l1_command.c
@@ -1,1409 +0,0 @@
-/* $Id: l1_command.c,v 1.2 2002/11/21 17:51:57 jh Exp $
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 1992-1997,2000-2002 Silicon Graphics, Inc. All rights reserved.
- */
-
-#include <linux/types.h>
-#include <linux/slab.h>
-#include <asm/sn/sgi.h>
-#include <asm/sn/io.h>
-#include <asm/sn/iograph.h>
-#include <asm/sn/invent.h>
-#include <asm/sn/hcl.h>
-#include <asm/sn/hcl_util.h>
-#include <asm/sn/labelcl.h>
-#include <asm/sn/eeprom.h>
-#include <asm/sn/router.h>
-#include <asm/sn/module.h>
-#include <asm/sn/ksys/l1.h>
-#include <asm/sn/nodepda.h>
-#include <asm/sn/clksupport.h>
-#include <asm/sn/sn_cpuid.h>
-
-#define ELSC_TIMEOUT 1000000 /* ELSC response timeout (usec) */
-#define LOCK_TIMEOUT 5000000 /* Hub lock timeout (usec) */
-
-#define LD(x) (*(volatile uint64_t *)(x))
-#define SD(x, v) (LD(x) = (uint64_t) (v))
-
-#define hub_cpu_get() 0
-
-#define LBYTE(caddr) (*(char *) caddr)
-
-extern char *bcopy(const char * src, char * dest, int count);
-
-#define LDEBUG 0
-
-/*
- * ELSC data is in NVRAM page 7 at the following offsets.
- */
-
-#define NVRAM_MAGIC_AD 0x700 /* magic number used for init */
-#define NVRAM_PASS_WD 0x701 /* password (4 bytes in length) */
-#define NVRAM_DBG1 0x705 /* virtual XOR debug switches */
-#define NVRAM_DBG2 0x706 /* physical XOR debug switches */
-#define NVRAM_CFG 0x707 /* ELSC Configuration info */
-#define NVRAM_MODULE 0x708 /* system module number */
-#define NVRAM_BIST_FLG 0x709 /* BIST flags (2 bits per nodeboard) */
-#define NVRAM_PARTITION 0x70a /* module's partition id */
-#define NVRAM_DOMAIN 0x70b /* module's domain id */
-#define NVRAM_CLUSTER 0x70c /* module's cluster id */
-#define NVRAM_CELL 0x70d /* module's cellid */
-
-#define NVRAM_MAGIC_NO 0x37 /* value of magic number */
-#define NVRAM_SIZE 16 /* 16 bytes in nvram */
-
-/*
- * Declare a static ELSC NVRAM buffer to hold all data read from
- * and written to NVRAM. This nvram "cache" will be used only during the
- * IP27prom execution.
- */
-static char elsc_nvram_buffer[NVRAM_SIZE];
-
-#define SC_COMMAND sc_command
-
-/*
- * elsc_init
- *
- * Initialize ELSC structure
- */
-
-void elsc_init(elsc_t *e, nasid_t nasid)
-{
- sc_init((l1sc_t *)e, nasid, BRL1_LOCALHUB_UART);
-}
-
-
-/*
- * elsc_errmsg
- *
- * Given a negative error code,
- * returns a corresponding static error string.
- */
-
-char *elsc_errmsg(int code)
-{
- switch (code) {
- case ELSC_ERROR_CMD_SEND:
- return "Command send error";
- case ELSC_ERROR_CMD_CHECKSUM:
- return "Command packet checksum error";
- case ELSC_ERROR_CMD_UNKNOWN:
- return "Unknown command";
- case ELSC_ERROR_CMD_ARGS:
- return "Invalid command argument(s)";
- case ELSC_ERROR_CMD_PERM:
- return "Permission denied";
- case ELSC_ERROR_RESP_TIMEOUT:
- return "System controller response timeout";
- case ELSC_ERROR_RESP_CHECKSUM:
- return "Response packet checksum error";
- case ELSC_ERROR_RESP_FORMAT:
- return "Response format error";
- case ELSC_ERROR_RESP_DIR:
- return "Response direction error";
- case ELSC_ERROR_MSG_LOST:
- return "Message lost because queue is full";
- case ELSC_ERROR_LOCK_TIMEOUT:
- return "Timed out getting ELSC lock";
- case ELSC_ERROR_DATA_SEND:
- return "Error sending data";
- case ELSC_ERROR_NIC:
- return "NIC protocol error";
- case ELSC_ERROR_NVMAGIC:
- return "Bad magic number in NVRAM";
- case ELSC_ERROR_MODULE:
- return "Module location protocol error";
- default:
- return "Unknown error";
- }
-}
-
-/*
- * elsc_nvram_init
- *
- * Initializes reads and writes to NVRAM. This will perform a single
- * read to NVRAM, getting all data at once. When the PROM tries to
- * read NVRAM, it returns the data from the buffer being read. If the
- * PROM tries to write out to NVRAM, the write is done, and the internal
- * buffer is updated.
- */
-
-void elsc_nvram_init(nasid_t nasid, uchar_t *elsc_nvram_data)
-{
- /* This might require implementation of multiple-packet request/responses
- * if it's to provide the same behavior that was available in SN0.
- */
- nasid = nasid;
- elsc_nvram_data = elsc_nvram_data;
-}
-
-/*
- * elsc_nvram_copy
- *
- * Copies the content of a buffer into the static buffer in this library.
- */
-
-void elsc_nvram_copy(uchar_t *elsc_nvram_data)
-{
- memcpy(elsc_nvram_buffer, elsc_nvram_data, NVRAM_SIZE);
-}
-
-/*
- * elsc_nvram_write
- *
- * Copies bytes from 'buf' into NVRAM, starting at NVRAM address
- * 'addr' which must be between 0 and 2047.
- *
- * If 'len' is non-negative, the routine copies 'len' bytes.
- *
- * If 'len' is negative, the routine treats the data as a string and
- * copies bytes up to and including a NUL-terminating zero, but not
- * to exceed '-len' bytes.
- */
-
-int elsc_nvram_write(elsc_t *e, int addr, char *buf, int len)
-{
- /* Here again, we might need to work out the details of a
- * multiple-packet protocol.
- */
-
- /* For now, pretend it worked. */
- e = e;
- addr = addr;
- buf = buf;
- return (len < 0 ? -len : len);
-}
-
-/*
- * elsc_nvram_read
- *
- * Copies bytes from NVRAM into 'buf', starting at NVRAM address
- * 'addr' which must be between 0 and 2047.
- *
- * If 'len' is non-negative, the routine copies 'len' bytes.
- *
- * If 'len' is negative, the routine treats the data as a string and
- * copies bytes up to and including a NUL-terminating zero, but not
- * to exceed '-len' bytes. NOTE: This method is no longer supported.
- * It was never used in the first place.
- */
-
-int elsc_nvram_read(elsc_t *e, int addr, char *buf, int len)
-{
- /* multiple packets? */
- e = e;
- addr = addr;
- buf = buf;
- len = len;
- return -1;
-}
-
-
-/*
- * Command Set
- */
-
-int elsc_version(elsc_t *e, char *result)
-{
- char msg[BRL1_QSIZE];
- int len; /* length of message being sent */
- int subch; /* system controller subchannel used */
- int major, /* major rev number */
- minor, /* minor rev number */
- bugfix; /* bugfix rev number */
-
- /* fill in msg with the opcode & params */
- bzero( msg, BRL1_QSIZE );
- subch = sc_open( (l1sc_t *)e, L1_ADDR_LOCAL );
-
- if( (len = sc_construct_msg( (l1sc_t *)e, subch, msg, BRL1_QSIZE,
- L1_ADDR_TASK_GENERAL,
- L1_REQ_FW_REV, 0 )) < 0 )
- {
- sc_close( e, subch );
- return( ELSC_ERROR_CMD_ARGS );
- }
-
- /* send the request to the L1 */
- if( SC_COMMAND( (l1sc_t *)e, subch, msg, msg, &len ) < 0 )
- {
- sc_close( e, subch );
- return( ELSC_ERROR_CMD_SEND );
- }
-
- /* free up subchannel */
- sc_close( (l1sc_t *)e, subch );
-
- /* check response */
- if( sc_interpret_resp( msg, 6, L1_ARG_INT, &major,
- L1_ARG_INT, &minor, L1_ARG_INT, &bugfix )
- < 0 )
- {
- return( ELSC_ERROR_RESP_FORMAT );
- }
-
- sprintf( result, "%d.%d.%d", major, minor, bugfix );
-
- return 0;
-}
-
-int elsc_debug_set(elsc_t *e, u_char byte1, u_char byte2)
-{
- /* shush compiler */
- e = e;
- byte1 = byte1;
- byte2 = byte2;
-
- /* fill in a buffer with the opcode & params; call sc_command */
-
- return 0;
-}
-
-int elsc_debug_get(elsc_t *e, u_char *byte1, u_char *byte2)
-{
- char msg[BRL1_QSIZE];
- int subch; /* system controller subchannel used */
- int dbg_sw; /* holds debug switch settings */
- int len; /* number of msg buffer bytes used */
-
- /* fill in msg with the opcode & params */
- bzero( msg, BRL1_QSIZE );
- if( (subch = sc_open( (l1sc_t *)e, L1_ADDR_LOCAL )) < 0 ) {
- return( ELSC_ERROR_CMD_SEND );
- }
-
- if( (len = sc_construct_msg( (l1sc_t *)e, subch, msg, BRL1_QSIZE,
- L1_ADDR_TASK_GENERAL,
- L1_REQ_RDBG, 0 ) ) < 0 )
- {
- sc_close( e, subch );
- return( ELSC_ERROR_CMD_ARGS );
- }
-
- /* send the request to the L1 */
- if( sc_command( (l1sc_t *)e, subch, msg, msg, &len ) < 0 )
- {
- sc_close( e, subch );
- return( ELSC_ERROR_CMD_SEND );
- }
-
- /* free up subchannel */
- sc_close( (l1sc_t *)e, subch );
-
- /* check response */
- if( sc_interpret_resp( msg, 2, L1_ARG_INT, &dbg_sw ) < 0 )
- {
- return( ELSC_ERROR_RESP_FORMAT );
- }
-
- /* copy out debug switch settings (last two bytes of the
- * integer response)
- */
- *byte1 = ((dbg_sw >> 8) & 0xFF);
- *byte2 = (dbg_sw & 0xFF);
-
- return 0;
-}
-
-
-/*
- * elsc_rack_bay_get fills in the two int * arguments with the
- * rack number and bay number of the L1 being addressed
- */
-int elsc_rack_bay_get(elsc_t *e, uint *rack, uint *bay)
-{
- char msg[BRL1_QSIZE]; /* L1 request/response info */
- int subch; /* system controller subchannel used */
- int len; /* length of message */
- uint32_t buf32; /* used to copy 32-bit rack/bay out of msg */
-
- /* fill in msg with the opcode & params */
- bzero( msg, BRL1_QSIZE );
- if( (subch = sc_open( (l1sc_t *)e, L1_ADDR_LOCAL )) < 0 ) {
- return( ELSC_ERROR_CMD_SEND );
- }
-
- if( (len = sc_construct_msg( (l1sc_t *)e, subch, msg, BRL1_QSIZE,
- L1_ADDR_TASK_GENERAL,
- L1_REQ_RRACK, 0 )) < 0 )
- {
- sc_close( e, subch );
- return( ELSC_ERROR_CMD_ARGS );
- }
-
-
- /* send the request to the L1 */
- if( sc_command( (l1sc_t *)e, subch, msg, msg, &len ) ) {
- sc_close( e, subch );
- return( ELSC_ERROR_CMD_SEND );
- }
-
- /* free up subchannel */
- sc_close(e, subch);
-
- /* check response */
- if( sc_interpret_resp( msg, 2, L1_ARG_INT, &buf32 ) < 0 )
- {
- return( ELSC_ERROR_RESP_FORMAT );
- }
-
- /* extract rack/bay info
- *
- * note that the 32-bit value returned by the L1 actually
- * only uses the low-order sixteen bits for rack and bay
- * information. A "normal" L1 address puts rack and bay
- * information in bit positions 12 through 28. So if
- * we initially shift the value returned 12 bits to the left,
- * we can use the L1 addressing #define's to extract the
- * values we need (see ksys/l1.h for a complete list of the
- * various fields of an L1 address).
- */
- buf32 <<= L1_ADDR_BAY_SHFT;
-
- *rack = (buf32 & L1_ADDR_RACK_MASK) >> L1_ADDR_RACK_SHFT;
- *bay = (buf32 & L1_ADDR_BAY_MASK) >> L1_ADDR_BAY_SHFT;
-
- return 0;
-}
-
-
-/* elsc_rack_bay_type_get fills in the three int * arguments with the
- * rack number, bay number and brick type of the L1 being addressed. Note
- * that if the L1 operation fails and this function returns an error value,
- * garbage may be written to brick_type.
- */
-int elsc_rack_bay_type_get( l1sc_t *sc, uint *rack,
- uint *bay, uint *brick_type )
-{
- char msg[BRL1_QSIZE]; /* L1 request/response info */
- int subch; /* system controller subchannel used */
- int len; /* length of message */
- uint32_t buf32; /* used to copy 32-bit rack & bay out of msg */
-
- /* fill in msg with the opcode & params */
- bzero( msg, BRL1_QSIZE );
- if( (subch = sc_open( sc, L1_ADDR_LOCAL )) < 0 ) {
- return ELSC_ERROR_CMD_SEND;
- }
-
- if( (len = sc_construct_msg( sc, subch, msg, BRL1_QSIZE,
- L1_ADDR_TASK_GENERAL,
- L1_REQ_RRBT, 0 )) < 0 )
- {
- sc_close( sc, subch );
- return( ELSC_ERROR_CMD_ARGS );
- }
-
- /* send the request to the L1 */
- if( SC_COMMAND( sc, subch, msg, msg, &len ) ) {
- sc_close( sc, subch );
- return( ELSC_ERROR_CMD_SEND );
- }
-
- /* free up subchannel */
- sc_close( sc, subch );
-
- /* check response */
- if( sc_interpret_resp( msg, 4, L1_ARG_INT, &buf32,
- L1_ARG_INT, brick_type ) < 0 )
- {
- return( ELSC_ERROR_RESP_FORMAT );
- }
-
- /* extract rack/bay info
- *
- * note that the 32-bit value returned by the L1 actually
- * only uses the low-order sixteen bits for rack and bay
- * information. A "normal" L1 address puts rack and bay
- * information in bit positions 12 through 28. So if
- * we initially shift the value returned 12 bits to the left,
- * we can use the L1 addressing #define's to extract the
- * values we need (see ksys/l1.h for a complete list of the
- * various fields of an L1 address).
- */
- buf32 <<= L1_ADDR_BAY_SHFT;
-
- *rack = (buf32 & L1_ADDR_RACK_MASK) >> L1_ADDR_RACK_SHFT;
- *bay = (buf32 & L1_ADDR_BAY_MASK) >> L1_ADDR_BAY_SHFT;
-
- /* convert brick_type to lower case */
- *brick_type = *brick_type - 'A' + 'a';
-
- return 0;
-}
-
-
-int elsc_module_get(elsc_t *e)
-{
- extern char brick_types[];
- uint rnum, rack, bay, bricktype, t;
- int ret;
-
- /* construct module ID from rack and slot info */
-
- if ((ret = elsc_rack_bay_type_get(e, &rnum, &bay, &bricktype)) < 0) {
- return ret;
- }
-
- /* report unset location info. with a special, otherwise invalid modid */
- if (rnum == 0 && bay == 0)
- return MODULE_NOT_SET;
-
- if (bay > MODULE_BPOS_MASK >> MODULE_BPOS_SHFT)
- return ELSC_ERROR_MODULE;
-
- /* Build a moduleid_t-compatible rack number */
-
- rack = 0;
- t = rnum / 100; /* rack class (CPU/IO) */
- if (t > RACK_CLASS_MASK(rack) >> RACK_CLASS_SHFT(rack))
- return ELSC_ERROR_MODULE;
- RACK_ADD_CLASS(rack, t);
- rnum %= 100;
-
- t = rnum / 10; /* rack group */
- if (t > RACK_GROUP_MASK(rack) >> RACK_GROUP_SHFT(rack))
- return ELSC_ERROR_MODULE;
- RACK_ADD_GROUP(rack, t);
-
- t = rnum % 10; /* rack number (one-based) */
- if (t-1 > RACK_NUM_MASK(rack) >> RACK_NUM_SHFT(rack))
- return ELSC_ERROR_MODULE;
- RACK_ADD_NUM(rack, t);
-
- for( t = 0; t < MAX_BRICK_TYPES; t++ ) {
- if( brick_types[t] == bricktype )
- return RBT_TO_MODULE(rack, bay, t);
- }
-
- return ELSC_ERROR_MODULE;
-}
-
-int elsc_partition_set(elsc_t *e, int partition)
-{
- char msg[BRL1_QSIZE]; /* L1 request/response info */
- int subch; /* system controller subchannel used */
- int len; /* length of message */
-
- /* fill in msg with the opcode & params */
- bzero( msg, BRL1_QSIZE );
- if( (subch = sc_open( e, L1_ADDR_LOCAL )) < 0 ) {
- return ELSC_ERROR_CMD_SEND;
- }
-
- if( (len = sc_construct_msg( e, subch, msg, BRL1_QSIZE,
- L1_ADDR_TASK_GENERAL,
- L1_REQ_PARTITION_SET, 2,
- L1_ARG_INT, partition )) < 0 )
- {
-
- sc_close( e, subch );
- return( ELSC_ERROR_CMD_ARGS );
- }
-
- /* send the request to the L1 */
- if( sc_command( e, subch, msg, msg, &len ) ) {
- sc_close( e, subch );
- return( ELSC_ERROR_CMD_SEND );
- }
-
- /* free up subchannel */
- sc_close( e, subch );
-
- /* check response */
- if( sc_interpret_resp( msg, 0 ) < 0 )
- {
- return( ELSC_ERROR_RESP_FORMAT );
- }
-
- return( 0 );
-}
-
-int elsc_partition_get(elsc_t *e)
-{
- char msg[BRL1_QSIZE]; /* L1 request/response info */
- int subch; /* system controller subchannel used */
- int len; /* length of message */
- uint32_t partition_id; /* used to copy partition id out of msg */
-
- /* fill in msg with the opcode & params */
- bzero( msg, BRL1_QSIZE );
- if( (subch = sc_open( e, L1_ADDR_LOCAL )) < 0 ) {
- return ELSC_ERROR_CMD_SEND;
- }
-
- if( (len = sc_construct_msg( e, subch, msg, BRL1_QSIZE,
- L1_ADDR_TASK_GENERAL,
- L1_REQ_PARTITION_GET, 0 )) < 0 )
-
- {
- sc_close( e, subch );
- return( ELSC_ERROR_CMD_ARGS );
- }
-
- /* send the request to the L1 */
- if( sc_command( e, subch, msg, msg, &len ) ) {
- sc_close( e, subch );
- return( ELSC_ERROR_CMD_SEND );
- }
-
- /* free up subchannel */
- sc_close( e, subch );
-
- /* check response */
- if( sc_interpret_resp( msg, 2, L1_ARG_INT, &partition_id ) < 0 )
- {
- return( ELSC_ERROR_RESP_FORMAT );
- }
-
- return( partition_id );
-}
-
-
-/*
- * elsc_cons_subch selects the "active" console subchannel for this node
- * (i.e., the one that will currently receive input)
- */
-int elsc_cons_subch(elsc_t *e, uint ch)
-{
- char msg[BRL1_QSIZE]; /* L1 request/response info */
- int subch; /* system controller subchannel used */
- int len; /* length of message */
-
- /* fill in msg with the opcode & params */
- bzero( msg, BRL1_QSIZE );
- subch = sc_open( e, L1_ADDR_LOCAL );
-
- if( (len = sc_construct_msg( e, subch, msg, BRL1_QSIZE,
- L1_ADDR_TASK_GENERAL,
- L1_REQ_CONS_SUBCH, 2,
- L1_ARG_INT, ch)) < 0 )
- {
- sc_close( e, subch );
- return( ELSC_ERROR_CMD_ARGS );
- }
-
- /* send the request to the L1 */
- if( SC_COMMAND( e, subch, msg, msg, &len ) ) {
- sc_close( e, subch );
- return( ELSC_ERROR_CMD_SEND );
- }
-
- /* free up subchannel */
- sc_close( e, subch );
-
- /* check response */
- if( sc_interpret_resp( msg, 0 ) < 0 )
- {
- return( ELSC_ERROR_RESP_FORMAT );
- }
-
- return 0;
-}
-
-
-/*
- * elsc_cons_node should only be executed by one node. It declares to
- * the system controller that the node from which it is called will be
- * the owner of the system console.
- */
-int elsc_cons_node(elsc_t *e)
-{
- char msg[BRL1_QSIZE]; /* L1 request/response info */
- int subch; /* system controller subchannel used */
- int len; /* length of message */
-
- /* fill in msg with the opcode & params */
- bzero( msg, BRL1_QSIZE );
- subch = sc_open( e, L1_ADDR_LOCAL );
-
- if( (len = sc_construct_msg( e, subch, msg, BRL1_QSIZE,
- L1_ADDR_TASK_GENERAL,
- L1_REQ_CONS_NODE, 0 )) < 0 )
- {
- sc_close( e, subch );
- return( ELSC_ERROR_CMD_ARGS );
- }
-
- /* send the request to the L1 */
- if( SC_COMMAND( e, subch, msg, msg, &len ) ) {
- sc_close( e, subch );
- return( ELSC_ERROR_CMD_SEND );
- }
-
- /* free up subchannel */
- sc_close( e, subch );
-
- /* check response */
- if( sc_interpret_resp( msg, 0 ) < 0 )
- {
- return( ELSC_ERROR_RESP_FORMAT );
- }
-
- return 0;
-}
-
-
-/* elsc_display_line writes up to 12 characters to either the top or bottom
- * line of the L1 display. line points to a buffer containing the message
- * to be displayed. The zero-based line number is specified by lnum (so
- * lnum == 0 specifies the top line and lnum == 1 specifies the bottom).
- * Lines longer than 12 characters, or line numbers not less than
- * L1_DISPLAY_LINES, cause elsc_display_line to return an error.
- */
-int elsc_display_line(elsc_t *e, char *line, int lnum)
-{
- char msg[BRL1_QSIZE];
- int subch; /* system controller subchannel used */
- int len; /* number of msg buffer bytes used */
-
- /* argument sanity checking */
- if( !(lnum < L1_DISPLAY_LINES) )
- return( ELSC_ERROR_CMD_ARGS );
- if( !(strlen( line ) <= L1_DISPLAY_LINE_LENGTH) )
- return( ELSC_ERROR_CMD_ARGS );
-
- /* fill in msg with the opcode & params */
- bzero( msg, BRL1_QSIZE );
- subch = sc_open( (l1sc_t *)e, L1_ADDR_LOCAL );
-
- if( (len = sc_construct_msg( (l1sc_t *)e, subch, msg, BRL1_QSIZE,
- L1_ADDR_TASK_GENERAL,
- (L1_REQ_DISP1+lnum), 2,
- L1_ARG_ASCII, line )) < 0 )
- {
- sc_close( e, subch );
- return( ELSC_ERROR_CMD_ARGS );
- }
-
- /* send the request to the L1 */
- if( SC_COMMAND( (l1sc_t *)e, subch, msg, msg, &len ) < 0 )
- {
- sc_close( e, subch );
- return( ELSC_ERROR_CMD_SEND );
- }
-
- /* free up subchannel */
- sc_close( (l1sc_t *)e, subch );
-
- /* check response */
- if( sc_interpret_resp( msg, 0 ) < 0 )
- {
- return( ELSC_ERROR_RESP_FORMAT );
- }
-
- return 0;
-}
-
-
-/* elsc_display_mesg silently drops message characters beyond the 12th.
- */
-int elsc_display_mesg(elsc_t *e, char *chr)
-{
-
- char line[L1_DISPLAY_LINE_LENGTH+1];
- int numlines, i;
- int result;
-
- numlines = (strlen( chr ) + L1_DISPLAY_LINE_LENGTH - 1) /
- L1_DISPLAY_LINE_LENGTH;
-
- if( numlines > L1_DISPLAY_LINES )
- numlines = L1_DISPLAY_LINES;
-
- for( i = 0; i < numlines; i++ )
- {
- strncpy( line, chr, L1_DISPLAY_LINE_LENGTH );
- line[L1_DISPLAY_LINE_LENGTH] = '\0';
-
- /* generally we want to leave the first line of the L1 display
- * alone (so the L1 can manipulate it). If you need to be able
- * to display to both lines (for debugging purposes), define
- * L1_DISP_2LINES in irix/kern/ksys/l1.h, or add -DL1_DISP_2LINES
- * to your 'defs file.
- */
-#if defined(L1_DISP_2LINES)
- if( (result = elsc_display_line( e, line, i )) < 0 )
-#else
- if( (result = elsc_display_line( e, line, i+1 )) < 0 )
-#endif
-
- return result;
-
- chr += L1_DISPLAY_LINE_LENGTH;
- }
-
- return 0;
-}
-
-
-int elsc_password_set(elsc_t *e, char *password)
-{
- /* shush compiler */
- e = e;
- password = password;
-
- /* fill in buffer with the opcode & params; call elsc_command */
-
- return 0;
-}
-
-int elsc_password_get(elsc_t *e, char *password)
-{
- /* shush compiler */
- e = e;
- password = password;
-
- /* fill in buffer with the opcode & params; call elsc_command */
-
- return 0;
-}
-
-
-/*
- * sc_portspeed_get
- *
- * retrieve the current portspeed setting for the bedrock II
- */
-int sc_portspeed_get(l1sc_t *sc)
-{
- char msg[BRL1_QSIZE];
- int len; /* length of message being sent */
- int subch; /* system controller subchannel used */
- int portspeed_a, portspeed_b;
- /* ioport clock rates */
-
- bzero( msg, BRL1_QSIZE );
- subch = sc_open( sc, L1_ADDR_LOCAL );
-
- if( (len = sc_construct_msg( sc, subch, msg, BRL1_QSIZE,
- L1_ADDR_TASK_GENERAL,
- L1_REQ_PORTSPEED,
- 0 )) < 0 )
- {
- sc_close( sc, subch );
- return( ELSC_ERROR_CMD_ARGS );
- }
-
- /* send the request to the L1 */
- if( sc_command( sc, subch, msg, msg, &len ) < 0 )
- {
- sc_close( sc, subch );
- return( ELSC_ERROR_CMD_SEND );
- }
-
- /* free up subchannel */
- sc_close( sc, subch );
-
- /* check response */
- if( sc_interpret_resp( msg, 4,
- L1_ARG_INT, &portspeed_a,
- L1_ARG_INT, &portspeed_b ) < 0 )
- {
- return( ELSC_ERROR_RESP_FORMAT );
- }
-
- /* for the c-brick, we ignore the portspeed_b value */
- return (portspeed_a ? 600 : 400);
-}
-
-/*
- * elsc_power_query
- *
- * To be used after system reset, this command returns 1 if the reset
- * was the result of a power-on, 0 otherwise.
- *
- * The power query status is cleared to 0 after it is read.
- */
-
-int elsc_power_query(elsc_t *e)
-{
- e = e; /* shush the compiler */
-
- /* fill in buffer with the opcode & params; call elsc_command */
-
- return 1;
-}
-
-int elsc_rpwr_query(elsc_t *e, int is_master)
-{
- /* shush the compiler */
- e = e;
- is_master = is_master;
-
- /* fill in buffer with the opcode & params; call elsc_command */
-
- return 0;
-}
-
-/*
- * elsc_power_down
- *
- * Sets up system to shut down in "sec" seconds (or modifies the
- * shutdown time if one is already in effect). Use 0 to power
- * down immediately.
- */
-
-int elsc_power_down(elsc_t *e, int sec)
-{
- /* shush compiler */
- e = e;
- sec = sec;
-
- /* fill in buffer with the opcode & params; call elsc_command */
-
- return 0;
-}
-
-
-int elsc_system_reset(elsc_t *e)
-{
- char msg[BRL1_QSIZE];
- int subch; /* system controller subchannel used */
- int len; /* number of msg buffer bytes used */
- int result;
-
- /* fill in msg with the opcode & params */
- bzero( msg, BRL1_QSIZE );
- if( (subch = sc_open( e, L1_ADDR_LOCAL )) < 0 ) {
- return ELSC_ERROR_CMD_SEND;
- }
-
- if( (len = sc_construct_msg( e, subch, msg, BRL1_QSIZE,
- L1_ADDR_TASK_GENERAL,
- L1_REQ_RESET, 0 )) < 0 )
- {
- sc_close( e, subch );
- return( ELSC_ERROR_CMD_ARGS );
- }
-
- /* send the request to the L1 */
- if( (result = sc_command( e, subch, msg, msg, &len )) ) {
- sc_close( e, subch );
- if( result == SC_NMSG ) {
- /* timeout is OK. We've sent the reset. Now it's just
- * a matter of time...
- */
- return( 0 );
- }
- return( ELSC_ERROR_CMD_SEND );
- }
-
- /* free up subchannel */
- sc_close( e, subch );
-
- /* check response */
- if( sc_interpret_resp( msg, 0 ) < 0 )
- {
- return( ELSC_ERROR_RESP_FORMAT );
- }
-
- return 0;
-}
-
-
-int elsc_power_cycle(elsc_t *e)
-{
- /* shush compiler */
- e = e;
-
- /* fill in buffer with the opcode & params; call sc_command */
-
- return 0;
-}
-
-
-int _elsc_hbt(elsc_t *e, int ival, int rdly)
-{
- e = e;
- ival = ival;
- rdly = rdly;
-
- /* fill in buffer with the opcode & params; call elsc_command */
-
- return 0;
-}
-
-
-/* send a command string to an L1 */
-int sc_command_interp( l1sc_t *sc, l1addr_t compt, l1addr_t rack, l1addr_t bay,
- char *cmd )
-{
- char msg[BRL1_QSIZE];
- int len; /* length of message being sent */
- int subch; /* system controller subchannel used */
- l1addr_t target; /* target system controller for command */
-
- /* fill in msg with the opcode & params */
- bzero( msg, BRL1_QSIZE );
-
- L1_BUILD_ADDR( &target, compt, rack, bay, 0 );
- subch = sc_open( sc, target );
-
- if( (len = sc_construct_msg( sc, subch, msg, BRL1_QSIZE,
- L1_ADDR_TASK_CMD, L1_REQ_EXEC_CMD, 2,
- L1_ARG_ASCII, cmd )) < 0 )
- {
- sc_close( sc, subch );
- return( ELSC_ERROR_CMD_ARGS );
- }
-
- /* send the request to the L1 */
- if( SC_COMMAND( sc, subch, msg, msg, &len ) < 0 )
- {
- sc_close( sc, subch );
- return( ELSC_ERROR_CMD_SEND );
- }
-
- /* free up subchannel */
- sc_close( sc, subch );
-
- /* check response */
- if( sc_interpret_resp( msg, 0 ) < 0 )
- {
- return( ELSC_ERROR_RESP_FORMAT );
- }
-
- return 0;
-}
-
-/*
- * sc_power_down
- *
- * Shuts down the c-brick associated with sc, and any attached I/O bricks
- * or other c-bricks (won't go through r-bricks).
- */
-
-int sc_power_down(l1sc_t *sc)
-{
- return sc_command_interp( sc, L1_ADDR_TYPE_L1, L1_ADDR_RACK_LOCAL,
- L1_ADDR_BAY_LOCAL, "* pwr d" );
-}
-
-
-/*
- * sc_power_down_all
- *
- * Works similarly to sc_power_down, except that the request is sent to the
- * closest L2 and EVERYBODY gets turned off.
- */
-
-int sc_power_down_all(l1sc_t *sc)
-{
- if( nodepda->num_routers > 0 ) {
- return sc_command_interp( sc, L1_ADDR_TYPE_L2, L1_ADDR_RACK_LOCAL,
- L1_ADDR_BAY_LOCAL, "* pwr d" );
- }
- else {
- return sc_power_down( sc );
- }
-}
-
-
-/*
- * iobrick routines
- */
-
-/* iobrick_rack_bay_type_get fills in the three int * arguments with the
- * rack number, bay number and brick type of the L1 being addressed. Note
- * that if the L1 operation fails and this function returns an error value,
- * garbage may be written to brick_type.
- */
-int iobrick_rack_bay_type_get( l1sc_t *sc, uint *rack,
- uint *bay, uint *brick_type )
-{
- char msg[BRL1_QSIZE]; /* L1 request/response info */
- int subch; /* system controller subchannel used */
- int len; /* length of message */
- uint32_t buf32; /* used to copy 32-bit rack & bay out of msg */
-
- /* fill in msg with the opcode & params */
- bzero( msg, BRL1_QSIZE );
- if( (subch = sc_open( sc, L1_ADDR_LOCALIO )) < 0 ) {
- return( ELSC_ERROR_CMD_SEND );
- }
-
- if( (len = sc_construct_msg( sc, subch, msg, BRL1_QSIZE,
- L1_ADDR_TASK_GENERAL,
- L1_REQ_RRBT, 0 )) < 0 )
- {
- sc_close( sc, subch );
- return( ELSC_ERROR_CMD_ARGS );
- }
-
- /* send the request to the L1 */
- if( sc_command( sc, subch, msg, msg, &len ) ) {
- sc_close( sc, subch );
- return( ELSC_ERROR_CMD_SEND );
- }
-
- /* free up subchannel */
- sc_close( sc, subch );
-
- /* check response */
- if( sc_interpret_resp( msg, 4, L1_ARG_INT, &buf32,
- L1_ARG_INT, brick_type ) < 0 )
- {
- return( ELSC_ERROR_RESP_FORMAT );
- }
-
- /* extract rack/bay info
- *
- * note that the 32-bit value returned by the L1 actually
- * only uses the low-order sixteen bits for rack and bay
- * information. A "normal" L1 address puts rack and bay
- * information in bit positions 12 through 28. So if
- * we initially shift the value returned 12 bits to the left,
- * we can use the L1 addressing #define's to extract the
- * values we need (see ksys/l1.h for a complete list of the
- * various fields of an L1 address).
- */
- buf32 <<= L1_ADDR_BAY_SHFT;
-
- *rack = (buf32 & L1_ADDR_RACK_MASK) >> L1_ADDR_RACK_SHFT;
- *bay = (buf32 & L1_ADDR_BAY_MASK) >> L1_ADDR_BAY_SHFT;
-
- return 0;
-}
-
-
-int iobrick_module_get(l1sc_t *sc)
-{
- uint rnum, rack, bay, brick_type, t;
- int ret;
-
- /* construct module ID from rack and slot info */
-
- if ((ret = iobrick_rack_bay_type_get(sc, &rnum, &bay, &brick_type)) < 0)
- return ret;
-
- if (bay > MODULE_BPOS_MASK >> MODULE_BPOS_SHFT)
- return ELSC_ERROR_MODULE;
-
- /* Build a moduleid_t-compatible rack number */
-
- rack = 0;
- t = rnum / 100; /* rack class (CPU/IO) */
- if (t > RACK_CLASS_MASK(rack) >> RACK_CLASS_SHFT(rack))
- return ELSC_ERROR_MODULE;
- RACK_ADD_CLASS(rack, t);
- rnum %= 100;
-
- t = rnum / 10; /* rack group */
- if (t > RACK_GROUP_MASK(rack) >> RACK_GROUP_SHFT(rack))
- return ELSC_ERROR_MODULE;
- RACK_ADD_GROUP(rack, t);
-
- t = rnum % 10; /* rack number (one-based) */
- if (t-1 > RACK_NUM_MASK(rack) >> RACK_NUM_SHFT(rack))
- return ELSC_ERROR_MODULE;
- RACK_ADD_NUM(rack, t);
-
- switch( brick_type ) {
- case 'I':
- brick_type = MODULE_IBRICK; break;
- case 'P':
- brick_type = MODULE_PBRICK; break;
- case 'X':
- brick_type = MODULE_XBRICK; break;
- }
-
- ret = RBT_TO_MODULE(rack, bay, brick_type);
-
- return ret;
-}
-
-/*
- * iobrick_module_get_nasid() returns a module_id which has the brick
- * type encoded in bits 15-12, but this is not the true brick type...
- * The module_id returned by iobrick_module_get_nasid() is modified
- * to make a PEBRICKs & PXBRICKs look like a PBRICK. So this routine
- * iobrick_type_get_nasid() returns the true unmodified brick type.
- */
-int
-iobrick_type_get_nasid(nasid_t nasid)
-{
- l1sc_t *sc = get_elsc();
- elsc_t tmp_sc;
- uint rack, bay, type;
- int t, ret;
-
-#ifdef PIC_LATER
- if (PEBRICK_NODE(nasid)) {
- if (peer_iobrick_rack_bay_get(nasid, &rack, &bay)) {
- printf("Could not read rack and bay location "
- "of PEBrick at nasid %d\n", nasid);
- }
- if ((ret = peer_iobrick_type_get(sc, rack, bay, &type)) < 0)
- return ret;
- }
- else
-#endif /* PIC_LATER */
- if (nasid != get_nasid()) { /* get the io_moduleid from remote node */
- elsc_init(&tmp_sc, nasid);
- if ((ret = iobrick_rack_bay_type_get(&tmp_sc, &rack, &bay, &type)) < 0)
- return ret;
- }
- else {
- if ((ret = iobrick_rack_bay_type_get(sc, &rack, &bay, &type)) < 0)
- return ret;
- }
-
- /*
- * Some brick_types need special treatment. NOTE: This switch is
- * duplicated in iobrick_module_get(), so if you change this switch
- * you must also change it there.
- */
- switch (type)
- {
- case L1_BRICKTYPE_IP45:
- /* treat speedo2 like Ibrick for moduleid purposes */
- type = L1_BRICKTYPE_I;
- break;
- case L1_BRICKTYPE_X2:
- /* give X2 bricks the same moduleid as earlier models */
- type = L1_BRICKTYPE_X;
- break;
- }
-
- /* convert brick_type to lower case */
- if ((type >= 'A') && (type <= 'Z'))
- type = type - 'A' + 'a';
-
- /* convert to a module.h brick type */
- for( t = 0; t < MAX_BRICK_TYPES; t++ ) {
- if( brick_types[t] == type )
- return t;
- }
-
- return -1; /* unknown brick */
-}
-
-int iobrick_module_get_nasid(nasid_t nasid)
-{
- int io_moduleid;
- l1sc_t *sc = get_elsc();
- elsc_t tmp_sc;
-
-#ifdef PIC_LATER
- uint rack, bay;
-
- if (PEBRICK_NODE(nasid)) {
- if (peer_iobrick_rack_bay_get(nasid, &rack, &bay)) {
- printf("Could not read rack and bay location "
- "of PEBrick at nasid %d\n", nasid);
- }
-
- io_moduleid = peer_iobrick_module_get(sc, rack, bay);
- }
- else
-#endif /* PIC_LATER */
- if (nasid != get_nasid()) { /* get the io_moduleid from remote node */
- elsc_init(&tmp_sc, nasid);
-
- io_moduleid = iobrick_module_get(&tmp_sc);
- }
- else {
- io_moduleid = iobrick_module_get(sc);
- }
-
- return io_moduleid;
-}
-
-
-/* iobrick_get_sys_snum asks the attached iobrick for the system
- * serial number. This function will only be relevant to the master
- * cbrick (the one attached to the bootmaster ibrick); other nodes
- * may call the function, but the value returned to the master node
- * will be the one used as the system serial number by the kernel.
- */
-
-int
-iobrick_get_sys_snum( l1sc_t *sc, char *snum_str )
-{
- char msg[BRL1_QSIZE]; /* L1 request/response info */
- int subch; /* system controller subchannel used */
- int len; /* length of message */
-
- /* fill in msg with the opcode & params */
- bzero( msg, BRL1_QSIZE );
- if( (subch = sc_open( sc, L1_ADDR_LOCALIO )) < 0 ) {
- return( ELSC_ERROR_CMD_SEND );
- }
-
- if( (len = sc_construct_msg( sc, subch, msg, BRL1_QSIZE,
- L1_ADDR_TASK_GENERAL,
- L1_REQ_SYS_SERIAL, 0 )) < 0 )
- {
- sc_close( sc, subch );
- return( ELSC_ERROR_CMD_ARGS );
- }
-
- /* send the request to the L1 */
- if( sc_command( sc, subch, msg, msg, &len ) ) {
- sc_close( sc, subch );
- return( ELSC_ERROR_CMD_SEND );
- }
-
- /* free up subchannel */
- sc_close( sc, subch );
-
- /* check response */
- return( sc_interpret_resp( msg, 2, L1_ARG_ASCII, snum_str ) );
-}
-
-
-/*
- * The following functions apply (or cut off) power to the specified
- * pci bus or slot.
- */
-
-int
-iobrick_pci_pwr( l1sc_t *sc, int bus, int slot, int req_code )
-{
-#if 0 /* The "bedrock request" method of performing this function
- * seems to be broken in the L1, so for now use the command-
- * interpreter method
- */
-
- char msg[BRL1_QSIZE];
- int len; /* length of message being sent */
- int subch; /* system controller subchannel used */
-
- /* fill in msg with the opcode & params */
- bzero( msg, BRL1_QSIZE );
- subch = sc_open( sc, L1_ADDR_LOCALIO );
-
- if( (len = sc_construct_msg( sc, subch, msg, BRL1_QSIZE,
- L1_ADDR_TASK_GENERAL,
- req_code, 4,
- L1_ARG_INT, bus,
- L1_ARG_INT, slot )) < 0 )
- {
- sc_close( sc, subch );
- return( ELSC_ERROR_CMD_ARGS );
- }
-
- /* send the request to the L1 */
- if( SC_COMMAND(sc, subch, msg, msg, &len ) < 0 )
- {
- sc_close( sc, subch );
- return( ELSC_ERROR_CMD_SEND );
- }
-
- /* free up subchannel */
- sc_close( sc, subch );
-
- /* check response */
- if( sc_interpret_resp( msg, 0 ) < 0 )
- {
- return( ELSC_ERROR_RESP_FORMAT );
- }
-
- return 0;
-
-#else
- char cmd[64];
- char *fxn;
-
- switch( req_code )
- {
- case L1_REQ_PCI_UP:
- fxn = "u";
- break;
- case L1_REQ_PCI_DOWN:
- fxn = "d";
- break;
- case L1_REQ_PCI_RESET:
- fxn = "rst";
- break;
- default:
- return( ELSC_ERROR_CMD_ARGS );
- }
-
- if( slot == -1 )
- sprintf( cmd, "pci %d %s", bus, fxn );
- else
- sprintf( cmd, "pci %d %d %s", bus, slot, fxn );
-
- return sc_command_interp( sc, L1_ADDR_TYPE_IOBRICK,
- L1_ADDR_RACK_LOCAL, L1_ADDR_BAY_LOCAL, cmd );
-#endif
-}
-
-int
-iobrick_pci_slot_pwr( l1sc_t *sc, int bus, int slot, int up )
-{
- return iobrick_pci_pwr( sc, bus, slot, up );
-}
-
-int
-iobrick_pci_bus_pwr( l1sc_t *sc, int bus, int up )
-{
- return iobrick_pci_pwr( sc, bus, -1, up );
-}
-
-
-int
-iobrick_pci_slot_rst( l1sc_t *sc, int bus, int slot )
-{
- return iobrick_pci_pwr( sc, bus, slot, L1_REQ_PCI_RESET );
-}
-
-int
-iobrick_pci_bus_rst( l1sc_t *sc, int bus )
-{
- return iobrick_pci_pwr( sc, bus, -1, L1_REQ_PCI_RESET );
-}
-
-
-/* get the L1 firmware version for an iobrick */
-int
-iobrick_sc_version( l1sc_t *sc, char *result )
-{
- char msg[BRL1_QSIZE];
- int len; /* length of message being sent */
- int subch; /* system controller subchannel used */
- int major, /* major rev number */
- minor, /* minor rev number */
- bugfix; /* bugfix rev number */
-
- /* fill in msg with the opcode & params */
- bzero( msg, BRL1_QSIZE );
- subch = sc_open( sc, L1_ADDR_LOCALIO );
-
- if( (len = sc_construct_msg( sc, subch, msg, BRL1_QSIZE,
- L1_ADDR_TASK_GENERAL,
- L1_REQ_FW_REV, 0 )) < 0 )
- {
- sc_close( sc, subch );
- return( ELSC_ERROR_CMD_ARGS );
- }
-
- /* send the request to the L1 */
- if( SC_COMMAND(sc, subch, msg, msg, &len ) < 0 )
- {
- sc_close( sc, subch );
- return( ELSC_ERROR_CMD_SEND );
- }
-
- /* free up subchannel */
- sc_close( sc, subch );
-
- /* check response */
- if( sc_interpret_resp( msg, 6, L1_ARG_INT, &major,
- L1_ARG_INT, &minor, L1_ARG_INT, &bugfix )
- < 0 )
- {
- return( ELSC_ERROR_RESP_FORMAT );
- }
-
- sprintf( result, "%d.%d.%d", major, minor, bugfix );
-
- return 0;
-}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)