Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / sam-t2 / sam / devices / common / disk_parser.cc
// ========== Copyright Header Begin ==========================================
//
// OpenSPARC T2 Processor File: disk_parser.cc
// Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES.
//
// The above named program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public
// License version 2 as published by the Free Software Foundation.
//
// The above named program is distributed in the hope that it will be
// useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public
// License along with this work; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
//
// ========== Copyright Header End ============================================
#include "disk.h"
#include "arg.h"
#define MAX_SCSI_DISK_PARTITIONS 8
#define MAX_SCSI_TARGETS 16
#define LINE_BUF_SIZE 1024
extern SCSIDisk *parser_disk;
static char ** parse_args (const char * string, int * pargc) {
int allocc = 4;
int argc = 0;
char ** pargv = (char**) calloc (allocc, sizeof(char*));
char * tmpstr = (char*) strdup (string);
char * s = tmpstr;
char * ps;
int inquotes = 0; /* when we're inside " quotes */
int backslash = 0; /* yet another flag... */
if (pargv == NULL)
return NULL;
// remove leading white space
//
while (isspace(*s)) {
if ((*s == '\0') || (*s == '\n')) {
*pargc = 0;
return NULL;
}
++s;
}
ps = s;
for (;;) {
inquotes = 0;
while (!isspace(*s) || inquotes) {
if (*s == '"')
inquotes = ! inquotes;
++s;
if (*s == '\0')
goto EOLINE;
}
// copy parsed arg into argv
*s = '\0';
pargv[argc++] = (char*) strdup (ps);
++s;
// re-allocate argv if we have too many args
//
if (argc >= allocc) {
allocc *= 2;
pargv = (char**) realloc (pargv, sizeof(char*) * allocc);
}
//
// skip white space between words
//
while (isspace(*s)) {
++s;
}
if ((*s == '\0') || (*s == '\n'))
goto DONE;
ps = s;
}
EOLINE:
pargv[argc++] = (char*) strdup (ps);
DONE:
free(tmpstr);
*pargc = argc;
return pargv;
}
static void free_args (int argc, char ** argv) {
int i;
for (i = 0; i < argc; i++) {
free(argv[i]);
}
if (argc > 0)
free(argv);
}
char *process_str(const char *src) {
int ls = strlen(src);
char *dst = (char *)calloc(ls+1, sizeof(char));
if ((src[0] == '\'' /* single quoted */
&& src[ls-1] == '\'')
|| (src[0] == '"' /* or double quoted cases */
&& src[ls-1] == '"')) {
bcopy(src+1, dst, ls-2);
} else if (ls > 9 /* dotted hex case */
&& src[2] == '.' && src[5] == '.' && src[8] == '.') {
int j=0;
for (int i=0; i<ls; i++)
if (src[i] != '.') dst[j++] = src[i];
} else { /* default case */
bcopy(src, dst, ls);
}
return(dst);
}
// Scan through the whole file to parse all configs related to a target
// 0: succeed, -1: fail
int scsi_parse_config(const char * fname, FILE *fp, int target) {
char line_buf[LINE_BUF_SIZE];
char *charP;
int result;
int lineno;
int argc;
char **argv;
int i;
// for basic config
int target_id, disk_id, partition_id;
bool write_flag, vtoc_part;
// for extended config
const char *vendor_id, *product_id, *revision_id;
const char *serial_no;
const char *prodserial_no, *brdserial_no;
const char *port_wwn, *node_wwn;
const char *rdelay;
const char *bytes_per_sector;
const char *sectors_per_track;
const char *tracks_per_cylinder;
const char *debug_file;
const char *debug_level;
const char *disk_delay;
fseek(fp, 0, SEEK_SET);
lineno = 0;
argc = 0;
while (charP = fgets(line_buf, LINE_BUF_SIZE, fp)) {
// initializing variables
target_id = disk_id = partition_id = -1;
write_flag = false;
vtoc_part = false;
vendor_id = product_id = revision_id = NULL;
serial_no = NULL;
prodserial_no = brdserial_no = NULL;
port_wwn = node_wwn = NULL;
rdelay = NULL;
bytes_per_sector = NULL;
sectors_per_track = NULL;
tracks_per_cylinder = NULL;
debug_file = NULL;
debug_level = NULL;
disk_delay = NULL;
// lineno is used to track the error
lineno++;
// parse all parameters into arg
free_args(argc, argv);
argv = parse_args(charP, &argc);
// empty line
if (argc == 0)
continue;
// comment line
if (*argv[0] == '#')
continue;
if (argc < 2) {
free_args(argc, argv);
fprintf(stderr, "%s: lineno %d: insufficient args.\n", fname, lineno);
return(-1);
}
result = sscanf(argv[0], "t%dd%ds%x", &target_id, &disk_id, &partition_id);
if (result != 3) {
free_args(argc, argv);
fprintf(stderr, "%s: lineno %d: wrong disk partition name.\n", fname, lineno);
return(-1);
}
if (target_id >= MAX_SCSI_TARGETS || target_id < 0) {
free_args(argc, argv);
fprintf(stderr, "%s: lineno %d: invalid target id.\n", fname, lineno);
return(-1);
}
if (disk_id != 0) {
free_args(argc, argv);
fprintf(stderr, "%s: lineno %d: invalid disk id.\n", fname, lineno);
return(-1);
}
if (partition_id >= MAX_SCSI_DISK_PARTITIONS || partition_id < 0) {
free_args(argc, argv);
fprintf(stderr, "%s: lineno %d: invalid partition id.\n", fname, lineno);
return(-1);
}
if (target_id != target)
continue;
i = 2;
if (i < argc) {
bool other_params = false;
// the third parameter is either "ro", or "rw", or "vtoc", or others
if (strcmp(argv[i], "ro") == 0) {
write_flag = false;
i++;
} else if (strcmp(argv[i], "rw") == 0) {
write_flag = true;
i++;
} else if (strcmp(argv[i], "vtoc") == 0) {
vtoc_part = true;
i++;
} else {
other_params = true;
}
// the fourth parameter is "votc", or others
if (!other_params && i < argc) {
if (strcmp(argv[i], "vtoc") == 0) {
vtoc_part = true;
i++;
}
}
}
for (; i < argc; i++) {
if (argval ("vendor-id", argv[i], &vendor_id))
parser_disk->set_vendor_id(process_str(vendor_id));
else if (argval ("product-id", argv[i], &product_id))
parser_disk->set_product_id(process_str(product_id));
else if (argval ("revision-id", argv[i], &revision_id))
parser_disk->set_revision_id(process_str(revision_id));
else if (argval ("serial-no", argv[i], &serial_no))
parser_disk->set_serial_no(process_str(serial_no));
else if (argval ("prodserial-no", argv[i], &prodserial_no))
parser_disk->set_prodserial_no(process_str(prodserial_no));
else if (argval ("brdserial-no", argv[i], &brdserial_no))
parser_disk->set_brdserial_no(process_str(brdserial_no));
else if (argval ("port-wwn", argv[i], &port_wwn))
parser_disk->set_port_wwn(process_str(port_wwn));
else if (argval ("node-wwn", argv[i], &node_wwn))
parser_disk->set_node_wwn(process_str(node_wwn));
else if (argval ("bytes/sector", argv[i], &bytes_per_sector))
parser_disk->set_bytes_per_sector(atoi(bytes_per_sector));
else if (argval ("sectors/track", argv[i], &sectors_per_track))
parser_disk->set_sectors_per_track(atoi(sectors_per_track));
else if (argval ("tracks/cylinder", argv[i], &tracks_per_cylinder))
parser_disk->set_tracks_per_cylinder(atoi(tracks_per_cylinder));
else if (argval ("dd", argv[i], &disk_delay))
parser_disk->set_disk_delay(process_str(disk_delay));
else if (argval ("debug-file", argv[i], &debug_file))
parser_disk->set_debug_file(process_str(debug_file));
else if (argval ("debug-level", argv[i], &debug_level))
parser_disk->set_debug_level(atoi(debug_level));
else {
free_args(argc, argv);
fprintf(stderr, "%s: lineno %d: unrecognized arg.\n", fname, lineno);
return(-1);
}
}
// add one partition
parser_disk->add_partition(partition_id, argv[1], write_flag, vtoc_part);
}
return 0;
}