Print this page
6581 cmd/format should be able label virtio BLKDEV drives
Reviewed by: Hans Rosenfeld <hans.rosenfeld@nexenta.com>
Reviewed by: Toomas Soome <tsoome@me.com>
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/cmd/format/auto_sense.c
+++ new/usr/src/cmd/format/auto_sense.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
↓ open down ↓ |
16 lines elided |
↑ open up ↑ |
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21 /*
22 22 * Copyright (c) 2011 Gary Mills
23 23 *
24 24 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
25 25 * Use is subject to license terms.
26 26 * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
27 + * Copyright 2016 Igor Kozhukhov <ikozhukhov@gmail.com>
27 28 */
28 29
29 30 /*
30 31 * This file contains functions to implement automatic configuration
31 32 * of scsi disks.
32 33 */
33 34 #include "global.h"
34 35
35 36 #include <fcntl.h>
36 37 #include <stdlib.h>
37 38 #include <string.h>
38 39 #include <strings.h>
39 40 #include <stdlib.h>
40 41 #include <ctype.h>
41 42
42 43 #include "misc.h"
43 44 #include "param.h"
44 45 #include "ctlr_scsi.h"
45 46 #include "auto_sense.h"
46 47 #include "partition.h"
47 48 #include "label.h"
48 49 #include "startup.h"
49 50 #include "analyze.h"
50 51 #include "io.h"
51 52 #include "hardware_structs.h"
52 53 #include "menu_fdisk.h"
53 54
54 55
55 56 #define DISK_NAME_MAX 256
56 57
57 58 extern int nctypes;
58 59 extern struct ctlr_type ctlr_types[];
59 60
60 61
61 62 /*
62 63 * Marker for free hog partition
63 64 */
64 65 #define HOG (-1)
65 66
66 67
67 68
68 69 /*
69 70 * Default partition tables
70 71 *
71 72 * Disk capacity root swap usr
72 73 * ------------- ---- ---- ---
73 74 * 0mb to 64mb 0 0 remainder
74 75 * 64mb to 180mb 16mb 16mb remainder
75 76 * 180mb to 280mb 16mb 32mb remainder
76 77 * 280mb to 380mb 24mb 32mb remainder
77 78 * 380mb to 600mb 32mb 32mb remainder
78 79 * 600mb to 1gb 32mb 64mb remainder
79 80 * 1gb to 2gb 64mb 128mb remainder
80 81 * 2gb on up 128mb 128mb remainder
81 82 */
82 83 struct part_table {
83 84 int partitions[NDKMAP];
84 85 };
85 86
86 87 static struct part_table part_table_64mb = {
87 88 { 0, 0, 0, 0, 0, 0, HOG, 0}
88 89 };
89 90
90 91 static struct part_table part_table_180mb = {
91 92 { 16, 16, 0, 0, 0, 0, HOG, 0}
92 93 };
93 94
94 95 static struct part_table part_table_280mb = {
95 96 { 16, 32, 0, 0, 0, 0, HOG, 0}
96 97 };
97 98
98 99 static struct part_table part_table_380mb = {
99 100 { 24, 32, 0, 0, 0, 0, HOG, 0}
100 101 };
101 102
102 103 static struct part_table part_table_600mb = {
103 104 { 32, 32, 0, 0, 0, 0, HOG, 0}
104 105 };
105 106
106 107 static struct part_table part_table_1gb = {
107 108 { 32, 64, 0, 0, 0, 0, HOG, 0}
108 109 };
109 110
110 111 static struct part_table part_table_2gb = {
111 112 { 64, 128, 0, 0, 0, 0, HOG, 0}
112 113 };
113 114
114 115 static struct part_table part_table_infinity = {
115 116 { 128, 128, 0, 0, 0, 0, HOG, 0}
116 117 };
117 118
118 119
119 120 static struct default_partitions {
120 121 diskaddr_t min_capacity;
121 122 diskaddr_t max_capacity;
122 123 struct part_table *part_table;
123 124 } default_partitions[] = {
124 125 { 0, 64, &part_table_64mb }, /* 0 to 64 mb */
125 126 { 64, 180, &part_table_180mb }, /* 64 to 180 mb */
126 127 { 180, 280, &part_table_280mb }, /* 180 to 280 mb */
127 128 { 280, 380, &part_table_380mb }, /* 280 to 380 mb */
128 129 { 380, 600, &part_table_600mb }, /* 380 to 600 mb */
129 130 { 600, 1024, &part_table_1gb }, /* 600 to 1 gb */
130 131 { 1024, 2048, &part_table_2gb }, /* 1 to 2 gb */
131 132 { 2048, INFINITY, &part_table_infinity }, /* 2 gb on up */
132 133 };
133 134
134 135 #define DEFAULT_PARTITION_TABLE_SIZE \
135 136 (sizeof (default_partitions) / sizeof (struct default_partitions))
136 137
137 138 /*
138 139 * msgs for check()
139 140 */
140 141 #define FORMAT_MSG "Auto configuration via format.dat"
141 142 #define GENERIC_MSG "Auto configuration via generic SCSI-2"
142 143
143 144 /*
144 145 * Disks on symbios(Hardwire raid controller) return a fixed number
145 146 * of heads(64)/cylinders(64) and adjust the cylinders depending
146 147 * capacity of the configured lun.
147 148 * In such a case we get number of physical cylinders < 3 which
148 149 * is the minimum required by solaris(2 reserved + 1 data cylinders).
149 150 * Hence try to adjust the cylinders by reducing the "nsect/nhead".
150 151 *
151 152 */
152 153 /*
153 154 * assuming a minimum of 32 block cylinders.
154 155 */
155 156 #define MINIMUM_NO_HEADS 2
156 157 #define MINIMUM_NO_SECTORS 16
157 158
158 159 #define MINIMUM_NO_CYLINDERS 128
159 160
160 161 #if defined(_SUNOS_VTOC_8)
161 162
162 163 /* These are 16-bit fields */
163 164 #define MAXIMUM_NO_HEADS 65535
164 165 #define MAXIMUM_NO_SECTORS 65535
165 166 #define MAXIMUM_NO_CYLINDERS 65535
166 167
167 168 #endif /* defined(_SUNOS_VTOC_8) */
168 169
169 170 /*
170 171 * minimum number of cylinders required by Solaris.
171 172 */
172 173 #define SUN_MIN_CYL 3
173 174
174 175
175 176
176 177 /*
177 178 * ANSI prototypes for local static functions
178 179 */
179 180 static struct disk_type *generic_disk_sense(
180 181 int fd,
181 182 int can_prompt,
182 183 struct dk_label *label,
183 184 struct scsi_inquiry *inquiry,
184 185 struct scsi_capacity_16 *capacity,
185 186 char *disk_name);
186 187 static int use_existing_disk_type(
187 188 int fd,
188 189 int can_prompt,
189 190 struct dk_label *label,
190 191 struct scsi_inquiry *inquiry,
191 192 struct disk_type *disk_type,
192 193 struct scsi_capacity_16 *capacity);
193 194 int build_default_partition(struct dk_label *label,
194 195 int ctrl_type);
195 196 static struct disk_type *find_scsi_disk_type(
196 197 char *disk_name,
197 198 struct dk_label *label);
198 199 static struct disk_type *find_scsi_disk_by_name(
199 200 char *disk_name);
200 201 static struct ctlr_type *find_scsi_ctlr_type(void);
201 202 static struct ctlr_info *find_scsi_ctlr_info(
202 203 struct dk_cinfo *dkinfo);
↓ open down ↓ |
166 lines elided |
↑ open up ↑ |
203 204 static struct disk_type *new_scsi_disk_type(
204 205 int fd,
205 206 char *disk_name,
206 207 struct dk_label *label);
207 208 static struct disk_info *find_scsi_disk_info(
208 209 struct dk_cinfo *dkinfo);
209 210
210 211 static struct disk_type *new_direct_disk_type(int fd, char *disk_name,
211 212 struct dk_label *label);
212 213
213 -static struct disk_info *find_direct_disk_info(struct dk_cinfo *dkinfo);
214 214 static int efi_ioctl(int fd, int cmd, dk_efi_t *dk_ioc);
215 215 static int auto_label_init(struct dk_label *label);
216 -static struct ctlr_type *find_direct_ctlr_type(void);
217 -static struct ctlr_info *find_direct_ctlr_info(struct dk_cinfo *dkinfo);
218 -static struct disk_info *find_direct_disk_info(struct dk_cinfo *dkinfo);
219 -static struct ctlr_type *find_vbd_ctlr_type(void);
220 -static struct ctlr_info *find_vbd_ctlr_info(struct dk_cinfo *dkinfo);
221 -static struct disk_info *find_vbd_disk_info(struct dk_cinfo *dkinfo);
216 +static struct ctlr_type *find_ctlr_type(ushort_t);
217 +static struct ctlr_info *find_ctlr_info(struct dk_cinfo *, ushort_t);
218 +static struct disk_info *find_disk_info(struct dk_cinfo *, ushort_t);
222 219
223 220 static char *get_sun_disk_name(
224 221 char *disk_name,
225 222 struct scsi_inquiry *inquiry);
226 223 static char *strcopy(
227 224 char *dst,
228 225 char *src,
229 226 int n);
230 227 static int adjust_disk_geometry(diskaddr_t capacity, uint_t *cyl,
231 228 uint_t *nsect, uint_t *nhead);
232 229 static void compute_chs_values(diskaddr_t total_capacity,
233 230 diskaddr_t usable_capacity, uint_t *pcylp,
234 231 uint_t *nheadp, uint_t *nsectp);
235 232 #if defined(_SUNOS_VTOC_8)
236 233 static diskaddr_t square_box(
237 234 diskaddr_t capacity,
238 235 uint_t *dim1, uint_t lim1,
239 236 uint_t *dim2, uint_t lim2,
240 237 uint_t *dim3, uint_t lim3);
241 238 #endif /* defined(_SUNOS_VTOC_8) */
242 239
243 240
244 241 /*
245 242 * We need to get information necessary to construct a *new* efi
246 243 * label type
247 244 */
248 245 struct disk_type *
249 246 auto_efi_sense(int fd, struct efi_info *label)
250 247 {
251 248
252 249 struct dk_gpt *vtoc;
253 250 int i;
254 251
255 252 struct disk_type *disk, *dp;
256 253 struct disk_info *disk_info;
↓ open down ↓ |
25 lines elided |
↑ open up ↑ |
257 254 struct ctlr_info *ctlr;
258 255 struct dk_cinfo dkinfo;
259 256 struct partition_info *part;
260 257
261 258 if (ioctl(fd, DKIOCINFO, &dkinfo) == -1) {
262 259 if (option_msg && diag_msg) {
263 260 err_print("DKIOCINFO failed\n");
264 261 }
265 262 return (NULL);
266 263 }
267 - if ((cur_ctype != NULL) && (cur_ctype->ctype_ctype == DKC_DIRECT)) {
268 - ctlr = find_direct_ctlr_info(&dkinfo);
269 - disk_info = find_direct_disk_info(&dkinfo);
270 - } else if ((cur_ctype != NULL) && (cur_ctype->ctype_ctype == DKC_VBD)) {
271 - ctlr = find_vbd_ctlr_info(&dkinfo);
272 - disk_info = find_vbd_disk_info(&dkinfo);
264 + if ((cur_ctype != NULL) && (cur_ctype->ctype_ctype == DKC_DIRECT ||
265 + cur_ctype->ctype_ctype == DKC_VBD ||
266 + cur_ctype->ctype_ctype == DKC_BLKDEV)) {
267 + ctlr = find_ctlr_info(&dkinfo, cur_ctype->ctype_ctype);
268 + disk_info = find_disk_info(&dkinfo, cur_ctype->ctype_ctype);
273 269 } else {
274 270 ctlr = find_scsi_ctlr_info(&dkinfo);
275 271 disk_info = find_scsi_disk_info(&dkinfo);
276 272 }
277 273
278 274 /*
279 275 * get vendor, product, revision and capacity info.
280 276 */
281 277 if (get_disk_info(fd, label, disk_info) == -1) {
282 278 return ((struct disk_type *)NULL);
283 279 }
284 280 /*
285 281 * Now build the default partition table
286 282 */
287 283 if (efi_alloc_and_init(fd, EFI_NUMPAR, &vtoc) != 0) {
288 284 err_print("efi_alloc_and_init failed. \n");
289 285 return ((struct disk_type *)NULL);
290 286 }
291 287
292 288 label->e_parts = vtoc;
293 289
294 290 /*
295 291 * Create a whole hog EFI partition table:
296 292 * S0 takes the whole disk except the primary EFI label,
297 293 * backup EFI label, and the reserved partition.
298 294 */
299 295 vtoc->efi_parts[0].p_tag = V_USR;
300 296 vtoc->efi_parts[0].p_start = vtoc->efi_first_u_lba;
301 297 vtoc->efi_parts[0].p_size = vtoc->efi_last_u_lba - vtoc->efi_first_u_lba
302 298 - EFI_MIN_RESV_SIZE + 1;
303 299
304 300 /*
305 301 * S1-S6 are unassigned slices.
306 302 */
307 303 for (i = 1; i < vtoc->efi_nparts - 2; i ++) {
308 304 vtoc->efi_parts[i].p_tag = V_UNASSIGNED;
309 305 vtoc->efi_parts[i].p_start = 0;
310 306 vtoc->efi_parts[i].p_size = 0;
311 307 }
312 308
313 309 /*
314 310 * The reserved slice
315 311 */
316 312 vtoc->efi_parts[vtoc->efi_nparts - 1].p_tag = V_RESERVED;
317 313 vtoc->efi_parts[vtoc->efi_nparts - 1].p_start =
318 314 vtoc->efi_last_u_lba - EFI_MIN_RESV_SIZE + 1;
319 315 vtoc->efi_parts[vtoc->efi_nparts - 1].p_size = EFI_MIN_RESV_SIZE;
320 316
321 317 /*
322 318 * Now stick all of it into the disk_type struct
323 319 */
324 320
325 321 disk = (struct disk_type *)zalloc(sizeof (struct disk_type));
326 322 assert(disk_info->disk_ctlr == ctlr);
327 323 dp = ctlr->ctlr_ctype->ctype_dlist;
328 324 if (dp == NULL) {
329 325 ctlr->ctlr_ctype->ctype_dlist = dp;
330 326 } else {
331 327 while (dp->dtype_next != NULL) {
332 328 dp = dp->dtype_next;
333 329 }
334 330 dp->dtype_next = disk;
335 331 }
336 332 disk->dtype_next = NULL;
337 333
338 334 disk->vendor = strdup(label->vendor);
339 335 disk->product = strdup(label->product);
340 336 disk->revision = strdup(label->revision);
341 337
342 338 if (disk->vendor == NULL ||
343 339 disk->product == NULL ||
344 340 disk->revision == NULL) {
345 341 free(disk->vendor);
346 342 free(disk->product);
347 343 free(disk->revision);
348 344 free(disk);
349 345 return (NULL);
350 346 }
351 347
352 348 disk->capacity = label->capacity;
353 349
354 350 part = (struct partition_info *)
355 351 zalloc(sizeof (struct partition_info));
356 352 disk->dtype_plist = part;
357 353
358 354 part->pinfo_name = alloc_string("default");
359 355 part->pinfo_next = NULL;
360 356 part->etoc = vtoc;
361 357
362 358 bzero(disk_info->v_volume, LEN_DKL_VVOL);
363 359 disk_info->disk_parts = part;
364 360 return (disk);
365 361 }
366 362
367 363 static int
368 364 efi_ioctl(int fd, int cmd, dk_efi_t *dk_ioc)
369 365 {
370 366 void *data = dk_ioc->dki_data;
↓ open down ↓ |
88 lines elided |
↑ open up ↑ |
371 367 int error;
372 368
373 369 dk_ioc->dki_data_64 = (uint64_t)(uintptr_t)data;
374 370 error = ioctl(fd, cmd, (void *)dk_ioc);
375 371 dk_ioc->dki_data = data;
376 372
377 373 return (error);
378 374 }
379 375
380 376 static struct ctlr_type *
381 -find_direct_ctlr_type()
377 +find_ctlr_type(ushort_t type)
382 378 {
383 379 struct mctlr_list *mlp;
384 380
385 - mlp = controlp;
381 + assert(type == DKC_DIRECT ||
382 + type == DKC_VBD ||
383 + type == DKC_BLKDEV);
386 384
387 - while (mlp != NULL) {
388 - if (mlp->ctlr_type->ctype_ctype == DKC_DIRECT) {
389 - return (mlp->ctlr_type);
390 - }
391 - mlp = mlp->next;
392 - }
393 -
394 - impossible("no DIRECT controller type");
395 -
396 - return ((struct ctlr_type *)NULL);
397 -}
398 -
399 -static struct ctlr_type *
400 -find_vbd_ctlr_type()
401 -{
402 - struct mctlr_list *mlp;
403 -
404 385 mlp = controlp;
405 386
406 387 while (mlp != NULL) {
407 - if (mlp->ctlr_type->ctype_ctype == DKC_VBD) {
388 + if (mlp->ctlr_type->ctype_ctype == type) {
408 389 return (mlp->ctlr_type);
409 390 }
410 391 mlp = mlp->next;
411 392 }
412 393
413 - impossible("no VBD controller type");
394 + impossible("no DIRECT/VBD/BLKDEV controller type");
414 395
415 396 return ((struct ctlr_type *)NULL);
416 397 }
417 398
418 399 static struct ctlr_info *
419 -find_direct_ctlr_info(
420 - struct dk_cinfo *dkinfo)
400 +find_ctlr_info(struct dk_cinfo *dkinfo, ushort_t type)
421 401 {
422 402 struct ctlr_info *ctlr;
423 403
424 - if (dkinfo->dki_ctype != DKC_DIRECT)
425 - return (NULL);
404 + assert(type == DKC_DIRECT ||
405 + type == DKC_VBD ||
406 + type == DKC_BLKDEV);
426 407
427 408 for (ctlr = ctlr_list; ctlr != NULL; ctlr = ctlr->ctlr_next) {
428 409 if (ctlr->ctlr_addr == dkinfo->dki_addr &&
429 410 ctlr->ctlr_space == dkinfo->dki_space &&
430 - ctlr->ctlr_ctype->ctype_ctype == DKC_DIRECT) {
411 + ctlr->ctlr_ctype->ctype_ctype == dkinfo->dki_ctype) {
431 412 return (ctlr);
432 413 }
433 414 }
434 415
435 - impossible("no DIRECT controller info");
416 + impossible("no DIRECT/VBD/BLKDEV controller info");
436 417 /*NOTREACHED*/
418 + return ((struct ctlr_info *)NULL);
437 419 }
438 420
439 -static struct ctlr_info *
440 -find_vbd_ctlr_info(
441 - struct dk_cinfo *dkinfo)
442 -{
443 - struct ctlr_info *ctlr;
444 -
445 - if (dkinfo->dki_ctype != DKC_VBD)
446 - return (NULL);
447 -
448 - for (ctlr = ctlr_list; ctlr != NULL; ctlr = ctlr->ctlr_next) {
449 - if (ctlr->ctlr_addr == dkinfo->dki_addr &&
450 - ctlr->ctlr_space == dkinfo->dki_space &&
451 - ctlr->ctlr_ctype->ctype_ctype == DKC_VBD) {
452 - return (ctlr);
453 - }
454 - }
455 -
456 - impossible("no VBD controller info");
457 - /*NOTREACHED*/
458 -}
459 -
460 421 static struct disk_info *
461 -find_direct_disk_info(
462 - struct dk_cinfo *dkinfo)
422 +find_disk_info(struct dk_cinfo *dkinfo, ushort_t type)
463 423 {
464 424 struct disk_info *disk;
465 425 struct dk_cinfo *dp;
466 426
467 - for (disk = disk_list; disk != NULL; disk = disk->disk_next) {
468 - assert(dkinfo->dki_ctype == DKC_DIRECT);
469 - dp = &disk->disk_dkinfo;
470 - if (dp->dki_ctype == dkinfo->dki_ctype &&
471 - dp->dki_cnum == dkinfo->dki_cnum &&
472 - dp->dki_unit == dkinfo->dki_unit &&
473 - strcmp(dp->dki_dname, dkinfo->dki_dname) == 0) {
474 - return (disk);
475 - }
476 - }
427 + assert(type == DKC_DIRECT ||
428 + type == DKC_VBD ||
429 + type == DKC_BLKDEV);
477 430
478 - impossible("No DIRECT disk info instance\n");
479 - /*NOTREACHED*/
480 -}
481 -
482 -static struct disk_info *
483 -find_vbd_disk_info(
484 - struct dk_cinfo *dkinfo)
485 -{
486 - struct disk_info *disk;
487 - struct dk_cinfo *dp;
488 -
489 431 for (disk = disk_list; disk != NULL; disk = disk->disk_next) {
490 - assert(dkinfo->dki_ctype == DKC_VBD);
491 432 dp = &disk->disk_dkinfo;
492 433 if (dp->dki_ctype == dkinfo->dki_ctype &&
493 434 dp->dki_cnum == dkinfo->dki_cnum &&
494 435 dp->dki_unit == dkinfo->dki_unit &&
495 436 strcmp(dp->dki_dname, dkinfo->dki_dname) == 0) {
496 437 return (disk);
497 438 }
498 439 }
499 440
500 - impossible("No VBD disk info instance\n");
441 + impossible("No DIRECT/VBD/BLKDEV disk info instance\n");
501 442 /*NOTREACHED*/
443 + return ((struct disk_info *)NULL);
502 444 }
503 445
504 446 /*
505 447 * To convert EFI to SMI labels, we need to get label geometry.
506 448 * Unfortunately at this time there is no good way to do so.
507 449 * DKIOCGGEOM will fail if disk is EFI labeled. So we hack around
508 450 * it and clear EFI label, do a DKIOCGGEOM and put the EFI label
509 451 * back on disk.
510 452 * This routine gets the label geometry and initializes the label
511 453 * It uses cur_file as opened device.
512 454 * returns 0 if succeeds or -1 if failed.
513 455 */
514 456 static int
515 457 auto_label_init(struct dk_label *label)
516 458 {
517 459 dk_efi_t dk_ioc;
518 460 dk_efi_t dk_ioc_back;
519 461 efi_gpt_t *data = NULL;
520 462 efi_gpt_t *databack = NULL;
521 463 struct dk_geom disk_geom;
522 464 struct dk_minfo disk_info;
523 465 efi_gpt_t *backsigp;
524 466 int fd = cur_file;
525 467 int rval = -1;
526 468 int efisize = EFI_LABEL_SIZE * 2;
527 469 int success = 0;
528 470 uint64_t sig;
529 471 uint64_t backsig;
530 472
531 473 if ((data = calloc(efisize, 1)) == NULL) {
532 474 err_print("auto_label_init: calloc failed\n");
533 475 goto auto_label_init_out;
534 476 }
535 477
536 478 dk_ioc.dki_data = data;
537 479 dk_ioc.dki_lba = 1;
538 480 dk_ioc.dki_length = efisize;
539 481
540 482 if (efi_ioctl(fd, DKIOCGETEFI, &dk_ioc) != 0) {
541 483 err_print("auto_label_init: GETEFI failed\n");
542 484 goto auto_label_init_out;
543 485 }
544 486
545 487 if ((databack = calloc(efisize, 1)) == NULL) {
546 488 err_print("auto_label_init calloc2 failed");
547 489 goto auto_label_init_out;
548 490 }
549 491
550 492 /* get the LBA size and capacity */
551 493 if (ioctl(fd, DKIOCGMEDIAINFO, (caddr_t)&disk_info) == -1) {
552 494 err_print("auto_label_init: dkiocgmediainfo failed\n");
553 495 goto auto_label_init_out;
554 496 }
555 497
556 498 if (disk_info.dki_lbsize == 0) {
557 499 if (option_msg && diag_msg) {
558 500 err_print("auto_lbal_init: assuming 512 byte"
559 501 "block size");
560 502 }
561 503 disk_info.dki_lbsize = DEV_BSIZE;
562 504 }
563 505
564 506 dk_ioc_back.dki_data = databack;
565 507
566 508 /*
567 509 * back up efi label goes to capacity - 1, we are reading an extra block
568 510 * before the back up label.
569 511 */
570 512 dk_ioc_back.dki_lba = disk_info.dki_capacity - 1 - 1;
571 513 dk_ioc_back.dki_length = efisize;
572 514
573 515 if (efi_ioctl(fd, DKIOCGETEFI, &dk_ioc_back) != 0) {
574 516 err_print("auto_label_init: GETEFI backup failed\n");
575 517 goto auto_label_init_out;
576 518 }
577 519
578 520 sig = dk_ioc.dki_data->efi_gpt_Signature;
579 521 dk_ioc.dki_data->efi_gpt_Signature = 0x0;
580 522
581 523 enter_critical();
582 524
583 525 if (efi_ioctl(fd, DKIOCSETEFI, &dk_ioc) == -1) {
584 526 err_print("auto_label_init: SETEFI failed\n");
585 527 exit_critical();
586 528 goto auto_label_init_out;
587 529 }
588 530
589 531 backsigp = (efi_gpt_t *)((uintptr_t)dk_ioc_back.dki_data + cur_blksz);
590 532
591 533 backsig = backsigp->efi_gpt_Signature;
592 534
593 535 backsigp->efi_gpt_Signature = 0;
594 536
595 537 if (efi_ioctl(fd, DKIOCSETEFI, &dk_ioc_back) == -1) {
596 538 err_print("auto_label_init: SETEFI backup failed\n");
597 539 }
598 540
599 541 if (ioctl(cur_file, DKIOCGGEOM, &disk_geom) != 0)
600 542 err_print("auto_label_init: GGEOM failed\n");
601 543 else
602 544 success = 1;
603 545
604 546 dk_ioc.dki_data->efi_gpt_Signature = sig;
605 547 backsigp->efi_gpt_Signature = backsig;
606 548
607 549 if (efi_ioctl(cur_file, DKIOCSETEFI, &dk_ioc_back) == -1) {
608 550 err_print("auto_label_init: SETEFI revert backup failed\n");
609 551 success = 0;
610 552 }
611 553
612 554 if (efi_ioctl(cur_file, DKIOCSETEFI, &dk_ioc) == -1) {
613 555 err_print("auto_label_init: SETEFI revert failed\n");
614 556 success = 0;
615 557 }
616 558
617 559 exit_critical();
618 560
619 561 if (success == 0)
620 562 goto auto_label_init_out;
621 563
622 564 ncyl = disk_geom.dkg_ncyl;
623 565 acyl = disk_geom.dkg_acyl;
624 566 nhead = disk_geom.dkg_nhead;
625 567 nsect = disk_geom.dkg_nsect;
626 568 pcyl = ncyl + acyl;
627 569
628 570 label->dkl_pcyl = pcyl;
629 571 label->dkl_ncyl = ncyl;
630 572 label->dkl_acyl = acyl;
631 573 label->dkl_nhead = nhead;
632 574 label->dkl_nsect = nsect;
633 575 label->dkl_apc = 0;
634 576 label->dkl_intrlv = 1;
635 577 label->dkl_rpm = disk_geom.dkg_rpm;
636 578
637 579 label->dkl_magic = DKL_MAGIC;
638 580
639 581 (void) snprintf(label->dkl_asciilabel, sizeof (label->dkl_asciilabel),
640 582 "%s cyl %u alt %u hd %u sec %u",
641 583 "DEFAULT", ncyl, acyl, nhead, nsect);
642 584
643 585 rval = 0;
644 586 #if defined(_FIRMWARE_NEEDS_FDISK)
645 587 (void) auto_solaris_part(label);
646 588 ncyl = label->dkl_ncyl;
647 589
648 590 #endif /* defined(_FIRMWARE_NEEDS_FDISK) */
649 591
650 592 if (!build_default_partition(label, DKC_DIRECT)) {
651 593 rval = -1;
652 594 }
653 595
654 596 (void) checksum(label, CK_MAKESUM);
655 597
656 598
657 599 auto_label_init_out:
658 600 if (data)
659 601 free(data);
660 602 if (databack)
661 603 free(databack);
662 604
663 605 return (rval);
664 606 }
665 607
666 608 static struct disk_type *
667 609 new_direct_disk_type(
668 610 int fd,
669 611 char *disk_name,
670 612 struct dk_label *label)
671 613 {
672 614 struct disk_type *dp;
673 615 struct disk_type *disk;
674 616 struct ctlr_info *ctlr;
675 617 struct dk_cinfo dkinfo;
676 618 struct partition_info *part = NULL;
677 619 struct partition_info *pt;
678 620 struct disk_info *disk_info;
679 621 int i;
680 622
681 623 /*
682 624 * Get the disk controller info for this disk
683 625 */
↓ open down ↓ |
172 lines elided |
↑ open up ↑ |
684 626 if (ioctl(fd, DKIOCINFO, &dkinfo) == -1) {
685 627 if (option_msg && diag_msg) {
686 628 err_print("DKIOCINFO failed\n");
687 629 }
688 630 return (NULL);
689 631 }
690 632
691 633 /*
692 634 * Find the ctlr_info for this disk.
693 635 */
694 - ctlr = find_direct_ctlr_info(&dkinfo);
636 + ctlr = find_ctlr_info(&dkinfo, dkinfo.dki_ctype);
695 637
696 638 /*
697 639 * Allocate a new disk type for the direct controller.
698 640 */
699 641 disk = (struct disk_type *)zalloc(sizeof (struct disk_type));
700 642
701 643 /*
702 644 * Find the disk_info instance for this disk.
703 645 */
704 - disk_info = find_direct_disk_info(&dkinfo);
646 + disk_info = find_disk_info(&dkinfo, dkinfo.dki_ctype);
705 647
706 648 /*
707 649 * The controller and the disk should match.
708 650 */
709 651 assert(disk_info->disk_ctlr == ctlr);
710 652
711 653 /*
712 654 * Link the disk into the list of disks
713 655 */
714 656 dp = ctlr->ctlr_ctype->ctype_dlist;
715 657 if (dp == NULL) {
716 658 ctlr->ctlr_ctype->ctype_dlist = dp;
717 659 } else {
718 660 while (dp->dtype_next != NULL) {
719 661 dp = dp->dtype_next;
720 662 }
721 663 dp->dtype_next = disk;
722 664 }
723 665 disk->dtype_next = NULL;
724 666
725 667 /*
726 668 * Allocate and initialize the disk name.
727 669 */
728 670 disk->dtype_asciilabel = alloc_string(disk_name);
729 671
730 672 /*
731 673 * Initialize disk geometry info
732 674 */
733 675 disk->dtype_pcyl = label->dkl_pcyl;
734 676 disk->dtype_ncyl = label->dkl_ncyl;
735 677 disk->dtype_acyl = label->dkl_acyl;
736 678 disk->dtype_nhead = label->dkl_nhead;
737 679 disk->dtype_nsect = label->dkl_nsect;
738 680 disk->dtype_rpm = label->dkl_rpm;
739 681
740 682 part = (struct partition_info *)
741 683 zalloc(sizeof (struct partition_info));
742 684 pt = disk->dtype_plist;
743 685 if (pt == NULL) {
744 686 disk->dtype_plist = part;
745 687 } else {
746 688 while (pt->pinfo_next != NULL) {
747 689 pt = pt->pinfo_next;
748 690 }
749 691 pt->pinfo_next = part;
750 692 }
751 693
752 694 part->pinfo_next = NULL;
753 695
754 696 /*
755 697 * Set up the partition name
756 698 */
757 699 part->pinfo_name = alloc_string("default");
758 700
759 701 /*
760 702 * Fill in the partition info from the label
761 703 */
762 704 for (i = 0; i < NDKMAP; i++) {
763 705
764 706 #if defined(_SUNOS_VTOC_8)
765 707 part->pinfo_map[i] = label->dkl_map[i];
766 708
767 709 #elif defined(_SUNOS_VTOC_16)
768 710 part->pinfo_map[i].dkl_cylno =
769 711 label->dkl_vtoc.v_part[i].p_start /
770 712 ((blkaddr_t)(disk->dtype_nhead *
771 713 disk->dtype_nsect - apc));
772 714 part->pinfo_map[i].dkl_nblk =
773 715 label->dkl_vtoc.v_part[i].p_size;
774 716 #else
775 717 #error No VTOC format defined.
776 718 #endif /* defined(_SUNOS_VTOC_8) */
777 719 }
778 720
779 721 /*
780 722 * Use the VTOC if valid, or install a default
781 723 */
782 724 if (label->dkl_vtoc.v_version == V_VERSION) {
783 725 (void) memcpy(disk_info->v_volume, label->dkl_vtoc.v_volume,
784 726 LEN_DKL_VVOL);
785 727 part->vtoc = label->dkl_vtoc;
786 728 } else {
787 729 (void) memset(disk_info->v_volume, 0, LEN_DKL_VVOL);
788 730 set_vtoc_defaults(part);
789 731 }
790 732
791 733 /*
792 734 * Link the disk to the partition map
793 735 */
794 736 disk_info->disk_parts = part;
795 737
796 738 return (disk);
797 739 }
798 740
799 741 /*
800 742 * Get a disk type that has label info. This is used to convert
801 743 * EFI label to SMI label
802 744 */
803 745 struct disk_type *
804 746 auto_direct_get_geom_label(int fd, struct dk_label *label)
805 747 {
806 748 struct disk_type *disk_type;
807 749
808 750 if (auto_label_init(label) != 0) {
809 751 err_print("auto_direct_get_geom_label: failed to get label"
810 752 "geometry");
811 753 return (NULL);
812 754 } else {
813 755 disk_type = new_direct_disk_type(fd, "DEFAULT", label);
814 756 return (disk_type);
815 757 }
816 758 }
817 759
818 760 /*
819 761 * Auto-sense a scsi disk configuration, ie get the information
820 762 * necessary to construct a label. We have two different
821 763 * ways to auto-sense a scsi disk:
822 764 * - format.dat override, via inquiry name
823 765 * - generic scsi, via standard mode sense and inquiry
824 766 * Depending on how and when we are called, and/or
825 767 * change geometry and reformat.
826 768 */
827 769 struct disk_type *
828 770 auto_sense(
829 771 int fd,
830 772 int can_prompt,
831 773 struct dk_label *label)
832 774 {
833 775 struct scsi_inquiry inquiry;
834 776 struct scsi_capacity_16 capacity;
835 777 struct disk_type *disk_type;
836 778 char disk_name[DISK_NAME_MAX];
837 779 int force_format_dat = 0;
838 780 int force_generic = 0;
839 781 u_ioparam_t ioparam;
840 782 int deflt;
841 783 char *buf;
842 784
843 785 /*
844 786 * First, if expert mode, find out if the user
845 787 * wants to override any of the standard methods.
846 788 */
847 789 if (can_prompt && expert_mode) {
848 790 deflt = 1;
849 791 ioparam.io_charlist = confirm_list;
850 792 if (input(FIO_MSTR, FORMAT_MSG, '?', &ioparam,
851 793 &deflt, DATA_INPUT) == 0) {
852 794 force_format_dat = 1;
853 795 } else if (input(FIO_MSTR, GENERIC_MSG, '?', &ioparam,
854 796 &deflt, DATA_INPUT) == 0) {
855 797 force_generic = 1;
856 798 }
857 799 }
858 800
859 801 /*
860 802 * Get the Inquiry data. If this fails, there's
861 803 * no hope for this disk, so give up.
862 804 */
863 805 if (uscsi_inquiry(fd, (char *)&inquiry, sizeof (inquiry))) {
864 806 return ((struct disk_type *)NULL);
865 807 }
866 808 if (option_msg && diag_msg) {
867 809 err_print("Product id: ");
868 810 print_buf(inquiry.inq_pid, sizeof (inquiry.inq_pid));
869 811 err_print("\n");
870 812 }
871 813
872 814 /*
873 815 * Get the Read Capacity
874 816 */
875 817 if (uscsi_read_capacity(fd, &capacity)) {
876 818 return ((struct disk_type *)NULL);
877 819 }
878 820
879 821 /*
880 822 * If the reported capacity is set to zero, then the disk
881 823 * is not usable. If the reported capacity is set to all
882 824 * 0xf's, then this disk is too large. These could only
883 825 * happen with a device that supports LBAs larger than 64
884 826 * bits which are not defined by any current T10 standards
885 827 * or by error responding from target.
886 828 */
887 829 if ((capacity.sc_capacity == 0) ||
888 830 (capacity.sc_capacity == UINT_MAX64)) {
889 831 if (option_msg && diag_msg) {
890 832 err_print("Invalid capacity\n");
891 833 }
892 834 return ((struct disk_type *)NULL);
893 835 }
894 836 if (option_msg && diag_msg) {
895 837 err_print("blocks: %llu (0x%llx)\n",
896 838 capacity.sc_capacity, capacity.sc_capacity);
897 839 err_print("blksize: %u\n", capacity.sc_lbasize);
898 840 }
899 841
900 842 /*
901 843 * Extract the disk name for the format.dat override
902 844 */
903 845 (void) get_sun_disk_name(disk_name, &inquiry);
904 846 if (option_msg && diag_msg) {
905 847 err_print("disk name: `%s`\n", disk_name);
906 848 }
907 849
908 850 buf = zalloc(cur_blksz);
909 851 if (scsi_rdwr(DIR_READ, fd, (diskaddr_t)0, 1, (caddr_t)buf,
910 852 F_SILENT, NULL)) {
911 853 free(buf);
912 854 return ((struct disk_type *)NULL);
913 855 }
914 856 free(buf);
915 857
916 858 /*
917 859 * Figure out which method we use for auto sense.
918 860 * If a particular method fails, we fall back to
919 861 * the next possibility.
920 862 */
921 863
922 864 if (force_generic) {
923 865 return (generic_disk_sense(fd, can_prompt, label,
924 866 &inquiry, &capacity, disk_name));
925 867 }
926 868
927 869 /*
928 870 * Try for an existing format.dat first
929 871 */
930 872 if ((disk_type = find_scsi_disk_by_name(disk_name)) != NULL) {
931 873 if (use_existing_disk_type(fd, can_prompt, label,
932 874 &inquiry, disk_type, &capacity)) {
933 875 return (disk_type);
934 876 }
935 877 if (force_format_dat) {
936 878 return (NULL);
937 879 }
938 880 }
939 881
940 882 /*
941 883 * Otherwise, try using generic SCSI-2 sense and inquiry.
942 884 */
943 885
944 886 return (generic_disk_sense(fd, can_prompt, label,
945 887 &inquiry, &capacity, disk_name));
946 888 }
947 889
948 890
949 891
950 892 /*ARGSUSED*/
951 893 static struct disk_type *
952 894 generic_disk_sense(
953 895 int fd,
954 896 int can_prompt,
955 897 struct dk_label *label,
956 898 struct scsi_inquiry *inquiry,
957 899 struct scsi_capacity_16 *capacity,
958 900 char *disk_name)
959 901 {
960 902 struct disk_type *disk;
961 903 int setdefault = 0;
962 904 uint_t pcyl = 0;
963 905 uint_t ncyl = 0;
964 906 uint_t acyl = 0;
965 907 uint_t nhead = 0;
966 908 uint_t nsect = 0;
967 909 int rpm = 0;
968 910 diskaddr_t nblocks = 0;
969 911 diskaddr_t tblocks = 0;
970 912 union {
971 913 struct mode_format page3;
972 914 uchar_t buf3[MAX_MODE_SENSE_SIZE];
973 915 } u_page3;
974 916 union {
975 917 struct mode_geometry page4;
976 918 uchar_t buf4[MAX_MODE_SENSE_SIZE];
977 919 } u_page4;
978 920 struct mode_format *page3 = &u_page3.page3;
979 921 struct mode_geometry *page4 = &u_page4.page4;
980 922 struct scsi_ms_header header;
981 923
982 924 /*
983 925 * If the name of this disk appears to be "SUN", use it,
984 926 * otherwise construct a name out of the generic
985 927 * Inquiry info. If it turns out that we already
986 928 * have a SUN disk type of this name that differs
987 929 * in geometry, we will revert to the generic name
988 930 * anyway.
989 931 */
990 932 if (memcmp(disk_name, "SUN", strlen("SUN")) != 0) {
991 933 (void) get_generic_disk_name(disk_name, inquiry);
992 934 }
993 935
994 936 /*
995 937 * Get the number of blocks from Read Capacity data. Note that
996 938 * the logical block address range from 0 to capacity->sc_capacity.
997 939 * Limit the size to 2 TB (UINT32_MAX) to use with SMI labels.
998 940 */
999 941 tblocks = (capacity->sc_capacity + 1);
1000 942 if (tblocks > UINT32_MAX)
1001 943 nblocks = UINT32_MAX;
1002 944 else
1003 945 nblocks = tblocks;
1004 946
1005 947 /*
1006 948 * Get current Page 3 - Format Parameters page
1007 949 */
1008 950 if (uscsi_mode_sense(fd, DAD_MODE_FORMAT, MODE_SENSE_PC_CURRENT,
1009 951 (caddr_t)&u_page3, MAX_MODE_SENSE_SIZE, &header)) {
1010 952 setdefault = 1;
1011 953 }
1012 954
1013 955 /*
1014 956 * Get current Page 4 - Drive Geometry page
1015 957 */
1016 958 if (uscsi_mode_sense(fd, DAD_MODE_GEOMETRY, MODE_SENSE_PC_CURRENT,
1017 959 (caddr_t)&u_page4, MAX_MODE_SENSE_SIZE, &header)) {
1018 960 setdefault = 1;
1019 961 }
1020 962
1021 963 if (setdefault != 1) {
1022 964 /* The inquiry of mode page 3 & page 4 are successful */
1023 965 /*
1024 966 * Correct for byte order if necessary
1025 967 */
1026 968 page4->rpm = BE_16(page4->rpm);
1027 969 page4->step_rate = BE_16(page4->step_rate);
1028 970 page3->tracks_per_zone = BE_16(page3->tracks_per_zone);
1029 971 page3->alt_sect_zone = BE_16(page3->alt_sect_zone);
1030 972 page3->alt_tracks_zone = BE_16(page3->alt_tracks_zone);
1031 973 page3->alt_tracks_vol = BE_16(page3->alt_tracks_vol);
1032 974 page3->sect_track = BE_16(page3->sect_track);
1033 975 page3->data_bytes_sect = BE_16(page3->data_bytes_sect);
1034 976 page3->interleave = BE_16(page3->interleave);
1035 977 page3->track_skew = BE_16(page3->track_skew);
1036 978 page3->cylinder_skew = BE_16(page3->cylinder_skew);
1037 979
1038 980
1039 981 /*
1040 982 * Construct a new label out of the sense data,
1041 983 * Inquiry and Capacity.
1042 984 *
1043 985 * If the disk capacity is > 1TB then simply compute
1044 986 * the CHS values based on the total disk capacity and
1045 987 * not use the values from mode-sense data.
1046 988 */
1047 989 if (tblocks > INT32_MAX) {
1048 990 compute_chs_values(tblocks, nblocks, &pcyl, &nhead,
1049 991 &nsect);
1050 992 } else {
1051 993 pcyl = (page4->cyl_ub << 16) + (page4->cyl_mb << 8) +
1052 994 page4->cyl_lb;
1053 995 nhead = page4->heads;
1054 996 nsect = page3->sect_track;
1055 997 }
1056 998
1057 999 rpm = page4->rpm;
1058 1000
1059 1001 /*
1060 1002 * If the number of physical cylinders reported is less
1061 1003 * the SUN_MIN_CYL(3) then try to adjust the geometry so that
1062 1004 * we have atleast SUN_MIN_CYL cylinders.
1063 1005 */
1064 1006 if (pcyl < SUN_MIN_CYL) {
1065 1007 if (nhead == 0 || nsect == 0) {
1066 1008 setdefault = 1;
1067 1009 } else if (adjust_disk_geometry(
1068 1010 (diskaddr_t)(capacity->sc_capacity + 1),
1069 1011 &pcyl, &nhead, &nsect)) {
1070 1012 setdefault = 1;
1071 1013 }
1072 1014 }
1073 1015 }
1074 1016
1075 1017 /*
1076 1018 * Mode sense page 3 and page 4 are obsolete in SCSI-3. For
1077 1019 * newly developed large sector size disk, we will not rely on
1078 1020 * those two pages but compute geometry directly.
1079 1021 */
1080 1022 if ((setdefault == 1) || (capacity->sc_lbasize != DEV_BSIZE)) {
1081 1023 /*
1082 1024 * If the number of cylinders or the number of heads reported
1083 1025 * is zero, we think the inquiry of page 3 and page 4 failed.
1084 1026 * We will set the geometry infomation by ourselves.
1085 1027 */
1086 1028 compute_chs_values(tblocks, nblocks, &pcyl, &nhead, &nsect);
1087 1029 }
1088 1030
1089 1031 /*
1090 1032 * The sd driver reserves 2 cylinders the backup disk label and
1091 1033 * the deviceid. Set the number of data cylinders to pcyl-acyl.
1092 1034 */
1093 1035 acyl = DK_ACYL;
1094 1036 ncyl = pcyl - acyl;
1095 1037
1096 1038 if (option_msg && diag_msg) {
1097 1039 err_print("Geometry:\n");
1098 1040 err_print(" pcyl: %u\n", pcyl);
1099 1041 err_print(" ncyl: %u\n", ncyl);
1100 1042 err_print(" heads: %u\n", nhead);
1101 1043 err_print(" nsects: %u\n", nsect);
1102 1044 err_print(" acyl: %u\n", acyl);
1103 1045
1104 1046 #if defined(_SUNOS_VTOC_16)
1105 1047 err_print(" bcyl: %u\n", bcyl);
1106 1048 #endif /* defined(_SUNOS_VTOC_16) */
1107 1049
1108 1050 err_print(" rpm: %d\n", rpm);
1109 1051 err_print(" nblocks: %llu\n", nblocks);
1110 1052 }
1111 1053
1112 1054 /*
1113 1055 * Some drives do not support page4 or report 0 for page4->rpm,
1114 1056 * adjust it to AVG_RPM, 3600.
1115 1057 */
1116 1058 if (rpm < MIN_RPM || rpm > MAX_RPM) {
1117 1059 if (option_msg && diag_msg)
1118 1060 err_print("The current rpm value %d is invalid,"
1119 1061 " adjusting it to %d\n", rpm, AVG_RPM);
1120 1062 rpm = AVG_RPM;
1121 1063 }
1122 1064
1123 1065 /*
1124 1066 * Some drives report 0 for nsect (page 3, byte 10 and 11) if they
1125 1067 * have variable number of sectors per track. So adjust nsect.
1126 1068 * Also the value is defined as vendor specific, hence check if
1127 1069 * it is in a tolerable range. The values (32 and 4 below) are
1128 1070 * chosen so that this change below does not generate a different
1129 1071 * geometry for currently supported sun disks.
1130 1072 */
1131 1073 if ((nsect == 0) ||
1132 1074 ((diskaddr_t)pcyl * nhead * nsect) < (nblocks - nblocks/32) ||
1133 1075 ((diskaddr_t)pcyl * nhead * nsect) > (nblocks + nblocks/4)) {
1134 1076 if (nblocks > (pcyl * nhead)) {
1135 1077 err_print("Mode sense page(3) reports nsect value"
1136 1078 " as %d, adjusting it to %llu\n",
1137 1079 nsect, nblocks / (pcyl * nhead));
1138 1080 nsect = nblocks / (pcyl * nhead);
1139 1081 } else {
1140 1082 /* convert capacity to nsect * nhead * pcyl */
1141 1083 err_print("\nWARNING: Disk geometry is based on "
1142 1084 "capacity data.\n\n");
1143 1085 compute_chs_values(tblocks, nblocks, &pcyl, &nhead,
1144 1086 &nsect);
1145 1087 ncyl = pcyl - acyl;
1146 1088 if (option_msg && diag_msg) {
1147 1089 err_print("Geometry:(after adjustment)\n");
1148 1090 err_print(" pcyl: %u\n", pcyl);
1149 1091 err_print(" ncyl: %u\n", ncyl);
1150 1092 err_print(" heads: %u\n", nhead);
1151 1093 err_print(" nsects: %u\n", nsect);
1152 1094 err_print(" acyl: %u\n", acyl);
1153 1095
1154 1096 #if defined(_SUNOS_VTOC_16)
1155 1097 err_print(" bcyl: %u\n", bcyl);
1156 1098 #endif
1157 1099
1158 1100 err_print(" rpm: %d\n", rpm);
1159 1101 err_print(" nblocks: %llu\n", nblocks);
1160 1102 }
1161 1103 }
1162 1104 }
1163 1105
1164 1106 /*
1165 1107 * Some drives report their physical geometry such that
1166 1108 * it is greater than the actual capacity. Adjust the
1167 1109 * geometry to allow for this, so we don't run off
1168 1110 * the end of the disk.
1169 1111 */
1170 1112 if (((diskaddr_t)pcyl * nhead * nsect) > nblocks) {
1171 1113 uint_t p = pcyl;
1172 1114 if (option_msg && diag_msg) {
1173 1115 err_print("Computed capacity (%llu) exceeds actual "
1174 1116 "disk capacity (%llu)\n",
1175 1117 (diskaddr_t)pcyl * nhead * nsect, nblocks);
1176 1118 }
1177 1119 do {
1178 1120 pcyl--;
1179 1121 } while (((diskaddr_t)pcyl * nhead * nsect) > nblocks);
1180 1122
1181 1123 if (can_prompt && expert_mode && !option_f) {
1182 1124 /*
1183 1125 * Try to adjust nsect instead of pcyl to see if we
1184 1126 * can optimize. For compatability reasons do this
1185 1127 * only in expert mode (refer to bug 1144812).
1186 1128 */
1187 1129 uint_t n = nsect;
1188 1130 do {
1189 1131 n--;
1190 1132 } while (((diskaddr_t)p * nhead * n) > nblocks);
1191 1133 if (((diskaddr_t)p * nhead * n) >
1192 1134 ((diskaddr_t)pcyl * nhead * nsect)) {
1193 1135 u_ioparam_t ioparam;
1194 1136 int deflt = 1;
1195 1137 /*
1196 1138 * Ask the user for a choice here.
1197 1139 */
1198 1140 ioparam.io_bounds.lower = 1;
1199 1141 ioparam.io_bounds.upper = 2;
1200 1142 err_print("1. Capacity = %llu, with pcyl = %u "
1201 1143 "nhead = %u nsect = %u\n",
1202 1144 ((diskaddr_t)pcyl * nhead * nsect),
1203 1145 pcyl, nhead, nsect);
1204 1146 err_print("2. Capacity = %llu, with pcyl = %u "
1205 1147 "nhead = %u nsect = %u\n",
1206 1148 ((diskaddr_t)p * nhead * n),
1207 1149 p, nhead, n);
1208 1150 if (input(FIO_INT, "Select one of the above "
1209 1151 "choices ", ':', &ioparam,
1210 1152 &deflt, DATA_INPUT) == 2) {
1211 1153 pcyl = p;
1212 1154 nsect = n;
1213 1155 }
1214 1156 }
1215 1157 }
1216 1158 }
1217 1159
1218 1160 #if defined(_SUNOS_VTOC_8)
1219 1161 /*
1220 1162 * Finally, we need to make sure we don't overflow any of the
1221 1163 * fields in our disk label. To do this we need to `square
1222 1164 * the box' so to speak. We will lose bits here.
1223 1165 */
1224 1166
1225 1167 if ((pcyl > MAXIMUM_NO_CYLINDERS &&
1226 1168 ((nsect > MAXIMUM_NO_SECTORS) ||
1227 1169 (nhead > MAXIMUM_NO_HEADS))) ||
1228 1170 ((nsect > MAXIMUM_NO_SECTORS) &&
1229 1171 (nhead > MAXIMUM_NO_HEADS))) {
1230 1172 err_print("This disk is too big to label. "
1231 1173 " You will lose some blocks.\n");
1232 1174 }
1233 1175 if ((pcyl > MAXIMUM_NO_CYLINDERS) ||
1234 1176 (nsect > MAXIMUM_NO_SECTORS) ||
1235 1177 (nhead > MAXIMUM_NO_HEADS)) {
1236 1178 u_ioparam_t ioparam;
1237 1179 int order;
1238 1180 char msg[256];
1239 1181
1240 1182 order = ((pcyl > nhead)<<2) |
1241 1183 ((pcyl > nsect)<<1) |
1242 1184 (nhead > nsect);
1243 1185 switch (order) {
1244 1186 case 0x7: /* pcyl > nhead > nsect */
1245 1187 nblocks =
1246 1188 square_box(nblocks,
1247 1189 &pcyl, MAXIMUM_NO_CYLINDERS,
1248 1190 &nhead, MAXIMUM_NO_HEADS,
1249 1191 &nsect, MAXIMUM_NO_SECTORS);
1250 1192 break;
1251 1193 case 0x6: /* pcyl > nsect > nhead */
1252 1194 nblocks =
1253 1195 square_box(nblocks,
1254 1196 &pcyl, MAXIMUM_NO_CYLINDERS,
1255 1197 &nsect, MAXIMUM_NO_SECTORS,
1256 1198 &nhead, MAXIMUM_NO_HEADS);
1257 1199 break;
1258 1200 case 0x4: /* nsect > pcyl > nhead */
1259 1201 nblocks =
1260 1202 square_box(nblocks,
1261 1203 &nsect, MAXIMUM_NO_SECTORS,
1262 1204 &pcyl, MAXIMUM_NO_CYLINDERS,
1263 1205 &nhead, MAXIMUM_NO_HEADS);
1264 1206 break;
1265 1207 case 0x0: /* nsect > nhead > pcyl */
1266 1208 nblocks =
1267 1209 square_box(nblocks,
1268 1210 &nsect, MAXIMUM_NO_SECTORS,
1269 1211 &nhead, MAXIMUM_NO_HEADS,
1270 1212 &pcyl, MAXIMUM_NO_CYLINDERS);
1271 1213 break;
1272 1214 case 0x3: /* nhead > pcyl > nsect */
1273 1215 nblocks =
1274 1216 square_box(nblocks,
1275 1217 &nhead, MAXIMUM_NO_HEADS,
1276 1218 &pcyl, MAXIMUM_NO_CYLINDERS,
1277 1219 &nsect, MAXIMUM_NO_SECTORS);
1278 1220 break;
1279 1221 case 0x1: /* nhead > nsect > pcyl */
1280 1222 nblocks =
1281 1223 square_box(nblocks,
1282 1224 &nhead, MAXIMUM_NO_HEADS,
1283 1225 &nsect, MAXIMUM_NO_SECTORS,
1284 1226 &pcyl, MAXIMUM_NO_CYLINDERS);
1285 1227 break;
1286 1228 default:
1287 1229 /* How did we get here? */
1288 1230 impossible("label overflow adjustment");
1289 1231
1290 1232 /* Do something useful */
1291 1233 nblocks =
1292 1234 square_box(nblocks,
1293 1235 &nhead, MAXIMUM_NO_HEADS,
1294 1236 &nsect, MAXIMUM_NO_SECTORS,
1295 1237 &pcyl, MAXIMUM_NO_CYLINDERS);
1296 1238 break;
1297 1239 }
1298 1240 if (option_msg && diag_msg &&
1299 1241 (capacity->sc_capacity + 1 != nblocks)) {
1300 1242 err_print("After adjusting geometry you lost"
1301 1243 " %llu of %llu blocks.\n",
1302 1244 (capacity->sc_capacity + 1 - nblocks),
1303 1245 capacity->sc_capacity + 1);
1304 1246 }
1305 1247 while (can_prompt && expert_mode && !option_f) {
1306 1248 int deflt = 1;
1307 1249
1308 1250 /*
1309 1251 * Allow user to modify this by hand if desired.
1310 1252 */
1311 1253 (void) sprintf(msg,
1312 1254 "\nGeometry: %u heads, %u sectors %u cylinders"
1313 1255 " result in %llu out of %llu blocks.\n"
1314 1256 "Do you want to modify the device geometry",
1315 1257 nhead, nsect, pcyl,
1316 1258 nblocks, capacity->sc_capacity + 1);
1317 1259
1318 1260 ioparam.io_charlist = confirm_list;
1319 1261 if (input(FIO_MSTR, msg, '?', &ioparam,
1320 1262 &deflt, DATA_INPUT) != 0)
1321 1263 break;
1322 1264
1323 1265 ioparam.io_bounds.lower = MINIMUM_NO_HEADS;
1324 1266 ioparam.io_bounds.upper = MAXIMUM_NO_HEADS;
1325 1267 nhead = input(FIO_INT, "Number of heads", ':',
1326 1268 &ioparam, (int *)&nhead, DATA_INPUT);
1327 1269 ioparam.io_bounds.lower = MINIMUM_NO_SECTORS;
1328 1270 ioparam.io_bounds.upper = MAXIMUM_NO_SECTORS;
1329 1271 nsect = input(FIO_INT,
1330 1272 "Number of sectors per track",
1331 1273 ':', &ioparam, (int *)&nsect, DATA_INPUT);
1332 1274 ioparam.io_bounds.lower = SUN_MIN_CYL;
1333 1275 ioparam.io_bounds.upper = MAXIMUM_NO_CYLINDERS;
1334 1276 pcyl = input(FIO_INT, "Number of cylinders",
1335 1277 ':', &ioparam, (int *)&pcyl, DATA_INPUT);
1336 1278 nblocks = (diskaddr_t)nhead * nsect * pcyl;
1337 1279 if (nblocks > capacity->sc_capacity + 1) {
1338 1280 err_print("Warning: %llu blocks exceeds "
1339 1281 "disk capacity of %llu blocks\n",
1340 1282 nblocks,
1341 1283 capacity->sc_capacity + 1);
1342 1284 }
1343 1285 }
1344 1286 }
1345 1287 #endif /* defined(_SUNOS_VTOC_8) */
1346 1288
1347 1289 ncyl = pcyl - acyl;
1348 1290
1349 1291 if (option_msg && diag_msg) {
1350 1292 err_print("\nGeometry after adjusting for capacity:\n");
1351 1293 err_print(" pcyl: %u\n", pcyl);
1352 1294 err_print(" ncyl: %u\n", ncyl);
1353 1295 err_print(" heads: %u\n", nhead);
1354 1296 err_print(" nsects: %u\n", nsect);
1355 1297 err_print(" acyl: %u\n", acyl);
1356 1298 err_print(" rpm: %d\n", rpm);
1357 1299 }
1358 1300
1359 1301 (void) memset((char *)label, 0, sizeof (struct dk_label));
1360 1302
1361 1303 label->dkl_magic = DKL_MAGIC;
1362 1304
1363 1305 (void) snprintf(label->dkl_asciilabel, sizeof (label->dkl_asciilabel),
1364 1306 "%s cyl %u alt %u hd %u sec %u",
1365 1307 disk_name, ncyl, acyl, nhead, nsect);
1366 1308
1367 1309 label->dkl_pcyl = pcyl;
1368 1310 label->dkl_ncyl = ncyl;
1369 1311 label->dkl_acyl = acyl;
1370 1312 label->dkl_nhead = nhead;
1371 1313 label->dkl_nsect = nsect;
1372 1314 label->dkl_apc = 0;
1373 1315 label->dkl_intrlv = 1;
1374 1316 label->dkl_rpm = rpm;
1375 1317
1376 1318 #if defined(_FIRMWARE_NEEDS_FDISK)
1377 1319 if (auto_solaris_part(label) == -1)
1378 1320 goto err;
1379 1321 ncyl = label->dkl_ncyl;
1380 1322 #endif /* defined(_FIRMWARE_NEEDS_FDISK) */
1381 1323
1382 1324
1383 1325 if (!build_default_partition(label, DKC_SCSI_CCS)) {
1384 1326 goto err;
1385 1327 }
1386 1328
1387 1329 (void) checksum(label, CK_MAKESUM);
1388 1330
1389 1331 /*
1390 1332 * Find an existing disk type defined for this disk.
1391 1333 * For this to work, both the name and geometry must
1392 1334 * match. If there is no such type, but there already
1393 1335 * is a disk defined with that name, but with a different
1394 1336 * geometry, construct a new generic disk name out of
1395 1337 * the inquiry information. Whatever name we're
1396 1338 * finally using, if there's no such disk type defined,
1397 1339 * build a new disk definition.
1398 1340 */
1399 1341 if ((disk = find_scsi_disk_type(disk_name, label)) == NULL) {
1400 1342 if (find_scsi_disk_by_name(disk_name) != NULL) {
1401 1343 char old_name[DISK_NAME_MAX];
1402 1344 (void) strcpy(old_name, disk_name);
1403 1345 (void) get_generic_disk_name(disk_name,
1404 1346 inquiry);
1405 1347 if (option_msg && diag_msg) {
1406 1348 err_print(
1407 1349 "Changing disk type name from '%s' to '%s'\n", old_name, disk_name);
1408 1350 }
1409 1351 (void) snprintf(label->dkl_asciilabel,
1410 1352 sizeof (label->dkl_asciilabel),
1411 1353 "%s cyl %u alt %u hd %u sec %u",
1412 1354 disk_name, ncyl, acyl, nhead, nsect);
1413 1355 (void) checksum(label, CK_MAKESUM);
1414 1356 disk = find_scsi_disk_type(disk_name, label);
1415 1357 }
1416 1358 if (disk == NULL) {
1417 1359 disk = new_scsi_disk_type(fd, disk_name, label);
1418 1360 if (disk == NULL)
1419 1361 goto err;
1420 1362 }
1421 1363 }
1422 1364
1423 1365 return (disk);
1424 1366
1425 1367 err:
1426 1368 if (option_msg && diag_msg) {
1427 1369 err_print(
1428 1370 "Configuration via generic SCSI-2 information failed\n");
1429 1371 }
1430 1372 return (NULL);
1431 1373 }
1432 1374
1433 1375
1434 1376 /*ARGSUSED*/
1435 1377 static int
1436 1378 use_existing_disk_type(
1437 1379 int fd,
1438 1380 int can_prompt,
1439 1381 struct dk_label *label,
1440 1382 struct scsi_inquiry *inquiry,
1441 1383 struct disk_type *disk_type,
1442 1384 struct scsi_capacity_16 *capacity)
1443 1385 {
1444 1386 int pcyl;
1445 1387 int acyl;
1446 1388 int nhead;
1447 1389 int nsect;
1448 1390 int rpm;
1449 1391
1450 1392 /*
1451 1393 * Construct a new label out of the format.dat
1452 1394 */
1453 1395 pcyl = disk_type->dtype_pcyl;
1454 1396 acyl = disk_type->dtype_acyl;
1455 1397 ncyl = disk_type->dtype_ncyl;
1456 1398 nhead = disk_type->dtype_nhead;
1457 1399 nsect = disk_type->dtype_nsect;
1458 1400 rpm = disk_type->dtype_rpm;
1459 1401
1460 1402 if (option_msg && diag_msg) {
1461 1403 err_print("Format.dat geometry:\n");
1462 1404 err_print(" pcyl: %u\n", pcyl);
1463 1405 err_print(" heads: %u\n", nhead);
1464 1406 err_print(" nsects: %u\n", nsect);
1465 1407 err_print(" acyl: %u\n", acyl);
1466 1408 err_print(" rpm: %d\n", rpm);
1467 1409 }
1468 1410
1469 1411 (void) memset((char *)label, 0, sizeof (struct dk_label));
1470 1412
1471 1413 label->dkl_magic = DKL_MAGIC;
1472 1414
1473 1415 (void) snprintf(label->dkl_asciilabel, sizeof (label->dkl_asciilabel),
1474 1416 "%s cyl %u alt %u hd %u sec %u",
1475 1417 disk_type->dtype_asciilabel,
1476 1418 ncyl, acyl, nhead, nsect);
1477 1419
1478 1420 label->dkl_pcyl = pcyl;
1479 1421 label->dkl_ncyl = ncyl;
1480 1422 label->dkl_acyl = acyl;
1481 1423 label->dkl_nhead = nhead;
1482 1424 label->dkl_nsect = nsect;
1483 1425 label->dkl_apc = 0;
1484 1426 label->dkl_intrlv = 1;
1485 1427 label->dkl_rpm = rpm;
1486 1428
1487 1429 if (!build_default_partition(label, DKC_SCSI_CCS)) {
1488 1430 goto err;
1489 1431 }
1490 1432
1491 1433 (void) checksum(label, CK_MAKESUM);
1492 1434 return (1);
1493 1435
1494 1436 err:
1495 1437 if (option_msg && diag_msg) {
1496 1438 err_print(
1497 1439 "Configuration via format.dat geometry failed\n");
1498 1440 }
1499 1441 return (0);
1500 1442 }
1501 1443
1502 1444 int
1503 1445 build_default_partition(
1504 1446 struct dk_label *label,
1505 1447 int ctrl_type)
1506 1448 {
1507 1449 int i;
1508 1450 int ncyls[NDKMAP];
1509 1451 diskaddr_t nblks;
1510 1452 int cyl;
1511 1453 struct dk_vtoc *vtoc;
1512 1454 struct part_table *pt;
1513 1455 struct default_partitions *dpt;
1514 1456 diskaddr_t capacity;
1515 1457 int freecyls;
1516 1458 int blks_per_cyl;
1517 1459 int ncyl;
1518 1460
1519 1461 #ifdef lint
1520 1462 ctrl_type = ctrl_type;
1521 1463 #endif
1522 1464
1523 1465 /*
1524 1466 * Install a default vtoc
1525 1467 */
1526 1468 vtoc = &label->dkl_vtoc;
1527 1469 vtoc->v_version = V_VERSION;
1528 1470 vtoc->v_nparts = NDKMAP;
1529 1471 vtoc->v_sanity = VTOC_SANE;
1530 1472
1531 1473 for (i = 0; i < NDKMAP; i++) {
1532 1474 vtoc->v_part[i].p_tag = default_vtoc_map[i].p_tag;
1533 1475 vtoc->v_part[i].p_flag = default_vtoc_map[i].p_flag;
1534 1476 }
1535 1477
1536 1478 /*
1537 1479 * Find a partition that matches this disk. Capacity
1538 1480 * is in integral number of megabytes.
1539 1481 */
1540 1482 capacity = ((diskaddr_t)(label->dkl_ncyl) * label->dkl_nhead *
1541 1483 label->dkl_nsect) / (diskaddr_t)((1024 * 1024) / cur_blksz);
1542 1484 dpt = default_partitions;
1543 1485 for (i = 0; i < DEFAULT_PARTITION_TABLE_SIZE; i++, dpt++) {
1544 1486 if (capacity >= dpt->min_capacity &&
1545 1487 capacity < dpt->max_capacity) {
1546 1488 break;
1547 1489 }
1548 1490 }
1549 1491 if (i == DEFAULT_PARTITION_TABLE_SIZE) {
1550 1492 if (option_msg && diag_msg) {
1551 1493 err_print("No matching default partition (%llu)\n",
1552 1494 capacity);
1553 1495 }
1554 1496 return (0);
1555 1497 }
1556 1498 pt = dpt->part_table;
1557 1499
1558 1500 /*
1559 1501 * Go through default partition table, finding fixed
1560 1502 * sized entries.
1561 1503 */
1562 1504 freecyls = label->dkl_ncyl;
1563 1505 blks_per_cyl = label->dkl_nhead * label->dkl_nsect;
1564 1506 for (i = 0; i < NDKMAP; i++) {
1565 1507 if (pt->partitions[i] == HOG || pt->partitions[i] == 0) {
1566 1508 ncyls[i] = 0;
1567 1509 } else {
1568 1510 /*
1569 1511 * Calculate number of cylinders necessary
1570 1512 * for specified size, rounding up to
1571 1513 * the next greatest integral number of
1572 1514 * cylinders. Always give what they
1573 1515 * asked or more, never less.
1574 1516 */
1575 1517 nblks = pt->partitions[i] * ((1024*1024)/cur_blksz);
1576 1518 nblks += (blks_per_cyl - 1);
1577 1519 ncyls[i] = nblks / blks_per_cyl;
1578 1520 freecyls -= ncyls[i];
1579 1521 }
1580 1522 }
1581 1523
1582 1524 if (freecyls < 0) {
1583 1525 if (option_msg && diag_msg) {
1584 1526 for (i = 0; i < NDKMAP; i++) {
1585 1527 if (ncyls[i] == 0)
1586 1528 continue;
1587 1529 err_print("Partition %d: %u cyls\n",
1588 1530 i, ncyls[i]);
1589 1531 }
1590 1532 err_print("Free cylinders exhausted (%d)\n",
1591 1533 freecyls);
1592 1534 }
1593 1535 return (0);
1594 1536 }
1595 1537 #if defined(i386)
1596 1538 /*
1597 1539 * Set the default boot partition to 1 cylinder
1598 1540 */
1599 1541 ncyls[8] = 1;
1600 1542 freecyls -= 1;
1601 1543
1602 1544 /*
1603 1545 * If current disk type is not a SCSI disk,
1604 1546 * set the default alternates partition to 2 cylinders
1605 1547 */
1606 1548 if (ctrl_type != DKC_SCSI_CCS) {
1607 1549 ncyls[9] = 2;
1608 1550 freecyls -= 2;
1609 1551 }
1610 1552 #endif /* defined(i386) */
1611 1553
1612 1554 /*
1613 1555 * Set the free hog partition to whatever space remains.
1614 1556 * It's an error to have more than one HOG partition,
1615 1557 * but we don't verify that here.
1616 1558 */
1617 1559 for (i = 0; i < NDKMAP; i++) {
1618 1560 if (pt->partitions[i] == HOG) {
1619 1561 assert(ncyls[i] == 0);
1620 1562 ncyls[i] = freecyls;
1621 1563 break;
1622 1564 }
1623 1565 }
1624 1566
1625 1567 /*
1626 1568 * Error checking
1627 1569 */
1628 1570 ncyl = 0;
1629 1571 for (i = 0; i < NDKMAP; i++) {
1630 1572 ncyl += ncyls[i];
1631 1573 }
1632 1574 assert(ncyl == (label->dkl_ncyl));
1633 1575
1634 1576 /*
1635 1577 * Finally, install the partition in the label.
1636 1578 */
1637 1579 cyl = 0;
1638 1580
1639 1581 #if defined(_SUNOS_VTOC_16)
1640 1582 for (i = NDKMAP/2; i < NDKMAP; i++) {
1641 1583 if (i == 2 || ncyls[i] == 0)
1642 1584 continue;
1643 1585 label->dkl_vtoc.v_part[i].p_start = cyl * blks_per_cyl;
1644 1586 label->dkl_vtoc.v_part[i].p_size = ncyls[i] * blks_per_cyl;
1645 1587 cyl += ncyls[i];
1646 1588 }
1647 1589 for (i = 0; i < NDKMAP/2; i++) {
1648 1590
1649 1591 #elif defined(_SUNOS_VTOC_8)
1650 1592 for (i = 0; i < NDKMAP; i++) {
1651 1593
1652 1594 #else
1653 1595 #error No VTOC format defined.
1654 1596 #endif /* defined(_SUNOS_VTOC_16) */
1655 1597
1656 1598 if (i == 2 || ncyls[i] == 0) {
1657 1599 #if defined(_SUNOS_VTOC_8)
1658 1600 if (i != 2) {
1659 1601 label->dkl_map[i].dkl_cylno = 0;
1660 1602 label->dkl_map[i].dkl_nblk = 0;
1661 1603 }
1662 1604 #endif
1663 1605 continue;
1664 1606 }
1665 1607 #if defined(_SUNOS_VTOC_8)
1666 1608 label->dkl_map[i].dkl_cylno = cyl;
1667 1609 label->dkl_map[i].dkl_nblk = ncyls[i] * blks_per_cyl;
1668 1610 #elif defined(_SUNOS_VTOC_16)
1669 1611 label->dkl_vtoc.v_part[i].p_start = cyl * blks_per_cyl;
1670 1612 label->dkl_vtoc.v_part[i].p_size = ncyls[i] * blks_per_cyl;
1671 1613
1672 1614 #else
1673 1615 #error No VTOC format defined.
1674 1616 #endif /* defined(_SUNOS_VTOC_8) */
1675 1617
1676 1618 cyl += ncyls[i];
1677 1619 }
1678 1620
1679 1621 /*
1680 1622 * Set the whole disk partition
1681 1623 */
1682 1624 #if defined(_SUNOS_VTOC_8)
1683 1625 label->dkl_map[2].dkl_cylno = 0;
1684 1626 label->dkl_map[2].dkl_nblk =
1685 1627 label->dkl_ncyl * label->dkl_nhead * label->dkl_nsect;
1686 1628
1687 1629 #elif defined(_SUNOS_VTOC_16)
1688 1630 label->dkl_vtoc.v_part[2].p_start = 0;
1689 1631 label->dkl_vtoc.v_part[2].p_size =
1690 1632 (label->dkl_ncyl + label->dkl_acyl) * label->dkl_nhead *
1691 1633 label->dkl_nsect;
1692 1634 #else
1693 1635 #error No VTOC format defined.
1694 1636 #endif /* defined(_SUNOS_VTOC_8) */
1695 1637
1696 1638
1697 1639 if (option_msg && diag_msg) {
1698 1640 float scaled;
1699 1641 err_print("\n");
1700 1642 for (i = 0; i < NDKMAP; i++) {
1701 1643 #if defined(_SUNOS_VTOC_8)
1702 1644 if (label->dkl_map[i].dkl_nblk == 0)
1703 1645
1704 1646 #elif defined(_SUNOS_VTOC_16)
1705 1647 if (label->dkl_vtoc.v_part[i].p_size == 0)
1706 1648
1707 1649 #else
1708 1650 #error No VTOC format defined.
1709 1651 #endif /* defined(_SUNOS_VTOC_8) */
1710 1652
1711 1653 continue;
1712 1654 err_print("Partition %d: ", i);
1713 1655 #if defined(_SUNOS_VTOC_8)
1714 1656 scaled = bn2mb(label->dkl_map[i].dkl_nblk);
1715 1657
1716 1658 #elif defined(_SUNOS_VTOC_16)
1717 1659
1718 1660 scaled = bn2mb(label->dkl_vtoc.v_part[i].p_size);
1719 1661 #else
1720 1662 #error No VTOC format defined.
1721 1663 #endif /* defined(_SUNOS_VTOC_8) */
1722 1664
1723 1665 if (scaled > 1024.0) {
1724 1666 err_print("%6.2fGB ", scaled/1024.0);
1725 1667 } else {
1726 1668 err_print("%6.2fMB ", scaled);
1727 1669 }
1728 1670 #if defined(_SUNOS_VTOC_8)
1729 1671 err_print(" %6d cylinders\n",
1730 1672 label->dkl_map[i].dkl_nblk/blks_per_cyl);
1731 1673 #elif defined(_SUNOS_VTOC_16)
1732 1674 err_print(" %6d cylinders\n",
1733 1675 label->dkl_vtoc.v_part[i].p_size/blks_per_cyl);
1734 1676 #else
1735 1677 #error No VTOC format defined.
1736 1678 #endif /* defined(_SUNOS_VTOC_8) */
1737 1679
1738 1680 }
1739 1681 err_print("\n");
1740 1682 }
1741 1683
1742 1684 return (1);
1743 1685 }
1744 1686
1745 1687
1746 1688
1747 1689 /*
1748 1690 * Find an existing scsi disk definition by this name,
1749 1691 * if possible.
1750 1692 */
1751 1693 static struct disk_type *
1752 1694 find_scsi_disk_type(
1753 1695 char *disk_name,
1754 1696 struct dk_label *label)
1755 1697 {
1756 1698 struct ctlr_type *ctlr;
1757 1699 struct disk_type *dp;
1758 1700
1759 1701 ctlr = find_scsi_ctlr_type();
1760 1702 for (dp = ctlr->ctype_dlist; dp != NULL; dp = dp->dtype_next) {
1761 1703 if (dp->dtype_asciilabel) {
1762 1704 if ((strcmp(dp->dtype_asciilabel, disk_name) == 0) &&
1763 1705 dp->dtype_pcyl == label->dkl_pcyl &&
1764 1706 dp->dtype_ncyl == label->dkl_ncyl &&
1765 1707 dp->dtype_acyl == label->dkl_acyl &&
1766 1708 dp->dtype_nhead == label->dkl_nhead &&
1767 1709 dp->dtype_nsect == label->dkl_nsect) {
1768 1710 return (dp);
1769 1711 }
1770 1712 }
1771 1713 }
1772 1714
1773 1715 return ((struct disk_type *)NULL);
1774 1716 }
1775 1717
1776 1718
1777 1719 /*
1778 1720 * Find an existing scsi disk definition by this name,
1779 1721 * if possible.
1780 1722 */
1781 1723 static struct disk_type *
1782 1724 find_scsi_disk_by_name(
1783 1725 char *disk_name)
1784 1726 {
1785 1727 struct ctlr_type *ctlr;
1786 1728 struct disk_type *dp;
1787 1729
1788 1730 ctlr = find_scsi_ctlr_type();
1789 1731 for (dp = ctlr->ctype_dlist; dp != NULL; dp = dp->dtype_next) {
1790 1732 if (dp->dtype_asciilabel) {
1791 1733 if ((strcmp(dp->dtype_asciilabel, disk_name) == 0)) {
1792 1734 return (dp);
1793 1735 }
1794 1736 }
1795 1737 }
1796 1738
1797 1739 return ((struct disk_type *)NULL);
1798 1740 }
1799 1741
1800 1742
1801 1743 /*
1802 1744 * Return a pointer to the ctlr_type structure for SCSI
1803 1745 * disks. This list is built into the program, so there's
1804 1746 * no chance of not being able to find it, unless someone
1805 1747 * totally mangles the code.
1806 1748 */
1807 1749 static struct ctlr_type *
1808 1750 find_scsi_ctlr_type()
1809 1751 {
1810 1752 struct mctlr_list *mlp;
1811 1753
1812 1754 mlp = controlp;
1813 1755
1814 1756 while (mlp != NULL) {
1815 1757 if (mlp->ctlr_type->ctype_ctype == DKC_SCSI_CCS) {
1816 1758 return (mlp->ctlr_type);
1817 1759 }
1818 1760 mlp = mlp->next;
1819 1761 }
1820 1762
1821 1763 impossible("no SCSI controller type");
1822 1764
1823 1765 return ((struct ctlr_type *)NULL);
1824 1766 }
1825 1767
1826 1768
1827 1769
1828 1770 /*
1829 1771 * Return a pointer to the scsi ctlr_info structure. This
1830 1772 * structure is allocated the first time format sees a
1831 1773 * disk on this controller, so it must be present.
1832 1774 */
1833 1775 static struct ctlr_info *
1834 1776 find_scsi_ctlr_info(
1835 1777 struct dk_cinfo *dkinfo)
1836 1778 {
1837 1779 struct ctlr_info *ctlr;
1838 1780
1839 1781 if (dkinfo->dki_ctype != DKC_SCSI_CCS) {
1840 1782 return (NULL);
1841 1783 }
1842 1784
1843 1785 for (ctlr = ctlr_list; ctlr != NULL; ctlr = ctlr->ctlr_next) {
1844 1786 if (ctlr->ctlr_addr == dkinfo->dki_addr &&
1845 1787 ctlr->ctlr_space == dkinfo->dki_space &&
1846 1788 ctlr->ctlr_ctype->ctype_ctype == DKC_SCSI_CCS) {
1847 1789 return (ctlr);
1848 1790 }
1849 1791 }
1850 1792
1851 1793 impossible("no SCSI controller info");
1852 1794
1853 1795 return ((struct ctlr_info *)NULL);
1854 1796 }
1855 1797
1856 1798
1857 1799
1858 1800 static struct disk_type *
1859 1801 new_scsi_disk_type(
1860 1802 int fd,
1861 1803 char *disk_name,
1862 1804 struct dk_label *label)
1863 1805 {
1864 1806 struct disk_type *dp;
1865 1807 struct disk_type *disk;
1866 1808 struct ctlr_info *ctlr;
1867 1809 struct dk_cinfo dkinfo;
1868 1810 struct partition_info *part;
1869 1811 struct partition_info *pt;
1870 1812 struct disk_info *disk_info;
1871 1813 int i;
1872 1814
1873 1815 /*
1874 1816 * Get the disk controller info for this disk
1875 1817 */
1876 1818 if (ioctl(fd, DKIOCINFO, &dkinfo) == -1) {
1877 1819 if (option_msg && diag_msg) {
1878 1820 err_print("DKIOCINFO failed\n");
1879 1821 }
1880 1822 return (NULL);
1881 1823 }
1882 1824
1883 1825 /*
1884 1826 * Find the ctlr_info for this disk.
1885 1827 */
1886 1828 ctlr = find_scsi_ctlr_info(&dkinfo);
1887 1829
1888 1830 /*
1889 1831 * Allocate a new disk type for the SCSI controller.
1890 1832 */
1891 1833 disk = (struct disk_type *)zalloc(sizeof (struct disk_type));
1892 1834
1893 1835 /*
1894 1836 * Find the disk_info instance for this disk.
1895 1837 */
1896 1838 disk_info = find_scsi_disk_info(&dkinfo);
1897 1839
1898 1840 /*
1899 1841 * The controller and the disk should match.
1900 1842 */
1901 1843 assert(disk_info->disk_ctlr == ctlr);
1902 1844
1903 1845 /*
1904 1846 * Link the disk into the list of disks
1905 1847 */
1906 1848 dp = ctlr->ctlr_ctype->ctype_dlist;
1907 1849 if (dp == NULL) {
1908 1850 ctlr->ctlr_ctype->ctype_dlist = disk;
1909 1851 } else {
1910 1852 while (dp->dtype_next != NULL) {
1911 1853 dp = dp->dtype_next;
1912 1854 }
1913 1855 dp->dtype_next = disk;
1914 1856 }
1915 1857 disk->dtype_next = NULL;
1916 1858
1917 1859 /*
1918 1860 * Allocate and initialize the disk name.
1919 1861 */
1920 1862 disk->dtype_asciilabel = alloc_string(disk_name);
1921 1863
1922 1864 /*
1923 1865 * Initialize disk geometry info
1924 1866 */
1925 1867 disk->dtype_pcyl = label->dkl_pcyl;
1926 1868 disk->dtype_ncyl = label->dkl_ncyl;
1927 1869 disk->dtype_acyl = label->dkl_acyl;
1928 1870 disk->dtype_nhead = label->dkl_nhead;
1929 1871 disk->dtype_nsect = label->dkl_nsect;
1930 1872 disk->dtype_rpm = label->dkl_rpm;
1931 1873
1932 1874 /*
1933 1875 * Attempt to match the partition map in the label
1934 1876 * with a know partition for this disk type.
1935 1877 */
1936 1878 for (part = disk->dtype_plist; part; part = part->pinfo_next) {
1937 1879 if (parts_match(label, part)) {
1938 1880 break;
1939 1881 }
1940 1882 }
1941 1883
1942 1884 /*
1943 1885 * If no match was made, we need to create a partition
1944 1886 * map for this disk.
1945 1887 */
1946 1888 if (part == NULL) {
1947 1889 part = (struct partition_info *)
1948 1890 zalloc(sizeof (struct partition_info));
1949 1891 pt = disk->dtype_plist;
1950 1892 if (pt == NULL) {
1951 1893 disk->dtype_plist = part;
1952 1894 } else {
1953 1895 while (pt->pinfo_next != NULL) {
1954 1896 pt = pt->pinfo_next;
1955 1897 }
1956 1898 pt->pinfo_next = part;
1957 1899 }
1958 1900 part->pinfo_next = NULL;
1959 1901
1960 1902 /*
1961 1903 * Set up the partition name
1962 1904 */
1963 1905 part->pinfo_name = alloc_string("default");
1964 1906
1965 1907 /*
1966 1908 * Fill in the partition info from the label
1967 1909 */
1968 1910 for (i = 0; i < NDKMAP; i++) {
1969 1911
1970 1912 #if defined(_SUNOS_VTOC_8)
1971 1913 part->pinfo_map[i] = label->dkl_map[i];
1972 1914
1973 1915 #elif defined(_SUNOS_VTOC_16)
1974 1916 part->pinfo_map[i].dkl_cylno =
1975 1917 label->dkl_vtoc.v_part[i].p_start /
1976 1918 ((blkaddr32_t)(disk->dtype_nhead *
1977 1919 disk->dtype_nsect - apc));
1978 1920 part->pinfo_map[i].dkl_nblk =
1979 1921 label->dkl_vtoc.v_part[i].p_size;
1980 1922 #else
1981 1923 #error No VTOC format defined.
1982 1924 #endif /* defined(_SUNOS_VTOC_8) */
1983 1925
1984 1926 }
1985 1927 }
1986 1928
1987 1929
1988 1930 /*
1989 1931 * Use the VTOC if valid, or install a default
1990 1932 */
1991 1933 if (label->dkl_vtoc.v_version == V_VERSION) {
1992 1934 (void) memcpy(disk_info->v_volume, label->dkl_vtoc.v_volume,
1993 1935 LEN_DKL_VVOL);
1994 1936 part->vtoc = label->dkl_vtoc;
1995 1937 } else {
1996 1938 (void) memset(disk_info->v_volume, 0, LEN_DKL_VVOL);
1997 1939 set_vtoc_defaults(part);
1998 1940 }
1999 1941
2000 1942 /*
2001 1943 * Link the disk to the partition map
2002 1944 */
↓ open down ↓ |
1288 lines elided |
↑ open up ↑ |
2003 1945 disk_info->disk_parts = part;
2004 1946
2005 1947 return (disk);
2006 1948 }
2007 1949
2008 1950
2009 1951 /*
2010 1952 * Delete a disk type from disk type list.
2011 1953 */
2012 1954 int
2013 -delete_disk_type(
2014 - struct disk_type *disk_type)
1955 +delete_disk_type(struct disk_type *disk_type)
2015 1956 {
2016 1957 struct ctlr_type *ctlr;
2017 1958 struct disk_type *dp, *disk;
2018 1959
2019 - if (cur_ctype->ctype_ctype == DKC_DIRECT)
2020 - ctlr = find_direct_ctlr_type();
2021 - else if (cur_ctype->ctype_ctype == DKC_VBD)
2022 - ctlr = find_vbd_ctlr_type();
1960 + if (cur_ctype->ctype_ctype == DKC_DIRECT ||
1961 + cur_ctype->ctype_ctype == DKC_VBD ||
1962 + cur_ctype->ctype_ctype == DKC_BLKDEV)
1963 + ctlr = find_ctlr_type(cur_ctype->ctype_ctype);
2023 1964 else
2024 1965 ctlr = find_scsi_ctlr_type();
2025 1966 if (ctlr == NULL || ctlr->ctype_dlist == NULL) {
2026 1967 return (-1);
2027 1968 }
2028 1969
2029 1970 disk = ctlr->ctype_dlist;
2030 1971 if (disk == disk_type) {
2031 1972 ctlr->ctype_dlist = disk->dtype_next;
2032 1973 if (cur_label == L_TYPE_EFI)
2033 1974 free(disk->dtype_plist->etoc);
2034 1975 free(disk->dtype_plist);
2035 1976 free(disk->vendor);
2036 1977 free(disk->product);
2037 1978 free(disk->revision);
2038 1979 free(disk);
2039 1980 return (0);
2040 1981 } else {
2041 1982 for (dp = disk->dtype_next; dp != NULL;
2042 1983 disk = disk->dtype_next, dp = dp->dtype_next) {
2043 1984 if (dp == disk_type) {
2044 1985 disk->dtype_next = dp->dtype_next;
2045 1986 if (cur_label == L_TYPE_EFI)
2046 1987 free(dp->dtype_plist->etoc);
2047 1988 free(dp->dtype_plist);
2048 1989 free(dp->vendor);
2049 1990 free(dp->product);
2050 1991 free(dp->revision);
2051 1992 free(dp);
2052 1993 return (0);
2053 1994 }
2054 1995 }
2055 1996 return (-1);
2056 1997 }
2057 1998 }
2058 1999
2059 2000
2060 2001 static struct disk_info *
2061 2002 find_scsi_disk_info(
2062 2003 struct dk_cinfo *dkinfo)
2063 2004 {
2064 2005 struct disk_info *disk;
2065 2006 struct dk_cinfo *dp;
2066 2007
2067 2008 for (disk = disk_list; disk != NULL; disk = disk->disk_next) {
2068 2009 assert(dkinfo->dki_ctype == DKC_SCSI_CCS);
2069 2010 dp = &disk->disk_dkinfo;
2070 2011 if (dp->dki_ctype == dkinfo->dki_ctype &&
2071 2012 dp->dki_cnum == dkinfo->dki_cnum &&
2072 2013 dp->dki_unit == dkinfo->dki_unit &&
2073 2014 strcmp(dp->dki_dname, dkinfo->dki_dname) == 0) {
2074 2015 return (disk);
2075 2016 }
2076 2017 }
2077 2018
2078 2019 impossible("No SCSI disk info instance\n");
2079 2020
2080 2021 return ((struct disk_info *)NULL);
2081 2022 }
2082 2023
2083 2024
2084 2025 static char *
2085 2026 get_sun_disk_name(
2086 2027 char *disk_name,
2087 2028 struct scsi_inquiry *inquiry)
2088 2029 {
2089 2030 /*
2090 2031 * Extract the sun name of the disk
2091 2032 */
2092 2033 (void) memset(disk_name, 0, DISK_NAME_MAX);
2093 2034 (void) memcpy(disk_name, (char *)&inquiry->inq_pid[9], 7);
2094 2035
2095 2036 return (disk_name);
2096 2037 }
2097 2038
2098 2039
2099 2040 char *
2100 2041 get_generic_disk_name(
2101 2042 char *disk_name,
2102 2043 struct scsi_inquiry *inquiry)
2103 2044 {
2104 2045 char *p;
2105 2046
2106 2047 (void) memset(disk_name, 0, DISK_NAME_MAX);
2107 2048 p = strcopy(disk_name, inquiry->inq_vid,
2108 2049 sizeof (inquiry->inq_vid));
2109 2050 *p++ = '-';
2110 2051 p = strcopy(p, inquiry->inq_pid, sizeof (inquiry->inq_pid));
2111 2052 *p++ = '-';
2112 2053 p = strcopy(p, inquiry->inq_revision,
2113 2054 sizeof (inquiry->inq_revision));
2114 2055
2115 2056 return (disk_name);
2116 2057 }
2117 2058
2118 2059 /*
2119 2060 * Copy a string of characters from src to dst, for at
2120 2061 * most n bytes. Strip all leading and trailing spaces,
2121 2062 * and stop if there are any non-printable characters.
2122 2063 * Return ptr to the next character to be filled.
2123 2064 */
2124 2065 static char *
2125 2066 strcopy(
2126 2067 char *dst,
2127 2068 char *src,
2128 2069 int n)
2129 2070 {
2130 2071 int i;
2131 2072
2132 2073 while (*src == ' ' && n > 0) {
2133 2074 src++;
2134 2075 n--;
2135 2076 }
2136 2077
2137 2078 for (i = 0; n-- > 0 && isascii(*src) && isprint(*src); src++) {
2138 2079 if (*src == ' ') {
2139 2080 i++;
2140 2081 } else {
2141 2082 while (i-- > 0)
2142 2083 *dst++ = ' ';
2143 2084 *dst++ = *src;
2144 2085 }
2145 2086 }
2146 2087
2147 2088 *dst = 0;
2148 2089 return (dst);
2149 2090 }
↓ open down ↓ |
117 lines elided |
↑ open up ↑ |
2150 2091
2151 2092 /*
2152 2093 * adjust disk geometry.
2153 2094 * This is used when disk reports a disk geometry page having
2154 2095 * no of physical cylinders is < 3 which is the minimum required
2155 2096 * by Solaris (2 for storing labels and at least one as a data
2156 2097 * cylinder )
2157 2098 */
2158 2099 int
2159 2100 adjust_disk_geometry(diskaddr_t capacity, uint_t *cyl, uint_t *nhead,
2160 - uint_t *nsect)
2101 + uint_t *nsect)
2161 2102 {
2162 2103 uint_t lcyl = *cyl;
2163 2104 uint_t lnhead = *nhead;
2164 2105 uint_t lnsect = *nsect;
2165 2106
2166 2107 assert(lcyl < SUN_MIN_CYL);
2167 2108
2168 2109 /*
2169 2110 * reduce nsect by 2 for each iteration and re-calculate
2170 2111 * the number of cylinders.
2171 2112 */
2172 2113 while (lnsect > MINIMUM_NO_SECTORS &&
2173 2114 lcyl < MINIMUM_NO_CYLINDERS) {
2174 2115 /*
2175 2116 * make sure that we do not go below MINIMUM_NO_SECTORS.
2176 2117 */
2177 2118 lnsect = max(MINIMUM_NO_SECTORS, lnsect / 2);
2178 2119 lcyl = (capacity) / (lnhead * lnsect);
2179 2120 }
2180 2121 /*
2181 2122 * If the geometry still does not satisfy
2182 2123 * MINIMUM_NO_CYLINDERS then try to reduce the
2183 2124 * no of heads.
2184 2125 */
2185 2126 while (lnhead > MINIMUM_NO_HEADS &&
2186 2127 lcyl < MINIMUM_NO_CYLINDERS) {
2187 2128 lnhead = max(MINIMUM_NO_HEADS, lnhead / 2);
2188 2129 lcyl = (capacity) / (lnhead * lnsect);
2189 2130 }
2190 2131 /*
2191 2132 * now we should have atleast SUN_MIN_CYL cylinders.
2192 2133 * If we still do not get SUN_MIN_CYL with MINIMUM_NO_HEADS
2193 2134 * and MINIMUM_NO_HEADS then return error.
2194 2135 */
2195 2136 if (lcyl < SUN_MIN_CYL)
2196 2137 return (1);
2197 2138 else {
2198 2139 *cyl = lcyl;
2199 2140 *nhead = lnhead;
2200 2141 *nsect = lnsect;
2201 2142 return (0);
2202 2143 }
2203 2144 }
2204 2145
2205 2146 #if defined(_SUNOS_VTOC_8)
2206 2147 /*
2207 2148 * Reduce the size of one dimention below a specified
2208 2149 * limit with a minimum loss of volume. Dimenstions are
2209 2150 * assumed to be passed in form the largest value (the one
2210 2151 * that needs to be reduced) to the smallest value. The
2211 2152 * values will be twiddled until they are all less than or
2212 2153 * equal to their limit. Returns the number in the new geometry.
2213 2154 */
2214 2155 static diskaddr_t
2215 2156 square_box(
2216 2157 diskaddr_t capacity,
2217 2158 uint_t *dim1, uint_t lim1,
2218 2159 uint_t *dim2, uint_t lim2,
2219 2160 uint_t *dim3, uint_t lim3)
2220 2161 {
2221 2162 uint_t i;
2222 2163
2223 2164 /*
2224 2165 * Although the routine should work with any ordering of
2225 2166 * parameters, it's most efficient if they are passed in
2226 2167 * in decreasing magnitude.
2227 2168 */
2228 2169 assert(*dim1 >= *dim2);
2229 2170 assert(*dim2 >= *dim3);
2230 2171
2231 2172 /*
2232 2173 * This is done in a very arbitrary manner. We could try to
2233 2174 * find better values but I can't come up with a method that
2234 2175 * would run in a reasonable amount of time. That could take
2235 2176 * approximately 65535 * 65535 iterations of a dozen flops each
2236 2177 * or well over 4G flops.
2237 2178 *
2238 2179 * First:
2239 2180 *
2240 2181 * Let's see how far we can go with bitshifts w/o losing
2241 2182 * any blocks.
2242 2183 */
2243 2184
2244 2185 for (i = 0; (((*dim1)>>i)&1) == 0 && ((*dim1)>>i) > lim1; i++)
2245 2186 ;
2246 2187 if (i) {
2247 2188 *dim1 = ((*dim1)>>i);
2248 2189 *dim3 = ((*dim3)<<i);
2249 2190 }
2250 2191
2251 2192 if (((*dim1) > lim1) || ((*dim2) > lim2) || ((*dim3) > lim3)) {
2252 2193 double d[4];
2253 2194
2254 2195 /*
2255 2196 * Second:
2256 2197 *
2257 2198 * Set the highest value at its limit then calculate errors,
2258 2199 * adjusting the 2nd highest value (we get better resolution
2259 2200 * that way).
2260 2201 */
2261 2202 d[1] = lim1;
2262 2203 d[3] = *dim3;
2263 2204 d[2] = (double)capacity/(d[1]*d[3]);
2264 2205
2265 2206 /*
2266 2207 * If we overflowed the middle term, set it to its limit and
2267 2208 * chose a new low term.
2268 2209 */
2269 2210 if (d[2] > lim2) {
2270 2211 d[2] = lim2;
2271 2212 d[3] = (double)capacity/(d[1]*d[2]);
2272 2213 }
2273 2214 /*
2274 2215 * Convert to integers.
2275 2216 */
2276 2217 *dim1 = (int)d[1];
2277 2218 *dim2 = (int)d[2];
2278 2219 *dim3 = (int)d[3];
2279 2220 }
2280 2221 /*
2281 2222 * Fixup any other possible problems.
2282 2223 * If this happens, we need a new disklabel format.
2283 2224 */
2284 2225 if (*dim1 > lim1) *dim1 = lim1;
2285 2226 if (*dim2 > lim2) *dim2 = lim2;
2286 2227 if (*dim3 > lim3) *dim3 = lim3;
2287 2228 return (*dim1 * *dim2 * *dim3);
2288 2229 }
↓ open down ↓ |
118 lines elided |
↑ open up ↑ |
2289 2230 #endif /* defined(_SUNOS_VTOC_8) */
2290 2231
2291 2232 /*
2292 2233 * Calculate CHS values based on the capacity data.
2293 2234 *
2294 2235 * NOTE: This function is same as cmlb_convert_geomerty() function in
2295 2236 * cmlb kernel module.
2296 2237 */
2297 2238 static void
2298 2239 compute_chs_values(diskaddr_t total_capacity, diskaddr_t usable_capacity,
2299 - uint_t *pcylp, uint_t *nheadp, uint_t *nsectp)
2240 + uint_t *pcylp, uint_t *nheadp, uint_t *nsectp)
2300 2241 {
2301 2242
2302 2243 /* Unlabeled SCSI floppy device */
2303 2244 if (total_capacity < 160) {
2304 2245 /* Less than 80K */
2305 2246 *nheadp = 1;
2306 2247 *pcylp = total_capacity;
2307 2248 *nsectp = 1;
2308 2249 return;
2309 2250 } else if (total_capacity <= 0x1000) {
2310 2251 *nheadp = 2;
2311 2252 *pcylp = 80;
2312 2253 *nsectp = total_capacity / (80 * 2);
2313 2254 return;
2314 2255 }
2315 2256
2316 2257 /*
2317 2258 * For all devices we calculate cylinders using the heads and sectors
2318 2259 * we assign based on capacity of the device. The algorithm is
2319 2260 * designed to be compatible with the way other operating systems
2320 2261 * lay out fdisk tables for X86 and to insure that the cylinders never
2321 2262 * exceed 65535 to prevent problems with X86 ioctls that report
2322 2263 * geometry.
2323 2264 * For some smaller disk sizes we report geometry that matches those
2324 2265 * used by X86 BIOS usage. For larger disks, we use SPT that are
2325 2266 * multiples of 63, since other OSes that are not limited to 16-bits
2326 2267 * for cylinders stop at 63 SPT we make do by using multiples of 63 SPT.
2327 2268 *
2328 2269 * The following table (in order) illustrates some end result
2329 2270 * calculations:
2330 2271 *
2331 2272 * Maximum number of blocks nhead nsect
2332 2273 *
2333 2274 * 2097152 (1GB) 64 32
2334 2275 * 16777216 (8GB) 128 32
2335 2276 * 1052819775 (502.02GB) 255 63
2336 2277 * 2105639550 (0.98TB) 255 126
2337 2278 * 3158459325 (1.47TB) 255 189
2338 2279 * 4211279100 (1.96TB) 255 252
2339 2280 * 5264098875 (2.45TB) 255 315
2340 2281 * ...
2341 2282 */
2342 2283
2343 2284 if (total_capacity <= 0x200000) {
2344 2285 *nheadp = 64;
2345 2286 *nsectp = 32;
2346 2287 } else if (total_capacity <= 0x01000000) {
2347 2288 *nheadp = 128;
2348 2289 *nsectp = 32;
2349 2290 } else {
2350 2291 *nheadp = 255;
2351 2292
2352 2293 /* make nsect be smallest multiple of 63 */
2353 2294 *nsectp = ((total_capacity +
2354 2295 (UINT16_MAX * 255 * 63) - 1) /
2355 2296 (UINT16_MAX * 255 * 63)) * 63;
2356 2297
2357 2298 if (*nsectp == 0)
2358 2299 *nsectp = (UINT16_MAX / 63) * 63;
2359 2300 }
2360 2301
2361 2302 if (usable_capacity < total_capacity)
2362 2303 *pcylp = usable_capacity / ((*nheadp) * (*nsectp));
2363 2304 else
2364 2305 *pcylp = total_capacity / ((*nheadp) * (*nsectp));
2365 2306 }
↓ open down ↓ |
56 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX