On Fri, Mar 7, 2008 at 11:37 PM, Vesa Jääskeläinen <[EMAIL PROTECTED]> wrote:
>
> Bean wrote:
>  > Hi,
>  >
>  > This patch use int 13 func 4B01 to detect cdrom. It also change the
>  > name of the cd device to (hdN), where N is the bios drive number.
>
>  Hi Bean,
>
>  Have you tried to use EDD's functions to query for type of device?
>  (references are to EDD3 spec)
>
>  8.24 Get Device Parameters (FN 48h)
>  26 DWord Pointer to the Device Parameter Table Extension (DPTE)
>
>  8.24.3 Device Parameter Table Extension (DPTE)
>  10-11 Word BIOS selected hardware specific option flags
>
>  Bits 5 and 6; Removable device, ATAPI device.
>
>  This FN 48h can also be used to filter out PCI cards from ATA driver in
>  case there is BIOS support for the device already. So use BIOS if there
>  is BIOS handler for it, otherwise fall back to ATA driver.
>
>  I would prefer that CD's would be counted like (cd0) for first CD-ROM
>  device, (cd1) for second CD-ROM device, ... and so on. I think it is OK
>  to first allocate BIOS devices for CD's and after that use ATA driver
>  for rest of them. Ata driver can of course be accessed with ata name too.

Hi,

after some consideration, i think the best way to detect cdrom is to
check the number of bytes per sector. The handling of cdrom assume
sector size of 4096, cdrom that has other block size would not work.
On the other hand, the device don't even needs to be cdrom, as long as
it has 2048 sector size, the current handling works. Therefore,
checking sector size should be sufficient.

As for the device name, there are some drawbacks by using (cdN), in
init.c, we need to get the root device from bios drive number.
However, as Christian Franke discovers, the drive number can be:

0x82 (old Toshiba Laptop with unknown BIOS)
0x9f (PC with Phoenix-Award BIOS, VMware)
0xe0 (VirtualBox)
0xef (PC with AMI BIOS, VirtualPC)

It' quite tricky to determine whether a drive is cdrom or harddisk.

And in the multiboot loader, we need to do the oppisite, map the root
device to bios drive number. As names like (cd0) doesn't suggests the
number at all, we need to ask biosdisk for the number. Therefore,
multiboot loader will be depended on biosdisk, which is not a good
idea.

-- 
Bean
diff --git a/disk/i386/pc/biosdisk.c b/disk/i386/pc/biosdisk.c
index ddcc666..3efe7cb 100644
--- a/disk/i386/pc/biosdisk.c
+++ b/disk/i386/pc/biosdisk.c
@@ -18,6 +18,7 @@
 
 #include <grub/machine/biosdisk.h>
 #include <grub/machine/memory.h>
+#include <grub/machine/kernel.h>
 #include <grub/disk.h>
 #include <grub/dl.h>
 #include <grub/mm.h>
@@ -26,15 +27,12 @@
 #include <grub/err.h>
 #include <grub/term.h>
 
-static int cd_start = GRUB_BIOSDISK_MACHINE_CDROM_START;
-static int cd_count = 0;
-
 static int
 grub_biosdisk_get_drive (const char *name)
 {
   unsigned long drive;
 
-  if ((name[0] != 'f' && name[0] != 'h' && name[0] != 'c') || name[1] != 'd')
+  if ((name[0] != 'f' && name[0] != 'h') || name[1] != 'd')
     goto fail;
     
   drive = grub_strtoul (name + 2, 0, 10);
@@ -43,8 +41,6 @@ grub_biosdisk_get_drive (const char *name)
 
   if (name[0] == 'h')
     drive += 0x80;
-  else if (name[0] == 'c')
-    drive += cd_start;
   
   return (int) drive ;
 
@@ -58,10 +54,7 @@ grub_biosdisk_call_hook (int (*hook) (const char *name), int 
drive)
 {
   char name[10];
 
-  if (drive >= cd_start)
-    grub_sprintf (name, "cd%d", drive - cd_start);
-  else
-    grub_sprintf (name, (drive & 0x80) ? "hd%d" : "fd%d", drive & (~0x80));
+  grub_sprintf (name, (drive & 0x80) ? "hd%d" : "fd%d", drive & (~0x80));
   return hook (name);
 }
 
@@ -78,7 +71,8 @@ grub_biosdisk_iterate (int (*hook) (const char *name))
       return 1;
   
   /* For hard disks, attempt to read the MBR.  */
-  for (drive = 0x80; drive < 0x90; drive++)
+  for (drive = 0x80;
+       drive < GRUB_BIOSDISK_MACHINE_CDROM_START;  drive++)
     {
       if (grub_biosdisk_rw_standard (0x02, drive, 0, 0, 1, 1,
                                     GRUB_MEMORY_MACHINE_SCRATCH_SEG) != 0)
@@ -91,9 +85,30 @@ grub_biosdisk_iterate (int (*hook) (const char *name))
        return 1;
     }
 
-  for (drive = cd_start; drive < cd_start + cd_count; drive++)
-    if (grub_biosdisk_call_hook (hook, drive))
-      return 1;
+  if (grub_boot_drive >= GRUB_BIOSDISK_MACHINE_CDROM_START)
+    for (drive = grub_boot_drive;
+         drive < GRUB_BIOSDISK_MACHINE_CDROM_END; drive++)
+      {
+        struct grub_biosdisk_dap *dap;
+
+        dap = (struct grub_biosdisk_dap *) (GRUB_MEMORY_MACHINE_SCRATCH_ADDR
+                                            + (4 << GRUB_DISK_SECTOR_BITS));
+
+        dap->length = sizeof (*dap);
+        dap->reserved = 0;
+        dap->blocks = 1;
+        dap->buffer = GRUB_MEMORY_MACHINE_SCRATCH_SEG << 16;
+        dap->block = 0;
+
+        if (grub_biosdisk_rw_int13_extensions (0x42, drive, dap))
+          {
+            grub_dprintf ("disk", "Read error when probing cd 0x%2x\n", drive);
+            break;
+          }
+
+        if (grub_biosdisk_call_hook (hook, drive))
+          return 1;
+      }
 
   return 0;
 }
@@ -109,7 +124,7 @@ grub_biosdisk_open (const char *name, grub_disk_t disk)
   if (drive < 0)
     return grub_errno;
 
-  disk->has_partitions = ((drive & 0x80) && (drive < cd_start));
+  disk->has_partitions = ((drive & 0x80) != 0);
   disk->id = drive;
   
   data = (struct grub_biosdisk_data *) grub_malloc (sizeof (*data));
@@ -119,42 +134,43 @@ grub_biosdisk_open (const char *name, grub_disk_t disk)
   data->drive = drive;
   data->flags = 0;
 
-  if (drive >= cd_start)
-    {
-      data->flags = GRUB_BIOSDISK_FLAG_LBA | GRUB_BIOSDISK_FLAG_CDROM;
-      data->sectors = 32;
-      total_sectors = 9000000;  /* TODO: get the correct size.  */
-    }
-  else if (drive & 0x80)
+  if (drive & 0x80)
     {
       /* HDD */
       int version;
       
       version = grub_biosdisk_check_int13_extensions (drive);
       if (version)
-       {
-         struct grub_biosdisk_drp *drp
-           = (struct grub_biosdisk_drp *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR;
-
-         /* Clear out the DRP.  */
-         grub_memset (drp, 0, sizeof (*drp));
-         drp->size = sizeof (*drp);
-         if (! grub_biosdisk_get_diskinfo_int13_extensions (drive, drp))
-           {
-             data->flags = GRUB_BIOSDISK_FLAG_LBA;
-
-             if (drp->total_sectors)
-               total_sectors = drp->total_sectors;
-             else
+        {
+          struct grub_biosdisk_drp *drp
+                = (struct grub_biosdisk_drp *) 
GRUB_MEMORY_MACHINE_SCRATCH_ADDR;
+
+          /* Clear out the DRP.  */
+          grub_memset (drp, 0, sizeof (*drp));
+          drp->size = sizeof (*drp);
+          if (! grub_biosdisk_get_diskinfo_int13_extensions (drive, drp))
+            {
+              data->flags = GRUB_BIOSDISK_FLAG_LBA;
+
+              if (drp->total_sectors)
+                total_sectors = drp->total_sectors;
+              else
                 /* Some buggy BIOSes doesn't return the total sectors
                    correctly but returns zero. So if it is zero, compute
                    it by C/H/S returned by the LBA BIOS call.  */
                 total_sectors = drp->cylinders * drp->heads * drp->sectors;
-           }
-       }
+
+              if (drp->bytes_per_sector == (GRUB_DISK_SECTOR_SIZE << 2))
+                {
+                  data->flags |= GRUB_BIOSDISK_FLAG_CDROM;
+                  data->sectors = 32;
+                  total_sectors = 9000000;
+                }
+            }
+        }
     }
 
-  if (drive < cd_start)
+  if (! (data->flags & GRUB_BIOSDISK_FLAG_CDROM))
     {
       if (grub_biosdisk_get_diskinfo_standard (drive,
                                               &data->cylinders,
@@ -364,8 +380,6 @@ grub_disk_biosdisk_fini (void)
 
 GRUB_MOD_INIT(biosdisk)
 {
-  int drive, found = 0;
-
   if (grub_disk_firmware_is_tainted)
     {
       grub_printf ("Firmware is marked as tainted, refusing to initialize.\n");
@@ -374,24 +388,6 @@ GRUB_MOD_INIT(biosdisk)
   grub_disk_firmware_fini = grub_disk_biosdisk_fini;
 
   grub_disk_dev_register (&grub_biosdisk_dev);
-
-  for (drive = GRUB_BIOSDISK_MACHINE_CDROM_START;
-       drive < GRUB_BIOSDISK_MACHINE_CDROM_END; drive++)
-    {
-      if (grub_biosdisk_check_int13_extensions (drive))
-        {
-         if (! found)
-           cd_start = drive;
-         found++;
-       }
-      else
-        {
-         if (found)
-            break;
-       }
-    }
-
-  cd_count = found;
 }
 
 GRUB_MOD_FINI(biosdisk)
diff --git a/include/grub/i386/pc/kernel.h b/include/grub/i386/pc/kernel.h
index 848dad1..43a8d5b 100644
--- a/include/grub/i386/pc/kernel.h
+++ b/include/grub/i386/pc/kernel.h
@@ -71,7 +71,7 @@ extern grub_int32_t grub_memdisk_image_size;
 extern char grub_prefix[];
 
 /* The boot BIOS drive number.  */
-extern grub_int32_t grub_boot_drive;
+extern grub_int32_t EXPORT_VAR(grub_boot_drive);
 
 /* The root BIOS drive number.  */
 extern grub_int32_t grub_root_drive;
diff --git a/kern/i386/pc/init.c b/kern/i386/pc/init.c
index 7237492..525b667 100644
--- a/kern/i386/pc/init.c
+++ b/kern/i386/pc/init.c
@@ -22,7 +22,6 @@
 #include <grub/machine/memory.h>
 #include <grub/machine/console.h>
 #include <grub/machine/kernel.h>
-#include <grub/machine/biosdisk.h>
 #include <grub/types.h>
 #include <grub/err.h>
 #include <grub/dl.h>
@@ -77,13 +76,8 @@ make_install_device (void)
       if (grub_root_drive == 0xFF)
         grub_root_drive = grub_boot_drive;
       
-      if (grub_root_drive >= GRUB_BIOSDISK_MACHINE_CDROM_START)
-        grub_sprintf (dev, "(cd%u",
-                     grub_root_drive - GRUB_BIOSDISK_MACHINE_CDROM_START);
-      else
-        grub_sprintf (dev, "(%cd%u",
-                     (grub_root_drive & 0x80) ? 'h' : 'f',
-                     grub_root_drive & 0x7f);
+      grub_sprintf (dev, "(%cd%u", (grub_root_drive & 0x80) ? 'h' : 'f',
+                    grub_root_drive & 0x7f);
       
       if (grub_install_dos_part >= 0)
        grub_sprintf (dev + grub_strlen (dev), ",%u", grub_install_dos_part + 
1);
_______________________________________________
Grub-devel mailing list
Grub-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/grub-devel

Reply via email to