xref: /netbsd/sys/arch/mvme68k/mvme68k/disksubr.c (revision 99259f25)
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 *
readdisklabel(dev_t dev,void (* strat)(struct buf *),struct disklabel * lp,struct cpu_disklabel * clp)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
writedisklabel(dev_t dev,void (* strat)(struct buf *),struct disklabel * lp,struct cpu_disklabel * clp)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
bsdtocpulabel(struct disklabel * lp,struct cpu_disklabel * clp)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
cputobsdlabel(struct disklabel * lp,struct cpu_disklabel * clp)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
printlp(struct disklabel * lp,const char * str)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
printclp(struct cpu_disklabel * clp,const char * str)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