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