1
0
Files
irix-657m-src/stand/arcs/IO6prom/flashprom.c
2022-09-29 17:59:04 +03:00

1499 lines
35 KiB
C

/***********************************************************************\
* File: flashprom.c *
* *
* *
\***********************************************************************/
#include <ctype.h>
#include <libsc.h>
#include <libsk.h>
#include <pgdrv.h>
#include <io6fprom.h>
#include <promgraph.h>
#include <sys/SN/addrs.h>
#include <sys/SN/klconfig.h>
#define DEF_IP27_CONFIG_TABLE
#include <sys/SN/SN0/ip27config.h>
#include <sys/SN/promhdr.h>
#include <sys/SN/SN0/klhwinit.h> /* For definitions of LD, SD */
#include <sys/SN/slotnum.h>
#include <sys/graph.h>
#include <sys/hwgraph.h>
#include <sys/iograph.h>
/*
* SN_PDI - Prom Driver Infrastructure.
* This is an alternate way of building the prom hwgraph.
* Since the flash command uses prom hwgraph it needs to
* take care of both ways. SN_PDI is the new one. The
* globals, graph handle and root vertex handle are different
* for both cases, we need this ifdef.
*/
#ifdef SN_PDI
extern vertex_hdl_t snpdi_rvhdl ;
extern graph_hdl_t pg_hdl ;
#else
extern vertex_hdl_t hw_vertex_hdl ;
extern graph_hdl_t prom_graph_hdl ;
#endif
extern nasid_t master_nasid;
extern int slot_to_widget() ;
extern int get_my_node_slot_class() ;
#define MAX_IP27_SLOT 4
#define MAX_IO6_SLOT 12
int do_flash_cmd(int, char **);
nasid_t flash_getnasid(int) ;
void _get_cpu_hub_freq(ip27config_t *);
int _fill_in_config_info(ip27config_t *, int);
int _verify_config_info(ip27config_t *);
void _get_all_config_vals (ip27config_t *);
__uint32_t get_scache_size (__uint32_t);
ip27config_t *new_config_info;
#define LBYTEU(caddr) \
(u_char) ((*(uint *) ((__psunsigned_t) (caddr) & ~3) << \
((__psunsigned_t) (caddr) & 3) * 8) >> 24)
#define CONFIG_HDR_OFFSET (PROM_DATA_OFFSET + 0x60)
/* If we are flashing io prom on a speedo with an xbox then
* target is the flashprom in the xbox.
*/
#define IS_XBOX_FLASHPROM() (SN00 && \
(flash_which == IO_PROM) && \
(xbox_nasid_get() != INVALID_NASID))
/*
* NOTE: The flash commands use a set of global variables right now
* since we are flashing one prom at a time. If we have to do them
* in parallel then this has to be changed.
*/
int modid, slotid, n, w ;
nasid_t flashprom_nasid ;
int widgetid ;
int foundfile, boardlist, verbose, flash_debug ;
unsigned int erase_flag ;
unsigned int count_flag ;
int confirm_yes ;
int flash_which;
unsigned int log_erase_flag ;
unsigned int check_flag ;
unsigned int full_check_flag ;
unsigned int cache_size ;
char filename[FILENAME_BUF_SIZE];
char *remain ;
static char *command;
static int nasid_option ;
static int modid_option ;
char slotname[SLOTNUM_MAXLENGTH] ;
int
flash_cmd(int argc, char **argv)
{
flash_which = -1;
if (do_flash_cmd (argc, argv))
return 1;
return 0;
}
void
copy_buffer_adj_sum(ip27config_t *config_info)
{
__uint64_t old_sum, new_sum;
ip27config_t *config_buff_hdr;
config_buff_hdr = (ip27config_t *)(
TO_NODE(get_nasid(), FLASHBUF_BASE) + CONFIG_HDR_OFFSET);
old_sum = memsum((void *)(TO_NODE(get_nasid(), FLASHBUF_BASE) +
CONFIG_HDR_OFFSET), sizeof(ip27config_t))%256;
bcopy((char *)config_info, (char *) (TO_NODE(get_nasid(),
FLASHBUF_BASE) + CONFIG_HDR_OFFSET), sizeof(ip27config_t));
new_sum = memsum((void *) (TO_NODE(get_nasid(), FLASHBUF_BASE) +
CONFIG_HDR_OFFSET), sizeof(ip27config_t))%256;
/* now set the appropiate check sum adjust value so
that we're back to summing to 0 % 256 */
if (old_sum>new_sum) {
config_buff_hdr->check_sum_adj = (uint) (old_sum - new_sum);
}
else {
config_buff_hdr->check_sum_adj = (uint) (256 - (new_sum - old_sum));
}
config_buff_hdr->check_sum_adj = config_buff_hdr->check_sum_adj & 0xff;
}
int parse_megahertz(char *s)
{
int f = 1000000, n = atoi(s) * f;
if ((s = strchr(s, '.')) != 0)
while (*++s)
n += (*s - '0') * (f /= 10);
return n;
}
/*
* flash reads the future contents of the PROM from a binary file and
* writes the data directly into the flash prom. It is a little
* dangerous since if some kind of error occurs the flash prom
* can be corrupted.
*/
int
do_flash_cmd(int argc, char **argv)
{
char *buffer = (char *) TO_NODE(get_nasid(), FLASHBUF_BASE);
promhdr_t promhdr;
promhdr_t *ph;
char input_str[8];
int only_io;
int rtn_val;
new_config_info = ((ip27config_t *) malloc(sizeof(ip27config_t)));
/* flash parse sets various globals in printf below */
if (!flash_parse(argc, argv, flash_which)) {
rtn_val = 1;
goto end_do_flash;
}
if (flash_debug) {
printf("flash_parse: Module = %d, Slot = %d, widget = %d,\
nodepath = %d, nasid = %d\n",
modid, slotid, w, n, flashprom_nasid) ;
}
if (log_erase_flag) {
program_all_proms(KLTYPE_IP27, &promhdr, buffer);
rtn_val = 0;
goto end_do_flash;
}
if (!flash_debug) {
/* Read in the flashprom binary file if we're not erasing */
if (!(erase_flag || log_erase_flag || count_flag)) {
printf("Reading PROM Image file %s ...\n", filename) ;
if (read_flashprom(filename, &promhdr, buffer) == -1) {
rtn_val = 0;
goto end_do_flash;
}
}
}
only_io = 0;
if ((flash_which == IO_PROM) || (flash_which == -1)) {
if (flash_which == IO_PROM)
only_io = 1;
flash_which = IO_PROM;
if ((full_check_flag) && (only_io))
printf("Ignoring -F since we're only flashing the IO Prom\n");
if ((check_flag) && (only_io))
printf("Ignoring -f since we're only flashing the IO Prom\n");
/* easy case - don't need to fix configuration bits */
/* Program the selected boards */
if (boardlist) {
program_io6(&promhdr, buffer);
} else {
program_all_proms(KLTYPE_BASEIO, &promhdr, buffer);
}
if (only_io) {
rtn_val = 0;
goto end_do_flash;
}
}
/* if we're here that means we need a valid cpu image thus we
will need to obtain valid configuration bits
if we're flashing all the proms we'll pick up the specific
config info for each board in flash_all_nodes */
flash_which = CPU_PROM;
if (full_check_flag) {
_get_all_config_vals(new_config_info);
}
else if (check_flag) {
/*
* only frequencies and scache size
*/
_get_cpu_hub_freq(new_config_info);
new_config_info->r10k_mode = get_scache_size(SN00 ?
1 << IP27C_R10000_SCS_SHFT :
4 << IP27C_R10000_SCS_SHFT );
if (! _verify_config_info(new_config_info)) {
printf("invalid configuration values\n");
rtn_val = 1;
goto end_do_flash;
}
}
else ;
/* Now program the selected boards */
if (boardlist) {
program_ip27(&promhdr, buffer);
} else {
if (full_check_flag || check_flag) {
printf("When using -f or -F it is recommended that proms are flashed individually.\n");
printf(" Since a board has not been specified all proms will be flashed.\n");
printf(" Do you wish to continue with flash y/n [n] ");
gets(input_str);
if (input_str[0] != 'y') {
rtn_val = 0;
goto end_do_flash;
}
}
program_all_proms(KLTYPE_IP27, &promhdr, buffer);
}
rtn_val = 0;
end_do_flash:
free(new_config_info);
return rtn_val;
}
/* returns 1 if there's enough info in the header to set the entire
configuration header - else rerturn 0 */
int
_verify_config_info(ip27config_t *config_info)
{
int i;
/*
* check if this is a valid configuration, e.g. it shows
* up in the configuration tables.
*/
for (i=0; i<NUMB_IP27_CONFIGS; i++) {
__uint32_t sz1,sz2;
sz1 = ip27config_table[i].r10k_mode & IP27C_R10000_SCS_MASK;
sz2 = config_info->r10k_mode & IP27C_R10000_SCS_MASK;
if ((sz1 == sz2 ) &&
(ip27config_table[i].mach_type == config_info->mach_type) &&
(ip27config_table[i].freq_cpu == config_info->freq_cpu ) &&
(ip27config_table[i].freq_hub == config_info->freq_hub ))
return _fill_in_config_info(config_info, i);
}
printf("unknown configuration use set manually with -F\n");
return 0;
}
int
_fill_in_config_info(ip27config_t *config_info, int index)
{
config_info->time_const = (uint) CONFIG_TIME_CONST;
config_info->magic = (__uint64_t) CONFIG_MAGIC;
config_info->freq_rtc = (__uint64_t) IP27C_KHZ(IP27_RTC_FREQ);
config_info->ecc_enable = (uint) CONFIG_ECC_ENABLE;
config_info->check_sum_adj = (uint) 0;
/* freq_cpu, freq_hub, and mach_type have already been set */
config_info->r10k_mode = ip27config_table[index].r10k_mode;
config_info->fprom_cyc = ip27config_table[index].fprom_cyc;
config_info->fprom_wr = ip27config_table[index].fprom_wr;
return 1;
}
void
_get_cpu_hub_freq(ip27config_t *config_info)
{
char input_str[8];
config_info->freq_cpu = (__uint64_t) IP27C_MHZ(300) ;
printf("%-35s [%5d] : ","CPU frequency (MHZ)",
config_info->freq_cpu / 1000000);
gets(input_str);
if (strlen(input_str) > 0)
config_info->freq_cpu = (__uint64_t) parse_megahertz(input_str);
config_info->freq_hub = (__uint64_t) IP27C_MHZ(100) ;
printf("%-35s [%5d] : ","Hub frequency (MHZ)",
config_info->freq_hub / 1000000);
gets(input_str);
if (strlen(input_str) > 0)
config_info->freq_hub = (__uint64_t) parse_megahertz(input_str);
config_info->mach_type = (uint) SN00 ? 1 : 0;
printf("%-35s [%5d] : ","Machine type (0)SN0 (1)SN00",
config_info->mach_type);
gets(input_str);
if (strlen(input_str) > 0)
config_info->mach_type = (uint) atoi(input_str);
config_info->check_sum_adj = (uint) 0;
config_info->fprom_cyc =
(config_info->mach_type == SN00_MACH_TYPE ? 15 : 8);
config_info->fprom_wr =
(config_info->mach_type == SN00_MACH_TYPE ? 4 : 1);
}
/*
* returns the CPU mode bits setting for secondary
* cache size.
*
* same format and options for IP27 and IO6
*/
char *cache_size_mb[8] = { "0.5","1","2","4","8","16","RSV","RSV" };
__uint32_t
get_scache_size(__uint32_t def_mode)
{
__uint32_t result;
char buf[8];
int cache;
cache = -1;
while (cache == -1) {
printf("%-35s [%5s] : ","Scache size in MB",
cache_size_mb[((def_mode & IP27C_R10000_SCS_MASK) >>
IP27C_R10000_SCS_SHFT)]);
if (gets(buf) && strlen(buf)) {
if (!strcmp(buf,"0.5"))
cache = 0;
switch(atoi(buf)) {
case 1 : cache = 1 ; break;
case 2 : cache = 2 ; break;
case 4 : cache = 3 ; break;
case 8 : cache = 4 ; break;
case 16 : cache = 5 ; break;
default : break;
}
if (cache == -1)
printf("Invalid secondary cache size, try again\n");
} else {
return def_mode;
}
}
result = def_mode & (~IP27C_R10000_SCS_MASK);
result |= (cache << IP27C_R10000_SCS_SHFT);
return result;
}
#define MHZ(f) (f / 1000000)
/*
* the define should move to /usr/include/sys/R10k.h
*/
#ifndef R10000_DDR_SHFT
#define R10000_DDR_SHFT 23
#endif
void
_get_all_config_vals(ip27config_t *config_info)
{
char buf[8];
__uint32_t cpu_mode,val,tap,onetap,SysClkDiv,SCClkDiv;
int is_r14k;
re_enter:
config_info->r10k_mode = 0;
/*
* default mode bits, there should be no need to change them
*/
cpu_mode = 5 << R10000_KSEG0CA_SHFT | /* kseg0 cache algorithm */
/* 5 == cacheable coherent */
/* exclusive on write */
1 << R10000_SCBS_SHFT | /* secondary cache block sz */
/* 1 == 32 words */
1 << R10000_ME_SHFT ; /* Memory endianness */
/* 1 == big endian */
_get_cpu_hub_freq(config_info);
is_r14k = 0;
printf("%-35s [%5d] : ","CPU type (0)R10K/R12K (1)R14K",is_r14k);
gets(buf);
if (strlen(buf) && atoi(buf) == 1)
is_r14k = 1;
cpu_mode |= get_scache_size(SN00 ? 1 << IP27C_R10000_SCS_SHFT :
4 << IP27C_R10000_SCS_SHFT );
if (is_r14k) {
printf("%-35s [%5d] : ","DDR SRam",0);
gets(buf);
if (strlen(buf) && atoi(buf) == 1)
cpu_mode |= (1 << R10000_DDR_SHFT);
}
printf("%-35s [%5d] : ","Tandem Mode bit",0);
gets(buf);
if (strlen(buf) && atoi(buf) == 1)
cpu_mode |= (1 << R10000_SCCE_SHFT);
/*
* we have a pretty good idea how the divisor should look like
* given the hub and CPU frequencies, so we'll use this as
* the default
*/
val = ((MHZ(config_info->freq_cpu) * 2) /
MHZ(config_info->freq_hub)) - 1;
printf("%-35s [%5d] : ","SysClk Divisor (PClk/SysClk ratio)",val);
gets(buf);
if (strlen(buf))
val = atoi(buf);
cpu_mode |= ((val << R10000_SCD_SHFT) & R10000_SCD_MASK);
val = 2; /* reasonable default */
printf("%-35s [%5d] : ","SCClk Divisor (PClk/SCClk ratio)", val);
gets(buf);
if (strlen(buf))
val = atoi(buf);
cpu_mode |= ((val << R10000_SCCD_SHFT) & R10000_SCCD_MASK);
tap = 0xa; /* reasonable default */
printf("%-35s [ 0x%x] : ","SCClk Tap", tap);
gets(buf);
if (strlen(buf))
tap = strtoull(buf, NULL, 16);
cpu_mode |= ((tap << R10000_SCCT_SHFT) & R10000_SCCT_MASK);
val = 0x3;
printf("%-35s [ 0x%x] : ","Outstanding requests", val);
gets(buf);
if (strlen(buf))
val = strtoull(buf, NULL, 16);
cpu_mode |= ((val << R10000_PRM_SHFT) & R10000_PRM_MASK);
config_info->r10k_mode = cpu_mode;
config_info->freq_rtc = (__uint64_t) IP27C_KHZ(IP27_RTC_FREQ);
printf("%-35s [ 1.25] : ","RTC frequency (MHZ)");
if (gets(buf) && strlen(buf) > 0)
config_info->freq_rtc = (__uint64_t) parse_megahertz(buf);
config_info->config_type = (uint) 0;
printf("%-35s [%5d] : ","Configuration (0)Normal (1)12P4I",
config_info->config_type);
gets(buf);
if (strlen(buf) > 0)
config_info->config_type = (uint) atoi(buf);
printf("\n");
/*
* Verification
* ------------
*/
printf("CPU freq\t%3d MHz\n", MHZ(config_info->freq_cpu));
printf("CPU type\t%s\n" , is_r14k ? "R14K":"R10K/R12k");
printf("Hub freq\t%3d MHz\n", MHZ(config_info->freq_hub));
/*
* Secondary cache information
*/
SysClkDiv = (config_info->r10k_mode & R10000_SCD_MASK)
>> R10000_SCD_SHFT;
SCClkDiv = (config_info->r10k_mode & R10000_SCCD_MASK)
>> R10000_SCCD_SHFT;
/*
* if this is R14K running in DDR mode we need to twist
* the SCClkDiv a bit in order to compute the correct
* scache speed. Also handle siliconn test modes in R14k
*
* Code R10K/R12K R14K SDR R14K DDR
* 0 rsv rsv rsv
* 1 1 1 2
* 2 1.5 1.5 2
* 3 2 2 2
* 4 2.5 2.5 2
* 5 3 3 3
* 6 rsv 6 6
* 7 rsv 4 4
*
*/
if (is_r14k) {
/*
* handle silicon test modes. Code 7 translates
* correctly to a div 4.0
*/
if (SCClkDiv == 6)
SCClkDiv = 11;
if (config_info->r10k_mode & (1 << R10000_DDR_SHFT)) {
switch(SCClkDiv) {
case 1 :
case 2 :
case 4 :
SCClkDiv = 3;
break;
default:
break;
}
}
printf("Scache mode\t%s\n",
config_info->r10k_mode & (1 << R10000_DDR_SHFT) ?
"DDR":"SDR");
}
if (is_r14k && (config_info->r10k_mode & (1 << R10000_DDR_SHFT))) {
printf("Scache freq\tread %3d MHz / write %3d Mhz\n",
(MHZ(config_info->freq_hub) *
(SysClkDiv + 1) / (SCClkDiv + 1)) * 2,
MHZ(config_info->freq_hub) *
(SysClkDiv + 1) / (SCClkDiv + 1));
} else {
printf("Scache freq\t%3d MHz\n",
MHZ(config_info->freq_hub) *
(SysClkDiv + 1) / (SCClkDiv + 1));
}
printf("Scache Tap\t[0x%x] ",tap);
onetap = (int) 1E6 / MHZ(config_info->freq_cpu) / 12;
switch (tap) {
case 0x0 : printf("same phase as internal clock"); break;
case 0x1 : printf("%d ps",onetap * 1); break;
case 0x2 : printf("%d ps",onetap * 2); break;
case 0x3 : printf("%d ps",onetap * 3); break;
case 0x4 : printf("%d ps",onetap * 4); break;
case 0x5 : printf("%d ps",onetap * 5); break;
case 0x6 : printf("UNDEFINED"); break;
case 0x7 : printf("UNDEFINED"); break;
case 0x8 : printf("%d ps",onetap * 6); break;
case 0x9 : printf("%d ps",onetap * 7); break;
case 0xa : printf("%d ps",onetap * 8); break;
case 0xb : printf("%d ps",onetap * 9); break;
case 0xc : printf("%d ps",onetap * 10); break;
case 0xd : printf("%d ps",onetap * 11); break;
case 0xe : printf("UNDEFINED"); break;
case 0xf : printf("UNDEFINED"); break;
default : printf("INVAL \"%d\"",tap); break;
}
printf(", tap inc %d ps\n",onetap);
printf("Machine type\t%s\n",
config_info->mach_type == SN00_MACH_TYPE ? "SN00" : "SN0");
printf("Cache size\t%s MB\n",
cache_size_mb[((config_info->r10k_mode & 0x00070000)
>> IP27C_R10000_SCS_SHFT)]);
printf("Tandem mode\t%d\n",
(config_info->r10k_mode & R10000_SCCE_MASK)
>> R10000_SCCE_SHFT);
printf("R10K mode\t0x%x\n", config_info->r10k_mode);
printf("RTC freq (KHZ)\t%d\n",config_info->freq_rtc / 1000);
printf("Configuration\t%s",config_info->config_type == 0 ?
"Normal" : "12P4I");
printf("\n\nProceed ? [n] ");
if (!gets(buf) || ((buf[0] != 'y') && (buf[0] != 'Y')))
goto re_enter;
config_info->time_const = (uint) CONFIG_TIME_CONST;
config_info->magic = (__uint64_t) CONFIG_MAGIC;
config_info->ecc_enable = (uint) CONFIG_ECC_ENABLE;
config_info->check_sum_adj = (uint) 0;
}
int
flash_parse(int argc, char **argv, int type)
{
int i ;
/* Init all globals */
bzero(filename, FILENAME_BUF_SIZE);
log_erase_flag = 0;
check_flag = 0;
full_check_flag = 0;
erase_flag = 0 ;
count_flag = 0 ;
foundfile = 0 ;
verbose = 0 ;
boardlist = 0 ;
flash_debug = 0 ;
nasid_option = 0 ;
modid_option = 0 ;
confirm_yes = 0 ;
slotname[0] = 0 ;
modid = slotid = -1 ;
widgetid = -1 ;
flashprom_nasid = INVALID_NASID;
command = "Flashing";
/* Check arguments */
if (argc < 2) /* too less */
return 0;
for (i = 1; i < argc; i++) {
if (argv[i][0] == '-') {
switch (argv[i][1]) {
case 'c':
if (flash_which != -1) {
printf("Error: choice of proms already specified\n");
return 0;
}
flash_which = CPU_PROM ;
break ;
case 'C':
count_flag = 1 ;
command = "Counting";
break ;
case 'e':
erase_flag = 1 ;
command = "Erasing";
break ;
case 'f':
check_flag = 1 ;
break ;
case 'F':
full_check_flag = 1 ;
break ;
case 'i':
if (flash_which != -1) {
printf("Error: choice of proms already specified\n");
return 0;
}
flash_which = IO_PROM ;
break ;
case 'l':
log_erase_flag = 1 ;
break ;
case 'm':
if (++i == argc)
return 0 ;
if (!(isdigit(argv[i][0]))) {
printf(
"Error: Module id must be a number\n");
return 0 ;
}
modid = atoi(argv[i]) ;
break ;
case 'n':
if (flash_which != -1) {
printf("Error: choice of proms already specified\n");
return 0;
}
flash_which = CPU_PROM ;
break ;
case 'N':
/* For compatibility with the 'flash'
command in the IP27prom POD mode
we can flash a cpu prom with a nasid */
if (++i == argc)
return 0 ;
if (!(isdigit(argv[i][0]))) {
printf(
"Error: Nasid must be a number\n");
return 0 ;
}
flashprom_nasid = atoi(argv[i]) ;
nasid_option = 1 ;
break ;
case 's':
/* If we are an xbox system then we
* can flash the io prom by specifying
* module & io slot number.
*/
if (SN00 &&
xbox_nasid_get() == INVALID_NASID)
if (++i == argc)
return 0 ;
else
break ;
if (++i == argc)
return 0 ;
if (flash_which == IO_PROM) {
if (strncmp(argv[i], "io", 2)) {
printf(
"Error: Slotname must begin with \'io\'\n") ;
return 0 ;
}
slotid = atoi(&argv[i][2]) ;
/* If we are an xbox and are trying
* to specify an io slot other than
* 7 then print an error.
*/
if (SN00 && slotid != 7) {
printf(
"Invalid XBOX IO PROM slot io%d\n",
slotid);
return(0);
}
}
else
if (flash_which == CPU_PROM) {
if (argv[i][0] != 'n') {
printf(
"Error: Slotname must begin with \'n\'\n") ;
return 0 ;
}
slotid = atoi(&argv[i][1]) ;
}
else {
printf("Please specify the type of PROM to flash first.\n") ;
return 0 ;
}
strcpy(slotname, argv[i]) ;
break ;
case 'v':
verbose = 1 ;
break ;
case 'd':
flash_debug = 1 ;
break ;
case 'y':
confirm_yes = 1 ;
break ;
default:
parse_err:
printf(
"Error: Unrecognized flag: '%s'\n",
argv[i]);
return 0 ;
}
} else {
if (!foundfile) {
strcpy(filename, argv[i]) ;
i ++ ;
foundfile = 1 ;
} else {
printf(
"Error: already specified filename '%s'.\n",
filename);
return 0 ;
}
break ;
}
}
if (count_flag || log_erase_flag) {
if (flash_which != CPU_PROM) {
printf("error you must specify the cpu prom (-c|-n) when requesting to erase the log or count the number of flashes\n");
return 0;
}
}
if (i != argc)
printf("Extra argument at end of list ignored\n") ;
if ((modid == -1) && (slotid != -1)) {
/* module not specified but slot specified */
printf("Module id required if slotid is specified.\n") ;
return 0 ;
}
/* Complain if no file name was specified */
if (!foundfile) {
if (!(erase_flag || log_erase_flag || count_flag)) {
printf("Error: no filename specified\n");
return 0;
}
}
/* Check for proper range of values for module id and slot id */
if ((slotid > MAX_IP27_SLOT) && (flash_which == CPU_PROM)) {
printf("Error: Invalid NODE slot number %d\n", slotid) ;
return 0 ;
}
if ((slotid > MAX_IO6_SLOT) && (flash_which == IO_PROM)) {
printf("Error: Invalid IO slot number %d\n", slotid) ;
return 0 ;
}
if ((flashprom_nasid == INVALID_NASID) && (modid == -1) && (slotid == -1)) {
printf("%s all PROMs in the system\n", command) ;
}
else if ((modid != -1) && (slotid == -1)) {
/* Flash all proms in module */
modid_option = 1 ;
} else {
/* modid and slotid are non-negative or nasid is specified on cmd line */
/* get nasid from promgraph */
if (flashprom_nasid == INVALID_NASID)
flashprom_nasid = flash_getnasid(type) ;
if (flashprom_nasid == INVALID_NASID)
return 0 ;
boardlist = 1 ;
if (nasid_option)
printf("%s PROM in Node ID %d\n",
command, flashprom_nasid) ;
else
printf("%s PROM in Module %d Slot %d\n",
command, modid, slotid) ;
}
return 1 ;
}
__uint64_t
memsum(void *base, size_t len)
{
uchar_t *src = base;
__uint64_t sum, part, mask, v;
int i;
mask = 0x00ff00ff00ff00ff;
sum = 0;
while (len > 0 && (__psunsigned_t) src & 7) {
sum += LBYTEU(src);
src++;
len--;
}
while (len >= 128 * 8) {
part = 0;
for (i = 0; i < 128; i++) {
v = *(__uint64_t *) src;
src += 8;
part += v & mask;
part += v >> 8 & mask;
}
sum += part & 0xffff;
sum += part >> 16 & 0xffff;
sum += part >> 32 & 0xffff;
sum += part >> 48 & 0xffff;
len -= 128 * 8;
}
while (len > 0) {
sum += LBYTEU(src);
src++;
len--;
}
return sum;
}
hub_accessible(nasid_t nasid)
{
__uint64_t reg, tst;
int r = 0;
reg = (__uint64_t) REMOTE_HUB(nasid, MD_PERF_CNT5);
tst = 0x5555ULL;
SD(reg, tst);
if (LD(reg) != tst)
goto done;
tst = 0xaaaaULL;
SD(reg, tst);
if (LD(reg) != tst)
goto done;
r = 1;
done:
return r;
}
#define PRINT_ADDRESS 0x8000
#define PRINT_DOT 0x1000
int
fprom_write_buffer(fprom_t *f, char *buffer, int count)
{
char *src, *src_end;
off_t dst_off;
int r, done, first, n ;
int pra, prd ;
src = (char *)buffer;
src_end = src + count ;
dst_off = 0 ;
pra = 0 ;
prd = 0 ;
done = 0 ;
first = 1 ;
while (1) {
if ((n = src_end - src) > 256)
n = 256 ;
if (done >= pra || n == 0) {
if (!first)
printf("\n") ;
first = 0 ;
printf("> %5lx/%05lx ", done, count) ;
if (n == 0)
break ;
pra += PRINT_ADDRESS ;
}
if ((r = fprom_write(f, dst_off, src, n)) < 0) {
printf("> Error programming PROM: %s\n",
fprom_errmsg(r));
printf("base = %x, off = %x, src = %x\n",
f->base, dst_off, src) ;
return 0 ;
}
if (done >= prd) {
printf(".") ;
prd += PRINT_DOT ;
}
src += n;
dst_off += n;
done += n;
}
return 1 ;
}
/*
* void dump_promhdr
* Dump the information in the promhdr_t structure.
*/
void
dump_promhdr(promhdr_t *ph)
{
int i;
printf("PROM Header contains:\n");
printf(" Magic: 0x%llx\n", ph->magic);
printf(" Version: %lld.%lld\n", ph->version, ph->revision);
printf(" Length: 0x%llx\n", ph->length);
printf(" Segments: %lld\n", ph->numsegs);
if (ph->numsegs > 6) {
printf("Corrupt segment count in segldr header (%d)\n", ph->numsegs);
return ;
}
for (i = 0; i < ph->numsegs; i++) {
promseg_t *seg = &ph->segs[i];
printf("Segment %d:\n", i);
printf(" Name: %s\n", seg->name);
printf(" Flags: 0x%lx\n", seg->flags);
printf(" Offset: 0x%lx\n", seg->offset);
printf(" Entry: 0x%lx\n", seg->entry);
printf(" Ld Addr: 0x%lx\n", seg->loadaddr);
printf(" True Length: 0x%lx\n", seg->length);
printf(" True sum: 0x%lx\n", seg->sum);
if (seg->flags & SFLAG_COMPMASK) {
printf(" Cmprsd len: 0x%lx\n", seg->length_c);
printf(" Cmprsd sum: 0x%lx\n", seg->sum_c);
}
}
}
/*
* read_flashprom()
* Reads the flash prom binary data out of the specified
* file, checks its checksum, and then converts it into a
* form suitable for burning.
XXX Check the header and make sure that we are not flashing
a IO6prom image into a IP27prom and vice versa.
*/
int
read_flashprom(char *file_name, promhdr_t *ph, char *buffer)
{
ULONG fd, fdwr, cnt, wrcnt;
long err;
int numsegs;
char *curbufptr, *start ;
int numbytes, offset;
__uint64_t cksum, cksum2 ;
unsigned int i, j;
uint length = 0 ;
if (*filename == 0)
return -1 ;
/* Open the file */
if ((err = Open(file_name, OpenReadOnly, &fd)) != 0) {
printf("Cannot open flash prom source file: ");
perror(err, file_name);
return -1;
}
/* Read in the header and make sure it looks kosher before we
* fry the flash prom.
*/
if (err = Read(fd, buffer, PROM_DATA_OFFSET, &cnt)) {
printf("Could not read header structure from file.\n");
Close(fd);
return -1;
}
if (cnt != PROM_DATA_OFFSET) {
printf("Unable to read prom header.\n");
Close(fd);
return -1;
}
bcopy(buffer, (char *)ph, sizeof(promhdr_t)) ;
if (ph->magic != PROM_MAGIC) {
printf("Invalid PROM magic number: 0x%x\n", ph->magic);
Close(fd);
return -1;
}
if (verbose)
dump_promhdr(ph) ;
if (flash_which == CPU_PROM) {
if (strcmp(ph->segs[0].name, "ip27prom")) {
printf("Image file contains a %s segment. Try again with correct image.\n",
ph->segs[0].name);
Close(fd);
return -1;
}
}
if (flash_which == IO_PROM) {
if (strcmp(ph->segs[0].name, "io6prom")) {
printf("Image file contains a %s segment. Try again with correct image.\n",
ph->segs[0].name);
Close(fd);
return -1;
}
}
cksum2 = cksum = 0 ;
length = ph->segs[0].offset ;
numsegs = ph->numsegs ;
for (i = 0; i < numsegs; i++) {
if (ph->segs[i].flags&SFLAG_COMPMASK) {
length += ph->segs[i].length_c;
cksum2 += ph->segs[i].sum_c ;
} else {
length += ph->segs[i].length ;
cksum2 += ph->segs[i].sum ;
}
length = (length + 7) & ~7;
}
if (length != ph->length) {
printf("Total length of prom data does not match header.\n") ;
printf("calculated length = %d, prom header length = %d\n",
length, ph->length) ;
return -1 ;
}
if (length > FLASHPROM_SIZE) {
printf("Flash data is too big and won't fit in Flash PROM.\n");
Close(fd);
return -1;
}
/* Read in the Flash EPROM contents */
length -= ph->segs[0].offset ;
curbufptr = buffer + PROM_DATA_OFFSET ;
start = curbufptr;
numbytes = length ;
if (verbose)
printf(" Reading the entire prom data (%d bytes) ...", numbytes);
while (numbytes) {
unsigned int count = ((numbytes < IO6_FPROM_CHUNK_SIZE) ?
numbytes : IO6_FPROM_CHUNK_SIZE);
if (err = Read(fd, (CHAR*) curbufptr, count, &cnt)) {
printf("Error occurred while reading prom file.\n");
Close(fd);
return -1;
}
if (cnt == 0) {
printf(" \nUnexpected EOF");
printf("after reading %d bytes.\n", numbytes) ;
Close(fd);
return -1;
}
curbufptr += cnt;
numbytes -= cnt;
}
putchar('\n');
/* Checksum the buffer and make sure it seems okay */
numbytes = length ;
cksum = memsum(start, numbytes) ;
if (verbose)
printf(" Checksum results (%x %x).\n", cksum, cksum2);
if (cksum != cksum2) {
printf(" Checksum error (%x %x).\n", cksum, cksum2);
printf(" Aborting command.\n") ;
Close(fd);
return -1;
}
Close(fd);
return 0;
}
static int
check_abort()
{
return 1 ;
}
void
prom_check(fprom_t *f)
{
promhdr_t phdr ;
if (fprom_read(f, 0, (char *)&phdr, sizeof(promhdr_t))) {
printf("Error reading prom header.\n") ;
return ;
}
dump_promhdr(&phdr) ;
}
nasid_t
flash_getnasid(int type)
{
lboard_t lb, *rlb ;
unchar brd_class ;
unchar nsclass = 0 ;
/*
* Calculate widget id. This is used later to get
* bridge base.
*/
w = slot_to_widget(slotid-1) ; /* get the composite widget no */
w &= SLOTNUM_SLOT_MASK ; /* widget number */
if ((SN00) || (CONFIG_12P4I))
/*
* In olden days, on SN00, slots used to have
* dummy numbers like 1 and 11 while in reality
* the widget numbers were 0. Hub directly
* connected to the bridge.
*/
if ((slotid == 1) || (slotid == 11))
w = 0 ;
widgetid = w ;
/* fill a dummy lboard struct and find a match */
brd_class = (flash_which == CPU_PROM) ? KLCLASS_CPU : KLCLASS_IO ;
/*
* This is needed as KEGO's have a different slot class for
* CPU boards.
*/
visit_lboard(get_my_node_slot_class, NULL, (void *)&nsclass) ;
/* slotid can be anything for SN00. */
lb.brd_type = brd_class | slotid ;
lb.brd_module = modid ;
lb.brd_slot = (brd_class == KLCLASS_IO) ?
(SLOTNUM_XTALK_CLASS|slotid) :
(nsclass|slotid) ;
rlb = get_match_lb(&lb, 0) ;
if (rlb) {
flashprom_nasid = rlb->brd_nasid ;
return(rlb->brd_nasid) ;
}
return INVALID_NASID ;
}
/*
* Scans all modules and calls program_all_nodes
*/
int
program_all_proms(int which, promhdr_t *promhdr, char *buffer)
{
graph_error_t graph_err, graph_err1 ;
char tmp_buf[64] ;
char edge_name[64] ;
vertex_hdl_t mod_vhdl, nextmod_vhdl ;
graph_edge_place_t eplace = GRAPH_EDGE_PLACE_NONE ;
#ifdef SN_PDI
strcpy(tmp_buf, "/hw/module/") ;
graph_err = hwgraph_path_lookup(snpdi_rvhdl, tmp_buf,
&mod_vhdl, &remain) ;
#else
strcpy(tmp_buf, "/module/") ;
graph_err = hwgraph_path_lookup(hw_vertex_hdl, tmp_buf,
&mod_vhdl, &remain) ;
#endif
if (graph_err != GRAPH_SUCCESS) {
printf("Error: No Modules in HWGRAPH.\n") ;
return 0 ;
}
do {
#ifdef SN_PDI
graph_err = graph_edge_get_next(pg_hdl,
mod_vhdl,
edge_name,
&nextmod_vhdl, &eplace) ;
#else
graph_err = graph_edge_get_next(prom_graph_hdl,
mod_vhdl,
edge_name,
&nextmod_vhdl, &eplace) ;
#endif
if (graph_err != GRAPH_SUCCESS) {
break ;
}
if (modid_option) {
if (atoi(edge_name) != modid)
continue ;
}
if (program_all_nodes(nextmod_vhdl, edge_name,
promhdr, buffer, which) == FLASH_QUIT)
return FLASH_QUIT ;
} while (graph_err == GRAPH_SUCCESS) ;
return 1 ;
}
int
program_all_nodes(vertex_hdl_t mod_vhdl, char *mod_name,
promhdr_t *promhdr,
char *buffer, int type)
{
graph_error_t graph_err ;
char tmp_buf[64] ;
vertex_hdl_t node_vhdl, next_vhdl, slot_vhdl ;
graph_edge_place_t eplace = GRAPH_EDGE_PLACE_NONE ;
char slot_name[32] ;
klinfo_t *kliptr ;
lboard_t *lb ;
strcpy(tmp_buf, "slot") ;
graph_err = hwgraph_path_lookup(mod_vhdl, tmp_buf,
&slot_vhdl, &remain) ;
if (graph_err != GRAPH_SUCCESS) {
printf("Error: Edge Slot Module %d not found\n", modid) ;
return 0 ;
}
do {
#ifdef SN_PDI
graph_err = graph_edge_get_next(pg_hdl,
slot_vhdl,
slot_name,
&next_vhdl, &eplace) ;
#else
graph_err = graph_edge_get_next(prom_graph_hdl,
slot_vhdl,
slot_name,
&next_vhdl, &eplace) ;
#endif
if (graph_err != GRAPH_SUCCESS) {
break ;
}
lb = (lboard_t *)pg_get_lbl(next_vhdl, INFO_LBL_BRD_INFO) ;
if (lb) {
if (flash_which == CPU_PROM) {
if (KLCLASS(lb->brd_type) != KLCLASS_CPU)
continue ;
}
else if (flash_which == IO_PROM) {
if (KLCLASS(lb->brd_type) != KLCLASS_IO)
continue ;
}
else
continue ;
} else
continue ;
flashprom_nasid = lb->brd_nasid ;
strcpy(slotname, slot_name) ; /* for msg printing */
if (flash_which == CPU_PROM) {
printf("%s CPUPROM in module %s slot %s\n", command,
mod_name, slot_name) ;
if (program_ip27(promhdr, buffer) == 2)
return 2 ;
} else if (flash_which == IO_PROM) {
if (program_all_widgets(lb, promhdr, buffer)
== FLASH_QUIT)
return FLASH_QUIT ;
} else {
printf("program_all_nodes: Unknown type of board %d\n",
type) ;
break ;
}
} while (1) ;
return 1 ;
}
int
program_all_widgets(lboard_t *lb,
promhdr_t *promhdr, char *buffer)
{
int is_xbox = (xbox_nasid_get() != INVALID_NASID);
/* If we are a speedo without an xbox then
* there is no need to program the io prom.
*/
if (SN00 && !is_xbox)
return 1 ;
slotid = SLOTNUM_GETSLOT(lb->brd_slot) ;
w = slot_to_widget(slotid-1) ;
w &= SLOTNUM_SLOT_MASK ;
if ((SN00) || (CONFIG_12P4I))
if ((slotid == 1) || (slotid == 11))
w = 0 ;
widgetid = w ;
/* If we are trying to flash the io prom on the xbox
* flash then it can be only at ONE place (widget 8)
*/
if (SN00 && is_xbox && (widgetid != XBOX_FLASHPROM_WID))
return(1);
if (!is_xbox && (lb->brd_type != KLTYPE_BASEIO))
return 1 ;
get_slotname(lb->brd_slot, slotname) ;
printf("%s IO PROM on module %d slot %s\n",
command, lb->brd_module, slotname);
if (program_io6(promhdr, buffer)==FLASH_QUIT)
return FLASH_QUIT ;
return 1 ;
}
char
confirm(char *type, char *action)
{
char buf[32], ans = 0 ;
char *s;
s = (nasid_option) ? "corresponding to the given nasid" : slotname;
while ((ans!='y') && (ans!='n') && (ans!='q')) {
printf("\nOK to %s the %s PROM in slot %s ? (y|n|q)[y]:",
action, type, s) ;
gets(buf) ;
if (buf[0] == '\0')
ans = 'y' ;
else
ans = buf[0] ;
}
return ans ;
}