/* /usr/src/mach/utils/wrdl.c Version 1.0 Purpose: Create a disk label for a PC532 Mach SCSI disc. Invocation: ./wrdl > /dev/rsd1c Author: jhs@ Released Public Domain 1-93 Based on a simpler program of same name by gj@_ERASE_freebsd.org (thanks Gary). To Do: - Maybe convert to use /etc/disktab format later. - If nothing defined, create a valid disc label, but with all sizes 0. Usage: For a demo run, try cc -Djulian_663476 wrdl.c ; a.out | rddl See Also: gj's rddl.c (for which I merely improved the display format). */ /* ------------------------------------------------------------------------- */ /* USER SPECIFIABLE DISC MODEL NAME & PARTITION SIZES - CHANGE AT WILL. - Standard size partitions ease partition clone copying between discs. - Partitions not aligned to cylinder boundaries may be slightly slower, but - Cylinder alignement seems to not be achievable on some SCSI discs, as Seagate ST4767 94601 Spec. P176 says: "Because of Zone Bit Recording(TM), there exists no single value for sectors per track" It is also worth noting, the Seagate Spec. also says: "number of user sectors/track may be less than the reported value, depending on sparing scheme selected". - The following optional defines may be asserted ( either here or from the cc command ) : Name Meaning If Defined SHORT_KERNEL Reduce 1st kernel by 1 sector from normal KERNEL_SIZE (so that 2nd kernel offset is KERNEL_SIZE). ONE_KERNEL Have just 1 kernel, instead of normal 2 adjacent kernels. TWO_ROOTS Have 2 adjacent roots, else just 1 normally. KERNEL_SIZE Size of kernel partition (1st kernel might be 1 less) ROOT_SIZE Size of root partition USR_SIZE Size of usr partition (not used for usr1) m_Something Generic model type attributes. - Model names are all either of form - m_MANUFACTURER_MODEL_m_123456_p_123456, with first 123456 being declared size of media, second being declared size of C partition This is done because some of the entries are obviously wrong, & need to be corrected, but users must agree first. - m_MANUFACTURER_MODEL_s_123456 where media size & C partition size are declared the same. Please mail jhs@ name of manufacturer & model where _UNKNOWN is shown. */ #ifdef julian #define m_MICROPOLIS_1684v7_s_663476 #define TWO_ROOTS #endif /* } */ #ifdef jordan #define m_SEAGATE_ST1480N_s_832527 #define TWO_ROOTS #endif /* } */ #ifdef stuart #define m_MICROPOLIS_1375_s_284480 #endif /* } */ #ifdef khe /* { */ #define m_MICROPOLIS_1375_s_284480 #endif /* } */ #ifdef gary_288750 /* { */ /* what used to be known as MB140, without jordan variant */ #define m_UNKNOWN_GARY_OR_JORDAN_TO_SAY_s_288750 #define SHORT_KERNEL #define KERNEL_SIZE 1025 #define ROOT_SIZE 37800 #define USR_SIZE 248389 #define MB140_BACKWARD_COMPATIBLE_HACK #define PARTITION_CHANGES #endif /* } */ #ifdef gary_831488 /* { */ /* Previously known to Gary's wrdl.c as MB406 */ #define m_UNKNOWN_GARY_TO_SAY_s_831488 #define SHORT_KERNEL #define KERNEL_SIZE 1025 #define ROOT_SIZE 120000 #define USR_SIZE 240000 #define TWO_ROOTS #define PARTITION_CHANGES #endif /* } */ #ifdef gary_1006016 /* { */ /* Previously known as MB503 */ #define m_UNKNOWN_GARY_TO_SAY_s_1006016 #define SHORT_KERNEL #define KERNEL_SIZE 10560 #define ROOT_SIZE 119680 #define USR_SIZE 239360 #define TWO_ROOTS #define PARTITION_CHANGES #endif /* } */ /* ------------------------------------------------------------------------- If you'r using a drive type somebody else has already defined, you May not need to edit anything else in this file, However some old entries still have partition sizes hard-coded in ! (see PARTITION_CHANGES), & some have (CAPACITY_DISPARITY entries) ------------------------------------------------------------------------- GENERIC DEFAULT PREFERENCES - DO NOT CHANGE THESE (unless you are review all entries above also) */ #ifndef KERNEL_SIZE /* { */ #define KERNEL_SIZE 1280 #endif /* } */ #ifndef ROOT_SIZE /* { */ #define ROOT_SIZE 60000 #endif /* } */ #ifndef USR_SIZE /* { */ #define USR_SIZE 120000 #endif /* } */ /* ------------------------------------------------------------------------- */ /* Device driver minor inode number offsets - do not change order ( because although offsets are taken explicitly from here, other code in this file also assumes the same ordering) */ #define MINOR_0A_ROOT1 0 /* Partition # 4 */ #define MINOR_1B_ROOT2 1 /* Partition # 5 (optional) */ #define MINOR_2C_TOTAL 2 /* Whole Disc */ #define MINOR_3D_USR 3 /* Partition # 6 */ #define MINOR_4E_USR1 4 /* Partition # 7 (optional) */ #define MINOR_5F_DISKLABEL 5 /* Partition # 1 */ #define MINOR_6G_KERNEL1 6 /* Partition # 2 */ #define MINOR_7H_KERNEL2 7 /* Partition # 3 (optional) */ /* ------------------------------------------------------------------------- */ #include #include #include #include "../dl.h" #define BYTES_PER_SECTOR 512 unsigned char sector[BYTES_PER_SECTOR] ; u_long remainder ; /* unallocated sectors */ char **ARGV ; /* name of program */ /* Tell it how many sectors you want, it returns same number, if available, or maybe somewhat less, or 0 if [none left or none requested] (remember amount we want may be 0 for alternate root size) */ u_long sec_alloc(want,name) u_long want ; char* name ; { if ( want <= remainder ) { remainder -= want ; return(want) ; } fprintf(stderr,"%s: Warning %s partition size only %ld, not %ld.\n", *ARGV, name, (long)remainder, (long)want) ; want = remainder ; remainder = (u_long)0 ; return(want) ; } main(argc,argv,envp) int argc ; char **argv ; char **envp ; { struct disklabel *dl ; int fd ; int bytes ; int count ; ARGV = argv ; dl = (struct disklabel *)§or [LABELOFFSET] ; dl->d_magic = dl->d_magic2 = DISKMAGIC ; dl->d_type = DTYPE_SCSI ; strcpy(dl->d_typename,"SCSI") ; dl->d_secsize = (long)BYTES_PER_SECTOR ; #define EIGHT 8 dl->d_npartitions = EIGHT ; /* ------------------------------------------------------------------------- */ #define SIZE_DISKLABEL 1 #ifdef SHORT_KERNEL /* { */ #define SIZE_KERNEL1 ( KERNEL_SIZE - 1 ) #else /* }{ */ #define SIZE_KERNEL1 KERNEL_SIZE #endif /* } */ #ifdef ONE_KERNEL /* { One kernel space */ #define SIZE_KERNEL2 0 #else /* }{ Two Kernel spaces */ #define SIZE_KERNEL2 KERNEL_SIZE #endif /* } */ #ifdef TWO_ROOTS /* { Devote space for a spare emergency root */ #define SIZE_ROOT2 ROOT_SIZE #else /* }{ No spare root, Probably a small disc, */ #define SIZE_ROOT2 0 #endif /* } */ /* ------------------------------------------------------------------------- */ /* GENERIC PARAMETERS Some default values. Note, Where values are known for certain for a specific disk, they should be repeated in that #ifdef entry, thus protecting against possible change of defaults. */ dl->d_rpm = 3600 ; dl->d_interleave = 1 ; dl->d_cylskew = 0 ; dl->d_trackskew = 0 ; dl->d_headswitch = 0 ; /* head switch time, usec */ dl->d_trkseek = 5000 ; dl->d_acylinders = 3 ; /* I initialise to 1 here, because if we let C compiler init to 0, when Mach boots, something does a divide by zero, & boot fails. Init to 1 here means if we dont know specific values we dont have to set arbitrary dummy values */ dl->d_nsectors = dl->d_sparespertrack = dl->d_ntracks = dl->d_ncylinders = dl->d_rpm = 1 ; /* ------------------------------------------------------------------------- */ /* START OF: DISC MODEL NUMBER DEPENDENT GENERIC PARAMETERS Shouldnt need to be changed, unless the low level format utility (in the eprom of disc controller card, or scsi analyser) has invoked a format with non standard parameters (No aggregate parameters here, such as dl->d_sparespercyl, dl->d_secpercyl, dl->d_secperunit ) */ #ifdef m_MICROPOLIS_1375_s_284480 /* { values from jhs@ 142 MB 284480 sectors */ dl->d_nsectors = 35 ; /* 35 data + 1 spare, probably */ dl->d_sparespertrack = 1 ; dl->d_ntracks = 8 ; dl->d_ncylinders = 1016 ; dl->d_rpm = 3600 ; #define CAPACITY_DISPARITY #define MODEL_DEFINED #endif /* } */ #ifdef m_UNKNOWN_GARY_OR_JORDAN_TO_SAY_s_288750 /* { */ dl->d_nsectors = 35 ; dl->d_ntracks = 10 ; dl->d_ncylinders = 830 ; dl->d_sparespertrack = 1 ; dl->d_acylinders = 5 ; #define CAPACITY_DISPARITY #define MODEL_DEFINED #endif /* } */ #ifdef m_MICROPOLIS_1684v7_s_663476 /* { */ dl->d_nsectors = 54 ; dl->d_ntracks = 7 ; dl->d_ncylinders = 1776 ; #define CAPACITY_DISPARITY #define MODEL_DEFINED #endif /* } */ #ifdef m_UNKNOWN_GARY_TO_SAY_s_831488 /* { */ dl->d_nsectors = 62 ; dl->d_ntracks = 9 ; dl->d_ncylinders = 1476 ; dl->d_sparespertrack = 1 ; dl->d_acylinders = 2 ; #define CAPACITY_DISPARITY #define MODEL_DEFINED #endif /* } */ #ifdef m_UNKNOWN_GARY_TO_SAY_s_1006016 /* { */ dl->d_nsectors = 64 ; dl->d_ntracks = 11 ; dl->d_ncylinders = 1429 ; dl->d_sparespertrack = 1 ; dl->d_acylinders = 2 ; #define CAPACITY_DISPARITY #define MODEL_DEFINED #endif /* } */ #ifdef m_SEAGATE_ST4767N_s_1299840 /* { values from jhs@ */ dl->d_ntracks = 15 ; /* Seagate info. */ dl->d_rpm = 4800 ;/* Seagate info. */ dl->d_sparespertrack = 1 ; /* Seagate 94601 Spec. P174 */ dl->d_interleave = 1 ; /* Seagate 94601 Spec. P174 */ dl->d_cylskew = 0x16; /* Seagate 94601 Spec. P174 */ dl->d_trackskew = 0xC ; /* Seagate 94601 Spec. P174 */ dl->d_trkseek = 2500 ; /* Seagate Sales Leaflet */ dl->d_acylinders = 2 ; /* Seagate sample Page 15 94601 Spec. */ /* Suspect values below */ dl->d_ncylinders = 1356 /* 1356 is Seagate info. */ - dl->d_acylinders ; dl->d_nsectors = 71 - dl->d_sparespertrack ; /* 70 */ /* Seagate 94601 Spec. P176 says: number of user sectors/track may be less than the reported value, depending onsparing scheme selected */ #define CAPACITY_DISPARITY #define MODEL_DEFINED #endif /* } */ #ifdef m_SEAGATE_ST1096N /* { arbitrary dummy figures */ #define CAPACITY_DISPARITY #define MODEL_DEFINED #endif /* } */ #ifdef m_SEAGATE_ST1480N_s_832527 #define CAPACITY_DISPARITY #define MODEL_DEFINED #endif /* } */ #ifndef MODEL_DEFINED /* { */ This uncommented text is to enable the compiler to detect that you have failed to select a disc model type ; #endif /* } */ /* ------------------------------------------------------------------------- */ /* Calculate aggregate parameters here. */ dl->d_sparespercyl = dl->d_sparespertrack * dl->d_ntracks ; dl->d_secpercyl = dl->d_nsectors * dl->d_ntracks ; /* how many sectors should be in a disc */ dl->d_secperunit = (dl->d_secpercyl - dl->d_sparespercyl) * ( dl->d_ncylinders - dl->d_acylinders) ; /* Note this dl->d_secperunit never seems to be what we get in fact */ dl->d_partitions[MINOR_2C_TOTAL].p_size = 0 ; /* mark as unset */ /* ------------------------------------------------------------------------- */ #ifdef CAPACITY_DISPARITY /* { */ /* - Usually the theoretical number of sectors on a disc does not concur with what is actually available, hence this CAPACITY_DISPARITY ifdef. - To find a disc's actual capacity, do a hard reformat, write a much-larger-than-expected disc label, then do a raw read of the whole disc with dd & note record count. ( dd if=/dev/rsd0c of=/dev/null ) - The reason jordan's totals are less than disc should provide, is that he often guessed a capacity, then rounded down, rather than wait for a dd capacity test to run. */ #ifdef m_MICROPOLIS_1375_s_284480 dl->d_secperunit = 284480 ; #define DISPARITY_DEFINED #endif /* } */ #ifdef m_UNKNOWN_GARY_OR_JORDAN_TO_SAY_s_288750 /* { */ dl->d_secperunit = 288750 ; /* 825 * 350 */ ; dl->d_partitions[MINOR_2C_TOTAL].p_size = 288749 ; #define DISPARITY_DEFINED #endif /* } */ #ifdef m_UNKNOWN_JORDAN_TO_SAY_m_831488_p_335789 /* { */ dl->d_secperunit = 831488 ; dl->d_partitions[MINOR_2C_TOTAL].p_size = 335789 ; #define DISPARITY_DEFINED #endif /* } */ #ifdef m_UNKNOWN_GARY_TO_SAY_s_831488 /* { */ dl->d_secpercyl = 350 ; dl->d_secperunit = dl->d_partitions[MINOR_2C_TOTAL].p_size = 831488 ; #define DISPARITY_DEFINED #endif /* } */ #ifdef m_UNKNOWN_GARY_TO_SAY_s_1006016 /* { */ dl->d_secperunit = 1006016 ; #define DISPARITY_DEFINED #endif /* } */ #ifdef m_MICROPOLIS_1684v7_s_663476 /* { */ dl->d_secperunit = 663476 ; /* values from jhs@ after format by adaptec 1542b */ #define DISPARITY_DEFINED #endif /* } */ #ifdef m_SEAGATE_ST4767N_s_1299840 /* { values from jhs@ */ dl->d_secperunit = 1299840 ; /* 665,518,080 bytes */ /* Theoretically 1,421,700 sectors. Seagate products guide says 676M @ 512 bytes/sector. These dl->d_sparespercyl and dl->d_secpercyl are not used below, ( and not used by the kernel, so I've been told, ) so not bothering to set these. */ #define DISPARITY_DEFINED #endif /* } */ #ifdef m_SEAGATE_ST1480N_s_832527 dl->d_secperunit = 832527 ; #define DISPARITY_DEFINED #endif /* } */ #ifdef m_SEAGATE_ST1096N dl->d_secperunit = 180000 ; /* initial guess */ #define DISPARITY_DEFINED /* stuart currently configured by gary as: d_type: 4 ( DTYPE_SCSI is 4 ) d_typename: SCSI d_secsize: 512 d_npartitions: 8 d_nsectors: 70 d_ntracks: 15 d_ncylinders: 1354 d_secpercyl: 1050 d_secperunit: 180000 d_sparespertrack: 1 d_sparespercyl: 15 d_acylinders: 2 d_rpm: 4800 d_interleave: 1 d_trackskew: 12 d_cylskew: 22 d_headswitch: 0 d_trkseek: 2500 d_npartitions: 8 [0=a]: size 60000, offset 2561, Root [1=b]: size 0, offset 0, Alternate Root [2=c]: size 180000, offset 0, Whole Disc [3=d]: size 117439, offset 62561, Usr [4=e]: size 0, offset 0, Usr1 [5=f]: size 1, offset 0, Disc Label [6=g]: size 1280, offset 1, First Kernel [7=h]: size 1280, offset 1281, Second Kernel */ #endif /* } */ #ifndef DISPARITY_DEFINED /* { */ This uncommented text is to enable the compiler to detect that you have specified CAPACITY_DISPARITY, but that no disparity information was found for the appropriate m_Something; #endif /* DISPARITY_DEFINED } */ #endif /* CAPACITY_DISPARITY } */ /* ------------------------------------------------------------------------- */ /* Check if we have a finite size disc to allocate */ if (dl->d_secperunit == 0) { fprintf(stderr, "%s: Fatal Error, program compiled with no disc defined.\n", *ARGV) ; exit(1) ; } /* allocate disk slices */ if (dl->d_partitions[MINOR_2C_TOTAL].p_size == 0) /* if no special fix above, make c partition = media size */ dl->d_partitions[MINOR_2C_TOTAL].p_size = dl->d_secperunit ; remainder = dl->d_partitions[MINOR_2C_TOTAL].p_size ; dl->d_partitions[MINOR_2C_TOTAL].p_offset = 0 ; dl->d_partitions[MINOR_5F_DISKLABEL].p_offset = 0 ; dl->d_partitions[MINOR_5F_DISKLABEL].p_size = sec_alloc( SIZE_DISKLABEL,"Disc Label") ; dl->d_partitions[MINOR_6G_KERNEL1].p_offset = dl->d_partitions[MINOR_5F_DISKLABEL].p_offset + dl->d_partitions[MINOR_5F_DISKLABEL].p_size ; dl->d_partitions[MINOR_6G_KERNEL1].p_size = sec_alloc( SIZE_KERNEL1,"First Kernel") ; dl->d_partitions[MINOR_7H_KERNEL2].p_offset = dl->d_partitions[MINOR_6G_KERNEL1].p_offset + dl->d_partitions[MINOR_6G_KERNEL1].p_size ; dl->d_partitions[MINOR_7H_KERNEL2].p_size = sec_alloc( SIZE_KERNEL2,"Second Kernel") ; dl->d_partitions[MINOR_0A_ROOT1].p_offset = dl->d_partitions[MINOR_7H_KERNEL2].p_offset + dl->d_partitions[MINOR_7H_KERNEL2].p_size ; #ifdef MB140_BACKWARD_COMPATIBLE_HACK /* { */ /* Urgh - This is a weird config. Kernels of 1025 and a root offset at 2*1280 - why ? I suggest whoever has this do this : Invoke rom monitor or dd (on /dev/...c) to move 2nd kernel up a bit, Increase KERNEL_SIZE to 1280, Recompile & create new disklabel PLEASE Mail jhs@ when this ifdef can be deleted. */ dl->d_partitions[MINOR_0A_ROOT1].p_offset = 2*1280 ; #endif /* } */ dl->d_partitions[MINOR_0A_ROOT1].p_size = sec_alloc(ROOT_SIZE, "Root") ; dl->d_partitions[MINOR_1B_ROOT2].p_offset = dl->d_partitions[MINOR_0A_ROOT1].p_offset + dl->d_partitions[MINOR_0A_ROOT1].p_size ; dl->d_partitions[MINOR_1B_ROOT2].p_size = sec_alloc( SIZE_ROOT2,"Alternate Root") ; dl->d_partitions[MINOR_3D_USR].p_offset = dl->d_partitions[MINOR_1B_ROOT2].p_offset + dl->d_partitions[MINOR_1B_ROOT2].p_size ; dl->d_partitions[MINOR_3D_USR].p_size = sec_alloc( USR_SIZE,"Usr") ; /* All/any remaining space gets allocated here */ dl->d_partitions[MINOR_4E_USR1].p_offset = dl->d_partitions[MINOR_3D_USR].p_offset + dl->d_partitions[MINOR_3D_USR].p_size ; dl->d_partitions[MINOR_4E_USR1].p_size = remainder ; /* ------------------------------------------------------------------------- */ #ifdef PARTITION_CHANGES /* { */ /* PARTITION MODIFICATIONS for old configurations, Kept only for compatability. The program has by now automatically calculated the correct value for MINOR_4E_USR1 p_size & p_offset, so the values forced below either waste space or reach beyond the end of physical disk. The reason for these anomalous values is presumably one of: - Bad manual calculation - Segments of disc being reserved for other usage (possibly in Gary's case because one of his SCSI disks has a large physically damaged area). */ #ifdef jordan_288750 /* { */ dl->d_partitions[MINOR_4E_USR1].p_size = 0 ; #define PARTITION_CHANGE_DEFINED #endif /* } */ #ifdef gary_288750 /* { */ dl->d_partitions[MINOR_4E_USR1].p_size = 125000 ; dl->d_partitions[MINOR_4E_USR1].p_offset = 159900 ; #define PARTITION_CHANGE_DEFINED #endif /* } */ #ifdef gary_831488 /* { */ dl->d_partitions[MINOR_4E_USR1].p_size = 349438 ; #define PARTITION_CHANGE_DEFINED #endif /* } */ #ifdef jordan_335789 /* { */ dl->d_partitions[MINOR_4E_USR1].p_size = 0 ; #define PARTITION_CHANGE_DEFINED #endif /* } */ #ifdef gary_1006016 /* { */ dl->d_partitions[MINOR_4E_USR1].p_size = 506176 ; #define PARTITION_CHANGE_DEFINED #endif /* } */ #ifndef PARTITION_CHANGE_DEFINED /* { */ This uncommented text is to enable the compiler to detect that no PARTITION_CHANGES are specified for OWNER ; #endif /* } */ #endif /* } */ /* ------------------------------------------------------------------------- */ /* Cosmetics, so disk label will look exactly the same as a hand made label */ for (count = 0 ; count < EIGHT ; count++ ) if ( dl->d_partitions[count].p_size == 0 ) dl->d_partitions[count].p_offset = 0 ; /* ------------------------------------------------------------------------- */ if ((bytes=write(1, sector, BYTES_PER_SECTOR)) != BYTES_PER_SECTOR) { fprintf(stderr,"%s: Only wrote %d bytes, not %d.\n", *ARGV,bytes,BYTES_PER_SECTOR) ; exit (1) ; } }