Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / sam-t2 / sam / devices / common / disk_parser.cc
CommitLineData
920dae64
AT
1// ========== Copyright Header Begin ==========================================
2//
3// OpenSPARC T2 Processor File: disk_parser.cc
4// Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
5// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES.
6//
7// The above named program is free software; you can redistribute it and/or
8// modify it under the terms of the GNU General Public
9// License version 2 as published by the Free Software Foundation.
10//
11// The above named program is distributed in the hope that it will be
12// useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14// General Public License for more details.
15//
16// You should have received a copy of the GNU General Public
17// License along with this work; if not, write to the Free Software
18// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
19//
20// ========== Copyright Header End ============================================
21#include "disk.h"
22#include "arg.h"
23
24#define MAX_SCSI_DISK_PARTITIONS 8
25#define MAX_SCSI_TARGETS 16
26#define LINE_BUF_SIZE 1024
27
28extern SCSIDisk *parser_disk;
29
30
31static char ** parse_args (const char * string, int * pargc) {
32 int allocc = 4;
33 int argc = 0;
34 char ** pargv = (char**) calloc (allocc, sizeof(char*));
35 char * tmpstr = (char*) strdup (string);
36 char * s = tmpstr;
37 char * ps;
38 int inquotes = 0; /* when we're inside " quotes */
39 int backslash = 0; /* yet another flag... */
40
41 if (pargv == NULL)
42 return NULL;
43
44 // remove leading white space
45 //
46 while (isspace(*s)) {
47 if ((*s == '\0') || (*s == '\n')) {
48 *pargc = 0;
49 return NULL;
50 }
51 ++s;
52 }
53
54 ps = s;
55 for (;;) {
56
57 inquotes = 0;
58 while (!isspace(*s) || inquotes) {
59 if (*s == '"')
60 inquotes = ! inquotes;
61 ++s;
62 if (*s == '\0')
63 goto EOLINE;
64 }
65
66 // copy parsed arg into argv
67 *s = '\0';
68 pargv[argc++] = (char*) strdup (ps);
69 ++s;
70
71 // re-allocate argv if we have too many args
72 //
73 if (argc >= allocc) {
74 allocc *= 2;
75 pargv = (char**) realloc (pargv, sizeof(char*) * allocc);
76 }
77
78 //
79 // skip white space between words
80 //
81 while (isspace(*s)) {
82 ++s;
83 }
84 if ((*s == '\0') || (*s == '\n'))
85 goto DONE;
86 ps = s;
87 }
88
89EOLINE:
90 pargv[argc++] = (char*) strdup (ps);
91DONE:
92 free(tmpstr);
93
94 *pargc = argc;
95 return pargv;
96}
97
98
99static void free_args (int argc, char ** argv) {
100 int i;
101 for (i = 0; i < argc; i++) {
102 free(argv[i]);
103 }
104 if (argc > 0)
105 free(argv);
106}
107
108
109char *process_str(const char *src) {
110 int ls = strlen(src);
111 char *dst = (char *)calloc(ls+1, sizeof(char));
112
113 if ((src[0] == '\'' /* single quoted */
114 && src[ls-1] == '\'')
115 || (src[0] == '"' /* or double quoted cases */
116 && src[ls-1] == '"')) {
117
118 bcopy(src+1, dst, ls-2);
119
120 } else if (ls > 9 /* dotted hex case */
121 && src[2] == '.' && src[5] == '.' && src[8] == '.') {
122
123 int j=0;
124 for (int i=0; i<ls; i++)
125 if (src[i] != '.') dst[j++] = src[i];
126
127 } else { /* default case */
128
129 bcopy(src, dst, ls);
130 }
131
132 return(dst);
133}
134
135
136// Scan through the whole file to parse all configs related to a target
137// 0: succeed, -1: fail
138int scsi_parse_config(const char * fname, FILE *fp, int target) {
139 char line_buf[LINE_BUF_SIZE];
140 char *charP;
141 int result;
142 int lineno;
143 int argc;
144 char **argv;
145 int i;
146
147 // for basic config
148 int target_id, disk_id, partition_id;
149 bool write_flag, vtoc_part;
150
151 // for extended config
152 const char *vendor_id, *product_id, *revision_id;
153 const char *serial_no;
154 const char *prodserial_no, *brdserial_no;
155 const char *port_wwn, *node_wwn;
156 const char *rdelay;
157 const char *bytes_per_sector;
158 const char *sectors_per_track;
159 const char *tracks_per_cylinder;
160 const char *debug_file;
161 const char *debug_level;
162 const char *disk_delay;
163
164 fseek(fp, 0, SEEK_SET);
165 lineno = 0;
166 argc = 0;
167
168 while (charP = fgets(line_buf, LINE_BUF_SIZE, fp)) {
169 // initializing variables
170 target_id = disk_id = partition_id = -1;
171 write_flag = false;
172 vtoc_part = false;
173
174 vendor_id = product_id = revision_id = NULL;
175 serial_no = NULL;
176 prodserial_no = brdserial_no = NULL;
177 port_wwn = node_wwn = NULL;
178 rdelay = NULL;
179 bytes_per_sector = NULL;
180 sectors_per_track = NULL;
181 tracks_per_cylinder = NULL;
182 debug_file = NULL;
183 debug_level = NULL;
184 disk_delay = NULL;
185
186 // lineno is used to track the error
187 lineno++;
188
189 // parse all parameters into arg
190 free_args(argc, argv);
191 argv = parse_args(charP, &argc);
192
193 // empty line
194 if (argc == 0)
195 continue;
196
197 // comment line
198 if (*argv[0] == '#')
199 continue;
200
201 if (argc < 2) {
202 free_args(argc, argv);
203 fprintf(stderr, "%s: lineno %d: insufficient args.\n", fname, lineno);
204 return(-1);
205 }
206
207 result = sscanf(argv[0], "t%dd%ds%x", &target_id, &disk_id, &partition_id);
208 if (result != 3) {
209 free_args(argc, argv);
210 fprintf(stderr, "%s: lineno %d: wrong disk partition name.\n", fname, lineno);
211 return(-1);
212 }
213
214 if (target_id >= MAX_SCSI_TARGETS || target_id < 0) {
215 free_args(argc, argv);
216 fprintf(stderr, "%s: lineno %d: invalid target id.\n", fname, lineno);
217 return(-1);
218 }
219
220 if (disk_id != 0) {
221 free_args(argc, argv);
222 fprintf(stderr, "%s: lineno %d: invalid disk id.\n", fname, lineno);
223 return(-1);
224 }
225
226 if (partition_id >= MAX_SCSI_DISK_PARTITIONS || partition_id < 0) {
227 free_args(argc, argv);
228 fprintf(stderr, "%s: lineno %d: invalid partition id.\n", fname, lineno);
229 return(-1);
230 }
231
232 if (target_id != target)
233 continue;
234
235 i = 2;
236
237 if (i < argc) {
238 bool other_params = false;
239
240 // the third parameter is either "ro", or "rw", or "vtoc", or others
241 if (strcmp(argv[i], "ro") == 0) {
242 write_flag = false;
243 i++;
244 } else if (strcmp(argv[i], "rw") == 0) {
245 write_flag = true;
246 i++;
247 } else if (strcmp(argv[i], "vtoc") == 0) {
248 vtoc_part = true;
249 i++;
250 } else {
251 other_params = true;
252 }
253
254 // the fourth parameter is "votc", or others
255 if (!other_params && i < argc) {
256 if (strcmp(argv[i], "vtoc") == 0) {
257 vtoc_part = true;
258 i++;
259 }
260 }
261 }
262
263 for (; i < argc; i++) {
264 if (argval ("vendor-id", argv[i], &vendor_id))
265 parser_disk->set_vendor_id(process_str(vendor_id));
266 else if (argval ("product-id", argv[i], &product_id))
267 parser_disk->set_product_id(process_str(product_id));
268 else if (argval ("revision-id", argv[i], &revision_id))
269 parser_disk->set_revision_id(process_str(revision_id));
270 else if (argval ("serial-no", argv[i], &serial_no))
271 parser_disk->set_serial_no(process_str(serial_no));
272 else if (argval ("prodserial-no", argv[i], &prodserial_no))
273 parser_disk->set_prodserial_no(process_str(prodserial_no));
274 else if (argval ("brdserial-no", argv[i], &brdserial_no))
275 parser_disk->set_brdserial_no(process_str(brdserial_no));
276 else if (argval ("port-wwn", argv[i], &port_wwn))
277 parser_disk->set_port_wwn(process_str(port_wwn));
278 else if (argval ("node-wwn", argv[i], &node_wwn))
279 parser_disk->set_node_wwn(process_str(node_wwn));
280 else if (argval ("bytes/sector", argv[i], &bytes_per_sector))
281 parser_disk->set_bytes_per_sector(atoi(bytes_per_sector));
282 else if (argval ("sectors/track", argv[i], &sectors_per_track))
283 parser_disk->set_sectors_per_track(atoi(sectors_per_track));
284 else if (argval ("tracks/cylinder", argv[i], &tracks_per_cylinder))
285 parser_disk->set_tracks_per_cylinder(atoi(tracks_per_cylinder));
286 else if (argval ("dd", argv[i], &disk_delay))
287 parser_disk->set_disk_delay(process_str(disk_delay));
288 else if (argval ("debug-file", argv[i], &debug_file))
289 parser_disk->set_debug_file(process_str(debug_file));
290 else if (argval ("debug-level", argv[i], &debug_level))
291 parser_disk->set_debug_level(atoi(debug_level));
292 else {
293 free_args(argc, argv);
294 fprintf(stderr, "%s: lineno %d: unrecognized arg.\n", fname, lineno);
295 return(-1);
296 }
297 }
298
299 // add one partition
300 parser_disk->add_partition(partition_id, argv[1], write_flag, vtoc_part);
301 }
302
303 return 0;
304}