17c478bd9Sstevel@tonic-gate /* bios.c - implement C part of low-level BIOS disk input and output */
27c478bd9Sstevel@tonic-gate /*
37c478bd9Sstevel@tonic-gate * GRUB -- GRand Unified Bootloader
47c478bd9Sstevel@tonic-gate * Copyright (C) 1999,2000,2003,2004 Free Software Foundation, Inc.
57c478bd9Sstevel@tonic-gate *
67c478bd9Sstevel@tonic-gate * This program is free software; you can redistribute it and/or modify
77c478bd9Sstevel@tonic-gate * it under the terms of the GNU General Public License as published by
87c478bd9Sstevel@tonic-gate * the Free Software Foundation; either version 2 of the License, or
97c478bd9Sstevel@tonic-gate * (at your option) any later version.
107c478bd9Sstevel@tonic-gate *
117c478bd9Sstevel@tonic-gate * This program is distributed in the hope that it will be useful,
127c478bd9Sstevel@tonic-gate * but WITHOUT ANY WARRANTY; without even the implied warranty of
137c478bd9Sstevel@tonic-gate * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
147c478bd9Sstevel@tonic-gate * GNU General Public License for more details.
157c478bd9Sstevel@tonic-gate *
167c478bd9Sstevel@tonic-gate * You should have received a copy of the GNU General Public License
177c478bd9Sstevel@tonic-gate * along with this program; if not, write to the Free Software
187c478bd9Sstevel@tonic-gate * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
197c478bd9Sstevel@tonic-gate */
209890706eSHans Rosenfeld /*
219890706eSHans Rosenfeld * Copyright 2016 Nexenta Systems, Inc.
229890706eSHans Rosenfeld */
237c478bd9Sstevel@tonic-gate
247c478bd9Sstevel@tonic-gate #include "shared.h"
257c478bd9Sstevel@tonic-gate
267c478bd9Sstevel@tonic-gate
277c478bd9Sstevel@tonic-gate /* These are defined in asm.S, and never be used elsewhere, so declare the
287c478bd9Sstevel@tonic-gate prototypes here. */
297c478bd9Sstevel@tonic-gate extern int biosdisk_int13_extensions (int ax, int drive, void *dap);
307c478bd9Sstevel@tonic-gate extern int biosdisk_standard (int ah, int drive,
317c478bd9Sstevel@tonic-gate int coff, int hoff, int soff,
327c478bd9Sstevel@tonic-gate int nsec, int segment);
337c478bd9Sstevel@tonic-gate extern int check_int13_extensions (int drive);
347c478bd9Sstevel@tonic-gate extern int get_diskinfo_standard (int drive,
357c478bd9Sstevel@tonic-gate unsigned long *cylinders,
367c478bd9Sstevel@tonic-gate unsigned long *heads,
377c478bd9Sstevel@tonic-gate unsigned long *sectors);
387c478bd9Sstevel@tonic-gate #if 0
397c478bd9Sstevel@tonic-gate extern int get_diskinfo_floppy (int drive,
407c478bd9Sstevel@tonic-gate unsigned long *cylinders,
417c478bd9Sstevel@tonic-gate unsigned long *heads,
427c478bd9Sstevel@tonic-gate unsigned long *sectors);
437c478bd9Sstevel@tonic-gate #endif
447c478bd9Sstevel@tonic-gate
457c478bd9Sstevel@tonic-gate
467c478bd9Sstevel@tonic-gate /* Read/write NSEC sectors starting from SECTOR in DRIVE disk with GEOMETRY
477c478bd9Sstevel@tonic-gate from/into SEGMENT segment. If READ is BIOSDISK_READ, then read it,
487c478bd9Sstevel@tonic-gate else if READ is BIOSDISK_WRITE, then write it. If an geometry error
497c478bd9Sstevel@tonic-gate occurs, return BIOSDISK_ERROR_GEOMETRY, and if other error occurs, then
507c478bd9Sstevel@tonic-gate return the error number. Otherwise, return 0. */
517c478bd9Sstevel@tonic-gate int
biosdisk(int read,int drive,struct geometry * geometry,unsigned long long sector,int nsec,int segment)527c478bd9Sstevel@tonic-gate biosdisk (int read, int drive, struct geometry *geometry,
539890706eSHans Rosenfeld unsigned long long sector, int nsec, int segment)
547c478bd9Sstevel@tonic-gate {
55342440ecSPrasad Singamsetty
567c478bd9Sstevel@tonic-gate int err;
577c478bd9Sstevel@tonic-gate
587c478bd9Sstevel@tonic-gate if (geometry->flags & BIOSDISK_FLAG_LBA_EXTENSION)
597c478bd9Sstevel@tonic-gate {
607c478bd9Sstevel@tonic-gate struct disk_address_packet
617c478bd9Sstevel@tonic-gate {
627c478bd9Sstevel@tonic-gate unsigned char length;
637c478bd9Sstevel@tonic-gate unsigned char reserved;
647c478bd9Sstevel@tonic-gate unsigned short blocks;
657c478bd9Sstevel@tonic-gate unsigned long buffer;
667c478bd9Sstevel@tonic-gate unsigned long long block;
677c478bd9Sstevel@tonic-gate } __attribute__ ((packed)) dap;
687c478bd9Sstevel@tonic-gate
697c478bd9Sstevel@tonic-gate /* XXX: Don't check the geometry by default, because some buggy
707c478bd9Sstevel@tonic-gate BIOSes don't return the number of total sectors correctly,
717c478bd9Sstevel@tonic-gate even if they have working LBA support. Hell. */
727c478bd9Sstevel@tonic-gate #ifdef NO_BUGGY_BIOS_IN_THE_WORLD
737c478bd9Sstevel@tonic-gate if (sector >= geometry->total_sectors)
747c478bd9Sstevel@tonic-gate return BIOSDISK_ERROR_GEOMETRY;
757c478bd9Sstevel@tonic-gate #endif /* NO_BUGGY_BIOS_IN_THE_WORLD */
767c478bd9Sstevel@tonic-gate
777c478bd9Sstevel@tonic-gate /* FIXME: sizeof (DAP) must be 0x10. Should assert that the compiler
787c478bd9Sstevel@tonic-gate can't add any padding. */
797c478bd9Sstevel@tonic-gate dap.length = sizeof (dap);
807c478bd9Sstevel@tonic-gate dap.block = sector;
817c478bd9Sstevel@tonic-gate dap.blocks = nsec;
827c478bd9Sstevel@tonic-gate dap.reserved = 0;
837c478bd9Sstevel@tonic-gate /* This is undocumented part. The address is formated in
847c478bd9Sstevel@tonic-gate SEGMENT:ADDRESS. */
857c478bd9Sstevel@tonic-gate dap.buffer = segment << 16;
867c478bd9Sstevel@tonic-gate err = biosdisk_int13_extensions ((read + 0x42) << 8, drive, &dap);
879caa1482Sszhou /*
889caa1482Sszhou * Try to report errors upwards when the bios has read only part of
899caa1482Sszhou * the requested buffer, but didn't return an error code.
909caa1482Sszhou */
919caa1482Sszhou if (err == 0 && dap.blocks != nsec)
929caa1482Sszhou err = BIOSDISK_ERROR_SHORT_IO;
937c478bd9Sstevel@tonic-gate
947c478bd9Sstevel@tonic-gate /* #undef NO_INT13_FALLBACK */
957c478bd9Sstevel@tonic-gate #ifndef NO_INT13_FALLBACK
967c478bd9Sstevel@tonic-gate if (err)
977c478bd9Sstevel@tonic-gate {
987c478bd9Sstevel@tonic-gate if (geometry->flags & BIOSDISK_FLAG_CDROM)
997c478bd9Sstevel@tonic-gate return err;
1007c478bd9Sstevel@tonic-gate
1017c478bd9Sstevel@tonic-gate geometry->flags &= ~BIOSDISK_FLAG_LBA_EXTENSION;
102828d47c1SShidokht Yadegari geometry->total_sectors = ((unsigned long long)geometry->cylinders
1037c478bd9Sstevel@tonic-gate * geometry->heads
1047c478bd9Sstevel@tonic-gate * geometry->sectors);
1057c478bd9Sstevel@tonic-gate return biosdisk (read, drive, geometry, sector, nsec, segment);
1067c478bd9Sstevel@tonic-gate }
1077c478bd9Sstevel@tonic-gate #endif /* ! NO_INT13_FALLBACK */
1087c478bd9Sstevel@tonic-gate
1097c478bd9Sstevel@tonic-gate }
1107c478bd9Sstevel@tonic-gate else
1117c478bd9Sstevel@tonic-gate {
1127c478bd9Sstevel@tonic-gate int cylinder_offset, head_offset, sector_offset;
1137c478bd9Sstevel@tonic-gate int head;
1147c478bd9Sstevel@tonic-gate /* SECTOR_OFFSET is counted from one, while HEAD_OFFSET and
1157c478bd9Sstevel@tonic-gate CYLINDER_OFFSET are counted from zero. */
1167c478bd9Sstevel@tonic-gate sector_offset = sector % geometry->sectors + 1;
1177c478bd9Sstevel@tonic-gate head = sector / geometry->sectors;
1187c478bd9Sstevel@tonic-gate head_offset = head % geometry->heads;
1197c478bd9Sstevel@tonic-gate cylinder_offset = head / geometry->heads;
1207c478bd9Sstevel@tonic-gate
1217c478bd9Sstevel@tonic-gate if (cylinder_offset >= geometry->cylinders)
1227c478bd9Sstevel@tonic-gate return BIOSDISK_ERROR_GEOMETRY;
1237c478bd9Sstevel@tonic-gate
1247c478bd9Sstevel@tonic-gate err = biosdisk_standard (read + 0x02, drive,
1257c478bd9Sstevel@tonic-gate cylinder_offset, head_offset, sector_offset,
1267c478bd9Sstevel@tonic-gate nsec, segment);
1277c478bd9Sstevel@tonic-gate }
1287c478bd9Sstevel@tonic-gate
1297c478bd9Sstevel@tonic-gate return err;
1307c478bd9Sstevel@tonic-gate }
1317c478bd9Sstevel@tonic-gate
1327c478bd9Sstevel@tonic-gate /* Check bootable CD-ROM emulation status. */
1337c478bd9Sstevel@tonic-gate static int
get_cdinfo(int drive,struct geometry * geometry)1347c478bd9Sstevel@tonic-gate get_cdinfo (int drive, struct geometry *geometry)
1357c478bd9Sstevel@tonic-gate {
1367c478bd9Sstevel@tonic-gate int err;
1377c478bd9Sstevel@tonic-gate struct iso_spec_packet
1387c478bd9Sstevel@tonic-gate {
1397c478bd9Sstevel@tonic-gate unsigned char size;
1407c478bd9Sstevel@tonic-gate unsigned char media_type;
1417c478bd9Sstevel@tonic-gate unsigned char drive_no;
1427c478bd9Sstevel@tonic-gate unsigned char controller_no;
1437c478bd9Sstevel@tonic-gate unsigned long image_lba;
1447c478bd9Sstevel@tonic-gate unsigned short device_spec;
1457c478bd9Sstevel@tonic-gate unsigned short cache_seg;
1467c478bd9Sstevel@tonic-gate unsigned short load_seg;
1477c478bd9Sstevel@tonic-gate unsigned short length_sec512;
1487c478bd9Sstevel@tonic-gate unsigned char cylinders;
1497c478bd9Sstevel@tonic-gate unsigned char sectors;
1507c478bd9Sstevel@tonic-gate unsigned char heads;
1517c478bd9Sstevel@tonic-gate
1527c478bd9Sstevel@tonic-gate unsigned char dummy[16];
1537c478bd9Sstevel@tonic-gate } __attribute__ ((packed)) cdrp;
1547c478bd9Sstevel@tonic-gate
1557c478bd9Sstevel@tonic-gate grub_memset (&cdrp, 0, sizeof (cdrp));
1567c478bd9Sstevel@tonic-gate cdrp.size = sizeof (cdrp) - sizeof (cdrp.dummy);
1577c478bd9Sstevel@tonic-gate err = biosdisk_int13_extensions (0x4B01, drive, &cdrp);
1587c478bd9Sstevel@tonic-gate if (! err && cdrp.drive_no == drive)
1597c478bd9Sstevel@tonic-gate {
1607c478bd9Sstevel@tonic-gate if ((cdrp.media_type & 0x0F) == 0)
1617c478bd9Sstevel@tonic-gate {
1627c478bd9Sstevel@tonic-gate /* No emulation bootable CD-ROM */
1637c478bd9Sstevel@tonic-gate geometry->flags = BIOSDISK_FLAG_LBA_EXTENSION | BIOSDISK_FLAG_CDROM;
1647c478bd9Sstevel@tonic-gate geometry->cylinders = 0;
1657c478bd9Sstevel@tonic-gate geometry->heads = 1;
1667c478bd9Sstevel@tonic-gate geometry->sectors = 15;
1677c478bd9Sstevel@tonic-gate geometry->sector_size = 2048;
16898c507c4SJan Setje-Eilers geometry->total_sectors = MAXUINT;
1697c478bd9Sstevel@tonic-gate return 1;
1707c478bd9Sstevel@tonic-gate }
1717c478bd9Sstevel@tonic-gate else
1727c478bd9Sstevel@tonic-gate {
1737c478bd9Sstevel@tonic-gate /* Floppy or hard-disk emulation */
1747c478bd9Sstevel@tonic-gate geometry->cylinders
1757c478bd9Sstevel@tonic-gate = ((unsigned int) cdrp.cylinders
1767c478bd9Sstevel@tonic-gate + (((unsigned int) (cdrp.sectors & 0xC0)) << 2));
1777c478bd9Sstevel@tonic-gate geometry->heads = cdrp.heads;
1787c478bd9Sstevel@tonic-gate geometry->sectors = cdrp.sectors & 0x3F;
1797c478bd9Sstevel@tonic-gate geometry->sector_size = SECTOR_SIZE;
180828d47c1SShidokht Yadegari geometry->total_sectors = ((unsigned long long)geometry->cylinders
1817c478bd9Sstevel@tonic-gate * geometry->heads
1827c478bd9Sstevel@tonic-gate * geometry->sectors);
1837c478bd9Sstevel@tonic-gate return -1;
1847c478bd9Sstevel@tonic-gate }
1857c478bd9Sstevel@tonic-gate }
1867c478bd9Sstevel@tonic-gate
1877c478bd9Sstevel@tonic-gate /*
1887c478bd9Sstevel@tonic-gate * If this is the boot_drive, default to non-emulation bootable CD-ROM.
1897c478bd9Sstevel@tonic-gate *
1907c478bd9Sstevel@tonic-gate * Some BIOS (Tecra S1) fails the int13 call above. If we return
1917c478bd9Sstevel@tonic-gate * failure here, GRUB will run, but cannot see the boot drive,
1927c478bd9Sstevel@tonic-gate * not a very good situation. Defaulting to non-emulation mode
1937c478bd9Sstevel@tonic-gate * is a last-ditch effort.
1947c478bd9Sstevel@tonic-gate */
1957c478bd9Sstevel@tonic-gate if (drive >= 0x88 && drive == boot_drive)
1967c478bd9Sstevel@tonic-gate {
1977c478bd9Sstevel@tonic-gate geometry->flags = BIOSDISK_FLAG_LBA_EXTENSION | BIOSDISK_FLAG_CDROM;
1987c478bd9Sstevel@tonic-gate geometry->cylinders = 0;
1997c478bd9Sstevel@tonic-gate geometry->heads = 1;
2007c478bd9Sstevel@tonic-gate geometry->sectors = 15;
2017c478bd9Sstevel@tonic-gate geometry->sector_size = 2048;
20298c507c4SJan Setje-Eilers geometry->total_sectors = MAXUINT;
2037c478bd9Sstevel@tonic-gate return 1;
2047c478bd9Sstevel@tonic-gate }
2057c478bd9Sstevel@tonic-gate return 0;
2067c478bd9Sstevel@tonic-gate }
2077c478bd9Sstevel@tonic-gate
2087c478bd9Sstevel@tonic-gate /* Return the geometry of DRIVE in GEOMETRY. If an error occurs, return
2097c478bd9Sstevel@tonic-gate non-zero, otherwise zero. */
2107c478bd9Sstevel@tonic-gate int
get_diskinfo(int drive,struct geometry * geometry)2117c478bd9Sstevel@tonic-gate get_diskinfo (int drive, struct geometry *geometry)
2127c478bd9Sstevel@tonic-gate {
2137c478bd9Sstevel@tonic-gate int err;
214*2f7f7a62SAlex Wilson int gotchs = 0;
2157c478bd9Sstevel@tonic-gate
2167c478bd9Sstevel@tonic-gate /* Clear the flags. */
2177c478bd9Sstevel@tonic-gate geometry->flags = 0;
2187c478bd9Sstevel@tonic-gate
2197c478bd9Sstevel@tonic-gate if (drive & 0x80)
2207c478bd9Sstevel@tonic-gate {
2217c478bd9Sstevel@tonic-gate /* hard disk or CD-ROM */
2227c478bd9Sstevel@tonic-gate int version;
223828d47c1SShidokht Yadegari unsigned long long total_sectors = 0;
2247c478bd9Sstevel@tonic-gate
2257c478bd9Sstevel@tonic-gate version = check_int13_extensions (drive);
2267c478bd9Sstevel@tonic-gate
2277c478bd9Sstevel@tonic-gate if (drive >= 0x88 || version)
2287c478bd9Sstevel@tonic-gate {
2297c478bd9Sstevel@tonic-gate /* Possible CD-ROM - check the status. */
2307c478bd9Sstevel@tonic-gate if (get_cdinfo (drive, geometry))
2317c478bd9Sstevel@tonic-gate return 0;
2327c478bd9Sstevel@tonic-gate }
233*2f7f7a62SAlex Wilson
234*2f7f7a62SAlex Wilson /* Don't pass GEOMETRY directly, but pass each element instead,
235*2f7f7a62SAlex Wilson so that we can change the structure easily. */
236*2f7f7a62SAlex Wilson err = get_diskinfo_standard (drive,
237*2f7f7a62SAlex Wilson &geometry->cylinders,
238*2f7f7a62SAlex Wilson &geometry->heads,
239*2f7f7a62SAlex Wilson &geometry->sectors);
240*2f7f7a62SAlex Wilson if (err == 0)
241*2f7f7a62SAlex Wilson gotchs = 1;
242*2f7f7a62SAlex Wilson /* get_diskinfo_standard returns 0x60 if the BIOS call actually
243*2f7f7a62SAlex Wilson succeeded but returned 0 sectors -- in this case don't
244*2f7f7a62SAlex Wilson return yet but continue to check the LBA geom */
245*2f7f7a62SAlex Wilson else if (err != 0x60)
246*2f7f7a62SAlex Wilson return err;
2477c478bd9Sstevel@tonic-gate
2487c478bd9Sstevel@tonic-gate if (version)
2497c478bd9Sstevel@tonic-gate {
2507c478bd9Sstevel@tonic-gate struct drive_parameters
2517c478bd9Sstevel@tonic-gate {
2527c478bd9Sstevel@tonic-gate unsigned short size;
2537c478bd9Sstevel@tonic-gate unsigned short flags;
2547c478bd9Sstevel@tonic-gate unsigned long cylinders;
2557c478bd9Sstevel@tonic-gate unsigned long heads;
2567c478bd9Sstevel@tonic-gate unsigned long sectors;
2577c478bd9Sstevel@tonic-gate unsigned long long total_sectors;
2587c478bd9Sstevel@tonic-gate unsigned short bytes_per_sector;
2597c478bd9Sstevel@tonic-gate /* ver 2.0 or higher */
2607c478bd9Sstevel@tonic-gate unsigned long EDD_configuration_parameters;
2617c478bd9Sstevel@tonic-gate /* ver 3.0 or higher */
2627c478bd9Sstevel@tonic-gate unsigned short signature_dpi;
2637c478bd9Sstevel@tonic-gate unsigned char length_dpi;
2647c478bd9Sstevel@tonic-gate unsigned char reserved[3];
2657c478bd9Sstevel@tonic-gate unsigned char name_of_host_bus[4];
2667c478bd9Sstevel@tonic-gate unsigned char name_of_interface_type[8];
2677c478bd9Sstevel@tonic-gate unsigned char interface_path[8];
2687c478bd9Sstevel@tonic-gate unsigned char device_path[8];
2697c478bd9Sstevel@tonic-gate unsigned char reserved2;
2707c478bd9Sstevel@tonic-gate unsigned char checksum;
2717c478bd9Sstevel@tonic-gate
2727c478bd9Sstevel@tonic-gate /* XXX: This is necessary, because the BIOS of Thinkpad X20
2737c478bd9Sstevel@tonic-gate writes a garbage to the tail of drive parameters,
2747c478bd9Sstevel@tonic-gate regardless of a size specified in a caller. */
2757c478bd9Sstevel@tonic-gate unsigned char dummy[16];
2767c478bd9Sstevel@tonic-gate } __attribute__ ((packed)) drp;
2777c478bd9Sstevel@tonic-gate
2787c478bd9Sstevel@tonic-gate /* It is safe to clear out DRP. */
2797c478bd9Sstevel@tonic-gate grub_memset (&drp, 0, sizeof (drp));
2807c478bd9Sstevel@tonic-gate
2817c478bd9Sstevel@tonic-gate /* PhoenixBIOS 4.0 Revision 6.0 for ZF Micro might understand
2827c478bd9Sstevel@tonic-gate the greater buffer size for the "get drive parameters" int
2837c478bd9Sstevel@tonic-gate 0x13 call in its own way. Supposedly the BIOS assumes even
2847c478bd9Sstevel@tonic-gate bigger space is available and thus corrupts the stack.
2857c478bd9Sstevel@tonic-gate This is why we specify the exactly necessary size of 0x42
2867c478bd9Sstevel@tonic-gate bytes. */
2877c478bd9Sstevel@tonic-gate drp.size = sizeof (drp) - sizeof (drp.dummy);
2887c478bd9Sstevel@tonic-gate
2897c478bd9Sstevel@tonic-gate err = biosdisk_int13_extensions (0x4800, drive, &drp);
2907c478bd9Sstevel@tonic-gate if (! err)
2917c478bd9Sstevel@tonic-gate {
2927c478bd9Sstevel@tonic-gate /* Set the LBA flag. */
2937c478bd9Sstevel@tonic-gate geometry->flags = BIOSDISK_FLAG_LBA_EXTENSION;
2947c478bd9Sstevel@tonic-gate
2957c478bd9Sstevel@tonic-gate /* I'm not sure if GRUB should check the bit 1 of DRP.FLAGS,
2967c478bd9Sstevel@tonic-gate so I omit the check for now. - okuji */
2977c478bd9Sstevel@tonic-gate /* if (drp.flags & (1 << 1)) */
298*2f7f7a62SAlex Wilson
299*2f7f7a62SAlex Wilson /* If we didn't get valid CHS info from the standard call,
300*2f7f7a62SAlex Wilson then we should fill it out here */
301*2f7f7a62SAlex Wilson if (! gotchs)
302*2f7f7a62SAlex Wilson {
303*2f7f7a62SAlex Wilson geometry->cylinders = drp.cylinders;
304*2f7f7a62SAlex Wilson
305*2f7f7a62SAlex Wilson if (drp.sectors > 0 && drp.heads > 0)
306*2f7f7a62SAlex Wilson {
307*2f7f7a62SAlex Wilson geometry->heads = drp.heads;
308*2f7f7a62SAlex Wilson geometry->sectors = drp.sectors;
309*2f7f7a62SAlex Wilson }
310*2f7f7a62SAlex Wilson else
311*2f7f7a62SAlex Wilson {
312*2f7f7a62SAlex Wilson /* Return fake geometry. This disk reports that it
313*2f7f7a62SAlex Wilson supports LBA, so all the other routines will use LBA
314*2f7f7a62SAlex Wilson to talk to it and not look at this geometry. However,
315*2f7f7a62SAlex Wilson some of the partition-finding routines still need
316*2f7f7a62SAlex Wilson non-zero values in these fields. */
317*2f7f7a62SAlex Wilson geometry->heads = 16;
318*2f7f7a62SAlex Wilson geometry->sectors = 63;
319*2f7f7a62SAlex Wilson }
320*2f7f7a62SAlex Wilson gotchs = 1;
321*2f7f7a62SAlex Wilson }
3227c478bd9Sstevel@tonic-gate
3237c478bd9Sstevel@tonic-gate if (drp.total_sectors)
324828d47c1SShidokht Yadegari total_sectors = drp.total_sectors;
3257c478bd9Sstevel@tonic-gate else
3267c478bd9Sstevel@tonic-gate /* Some buggy BIOSes doesn't return the total sectors
3277c478bd9Sstevel@tonic-gate correctly but returns zero. So if it is zero, compute
3287c478bd9Sstevel@tonic-gate it by C/H/S returned by the LBA BIOS call. */
329828d47c1SShidokht Yadegari total_sectors = (unsigned long long)drp.cylinders *
330828d47c1SShidokht Yadegari drp.heads * drp.sectors;
3317c478bd9Sstevel@tonic-gate }
3327c478bd9Sstevel@tonic-gate }
3337c478bd9Sstevel@tonic-gate
334*2f7f7a62SAlex Wilson /* In case we got the 0x60 return code from _standard on a disk that
335*2f7f7a62SAlex Wilson didn't support LBA (or was somehow invalid), return that error now */
336*2f7f7a62SAlex Wilson if (! gotchs)
337*2f7f7a62SAlex Wilson return 0x60;
3387c478bd9Sstevel@tonic-gate
3397c478bd9Sstevel@tonic-gate if (! total_sectors)
3407c478bd9Sstevel@tonic-gate {
341828d47c1SShidokht Yadegari total_sectors = ((unsigned long long)geometry->cylinders
3427c478bd9Sstevel@tonic-gate * geometry->heads
3437c478bd9Sstevel@tonic-gate * geometry->sectors);
3447c478bd9Sstevel@tonic-gate }
3457c478bd9Sstevel@tonic-gate geometry->total_sectors = total_sectors;
3467c478bd9Sstevel@tonic-gate geometry->sector_size = SECTOR_SIZE;
3477c478bd9Sstevel@tonic-gate }
3487c478bd9Sstevel@tonic-gate else
3497c478bd9Sstevel@tonic-gate {
3507c478bd9Sstevel@tonic-gate /* floppy disk */
3517c478bd9Sstevel@tonic-gate
3527c478bd9Sstevel@tonic-gate /* First, try INT 13 AH=8h call. */
3537c478bd9Sstevel@tonic-gate err = get_diskinfo_standard (drive,
3547c478bd9Sstevel@tonic-gate &geometry->cylinders,
3557c478bd9Sstevel@tonic-gate &geometry->heads,
3567c478bd9Sstevel@tonic-gate &geometry->sectors);
3577c478bd9Sstevel@tonic-gate
3587c478bd9Sstevel@tonic-gate #if 0
3597c478bd9Sstevel@tonic-gate /* If fails, then try floppy-specific probe routine. */
3607c478bd9Sstevel@tonic-gate if (err)
3617c478bd9Sstevel@tonic-gate err = get_diskinfo_floppy (drive,
3627c478bd9Sstevel@tonic-gate &geometry->cylinders,
3637c478bd9Sstevel@tonic-gate &geometry->heads,
3647c478bd9Sstevel@tonic-gate &geometry->sectors);
3657c478bd9Sstevel@tonic-gate #endif
3667c478bd9Sstevel@tonic-gate
3677c478bd9Sstevel@tonic-gate if (err)
3687c478bd9Sstevel@tonic-gate return err;
3697c478bd9Sstevel@tonic-gate
370828d47c1SShidokht Yadegari geometry->total_sectors = ((unsigned long long)geometry->cylinders
3717c478bd9Sstevel@tonic-gate * geometry->heads
3727c478bd9Sstevel@tonic-gate * geometry->sectors);
3737c478bd9Sstevel@tonic-gate geometry->sector_size = SECTOR_SIZE;
3747c478bd9Sstevel@tonic-gate }
3757c478bd9Sstevel@tonic-gate
3767c478bd9Sstevel@tonic-gate return 0;
3777c478bd9Sstevel@tonic-gate }
378