📄 eeprom.c
字号:
/* fill in msg with the opcode & params */ BZERO( msg, BRL1_QSIZE ); if( (subch = sc_open( &sc, L1_ADDR_LOCAL )) < 0 ) { ROUTER_UNLOCK(path); FAIL; } if( (len = sc_construct_msg( &sc, subch, msg, BRL1_QSIZE, L1_ADDR_TASK_GENERAL, L1_REQ_SER_NUM, 0 )) < 0 ) { ROUTER_UNLOCK(path); sc_close( &sc, subch ); FAIL; } /* send the request to the L1 */ if( sc_command( &sc, subch, msg, msg, &len ) ) { ROUTER_UNLOCK(path); sc_close( &sc, subch ); FAIL; } /* free up subchannel */ ROUTER_UNLOCK(path); sc_close(&sc, subch); /* check response */ if( sc_interpret_resp( msg, 2, L1_ARG_ASCII, uid_str ) < 0 ) { FAIL; } *uid = generate_unique_id( uid_str, strlen( uid_str ) ); return EEP_OK;#endif /* CONFIG_SERIAL_SGI_L1_PROTOCOL */}int iobrick_uid_get( nasid_t nasid, uint64_t *uid ){ eeprom_brd_record_t eep; eeprom_board_ia_t board; eeprom_chassis_ia_t chassis; int r; eep.board_ia = &board; eep.chassis_ia = &chassis; eep.spd = NULL; r = iobrick_eeprom_read( &eep, nasid, IO_BRICK ); if( r != EEP_OK ) { *uid = rtc_time(); return r; } *uid = generate_unique_id( board.serial_num, board.serial_num_tl & FIELD_LENGTH_MASK ); return EEP_OK;}int ibrick_mac_addr_get( nasid_t nasid, char *eaddr ){ eeprom_brd_record_t eep; eeprom_board_ia_t board; eeprom_chassis_ia_t chassis; int r; char *tmp; eep.board_ia = &board; eep.chassis_ia = &chassis; eep.spd = NULL; r = iobrick_eeprom_read( &eep, nasid, IO_BRICK ); if( (r != EEP_OK) || (board.mac_addr[0] == '\0') ) { db_printf(( "ibrick_mac_addr_get: " "Couldn't read MAC address from EEPROM\n" )); return EEP_L1; } else { /* successfully read info area */ int ix; tmp = board.mac_addr; for( ix = 0; ix < (board.mac_addr_tl & FIELD_LENGTH_MASK); ix++ ) { *eaddr++ = *tmp++; } *eaddr = '\0'; } return EEP_OK;}/* * eeprom_vertex_info_set * * Given a vertex handle, a component designation, a starting nasid * and (in the case of a router) a vector path to the component, this * function will read the EEPROM and attach the resulting information * to the vertex in the same string format as that provided by the * Dallas Semiconductor NIC drivers. If the vertex already has the * string, this function just returns the string. */extern char *nic_vertex_info_get( devfs_handle_t );extern void nic_vmc_check( devfs_handle_t, char * );#ifdef BRINGUP/* the following were lifted from nic.c - change later? */#define MAX_INFO 2048#define NEWSZ(ptr,sz) ((ptr) = kern_malloc((sz)))#define DEL(ptr) (kern_free((ptr)))#endif /* BRINGUP */char *eeprom_vertex_info_set( int component, int nasid, devfs_handle_t v, net_vec_t path ){ char *info_tmp; int info_len; char *info; /* see if this vertex is already marked */ info_tmp = nic_vertex_info_get(v); if (info_tmp) return info_tmp; /* get a temporary place for the data */ NEWSZ(info_tmp, MAX_INFO); if (!info_tmp) return NULL; /* read the EEPROM */ if( component & R_BRICK ) { if( RBRICK_EEPROM_STR( info_tmp, nasid, path ) != EEP_OK ) return NULL; } else { if( eeprom_str( info_tmp, nasid, component ) != EEP_OK ) return NULL; } /* allocate a smaller final place */ info_len = strlen(info_tmp)+1; NEWSZ(info, info_len); if (info) { strcpy(info, info_tmp); DEL(info_tmp); } else { info = info_tmp; } /* add info to the vertex */ hwgraph_info_add_LBL(v, INFO_LBL_NIC, (arbitrary_info_t) info); /* see if someone else got there first */ info_tmp = nic_vertex_info_get(v); if (info != info_tmp) { DEL(info); return info_tmp; } /* export the data */ hwgraph_info_export_LBL(v, INFO_LBL_NIC, info_len); /* trigger all matching callbacks */ nic_vmc_check(v, info); return info;}/********************************************************************* * * stubs for use until the Bedrock/L1 link is available * */#include <asm/sn/nic.h>/* #define EEPROM_TEST *//* fake eeprom reading functions (replace when the BR/L1 communication * channel is in working order) *//* generate a charater in [0-9A-Z]; if an "extra" character is * specified (such as '_'), include it as one of the possibilities. */char random_eeprom_ch( char extra ) { char ch; int modval = 36; if( extra ) modval++; ch = rtc_time() % modval; if( ch < 10 ) ch += '0'; else if( ch >= 10 && ch < 36 ) ch += ('A' - 10); else ch = extra; return ch;}/* create a part number of the form xxx-xxxx-xxx. * It may be important later to generate different * part numbers depending on the component we're * supposed to be "reading" from, so the component * paramter is provided. */void fake_a_part_number( char *buf, int component ){ int i; switch( component ) { /* insert component-specific routines here */ case C_BRICK: strcpy( buf, "030-1266-001" ); break; default: for( i = 0; i < 12; i++ ) { if( i == 3 || i == 8 ) buf[i] = '-'; else buf[i] = random_eeprom_ch(0); } }}/* create a six-character serial number */void fake_a_serial_number( char *buf, uint64_t ser ){ int i; static const char hexchars[] = "0123456789ABCDEF"; if (ser) { for( i = 5; i >=0; i-- ) { buf[i] = hexchars[ser & 0xf]; ser >>= 4; } } else { for( i = 0; i < 6; i++ ) buf[i] = random_eeprom_ch(0); }}void fake_a_product_name( uchar_t *format, char* buf, int component ){ switch( component & BRICK_MASK ) { case C_BRICK: if( component & SUBORD_MASK ) { strcpy( buf, "C_BRICK_SUB" ); *format = 0xCB; } else { strcpy( buf, "IP35" ); *format = 0xC4; } break; case R_BRICK: if( component & SUBORD_MASK ) { strcpy( buf, "R_BRICK_SUB" ); *format = 0xCB; } else { strcpy( buf, "R_BRICK" ); *format = 0xC7; } break; case IO_BRICK: if( component & SUBORD_MASK ) { strcpy( buf, "IO_BRICK_SUB" ); *format = 0xCC; } else { strcpy( buf, "IO_BRICK" ); *format = 0xC8; } break; default: strcpy( buf, "UNK_DEVICE" ); *format = 0xCA; }}int fake_an_eeprom_record( eeprom_brd_record_t *buf, int component, uint64_t ser ){ eeprom_board_ia_t *board; eeprom_chassis_ia_t *chassis; int i, cs; board = buf->board_ia; chassis = buf->chassis_ia; if( !(component & SUBORD_MASK) ) { if( !chassis ) return EEP_PARAM; chassis->format = 0; chassis->length = 5; chassis->type = 0x17; chassis->part_num_tl = 0xCC; fake_a_part_number( chassis->part_num, component ); chassis->serial_num_tl = 0xC6; fake_a_serial_number( chassis->serial_num, ser ); cs = chassis->format + chassis->length + chassis->type + chassis->part_num_tl + chassis->serial_num_tl; for( i = 0; i < (chassis->part_num_tl & FIELD_LENGTH_MASK); i++ ) cs += chassis->part_num[i]; for( i = 0; i < (chassis->serial_num_tl & FIELD_LENGTH_MASK); i++ ) cs += chassis->serial_num[i]; chassis->checksum = 256 - (cs % 256); } if( !board ) return EEP_PARAM; board->format = 0; board->length = 10; board->language = 0; board->mfg_date = 1789200; /* noon, 5/26/99 */ board->manuf_tl = 0xC3; strcpy( board->manuf, "SGI" ); fake_a_product_name( &(board->product_tl), board->product, component ); board->serial_num_tl = 0xC6; fake_a_serial_number( board->serial_num, ser ); board->part_num_tl = 0xCC; fake_a_part_number( board->part_num, component ); board->board_rev_tl = 0xC2; board->board_rev[0] = '0'; board->board_rev[1] = '1'; board->eeprom_size_tl = 0x01; board->eeprom_size = 1; board->temp_waiver_tl = 0xC2; board->temp_waiver[0] = '0'; board->temp_waiver[1] = '1'; cs = board->format + board->length + board->language + (board->mfg_date & 0xFF) + (board->mfg_date & 0xFF00) + (board->mfg_date & 0xFF0000) + board->manuf_tl + board->product_tl + board->serial_num_tl + board->part_num_tl + board->board_rev_tl + board->board_rev[0] + board->board_rev[1] + board->eeprom_size_tl + board->eeprom_size + board->temp_waiver_tl + board->temp_waiver[0] + board->temp_waiver[1]; for( i = 0; i < (board->manuf_tl & FIELD_LENGTH_MASK); i++ ) cs += board->manuf[i]; for( i = 0; i < (board->product_tl & FIELD_LENGTH_MASK); i++ ) cs += board->product[i]; for( i = 0; i < (board->serial_num_tl & FIELD_LENGTH_MASK); i++ ) cs += board->serial_num[i]; for( i = 0; i < (board->part_num_tl & FIELD_LENGTH_MASK); i++ ) cs += board->part_num[i]; board->checksum = 256 - (cs % 256); return EEP_OK;}#define EEPROM_CHUNKSIZE 64#if defined(EEPROM_DEBUG)#define RETURN_ERROR \{ \ printk( "read_ia error return, component 0x%x, line %d" \ ", address 0x%x, ia code 0x%x\n", \ l1_compt, __LINE__, sc->subch[subch].target, ia_code ); \ return EEP_L1; \}#else#define RETURN_ERROR return(EEP_L1)#endifint read_ia( l1sc_t *sc, int subch, int l1_compt, int ia_code, char *eep_record ){#if !defined(CONFIG_SERIAL_SGI_L1_PROTOCOL) return EEP_L1;#else char msg[BRL1_QSIZE]; /* message buffer */ int len; /* number of bytes used in message buffer */ int ia_len = EEPROM_CHUNKSIZE; /* remaining bytes in info area */ int offset = 0; /* current offset into info area */ if ( IS_RUNNING_ON_SIMULATOR() ) return EEP_L1; BZERO( msg, BRL1_QSIZE ); /* retrieve EEPROM data in 64-byte chunks */ while( ia_len ) { /* fill in msg with opcode & params */ if( (len = sc_construct_msg( sc, subch, msg, BRL1_QSIZE, L1_ADDR_TASK_GENERAL, L1_REQ_EEPROM, 8, L1_ARG_INT, l1_compt, L1_ARG_INT, ia_code, L1_ARG_INT, offset, L1_ARG_INT, ia_len )) < 0 ) { RETURN_ERROR; } /* send the request to the L1 */ if( sc_command( sc, subch, msg, msg, &len ) ) { RETURN_ERROR; } /* check response */ if( sc_interpret_resp( msg, 5, L1_ARG_INT, &ia_len, L1_ARG_UNKNOWN, &len, eep_record ) < 0 ) { RETURN_ERROR; } if( ia_len > EEPROM_CHUNKSIZE ) ia_len = EEPROM_CHUNKSIZE; eep_record += EEPROM_CHUNKSIZE; offset += EEPROM_CHUNKSIZE; } return EEP_OK;#endif /* CONFIG_SERIAL_SGI_L1_PROTOCOL */}int read_spd( l1sc_t *sc, int subch, int l1_compt, eeprom_spd_u *spd ){#if !defined(CONFIG_SERIAL_SGI_L1_PROTOCOL) return EEP_L1;#else char msg[BRL1_QSIZE]; /* message buffer */ int len; /* number of bytes used in message buffer */ int spd_len = EEPROM_CHUNKSIZE; /* remaining bytes in spd record */ int offset = 0; /* current offset into spd record */ char *spd_p = spd->bytes; /* "thumb" for writing to spd */ if ( IS_RUNNING_ON_SIMULATOR() ) return EEP_L1; BZERO( msg, BRL1_QSIZE ); /* retrieve EEPROM data in 64-byte chunks */ while( spd_len ) { /* fill in msg with opcode & params */ if( (len = sc_construct_msg( sc, subch, msg, BRL1_QSIZE, L1_ADDR_TASK_GENERAL, L1_REQ_EEPROM, 8, L1_ARG_INT, l1_compt, L1_ARG_INT, L1_EEP_SPD, L1_ARG_INT, offset,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -