diff options
Diffstat (limited to 'arch/ia64/sn/io/l1_command.c')
-rw-r--r-- | arch/ia64/sn/io/l1_command.c | 1378 |
1 files changed, 0 insertions, 1378 deletions
diff --git a/arch/ia64/sn/io/l1_command.c b/arch/ia64/sn/io/l1_command.c deleted file mode 100644 index 3da21f1d7da233..00000000000000 --- a/arch/ia64/sn/io/l1_command.c +++ /dev/null @@ -1,1378 +0,0 @@ -/* $Id$ - * - * 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 - 2001 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> - -#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; -} - - -/* - * L1 Support for reading - * cbrick uid. - */ - -int elsc_nic_get(elsc_t *e, uint64_t *nic, int verbose) -{ - /* this parameter included only for SN0 compatibility */ - verbose = verbose; - - /* We don't go straight to the bedrock/L1 protocol on this one, but let - * the eeprom layer prepare the eeprom data as we would like it to - * appear to the caller - */ - return cbrick_uid_get( e->nasid, nic ); -} - - -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 ); - } -} - - -/* - * Routines for reading the R-brick's L1 - */ - -int router_module_get( nasid_t nasid, net_vec_t path ) -{ - uint rnum, rack, bay, t; - int ret; - l1sc_t sc; - - /* prepare l1sc_t struct */ - sc_init( &sc, nasid, path ); - - /* construct module ID from rack and slot info */ - - if ((ret = elsc_rack_bay_get(&sc, &rnum, &bay)) < 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); - - ret = RBT_TO_MODULE(rack, bay, MODULE_RBRICK); - return ret; -} - - -/* - * 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_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; -} |