1 #ifndef lint
2 static char sccsid[] = "@(#)disklabel.c	1.3 (Berkeley/CCI) 06/24/90";
3 #endif
4 
5 #include	"vdfmt.h"
6 #include	"cmd.h"
7 
8 int	lab_help();
9 
10 /*
11 **
12 */
13 
14 get_drive_type(ctlr, drive, op_mask)
15 int	ctlr, drive, op_mask;
16 {
17 	int	tokens[20];
18 	char	line[132];
19 	int	savedevflags = 0;
20 	register struct disklabel *lp;
21 	struct disklabel *plp, *getdiskbyname(), *promptfordisk(), *findproto();
22 
23 	lp = lab;
24 	if (lp->d_typename[0] == 0) {
25 		print("Read label from drive %d, controller %d? ", drive, ctlr);
26 		get_string_cmd(line, lab_help);
27 		if (kill_processes == true)
28 			return;
29 		if (line[0] == 'y' || line[0] == 'Y') {
30 			lp->d_secsize = 512;
31 			lp->d_nsectors = 66;
32 			lp->d_ntracks = 23;
33 			lp->d_ncylinders = 850;
34 			lp->d_secpercyl = 66*23;
35 			if (D_INFO->alive != u_true)
36 				spin_up_drive();
37 			savedevflags = lab->d_devflags;
38 			if (readlabel()) {
39 				lp->d_devflags = savedevflags;
40 				lp->d_pat = 0;	/* this can't be what we want */
41 				goto check;
42 			}
43 			lab->d_devflags = savedevflags;
44 			lp->d_typename[0] = 0;
45 		}
46 	}
47 	for (;;) {
48 		print("Drive type for controller %d, drive %d? ", ctlr, drive);
49 		if (lp->d_typename[0] != 0)
50 			printf("(%s) ", lp->d_typename);
51 		get_string_cmd(line, lab_help);
52 		if (kill_processes == true)
53 			return;
54 		if (lp->d_typename[0] != 0 &&
55 		    (line[0] == 0 || strcmp(lp->d_typename, line) == 0))
56 			break;
57 		if (lp = findproto(line))
58 			break;;
59 		if (lp = getdiskbyname(line))
60 			break;
61 		if (lp = promptfordisk(line))
62 			break;
63 		if (kill_processes == true)
64 			return;
65 		lp = lab;
66 	}
67 check:
68 	plp = findproto(lp->d_typename);
69 	while (lp->d_traksize == 0) {
70 		print("number of bytes per track");
71 		if (plp && plp->d_traksize)
72 			printf(" (%d)", plp->d_traksize);
73 		printf(": ");
74 		get_string_cmd(line, lab_help);
75 		if (kill_processes == true)
76 			return;
77 		if (line[0] == 0) {
78 			if (plp->d_traksize == 0)
79 				print("no default value\n");
80 			lp->d_traksize = plp->d_traksize;
81 		} else
82 			lp->d_traksize = atol(line);
83 	}
84 	print("Drive geometry for controller %d, drive %d (%s):\n",
85 	    ctlr, drive, lp->d_typename);
86 	print("  sector size %d; %d sectors, %d tracks, %d cylinders\n",
87 	    lp->d_secsize, lp->d_nsectors, lp->d_ntracks, lp->d_ncylinders);
88 	if (lp->d_pat == 0 && op_mask & (FORMAT_OP | VERIFY_OP)) {
89 		extern struct flawpat defpats, cdcpats;
90 
91 		print("media patterns for verify (default or cdc): ");
92 		get_string_cmd(line, lab_help);
93 		if (kill_processes == true)
94 			return;
95 		if (strcmp(line, "cdc") == 0)
96 			lp->d_pat = (long) &cdcpats;
97 		else
98 			lp->d_pat = (long) &defpats;
99 	}
100 	if (lab->d_cylskew == -1)
101 		lab->d_cylskew = 0;
102 	if (lab->d_trackskew == -1)
103 		lab->d_trackskew = 0;
104 	if (lab->d_sparespertrack == -1)
105 		lab->d_sparespertrack = 0;
106 	if (lp != lab) {
107 		*lab = *lp;
108 		if (savedevflags)
109 			lab->d_devflags = savedevflags;
110 	}
111 	configure_drive(1);		/* set new parameters */
112 }
113 
114 struct disklabel *
115 findproto(name)
116 	char *name;
117 {
118 	int count;
119 
120 	if (C_INFO->type == VDTYPE_VDDC)
121 		count = smddrives;
122 	else
123 		count = 0;
124 	for (; count < ndrives; count++)
125 		if (strcmp(vdproto[count].d_typename, name) == 0)
126 			return (&vdproto[count]);
127 	return ((struct disklabel *) 0);
128 }
129 
130 struct disklabel disk;
131 
132 struct	field {
133 	char	*f_name;
134 	char	*f_defaults;
135 	u_long	*f_location;
136 } fields[] = {
137 	{ "sector size",		"512",	&disk.d_secsize },
138 	{ "#sectors/track",		0,	&disk.d_nsectors },
139 	{ "#tracks/cylinder",		0,	&disk.d_ntracks },
140 	{ "#cylinders",			0,	&disk.d_ncylinders },
141 	{ "#bytes/track",		0,	&disk.d_traksize },
142 	{ 0, 0, 0 },
143 };
144 
145 struct disklabel *
146 promptfordisk(name)
147 	char *name;
148 {
149 	register struct disklabel *dp = &disk;
150 	register struct field *fp;
151 	register i;
152 	char buf[132], *cp;
153 
154 	print("%s: unknown drive type\n", name);
155 	if (get_yes_no("Enter drive parameters") == false)
156 		return ((struct disklabel *)0);
157 
158 	strncpy(dp->d_typename, name, sizeof(dp->d_typename));
159 	dp->d_type = DTYPE_SMD;
160 	dp->d_flags = 0;
161 
162 	print("(type <cr> to get default value, if only one)\n");
163 	for (fp = fields; fp->f_name != NULL; fp++) {
164 again:
165 		print("%s ", fp->f_name);
166 		if (fp->f_defaults != NULL)
167 			printf("(%s)", fp->f_defaults);
168 		printf("? ");
169 		get_string_cmd(buf, lab_help);
170 		if (kill_processes == true)
171 			return ((struct disklabel *)0);
172 		cp = buf;
173 		if (*cp == '\0') {
174 			if (fp->f_defaults == NULL) {
175 				print("no default value\n");
176 				goto again;
177 			}
178 			cp = fp->f_defaults;
179 		}
180 		*fp->f_location = atol(cp);
181 		if (*fp->f_location == 0) {
182 			print("%s: bad value\n", cp);
183 			goto again;
184 		}
185 	}
186 	print("sectors/cylinder (%d)? ", dp->d_nsectors * dp->d_ntracks);
187 	get_string_cmd(buf, lab_help);
188 	if (kill_processes == true)
189 		return ((struct disklabel *)0);
190 	if (buf[0] == 0)
191 		dp->d_secpercyl = dp->d_nsectors * dp->d_ntracks;
192 	else
193 		dp->d_secpercyl = atol(buf);
194 	return (dp);
195 }
196 
197 lab_help()
198 {
199 	indent();
200 	print("Entering drive type and parameters:\n");
201 	indent();
202 	print("Answer each question with a number or name, as appropriate.\n");
203 	print("Questions with defaults show them in (parentheses);\n");
204 	print("press return to accept the default.\n\n");
205 	exdent(1);
206 	print("Other commands available:\n");
207 	indent();
208 	print("QUIT     - abort current operation\n");
209 	exdent(2);
210 }
211 
212 static char labelsector[VD_MAXSECSIZE];
213 
214 /*
215  * Fetch disklabel for disk.
216  */
217 readlabel()
218 {
219 	register struct disklabel *lp;
220 
221 	bzero(labelsector, sizeof(labelsector));
222 	if (vread(LABELSECTOR, labelsector, 1) < 1)
223 		return (0);
224 	for (lp = (struct disklabel *)labelsector;
225 	    lp <= (struct disklabel *)(labelsector+VD_MAXSECSIZE - sizeof(*lp));
226 	    lp = (struct disklabel *)((char *)lp + 16))
227 		if (lp->d_magic == DISKMAGIC &&
228 		    lp->d_magic2 == DISKMAGIC)
229 			break;
230 	if (lp > (struct disklabel *)(labelsector+VD_MAXSECSIZE-sizeof(*lp)) ||
231 	    lp->d_magic != DISKMAGIC || lp->d_magic2 != DISKMAGIC ||
232 	    dkcksum(lp) != 0) {
233 		print("Disk is unlabeled.\n");
234 		return (0);
235 	}
236 	*lab = *lp;
237 	return (1);
238 }
239 
240 writelabel()
241 {
242 	register struct disklabel *lp;
243 
244 	bzero(labelsector, sizeof(labelsector));
245 	lp = (struct disklabel *)(labelsector + LABELOFFSET);
246 	*lp = *lab;
247 	lp->d_magic = DISKMAGIC;
248 	lp->d_magic2 = DISKMAGIC;
249 	lp->d_checksum = 0;
250 	lp->d_checksum = dkcksum(lp);
251 	if (vwrite(LABELSECTOR, labelsector, 1) != 1)
252 		printf("error writing disk label\n");
253 }
254