* ========== Copyright Header Begin ==========================================
* OpenSPARC T2 Processor File: disk.h
* 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 ============================================
/*-------------------------- vtoc8 disk label -------------------------------*/
// On sparc platform _SUNOS_VTOC_8 is defined whereas on i386 platform
// _SUNOS_VTOC_16 is defined. We want to simulate sparc on i386 and
// cannot simply override these definitions, hence we have to lift vtoc/label
// out of system include files and create our own.
#define LEN_DKL_ASCII 128 /* length of dkl_asciilabel */
#define LEN_DKL_VVOL 8 /* length of v_volume */
#define DK_LABEL_SIZE 512 /* size of disk label */
#define READ_DELAY_DEFAULT 0 /* default disk read delay in microseconds */
#define WRITE_DELAY_DEFAULT 0 /* default disk write delay in microseconds */
* partition headers: section 1
* Fixed size for on-disk dk_label
int32_t dkl_cylno
; /* starting cylinder */
int32_t dkl_nblk
; /* number of blocks; if == 0, */
/* partition is undefined */
* partition headers: section 2,
* brought over from AT&T SVr4 vtoc structure.
uint16_t p_tag
; /* ID tag of partition */
uint16_t p_flag
; /* permission flag */
#define VTOC8_NDKMAP 8 /* # of logical partitions */
#define VTOC8_DK_LABEL_LOC 0 /* location of disk label */
uint32_t v_version
; /* layout version */
char v_volume
[LEN_DKL_VVOL
]; /* volume name */
uint16_t v_nparts
; /* number of partitions */
struct dk_map2 v_part
[VTOC8_NDKMAP
]; /* partition hdrs, sec 2 */
uint32_t v_bootinfo
[3]; /* info needed by mboot */
uint32_t v_sanity
; /* to verify vtoc sanity */
uint32_t v_reserved
[10]; /* free space */
int32_t v_timestamp
[VTOC8_NDKMAP
]; /* partition timestamp */
#define VTOC8_LEN_DKL_PAD (DK_LABEL_SIZE \
(sizeof (struct vtoc8_dk_vtoc)) + \
(sizeof (struct dk_map32) * VTOC8_NDKMAP) + \
(14 * (sizeof (uint16_t))) + \
(2 * (sizeof (uint16_t)))))
char dkl_ascii_label
[LEN_DKL_ASCII
]; /* for compatibility */
struct vtoc8_dk_vtoc dkl_vtoc
; /* vtoc inclusions from AT&T SVr4 */
uint16_t dkl_write_reinstruct
; /* # sectors to skip, writes */
uint16_t dkl_read_reinstruct
; /* # sectors to skip, reads */
char dkl_pad
[VTOC8_LEN_DKL_PAD
]; /* unused part of 512 bytes */
uint16_t dkl_rpm
; /* rotations per minute */
uint16_t dkl_pcyl
; /* # physical cylinders */
uint16_t dkl_apc
; /* alternates per cylinder */
uint16_t dkl_obs1
; /* obsolete */
uint16_t dkl_obs2
; /* obsolete */
uint16_t dkl_intrlv
; /* interleave factor */
uint16_t dkl_ncyl
; /* # of data cylinders */
uint16_t dkl_acyl
; /* # of alternate cylinders */
uint16_t dkl_nhead
; /* # of heads in this partition */
uint16_t dkl_nsect
; /* # of 512 byte sectors per track */
uint16_t dkl_obs3
; /* obsolete */
uint16_t dkl_obs4
; /* obsolete */
struct dk_map32 dkl_map
[VTOC8_NDKMAP
]; /* logical partition headers */
uint16_t dkl_magic
; /* identifies this label format */
uint16_t dkl_cksum
; /* xor checksum of sector */
/*---------------------------------------------------------------------------*/
extern "C" char *overlaydir
;
bitset(uint64_t s
,const char *n
= 0){
map_size
= s
%64 ? s
/64 + 1: s
/64;
name
= n
? strdup(n
):strdup("bitset");
map
= new uint64_t[map_size
];
for(uint64_t i
= 0; i
< map_size
; i
++)
map
[index
] |= 1ULL << pos
%64;
void clear(uint64_t pos
){
map
[index
] &= ~(1ULL << pos
%64);
return (map
[index
] >> pos
%64) & 0x1;
assert (s
->size
== size
);
for(uint64_t i
= 0; i
< map_size
; i
++ )
assert (s
->size
== size
);
for(uint64_t i
= 0; i
< map_size
; i
++ )
if(fwrite((void*)map
,map_size
* 8, 1, fp
) != 1){
fprintf(stderr
,"%s: dump failed\n",name
);
if(fread((void*)map
,map_size
* 8, 1, fp
) != 1){
fprintf(stderr
,"%s: restore failed\n",name
);
struct SCSI_Inquiry_Data
{ // Inquiry returns this
uint8_t devType
; // 0 Device type,
uint8_t devTypeMod
; // 1 Device type modifier
uint8_t version
; // 2 ISO/ECMA/ANSI version
uint8_t format
; // 3 Response data format
uint8_t length
; // 4 Additional Length
uint8_t reserved5
; // 5 Reserved
uint8_t reserved6
; // 6 Reserved
uint8_t flags
; // 7 Capability flags
uint8_t vendor
[8]; // 8-15 Vendor-specific
uint8_t product
[16]; // 16-31 Product id
uint8_t revision
[4]; // 32-35 Product revision
uint8_t serialnum
[8]; // 36-43 Drive Serial Number
uint8_t vendorSpecific
[12];// 36-55 Vendor stuff
uint8_t moreReserved
[40]; // 56-95 Reserved
uint8_t copyright
[48]; // 96-143 copyright data
devType
= 0x00; /* peripheral type, 0 => disk */
devTypeMod
= 0x00; /* zero */
version
= 0x02; /* 2 => device commands: SCSI-2 */
format
= 0x02; /* 2 => reply format: SCSI-2 */
length
= 0x8b; /* page len = number bytes following = (sizeof - 5) */
reserved5
= 0x00; /* feature bits */
reserved6
= 0x00; /* feature bits */
flags
= 0x00; /* feature bits */
strncpy((char*)vendor
, "YOYODYNE",sizeof(vendor
)); /* char VendorID[8] */
strncpy((char*)product
,"Turbo Frisbee ",sizeof(product
));/* char ProductID[16] */
strncpy((char*)revision
,"0000",sizeof(revision
)); /* char RevisionID[4] */
strncpy((char*)serialnum
," ",sizeof(serialnum
)); /* char SerialNumber[8] */
bzero((char*)vendorSpecific
, sizeof(vendorSpecific
));
bzero((char*)moreReserved
, sizeof(moreReserved
));
strncpy((char*)copyright
, "Copyright (c) 2001 Yoyodyne All rights reserved.",sizeof(copyright
));
struct Supported_VPD
{ //0x00
Supported_VPD(){ // by default support all data
devType
= 0x0; /* peripheral type */
pageCode
= 0x0; /* request code for this reply page */
pageLength
= 0xc; /* page len = number bytes following = (sizeof - 4) */
pageList
[0] = 0x00; /* Supported Vital Product Data pages */
pageList
[1] = 0x80; /* Unit Serial Number page */
pageList
[2] = 0x81; /* Implemented Operating Definition page */
pageList
[3] = 0x83; /* Device Identification page */
pageList
[4] = 0xc0; /* Firmware Numbers page */
pageList
[5] = 0xc1; /* Date Code page */
pageList
[6] = 0xc2; /* Jumper Settings page */
pageList
[7] = 0xc3; /* Device Behaviour page */
pageList
[8] = 0xd1; /* Vendor Specific page */
pageList
[9] = 0xd2; /* Vendor Specific page */
pageList
[10] = 0xd3; /* Vendor Specific page */
pageList
[11] = 0xd4; /* Vendor Specific page */
struct Unit_Serial_Number
{ // 0x80
uint8_t productSerialNumber
[8];
uint8_t boardSerialNumber
[12];
devType
= 0x00; /* peripheral type */
pageCode
= 0x80; /* request code for this reply page */
pageLength
= 0x14; /* page len = number bytes following = (sizeof - 4) */
strncpy((char*)productSerialNumber
," ",sizeof(productSerialNumber
));
strncpy((char*)boardSerialNumber
, " ",sizeof(boardSerialNumber
));
struct Implemented_Operating_Definition
{ // 0x81
Implemented_Operating_Definition(){
devType
= 0x00; /* peripheral type */
pageCode
= 0x81; /* request code for this reply page */
pageLength
= 0x03; /* page len = number bytes following = (sizeof - 4) */
currentOpDef
= 0x01; /* Current Operating Definition, 1 => SCSI-2 */
defaultOpDef
[0] = 0x01; /* Default Operating Definition, 1 => SCSI-2 */
defaultOpDef
[1] = 0x01; /* Unknown Operating Definition, 1 => SCSI-2 */
struct Device_Identification
{ // 0x83
devType
= 0x00; /* peripheral type */
pageCode
= 0x83; /* request code for this reply page */
pageLength
= 0x00; /* page len = number bytes following = (sizeof - 4) */
struct FC_Device_Identification
:public Device_Identification
{
FC_Device_Identification():Device_Identification(){
codeSet0
= codeSet1
= 0x01; /* code: 1=binary (,2=ascii) */
idType_Asso0
= 0x13; /* assoc: 1=port (,0=node); uid type: 3=NAA */
idType_Asso1
= 0x03; /* assoc: 0=node (,1=port); uid type: 3=NAA */
reserved10
= reserved11
= 0x00;
idLength0
= idLength1
= 0x8;
pageLength
= 0x18; // override pagelength in base
// other page codes are not supported.
static const int BYTES_PER_SECTOR
= 512;
static const int DISK_PAGE_SIZE
= 512; // granularity of r/w to backup/overlay files
// this is chosen same as BYTES_PER_SECTOR to handle/simplify the case of
// overlapping partitions (can be specified by real vtoc's). The disk image
// may not be aligned to a larger mutiple of DISK_PAGE_SIZE which may create
// undetected holes in lblks.
static const int BLOCKS_PER_PAGE
= DISK_PAGE_SIZE
/BYTES_PER_SECTOR
;
// Real physical file name or disk partition name in which
// data for the simulated disk partition exists.
const char* part_filename
;
// simulated disk partition name
// filename of shadow of simulated disk partition in which
// write data is stored. This shadow file is used only when
// the partition is attached read-only which is the default.
const char* overlay_filename
;
const char* ckpt_filename
;
// if set, write enabled. Otherwise, read only
// true if the parition is an actual host system disk. set from st_rdev of
// the stat buf of part_filename
// this partition has vtoc from the real disk if true
// size of simulated disk partition in bytes
// size of simulated disk partition in logical blocks OR
// the value read from a real vtoc. Can be different from
// starting disk block number of this simulated disk partition
// ending disk block number of this simulated disk partition
// index,flag and tag of this simulated disk partition
// bitmap of pages in the disk partition that have been modified.
// The modified pages will be in shadow file. The bitmap is used
// only when the partiton is attached read-only which is the default.
bool lblk_inrange(uint64_t lblk
){
if( (lblk
>= start_lblk
) && (lblk
<= end_lblk
) )
bool create_overlay(const char * dir
, const char * disk
){
return true; // no need for overlays, partition is rw
// make this function reentrant
if(overlay_bitmap
&& overlay_fd
!= -1)
// create the bitmap where each bit corresponds to 8K size block
bitmap_size
= (nblks
*BYTES_PER_SECTOR
+ DISK_PAGE_SIZE
- 1)/DISK_PAGE_SIZE
;
if( overlay_bitmap
== 0 )
overlay_bitmap
= new bitset(bitmap_size
,part_name
);
sprintf(buf
,"%s/%s.%s.shadow",dir
,disk
,part_name
);
overlay_filename
= strdup(buf
);
overlay_fd
= open(overlay_filename
,O_RDWR
|O_CREAT
|O_LARGEFILE
|O_TRUNC
,0666);
fprintf(debug_file
,"%s: could not create overlay file %s\n",\
part_name
,overlay_filename
);
// make the overlay file size a multiple of DISK_PAGE_SIZE
if(lseek(overlay_fd
, bitmap_size
*DISK_PAGE_SIZE
- 1,SEEK_SET
) == -1){
fprintf(debug_file
,"%s: could not lseek overlay file %s\n",\
part_name
,overlay_filename
);
// set the size of this file
if(write(overlay_fd
, "", 1) != 1){
fprintf(debug_file
,"%s: could not write overlay file %s\n",\
part_name
,overlay_filename
);
void set_debug_level( int level
){ debug_level
= level
; }
void set_debug_file( FILE* f
){ debug_file
= f
; }
uint32_t Write(uint64_t lblkno
, uint8_t *buf
, uint32_t numblks
);
uint32_t Read(uint64_t lblkno
, uint8_t *buf
, uint32_t numblks
);
bool restore(const char * dir
, const char * disk_name
);
bool dump(const char * dir
, const char * disk_name
);
uint64_t lblk_reads_primary
;
uint64_t lblk_writes_primary
;
uint64_t lblk_reads_overlay
;
uint64_t lblk_writes_overlay
;
uint64_t lblk_reads_ckpt
;
static const int MAX_TRIES
= 10;
static const int BYTES_PER_SECTOR
= 512;
static const int MAX_PARTITIONS
= 8;
static const int VTOC_SANITY
= 0x600ddeee;
static const int DKLABEL_RPM
= 5400;
static const int DKLABEL_INTRLV
= 1;
static const int DKLABEL_ACYL
= 0;
static const int DKLABEL_MAGIC
= 0xDABE;
char debug_file_name
[1024];
static bool UI_registered
;
// disk label structure. Used only if faking a vtoc/disk label
struct vtoc8_dk_label disk_label
;
Partition
*partitions
[MAX_PARTITIONS
];
// init the disk label in case of fake vtoc
bool is_s2
; // true if disk has a single s2 partition
int vtoc_partition
; // vtoc partition, in case of real disk vtoc, else -1
bool fake_vtoc
; // true if SAM needs to fake vtoc, false otherwise
uint32_t read_delay
; // disk read delay
uint32_t write_delay
; // disk write delay
// some parameters, useful when faking vtoc
uint16_t sectors_per_track
; // dkl_nsect, default 32
uint16_t tracks_per_cylinder
; // dkl_nhead, default 16
uint16_t bytes_per_sector
; // default 512
uint32_t num_cylinder
; // total number of cyinders in disk
uint64_t num_blks
; // total number of disk blocks in all partitions
// note capacity command will return
count
= sizeof(disk_label
) / (int) (sizeof(uint16_t));
struct vtoc8_dk_label tmp
;
bcopy(&disk_label
, &tmp
, sizeof(disk_label
));
label_endian_convert(&tmp
);
shortp
= (uint16_t *) &tmp
;
sum
^= ss_byteswap16(*shortp
);
shortp
= (uint16_t *) &disk_label
;
disk_label
.dkl_cksum
= sum
;
void label_endian_convert(struct vtoc8_dk_label
*dklp
) {
dklp
->dkl_vtoc
.v_version
= ss_byteswap32(dklp
->dkl_vtoc
.v_version
);
dklp
->dkl_vtoc
.v_nparts
= ss_byteswap16(dklp
->dkl_vtoc
.v_nparts
);
for (i
=0;i
<VTOC8_NDKMAP
;i
++) {
dklp
->dkl_vtoc
.v_part
[i
].p_tag
= ss_byteswap16(dklp
->dkl_vtoc
.v_part
[i
].p_tag
);
dklp
->dkl_vtoc
.v_part
[i
].p_flag
= ss_byteswap16(dklp
->dkl_vtoc
.v_part
[i
].p_flag
);
dklp
->dkl_vtoc
.v_timestamp
[i
] = ss_byteswap32(dklp
->dkl_vtoc
.v_timestamp
[i
]);
dklp
->dkl_map
[i
].dkl_cylno
= ss_byteswap32(dklp
->dkl_map
[i
].dkl_cylno
);
dklp
->dkl_map
[i
].dkl_nblk
= ss_byteswap32(dklp
->dkl_map
[i
].dkl_nblk
);
dklp
->dkl_vtoc
.v_bootinfo
[i
] = ss_byteswap32(dklp
->dkl_vtoc
.v_bootinfo
[i
]);
dklp
->dkl_vtoc
.v_sanity
= ss_byteswap32(dklp
->dkl_vtoc
.v_sanity
);
dklp
->dkl_write_reinstruct
= ss_byteswap16(dklp
->dkl_write_reinstruct
);
dklp
->dkl_read_reinstruct
= ss_byteswap16(dklp
->dkl_read_reinstruct
);
dklp
->dkl_rpm
= ss_byteswap16(dklp
->dkl_rpm
);
dklp
->dkl_pcyl
= ss_byteswap16(dklp
->dkl_pcyl
);
dklp
->dkl_apc
= ss_byteswap16(dklp
->dkl_apc
);
dklp
->dkl_intrlv
= ss_byteswap16(dklp
->dkl_intrlv
);
dklp
->dkl_ncyl
= ss_byteswap16(dklp
->dkl_ncyl
);
dklp
->dkl_acyl
= ss_byteswap16(dklp
->dkl_acyl
);
dklp
->dkl_nhead
= ss_byteswap16(dklp
->dkl_nhead
);
dklp
->dkl_nsect
= ss_byteswap16(dklp
->dkl_nsect
);
dklp
->dkl_magic
= ss_byteswap16(dklp
->dkl_magic
);
dklp
->dkl_cksum
= ss_byteswap16(dklp
->dkl_cksum
);
bool dump_misc(const char * dir
){
sprintf(buf
, "%s/%s.miscdmp",dir
,disk_name
);
FILE * fp
= fopen(buf
,"w");
sprintf(buf
,"read_delay %u\n",read_delay
);
fwrite(buf
,strlen(buf
),1,fp
);
sprintf(buf
,"write_delay %u\n",write_delay
);
fwrite(buf
,strlen(buf
),1,fp
);
sprintf(buf
,"debug_level %d\n",debug_level
);
fwrite(buf
,strlen(buf
),1,fp
);
sprintf(buf
,"debug_file_name %s\n",debug_file_name
);
fwrite(buf
,strlen(buf
),1,fp
);
for(int i
= 0; i
< MAX_PARTITIONS
; i
++){
sprintf(buf
,"Partition %d\n",i
);
fwrite(buf
,strlen(buf
),1,fp
);
sprintf(buf
," lblk_reads %lld\n",partitions
[i
]->lblk_reads
);
fwrite(buf
,strlen(buf
),1,fp
);
sprintf(buf
," lblk_writes %lld\n",partitions
[i
]->lblk_writes
);
fwrite(buf
,strlen(buf
),1,fp
);
sprintf(buf
," lblk_reads_primary %lld\n",partitions
[i
]->lblk_reads_primary
);
fwrite(buf
,strlen(buf
),1,fp
);
sprintf(buf
," lblk_writes_primary %lld\n",partitions
[i
]->lblk_writes_primary
);
fwrite(buf
,strlen(buf
),1,fp
);
sprintf(buf
," lblk_reads_overlay %lld\n",partitions
[i
]->lblk_reads_overlay
);
fwrite(buf
,strlen(buf
),1,fp
);
sprintf(buf
," lblk_writes_overlay %lld\n",partitions
[i
]->lblk_writes_overlay
);
fwrite(buf
,strlen(buf
),1,fp
);
sprintf(buf
," lblk_reads_ckpt %lld\n",partitions
[i
]->lblk_reads_ckpt
);
fwrite(buf
,strlen(buf
),1,fp
);
bool restore_misc(const char * dir
){
char buf
[1024], keyword
[1024];
sprintf(buf
, "%s/%s.miscdmp",dir
,disk_name
);
FILE * fp
= fopen(buf
,"r");
// support more flexible dump format
sscanf(buf
,"%s", keyword
);
if (!strcmp(keyword
, "read_delay"))
sscanf(buf
,"%s %u\n",keyword
,&read_delay
);
else if (!strcmp(keyword
, "write_delay"))
sscanf(buf
,"%s %u\n",keyword
,&write_delay
);
else if (!strcmp(keyword
, "debug_level"))
sscanf(buf
,"%s %d\n",keyword
,&debug_level
);
else if (!strcmp(keyword
, "debug_file_name")){
sscanf(buf
,"%s %s\n",keyword
,&debug_file_name
);
if(!strcmp(debug_file_name
,"stderr")){
}else if(!strcmp(debug_file_name
,"stdout")){
debug_file
= fopen(debug_file_name
,"w+");
else if (!strcmp(keyword
, "Partition"))
for(int i
= 0; i
< MAX_PARTITIONS
; i
++){
sscanf(buf
," lblk_reads %lld\n",&partitions
[i
]->lblk_reads
);
sscanf(buf
," lblk_writes %lld\n",&partitions
[i
]->lblk_writes
);
sscanf(buf
," lblk_reads_primary %lld\n",&partitions
[i
]->lblk_reads_primary
);
sscanf(buf
," lblk_writes_primary %lld\n",&partitions
[i
]->lblk_writes_primary
);
sscanf(buf
," lblk_reads_overlay %lld\n",&partitions
[i
]->lblk_reads_overlay
);
sscanf(buf
," lblk_writes_overlay %lld\n",&partitions
[i
]->lblk_writes_overlay
);
sscanf(buf
," lblk_reads_ckpt %lld\n",&partitions
[i
]->lblk_reads_ckpt
);
// to be called after all partitions have been seen and added
bool add_partition_fini();
for(int i
= 0; i
< MAX_PARTITIONS
; i
++)
ret
&= partitions
[i
]->create_overlay(overlaydir
,disk_name
);
bool add_partition( int partition
, const char * file
, bool rw
= false, bool has_vtoc
= false );
///////// external interface to the gdisk /////////
uint32_t disk_write_lblk( uint64_t lblkno
, uint8_t *buf
, uint32_t nblks
);
uint32_t disk_read_lblk ( uint64_t lblkno
, uint8_t *buf
, uint32_t nblks
);
bool dump( const char * dir
);
bool restore( const char * dir
);
const char * get_name(){ return disk_name
; }
int get_target_id(){ return target_id
;}
///////// external interface to the gdisk /////////
void set_name(const char * s
){
void set_target(int id
){target_id
= id
;}
int get_num_partitions() { return num_partitions
; }
for(int i
= 0; i
< MAX_PARTITIONS
; i
++)
if (partitions
[i
]->overlay_fd
> 0)
close(partitions
[i
]->overlay_fd
);
void set_read_delay(uint32_t delay
){
uint32_t get_read_delay(){
void set_write_delay(uint32_t delay
){
uint32_t get_write_delay(){
// parse string for diskdelay in the form "<rdelay>/<wdelay>"
void parse_ddelay(const char *ddelays
, uint32_t *rdelay
, uint32_t *wdelay
){
strcpy(rdelays
, ddelays
);
char *wdelays
= strchr(rdelays
, '/');
wdelays
++; // ptr to write delay
wdelays
= rdelays
; // same as read delay
if (*rdelay
& 0x80000000) *rdelay
= 0;
if (*wdelay
& 0x80000000) *wdelay
= 0;
void set_disk_delay(const char * s
) {
parse_ddelay(s
, &rdelay
, &wdelay
);
Disk( const char * name
);
virtual void display_label();
virtual void display_geometry();
virtual void display_stats();
virtual void display_partitions(int part_num
= -1); // -1 displays all
virtual void display_disk_delay();
virtual void set_debug_level(int l
);
virtual void set_debug_file(const char * file
);
virtual void display_vpd(){}
virtual void display_help();
virtual void handle_ui(int argc
, char * argv
[]){
if(!strcmp(argv
[2],"label")){
else if(!strcmp(argv
[2],"geometry")){
}else if(!strcmp(argv
[2],"stat")){
}else if(!strcmp(argv
[2],"partitions")){
int p
= strtol(argv
[3],0,0);
if( p
< 0 || p
>= MAX_PARTITIONS
){
fprintf(debug_file
,"%s Partition number %d out of range\n",disk_name
,p
);
}else if(!strcmp(argv
[2],"vpd")){
}else if(!strcmp(argv
[2],"op")){
fprintf(debug_file
," %s\n",debug_file_name
);
}else if(!strcmp(argv
[2],"debug")){
debug_level
= strtol(argv
[3],0,0);
set_debug_level(debug_level
);
fprintf(debug_file
,"%s: debug level %d\n",disk_name
,debug_level
);
}else if (!strcmp(argv
[2],"dd")){
fprintf(debug_file
,"gdisk: unknown command %s\n",argv
[2]);
class SCSIDisk
: public Disk
{
Implemented_Operating_Definition iod
;
Device_Identification di
;
FC_Device_Identification fdi
;
uint8_t *vendorid
; // Drive Standard Inquiry info
uint8_t *serialno
; // NOTE, Sun Qualified Disks have 12 (not 8) bytes !!!!
uint8_t *prodserialno
; // Unit Serial Number Inquiry (code 80h) info
uint8_t *portwwn
; // Devide Identification Inquiry (code 83h) info
void copy(uint8_t * copy_to
, int size_to
, const char * copy_from
){
int size
= strlen(copy_from
);
if(strlen(copy_from
) > size_to
){
fprintf(debug_file
,"WARNING: string %s longer than %d. Truncated\n",copy_from
,size_to
);
memset((void*)copy_to
,0x20,size_to
); // initialize with space chars
bcopy(copy_from
,copy_to
,size
);
// external interface to the SCSI/FC Disk. Includes the Disk interface
bool parse_config(const char * filename
, FILE *, int target
= -1);
const char * get_SCSI_Inquiry_Data() { return (const char *) &sid
; }
const char * get_Supported_VPD() { return (const char *) &sv
; }
const char * get_Unit_Serial_Number() { return (const char *) &usn
; }
const char * get_Implemented_Operating_Definition() { return (const char *) &iod
; }
const char * get_Device_Identification() { return (const char *) &di
; }
const char * get_FC_Device_Identification() { return (const char *) &fdi
; }
uint64_t get_capacity() {
uint64_t capacity
= disk_label
.dkl_ncyl
* disk_label
.dkl_nhead
* disk_label
.dkl_nsect
;
capacity
+= disk_label
.dkl_nhead
* disk_label
.dkl_nsect
;
//////////////////// end external interface /////////////////////
void set_vendor_id(const char * str
){
copy(vendorid
,sizeof_vendorid
,str
);
void set_product_id(const char * str
){
copy(productid
,sizeof_productid
,str
);
void set_revision_id(const char * str
){
copy(revisionid
,sizeof_revisionid
,str
);
void set_serial_no(const char * str
){
copy(serialno
,sizeof_serialno
,str
);
void set_prodserial_no(const char * str
){
copy(prodserialno
,sizeof_prodserialno
,str
);
void set_brdserial_no(const char * str
){
copy(brdserialno
,sizeof_brdserialno
,str
);
void set_port_wwn(const char * str
){
copy(portwwn
,sizeof_portwwn
,str
);
void set_node_wwn(const char * str
){
copy(nodewwn
,sizeof_nodewwn
,str
);
void set_bytes_per_sector(int32_t n
){
fprintf(debug_file
,"%s: can not change bytes/sector\n",disk_name
);
void set_sectors_per_track(int32_t n
){
fprintf(debug_file
,"%s: value of sectors/track cannot be larger than 0xffff\n",disk_name
);
void set_tracks_per_cylinder(int32_t n
){
fprintf(debug_file
,"%s: value of tracks/cylinder cannot be larger than 0xffff\n",disk_name
);