Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / sam-t2 / sam / devices / common / include / disk.h
CommitLineData
920dae64
AT
1/*
2* ========== Copyright Header Begin ==========================================
3*
4* OpenSPARC T2 Processor File: disk.h
5* Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
6* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES.
7*
8* The above named program is free software; you can redistribute it and/or
9* modify it under the terms of the GNU General Public
10* License version 2 as published by the Free Software Foundation.
11*
12* The above named program is distributed in the hope that it will be
13* useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
14* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15* General Public License for more details.
16*
17* You should have received a copy of the GNU General Public
18* License along with this work; if not, write to the Free Software
19* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
20*
21* ========== Copyright Header End ============================================
22*/
23#ifndef __DISK_H__
24#define __DISK_H__
25
26#include <sys/types.h>
27#include <sys/stat.h>
28#include <fcntl.h>
29#include <unistd.h>
30#include <stdlib.h>
31#include "utils.h"
32
33/*-------------------------- vtoc8 disk label -------------------------------*/
34
35// On sparc platform _SUNOS_VTOC_8 is defined whereas on i386 platform
36// _SUNOS_VTOC_16 is defined. We want to simulate sparc on i386 and
37// cannot simply override these definitions, hence we have to lift vtoc/label
38// out of system include files and create our own.
39
40#define LEN_DKL_ASCII 128 /* length of dkl_asciilabel */
41#define LEN_DKL_VVOL 8 /* length of v_volume */
42#define DK_LABEL_SIZE 512 /* size of disk label */
43#define READ_DELAY_DEFAULT 0 /* default disk read delay in microseconds */
44#define WRITE_DELAY_DEFAULT 0 /* default disk write delay in microseconds */
45
46/*
47 * partition headers: section 1
48 * Fixed size for on-disk dk_label
49 */
50struct dk_map32 {
51 int32_t dkl_cylno; /* starting cylinder */
52 int32_t dkl_nblk; /* number of blocks; if == 0, */
53 /* partition is undefined */
54};
55
56/*
57 * partition headers: section 2,
58 * brought over from AT&T SVr4 vtoc structure.
59 */
60struct dk_map2 {
61 uint16_t p_tag; /* ID tag of partition */
62 uint16_t p_flag; /* permission flag */
63};
64
65#define VTOC8_NDKMAP 8 /* # of logical partitions */
66#define VTOC8_DK_LABEL_LOC 0 /* location of disk label */
67
68struct vtoc8_dk_vtoc {
69 uint32_t v_version; /* layout version */
70 char v_volume[LEN_DKL_VVOL]; /* volume name */
71 uint16_t v_nparts; /* number of partitions */
72 struct dk_map2 v_part[VTOC8_NDKMAP]; /* partition hdrs, sec 2 */
73 uint32_t v_bootinfo[3]; /* info needed by mboot */
74 uint32_t v_sanity; /* to verify vtoc sanity */
75 uint32_t v_reserved[10]; /* free space */
76 int32_t v_timestamp[VTOC8_NDKMAP]; /* partition timestamp */
77};
78
79#define VTOC8_LEN_DKL_PAD (DK_LABEL_SIZE \
80 - ((LEN_DKL_ASCII) + \
81 (sizeof (struct vtoc8_dk_vtoc)) + \
82 (sizeof (struct dk_map32) * VTOC8_NDKMAP) + \
83 (14 * (sizeof (uint16_t))) + \
84 (2 * (sizeof (uint16_t)))))
85
86struct vtoc8_dk_label {
87 char dkl_ascii_label[LEN_DKL_ASCII]; /* for compatibility */
88 struct vtoc8_dk_vtoc dkl_vtoc; /* vtoc inclusions from AT&T SVr4 */
89 uint16_t dkl_write_reinstruct; /* # sectors to skip, writes */
90 uint16_t dkl_read_reinstruct; /* # sectors to skip, reads */
91 char dkl_pad[VTOC8_LEN_DKL_PAD]; /* unused part of 512 bytes */
92 uint16_t dkl_rpm; /* rotations per minute */
93 uint16_t dkl_pcyl; /* # physical cylinders */
94 uint16_t dkl_apc; /* alternates per cylinder */
95 uint16_t dkl_obs1; /* obsolete */
96 uint16_t dkl_obs2; /* obsolete */
97 uint16_t dkl_intrlv; /* interleave factor */
98 uint16_t dkl_ncyl; /* # of data cylinders */
99 uint16_t dkl_acyl; /* # of alternate cylinders */
100 uint16_t dkl_nhead; /* # of heads in this partition */
101 uint16_t dkl_nsect; /* # of 512 byte sectors per track */
102 uint16_t dkl_obs3; /* obsolete */
103 uint16_t dkl_obs4; /* obsolete */
104 struct dk_map32 dkl_map[VTOC8_NDKMAP]; /* logical partition headers */
105 uint16_t dkl_magic; /* identifies this label format */
106 uint16_t dkl_cksum; /* xor checksum of sector */
107};
108
109/*---------------------------------------------------------------------------*/
110
111#include <stdio.h>
112#include <assert.h>
113#include <strings.h>
114#include <math.h>
115#include <errno.h>
116#include "ui.h"
117#include <list>
118
119extern "C" char *overlaydir;
120
121class bitset{
122 uint64_t size;
123 uint64_t map_size;
124 const char * name;
125 uint64_t * map;
126public:
127
128 bitset(uint64_t s,const char *n = 0){
129 assert(s);
130 size = s;
131 map_size = s%64 ? s/64 + 1: s/64;
132 name = n ? strdup(n):strdup("bitset");
133 map = new uint64_t[map_size];
134 assert(map);
135 for(uint64_t i = 0; i < map_size; i++)
136 map[i] = 0;
137 }
138
139 ~bitset(){ delete map;}
140
141 void set(uint64_t pos){
142 assert(pos < size);
143 uint64_t index = pos/64;
144 map[index] |= 1ULL << pos%64;
145 }
146
147 void clear(uint64_t pos){
148 assert(pos < size);
149 uint64_t index = pos/64;
150 map[index] &= ~(1ULL << pos%64);
151 }
152
153 bool get(uint64_t pos){
154 assert(pos < size);
155 uint64_t index = pos/64;
156 return (map[index] >> pos%64) & 0x1;
157 }
158
159 void Or(bitset * s){
160 assert (s->size == size);
161 for(uint64_t i = 0; i < map_size; i++ )
162 map[i] |= s->map[i];
163 }
164 void And(bitset * s){
165 assert (s->size == size);
166 for(uint64_t i = 0; i < map_size; i++ )
167 map[i] &= s->map[i];
168 }
169 bool dump(FILE * fp){
170 assert(fp);
171 if(fwrite((void*)map,map_size * 8, 1, fp) != 1){
172 fprintf(stderr,"%s: dump failed\n",name);
173 return false;
174 }
175 return true;
176 }
177
178 bool restore(FILE * fp){
179 assert(fp);
180 if(fread((void*)map,map_size * 8, 1, fp) != 1){
181 fprintf(stderr,"%s: restore failed\n",name);
182 return false;
183 }
184 return true;
185 }
186};
187
188
189struct SCSI_Inquiry_Data { // Inquiry returns this
190 uint8_t devType; // 0 Device type,
191 uint8_t devTypeMod; // 1 Device type modifier
192 uint8_t version; // 2 ISO/ECMA/ANSI version
193 uint8_t format; // 3 Response data format
194 uint8_t length; // 4 Additional Length
195 uint8_t reserved5; // 5 Reserved
196 uint8_t reserved6; // 6 Reserved
197 uint8_t flags; // 7 Capability flags
198 uint8_t vendor[8]; // 8-15 Vendor-specific
199 uint8_t product[16]; // 16-31 Product id
200 uint8_t revision[4]; // 32-35 Product revision
201 uint8_t serialnum[8]; // 36-43 Drive Serial Number
202 uint8_t vendorSpecific[12];// 36-55 Vendor stuff
203 uint8_t moreReserved[40]; // 56-95 Reserved
204 uint8_t copyright[48]; // 96-143 copyright data
205
206
207
208 SCSI_Inquiry_Data(){
209 devType = 0x00; /* peripheral type, 0 => disk */
210 devTypeMod = 0x00; /* zero */
211 version = 0x02; /* 2 => device commands: SCSI-2 */
212 format = 0x02; /* 2 => reply format: SCSI-2 */
213 length = 0x8b; /* page len = number bytes following = (sizeof - 5) */
214 reserved5 = 0x00; /* feature bits */
215 reserved6 = 0x00; /* feature bits */
216 flags = 0x00; /* feature bits */
217 strncpy((char*)vendor, "YOYODYNE",sizeof(vendor)); /* char VendorID[8] */
218 strncpy((char*)product,"Turbo Frisbee ",sizeof(product));/* char ProductID[16] */
219 strncpy((char*)revision,"0000",sizeof(revision)); /* char RevisionID[4] */
220 strncpy((char*)serialnum," ",sizeof(serialnum)); /* char SerialNumber[8] */
221 bzero((char*)vendorSpecific, sizeof(vendorSpecific));
222 bzero((char*)moreReserved, sizeof(moreReserved));
223 strncpy((char*)copyright, "Copyright (c) 2001 Yoyodyne All rights reserved.",sizeof(copyright));
224 }
225};
226
227
228struct Supported_VPD{ //0x00
229 uint8_t devType;
230 uint8_t pageCode;
231 uint8_t reserved0;
232 uint8_t pageLength;
233 uint8_t pageList[12];
234
235 Supported_VPD(){ // by default support all data
236 devType = 0x0; /* peripheral type */
237 pageCode = 0x0; /* request code for this reply page */
238 reserved0 = 0x0;
239 pageLength = 0xc; /* page len = number bytes following = (sizeof - 4) */
240 pageList[0] = 0x00; /* Supported Vital Product Data pages */
241 pageList[1] = 0x80; /* Unit Serial Number page */
242 pageList[2] = 0x81; /* Implemented Operating Definition page */
243 pageList[3] = 0x83; /* Device Identification page */
244 pageList[4] = 0xc0; /* Firmware Numbers page */
245 pageList[5] = 0xc1; /* Date Code page */
246 pageList[6] = 0xc2; /* Jumper Settings page */
247 pageList[7] = 0xc3; /* Device Behaviour page */
248 pageList[8] = 0xd1; /* Vendor Specific page */
249 pageList[9] = 0xd2; /* Vendor Specific page */
250 pageList[10] = 0xd3; /* Vendor Specific page */
251 pageList[11] = 0xd4; /* Vendor Specific page */
252 }
253};
254
255struct Unit_Serial_Number { // 0x80
256 uint8_t devType;
257 uint8_t pageCode;
258 uint8_t reserved0;
259 uint8_t pageLength;
260 uint8_t productSerialNumber[8];
261 uint8_t boardSerialNumber[12];
262
263 Unit_Serial_Number(){
264 devType = 0x00; /* peripheral type */
265 pageCode = 0x80; /* request code for this reply page */
266 reserved0 = 0x00;
267 pageLength = 0x14; /* page len = number bytes following = (sizeof - 4) */
268 strncpy((char*)productSerialNumber," ",sizeof(productSerialNumber));
269 strncpy((char*)boardSerialNumber, " ",sizeof(boardSerialNumber));
270 }
271};
272
273
274struct Implemented_Operating_Definition{ // 0x81
275 uint8_t devType;
276 uint8_t pageCode;
277 uint8_t reserved0;
278 uint8_t pageLength;
279 uint8_t currentOpDef;
280 uint8_t defaultOpDef[2];
281
282 Implemented_Operating_Definition(){
283 devType = 0x00; /* peripheral type */
284 pageCode = 0x81; /* request code for this reply page */
285 reserved0 = 0x00;
286 pageLength = 0x03; /* page len = number bytes following = (sizeof - 4) */
287 currentOpDef = 0x01; /* Current Operating Definition, 1 => SCSI-2 */
288 defaultOpDef[0] = 0x01; /* Default Operating Definition, 1 => SCSI-2 */
289 defaultOpDef[1] = 0x01; /* Unknown Operating Definition, 1 => SCSI-2 */
290 }
291};
292
293
294struct Device_Identification{ // 0x83
295 uint8_t devType;
296 uint8_t pageCode;
297 uint8_t reserved0;
298 uint8_t pageLength;
299
300 Device_Identification(){
301 devType = 0x00; /* peripheral type */
302 pageCode = 0x83; /* request code for this reply page */
303 reserved0 = 0x00;
304 pageLength = 0x00; /* page len = number bytes following = (sizeof - 4) */
305 }
306};
307
308struct FC_Device_Identification:public Device_Identification{
309 // 0x83
310 uint8_t codeSet0;
311 uint8_t idType_Asso0;
312 uint8_t reserved10;
313 uint8_t idLength0;
314 uint8_t id0[8];
315
316 uint8_t codeSet1;
317 uint8_t idType_Asso1;
318 uint8_t reserved11;
319 uint8_t idLength1;
320 uint8_t id1[8];
321
322 FC_Device_Identification():Device_Identification(){
323 codeSet0 = codeSet1 = 0x01; /* code: 1=binary (,2=ascii) */
324 idType_Asso0 = 0x13; /* assoc: 1=port (,0=node); uid type: 3=NAA */
325 idType_Asso1 = 0x03; /* assoc: 0=node (,1=port); uid type: 3=NAA */
326 reserved10 = reserved11 = 0x00;
327 idLength0 = idLength1 = 0x8;
328 bzero(id0, sizeof(id0));
329 bzero(id1, sizeof(id1));
330 pageLength = 0x18; // override pagelength in base
331 }
332};
333
334
335// other page codes are not supported.
336
337
338class Partition{
339public:
340 static const int BYTES_PER_SECTOR = 512;
341
342 static const int DISK_PAGE_SIZE = 512; // granularity of r/w to backup/overlay files
343 // this is chosen same as BYTES_PER_SECTOR to handle/simplify the case of
344 // overlapping partitions (can be specified by real vtoc's). The disk image
345 // may not be aligned to a larger mutiple of DISK_PAGE_SIZE which may create
346 // undetected holes in lblks.
347
348 static const int BLOCKS_PER_PAGE = DISK_PAGE_SIZE/BYTES_PER_SECTOR;
349
350
351 int debug_level;
352 FILE * debug_file;
353
354 // Real physical file name or disk partition name in which
355 // data for the simulated disk partition exists.
356 const char* part_filename;
357
358 // simulated disk partition name
359 const char* part_name;
360
361 // filename of shadow of simulated disk partition in which
362 // write data is stored. This shadow file is used only when
363 // the partition is attached read-only which is the default.
364 const char* overlay_filename;
365 const char* ckpt_filename;
366
367 // if set, write enabled. Otherwise, read only
368 bool rw;
369
370 // true if the parition is an actual host system disk. set from st_rdev of
371 // the stat buf of part_filename
372 bool is_device_file;
373
374 // this partition has vtoc from the real disk if true
375 bool has_vtoc;
376
377 // size of simulated disk partition in bytes
378 uint64_t size;
379
380 // size of simulated disk partition in logical blocks OR
381 // the value read from a real vtoc. Can be different from
382 // size/BYTES_PER_SECTOR
383 uint64_t nblks;
384
385 // starting disk block number of this simulated disk partition
386 uint64_t start_lblk;
387
388 // ending disk block number of this simulated disk partition
389 uint64_t end_lblk;
390
391 // index,flag and tag of this simulated disk partition
392 int index;
393 int primary_fd;
394 int overlay_fd;
395 int ckpt_fd;
396
397 // bitmap of pages in the disk partition that have been modified.
398 // The modified pages will be in shadow file. The bitmap is used
399 // only when the partiton is attached read-only which is the default.
400
401 uint64_t bitmap_size;
402 bitset* overlay_bitmap;
403 bitset* ckpt_bitmap;
404
405 Partition();
406 ~Partition();
407
408 bool lblk_inrange(uint64_t lblk){
409 if( (lblk >= start_lblk) && (lblk <= end_lblk) )
410 return true;
411 return false;
412 }
413
414 bool create_overlay(const char * dir, const char * disk){
415 if(rw)
416 return true; // no need for overlays, partition is rw
417
418 // make this function reentrant
419 if(overlay_bitmap && overlay_fd != -1)
420 return true;
421
422 // create the bitmap where each bit corresponds to 8K size block
423 // in partition
424 bitmap_size = (nblks*BYTES_PER_SECTOR + DISK_PAGE_SIZE - 1)/DISK_PAGE_SIZE;
425 if( overlay_bitmap == 0 )
426 overlay_bitmap = new bitset(bitmap_size,part_name);
427 assert(overlay_bitmap);
428
429 char buf[1024];
430 sprintf(buf,"%s/%s.%s.shadow",dir,disk,part_name);
431 overlay_filename = strdup(buf);
432
433 if(overlay_fd == -1)
434 overlay_fd = open(overlay_filename,O_RDWR|O_CREAT|O_LARGEFILE|O_TRUNC,0666);
435
436 if(overlay_fd == -1){
437 fprintf(debug_file,"%s: could not create overlay file %s\n",\
438 part_name,overlay_filename);
439 perror("");
440 return false;
441 }
442
443 // make the overlay file size a multiple of DISK_PAGE_SIZE
444 if(lseek(overlay_fd, bitmap_size*DISK_PAGE_SIZE - 1,SEEK_SET) == -1){
445 fprintf(debug_file,"%s: could not lseek overlay file %s\n",\
446 part_name,overlay_filename);
447 perror("");
448 return false;
449 }
450
451 // set the size of this file
452 if(write(overlay_fd, "", 1) != 1){
453 fprintf(debug_file,"%s: could not write overlay file %s\n",\
454 part_name,overlay_filename);
455 perror("");
456 return false;
457 }
458 return true;
459 }
460
461 void set_debug_level( int level ){ debug_level = level; }
462 void set_debug_file( FILE* f ){ debug_file = f; }
463 void info();
464 uint32_t Write(uint64_t lblkno, uint8_t *buf, uint32_t numblks);
465 uint32_t Read(uint64_t lblkno, uint8_t *buf, uint32_t numblks);
466 bool restore(const char * dir, const char * disk_name);
467 bool dump(const char * dir, const char * disk_name);
468
469 // some statistics
470 uint64_t lblk_reads;
471 uint64_t lblk_writes;
472 uint64_t lblk_reads_primary;
473 uint64_t lblk_writes_primary;
474 uint64_t lblk_reads_overlay;
475 uint64_t lblk_writes_overlay;
476 uint64_t lblk_reads_ckpt;
477};
478
479
480
481class Disk{
482public:
483 static const int MAX_TRIES = 10;
484 static const int BYTES_PER_SECTOR = 512;
485 static const int MAX_PARTITIONS = 8;
486 static const int VTOC_SANITY = 0x600ddeee;
487 static const int DKLABEL_RPM = 5400;
488 static const int DKLABEL_INTRLV = 1;
489 static const int DKLABEL_ACYL= 0;
490 static const int DKLABEL_MAGIC = 0xDABE;
491 int debug_level;
492 FILE * debug_file;
493 char debug_file_name[1024];
494protected:
495 static bool UI_registered;
496 int target_id;
497
498 // disk label structure. Used only if faking a vtoc/disk label
499 struct vtoc8_dk_label disk_label;
500 const char * disk_name;
501
502 Partition *partitions[MAX_PARTITIONS];
503
504 // init the disk label in case of fake vtoc
505 void label_init();
506
507 bool is_s2; // true if disk has a single s2 partition
508 int num_partitions;
509
510 int vtoc_partition; // vtoc partition, in case of real disk vtoc, else -1
511 bool fake_vtoc; // true if SAM needs to fake vtoc, false otherwise
512
513 bool user_geometry;
514
515 uint32_t read_delay; // disk read delay
516 uint32_t write_delay; // disk write delay
517
518 // some parameters, useful when faking vtoc
519 uint16_t sectors_per_track; // dkl_nsect, default 32
520 uint16_t tracks_per_cylinder; // dkl_nhead, default 16
521 uint16_t bytes_per_sector; // default 512
522 uint32_t num_cylinder; // total number of cyinders in disk
523 uint64_t num_blks; // total number of disk blocks in all partitions
524 // note capacity command will return
525 // different value
526
527
528 void set_dkl_cksum(){
529 int count;
530 uint16_t *shortp;
531 uint32_t sum;
532
533
534 sum = 0;
535 count = sizeof(disk_label) / (int) (sizeof(uint16_t));
536
537#if defined(ARCH_X64)
538 struct vtoc8_dk_label tmp;
539 bcopy(&disk_label, &tmp, sizeof(disk_label));
540 label_endian_convert(&tmp);
541 shortp = (uint16_t *) &tmp;
542 while (count--) {
543 sum ^= ss_byteswap16(*shortp);
544 shortp++;
545 }
546#else
547 shortp = (uint16_t *) &disk_label;
548 while (count--)
549 sum ^= *shortp++;
550#endif
551
552 sum = sum & 0x0000FFFF;
553
554 disk_label.dkl_cksum = sum;
555 }
556
557#if defined(ARCH_X64)
558 void label_endian_convert(struct vtoc8_dk_label *dklp) {
559 int i;
560 dklp->dkl_vtoc.v_version = ss_byteswap32(dklp->dkl_vtoc.v_version);
561 dklp->dkl_vtoc.v_nparts = ss_byteswap16(dklp->dkl_vtoc.v_nparts);
562 for (i=0;i<VTOC8_NDKMAP;i++) {
563 dklp->dkl_vtoc.v_part[i].p_tag = ss_byteswap16(dklp->dkl_vtoc.v_part[i].p_tag);
564 dklp->dkl_vtoc.v_part[i].p_flag = ss_byteswap16(dklp->dkl_vtoc.v_part[i].p_flag);
565 dklp->dkl_vtoc.v_timestamp[i] = ss_byteswap32(dklp->dkl_vtoc.v_timestamp[i]);
566 dklp->dkl_map[i].dkl_cylno = ss_byteswap32(dklp->dkl_map[i].dkl_cylno);
567 dklp->dkl_map[i].dkl_nblk = ss_byteswap32(dklp->dkl_map[i].dkl_nblk);
568 }
569 for (i=0;i<3;i++)
570 dklp->dkl_vtoc.v_bootinfo[i] = ss_byteswap32(dklp->dkl_vtoc.v_bootinfo[i]);
571 dklp->dkl_vtoc.v_sanity = ss_byteswap32(dklp->dkl_vtoc.v_sanity);
572 dklp->dkl_write_reinstruct = ss_byteswap16(dklp->dkl_write_reinstruct);
573 dklp->dkl_read_reinstruct = ss_byteswap16(dklp->dkl_read_reinstruct);
574 dklp->dkl_rpm = ss_byteswap16(dklp->dkl_rpm);
575 dklp->dkl_pcyl = ss_byteswap16(dklp->dkl_pcyl);
576 dklp->dkl_apc = ss_byteswap16(dklp->dkl_apc);
577 dklp->dkl_intrlv = ss_byteswap16(dklp->dkl_intrlv);
578 dklp->dkl_ncyl = ss_byteswap16(dklp->dkl_ncyl);
579 dklp->dkl_acyl = ss_byteswap16(dklp->dkl_acyl);
580 dklp->dkl_nhead = ss_byteswap16(dklp->dkl_nhead);
581 dklp->dkl_nsect = ss_byteswap16(dklp->dkl_nsect);
582 dklp->dkl_magic = ss_byteswap16(dklp->dkl_magic);
583 dklp->dkl_cksum = ss_byteswap16(dklp->dkl_cksum);
584 }
585#endif
586
587 bool dump_misc(const char * dir){
588 char buf[1024];
589 sprintf(buf, "%s/%s.miscdmp",dir,disk_name);
590
591 FILE * fp = fopen(buf,"w");
592
593 if(!fp)
594 return true;
595
596 sprintf(buf,"read_delay %u\n",read_delay);
597 fwrite(buf,strlen(buf),1,fp);
598 sprintf(buf,"write_delay %u\n",write_delay);
599 fwrite(buf,strlen(buf),1,fp);
600 sprintf(buf,"debug_level %d\n",debug_level);
601 fwrite(buf,strlen(buf),1,fp);
602 sprintf(buf,"debug_file_name %s\n",debug_file_name);
603 fwrite(buf,strlen(buf),1,fp);
604
605 for(int i = 0; i < MAX_PARTITIONS; i++){
606 if(partitions[i]){
607 sprintf(buf,"Partition %d\n",i);
608 fwrite(buf,strlen(buf),1,fp);
609 sprintf(buf," lblk_reads %lld\n",partitions[i]->lblk_reads);
610 fwrite(buf,strlen(buf),1,fp);
611 sprintf(buf," lblk_writes %lld\n",partitions[i]->lblk_writes);
612 fwrite(buf,strlen(buf),1,fp);
613 sprintf(buf," lblk_reads_primary %lld\n",partitions[i]->lblk_reads_primary);
614 fwrite(buf,strlen(buf),1,fp);
615 sprintf(buf," lblk_writes_primary %lld\n",partitions[i]->lblk_writes_primary);
616 fwrite(buf,strlen(buf),1,fp);
617 sprintf(buf," lblk_reads_overlay %lld\n",partitions[i]->lblk_reads_overlay);
618 fwrite(buf,strlen(buf),1,fp);
619 sprintf(buf," lblk_writes_overlay %lld\n",partitions[i]->lblk_writes_overlay);
620 fwrite(buf,strlen(buf),1,fp);
621 sprintf(buf," lblk_reads_ckpt %lld\n",partitions[i]->lblk_reads_ckpt);
622 fwrite(buf,strlen(buf),1,fp);
623 }
624 }
625
626 fclose(fp);
627 return true;
628 }
629
630 bool restore_misc(const char * dir){
631 char buf[1024], keyword[1024];
632 sprintf(buf, "%s/%s.miscdmp",dir,disk_name);
633
634 FILE * fp = fopen(buf,"r");
635 if(!fp)
636 return true;
637
638 // support more flexible dump format
639 while (true) {
640 fgets(buf,1024,fp);
641 sscanf(buf,"%s", keyword);
642
643 if (!strcmp(keyword, "read_delay"))
644 sscanf(buf,"%s %u\n",keyword,&read_delay);
645 else if (!strcmp(keyword, "write_delay"))
646 sscanf(buf,"%s %u\n",keyword,&write_delay);
647 else if (!strcmp(keyword, "debug_level"))
648 sscanf(buf,"%s %d\n",keyword,&debug_level);
649 else if (!strcmp(keyword, "debug_file_name")){
650 sscanf(buf,"%s %s\n",keyword,&debug_file_name);
651 if(!strcmp(debug_file_name,"stderr")){
652 debug_file = stderr;
653 }else if(!strcmp(debug_file_name,"stdout")){
654 debug_file = stdout;
655 }else
656 debug_file = fopen(debug_file_name,"w+");
657 if(!debug_file)
658 debug_file = stderr;
659 }
660 else if (!strcmp(keyword, "Partition"))
661 break;
662 }
663
664 for(int i = 0; i < MAX_PARTITIONS; i++){
665 if(partitions[i]){
666 fgets(buf,1024,fp);
667 sscanf(buf," lblk_reads %lld\n",&partitions[i]->lblk_reads);
668 fgets(buf,1024,fp);
669 sscanf(buf," lblk_writes %lld\n",&partitions[i]->lblk_writes);
670 fgets(buf,1024,fp);
671 sscanf(buf," lblk_reads_primary %lld\n",&partitions[i]->lblk_reads_primary);
672 fgets(buf,1024,fp);
673 sscanf(buf," lblk_writes_primary %lld\n",&partitions[i]->lblk_writes_primary);
674 fgets(buf,1024,fp);
675 sscanf(buf," lblk_reads_overlay %lld\n",&partitions[i]->lblk_reads_overlay);
676 fgets(buf,1024,fp);
677 sscanf(buf," lblk_writes_overlay %lld\n",&partitions[i]->lblk_writes_overlay);
678 fgets(buf,1024,fp);
679 sscanf(buf," lblk_reads_ckpt %lld\n",&partitions[i]->lblk_reads_ckpt);
680 }
681 }
682 fclose(fp);
683 return true;
684
685 }
686
687 // to be called after all partitions have been seen and added
688 bool add_partition_fini();
689 bool create_overlays(){
690 bool ret = true;
691 for(int i = 0; i < MAX_PARTITIONS; i++)
692 if(partitions[i])
693 ret &= partitions[i]->create_overlay(overlaydir,disk_name);
694 return ret;
695 }
696
697public:
698 bool add_partition( int partition, const char * file, bool rw = false, bool has_vtoc = false );
699
700 ///////// external interface to the gdisk /////////
701 uint32_t disk_write_lblk( uint64_t lblkno, uint8_t *buf, uint32_t nblks );
702 uint32_t disk_read_lblk ( uint64_t lblkno, uint8_t *buf, uint32_t nblks );
703 bool dump( const char * dir );
704 bool restore( const char * dir );
705 const char * get_name(){ return disk_name; }
706 int get_target_id(){ return target_id;}
707 ///////// external interface to the gdisk /////////
708
709
710 void set_name(const char * s){
711 if(disk_name)
712 free((void*)disk_name);
713 disk_name = strdup(s);
714 }
715 void set_target(int id){target_id = id;}
716
717 int get_num_partitions() { return num_partitions; }
718
719 void delete_overlays() {
720 for(int i = 0; i < MAX_PARTITIONS; i++)
721 if(partitions[i])
722 if (partitions[i]->overlay_fd > 0)
723 close(partitions[i]->overlay_fd);
724 }
725
726 void set_read_delay(uint32_t delay){
727 read_delay = delay;
728 }
729
730 uint32_t get_read_delay(){
731 return(read_delay);
732 }
733
734 void set_write_delay(uint32_t delay){
735 write_delay = delay;
736 }
737
738 uint32_t get_write_delay(){
739 return(write_delay);
740 }
741
742 // parse string for diskdelay in the form "<rdelay>/<wdelay>"
743 void parse_ddelay(const char *ddelays, uint32_t *rdelay, uint32_t *wdelay){
744 char rdelays[100];
745
746 strcpy(rdelays, ddelays);
747 char *wdelays = strchr(rdelays, '/');
748 if (wdelays){
749 *wdelays = '\0';
750 wdelays++; // ptr to write delay
751 }else{
752 wdelays = rdelays; // same as read delay
753 }
754
755 *rdelay = atoi(rdelays);
756 *wdelay = atoi(wdelays);
757 if (*rdelay & 0x80000000) *rdelay = 0;
758 if (*wdelay & 0x80000000) *wdelay = 0;
759 }
760
761 void set_disk_delay(const char * s) {
762 uint32_t rdelay, wdelay;
763 parse_ddelay(s, &rdelay, &wdelay);
764 set_read_delay(rdelay);
765 set_write_delay(wdelay);
766 }
767
768 Disk( const char * name );
769 ~Disk(){}
770
771 // UI functions
772 virtual void display_label();
773 virtual void display_geometry();
774 virtual void display_stats();
775 virtual void display_partitions(int part_num = -1); // -1 displays all
776 virtual void display_disk_delay();
777 virtual void set_debug_level(int l);
778 virtual void set_debug_file(const char * file);
779 virtual void display_vpd(){}
780 virtual void display_help();
781 virtual void handle_ui(int argc, char * argv[]){
782
783 if(!strcmp(argv[2],"label")){
784 display_label();
785 }
786 else if(!strcmp(argv[2],"geometry")){
787 display_geometry();
788 }else if(!strcmp(argv[2],"stat")){
789 display_stats();
790 }else if(!strcmp(argv[2],"partitions")){
791 if(argv[3]){
792 int p = strtol(argv[3],0,0);
793 if( p < 0 || p >= MAX_PARTITIONS){
794 fprintf(debug_file,"%s Partition number %d out of range\n",disk_name,p);
795 return;
796 }
797 display_partitions(p);
798 }else
799 display_partitions(-1);
800 }else if(!strcmp(argv[2],"vpd")){
801 display_vpd();
802 }else if(!strcmp(argv[2],"op")){
803 if(argv[3])
804 set_debug_file(argv[3]);
805 else
806 fprintf(debug_file," %s\n",debug_file_name);
807 }else if(!strcmp(argv[2],"debug")){
808 if(argv[3]){
809 debug_level = strtol(argv[3],0,0);
810 set_debug_level(debug_level);
811 }else
812 fprintf(debug_file,"%s: debug level %d\n",disk_name,debug_level);
813 }else if (!strcmp(argv[2],"dd")){
814 if (argv[3])
815 set_disk_delay(argv[3]);
816 else
817 display_disk_delay();
818 }else
819 fprintf(debug_file,"gdisk: unknown command %s\n",argv[2]);
820
821 return;
822 }
823};
824
825
826class SCSIDisk: public Disk{
827
828 SCSI_Inquiry_Data sid;
829 Supported_VPD sv;
830 Unit_Serial_Number usn;
831 Implemented_Operating_Definition iod;
832 Device_Identification di;
833 FC_Device_Identification fdi;
834
835
836 uint8_t *vendorid; // Drive Standard Inquiry info
837 int sizeof_vendorid;
838 uint8_t *productid;
839 int sizeof_productid;
840 uint8_t *revisionid;
841 int sizeof_revisionid;
842 uint8_t *serialno; // NOTE, Sun Qualified Disks have 12 (not 8) bytes !!!!
843 int sizeof_serialno;
844 uint8_t *prodserialno; // Unit Serial Number Inquiry (code 80h) info
845 int sizeof_prodserialno;
846 uint8_t *brdserialno;
847 int sizeof_brdserialno;
848 uint8_t *portwwn; // Devide Identification Inquiry (code 83h) info
849 int sizeof_portwwn;
850 uint8_t *nodewwn;
851 int sizeof_nodewwn;
852
853 void copy(uint8_t * copy_to, int size_to, const char * copy_from){
854 int size = strlen(copy_from);
855 if(strlen(copy_from) > size_to){
856 fprintf(debug_file,"WARNING: string %s longer than %d. Truncated\n",copy_from,size_to);
857 size = size_to;
858 }
859 memset((void*)copy_to,0x20,size_to); // initialize with space chars
860 bcopy(copy_from,copy_to,size);
861 }
862
863
864public:
865 int Supported_VPD_size;
866
867 // external interface to the SCSI/FC Disk. Includes the Disk interface
868 // functions as well.
869
870 SCSIDisk();
871 ~SCSIDisk();
872 bool parse_config(const char * filename, FILE *, int target = -1);
873 const char * get_SCSI_Inquiry_Data() { return (const char *) &sid; }
874 const char * get_Supported_VPD() { return (const char *) &sv; }
875 const char * get_Unit_Serial_Number() { return (const char *) &usn; }
876 const char * get_Implemented_Operating_Definition() { return (const char *) &iod; }
877 const char * get_Device_Identification() { return (const char *) &di; }
878 const char * get_FC_Device_Identification() { return (const char *) &fdi; }
879 uint64_t get_capacity() {
880 uint64_t capacity = disk_label.dkl_ncyl * disk_label.dkl_nhead * disk_label.dkl_nsect;
881 if(disk_label.dkl_acyl)
882 capacity += disk_label.dkl_nhead * disk_label.dkl_nsect;
883 return capacity;
884 }
885
886 //////////////////// end external interface /////////////////////
887
888 void set_vendor_id(const char * str){
889 copy(vendorid,sizeof_vendorid,str);
890 }
891 void set_product_id(const char * str){
892 copy(productid,sizeof_productid,str);
893 }
894 void set_revision_id(const char * str){
895 copy(revisionid,sizeof_revisionid,str);
896 }
897 void set_serial_no(const char * str){
898 copy(serialno,sizeof_serialno,str);
899 }
900 void set_prodserial_no(const char * str){
901 copy(prodserialno,sizeof_prodserialno,str);
902 }
903 void set_brdserial_no(const char * str){
904 copy(brdserialno,sizeof_brdserialno,str);
905 }
906 void set_port_wwn(const char * str){
907 copy(portwwn,sizeof_portwwn,str);
908 }
909 void set_node_wwn(const char * str){
910 copy(nodewwn,sizeof_nodewwn,str);
911 }
912 void set_bytes_per_sector(int32_t n){
913 fprintf(debug_file,"%s: can not change bytes/sector\n",disk_name);
914 }
915 void set_sectors_per_track(int32_t n){
916 if( n > 0xffff){
917 fprintf(debug_file,"%s: value of sectors/track cannot be larger than 0xffff\n",disk_name);
918 exit(1);
919 }else
920 sectors_per_track = n;
921 user_geometry = true;
922 }
923 void set_tracks_per_cylinder(int32_t n){
924 if( n > 0xffff){
925 fprintf(debug_file,"%s: value of tracks/cylinder cannot be larger than 0xffff\n",disk_name);
926 exit(1);
927 }else
928 tracks_per_cylinder = n;
929 user_geometry = true;
930 }
931
932 // UI functions
933 void display_vpd();
934
935};
936
937
938
939
940#endif // __DISK_H__