10 #include <sys/ioctl.h>
11 #include <linux/iso_fs.h>
19 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
22 * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
25 static void get_block_devs(hd_data_t
*hd_data
);
26 static void add_partitions(hd_data_t
*hd_data
, hd_t
*hd
, char *path
);
27 static void add_cdrom_info(hd_data_t
*hd_data
, hd_t
*hd
);
28 static void add_other_sysfs_info(hd_data_t
*hd_data
, hd_t
*hd
, struct sysfs_device
*sf_dev
);
29 static void add_ide_sysfs_info(hd_data_t
*hd_data
, hd_t
*hd
, struct sysfs_device
*sf_dev
);
30 static void add_scsi_sysfs_info(hd_data_t
*hd_data
, hd_t
*hd
, struct sysfs_device
*sf_dev
);
31 static void read_partitions(hd_data_t
*hd_data
);
32 static void read_cdroms(hd_data_t
*hd_data
);
33 static cdrom_info_t
*new_cdrom_entry(cdrom_info_t
**ci
);
34 static cdrom_info_t
*get_cdrom_entry(cdrom_info_t
*ci
, int n
);
35 static void get_scsi_tape(hd_data_t
*hd_data
);
36 static void get_generic_scsi_devs(hd_data_t
*hd_data
);
37 static void add_disk_size(hd_data_t
*hd_data
, hd_t
*hd
);
40 void hd_scan_sysfs_block(hd_data_t
*hd_data
)
42 if(!hd_probe_feature(hd_data
, pr_block
)) return;
44 hd_data
->module
= mod_block
;
47 remove_hd_entries(hd_data
);
49 hd_data
->disks
= free_str_list(hd_data
->disks
);
50 hd_data
->partitions
= free_str_list(hd_data
->partitions
);
51 hd_data
->cdroms
= free_str_list(hd_data
->cdroms
);
53 if(hd_probe_feature(hd_data
, pr_block_mods
)) {
54 PROGRESS(1, 0, "block modules");
55 load_module(hd_data
, "ide_cd");
56 load_module(hd_data
, "sr_mod");
57 load_module(hd_data
, "sd_mod");
58 load_module(hd_data
, "st");
61 PROGRESS(2, 0, "sysfs drivers");
63 hd_sysfs_driver_list(hd_data
);
65 PROGRESS(3, 0, "cdrom");
69 PROGRESS(4, 0, "partition");
71 read_partitions(hd_data
);
73 PROGRESS(5, 0, "get sysfs block dev data");
75 get_block_devs(hd_data
);
78 ADD2LOG("oops: cdrom list not empty\n");
83 void get_block_devs(hd_data_t
*hd_data
)
92 struct sysfs_bus
*sf_bus
;
93 struct sysfs_class
*sf_class
;
94 struct sysfs_class_device
*sf_cdev
;
95 struct sysfs_device
*sf_dev
;
96 struct dlist
*sf_cdev_list
;
97 struct dlist
*sf_ide_list
= NULL
;
98 struct sysfs_device
*sf_ide
;
100 sf_bus
= sysfs_open_bus("ide");
102 sf_ide_list
= sysfs_get_bus_devices(sf_bus
);
103 if(sf_ide_list
) dlist_for_each_data(sf_ide_list
, sf_ide
, struct sysfs_device
) {
105 " ide: bus_id = %s path = %s\n",
107 hd_sysfs_id(sf_ide
->path
)
112 sf_class
= sysfs_open_class("block");
115 ADD2LOG("sysfs: no such class: block\n");
119 sf_cdev_list
= sysfs_get_class_devices(sf_class
);
120 if(sf_cdev_list
) dlist_for_each_data(sf_cdev_list
, sf_cdev
, struct sysfs_class_device
) {
122 " block: name = %s, path = %s\n",
124 hd_sysfs_id(sf_cdev
->path
)
127 memset(&dev_num
, 0, sizeof dev_num
);
129 if((s
= hd_attr_str(sysfs_get_classdev_attr(sf_cdev
, "dev")))) {
130 if(sscanf(s
, "%u:%u", &u1
, &u2
) == 2) {
136 ADD2LOG(" dev = %u:%u\n", u1
, u2
);
139 if(hd_attr_uint(sysfs_get_classdev_attr(sf_cdev
, "range"), &ul0
, 0)) {
141 ADD2LOG(" range = %u\n", dev_num
.range
);
144 sf_dev
= sysfs_get_classdev_device(sf_cdev
);
147 " block device: bus = %s, bus_id = %s driver = %s\n path = %s\n",
151 hd_sysfs_id(sf_dev
->path
)
157 /* check if disk is DASD and has already been found by s390.c */
158 if(sf_dev
&& sf_dev
->driver_name
&& strstr(sf_dev
->driver_name
,"dasd"))
162 //fprintf(stderr,"dn %s bi %s\n",sf_dev->driver_name,sf_dev->bus_id);
163 for(hd
=hd_data
->hd
;hd
;hd
=hd
->next
)
165 //fprintf(stderr,"bcid %d\n",hd->base_class.id);
166 if(hd
->base_class
.id
== bc_storage_device
168 && hd
->detail
->ccw
.type
== hd_detail_ccw
)
170 for(res
=hd
->res
;res
;res
=res
->next
)
172 if(res
->io
.type
==res_io
)
174 sprintf(bid
,"%01x.%01x.%04x",
175 hd
->detail
->ccw
.data
->lcss
>> 8,
176 hd
->detail
->ccw
.data
->lcss
& 0xff,
177 (unsigned short)res
->io
.base
);
178 //fprintf(stderr,"bid %s\n",bid);
179 if (strcmp(bid
,sf_dev
->bus_id
)==0) goto out
;
187 else if((sl
= search_str_list(hd_data
->disks
, hd_sysfs_name2_dev(sf_cdev
->name
)))) {
188 hd
= add_hd_entry(hd_data
, __LINE__
, 0);
189 hd
->sub_class
.id
= sc_sdev_disk
;
191 else if((sl
= search_str_list(hd_data
->cdroms
, hd_sysfs_name2_dev(sf_cdev
->name
)))) {
192 hd
= add_hd_entry(hd_data
, __LINE__
, 0);
193 hd
->sub_class
.id
= sc_sdev_cdrom
;
198 (!strcmp(sf_dev
->bus
, "scsi") || !strcmp(sf_dev
->bus
, "ide"))
200 hd
= add_hd_entry(hd_data
, __LINE__
, 0);
201 hd
->sub_class
.id
= sc_sdev_other
;
205 str_printf(&hd
->unix_dev_name
, 0, "/dev/%s", hd_sysfs_name2_dev(sf_cdev
->name
));
207 hd
->base_class
.id
= bc_storage_device
;
209 hd
->sysfs_id
= new_str(hd_sysfs_id(sf_cdev
->path
));
211 if(sf_dev
) hd
->sysfs_device_link
= new_str(hd_sysfs_id(sf_dev
->path
));
213 hd
->unix_dev_num
= dev_num
;
215 hd
->bus
.id
= bus_none
;
219 if(!strcmp(sf_dev
->bus
, "ide")) hd
->bus
.id
= bus_ide
;
220 else if(!strcmp(sf_dev
->bus
, "scsi")) hd
->bus
.id
= bus_scsi
;
222 hd
->sysfs_bus_id
= new_str(sf_dev
->bus_id
);
225 if(sf_dev
&& (s
= hd_sysfs_id(sf_dev
->path
))) {
227 /* parent has longest matching sysfs id */
229 for(u3
= 0, hd1
= hd_data
->hd
; hd1
; hd1
= hd1
->next
) {
231 u1
= strlen(hd1
->sysfs_id
);
232 if(u1
> u3
&& u1
<= u2
&& !strncmp(s
, hd1
->sysfs_id
, u1
)) {
234 hd
->attached_to
= hd1
->idx
;
239 /* find longest matching sysfs id we have a driver for */
243 t
= hd_sysfs_find_driver(hd_data
, s
, 0);
245 add_str_list(&hd
->drivers
, t
);
249 /* look for ide-scsi handled devices */
250 if(hd
->bus
.id
== bus_scsi
) {
251 if(sf_ide_list
) dlist_for_each_data(sf_ide_list
, sf_ide
, struct sysfs_device
) {
253 strcmp(sf_dev
->path
, sf_ide
->path
) &&
254 !strncmp(sf_dev
->path
, sf_ide
->path
, strlen(sf_ide
->path
)) &&
255 sscanf(sf_ide
->bus_id
, "%u.%u", &u1
, &u2
) == 2
257 str_printf(&hd
->unix_dev_name2
, 0, "/dev/hd%c", 'a' + (u1
<< 1) + u2
);
264 * set hd->drivers before calling any of add_xxx_sysfs_info()
268 sf_dev
->driver_name
&&
269 *sf_dev
->driver_name
&&
270 strcmp(sf_dev
->driver_name
, "unknown")
272 add_str_list(&hd
->drivers
, sf_dev
->driver_name
);
275 if(hd
->bus
.id
== bus_ide
) {
276 add_ide_sysfs_info(hd_data
, hd
, sf_dev
);
278 else if(hd
->bus
.id
== bus_scsi
) {
279 add_scsi_sysfs_info(hd_data
, hd
, sf_dev
);
282 add_other_sysfs_info(hd_data
, hd
, sf_dev
);
286 if(hd
->sub_class
.id
== sc_sdev_cdrom
) {
287 add_cdrom_info(hd_data
, hd
);
291 hd
->sub_class
.id
== sc_sdev_disk
&&
292 hd_probe_feature(hd_data
, pr_block_part
)
294 add_partitions(hd_data
, hd
, sf_cdev
->path
);
301 sysfs_close_class(sf_class
);
303 sysfs_close_bus(sf_bus
);
308 * Find driver for sysfs_id.
310 * Return driver for id (exact = 1) or longest matching id (exact = 0).
312 char *hd_sysfs_find_driver(hd_data_t
*hd_data
, char *sysfs_id
, int exact
)
318 if(!sysfs_id
|| !*sysfs_id
) return NULL
;
323 for(sf
= hd_data
->sysfsdrv
; sf
; sf
= sf
->next
) {
324 if(!strcmp(sysfs_id
, sf
->device
)) {
331 u2
= strlen(sysfs_id
);
333 for(sf
= hd_data
->sysfsdrv
; sf
; sf
= sf
->next
) {
334 u1
= strlen(sf
->device
);
335 if(u1
> u3
&& u1
<= u2
&& !strncmp(sysfs_id
, sf
->device
, u1
)) {
346 void add_partitions(hd_data_t
*hd_data
, hd_t
*hd
, char *path
)
353 s
= hd
->unix_dev_name
+ sizeof "/dev/" - 1;
355 for(sl
= hd_data
->partitions
; sl
; sl
= sl
->next
) {
356 if(!strncmp(sl
->str
, s
, len
)) {
357 hd1
= add_hd_entry(hd_data
, __LINE__
, 0);
358 hd1
->base_class
.id
= bc_partition
;
359 str_printf(&hd1
->unix_dev_name
, 0, "/dev/%s", sl
->str
);
360 hd1
->attached_to
= hd
->idx
;
362 str_printf(&hd1
->sysfs_id
, 0, "%s/%s", hd
->sysfs_id
, hd_sysfs_dev2_name(sl
->str
));
368 void add_cdrom_info(hd_data_t
*hd_data
, hd_t
*hd
)
370 cdrom_info_t
*ci
, **prev
;
372 hd
->detail
= free_hd_detail(hd
->detail
);
373 hd
->detail
= new_mem(sizeof *hd
->detail
);
374 hd
->detail
->type
= hd_detail_cdrom
;
376 for(ci
= *(prev
= &hd_data
->cdrom
); ci
; ci
= *(prev
= &ci
->next
)) {
377 if(!strcmp(hd
->unix_dev_name
+ sizeof "/dev/" - 1, ci
->name
)) {
378 hd
->detail
->cdrom
.data
= ci
;
380 hd
->detail
->cdrom
.data
->next
= NULL
;
385 if((ci
= hd
->detail
->cdrom
.data
)) {
386 /* update prog_if: cdr, cdrw, ... */
388 /* ###### FIXME: dosn't work anyway: ide-scsi doesn't support sysfs */
389 hd
->bus
.id
== bus_scsi
&&
390 !search_str_list(hd
->drivers
, "ide-scsi") /* could be ide, though */
393 if(ci
->dvd
&& (ci
->cdrw
|| ci
->dvdr
|| ci
->dvdram
)) {
394 ci
->dvd
= ci
->dvdr
= ci
->dvdram
= 0;
396 ci
->dvdr
= ci
->dvdram
= 0;
397 ci
->cdr
= ci
->cdrw
= 0;
398 if(hd
->prog_if
.id
== pif_cdr
) ci
->cdr
= 1;
404 hd
->prog_if
.id
= pif_dvd
;
408 hd
->prog_if
.id
= pif_cdr
;
412 hd
->prog_if
.id
= pif_cdrw
;
416 hd
->prog_if
.id
= pif_dvdr
;
420 hd
->prog_if
.id
= pif_dvdram
;
425 hd_probe_feature(hd_data
, pr_block_cdrom
) &&
426 hd_report_this(hd_data
, hd
)
428 hd_read_cdrom_info(hd_data
, hd
);
433 void add_other_sysfs_info(hd_data_t
*hd_data
, hd_t
*hd
, struct sysfs_device
*sf_dev
)
440 sscanf(hd
->sysfs_id
, "/block/cciss!c%ud%u", &u0
, &u1
) == 2
442 hd
->slot
= (u0
<< 8) + u1
;
443 str_printf(&hd
->device
.name
, 0, "CCISS disk %u/%u", u0
, u1
);
446 sscanf(hd
->sysfs_id
, "/block/ida!c%ud%u", &u0
, &u1
) == 2
448 hd
->slot
= (u0
<< 8) + u1
;
449 str_printf(&hd
->device
.name
, 0, "SMART Array %u/%u", u0
, u1
);
452 sscanf(hd
->sysfs_id
, "/block/rd!c%ud%u", &u0
, &u1
) == 2
454 hd
->slot
= (u0
<< 8) + u1
;
455 str_printf(&hd
->device
.name
, 0, "DAC960 RAID Array %u/%u", u0
, u1
);
458 sscanf(hd
->sysfs_id
, "/block/i2o!hd%c", &c
) == 1 &&
462 str_printf(&hd
->device
.name
, 0, "I2O disk %u", hd
->slot
);
465 sscanf(hd
->sysfs_id
, "/block/dasd%c", &c
) == 1 &&
469 hd
->device
.name
= new_str("S390 Disk");
473 add_disk_size(hd_data
, hd
);
477 void add_ide_sysfs_info(hd_data_t
*hd_data
, hd_t
*hd
, struct sysfs_device
*sf_dev
)
479 char *fname
= NULL
, buf
[256], *dev_name
, *s
;
480 unsigned u0
, u1
, u2
, size
= 0;
481 str_list_t
*sl
, *sl0
;
485 if(!hd_report_this(hd_data
, hd
)) return;
487 if(hd
->sysfs_bus_id
&& sscanf(hd
->sysfs_bus_id
, "%u.%u", &u0
, &u1
) == 2) {
488 /* host.master/slave */
489 hd
->slot
= (u0
<< 1) + u1
;
494 strlen(hd
->unix_dev_name
) > 5
496 dev_name
= hd
->unix_dev_name
+ 5;
498 str_printf(&fname
, 0, PROC_IDE
"/%s/media", dev_name
);
499 if((sl
= read_file(fname
, 0, 1))) {
501 if(strstr(sl
->str
, "floppy"))
502 hd
->sub_class
.id
= sc_sdev_floppy
;
503 else if(strstr(sl
->str
, "cdrom"))
504 hd
->sub_class
.id
= sc_sdev_cdrom
;
505 else if(strstr(sl
->str
, "tape"))
506 hd
->sub_class
.id
= sc_sdev_tape
;
511 str_printf(&fname
, 0, PROC_IDE
"/%s/model", dev_name
);
512 if((sl
= read_file(fname
, 0, 1))) {
513 hd
->vendor
.name
= canon_str(sl
->str
, strlen(sl
->str
));
514 if((s
= strchr(hd
->vendor
.name
, ' '))) {
515 hd
->device
.name
= canon_str(s
, strlen(s
));
516 if(*hd
->device
.name
) {
520 hd
->device
.name
= free_mem(hd
->device
.name
);
523 if(!hd
->device
.name
) {
524 hd
->device
.name
= hd
->vendor
.name
;
525 hd
->vendor
.name
= NULL
;
531 str_printf(&fname
, 0, PROC_IDE
"/%s/driver", dev_name
);
532 if((sl
= read_file(fname
, 0, 1))) {
533 if((s
= strchr(sl
->str
, ' '))) *s
= 0;
534 s
= canon_str(sl
->str
, strlen(sl
->str
));
535 add_str_list(&hd
->drivers
, s
);
540 str_printf(&fname
, 0, PROC_IDE
"/%s/capacity", dev_name
);
541 if((sl
= read_file(fname
, 0, 1))) {
542 if(sscanf(sl
->str
, "%u", &u0
) == 1 && u0
!= 0x7fffffff) {
543 res
= add_res_entry(&hd
->res
, new_mem(sizeof *res
));
544 res
->size
.type
= res_size
;
545 res
->size
.unit
= size_unit_sectors
;
546 res
->size
.val1
= size
= u0
;
547 res
->size
.val2
= 512; // ####### FIXME: sector size?
552 str_printf(&fname
, 0, PROC_IDE
"/%s/geometry", dev_name
);
553 if((sl0
= read_file(fname
, 0, 2))) {
554 for(sl
= sl0
; sl
; sl
= sl
->next
) {
555 if(sscanf(sl
->str
, " physical %u / %u / %u", &u0
, &u1
, &u2
) == 3) {
557 if(size
&& u1
&& u2
) {
558 u0
= size
/ (u1
* u2
);
560 res
= add_res_entry(&hd
->res
, new_mem(sizeof *res
));
561 res
->disk_geo
.type
= res_disk_geo
;
562 res
->disk_geo
.cyls
= u0
;
563 res
->disk_geo
.heads
= u1
;
564 res
->disk_geo
.sectors
= u2
;
565 res
->disk_geo
.geotype
= geo_physical
;
570 if(sscanf(sl
->str
, " logical %u / %u / %u", &u0
, &u1
, &u2
) == 3) {
571 if(size
&& u1
&& u2
) {
572 u0
= size
/ (u1
* u2
);
574 res
= add_res_entry(&hd
->res
, new_mem(sizeof *res
));
575 res
->disk_geo
.type
= res_disk_geo
;
576 res
->disk_geo
.cyls
= u0
;
577 res
->disk_geo
.heads
= u1
;
578 res
->disk_geo
.sectors
= u2
;
579 res
->disk_geo
.geotype
= geo_logical
;
585 str_printf(&fname
, 0, PROC_IDE
"/%s/cache", dev_name
);
586 if((sl
= read_file(fname
, 0, 1))) {
587 if(sscanf(sl
->str
, "%u", &u0
) == 1 && u0
) {
588 res
= add_res_entry(&hd
->res
, new_mem(sizeof *res
));
589 res
->cache
.type
= res_cache
;
590 res
->cache
.size
= u0
;
595 str_printf(&fname
, 0, PROC_IDE
"/%s/identify", dev_name
);
596 if((f
= fopen(fname
, "r"))) {
598 memset(buf
, sizeof buf
, 0);
599 while(u1
< sizeof buf
- 1 && fscanf(f
, "%x", &u0
) == 1) {
600 buf
[u1
++] = u0
>> 8; buf
[u1
++] = u0
;
604 /* ok, we now have the ATA/ATAPI ident block */
606 if(buf
[0x14] || buf
[0x15]) { /* has serial id */
607 hd
->serial
= canon_str(buf
+ 0x14, 20);
609 if(buf
[0x2e] || buf
[0x2f]) { /* has revision id */
610 hd
->revision
.name
= canon_str(buf
+ 0x2e, 8);
617 if(!size
) add_disk_size(hd_data
, hd
);
622 * assumes hd->drivers aleady includes scsi device drivers (like 'sd')
624 void add_scsi_sysfs_info(hd_data_t
*hd_data
, hd_t
*hd
, struct sysfs_device
*sf_dev
)
627 char *s
, *t
, *cs
, *pr_str
;
628 unsigned u0
, u1
, u2
, u3
;
630 unsigned char scsi_cmd_buf
[0x300];
631 struct sg_io_hdr hdr
;
634 hd_res_t
*geo
, *size
;
637 if(!hd_report_this(hd_data
, hd
)) return;
639 hd
->detail
= new_mem(sizeof *hd
->detail
);
640 hd
->detail
->type
= hd_detail_scsi
;
641 hd
->detail
->scsi
.data
= scsi
= new_mem(sizeof *scsi
);
643 if(hd
->sysfs_bus_id
&& sscanf(hd
->sysfs_bus_id
, "%u:%u:%u:%u", &u0
, &u1
, &u2
, &u3
) == 4) {
644 /* host:channel:id:lun */
645 hd
->slot
= (u0
<< 8) + (u1
<< 4) + u2
;
649 if((s
= hd_attr_str(sysfs_get_device_attr(sf_dev
, "vendor")))) {
650 cs
= canon_str(s
, strlen(s
));
651 ADD2LOG(" vendor = %s\n", cs
);
653 hd
->vendor
.name
= cs
;
660 if((s
= hd_attr_str(sysfs_get_device_attr(sf_dev
, "model")))) {
661 cs
= canon_str(s
, strlen(s
));
662 ADD2LOG(" model = %s\n", cs
);
664 hd
->device
.name
= cs
;
670 /* sata entries are somewhat strange... */
673 !strcmp(hd
->vendor
.name
, "ATA") &&
676 hd
->bus
.id
= bus_ide
;
678 if((cs
= strchr(hd
->device
.name
, ' '))) {
679 t
= canon_str(cs
, strlen(cs
));
682 free_mem(hd
->vendor
.name
);
683 hd
->vendor
.name
= hd
->device
.name
;
691 if(!strcmp(hd
->vendor
.name
, "ATA")) {
692 hd
->vendor
.name
= free_mem(hd
->vendor
.name
);
697 if((s
= hd_attr_str(sysfs_get_device_attr(sf_dev
, "rev")))) {
698 cs
= canon_str(s
, strlen(s
));
699 ADD2LOG(" rev = %s\n", cs
);
701 hd
->revision
.name
= cs
;
708 if(hd_attr_uint(sysfs_get_device_attr(sf_dev
, "type"), &ul0
, 0)) {
709 ADD2LOG(" type = %u\n", (unsigned) ul0
);
710 if(ul0
== 6 /* scanner */) {
711 hd
->sub_class
.id
= sc_sdev_scanner
;
713 else if(ul0
== 3 /* processor */ && hd
->vendor
.name
) {
715 !strncmp(hd
->vendor
.name
, "HP", sizeof "HP" - 1) ||
716 !strncmp(hd
->vendor
.name
, "EPSON", sizeof "EPSON" - 1)
718 hd
->sub_class
.id
= sc_sdev_scanner
;
723 * typically needed for usb card readers (unused slots)
726 hd
->base_class
.id
== bc_storage_device
&&
727 hd
->sub_class
.id
== sc_sdev_other
731 if(search_str_list(hd
->drivers
, "sd")) {
732 hd
->sub_class
.id
= sc_sdev_disk
;
737 if(search_str_list(hd
->drivers
, "sr")) {
738 hd
->sub_class
.id
= sc_sdev_cdrom
;
746 /* s390: wwpn & fcp lun */
747 if(hd_attr_uint(sysfs_get_device_attr(sf_dev
, "wwpn"), &ul0
, 0)) {
748 ADD2LOG(" wwpn = 0x%016"PRIx64
"\n", ul0
);
751 /* it's a bit of a hack, actually */
752 t
= new_str(hd_sysfs_id(sf_dev
->path
));
754 if((s
= strrchr(t
, '/'))) *s
= 0;
755 if((s
= strrchr(t
, '/'))) *s
= 0;
756 if((s
= strrchr(t
, '/'))) {
757 scsi
->controller_id
= new_str(s
+ 1);
763 if(hd_attr_uint(sysfs_get_device_attr(sf_dev
, "fcp_lun"), &ul0
, 0)) {
764 ADD2LOG(" fcp_lun = 0x%016"PRIx64
"\n", ul0
);
768 /* ppc: get rom id */
769 if((hd1
= hd_get_device_by_idx(hd_data
, hd
->attached_to
)) && hd1
->rom_id
) {
770 str_printf(&hd
->rom_id
, 0, "%s/@%u", hd1
->rom_id
, (hd
->slot
& 0xf));
776 hd_report_this(hd_data
, hd
) &&
778 hd
->sub_class
.id
== sc_sdev_cdrom
&&
779 hd_data
->in_vmware
!= 1 /* VMWare doesn't like it */
781 PROGRESS(5, 0, hd
->unix_dev_name
);
782 fd
= open(hd
->unix_dev_name
, O_RDONLY
| O_NONBLOCK
);
785 str_printf(&pr_str
, 0, "%s cache", hd
->unix_dev_name
);
786 PROGRESS(5, 1, pr_str
);
788 memset(scsi_cmd_buf
, 0, sizeof scsi_cmd_buf
);
789 memset(&hdr
, 0, sizeof(hdr
));
791 hdr
.interface_id
= 'S';
793 hdr
.dxfer_direction
= SG_DXFER_FROM_DEV
;
794 hdr
.dxferp
= scsi_cmd_buf
+ 8 + 6;
795 hdr
.dxfer_len
= 0xff;
796 hdr
.cmdp
= scsi_cmd_buf
+ 8;
801 k
= ioctl(fd
, SG_IO
, &hdr
);
804 ADD2LOG("%s status(0x1a:8) 0x%x\n", hd
->unix_dev_name
, k
);
807 unsigned char *ptr
= hdr
.dxferp
;
809 uc
= ptr
+ 4 + ptr
[3] + 2;
811 ADD2LOG(" scsi cache: 0x%02x\n", uc
[0]);
813 if((scsi
->cache
& 4)) {
814 hd
->prog_if
.id
= pif_cdr
;
824 hd_report_this(hd_data
, hd
) &&
826 hd
->sub_class
.id
== sc_sdev_disk
&&
827 !hd_probe_feature(hd_data
, pr_scsi_noserial
)
829 PROGRESS(5, 0, hd
->unix_dev_name
);
830 fd
= open(hd
->unix_dev_name
, O_RDONLY
| O_NONBLOCK
);
833 str_printf(&pr_str
, 0, "%s geo", hd
->unix_dev_name
);
834 PROGRESS(5, 1, pr_str
);
836 if(hd_getdisksize(hd_data
, hd
->unix_dev_name
, fd
, &geo
, &size
) == 1) {
837 /* (low-level) unformatted disk */
841 if(geo
) add_res_entry(&hd
->res
, geo
);
842 if(size
) add_res_entry(&hd
->res
, size
);
844 str_printf(&pr_str
, 0, "%s serial", hd
->unix_dev_name
);
845 PROGRESS(5, 2, pr_str
);
847 memset(scsi_cmd_buf
, 0, sizeof scsi_cmd_buf
);
848 memset(&hdr
, 0, sizeof(hdr
));
850 hdr
.interface_id
= 'S';
852 hdr
.dxfer_direction
= SG_DXFER_FROM_DEV
;
853 hdr
.dxferp
= scsi_cmd_buf
+ 8 + 6;
854 hdr
.dxfer_len
= 0x24;
855 hdr
.cmdp
= scsi_cmd_buf
+ 8;
861 k
= ioctl(fd
, SG_IO
, &hdr
);
864 ADD2LOG("%s status(0x12) 0x%x\n", scsi
->dev_name
, k
);
867 unsigned char *ptr
= hdr
.dxferp
;
869 ADD2LOG(" serial id len: %u\n", ptr
[3]);
871 if((hd
->serial
= canon_str(ptr
+ 4, ptr
[3]))) {
872 if(!*hd
->serial
) hd
->serial
= free_mem(hd
->serial
);
880 pr_str
= free_mem(pr_str
);
884 hd
->base_class
.id
== bc_storage_device
&&
885 hd
->sub_class
.id
== sc_sdev_scanner
887 hd
->base_class
.id
= bc_scanner
;
890 // ###### FIXME: usb-storage: disk vs. floppy?
895 void read_partitions(hd_data_t
*hd_data
)
897 str_list_t
*sl
, *sl0
, *pl0
= NULL
;
898 char buf
[256], *s1
, *name
, *base
;
899 char *last_base
= new_str(" ");
900 char *last_name
= new_str(" ");
903 if(!(sl0
= read_file(PROC_PARTITIONS
, 2, 0))) return;
906 ADD2LOG("----- "PROC_PARTITIONS
" -----\n");
907 for(sl
= sl0
; sl
; sl
= sl
->next
) {
908 ADD2LOG(" %s", sl
->str
);
910 ADD2LOG("----- "PROC_PARTITIONS
" end -----\n");
913 for(sl
= sl0
; sl
; sl
= sl
->next
) {
915 if(sscanf(sl
->str
, "%*s %*s %*s %255s", buf
) > 0) {
916 if(*buf
) add_str_list(&pl0
, buf
);
922 for(is_disk
= 1, sl
= pl0
; sl
; sl
= sl
->next
) {
928 while(isdigit(*s1
) && s1
> base
) s1
--;
929 if(s1
== base
) continue;
931 name
= new_str(base
);
934 if(!strcmp(last_base
, base
)) {
935 if(!strcmp(last_name
, base
)) is_disk
= 0;
938 is_disk
= strncmp(last_name
, base
, strlen(last_name
)) ? 1 : 0;
941 if(!search_str_list(hd_data
->cdroms
, name
)) {
943 strncmp(name
, "loop", sizeof "loop" - 1) &&
945 hd_data
->flags
.list_md
||
947 strncmp(name
, "md", sizeof "md" - 1) &&
948 strncmp(name
, "dm-", sizeof "dm-" - 1)
952 add_str_list(is_disk
? &hd_data
->disks
: &hd_data
->partitions
, name
);
958 last_base
= new_str(base
);
959 last_name
= name
; name
= NULL
;
969 for(sl
= hd_data
->disks
; sl
; sl
= sl
->next
) ADD2LOG(" %s\n", sl
->str
);
970 ADD2LOG("partitions:\n");
971 for(sl
= hd_data
->partitions
; sl
; sl
= sl
->next
) ADD2LOG(" %s\n", sl
->str
);
977 * Read iso9660/el torito info, if there is a CD inserted.
978 * Returns NULL if nothing was found
980 cdrom_info_t
*hd_read_cdrom_info(hd_data_t
*hd_data
, hd_t
*hd
)
985 struct iso_primary_descriptor iso_desc
;
986 unsigned char sector
[0x800];
990 #ifdef LIBHD_MEMCHECK
993 fprintf(libhd_log
, "; %s\t%p\t%p\n", __FUNCTION__
, CALLED_FROM(hd_read_cdrom_info
, hd_data
), hd_data
);
997 /* free existing entry */
998 if(hd
->detail
&& hd
->detail
->type
!= hd_detail_cdrom
) {
999 hd
->detail
= free_hd_detail(hd
->detail
);
1003 hd
->detail
= new_mem(sizeof *hd
->detail
);
1004 hd
->detail
->type
= hd_detail_cdrom
;
1005 hd
->detail
->cdrom
.data
= new_mem(sizeof *hd
->detail
->cdrom
.data
);
1008 ci
= hd
->detail
->cdrom
.data
;
1010 hd
->is
.notready
= 0;
1012 if((fd
= open(hd
->unix_dev_name
, O_RDONLY
)) < 0) {
1013 /* we are here if there is no CD in the drive */
1014 hd
->is
.notready
= 1;
1020 lseek(fd
, 0x8000, SEEK_SET
) >= 0 &&
1021 read(fd
, &iso_desc
, sizeof iso_desc
) == sizeof iso_desc
1024 if(!memcmp(iso_desc
.id
, "CD001", 5)) {
1026 /* now, fill in the fields */
1027 s
= canon_str(iso_desc
.volume_id
, sizeof iso_desc
.volume_id
);
1028 if(!*s
) s
= free_mem(s
);
1029 ci
->iso9660
.volume
= s
;
1031 s
= canon_str(iso_desc
.publisher_id
, sizeof iso_desc
.publisher_id
);
1032 if(!*s
) s
= free_mem(s
);
1033 ci
->iso9660
.publisher
= s
;
1035 s
= canon_str(iso_desc
.preparer_id
, sizeof iso_desc
.preparer_id
);
1036 if(!*s
) s
= free_mem(s
);
1037 ci
->iso9660
.preparer
= s
;
1039 s
= canon_str(iso_desc
.application_id
, sizeof iso_desc
.application_id
);
1040 if(!*s
) s
= free_mem(s
);
1041 ci
->iso9660
.application
= s
;
1043 s
= canon_str(iso_desc
.creation_date
, sizeof iso_desc
.creation_date
);
1044 if(!*s
) s
= free_mem(s
);
1045 ci
->iso9660
.creation_date
= s
;
1051 lseek(fd
, 0x8800, SEEK_SET
) >= 0 &&
1052 read(fd
, §or
, sizeof sector
) == sizeof sector
1055 sector
[0] == 0 && sector
[6] == 1 &&
1056 !memcmp(sector
+ 1, "CD001", 5) &&
1057 !memcmp(sector
+ 7, "EL TORITO SPECIFICATION", 23)
1059 et
= sector
[0x47] + (sector
[0x48] << 8) + (sector
[0x49] << 16) + (sector
[0x4a] << 24);
1060 ADD2LOG(" %s: el torito boot catalog at 0x%04x\n", ci
->name
, et
);
1062 lseek(fd
, et
* 0x800, SEEK_SET
) >= 0 &&
1063 read(fd
, §or
, sizeof sector
) == sizeof sector
&&
1066 ci
->el_torito
.ok
= 1;
1067 ci
->el_torito
.catalog
= et
;
1068 ci
->el_torito
.platform
= sector
[1];
1069 s
= canon_str(sector
+ 4, 24);
1070 if(!*s
) s
= free_mem(s
);
1071 ci
->el_torito
.id_string
= s
;
1072 ci
->el_torito
.bootable
= sector
[0x20] == 0x88 ? 1 : 0;
1073 ci
->el_torito
.media_type
= sector
[0x21];
1074 ADD2LOG(" media type: %u\n", ci
->el_torito
.media_type
);
1075 ci
->el_torito
.load_address
= (sector
[0x22] + (sector
[0x23] << 8)) << 4;
1076 ADD2LOG(" load address: 0x%04x\n", ci
->el_torito
.load_address
);
1078 if(ci
->el_torito
.platform
== 0 && ci
->el_torito
.load_address
== 0)
1079 ci
->el_torito
.load_address
= 0x7c00;
1081 ci
->el_torito
.load_count
= sector
[0x26] + (sector
[0x27] << 8);
1082 ci
->el_torito
.start
= sector
[0x28] + (sector
[0x29] << 8) + (sector
[0x2a] << 16) + (sector
[0x2b] << 24);
1083 if(ci
->el_torito
.media_type
>= 1 && ci
->el_torito
.media_type
<= 3) {
1084 ci
->el_torito
.geo
.c
= 80;
1085 ci
->el_torito
.geo
.h
= 2;
1087 switch(ci
->el_torito
.media_type
) {
1089 ci
->el_torito
.geo
.s
= 15;
1092 ci
->el_torito
.geo
.s
= 18;
1095 ci
->el_torito
.geo
.s
= 36;
1099 lseek(fd
, ci
->el_torito
.start
* 0x800, SEEK_SET
) >= 0 &&
1100 read(fd
, §or
, sizeof sector
) == sizeof sector
1102 if(ci
->el_torito
.media_type
== 4) {
1103 /* ##### we should go on and read the 1st partition sector in this case... */
1104 ci
->el_torito
.geo
.h
= (unsigned) sector
[0x1be + 5] + 1;
1105 ci
->el_torito
.geo
.s
= sector
[0x1be + 6] & 0x3f;
1106 ci
->el_torito
.geo
.c
= sector
[0x1be + 7] + (((unsigned) sector
[0x1be + 6] >> 6) << 8);
1109 sector
[0x1fe] == 0x55 && sector
[0x1ff] == 0xaa &&
1110 sector
[0x0b] == 0 && sector
[0x0c] == 2 &&
1111 sector
[0x0e] == 1 && sector
[0x0f] == 0
1113 u0
= sector
[0x13] + (sector
[0x14] << 8); /* partition size */
1114 u1
= sector
[0x18] + (sector
[0x19] << 8); /* sectors per track */
1115 u2
= sector
[0x1a] + (sector
[0x1b] << 8); /* heads */
1116 u0
= u0
? u0
: sector
[0x20] + (sector
[0x21] << 8) + (sector
[0x22] << 16) + ((unsigned) sector
[0x23] << 24);
1117 if(sector
[0x26] == 0x29) {
1118 s
= canon_str(sector
+ 0x2b, 11);
1119 if(!*s
) s
= free_mem(s
);
1120 ci
->el_torito
.label
= s
;
1122 if(!ci
->el_torito
.label
) {
1123 s
= canon_str(sector
+ 3, 8);
1124 if(!*s
) s
= free_mem(s
);
1125 ci
->el_torito
.label
= s
;
1128 (ci
->el_torito
.media_type
== 0 || ci
->el_torito
.media_type
> 3) &&
1131 ci
->el_torito
.geo
.h
= u2
;
1132 ci
->el_torito
.geo
.s
= u1
;
1133 ci
->el_torito
.geo
.size
= u0
;
1134 ci
->el_torito
.geo
.c
= ci
->el_torito
.geo
.size
/ (u1
* u2
);
1139 ci
->el_torito
.geo
.size
= ci
->el_torito
.geo
.s
* ci
->el_torito
.geo
.c
* ci
->el_torito
.geo
.h
;
1151 * Read the list of CDROM devices known to the kernel. The info is taken
1152 * from /proc/sys/dev/cdrom/info.
1154 void read_cdroms(hd_data_t
*hd_data
)
1157 str_list_t
*sl
, *sl0
;
1159 int i
, line
, entries
= 0;
1162 if(!(sl0
= read_file(PROC_CDROM_INFO
, 2, 0))) return;
1164 if((hd_data
->debug
& HD_DEB_CDROM
)) {
1165 ADD2LOG("----- "PROC_CDROM_INFO
" -----\n");
1166 for(sl
= sl0
; sl
; sl
= sl
->next
) {
1167 if(*sl
->str
!= '\n') ADD2LOG("%s", sl
->str
);
1169 ADD2LOG("----- "PROC_CDROM_INFO
" end -----\n");
1172 for(sl
= sl0
; sl
; sl
= sl
->next
) {
1174 (line
= 0, strstr(sl
->str
, "drive name:") == sl
->str
) ||
1175 (line
++, strstr(sl
->str
, "drive speed:") == sl
->str
) ||
1176 (line
++, strstr(sl
->str
, "Can write CD-R:") == sl
->str
) ||
1177 (line
++, strstr(sl
->str
, "Can write CD-RW:") == sl
->str
) ||
1178 (line
++, strstr(sl
->str
, "Can read DVD:") == sl
->str
) ||
1179 (line
++, strstr(sl
->str
, "Can write DVD-R:") == sl
->str
) ||
1180 (line
++, strstr(sl
->str
, "Can write DVD-RAM:") == sl
->str
)
1182 s
= strchr(sl
->str
, ':') + 1;
1184 while((t
= strsep(&s
, " \t\n"))) {
1188 case 0: /* drive name */
1189 ci
= new_cdrom_entry(&hd_data
->cdrom
);
1191 add_str_list(&hd_data
->cdroms
, t
);
1192 ci
->name
= new_str(t
);
1195 case 1: /* drive speed */
1196 case 2: /* Can write CD-R */
1197 case 3: /* Can write CD-RW */
1198 case 4: /* Can read DVD */
1199 case 5: /* Can write DVD-R */
1200 case 6: /* Can write DVD-RAM */
1201 ci
= get_cdrom_entry(hd_data
->cdrom
, entries
- i
);
1203 val
= strtoul(t
, &v
, 10);
1237 /* add new entries at the _start_ of the list */
1238 cdrom_info_t
*new_cdrom_entry(cdrom_info_t
**ci
)
1240 cdrom_info_t
*new_ci
= new_mem(sizeof *new_ci
);
1243 return *ci
= new_ci
;
1247 /* return nth entry */
1248 cdrom_info_t
*get_cdrom_entry(cdrom_info_t
*ci
, int n
)
1250 if(n
< 0) return NULL
;
1253 if(!ci
) return NULL
;
1262 * Add generic scsi devs.
1264 void hd_scan_sysfs_scsi(hd_data_t
*hd_data
)
1266 if(!hd_probe_feature(hd_data
, pr_scsi
)) return;
1268 hd_data
->module
= mod_scsi
;
1271 remove_hd_entries(hd_data
);
1273 PROGRESS(1, 0, "scsi modules");
1275 load_module(hd_data
, "sg");
1277 PROGRESS(2, 0, "scsi tape");
1279 get_scsi_tape(hd_data
);
1281 PROGRESS(3, 0, "scsi generic");
1283 get_generic_scsi_devs(hd_data
);
1287 void get_scsi_tape(hd_data_t
*hd_data
)
1290 unsigned u1
, u2
, u3
;
1293 hd_dev_num_t dev_num
;
1295 struct sysfs_class
*sf_class
;
1296 struct sysfs_class_device
*sf_cdev
;
1297 struct sysfs_device
*sf_dev
;
1298 struct dlist
*sf_cdev_list
;
1300 sf_class
= sysfs_open_class("scsi_tape");
1303 ADD2LOG("sysfs: no such class: scsi_tape\n");
1307 sf_cdev_list
= sysfs_get_class_devices(sf_class
);
1308 if(sf_cdev_list
) dlist_for_each_data(sf_cdev_list
, sf_cdev
, struct sysfs_class_device
) {
1310 " scsi tape: name = %s, path = %s\n",
1312 hd_sysfs_id(sf_cdev
->path
)
1315 memset(&dev_num
, 0, sizeof dev_num
);
1317 if((s
= hd_attr_str(sysfs_get_classdev_attr(sf_cdev
, "dev")))) {
1318 if(sscanf(s
, "%u:%u", &u1
, &u2
) == 2) {
1324 ADD2LOG(" dev = %u:%u\n", u1
, u2
);
1327 if(hd_attr_uint(sysfs_get_classdev_attr(sf_cdev
, "range"), &ul0
, 0)) {
1328 dev_num
.range
= ul0
;
1329 ADD2LOG(" range = %u\n", dev_num
.range
);
1332 sf_dev
= sysfs_get_classdev_device(sf_cdev
);
1334 s
= hd_sysfs_id(sf_dev
->path
);
1336 " scsi device: bus = %s, bus_id = %s driver = %s\n path = %s\n",
1339 sf_dev
->driver_name
,
1343 for(hd
= hd_data
->hd
; hd
; hd
= hd
->next
) {
1345 hd
->module
== hd_data
->module
&&
1346 hd
->sysfs_device_link
&&
1347 hd
->base_class
.id
== bc_storage_device
&&
1348 hd
->sub_class
.id
== sc_sdev_tape
&&
1350 !strcmp(hd
->sysfs_device_link
, s
)
1355 hd
= add_hd_entry(hd_data
, __LINE__
, 0);
1356 hd
->base_class
.id
= bc_storage_device
;
1357 hd
->sub_class
.id
= sc_sdev_tape
;
1359 hd
->bus
.id
= bus_scsi
;
1361 hd
->sysfs_device_link
= new_str(s
);
1363 hd
->sysfs_bus_id
= new_str(sf_dev
->bus_id
);
1365 /* parent has longest matching sysfs id */
1367 for(u3
= 0, hd1
= hd_data
->hd
; hd1
; hd1
= hd1
->next
) {
1369 u1
= strlen(hd1
->sysfs_id
);
1370 if(u1
> u3
&& u1
<= u2
&& !strncmp(s
, hd1
->sysfs_id
, u1
)) {
1372 hd
->attached_to
= hd1
->idx
;
1377 /* find longest matching sysfs id we have a driver for */
1379 t
= strrchr(s
, '/');
1381 t
= hd_sysfs_find_driver(hd_data
, s
, 0);
1383 add_str_list(&hd
->drivers
, t
);
1388 sf_dev
->driver_name
&&
1389 *sf_dev
->driver_name
&&
1390 strcmp(sf_dev
->driver_name
, "unknown")
1392 add_str_list(&hd
->drivers
, sf_dev
->driver_name
);
1395 add_scsi_sysfs_info(hd_data
, hd
, sf_dev
);
1398 s
= hd_sysfs_name2_dev(sf_cdev
->name
);
1400 if(!hd
->unix_dev_name
|| strlen(s
) + sizeof "/dev/" - 1 < strlen(hd
->unix_dev_name
)) {
1401 str_printf(&hd
->unix_dev_name
, 0, "/dev/%s", s
);
1402 hd
->unix_dev_num
= dev_num
;
1403 free_mem(hd
->sysfs_id
);
1404 hd
->sysfs_id
= new_str(hd_sysfs_id(sf_cdev
->path
));
1409 sysfs_close_class(sf_class
);
1413 void get_generic_scsi_devs(hd_data_t
*hd_data
)
1416 unsigned u1
, u2
, u3
;
1419 hd_dev_num_t dev_num
;
1421 struct sysfs_class
*sf_class
;
1422 struct sysfs_class_device
*sf_cdev
;
1423 struct sysfs_device
*sf_dev
;
1424 struct dlist
*sf_cdev_list
;
1426 sf_class
= sysfs_open_class("scsi_generic");
1429 ADD2LOG("sysfs: no such class: scsi_generic\n");
1433 sf_cdev_list
= sysfs_get_class_devices(sf_class
);
1434 if(sf_cdev_list
) dlist_for_each_data(sf_cdev_list
, sf_cdev
, struct sysfs_class_device
) {
1436 " scsi: name = %s, path = %s\n",
1438 hd_sysfs_id(sf_cdev
->path
)
1441 memset(&dev_num
, 0, sizeof dev_num
);
1443 if((s
= hd_attr_str(sysfs_get_classdev_attr(sf_cdev
, "dev")))) {
1444 if(sscanf(s
, "%u:%u", &u1
, &u2
) == 2) {
1450 ADD2LOG(" dev = %u:%u\n", u1
, u2
);
1453 if(hd_attr_uint(sysfs_get_classdev_attr(sf_cdev
, "range"), &ul0
, 0)) {
1454 dev_num
.range
= ul0
;
1455 ADD2LOG(" range = %u\n", dev_num
.range
);
1458 sf_dev
= sysfs_get_classdev_device(sf_cdev
);
1460 s
= hd_sysfs_id(sf_dev
->path
);
1463 " scsi device: bus = %s, bus_id = %s driver = %s\n path = %s\n",
1466 sf_dev
->driver_name
,
1471 for(hd
= hd_data
->hd
; hd
; hd
= hd
->next
) {
1473 hd
->sysfs_device_link
&&
1474 hd
->bus
.id
== bus_scsi
&&
1476 !strcmp(hd
->sysfs_device_link
, s
)
1481 if(!hd
->unix_dev_name2
) {
1482 str_printf(&hd
->unix_dev_name2
, 0, "/dev/%s", hd_sysfs_name2_dev(sf_cdev
->name
));
1483 hd
->unix_dev_num2
= dev_num
;
1491 sf_dev
->driver_name
&&
1492 !strcmp(sf_dev
->driver_name
, "unknown")
1494 hd
= add_hd_entry(hd_data
, __LINE__
, 0);
1495 hd
->base_class
.id
= bc_storage_device
;
1496 hd
->sub_class
.id
= sc_sdev_other
;
1498 str_printf(&hd
->unix_dev_name
, 0, "/dev/%s", hd_sysfs_name2_dev(sf_cdev
->name
));
1500 hd
->bus
.id
= bus_scsi
;
1502 hd
->sysfs_id
= new_str(hd_sysfs_id(sf_cdev
->path
));
1504 hd
->unix_dev_num
= dev_num
;
1506 if(sf_dev
) hd
->sysfs_bus_id
= new_str(sf_dev
->bus_id
);
1508 if(sf_dev
&& (s
= hd_sysfs_id(sf_dev
->path
))) {
1510 /* parent has longest matching sysfs id */
1512 for(u3
= 0, hd1
= hd_data
->hd
; hd1
; hd1
= hd1
->next
) {
1514 u1
= strlen(hd1
->sysfs_id
);
1515 if(u1
> u3
&& u1
<= u2
&& !strncmp(s
, hd1
->sysfs_id
, u1
)) {
1517 hd
->attached_to
= hd1
->idx
;
1522 /* find longest matching sysfs id we have a driver for */
1524 t
= strrchr(s
, '/');
1526 t
= hd_sysfs_find_driver(hd_data
, s
, 0);
1528 add_str_list(&hd
->drivers
, t
);
1534 add_scsi_sysfs_info(hd_data
, hd
, sf_dev
);
1540 sysfs_close_class(sf_class
);
1544 void add_disk_size(hd_data_t
*hd_data
, hd_t
*hd
)
1546 hd_res_t
*geo
, *size
;
1553 hd
->unix_dev_name
&&
1554 hd
->sub_class
.id
== sc_sdev_disk
1556 PROGRESS(5, 0, hd
->unix_dev_name
);
1557 fd
= open(hd
->unix_dev_name
, O_RDONLY
| O_NONBLOCK
);
1560 str_printf(&pr_str
, 0, "%s geo", hd
->unix_dev_name
);
1561 PROGRESS(5, 1, pr_str
);
1563 if(hd_getdisksize(hd_data
, hd
->unix_dev_name
, fd
, &geo
, &size
) == 1) {
1564 /* (low-level) unformatted disk */
1565 hd
->is
.notready
= 1;
1568 if(geo
) add_res_entry(&hd
->res
, geo
);
1569 if(size
) add_res_entry(&hd
->res
, size
);
1575 pr_str
= free_mem(pr_str
);