1
0
Files
irix-657m-src/irix/cmd/flashio/flashio_sn0.c
2022-09-29 17:59:04 +03:00

2210 lines
53 KiB
C

/***********************************************************************\
* File: flashio_ksn0.c *
* *
* Command to flash Proms on IO6 and cpu boards of SN0 system. *
* Most of this code is borrowed from prom flash driver *
* Header from prom flashprom driver is included below. *
* *
\***********************************************************************/
#ident "$Revision: 1.50 $"
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <unistd.h>
#include <limits.h>
#include <string.h>
#include <strings.h>
#include <signal.h>
#include <fcntl.h>
#include <ftw.h>
#include <sys/stat.h>
#include <sys/attributes.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/param.h>
#include <sys/sbd.h>
#include <sys/mman.h>
#include <sys/file.h>
#include <sys/times.h>
#include <sys/errno.h>
#include <sys/iograph.h>
#include <sys/invent.h>
#define DEF_IP27_CONFIG_TABLE
#include <sys/SN/SN0/ip27config.h>
#include <sys/SN/SN0/IP31.h>
#include <sys/SN/promhdr.h>
#include <sys/SN/prom_names.h>
#include <sys/SN/SN0/arch.h>
#include <sys/SN/router.h>
#include <sys/SN/SN0/hubmd.h>
#include <sys/SN/SN0/hubstat.h>
#include <sys/SN/SN0/sn0drv.h>
#include <sys/SN/fprom.h>
#define CONV_OFF 10000
#define ANYKID -1
#define MAX_HWG_DEPTH 100
#define MAXDEVNAME 1024
#define IOPROM_OFFSET 0xC00000
#define CPU_PROM 0
#define IO_PROM 1
#define MAX_PROM_LENGTH 917504 /* 64K per segment * 14 segments */
extern int errno;
static int flash_copy_ioprom(char *, char *);
static int print_version_ioprom(char *prom_devpath);
static int print_version_cpuprom(char *prom_devpath);
static void erase_promlog_sectors(char *prom_devpath) ;
int hasmetarouter = 0;
int set_prcreqmax = 0;
int promimg_dump(void);
int fprom_write_buffer(fprom_t *, char *, int, char pref_str[16]);
int flash_writeprom(char *prom_devpath, char *prom_image,
size_t prom_mapoffset, int prom_code);
int flash_copy_cpuprom(char *prom_devpath, char *cpufile);
int program_cpu_prom(char *prom_devpath);
int program_io_prom(char *prom_devpath);
int check_if_any_proms_to_flash(char *prom_devpath);
ip27config_t *verify_config_info;
ip27config_t *force_config_info;
unsigned int check_flag ;
unsigned int full_check_flag ;
unsigned int cache_size ;
#define USAGE \
"\nflash [-a] [-c|n] [-d] [-D] [-f] [-F] [-i] [-m module_id] [-o]\n\
[-p dir_name] [-P img_name] [-s slot_id] [-s] [-v]\n\
Flash all appropriate proms with images from /usr/cpu/firmware \n\
If nothing is specified all cpu and io proms in all modules \n\
will be flashed. If just cpu (-c or -n) or io (-i) prom is specified \n\
all of those type will be flashed. If -m is specified all proms \n\
in that module will be flashed. If both the module and slot (-s) are \n\
specified only the prom at that location will be flashed.\n\
-a flashes all proms in parallel rather than in two parallel batches\n\
-d dumps the prom header from a file to standard output\n\
-D dumps the whole prom to a file\n\
-f -F asks for overlay of config information any config info overlay\n\
-o overrides automatic version checking\n\
-p takes images from directory in pathname rather than default\n\
(/usr/cpu/firmware)\n\
-P takes images directly from file specified in full_pathname\n\
requires -n or -c for cpu prom image file, or -i for io prom\n\
image file\n\
-r nn set PrcReqMax to nn\n\
-S flashes proms sequentially rather than in two parallel batches\n\
-v turns on verbose output\n\
-V print currently loaded flash PROM version\n"
/* we'll gather up all the proms we want to flash into two groups
even and odd. With this we can flash in parallel, but not
all at once. This was in case something bad happens when we're
in the middle of a flash all the prom won't be fried. */
typedef struct prom_elem{
char hwg_path_name[256];
struct prom_elem *next;
} prom_list_t;
prom_list_t *even_io_prom = NULL;
prom_list_t *odd_io_prom = NULL;
prom_list_t *even_cpu_prom = NULL;
prom_list_t *odd_cpu_prom = NULL;
int io_prom_turn = 0;
int cpu_prom_turn = 0;
typedef struct child_info_elem {
char *hwg_path_name;
pid_t pid;
int exit_status;
} *child_info_elem_t;
typedef struct child_info_array {
int ne;
int responded;
struct child_info_elem child_info[];
} *child_info_array_t;
child_info_array_t child_info_ap;
#define sanitize_header(ph) \
(((ph)->magic == PROM_MAGIC) && ((ph)->numsegs < PROM_MAXSEGS))
#define MODULE_IDENTIFIER "module/%d/"
#define SLOT_IDENTIFIER "slot/%s/"
#define make_slot_ident(p, s) sprintf(p, SLOT_IDENTIFIER, s);
#define make_module_ident(p, i) sprintf(p, MODULE_IDENTIFIER, i);
int flash_all_cpuproms = 1;
int flash_all_ioproms = 1;
int flash_which= -1;
char flash_slot[32];
int sn0_verbose = 0;
int all_at_once = 0;
int sequential = 0;
int print_version = 0;
int check_for_prom_to_flash = 0;
int check_version = 0;
int from_alarm_sig = 0;
int override_vers = 0;
int dump_mode = 0;
int full_dump_mode = 0;
int flash_module = -1;
int erase_promlog = 0 ;
char path_name[256];
char img_name[256];
uint PrcReqMax;
void _get_all_config_vals(ip27config_t *);
void _get_subset_config_vals(ip27config_t *, int);
int _verify_config_info(ip27config_t *);
int _fill_in_config_info(ip27config_t *, int);
__uint64_t memsum(void *, size_t);
char *flash_read_imagefile(char *prom_image);
#define ADD_IO_PROM \
new_elem = ((prom_list_t *) malloc(sizeof (prom_list_t))); \
strcpy(new_elem->hwg_path_name, canonical_name); \
if ((io_prom_turn % 2) == 0) { \
new_elem->next = even_io_prom; \
even_io_prom = new_elem; \
} \
else { \
new_elem->next = odd_io_prom; \
odd_io_prom = new_elem; \
} \
io_prom_turn++;
#define ADD_CPU_PROM \
new_elem = ((prom_list_t *) malloc(sizeof (prom_list_t))); \
strcpy(new_elem->hwg_path_name, canonical_name); \
if ((cpu_prom_turn % 2) == 0) { \
new_elem->next = even_cpu_prom; \
even_cpu_prom = new_elem; \
} \
else { \
new_elem->next = odd_cpu_prom; \
odd_cpu_prom = new_elem; \
} \
cpu_prom_turn++;
/* walk_fn is called by nftw - in it we will check to see if we have
found a prom node */
/*ARGSUSED*/
int
walk_fn_and_flash_prom(const char *canonical_name,
const struct stat *stat_p,
int obj_type,
struct FTW *ftw_info)
{
inventory_t inv[10];
int i;
int inv_size = 10 * sizeof(inventory_t);
prom_list_t *new_elem;
for (i=0; i<10; i++) {
inv[i].inv_class = -1;
}
if (strstr(canonical_name, "metarouter")) {
hasmetarouter++;
}
if (attr_get(canonical_name, _INVENT_ATTR,
(char *)inv, &inv_size, 0) == -1) {
perror("error");
exit(0);
}
for (i=0; i<10; i++) {
if (inv[i].inv_class == INV_PROM) {
if ((inv[i].inv_type == INV_IO6PROM) &&
(flash_which == IO_PROM)) {
if (flash_module != -1) {
char slot_ident[256], module_ident[256];
make_module_ident(module_ident, flash_module);
if (strlen(flash_slot) > 0) {
make_slot_ident(slot_ident, flash_slot);
if ((strstr(canonical_name, slot_ident) != NULL) &&
(strstr(canonical_name, module_ident) != NULL)) {
ADD_IO_PROM
}
}
else {
if (strstr(canonical_name, module_ident) != NULL) {
ADD_IO_PROM
}
}
}
else {
ADD_IO_PROM
}
}
if ((inv[i].inv_type == INV_IP27PROM) &&
(flash_which == CPU_PROM)) {
if (flash_module != -1) {
char slot_ident[256], module_ident[256];
make_module_ident(module_ident, flash_module);
if (strlen(flash_slot) > 0) {
make_slot_ident(slot_ident, flash_slot);
if ((strstr(canonical_name, slot_ident) != NULL) &&
(strstr(canonical_name, module_ident) != NULL)) {
ADD_CPU_PROM
}
}
else {
if (strstr(canonical_name, module_ident) != NULL) {
ADD_CPU_PROM
}
}
}
else {
ADD_CPU_PROM
}
}
}
}
return 0;
}
static void
sig_chld_handler( void )
{
child_info_elem_t ciep;
int exit_stat;
int i;
pid_t pid;
do {
pid = waitpid ( ANYKID, &exit_stat, WNOHANG );
if ( pid > 0 ) {
/*
* a child process has terminated: record
* its exit status and wait for more
* children to finish flashing.
*/
for ( i = 0; i < child_info_ap->ne; i++ ) {
ciep = &(child_info_ap->child_info[i]);
if ( ciep->pid != pid ) {
continue;
}
ciep->exit_status = WEXITSTATUS ( exit_stat );
child_info_ap->responded++;
}
} else if ( ( pid < 0 ) && ( errno == ECHILD ) &&
( child_info_ap->responded != child_info_ap->ne ) ) {
printf("%d child process(es) did not respond.\n",
child_info_ap->ne - child_info_ap->responded);
child_info_ap->responded = child_info_ap->ne;
}
} while ( pid > 0 );
}
/*
* allow for an alarm call when waiting for input
* from the operator when an error has occurred
* during a flash operation.
*/
static void
sig_alrm_handler()
{
from_alarm_sig++;
}
/* ignore a ctrl-c otherwise if we're in the middle of flashing,
the machine will not boot after reset */
static void
sig_int_handler()
{
printf("\nIf flash is killed in the middle of execution, the machine\n");
printf(" will freeze after it is reset. continuing...\n");
}
int
flashio_sn0(int argc, char **argv)
{
int c;
int count;
int error = 0;
int exit_stat;
int i;
int only_io;
int option = 0;
int size;
pid_t pid;
child_info_elem_t ciep;
prom_list_t *search_elem;
sigset_t emptyset;
sigset_t set;
struct sigaction act;
int exists_prom_to_flash = 0;
act.sa_flags = 0;
act.sa_handler = sig_int_handler;
sigemptyset(&act.sa_mask);
sigaction(SIGINT, &act, NULL);
strcpy (path_name, "");
strcpy (img_name, "");
strcpy (flash_slot, "");
check_flag = 0;
full_check_flag = 0;
force_config_info = ((ip27config_t *) malloc(sizeof(ip27config_t)));
while((c = getopt(argc, argv, "acdeDifFm:nop:P:r:s:SvV")) != -1) {
switch(c){
case 'a':
all_at_once = 1;
break;
case 'c':
if (flash_which != -1) {
fprintf(stderr,
"Error: choice of proms already specified\n");
error++;
break;
}
flash_which = CPU_PROM;
break;
case 'd':
sn0_verbose = 1;
dump_mode = 1;
break;
case 'D':
sn0_verbose = 1;
full_dump_mode = 1;
break;
case 'e':
sn0_verbose = 1;
erase_promlog = 1 ;
break ;
case 'f':
check_flag = 1;
break;
case 'F':
full_check_flag = 1;
break;
case 'i':
if (flash_which != -1) {
fprintf(stderr,
"Error: choice of proms already specified\n");
error++;
break;
}
flash_which = IO_PROM;
break;
case 'm':
flash_module = atoi(optarg);
break;
case 'n':
if (flash_which != -1) {
fprintf(stderr,
"Error: choice of proms already specified\n");
error++;
break;
}
flash_which = CPU_PROM;
break;
case 'o':
override_vers = 1;
break;
case 'p':
strcpy(path_name,optarg);
break;
case 'P':
if ( strncmp( optarg, "/", 1 ) ) {
fprintf(stderr,
"Error: -P requires a pathname to "
"start with a slash (/).\n");
error++;
break;
}
strcpy(img_name,optarg);
break;
case 'r':
set_prcreqmax++;
PrcReqMax = atoi(optarg);
if ((PrcReqMax & ~3) != 0) {
fprintf(stderr,
"PrcReqMax=%#x is out of range 0..3\n",
PrcReqMax);
error++;
}
break;
case 's':
strcpy(flash_slot,optarg);
break;
case 'S':
sequential = 1;
break;
case 'v':
sn0_verbose = 1;
break;
case 'V':
print_version = 1;
break;
case '?':
default:
error++;
break;
}
}
if ( ( strlen(img_name) ) && ( flash_which < 0 ) ) {
fprintf(stderr,"Error: when you specify -P you "
"also have to specify either\n-c or -n, "
"or -i.\n");
error++;
}
if ( (flash_module == -1) && ( strlen(flash_slot) ) ) {
fprintf(stderr, "Error: you specified slot information\n"
"(-s %s) without module number (-m).\n",
flash_slot);
error++;
}
if ( error ) {
fprintf(stderr, USAGE);
return ( error );
}
if (strlen(path_name) == 0) {
if (sn0_verbose)
printf("setting default path_name to %s\n", DEFAULT_PATHNAME);
strcpy(path_name, DEFAULT_PATHNAME);
}
verify_config_info = ((ip27config_t *) malloc(sizeof(ip27config_t)));
if (dump_mode) {
promimg_dump();
return 0;
}
/*
* If erase promlog option is chosen, just erase all promlogs
* in series, and exit.
*/
if (erase_promlog) {
fprintf(stderr,
"WARNING: You need to do initlog at the PROM or sn0log -i in the kernel \n"
"to boot the system next time.\n") ;
/* set flags that help nftw search */
only_io = 0 ;
/* only cpu proms have promlogs. */
flash_which = CPU_PROM ;
/* Gather all hwg path names of proms in 2 lists. */
if (nftw("/hw", walk_fn_and_flash_prom,
MAX_HWG_DEPTH, FTW_PHYS)) {
perror("error in hw graph walk");
return 0 ;
}
/* Flash promlogs in both lists. */
search_elem = even_cpu_prom;
while (search_elem != NULL) {
erase_promlog_sectors(search_elem->hwg_path_name);
search_elem = search_elem->next;
}
search_elem = odd_cpu_prom;
while (search_elem != NULL) {
erase_promlog_sectors(search_elem->hwg_path_name);
search_elem = search_elem->next;
}
/* Dont bother about anything else now. */
return 0;
}
only_io = 0;
if ((flash_which == IO_PROM) || (flash_which == -1)) {
if (flash_which == IO_PROM)
only_io = 1;
flash_which = IO_PROM;
/* easy case - don't need to fix configuration bits */
/* Program the selected boards */
if (nftw("/hw", walk_fn_and_flash_prom, MAX_HWG_DEPTH, FTW_PHYS))
perror("error in hw graph walk");
if (only_io)
goto start_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 (nftw("/hw", walk_fn_and_flash_prom, MAX_HWG_DEPTH, FTW_PHYS))
perror("error in hw graph walk");
/* go ahead before asking the user for input and see if there's
actually going to be anything to flash */
if ((full_check_flag || check_flag) && (! override_vers)) {
char *promdata;
char prom_image[256];
promhdr_t *ph;
sprintf(prom_image, "%s/%s.dump", path_name, CPU_PROM_NAME);
promdata = flash_read_imagefile(prom_image);
ph = (promhdr_t *)promdata;
check_version = CONV_OFF*ph->version + ph->revision;
check_for_prom_to_flash = 1;
search_elem = even_cpu_prom;
while (search_elem != NULL) {
if (program_cpu_prom(search_elem->hwg_path_name))
exists_prom_to_flash = 1;
search_elem = search_elem->next;
}
search_elem = odd_cpu_prom;
while (search_elem != NULL) {
if (program_cpu_prom(search_elem->hwg_path_name))
exists_prom_to_flash = 1;
search_elem = search_elem->next;
}
check_for_prom_to_flash = 0;
if (! exists_prom_to_flash) {
printf("No proms need flashing\n");
exit(0);
}
}
if (full_check_flag) {
_get_all_config_vals(force_config_info);
}
else if (check_flag) {
_get_subset_config_vals(force_config_info, 1);
if (! _verify_config_info(force_config_info)) {
printf("invalid configuration values\n");
return 1;
}
}
else ;
start_flash:
count = io_prom_turn + cpu_prom_turn;
if ( count ) {
if ( !sequential ) {
/*
* set up the interrupt handler
* to keep track of the completion
* of the child processes.
*/
act.sa_flags = 0;
act.sa_handler = sig_chld_handler;
sigemptyset(&act.sa_mask);
sigaddset(&act.sa_mask, SIGCHLD);
sigaction(SIGCHLD, &act, NULL);
sigemptyset(&set);
sigemptyset(&emptyset);
sigaddset(&set, SIGCHLD);
sigprocmask(SIG_BLOCK, &set, NULL);
}
size = sizeof ( struct child_info_elem ) * ( count );
size += sizeof ( struct child_info_array );
act.sa_flags = 0;
act.sa_handler = sig_alrm_handler;
sigemptyset(&act.sa_mask);
sigaction(SIGALRM, &act, NULL);
}
wait_for_children:
if ( count ) {
child_info_ap = ( struct child_info_array * ) calloc (1, size );
if ( !child_info_ap ) {
printf("unable to obtain memory for child_info_array.\n");
return 1;
}
}
/* okay we have gathered up the proms we need to flash into two
groups flash the even then the odd ones */
search_elem = even_io_prom;
while (search_elem != NULL) {
program_io_prom(search_elem->hwg_path_name);
search_elem = search_elem->next;
}
search_elem = even_cpu_prom;
while (search_elem != NULL) {
program_cpu_prom(search_elem->hwg_path_name);
search_elem = search_elem->next;
}
if ( !all_at_once && !sequential ) {
while ( ( child_info_ap->ne - child_info_ap->responded ) > 0 ) {
sigsuspend(&emptyset);
}
}
search_elem = odd_io_prom;
while (search_elem != NULL) {
program_io_prom(search_elem->hwg_path_name);
search_elem = search_elem->next;
}
search_elem = odd_cpu_prom;
while (search_elem != NULL) {
program_cpu_prom(search_elem->hwg_path_name);
search_elem = search_elem->next;
}
if ( !sequential ) {
while ( (child_info_ap->ne - child_info_ap->responded) > 0 ) {
sigsuspend(&emptyset);
}
}
/*
* all child process have finished: take stock of each
* of their exit status and if one or more completed with
* an error, provide the user with intervention options.
*/
error = 0;
for ( i = 0; i < child_info_ap->ne; i++ ) {
ciep = &(child_info_ap->child_info[i]);
if ( ciep->exit_status ) {
if ( !error ) {
printf( "\nAn error was encountered "
"during programming the "
"following PROM(s):\n");
}
printf( "%s> Error programming PROM: "
"errno: %d.\n", ciep->hwg_path_name,
ciep->exit_status );
error++;
}
}
if ( !error ) {
return ( 0 );
}
/*
* one or more errors have been encountered.
*/
printf("\nenter \"[r]etry\" or \"[i]gnore\" "
"to continue: [r] ");
option = 0;
while ( !option ) {
alarm ( 60 );
option = getchar();
alarm ( 0 );
if ( from_alarm_sig ) {
from_alarm_sig = 0;
option = 'i';
printf("\ntimed out after 60 seconds: "
"[i]gnore assumed.\n");
} else if ( option != '\n' ) {
alarm ( 60 );
while ( getchar() != '\n' );
alarm ( 0 );
} else {
option = 'r';
}
switch ( option ) {
case 'r':
free ( child_info_ap );
goto wait_for_children;
case 'i':
break;
default:
printf("\nYour selection %c is not valid.\n",
option);
option = 0;
continue;
}
break;
}
free ( child_info_ap );
return ( 0 );
}
int
program_io_prom(char *prom_devpath) {
char prom_image[256];
if (print_version) {
return print_version_ioprom(prom_devpath);
}
if (full_dump_mode) {
sprintf(prom_image, "%s/%s.dump", path_name, IO_PROM_NAME);
if (sn0_verbose)
printf("going to read from %s and write to %s\n",
prom_devpath,prom_image);
return flash_copy_ioprom(prom_devpath, prom_image);
}
if (strlen(img_name) > 0)
sprintf(prom_image, "%s", img_name);
else
sprintf(prom_image, "%s/%s", path_name, IO_PROM_NAME);
return flash_writeprom(prom_devpath, prom_image,
IOPROM_OFFSET, FPROM_DEV_IO6_P1);
}
int
program_cpu_prom(char *prom_devpath) {
char prom_image[256];
if (check_for_prom_to_flash) {
return check_if_any_proms_to_flash(prom_devpath);
}
if (print_version) {
return print_version_cpuprom(prom_devpath);
}
if (full_dump_mode) {
sprintf(prom_image, "%s/%s.dump", path_name, CPU_PROM_NAME);
if (sn0_verbose)
printf(" going to read from %s and write to %s\n",
prom_devpath,prom_image);
return flash_copy_cpuprom(prom_devpath, prom_image);
}
if (strlen(img_name) > 0)
sprintf(prom_image, "%s", img_name);
else
sprintf(prom_image, "%s/%s", path_name, CPU_PROM_NAME);
return flash_writeprom(prom_devpath, prom_image,
0, FPROM_DEV_HUB);
}
void
dump_promseg(promseg_t *seg, char pref_str[16])
{
if (sn0_verbose) {
printf("%s Name: %s\n", pref_str, seg->name);
printf("%s Flags: 0x%llx\n", pref_str, seg->flags);
printf("%s Offset: 0x%llx\n", pref_str, seg->offset);
printf("%s Entry: 0x%llx\n", pref_str, seg->entry);
printf("%s Ld Addr: 0x%llx\n", pref_str, seg->loadaddr);
printf("%s True Length: 0x%llx\n", pref_str, seg->length);
printf("%s True sum: 0x%llx\n", pref_str, seg->sum);
if (seg->flags & SFLAG_COMPMASK) {
printf("%s Cmprsd len: 0x%llx\n", pref_str, seg->length_c);
printf("%s Cmprsd sum: 0x%llx\n", pref_str, seg->sum_c);
}
}
}
void
dump_promhdr(promhdr_t *ph, char pref_str[16])
{
int i;
if (sn0_verbose) {
printf("%sPROM Header contains:\n", pref_str);
printf("%s Magic: 0x%llx\n", pref_str, ph->magic);
printf("%s Version: %lld.%lld\n", pref_str, ph->version, ph->revision);
printf("%s Length: 0x%llx\n", pref_str, ph->length);
printf("%s Segments: %lld\n", pref_str, ph->numsegs);
if (ph->numsegs > 6) {
printf("%serror: corrupt segment count in segldr header (%lld)\n",
pref_str, ph->numsegs);
return ;
}
for (i = 0; i < ph->numsegs; i++) {
printf("%sSegment %d:\n", pref_str, i);
dump_promseg(&ph->segs[i], pref_str);
}
}
}
void *
map_prom(char *path, off_t offset, size_t size)
{
void *mapaddr;
int fd;
char errbuf[MAXDEVNAME];
fd = open(path, O_RDWR);
if (fd < 0 ) {
sprintf(errbuf, "Opening %s", path);
perror(errbuf);
if (getuid() != 0)
printf(" try executing as superuser\n");
exit ( EACCES );
}
mapaddr = mmap(0, size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, offset);
if (mapaddr == (void *)-1){
sprintf(errbuf, "Mapping %s file", path);
perror(errbuf);
close(fd);
return 0;
}
return mapaddr;
}
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, "") ;
}
char *prom_types[] = {"Hub", "P0 IO6", "P1 IO6"};
int
flash_readprom(char *prom_devpath, char *promdata, size_t prom_mapoffset,
size_t prom_size, int prom_code, int read_verbose, char pref_str[16])
{
int retval;
fprom_t f;
promhdr_t *ph;
int segnum;
int r,i;
int manu_code, dev_code;
ip27config_t *new_config_info;
f.base = map_prom(prom_devpath, prom_mapoffset, prom_size);
if (!f.base)
return 0;
/*
* afn and aparm are abort function and its args.
* They are null for now.
*/
f.afn = 0;
for (i=0;i<8;i++) {
f.aparm[i] = 0;
}
f.dev = prom_code;
r = fprom_probe(&f, &manu_code, &dev_code);
if (r < 0 && r != FPROM_ERROR_DEVICE) {
printf("Error initializing %s PROM: %s\n",
prom_types[prom_code], fprom_errmsg(r));
return 0 ;
}
if (r == FPROM_ERROR_DEVICE)
printf("*** Warning: Unknown manufacture/device code\n");
if (prom_code == FPROM_DEV_HUB) {
/*
* CPU Prom has no special segments or any such info.
* Just read the prom into the buffer,
* and return
*/
retval = fprom_read(&f, 0, promdata, prom_size);
if ((sn0_verbose && read_verbose) || print_version) {
new_config_info = (ip27config_t *)
(promdata + CONFIG_INFO_OFFSET);
printf(" Prom version %d.%d\n", new_config_info->pvers_vers,
new_config_info->pvers_rev);
}
return (retval == FPROM_ERROR_NONE) ? prom_size : 0 ;
}
/*
* Sequence of operation for the IOprom case.
* - First read prom header and check its sanity.
* -
* First read in the prom header.
*/
retval = fprom_read(&f, 0, promdata, sizeof(promhdr_t));
if (retval != FPROM_ERROR_NONE) {
printf("Error in reading Flash prom retval %d\n", retval);
return 0;
}
/*
* Now scan each segment, and read in the individual segments.
*/
ph = (promhdr_t *)promdata;
if (sanitize_header(ph) == 0) {
printf("Invalid Header \n");
dump_promhdr(ph, "");
return 0;
}
if ((sn0_verbose && read_verbose) || print_version)
printf(" Prom version %lld.%lld\n", ph->version, ph->revision);
for (segnum = 0; segnum < ph->numsegs; segnum++) {
promseg_t *seg;
seg = &ph->segs[segnum];
if (sn0_verbose && read_verbose) {
printf("%s Segment \n", pref_str);
dump_promseg(seg, pref_str);
}
retval = fprom_read(&f, seg->offset,
&promdata[seg->offset], seg->length);
if (retval != FPROM_ERROR_NONE) {
printf("Error in reading Segment retval %d\n", retval);
return 0;
}
}
return ph->length;
}
char *
flash_read_imagefile(char *prom_image)
{
struct stat buf;
char *promdata;
int fd;
/*
* Check if the data file exists.
*/
if (stat(prom_image, &buf) < 0){
printf("File %s does not exist\n", prom_image);
return 0;
}
if (!S_ISREG(buf.st_mode)){
printf("File %s is not a regular file\n", prom_image);
return 0;
}
promdata = malloc(FPROM_SIZE);
if (!promdata) {
printf("Unable to allocate Memory size %d\n", FPROM_SIZE);
}
/*
* Read in the prom imgage.
*/
fd = open(prom_image, 0);
if (fd < 0) {
perror("open");
return 0;
}
read(fd, promdata, FPROM_SIZE);
close(fd);
return promdata;
}
int
flash_writeprom(char *prom_devpath, char *prom_image,
size_t prom_mapoffset, int prom_code)
{
child_info_elem_t ciep;
fprom_t f;
int rtn_val = 0;
promhdr_t *ph;
int r,i;
int manu_code, dev_code;
char *promdata;
char *in_core_promdata;
int promlen;
ip27config_t *config_info;
ip27config_t *new_config_info;
int pid;
int compare_bytes, pref_index;
char pref_str[16];
char locate_str[64];
__uint64_t old_sum, new_sum;
int version, in_version;
int flash_count;
hubstat_t *buf;
int fd;
char *p;
char hub_devpath[256];
int pimm_psc;
strcpy(pref_str, "");
pid = -17;
if (! sequential) {
switch ((pid = fork())) {
case 0:
/* child process - will go ahead and do the work */
break;
case -1:
if (sn0_verbose)
printf("could not complete fork - all work being done by parent\n");
break;
default:
/*
* we have a child process, save its pid and
* return with the parent to flash next prom.
*/
ciep = &(child_info_ap->child_info[child_info_ap->ne]);
ciep->hwg_path_name = prom_devpath;
ciep->pid = pid;
ciep->exit_status = ECHILD;
child_info_ap->ne++;
return 0;
}
} else {
ciep = &(child_info_ap->child_info[child_info_ap->ne]);
ciep->hwg_path_name = prom_devpath;
ciep->exit_status = ECHILD;
child_info_ap->ne++;
}
/* we want to identify all the printfs with a unique preface */
pref_str[0] = 'm';
pref_index = 1;
if (strstr(prom_devpath, "module") != NULL) {
strcpy(locate_str, strstr(prom_devpath, "module"));
}
i=7;
while (i<strlen(locate_str)) {
pref_str[pref_index] = locate_str[i];
pref_index ++;
i++;
if (locate_str[i] == '/')
break;
}
pref_str[pref_index] = ' ';
pref_index ++;
if (strstr(prom_devpath, "slot") != NULL) {
strcpy(locate_str, strstr(prom_devpath, "slot"));
}
i=5;
while (i<strlen(locate_str)) {
pref_str[pref_index] = locate_str[i];
pref_index ++;
i++;
if (locate_str[i] == '/')
break;
}
pref_str[pref_index] = ':';
pref_str[pref_index+1] = ' ';
pref_str[pref_index+2] = '\0';
promdata = flash_read_imagefile(prom_image);
new_sum = memsum((void *)(promdata+PROM_DATA_OFFSET), 891584)%256;
if (prom_code == FPROM_DEV_HUB) {
ph = (promhdr_t *)promdata;
if (strcmp(ph->segs[0].name, "ip27prom") != 0) {
printf("%serror: attempted flash of cpu prom with something other than a cpu prom image\n",pref_str);
rtn_val = EINVAL;
goto end_no_verify_flash_write;
}
new_config_info = (ip27config_t *) (promdata + PROM_DATA_OFFSET + CONFIG_INFO_OFFSET);
old_sum = memsum((void *)(new_config_info),
sizeof(ip27config_t))%256;
in_core_promdata = malloc(FPROM_SIZE);
if (!in_core_promdata) {
printf("%sUnable to allocate Memory size %d\n", pref_str, FPROM_SIZE);
}
bzero(in_core_promdata, FPROM_SIZE);
flash_readprom(prom_devpath, in_core_promdata,
0, FPROM_SIZE, FPROM_DEV_HUB, 0, pref_str);
config_info = (ip27config_t *) (in_core_promdata + CONFIG_INFO_OFFSET);
in_version = CONV_OFF*config_info->pvers_vers + config_info->pvers_rev;
config_info->flash_count = config_info->flash_count + 1;
config_info->pvers_vers = new_config_info->pvers_vers;
config_info->pvers_rev = new_config_info->pvers_rev;
flash_count = config_info->flash_count;
if ((full_check_flag) || (check_flag)) {
bcopy(force_config_info, new_config_info,
sizeof(ip27config_t));
} else {
bcopy(config_info, new_config_info,
sizeof(ip27config_t));
/* here try to get the node info to check for ip31 boards */
buf = (hubstat_t *)malloc(sizeof(hubstat_t));
strcpy(hub_devpath, prom_devpath);
if((p = strstr(hub_devpath,"prom")) == NULL)
goto cont;
strcpy(p,"hub/mon");
fd = open(hub_devpath, O_RDONLY);
if(fd <= 0)
goto cont;
if((pimm_psc = ioctl(fd, SN0DRV_GET_PIMM_PSC)) <0) {
;
}
else
{
if(pimm_psc != PIMM_NOT_PRESENT)
{
/* load the config bits from table */
ip31_get_config(pimm_psc, new_config_info);
}
}
}
cont:
if (set_prcreqmax == 0) {
PrcReqMax = 3;
set_prcreqmax++;
}
if (set_prcreqmax) {
new_config_info->r10k_mode =
(new_config_info->r10k_mode & ~(3 << 7))
| (PrcReqMax << 7);
}
new_config_info->check_sum_adj = 0;
new_sum = memsum((void *)(new_config_info),
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) {
new_config_info->check_sum_adj = (uint) (old_sum - new_sum);
}
else {
new_config_info->check_sum_adj = (uint) (256 - (new_sum - old_sum));
}
new_config_info->check_sum_adj = new_config_info->check_sum_adj & 0xff;
bcopy(new_config_info, verify_config_info,
sizeof(ip27config_t));
new_sum = memsum((void *)(new_config_info),
sizeof(ip27config_t))%256;
if (sn0_verbose)
printf("%sfreq cpu %lld freq hub %lld sn0/0 bit %d\n", pref_str,
new_config_info->freq_cpu,
new_config_info->freq_hub,
new_config_info->mach_type);
}
else {
ph = (promhdr_t *)promdata;
if (strcmp(ph->segs[0].name, "io6prom") != 0) {
printf("%serror: attempted flash of io prom with something other than a io prom image\n",pref_str);
rtn_val = EINVAL;
goto end_no_verify_flash_write;
}
in_core_promdata = malloc(FPROM_SIZE);
if (!in_core_promdata) {
printf("%sUnable to allocate Memory size %d\n", pref_str, FPROM_SIZE);
}
bzero(in_core_promdata, FPROM_SIZE);
flash_readprom(prom_devpath, in_core_promdata,
IOPROM_OFFSET, FPROM_SIZE,
FPROM_DEV_IO6_P1, 0, pref_str);
ph = (promhdr_t *)in_core_promdata;
in_version = CONV_OFF*ph->version + ph->revision;
}
ph = (promhdr_t *)promdata;
version = CONV_OFF*ph->version + ph->revision;
/* the old revision numbering scheme was broke. For version
* 3.2 day they cheated and just used one number 320 so we need
* to check for this case and make sure we still flash even
* if the version is something like 320.320 I suppose at some
* we might need to be careful if the prom version numbering
* gets above 100.
*/
if (in_version > 100*CONV_OFF)
goto skip_check;
if ((in_version == version) && (! override_vers)) {
printf("NOTE: %sprom file version %d.%d is the same as "
"current version %d.%d: prom not flashed\n",
pref_str, version/CONV_OFF, version%CONV_OFF,
in_version/CONV_OFF, in_version%CONV_OFF);
rtn_val = 0;
goto end_no_verify_flash_write;
}
if ((in_version >= version) && (! override_vers)) {
printf("%sprom file version %d.%d is older than current "
"version %d.%d: prom not flashed\n",
pref_str, version/CONV_OFF, version%CONV_OFF,
in_version/CONV_OFF, in_version%CONV_OFF);
rtn_val = 0;
goto end_no_verify_flash_write;
}
skip_check:;
if (prom_code == FPROM_DEV_HUB)
printf("%sFlashed this prom %d times\n", pref_str, flash_count);
if (!promdata) {
rtn_val = EINVAL;
goto end_flash_write;
}
if (sn0_verbose) {
printf("%sFlashing prom data in file %s\n", pref_str, prom_image);
printf("%s to device %s\n", pref_str, prom_devpath);
}
if (prom_code == FPROM_DEV_HUB)
f.base = map_prom(prom_devpath, prom_mapoffset, 8*FPROM_SIZE);
else
f.base = map_prom(prom_devpath, prom_mapoffset, FPROM_SIZE);
if (!f.base) {
rtn_val = ENODEV;
goto end_no_verify_flash_write;
}
/*
* Check the number of segments in the prom, and flash
* accordingly.
* Note that the prom header starts from the beginning of the
* file. So, pointing ph to promdata should be sufficient
* to get to the prom header.
*/
if ((ph->length - ph->segs[0].offset) > MAX_PROM_LENGTH) {
printf("%serror: prom too large %lld - programming failed.\n", pref_str,ph->length);
rtn_val = EFBIG;
goto end_flash_write;
}
/*
* afn and aparm are abort function and its args.
* They are null for now.
*/
f.afn = 0;
for (i=0;i<8;i++) {
f.aparm[i] = 0;
}
f.dev = prom_code;
r = fprom_probe(&f, &manu_code, &dev_code);
if (r < 0 && r != FPROM_ERROR_DEVICE) {
printf("%sError initializing IO6 PROM: %s\n", pref_str,
fprom_errmsg(r));
goto done;
}
if (sn0_verbose) {
printf("%s> Manufacturer code: 0x%02x\n", pref_str, manu_code);
printf("%s> Device code : 0x%02x\n", pref_str, dev_code);
}
if (r == FPROM_ERROR_DEVICE) {
printf("%s*** Warning: Unknown manufacture/device code\n", pref_str);
rtn_val = EINVAL;
goto end_flash_write;
}
printf("%s> Erasing code sectors (15 to 20 seconds)\n", pref_str);
if ((r = fprom_flash_sectors(&f, 0x3fff)) < 0) {
printf("%sError erasing remote PROM: %s\n", pref_str, fprom_errmsg(r));
goto done;
}
printf("%s> Erasure complete and verified\n", pref_str);
dump_promhdr(ph, pref_str);
/*
* Program the PROM
*/
printf("%s> Programming %s PROM\n", pref_str, prom_types[prom_code]);
promlen = ph->length;
if (prom_code == FPROM_DEV_HUB) {
promdata += PROM_DATA_OFFSET;
promlen = promlen - PROM_DATA_OFFSET;
}
new_sum = memsum((void *)(promdata), promlen)%256;
printf("%s> Writing %d bytes of data ...\n", pref_str, promlen);
if (!(fprom_write_buffer(&f, promdata, promlen, pref_str)))
goto done ;
if (sn0_verbose)
printf("\n");
printf("%s> Programmed and verified\n", pref_str);
rtn_val= 0;
goto end_flash_write;
done:
printf("%s> PROM programming completed with error.\n", pref_str);
rtn_val = EINTR;
end_flash_write:
if (prom_code == FPROM_DEV_HUB) {
bzero(in_core_promdata, FPROM_SIZE);
flash_readprom(prom_devpath, in_core_promdata,
0, FPROM_SIZE, FPROM_DEV_HUB,
1, pref_str);
config_info = (ip27config_t *) (in_core_promdata + CONFIG_INFO_OFFSET);
printf("%sVerifying:\n",pref_str);
printf("%s cpu speed %lld\n",
pref_str, config_info->freq_cpu);
printf("%s hub speed %lld\n", pref_str,
config_info->freq_hub);
printf("%s SN0/0 bit %d\n", pref_str,
config_info->mach_type);
if (bcmp(verify_config_info, config_info,
sizeof(ip27config_t)) == 0) {
printf("%s other configuration information also verified\n", pref_str);
}
else {
printf("\n%sWarning: configuration information was not\n", pref_str);
printf("%s properly set - reflash recommended\n", pref_str);
}
/* compare only valid sector - not prom log
subtract out possibly different header and config info */
compare_bytes = promlen - CONFIG_INFO_OFFSET - sizeof(ip27config_t);
if (bcmp(in_core_promdata + CONFIG_INFO_OFFSET +
sizeof(ip27config_t),
promdata + CONFIG_INFO_OFFSET +
sizeof(ip27config_t),
compare_bytes)
== 0) {
printf("%sCompare of file data to in core prom data succeeded\n", pref_str);
}
else {
printf("\n%sCompare of file data to in core prom data failed\n", pref_str);
printf("%s reflash recommended\n", pref_str);
#ifdef ZERO
{char *core; core =(char *)17; core[0] = '\0';}
{ int fd;
fd = open("data-in", O_WRONLY|O_CREAT);
write(fd, in_core_promdata + CONFIG_INFO_OFFSET, compare_bytes);
close(fd);
fd = open("data-file", O_WRONLY|O_CREAT);
write(fd, promdata + CONFIG_INFO_OFFSET, compare_bytes);
close(fd);
}
#endif
}
}
else {
in_core_promdata = malloc(FPROM_SIZE);
bzero(in_core_promdata, FPROM_SIZE);
flash_readprom(prom_devpath, in_core_promdata,
IOPROM_OFFSET, FPROM_SIZE,
FPROM_DEV_IO6_P1, 1, pref_str);
if (bcmp(in_core_promdata, promdata, promlen) == 0) {
printf("%sCompare of file data to in core data succeeded\n", pref_str);
}
else {
printf("%sCompare of file data to core data failed\n", pref_str);
}
}
end_no_verify_flash_write:
if (pid == 0)
exit(rtn_val);
if ( sequential ) {
ciep = &(child_info_ap->child_info[child_info_ap->responded++]);
ciep->exit_status = rtn_val;
}
return rtn_val;
}
int
check_if_any_proms_to_flash(char *prom_devpath)
{
char *in_core_promdata;
ip27config_t *config_info;
int in_version;
in_core_promdata = malloc(FPROM_SIZE);
if (!in_core_promdata) {
printf("Unable to allocate Memory size %d\n", FPROM_SIZE);
}
bzero(in_core_promdata, FPROM_SIZE);
flash_readprom(prom_devpath, in_core_promdata,
0, FPROM_SIZE, FPROM_DEV_HUB, 0, "");
config_info = (ip27config_t *) (in_core_promdata + CONFIG_INFO_OFFSET);
in_version = CONV_OFF*config_info->pvers_vers + config_info->pvers_rev;
if (in_version < check_version)
return 1;
else
return 0;
}
int
print_version_cpuprom(char *prom_devpath)
{
char *promdata;
int length;
promdata = malloc(FPROM_SIZE);
if (!promdata) {
printf("Unable to allocate Memory size %d\n", FPROM_SIZE);
}
bzero(promdata, FPROM_SIZE);
printf("Info for prom at %s\n", prom_devpath);
length = flash_readprom(prom_devpath, promdata,
0, FPROM_SIZE, FPROM_DEV_HUB, 1, "");
if (length) {
;
} else {
printf("Failed to read prom data.. \n");
return EIO;
}
return 0;
}
int
flash_copy_cpuprom(char *prom_devpath, char *cpufile)
{
struct stat buf;
int fd;
char *promdata;
int length;
/*
* Check if the data file exists.
*/
if (stat(cpufile, &buf) > 0){
if (!S_ISREG(buf.st_mode)){
printf("File %s is not a regular file\n", cpufile);
return EIO;
}
printf("File %s already exists. Overwriting the file\n",
cpufile);
}
fd = creat(cpufile, 0644);
if (fd < 0 ) {
printf("Unable to create file %s", cpufile);
perror("");
return errno;
}
promdata = malloc(FPROM_SIZE);
if (!promdata) {
printf("Unable to allocate Memory size %lld\n", buf.st_size);
}
bzero(promdata, FPROM_SIZE);
length = flash_readprom(prom_devpath, promdata,
0, FPROM_SIZE, FPROM_DEV_HUB, 0, "");
if (length) {
write(fd, promdata, length);
} else {
printf("Failed to read prom data.. \n");
}
close(fd);
return 0;
}
int
flash_write_cpuprom(char *prom_devpath, char *prom_image)
{
return flash_writeprom(prom_devpath, prom_image,
0, FPROM_DEV_HUB);
}
/*
* read contents of the flash prom and print the header info
*/
static int
print_version_ioprom(char *prom_devpath)
{
char *promdata;
int length;
promdata = malloc(FPROM_SIZE);
if (!promdata) {
printf("Unable to allocate Memory size %d\n", FPROM_SIZE);
}
bzero(promdata, FPROM_SIZE);
printf("Info for prom at %s\n", prom_devpath);
length = flash_readprom(prom_devpath, promdata,
IOPROM_OFFSET, FPROM_SIZE, FPROM_DEV_IO6_P1, 1, "");
if (length) {
;
} else {
printf("Unable to read Prom data..\n");
return EIO;
}
return 0;
}
/*
* read contents of the flash prom given by the path 'prompath
* and place the data in the given buffer.
* This routine zeroes the buffer before copying.
* buflen should be greater than the size reported
* by the prom header.
*/
static int
flash_copy_ioprom(char *prom_devpath, char *prom_image)
{
struct stat buf;
char *promdata;
int fd;
int length;
/*
* Check if the data file exists.
*/
if (stat(prom_image, &buf) > 0){
if (!S_ISREG(buf.st_mode)){
printf("File %s is not a regular file\n", prom_image);
return EIO;
}
printf("File %s already exists. Overwriting the file\n",
prom_image);
}
fd = creat(prom_image, 0644);
if (fd < 0 ) {
printf("Unable to create file %s\n", prom_image);
perror("");
return errno;
}
promdata = malloc(FPROM_SIZE);
if (!promdata) {
printf("Unable to allocate Memory size %lld\n", buf.st_size);
}
bzero(promdata, FPROM_SIZE);
length = flash_readprom(prom_devpath, promdata,
IOPROM_OFFSET, FPROM_SIZE, FPROM_DEV_IO6_P1, 0, "");
if (length) {
write(fd, promdata, length);
} else {
printf("Unable to read Prom data..\n");
return EIO;
}
close(fd);
return 0;
}
/*
* Flash the specified prom paths.
* if prom_devpath is null, then flash all io proms in the system.
*/
int
flash_write_ioprom(char *prom_devpath, char *prom_image)
{
return flash_writeprom(prom_devpath, prom_image,
IOPROM_OFFSET, FPROM_DEV_IO6_P1);
}
#define PRINT_ADDRESS 0x8000
#define PRINT_DOT 0x1000
int
fprom_write_buffer(fprom_t *f, char *buffer, int count, char pref_str[16])
{
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)
if (sn0_verbose)
printf("\n") ;
first = 0 ;
if (sn0_verbose)
printf("%s> %5lx/%05lx ",pref_str, done, count) ;
if (n == 0)
break ;
pra += PRINT_ADDRESS ;
}
if ((r = fprom_write(f, dst_off, src, n)) < 0) {
printf("\n%s> Error programming PROM: %s\n", pref_str,
fprom_errmsg(r));
printf("%sbase = %lx, off = %llx, src = %x\n", pref_str,
f->base, dst_off, src) ;
return 0 ;
}
if (done >= prd) {
if (sn0_verbose)
printf(".") ;
prd += PRINT_DOT ;
}
src += n;
dst_off += n;
done += n;
}
return 1 ;
}
/*
* Trivial function to dump the header of a prom image.
* Used primarily for checking out a prom image.
*/
int
promimg_dump(void)
{
int fd;
promhdr_t ph;
/*
* Dump the prom headers in the given file.
* Primarily a debugging tool
*/
if (strlen(img_name) < 1) {
printf("specify full pathname with -P\n");
return 1;
}
fd = open(img_name, 0);
if (fd < 0 ) {
perror("open");
return errno;
}
/*
* Opened the file. Now read the required header, and dump
*/
if (read(fd, (char *)&ph, sizeof(promhdr_t)) < sizeof(promhdr_t)){
perror("read");
return errno;
}
dump_promhdr(&ph, "");
close(fd);
return 0;
}
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;
}
/* returns 1 if there's enough info in the header to set the entire
configuration header - else return 0 */
int
_verify_config_info(ip27config_t *config_info)
{
uint cache_code;
int i;
for (i=0; i<NUMB_IP27_CONFIGS; i++) {
cache_code = ip27config_table[i].r10k_mode;
/* SCS in bit 16, 17, and 18 */
cache_code = cache_code&0x00070000;
cache_code = cache_code >> IP27C_R10000_SCS_SHFT;
/* we have the SCS code convert it to MB (what user entered) */
if (cache_code == 1)
cache_code = 1;
if (cache_code == 3)
cache_code = 4;
if ((cache_size == cache_code) &&
(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_subset_config_vals(ip27config_t *config_info, int from_where)
{
int input_val;
char input_str[8];
config_info->freq_cpu = (__uint64_t) IP27C_MHZ(195);
printf("Enter CPU frequency (MHZ): [195] ");
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_KHZ(97500);
printf("Enter Hub frequency (MHZ): [97.5] ");
gets(input_str);
if (strlen(input_str) > 0) {
config_info->freq_hub = (__uint64_t) parse_megahertz(input_str);
}
config_info->mach_type = (uint) 0;
printf("Enter machine type (0) SN0 (1) Sn00: [0] ");
gets(input_str);
if (strlen(input_str) > 0) {
input_val = atoi(input_str);
config_info->mach_type = (uint) input_val;
}
config_info->check_sum_adj = (uint) 0;
if (from_where) {
cache_size = 4;
printf("Enter cache size (in MBs): [4] ");
gets(input_str);
if (strlen(input_str) > 0)
cache_size = atoi(input_str);
}
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);
}
void
_get_all_config_vals(ip27config_t *config_info)
{
int kseg0ca, devnum, cprt, per, prm, scd, scbs, me;
int scs, sccd, scct, scce, odsc, odsys, ctm;
int input_val;
char input_str[8];
re_enter:
_get_subset_config_vals(config_info, 0);
config_info->freq_rtc = (__uint64_t) IP27C_KHZ(IP27_RTC_FREQ);
printf("\nEnter the RTC frequency (MHZ): [1.25] ");
gets(input_str);
if (strlen(input_str) > 0) {
config_info->freq_rtc = (__uint64_t) parse_megahertz(input_str);
}
printf("Mode bit setting definitions may be found in the MIPS R10000 manual\n\n");
/* set up best guess defaults for bits we're going to request */
scd = 3;
scs = 3;
sccd = 2;
scct = 9;
/* put in values for all fixed settings */
kseg0ca = 5;
devnum = cprt = per = 0;
prm = 3;
scbs = 1;
me = 1;
scce = odsc = odsys = ctm =0;
/* most of these settings are fixed - no need to ask the user
uncomment out in future if need arises
printf("Enter the mode settings for the:\n");
printf(" Kseg0CA cache algorithm (KSEG0CA): ");
gets(input_str);
kseg0ca = atoi(input_str);
printf(" processor DevNum (DEVNUM): ");
gets(input_str);
devnum = atoi(input_str);
printf(" Coherent Processor Request Target (CPRT): ");
gets(input_str);
cprt = atoi(input_str);
printf(" Processor Eliminate Request (PER): ");
gets(input_str);
per = atoi(input_str);
printf(" Processor Request Maximum (PRM): ");
gets(input_str);
prm = atoi(input_str);
*/
printf(" PClk to SysClk ratio (in decimal) (SCD): [%d] ", scd);
gets(input_str);
if (strlen(input_str) > 0)
scd = atoi(input_str);
/* most of these settings are fixed - no need to ask the user
uncomment out in future if need arises
printf(" Secondary Cache Block Size (SCBS): ");
gets(input_str);
scbs = atoi(input_str);
printf(" Correction Method for the Secondary Cache: ");
gets(input_str);
scce = atoi(input_str);
printf(" Memory System Endians (ME): ");
gets(input_str);
me = atoi(input_str);
*/
printf(" Secondary Cache Code (e.g., 1 for 1MB, 3 for 4MB) (SCS): [%d] ", scs);
gets(input_str);
if (strlen(input_str) > 0)
scs = atoi(input_str);
printf(" PClk to SCClk ratio (SCCD): [%d] ", sccd);
gets(input_str);
if (strlen(input_str) > 0)
sccd = atoi(input_str);
printf(" alignment of SysClk to internal Sec Cache Clock (SCCT): [0x%x] ", scct);
gets(input_str);
if (strlen(input_str) > 0)
scct = (int) strtoul(input_str, NULL, 16);
/* most of these settings are fixed - no need to ask the user
uncomment out in future if need arises
printf(" : ");
gets(input_str);
odsc = atoi(input_str);
printf(" Configuration of Open Drain (ODSYS): ");
gets(input_str);
odsys = atoi(input_str);
printf(" Enabling of the Cache Test (CTM): ");
gets(input_str);
ctm = atoi(input_str);
*/
printf("\nThere is no checking that occurs when entering the full set of\n");
printf(" configuration bits. Please verify the following is correct:\n");
printf("CPU frequency (MHZ) %lld\nHub frequency (MHZ) %lld\nMachine type %d\n",
config_info->freq_cpu/1000000,
config_info->freq_hub/1000000,
config_info->mach_type);
printf("RTC frequency (KHZ) %lld\n",config_info->freq_rtc/1000);
/*
printf(" Kseg0CA \t\t(KSEG0CA) %d\n", kseg0ca);
printf(" DevNum \t\t(DEVNUM) %d\n", devnum);
printf(" Coh Proc Req Targ \t(CPRT) %d\n", cprt);
printf(" Proc Elim Req \t(PER) %d\n", per);
printf(" Proc Req Max \t(PRM) %d\n", prm);
printf(" PClk/SysClk \t(SCD) %d\n", scd);
printf(" Sec Cache Blk Sz \t(SCBS) %d\n", scbs);
printf(" Mem Sys End \t(ME) %d\n", me);
printf(" Sec Cache Size \t(SCS) %d\n", scs);
printf(" PClk/SCClk \t(SCCD) %d\n", sccd);
printf(" algn SClk Sec Cache Clk \t(SCCT) 0x%x\n", scct);
printf(" Open Drain Conf \t\t(ODSYS) %d\n", odsys);
printf(" Cache Test Enable \t(CTM) %d\n", ctm);
*/
printf(" PClk/SysClk \t(SCD) %d\n", scd);
printf(" Sec Cache Size \t(SCS) %d\n", scs);
printf(" PClk/SCClk \t(SCCD) %d\n", sccd);
printf(" algn SClk Sec Cache Clk \t(SCCT) 0x%x\n", scct);
printf("\nIf these value are correct enter y else n: ");
gets(input_str);
if (input_str[0] != 'y')
goto re_enter;
config_info->r10k_mode = (uint) (IP27C_R10000_KSEG0CA(kseg0ca) + \
IP27C_R10000_DEVNUM(devnum) + \
IP27C_R10000_CPRT(cprt) + \
IP27C_R10000_PER(per) + \
IP27C_R10000_PRM(prm) + \
IP27C_R10000_SCD(scd) + \
IP27C_R10000_SCBS(scbs) + \
IP27C_R10000_SCCE(scce) + \
IP27C_R10000_ME(me) + \
IP27C_R10000_SCS(scs) + \
IP27C_R10000_SCCD(sccd) + \
IP27C_R10000_SCCT(scct) + \
IP27C_R10000_ODSC(odsc) + \
IP27C_R10000_ODSYS(odsys) + \
IP27C_R10000_CTM(ctm));
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;
config_info->config_type = (uint) 0;
printf("Enter configuration type (0) Normal (1) 12P4I: [0] ");
gets(input_str);
if (strlen(input_str) > 0) {
input_val = atoi(input_str);
config_info->config_type = (uint) input_val;
}
}
#define LBYTEU(caddr) \
(u_char) ((*(uint *) ((__psunsigned_t) (caddr) & ~3) << \
((__psunsigned_t) (caddr) & 3) * 8) >> 24)
__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;
}
/*
* erase_promlog_sectors
*
* Fill up sectors 14 and 15 with 0xff.
*/
static void
erase_promlog_sectors(char *prom_devpath)
{
fprom_t f;
int manu_code, dev_code;
int r, i ;
int prom_mapoffset ;
printf("Erasing prom log of %s ........ ", prom_devpath) ;
/* Need to erase sectors 14 and 15 */
prom_mapoffset = 14 * FPROM_SECTOR_SIZE ;
f.base = map_prom(prom_devpath, prom_mapoffset, 8*FPROM_SIZE);
if (!f.base) {
printf("FAIL\n") ;
return ;
}
/*
* afn and aparm are abort function and its args.
* They are null for now.
*/
f.afn = 0;
for (i=0;i<8;i++) {
f.aparm[i] = 0;
}
f.dev = FPROM_DEV_HUB;
r = fprom_probe(&f, &manu_code, &dev_code);
if (r < 0 && r != FPROM_ERROR_DEVICE) {
printf("FAIL Init\n") ;
return ;
}
if (r == FPROM_ERROR_DEVICE) {
printf("FAIL Bad Mfg code\n") ;
return ;
}
if ((r = fprom_flash_sectors(&f, 0xC000)) < 0) {
printf("FAIL Erase\n") ;
return ;
}
printf("DONE\n") ;
}
int
ip31_get_config(int pimm_psc, ip27config_t *c)
{
int index;
if ((index = ip31_psc_to_flash_config[pimm_psc]) == IP27_CONFIG_UNKNOWN)
return -1;
c->time_const = (uint) CONFIG_TIME_CONST;
c->r10k_mode = ip27config_table[index].r10k_mode;
c->magic = (__uint64_t) CONFIG_MAGIC;
c->freq_cpu = ip27config_table[index].freq_cpu;
c->freq_hub = ip27config_table[index].freq_hub;
c->freq_rtc = (__uint64_t) IP27C_KHZ(IP27_RTC_FREQ);
c->ecc_enable = (uint) CONFIG_ECC_ENABLE;
c->fprom_cyc = ip27config_table[index].fprom_cyc;
c->mach_type = ip27config_table[index].mach_type;
c->check_sum_adj = (uint) 0;
c->fprom_wr = ip27config_table[index].fprom_wr;
return 0;
}