1
2
3
4
5
6
7
8
9
10
11
12
13
14
15#if ENABLE_FEATURE_SUN_LABEL
16
17#define SUNOS_SWAP 3
18#define SUN_WHOLE_DISK 5
19
20#define SUN_LABEL_MAGIC 0xDABE
21#define SUN_LABEL_MAGIC_SWAPPED 0xBEDA
22#define SUN_SSWAP16(x) (sun_other_endian ? fdisk_swap16(x) : (uint16_t)(x))
23#define SUN_SSWAP32(x) (sun_other_endian ? fdisk_swap32(x) : (uint32_t)(x))
24
25
26#define FLOPPY_MAJOR 2
27
28#define SCSI_IOCTL_GET_IDLUN 0x5382
29
30static int sun_other_endian;
31static int scsi_disk;
32static int floppy;
33
34#ifndef IDE0_MAJOR
35#define IDE0_MAJOR 3
36#endif
37#ifndef IDE1_MAJOR
38#define IDE1_MAJOR 22
39#endif
40
41static void
42guess_device_type(void)
43{
44 struct stat bootstat;
45
46 if (fstat(dev_fd, &bootstat) < 0) {
47 scsi_disk = 0;
48 floppy = 0;
49 } else if (S_ISBLK(bootstat.st_mode)
50 && (major(bootstat.st_rdev) == IDE0_MAJOR ||
51 major(bootstat.st_rdev) == IDE1_MAJOR)) {
52 scsi_disk = 0;
53 floppy = 0;
54 } else if (S_ISBLK(bootstat.st_mode)
55 && major(bootstat.st_rdev) == FLOPPY_MAJOR) {
56 scsi_disk = 0;
57 floppy = 1;
58 } else {
59 scsi_disk = 1;
60 floppy = 0;
61 }
62}
63
64static const char *const sun_sys_types[] = {
65 "\x00" "Empty" ,
66 "\x01" "Boot" ,
67 "\x02" "SunOS root" ,
68 "\x03" "SunOS swap" ,
69 "\x04" "SunOS usr" ,
70 "\x05" "Whole disk" ,
71 "\x06" "SunOS stand" ,
72 "\x07" "SunOS var" ,
73 "\x08" "SunOS home" ,
74 "\x82" "Linux swap" ,
75 "\x83" "Linux native",
76 "\x8e" "Linux LVM" ,
77
78 "\xfd" "Linux raid autodetect",
79 NULL
80};
81
82
83static void
84set_sun_partition(int i, uint start, uint stop, int sysid)
85{
86 sunlabel->infos[i].id = sysid;
87 sunlabel->partitions[i].start_cylinder =
88 SUN_SSWAP32(start / (g_heads * g_sectors));
89 sunlabel->partitions[i].num_sectors =
90 SUN_SSWAP32(stop - start);
91 set_changed(i);
92}
93
94static int
95check_sun_label(void)
96{
97 unsigned short *ush;
98 int csum;
99
100 if (sunlabel->magic != SUN_LABEL_MAGIC
101 && sunlabel->magic != SUN_LABEL_MAGIC_SWAPPED) {
102 current_label_type = LABEL_DOS;
103 sun_other_endian = 0;
104 return 0;
105 }
106 sun_other_endian = (sunlabel->magic == SUN_LABEL_MAGIC_SWAPPED);
107 ush = ((unsigned short *) (sunlabel + 1)) - 1;
108 for (csum = 0; ush >= (unsigned short *)sunlabel;) csum ^= *ush--;
109 if (csum) {
110 printf("Detected sun disklabel with wrong checksum.\n"
111"Probably you'll have to set all the values,\n"
112"e.g. heads, sectors, cylinders and partitions\n"
113"or force a fresh label (s command in main menu)\n");
114 } else {
115 g_heads = SUN_SSWAP16(sunlabel->ntrks);
116 g_cylinders = SUN_SSWAP16(sunlabel->ncyl);
117 g_sectors = SUN_SSWAP16(sunlabel->nsect);
118 }
119 update_units();
120 current_label_type = LABEL_SUN;
121 g_partitions = 8;
122 return 1;
123}
124
125static const struct sun_predefined_drives {
126 const char *vendor;
127 const char *model;
128 unsigned short sparecyl;
129 unsigned short ncyl;
130 unsigned short nacyl;
131 unsigned short pcylcount;
132 unsigned short ntrks;
133 unsigned short nsect;
134 unsigned short rspeed;
135} sun_drives[] = {
136 { "Quantum","ProDrive 80S",1,832,2,834,6,34,3662},
137 { "Quantum","ProDrive 105S",1,974,2,1019,6,35,3662},
138 { "CDC","Wren IV 94171-344",3,1545,2,1549,9,46,3600},
139 { "IBM","DPES-31080",0,4901,2,4903,4,108,5400},
140 { "IBM","DORS-32160",0,1015,2,1017,67,62,5400},
141 { "IBM","DNES-318350",0,11199,2,11474,10,320,7200},
142 { "SEAGATE","ST34371",0,3880,2,3882,16,135,7228},
143 { "","SUN0104",1,974,2,1019,6,35,3662},
144 { "","SUN0207",4,1254,2,1272,9,36,3600},
145 { "","SUN0327",3,1545,2,1549,9,46,3600},
146 { "","SUN0340",0,1538,2,1544,6,72,4200},
147 { "","SUN0424",2,1151,2,2500,9,80,4400},
148 { "","SUN0535",0,1866,2,2500,7,80,5400},
149 { "","SUN0669",5,1614,2,1632,15,54,3600},
150 { "","SUN1.0G",5,1703,2,1931,15,80,3597},
151 { "","SUN1.05",0,2036,2,2038,14,72,5400},
152 { "","SUN1.3G",6,1965,2,3500,17,80,5400},
153 { "","SUN2.1G",0,2733,2,3500,19,80,5400},
154 { "IOMEGA","Jaz",0,1019,2,1021,64,32,5394},
155};
156
157static const struct sun_predefined_drives *
158sun_autoconfigure_scsi(void)
159{
160 const struct sun_predefined_drives *p = NULL;
161
162#ifdef SCSI_IOCTL_GET_IDLUN
163 unsigned int id[2];
164 char buffer[2048];
165 char buffer2[2048];
166 FILE *pfd;
167 char *vendor;
168 char *model;
169 char *q;
170 int i;
171
172 if (ioctl(dev_fd, SCSI_IOCTL_GET_IDLUN, &id))
173 return NULL;
174
175 sprintf(buffer,
176 "Host: scsi%d Channel: %02d Id: %02d Lun: %02d\n",
177
178
179
180 0,
181 (id[0]>>16) & 0xff,
182 id[0] & 0xff,
183 (id[0]>>8) & 0xff
184 );
185 pfd = fopen_for_read("/proc/scsi/scsi");
186 if (!pfd) {
187 return NULL;
188 }
189 while (fgets(buffer2, 2048, pfd)) {
190 if (strcmp(buffer, buffer2))
191 continue;
192 if (!fgets(buffer2, 2048, pfd))
193 break;
194 q = strstr(buffer2, "Vendor: ");
195 if (!q)
196 break;
197 q += 8;
198 vendor = q;
199 q = strstr(q, " ");
200 *q++ = '\0';
201 q = strstr(q, "Model: ");
202 if (!q)
203 break;
204 *q = '\0';
205 q += 7;
206 model = q;
207 q = strstr(q, " Rev: ");
208 if (!q)
209 break;
210 *q = '\0';
211 for (i = 0; i < ARRAY_SIZE(sun_drives); i++) {
212 if (*sun_drives[i].vendor && strcasecmp(sun_drives[i].vendor, vendor))
213 continue;
214 if (!strstr(model, sun_drives[i].model))
215 continue;
216 printf("Autoconfigure found a %s%s%s\n",
217 sun_drives[i].vendor,
218 (*sun_drives[i].vendor) ? " " : "",
219 sun_drives[i].model);
220 p = sun_drives + i;
221 break;
222 }
223 break;
224 }
225 fclose(pfd);
226#endif
227 return p;
228}
229
230static void
231create_sunlabel(void)
232{
233 struct hd_geometry geometry;
234 unsigned ndiv;
235 unsigned char c;
236 const struct sun_predefined_drives *p = NULL;
237
238 printf(msg_building_new_label, "sun disklabel");
239
240 sun_other_endian = BB_LITTLE_ENDIAN;
241 memset(MBRbuffer, 0, sizeof(MBRbuffer));
242 sunlabel->magic = SUN_SSWAP16(SUN_LABEL_MAGIC);
243 if (!floppy) {
244 unsigned i;
245 puts("Drive type\n"
246 " ? auto configure\n"
247 " 0 custom (with hardware detected defaults)");
248 for (i = 0; i < ARRAY_SIZE(sun_drives); i++) {
249 printf(" %c %s%s%s\n",
250 i + 'a', sun_drives[i].vendor,
251 (*sun_drives[i].vendor) ? " " : "",
252 sun_drives[i].model);
253 }
254 while (1) {
255 c = read_nonempty("Select type (? for auto, 0 for custom): ");
256 if (c == '0') {
257 break;
258 }
259 if (c >= 'a' && c < 'a' + ARRAY_SIZE(sun_drives)) {
260 p = sun_drives + c - 'a';
261 break;
262 }
263 if (c >= 'A' && c < 'A' + ARRAY_SIZE(sun_drives)) {
264 p = sun_drives + c - 'A';
265 break;
266 }
267 if (c == '?' && scsi_disk) {
268 p = sun_autoconfigure_scsi();
269 if (p)
270 break;
271 printf("Autoconfigure failed\n");
272 }
273 }
274 }
275 if (!p || floppy) {
276 if (!ioctl(dev_fd, HDIO_GETGEO, &geometry)) {
277 g_heads = geometry.heads;
278 g_sectors = geometry.sectors;
279 g_cylinders = geometry.cylinders;
280 } else {
281 g_heads = 0;
282 g_sectors = 0;
283 g_cylinders = 0;
284 }
285 if (floppy) {
286 sunlabel->nacyl = 0;
287 sunlabel->pcylcount = SUN_SSWAP16(g_cylinders);
288 sunlabel->rspeed = SUN_SSWAP16(300);
289 sunlabel->ilfact = SUN_SSWAP16(1);
290 sunlabel->sparecyl = 0;
291 } else {
292 g_heads = read_int(1, g_heads, 1024, 0, "Heads");
293 g_sectors = read_int(1, g_sectors, 1024, 0, "Sectors/track");
294 if (g_cylinders)
295 g_cylinders = read_int(1, g_cylinders - 2, 65535, 0, "Cylinders");
296 else
297 g_cylinders = read_int(1, 0, 65535, 0, "Cylinders");
298 sunlabel->nacyl = SUN_SSWAP16(read_int(0, 2, 65535, 0, "Alternate cylinders"));
299 sunlabel->pcylcount = SUN_SSWAP16(read_int(0, g_cylinders + SUN_SSWAP16(sunlabel->nacyl), 65535, 0, "Physical cylinders"));
300 sunlabel->rspeed = SUN_SSWAP16(read_int(1, 5400, 100000, 0, "Rotation speed (rpm)"));
301 sunlabel->ilfact = SUN_SSWAP16(read_int(1, 1, 32, 0, "Interleave factor"));
302 sunlabel->sparecyl = SUN_SSWAP16(read_int(0, 0, g_sectors, 0, "Extra sectors per cylinder"));
303 }
304 } else {
305 sunlabel->sparecyl = SUN_SSWAP16(p->sparecyl);
306 sunlabel->ncyl = SUN_SSWAP16(p->ncyl);
307 sunlabel->nacyl = SUN_SSWAP16(p->nacyl);
308 sunlabel->pcylcount = SUN_SSWAP16(p->pcylcount);
309 sunlabel->ntrks = SUN_SSWAP16(p->ntrks);
310 sunlabel->nsect = SUN_SSWAP16(p->nsect);
311 sunlabel->rspeed = SUN_SSWAP16(p->rspeed);
312 sunlabel->ilfact = SUN_SSWAP16(1);
313 g_cylinders = p->ncyl;
314 g_heads = p->ntrks;
315 g_sectors = p->nsect;
316 puts("You may change all the disk params from the x menu");
317 }
318
319 snprintf((char *)(sunlabel->info), sizeof(sunlabel->info),
320 "%s%s%s cyl %d alt %d hd %d sec %d",
321 p ? p->vendor : "", (p && *p->vendor) ? " " : "",
322 p ? p->model : (floppy ? "3,5\" floppy" : "Linux custom"),
323 g_cylinders, SUN_SSWAP16(sunlabel->nacyl), g_heads, g_sectors);
324
325 sunlabel->ntrks = SUN_SSWAP16(g_heads);
326 sunlabel->nsect = SUN_SSWAP16(g_sectors);
327 sunlabel->ncyl = SUN_SSWAP16(g_cylinders);
328 if (floppy)
329 set_sun_partition(0, 0, g_cylinders * g_heads * g_sectors, LINUX_NATIVE);
330 else {
331 if (g_cylinders * g_heads * g_sectors >= 150 * 2048) {
332 ndiv = g_cylinders - (50 * 2048 / (g_heads * g_sectors));
333 } else
334 ndiv = g_cylinders * 2 / 3;
335 set_sun_partition(0, 0, ndiv * g_heads * g_sectors, LINUX_NATIVE);
336 set_sun_partition(1, ndiv * g_heads * g_sectors, g_cylinders * g_heads * g_sectors, LINUX_SWAP);
337 sunlabel->infos[1].flags |= 0x01;
338 }
339 set_sun_partition(2, 0, g_cylinders * g_heads * g_sectors, SUN_WHOLE_DISK);
340 {
341 unsigned short *ush = (unsigned short *)sunlabel;
342 unsigned short csum = 0;
343 while (ush < (unsigned short *)(&sunlabel->csum))
344 csum ^= *ush++;
345 sunlabel->csum = csum;
346 }
347
348 set_all_unchanged();
349 set_changed(0);
350 get_boot(CREATE_EMPTY_SUN);
351}
352
353static void
354toggle_sunflags(int i, unsigned char mask)
355{
356 if (sunlabel->infos[i].flags & mask)
357 sunlabel->infos[i].flags &= ~mask;
358 else
359 sunlabel->infos[i].flags |= mask;
360 set_changed(i);
361}
362
363static void
364fetch_sun(uint *starts, uint *lens, uint *start, uint *stop)
365{
366 int i, continuous = 1;
367
368 *start = 0;
369 *stop = g_cylinders * g_heads * g_sectors;
370 for (i = 0; i < g_partitions; i++) {
371 if (sunlabel->partitions[i].num_sectors
372 && sunlabel->infos[i].id
373 && sunlabel->infos[i].id != SUN_WHOLE_DISK) {
374 starts[i] = SUN_SSWAP32(sunlabel->partitions[i].start_cylinder) * g_heads * g_sectors;
375 lens[i] = SUN_SSWAP32(sunlabel->partitions[i].num_sectors);
376 if (continuous) {
377 if (starts[i] == *start)
378 *start += lens[i];
379 else if (starts[i] + lens[i] >= *stop)
380 *stop = starts[i];
381 else
382 continuous = 0;
383
384
385 }
386 } else {
387 starts[i] = 0;
388 lens[i] = 0;
389 }
390 }
391}
392
393static uint *verify_sun_starts;
394
395static int
396verify_sun_cmp(int *a, int *b)
397{
398 if (*a == -1) return 1;
399 if (*b == -1) return -1;
400 if (verify_sun_starts[*a] > verify_sun_starts[*b]) return 1;
401 return -1;
402}
403
404static void
405verify_sun(void)
406{
407 uint starts[8], lens[8], start, stop;
408 int i,j,k,starto,endo;
409 int array[8];
410
411 verify_sun_starts = starts;
412 fetch_sun(starts, lens, &start, &stop);
413 for (k = 0; k < 7; k++) {
414 for (i = 0; i < 8; i++) {
415 if (k && (lens[i] % (g_heads * g_sectors))) {
416 printf("Partition %d doesn't end on cylinder boundary\n", i+1);
417 }
418 if (lens[i]) {
419 for (j = 0; j < i; j++)
420 if (lens[j]) {
421 if (starts[j] == starts[i]+lens[i]) {
422 starts[j] = starts[i]; lens[j] += lens[i];
423 lens[i] = 0;
424 } else if (starts[i] == starts[j]+lens[j]){
425 lens[j] += lens[i];
426 lens[i] = 0;
427 } else if (!k) {
428 if (starts[i] < starts[j]+lens[j]
429 && starts[j] < starts[i]+lens[i]) {
430 starto = starts[i];
431 if (starts[j] > starto)
432 starto = starts[j];
433 endo = starts[i]+lens[i];
434 if (starts[j]+lens[j] < endo)
435 endo = starts[j]+lens[j];
436 printf("Partition %d overlaps with others in "
437 "sectors %d-%d\n", i+1, starto, endo);
438 }
439 }
440 }
441 }
442 }
443 }
444 for (i = 0; i < 8; i++) {
445 if (lens[i])
446 array[i] = i;
447 else
448 array[i] = -1;
449 }
450 qsort(array, ARRAY_SIZE(array), sizeof(array[0]),
451 (int (*)(const void *,const void *)) verify_sun_cmp);
452 if (array[0] == -1) {
453 printf("No partitions defined\n");
454 return;
455 }
456 stop = g_cylinders * g_heads * g_sectors;
457 if (starts[array[0]])
458 printf("Unused gap - sectors 0-%d\n", starts[array[0]]);
459 for (i = 0; i < 7 && array[i+1] != -1; i++) {
460 printf("Unused gap - sectors %d-%d\n", starts[array[i]]+lens[array[i]], starts[array[i+1]]);
461 }
462 start = starts[array[i]] + lens[array[i]];
463 if (start < stop)
464 printf("Unused gap - sectors %d-%d\n", start, stop);
465}
466
467static void
468add_sun_partition(int n, int sys)
469{
470 uint start, stop, stop2;
471 uint starts[8], lens[8];
472 int whole_disk = 0;
473
474 char mesg[256];
475 int i, first, last;
476
477 if (sunlabel->partitions[n].num_sectors && sunlabel->infos[n].id) {
478 printf(msg_part_already_defined, n + 1);
479 return;
480 }
481
482 fetch_sun(starts,lens,&start,&stop);
483 if (stop <= start) {
484 if (n == 2)
485 whole_disk = 1;
486 else {
487 printf("Other partitions already cover the whole disk.\n"
488 "Delete/shrink them before retry.\n");
489 return;
490 }
491 }
492 snprintf(mesg, sizeof(mesg), "First %s", str_units(SINGULAR));
493 while (1) {
494 if (whole_disk)
495 first = read_int(0, 0, 0, 0, mesg);
496 else
497 first = read_int(scround(start), scround(stop)+1,
498 scround(stop), 0, mesg);
499 if (display_in_cyl_units)
500 first *= units_per_sector;
501 else
502
503 first = (first + g_heads * g_sectors - 1) / (g_heads * g_sectors);
504 if (n == 2 && first != 0)
505 printf("\
506It is highly recommended that the third partition covers the whole disk\n\
507and is of type 'Whole disk'\n");
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524 for (i = 0; i < g_partitions; i++)
525 if (lens[i] && starts[i] <= first && starts[i] + lens[i] > first)
526 break;
527 if (i < g_partitions && !whole_disk) {
528 if (n == 2 && !first) {
529 whole_disk = 1;
530 break;
531 }
532 printf("Sector %d is already allocated\n", first);
533 } else
534 break;
535 }
536 stop = g_cylinders * g_heads * g_sectors;
537 stop2 = stop;
538 for (i = 0; i < g_partitions; i++) {
539 if (starts[i] > first && starts[i] < stop)
540 stop = starts[i];
541 }
542 snprintf(mesg, sizeof(mesg),
543 "Last %s or +size or +sizeM or +sizeK",
544 str_units(SINGULAR));
545 if (whole_disk)
546 last = read_int(scround(stop2), scround(stop2), scround(stop2),
547 0, mesg);
548 else if (n == 2 && !first)
549 last = read_int(scround(first), scround(stop2), scround(stop2),
550 scround(first), mesg);
551 else
552 last = read_int(scround(first), scround(stop), scround(stop),
553 scround(first), mesg);
554 if (display_in_cyl_units)
555 last *= units_per_sector;
556 if (n == 2 && !first) {
557 if (last >= stop2) {
558 whole_disk = 1;
559 last = stop2;
560 } else if (last > stop) {
561 printf(
562"You haven't covered the whole disk with the 3rd partition,\n"
563"but your value %d %s covers some other partition.\n"
564"Your entry has been changed to %d %s\n",
565 scround(last), str_units(SINGULAR),
566 scround(stop), str_units(SINGULAR));
567 last = stop;
568 }
569 } else if (!whole_disk && last > stop)
570 last = stop;
571
572 if (whole_disk)
573 sys = SUN_WHOLE_DISK;
574 set_sun_partition(n, first, last, sys);
575}
576
577static void
578sun_delete_partition(int i)
579{
580 unsigned int nsec;
581
582 if (i == 2
583 && sunlabel->infos[i].id == SUN_WHOLE_DISK
584 && !sunlabel->partitions[i].start_cylinder
585 && (nsec = SUN_SSWAP32(sunlabel->partitions[i].num_sectors)) == g_heads * g_sectors * g_cylinders)
586 printf("If you want to maintain SunOS/Solaris compatibility, "
587 "consider leaving this\n"
588 "partition as Whole disk (5), starting at 0, with %u "
589 "sectors\n", nsec);
590 sunlabel->infos[i].id = 0;
591 sunlabel->partitions[i].num_sectors = 0;
592}
593
594static void
595sun_change_sysid(int i, int sys)
596{
597 if (sys == LINUX_SWAP && !sunlabel->partitions[i].start_cylinder) {
598 read_maybe_empty(
599 "It is highly recommended that the partition at offset 0\n"
600 "is UFS, EXT2FS filesystem or SunOS swap. Putting Linux swap\n"
601 "there may destroy your partition table and bootblock.\n"
602 "Type YES if you're very sure you would like that partition\n"
603 "tagged with 82 (Linux swap): ");
604 if (strcmp (line_ptr, "YES\n"))
605 return;
606 }
607 switch (sys) {
608 case SUNOS_SWAP:
609 case LINUX_SWAP:
610
611 sunlabel->infos[i].flags |= 0x01;
612 break;
613 default:
614
615
616 sunlabel->infos[i].flags &= ~0x01;
617 break;
618 }
619 sunlabel->infos[i].id = sys;
620}
621
622static void
623sun_list_table(int xtra)
624{
625 int i, w;
626
627 w = strlen(disk_device);
628 if (xtra)
629 printf(
630 "\nDisk %s (Sun disk label): %d heads, %d sectors, %d rpm\n"
631 "%d cylinders, %d alternate cylinders, %d physical cylinders\n"
632 "%d extra sects/cyl, interleave %d:1\n"
633 "%s\n"
634 "Units = %s of %d * 512 bytes\n\n",
635 disk_device, g_heads, g_sectors, SUN_SSWAP16(sunlabel->rspeed),
636 g_cylinders, SUN_SSWAP16(sunlabel->nacyl),
637 SUN_SSWAP16(sunlabel->pcylcount),
638 SUN_SSWAP16(sunlabel->sparecyl),
639 SUN_SSWAP16(sunlabel->ilfact),
640 (char *)sunlabel,
641 str_units(PLURAL), units_per_sector);
642 else
643 printf(
644 "\nDisk %s (Sun disk label): %d heads, %d sectors, %d cylinders\n"
645 "Units = %s of %d * 512 bytes\n\n",
646 disk_device, g_heads, g_sectors, g_cylinders,
647 str_units(PLURAL), units_per_sector);
648
649 printf("%*s Flag Start End Blocks Id System\n",
650 w + 1, "Device");
651 for (i = 0; i < g_partitions; i++) {
652 if (sunlabel->partitions[i].num_sectors) {
653 uint32_t start = SUN_SSWAP32(sunlabel->partitions[i].start_cylinder) * g_heads * g_sectors;
654 uint32_t len = SUN_SSWAP32(sunlabel->partitions[i].num_sectors);
655 printf("%s %c%c %9ld %9ld %9ld%c %2x %s\n",
656 partname(disk_device, i+1, w),
657 (sunlabel->infos[i].flags & 0x01) ? 'u' : ' ',
658 (sunlabel->infos[i].flags & 0x10) ? 'r' : ' ',
659 (long) scround(start),
660 (long) scround(start+len),
661 (long) len / 2, len & 1 ? '+' : ' ',
662 sunlabel->infos[i].id,
663 partition_type(sunlabel->infos[i].id));
664 }
665 }
666}
667
668#if ENABLE_FEATURE_FDISK_ADVANCED
669
670static void
671sun_set_alt_cyl(void)
672{
673 sunlabel->nacyl =
674 SUN_SSWAP16(read_int(0, SUN_SSWAP16(sunlabel->nacyl), 65535, 0,
675 "Number of alternate cylinders"));
676}
677
678static void
679sun_set_ncyl(int cyl)
680{
681 sunlabel->ncyl = SUN_SSWAP16(cyl);
682}
683
684static void
685sun_set_xcyl(void)
686{
687 sunlabel->sparecyl =
688 SUN_SSWAP16(read_int(0, SUN_SSWAP16(sunlabel->sparecyl), g_sectors, 0,
689 "Extra sectors per cylinder"));
690}
691
692static void
693sun_set_ilfact(void)
694{
695 sunlabel->ilfact =
696 SUN_SSWAP16(read_int(1, SUN_SSWAP16(sunlabel->ilfact), 32, 0,
697 "Interleave factor"));
698}
699
700static void
701sun_set_rspeed(void)
702{
703 sunlabel->rspeed =
704 SUN_SSWAP16(read_int(1, SUN_SSWAP16(sunlabel->rspeed), 100000, 0,
705 "Rotation speed (rpm)"));
706}
707
708static void
709sun_set_pcylcount(void)
710{
711 sunlabel->pcylcount =
712 SUN_SSWAP16(read_int(0, SUN_SSWAP16(sunlabel->pcylcount), 65535, 0,
713 "Number of physical cylinders"));
714}
715#endif
716
717static void
718sun_write_table(void)
719{
720 unsigned short *ush = (unsigned short *)sunlabel;
721 unsigned short csum = 0;
722
723 while (ush < (unsigned short *)(&sunlabel->csum))
724 csum ^= *ush++;
725 sunlabel->csum = csum;
726 write_sector(0, sunlabel);
727}
728#endif
729