Home | History | Annotate | Line # | Download | only in mvme68k
      1 /*	$NetBSD: disksubr.c,v 1.36 2019/04/03 22:10:50 christos Exp $	*/
      2 
      3 /*
      4  * Copyright (c) 1995 Dale Rahn.
      5  * All rights reserved.
      6  *
      7  * Redistribution and use in source and binary forms, with or without
      8  * modification, are permitted provided that the following conditions
      9  * are met:
     10  * 1. Redistributions of source code must retain the above copyright
     11  *    notice, this list of conditions and the following disclaimer.
     12  * 2. Redistributions in binary form must reproduce the above copyright
     13  *    notice, this list of conditions and the following disclaimer in the
     14  *    documentation and/or other materials provided with the distribution.
     15  * 3. The name of the author may not be used to endorse or promote products
     16  *    derived from this software without specific prior written permission.
     17  *
     18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     19  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     20  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     21  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     22  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     23  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     24  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     25  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     26  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     27  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     28  */
     29 
     30 #include <sys/cdefs.h>
     31 __KERNEL_RCSID(0, "$NetBSD: disksubr.c,v 1.36 2019/04/03 22:10:50 christos Exp $");
     32 
     33 #include <sys/param.h>
     34 #include <sys/systm.h>
     35 #include <sys/buf.h>
     36 #include <sys/device.h>
     37 #define FSTYPENAMES
     38 #include <sys/disklabel.h>
     39 #include <sys/disk.h>
     40 
     41 #include <dev/scsipi/scsi_all.h>
     42 #include <dev/scsipi/scsipi_all.h>
     43 #include <dev/scsipi/scsiconf.h>
     44 
     45 #include <machine/autoconf.h>
     46 
     47 #ifdef DEBUG
     48 int disksubr_debug = 0;
     49 #endif
     50 
     51 static void bsdtocpulabel(struct disklabel *lp, struct cpu_disklabel *clp);
     52 static void cputobsdlabel(struct disklabel *lp, struct cpu_disklabel *clp);
     53 
     54 #ifdef DEBUG
     55 static void printlp(struct disklabel *lp, const char *str);
     56 static void printclp(struct cpu_disklabel *clp, const char *str);
     57 #endif
     58 
     59 
     60 /*
     61  * Attempt to read a disk label from a device
     62  * using the indicated strategy routine.
     63  * The label must be partly set up before this:
     64  * secpercyl and anything required in the strategy routine
     65  * (e.g., sector size) must be filled in before calling us.
     66  * Returns null on success and an error string on failure.
     67  */
     68 const char *
     69 readdisklabel(dev_t dev, void (*strat)(struct buf *), struct disklabel *lp,
     70     struct cpu_disklabel *clp)
     71 {
     72 	struct buf *bp;
     73 	const char *msg = NULL;
     74 
     75 	/* obtain buffer to probe drive with */
     76 	bp = geteblk((int)lp->d_secsize);
     77 
     78 	/* request no partition relocation by driver on I/O operations */
     79 	bp->b_dev = dev;
     80 	bp->b_blkno = 0; /* contained in block 0 */
     81 	bp->b_bcount = lp->d_secsize;
     82 	bp->b_flags |= B_READ;
     83 	bp->b_cylinder = 0; /* contained in block 0 */
     84 	(*strat)(bp);
     85 
     86 	if (biowait(bp)) {
     87 		msg = "cpu_disklabel read error\n";
     88 	} else {
     89 		memcpy(clp, bp->b_data, sizeof (struct cpu_disklabel));
     90 	}
     91 
     92 	brelse(bp, 0);
     93 
     94 	if (msg || clp->magic1 != DISKMAGIC || clp->magic2 != DISKMAGIC) {
     95 		return msg;
     96 	}
     97 
     98 	cputobsdlabel(lp, clp);
     99 #ifdef DEBUG
    100 	if(disksubr_debug > 0) {
    101 		printlp(lp, "readdisklabel: bsd label");
    102 		printclp(clp, "readdisklabel: cpu label");
    103 	}
    104 #endif
    105 	return msg;
    106 }
    107 
    108 /*
    109  * Write disk label back to device after modification.
    110  */
    111 int
    112 writedisklabel(dev_t dev, void (*strat)(struct buf *), struct disklabel *lp,
    113     struct cpu_disklabel *clp)
    114 {
    115 	struct buf *bp;
    116 	int error;
    117 
    118 #ifdef DEBUG
    119 	if(disksubr_debug > 0) {
    120 		printlp(lp, "writedisklabel: bsd label");
    121 	}
    122 #endif
    123 
    124 	/*
    125 	 * obtain buffer to read initial cpu_disklabel, for bootloader size :-)
    126 	 */
    127 	bp = geteblk((int)lp->d_secsize);
    128 
    129 	/* request no partition relocation by driver on I/O operations */
    130 	bp->b_dev = dev;
    131 	bp->b_blkno = 0; /* contained in block 0 */
    132 	bp->b_bcount = lp->d_secsize;
    133 	bp->b_flags |= B_READ;
    134 	bp->b_cylinder = 0; /* contained in block 0 */
    135 	(*strat)(bp);
    136 
    137 	if ( (error = biowait(bp)) != 0 ) {
    138 		/* nothing */
    139 	} else {
    140 		memcpy(clp, bp->b_data, sizeof(struct cpu_disklabel));
    141 	}
    142 
    143 	brelse(bp, 0);
    144 
    145 	if (error) {
    146 		return error;
    147 	}
    148 
    149 	bsdtocpulabel(lp, clp);
    150 
    151 #ifdef DEBUG
    152 	if (disksubr_debug > 0) {
    153 		printclp(clp, "writedisklabel: cpu label");
    154 	}
    155 #endif
    156 
    157 	if (lp->d_magic == DISKMAGIC && lp->d_magic2 == DISKMAGIC &&
    158 	    dkcksum(lp) == 0) {
    159 		/* obtain buffer to scrozz drive with */
    160 		bp = geteblk((int)lp->d_secsize);
    161 
    162 		memcpy(bp->b_data, clp, sizeof(struct cpu_disklabel));
    163 
    164 		/*
    165 		 * request no partition relocation by driver on I/O operations
    166 		 */
    167 		bp->b_dev = dev;
    168 		bp->b_blkno = 0; /* contained in block 0 */
    169 		bp->b_bcount = lp->d_secsize;
    170 		bp->b_flags |= B_WRITE;
    171 		bp->b_cylinder = 0; /* contained in block 0 */
    172 		(*strat)(bp);
    173 
    174 		error = biowait(bp);
    175 
    176 		brelse(bp, 0);
    177 	}
    178 	return error;
    179 }
    180 
    181 static void
    182 bsdtocpulabel(struct disklabel *lp, struct cpu_disklabel *clp)
    183 {
    184 	int i;
    185 
    186 	clp->magic1 = lp->d_magic;
    187 	clp->type = lp->d_type;
    188 	clp->subtype = lp->d_subtype;
    189 	strncpy(clp->vid_vd, lp->d_typename, 16);
    190 	strncpy(clp->packname, lp->d_packname, 16);
    191 	clp->cfg_psm = lp->d_secsize;
    192 	clp->cfg_spt = lp->d_nsectors;
    193 	clp->cfg_trk = lp->d_ncylinders;	/* trk is really num of cyl! */
    194 	clp->cfg_hds = lp->d_ntracks;
    195 
    196 	clp->secpercyl = lp->d_secpercyl;
    197 	clp->secperunit = lp->d_secperunit;
    198 	clp->sparespertrack = lp->d_sparespertrack;
    199 	clp->sparespercyl = lp->d_sparespercyl;
    200 	clp->acylinders = lp->d_acylinders;
    201 	clp->rpm = lp->d_rpm;
    202 
    203 	clp->cfg_ilv = lp->d_interleave;
    204 	clp->cfg_sof = lp->d_trackskew;
    205 	clp->cylskew = lp->d_cylskew;
    206 	clp->headswitch = lp->d_headswitch;
    207 
    208 	/* this silly table is for winchester drives */
    209 	if (lp->d_trkseek < 6) {
    210 		clp->cfg_ssr = 0;
    211 	} else if (lp->d_trkseek < 10) {
    212 		clp->cfg_ssr = 1;
    213 	} else if (lp->d_trkseek < 15) {
    214 		clp->cfg_ssr = 2;
    215 	} else if (lp->d_trkseek < 20) {
    216 		clp->cfg_ssr = 3;
    217 	} else {
    218 		clp->cfg_ssr = 4;
    219 	}
    220 
    221 	clp->flags = lp->d_flags;
    222 	for (i = 0; i < NDDATA; i++)
    223 		clp->drivedata[i] = lp->d_drivedata[i];
    224 	for (i = 0; i < NSPARE; i++)
    225 		clp->spare[i] = lp->d_spare[i];
    226 
    227 	clp->magic2 = lp->d_magic2;
    228 	clp->checksum = lp->d_checksum;
    229 	clp->partitions = lp->d_npartitions;
    230 	clp->bbsize = lp->d_bbsize;
    231 	clp->sbsize = lp->d_sbsize;
    232 	clp->checksum = lp->d_checksum;
    233 	/* note: assume at least 4 partitions */
    234 	memcpy(clp->vid_4, &lp->d_partitions[0], sizeof(struct partition) * 4);
    235 	memset(clp->cfg_4, 0, sizeof(struct partition) * 12);
    236 	memcpy(clp->cfg_4, &lp->d_partitions[4], sizeof(struct partition)
    237 	    * ((MAXPARTITIONS < 16) ? (MAXPARTITIONS - 4) : 12));
    238 
    239 	/*
    240 	 * here are the parts of the cpu_disklabel the kernel must init.
    241 	 * see disklabel.h for more details
    242 	 * [note: this used to be handled by 'wrtvid']
    243 	 */
    244 	memcpy(clp->vid_id, VID_ID, sizeof(clp->vid_id));
    245 	clp->vid_oss = VID_OSS;
    246 	clp->vid_osl = VID_OSL;
    247 	clp->vid_osa_u = VID_OSAU;
    248 	clp->vid_osa_l = VID_OSAL;
    249 	clp->vid_cas = VID_CAS;
    250 	clp->vid_cal = VID_CAL;
    251 	memcpy(clp->vid_mot, VID_MOT, sizeof(clp->vid_mot));
    252 	clp->cfg_rec = CFG_REC;
    253 	clp->cfg_psm = CFG_PSM;
    254 }
    255 
    256 static void
    257 cputobsdlabel(struct disklabel *lp, struct cpu_disklabel *clp)
    258 {
    259 	int i;
    260 
    261 	lp->d_magic = clp->magic1;
    262 	lp->d_type = clp->type;
    263 	lp->d_subtype = clp->subtype;
    264 	strncpy(lp->d_typename, clp->vid_vd, 16);
    265 	strncpy(lp->d_packname, clp->packname, 16);
    266 	lp->d_secsize = clp->cfg_psm;
    267 	lp->d_nsectors = clp->cfg_spt;
    268 	lp->d_ncylinders = clp->cfg_trk; /* trk is really num of cyl! */
    269 	lp->d_ntracks = clp->cfg_hds;
    270 
    271 	lp->d_secpercyl = clp->secpercyl;
    272 	lp->d_secperunit = clp->secperunit;
    273 	lp->d_secpercyl = clp->secpercyl;
    274 	lp->d_secperunit = clp->secperunit;
    275 	lp->d_sparespertrack = clp->sparespertrack;
    276 	lp->d_sparespercyl = clp->sparespercyl;
    277 	lp->d_acylinders = clp->acylinders;
    278 	lp->d_rpm = clp->rpm;
    279 	lp->d_interleave = clp->cfg_ilv;
    280 	lp->d_trackskew = clp->cfg_sof;
    281 	lp->d_cylskew = clp->cylskew;
    282 	lp->d_headswitch = clp->headswitch;
    283 
    284 	/* this silly table is for winchester drives */
    285 	switch (clp->cfg_ssr) {
    286 	case 0:
    287 		lp->d_trkseek = 0;
    288 		break;
    289 	case 1:
    290 		lp->d_trkseek = 6;
    291 		break;
    292 	case 2:
    293 		lp->d_trkseek = 10;
    294 		break;
    295 	case 3:
    296 		lp->d_trkseek = 15;
    297 		break;
    298 	case 4:
    299 		lp->d_trkseek = 20;
    300 		break;
    301 	default:
    302 		lp->d_trkseek = 0;
    303 	}
    304 	lp->d_flags = clp->flags;
    305 	for (i = 0; i < NDDATA; i++)
    306 		lp->d_drivedata[i] = clp->drivedata[i];
    307 	for (i = 0; i < NSPARE; i++)
    308 		lp->d_spare[i] = clp->spare[i];
    309 
    310 	lp->d_magic2 = clp->magic2;
    311 	lp->d_checksum = clp->checksum;
    312 	lp->d_npartitions = clp->partitions;
    313 	lp->d_bbsize = clp->bbsize;
    314 	lp->d_sbsize = clp->sbsize;
    315 	/* note: assume at least 4 partitions */
    316 	memcpy(&lp->d_partitions[0], clp->vid_4, sizeof(struct partition) * 4);
    317 	memcpy(&lp->d_partitions[4], clp->cfg_4, sizeof(struct partition)
    318 	    * ((MAXPARTITIONS < 16) ? (MAXPARTITIONS - 4) : 12));
    319 	lp->d_checksum = 0;
    320 	lp->d_checksum = dkcksum(lp);
    321 #if DEBUG
    322 	if (disksubr_debug > 0) {
    323 		printlp(lp, "translated label read from disk\n");
    324 	}
    325 #endif
    326 }
    327 
    328 #ifdef DEBUG
    329 static void
    330 printlp(struct disklabel *lp, const char *str)
    331 {
    332 	int i;
    333 
    334 	printf("%s\n", str);
    335 	printf("magic1 %x\n", lp->d_magic);
    336 	printf("magic2 %x\n", lp->d_magic2);
    337 	printf("typename %s\n", lp->d_typename);
    338 	printf("secsize %x nsect %x ntrack %x ncylinders %x\n",
    339 	    lp->d_secsize, lp->d_nsectors, lp->d_ntracks, lp->d_ncylinders);
    340 	printf("Num partitions %x\n", lp->d_npartitions);
    341 	for (i = 0; i < lp->d_npartitions; i++) {
    342 		struct partition *part = &lp->d_partitions[i];
    343 		const char *fstyp = fstypenames[part->p_fstype];
    344 
    345 		printf("%c: size %10x offset %10x type %7s frag %5x cpg %3x\n",
    346 		    'a' + i, part->p_size, part->p_offset, fstyp,
    347 		    part->p_frag, part->p_cpg);
    348 	}
    349 }
    350 
    351 static void
    352 printclp(struct cpu_disklabel *clp, const char *str)
    353 {
    354 	int maxp, i;
    355 
    356 	printf("%s\n", str);
    357 	printf("magic1 %lx\n", clp->magic1);
    358 	printf("magic2 %lx\n", clp->magic2);
    359 	printf("typename %s\n", clp->vid_vd);
    360 	printf("secsize %x nsect %x ntrack %x ncylinders %x\n",
    361 	    clp->cfg_psm, clp->cfg_spt, clp->cfg_hds, clp->cfg_trk);
    362 	printf("Num partitions %x\n", clp->partitions);
    363 	maxp = clp->partitions < 16 ? clp->partitions : 16;
    364 	for (i = 0; i < maxp; i++) {
    365 		struct partition *part;
    366 		const char *fstyp;
    367 
    368 		if (i < 4) {
    369 			part = (void *)&clp->vid_4[0];
    370 			part = &part[i];
    371 		} else {
    372 			part = (void *)&clp->cfg_4[0];
    373 			part = &part[i-4];
    374 		}
    375 
    376 		fstyp = fstypenames[part->p_fstype];
    377 
    378 		printf("%c: size %10x offset %10x type %7s frag %5x cpg %3x\n",
    379 		    'a' + i, part->p_size, part->p_offset, fstyp,
    380 		    part->p_frag, part->p_cpg);
    381 	}
    382 }
    383 #endif
    384