1/* Copyright 1999 Apple Computer, Inc. 2 * 3 * Generate a bsd disk label routine. 4 * Input: open file descriptor to the device node, and 5 * pointer to a disk label structure to fill in 6 * Return: errno status 7 * 8 * HISTORY 9 * 10 * 24 Feb 1999 D. Markarian at Apple 11 * Created. 12 */ 13 14#include <string.h> /* memset */ 15#include <sys/types.h> /* sys/disklabel.h */ 16#include <sys/param.h> /* NBPG */ 17 18#include <sys/disk.h> /* DKIOCGETBLOCKSIZE ioctl */ 19 20#include <sys/disklabel.h> /* struct disklabel */ 21 22u_short dkcksum __P((register struct disklabel *lp)); 23int dkdisklabelregenerate __P((int fd, struct disklabel * lp, int newblksize)); 24 25/* 26 * The following two constants set the default block and fragment sizes. 27 * Both constants must be a power of 2 and meet the following constraints: 28 * MINBSIZE <= GENBLKSIZE <= MAXBSIZE 29 * sectorsize <= GENFRAGSIZE <= GENBLKSIZE 30 * GENBLKSIZE / GENFRAGSIZE <= 8 31 */ 32#define GENFRAGSIZE 1024 33#define GENBLKSIZE NBPG /* 4096 */ 34 35/* 36 * Cylinder groups may have up to many cylinders. The actual 37 * number used depends upon how much information can be stored 38 * on a single cylinder. The default is to use 16 cylinders 39 * per group. 40 */ 41#define GENCPG 16 42 43/* 44 * Interleave is physical sector interleave, set up by the 45 * formatter or controller when formatting. When interleaving is 46 * in use, logically adjacent sectors are not physically 47 * contiguous, but instead are separated by some number of 48 * sectors. It is specified as the ratio of physical sectors 49 * traversed per logical sector. Thus an interleave of 1:1 50 * implies contiguous layout, while 2:1 implies that logical 51 * sector 0 is separated by one sector from logical sector 1. 52 */ 53#define GENINTERLEAVE 1 54 55/* 56 * Rotational speed; # of data sectors per track. 57 */ 58#define GENRPM 3600 59#define GENNSECTORS 32 60 61int dkdisklabel(int fd, struct disklabel * lp) 62{ 63 return dkdisklabelregenerate(fd, lp, 0); 64} 65 66int dkdisklabelregenerate(int fd, struct disklabel * lp, int newblksize) 67{ 68 /* 69 * Generate a bsd-style disk label for the specified device node. 70 */ 71 72 int blksize; 73 int error; 74 int index; 75 int64_t numblks; 76 77 /* obtain the size of the media (in blocks) */ 78 if ( (error = ioctl(fd, DKIOCGETBLOCKCOUNT, &numblks)) < 0 ) 79 return(error); 80 81 /* obtain the block size of the media */ 82 if ( (error = ioctl(fd, DKIOCGETBLOCKSIZE, &blksize)) < 0 ) 83 return(error); 84 85 /* adjust the size of the media with newblksize should it be specified */ 86 if (newblksize) 87 { 88 numblks = ((numblks * blksize) / newblksize); 89 blksize = newblksize; 90 } 91 92 /* 93 * clear the disk label structure and then fill in the appropriate fields; 94 * we comment out lines that are initializations to zero with //, since it 95 * is redundant work 96 */ 97 memset(lp, 0, sizeof(struct disklabel)); 98 99 lp->d_magic = DISKMAGIC; /* the magic number */ 100// lp->d_type = 0; /* drive type */ 101// lp->d_subtype = 0; /* controller/d_type specific */ 102// lp->d_typename[0] = 0; /* type name, e.g. "eagle" */ 103 /* 104 * d_packname contains the pack identifier and is returned when 105 * the disklabel is read off the disk or in-core copy. 106 * d_boot0 and d_boot1 are the (optional) names of the 107 * primary (block 0) and secondary (block 1-15) bootstraps 108 * as found in /usr/mdec. These are returned when using 109 * getdiskbyname(3) to retrieve the values from /etc/disktab. 110 */ 111// lp->d_packname[0] = 0; /* pack identifier */ 112 113 /* disk geometry: */ 114 lp->d_secsize = blksize; /* # of bytes per sector */ 115 lp->d_nsectors = GENNSECTORS; /* # of data sectors per track */ 116 /* # of tracks per cylinder */ 117 if (numblks < 8*32*1024) /* <=528.4 MB */ 118 lp->d_ntracks = 16; 119 else if (numblks < 16*32*1024) /* <=1.057 GB */ 120 lp->d_ntracks = 32; 121 else if (numblks < 32*32*1024) /* <=2.114 GB */ 122 lp->d_ntracks = 54; 123 else if (numblks < 64*32*1024) /* <=4.228 GB */ 124 lp->d_ntracks = 128; 125 else /* > 4.228 GB */ 126 lp->d_ntracks = 255; 127 /* # of data cylinders per unit */ 128 lp->d_ncylinders = numblks / lp->d_ntracks / lp->d_nsectors; 129 /* # of data sectors per cylinder */ 130 lp->d_secpercyl = lp->d_nsectors * lp->d_ntracks; 131 lp->d_secperunit = numblks; /* # of data sectors per unit */ 132 /* 133 * Spares (bad sector replacements) below are not counted in 134 * d_nsectors or d_secpercyl. Spare sectors are assumed to 135 * be physical sectors which occupy space at the end of each 136 * track and/or cylinder. 137 */ 138// lp->d_sparespertrack = 0; /* # of spare sectors per track */ 139// lp->d_sparespercyl = 0; /* # of data sectors per unit */ 140 /* 141 * Alternate cylinders include maintenance, replacement, configuration 142 * description areas, etc. 143 */ 144// lp->d_acylinders = 0; /* # of alt. cylinders per unit */ 145 146 /* hardware characteristics: */ 147 /* 148 * d_interleave, d_trackskew and d_cylskew describe perturbations 149 * in the media format used to compensate for a slow controller. 150 * Interleave is physical sector interleave, set up by the 151 * formatter or controller when formatting. When interleaving is 152 * in use, logically adjacent sectors are not physically 153 * contiguous, but instead are separated by some number of 154 * sectors. It is specified as the ratio of physical sectors 155 * traversed per logical sector. Thus an interleave of 1:1 156 * implies contiguous layout, while 2:1 implies that logical 157 * sector 0 is separated by one sector from logical sector 1. 158 * d_trackskew is the offset of sector 0 on track N relative to 159 * sector 0 on track N-1 on the same cylinder. Finally, d_cylskew 160 * is the offset of sector 0 on cylinder N relative to sector 0 161 * on cylinder N-1. 162 */ 163 lp->d_rpm = GENRPM; /* rotational speed */ 164 lp->d_interleave = GENINTERLEAVE; /* hardware sector interleave */ 165// lp->d_trackskew = 0; /* sector 0 skew, per track */ 166// lp->d_cylskew = 0; /* sector 0 skew, per cylinder */ 167// lp->d_headswitch = 0; /* head switch time, usec */ 168// lp->d_trkseek = 0; /* track-to-track seek, usec */ 169// lp->d_flags = 0; /* generic flags */ 170// lp->d_drivedata[0-4] = 0; /* drive-type specific information */ 171// lp->d_spare[0-4] = 0; /* reserved for future use */ 172 lp->d_magic2 = DISKMAGIC; /* the magic number (again) */ 173// lp->d_checksum = 0; /* xor of data incl. partitions */ 174 175 /* filesystem and partition information: */ 176 lp->d_npartitions = MAXPARTITIONS; /* number of partitions */ 177 178 for (index = 0; index < MAXPARTITIONS; index++) 179 { 180 struct partition * pp = &(lp->d_partitions[index]); 181 pp->p_size = numblks; /* number of sectors */ 182// pp->p_offset = 0; /* starting sector */ 183 pp->p_fsize = MAX(GENFRAGSIZE, blksize); /* fs fragment size */ 184 pp->p_fstype = FS_BSDFFS; /* fs type */ 185 pp->p_frag = MIN(8, GENBLKSIZE / pp->p_fsize);/* fs fragments/block */ 186 pp->p_cpg = GENCPG; /* fs cylinders/group */ 187 } 188 189 /* compute a checksum on the resulting structure */ 190 lp->d_checksum = dkcksum(lp); 191 192 return 0; /* success */ 193} 194