pupa-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

PUPA bugfixes


From: Marco Gerards
Subject: PUPA bugfixes
Date: 01 Nov 2003 17:41:34 +0100
User-agent: Gnus/5.09 (Gnus v5.9.0) Emacs/21.2

Hi,

Here are the two bugfixes.  The first fixes the "LBA bug" and the
second flushes the cache when it is required.

Okuji, you told me it is better to check if a disk was swapped and if
not the disk cache should be flushed.  I have implemented that, but I
don't really like this solution.  Some BIOSes have bugs that prevent
this check from working and often it is impossible to check if the
BIOS has such bug.  I also dislike that the check takes some time.

What about adding an interface to kern/disk.c can find out if a disk
is swappable or not and if it is a timeout is used to flush the disk
cache.  I think it is better to use this all the time because it
definitely works and it doesn't access the hardware.  This is much
more reliable and much faster.

Now I have implemented this timeout globally, if there is a timeout
the entire cache is flushed for _all_ drives.  Is that ok for you or
should I implement it so it works per disk?

And what do you think about adding "pupa-emu"?  I already sent in a
patch, but I didn't get feedback about it yet.  Do you want it?  If
you want it, what should I change before the patch can be committed?

Thanks,
Marco

2003-11-01  Marco Gerards  <address@hidden>

        * disk/i386/pc/biosdisk.c (pupa_biosdisk_open): Correctly check
        for available extensions.

        * disk/i386/pc/biosdisk.c (pupa_biosdisk_changed): New function.
        (pupa_biosdisk_dev): Added pupa_biosdisk_changed.
        * include/pupa/disk.h (PUPA_CACHE_TIMEOUT): New macro.
        (pupa_diskchange_t): New enumerator.
        (struct pupa_disk_dev): New member `changed'.
        * include/pupa/i386/pc/biosdisk.h (pupa_biosdisk_get_diskchange):
        New prototype.
        * include/pupa/i386/pc/kernel.h [PUPA_UTIL]: Include <time.h>.
        (PUPA_TICKS_PER_SECOND) [PUPA_UTIL]: New macro.
        (PUPA_TICKS_PER_SECOND) [! PUPA_UTIL]: Likewise.
        (pupa_currticks): New prototype.
        * kern/disk.c: Include <pupa/machine/kernel.h>.
        (pupa_disk_cache_invalidate_disk): New function.
        (pupa_disk_open): Flush the cache for a disk when it was swapped.
        Flush the cache when there was a timeout.
        * kern/i386/pc/startup.S (pupa_biosdisk_get_diskchange): New
        function.
        * util/misc.c: Include <sys/times.h>
        (pupa_currticks): New function.
        



Index: disk/i386/pc/biosdisk.c
===================================================================
RCS file: /cvsroot/pupa/pupa/disk/i386/pc/biosdisk.c,v
retrieving revision 1.2
diff -u -p -r1.2 biosdisk.c
--- disk/i386/pc/biosdisk.c     2 Jan 2003 20:12:32 -0000       1.2
+++ disk/i386/pc/biosdisk.c     1 Nov 2003 16:37:10 -0000
@@ -2,6 +2,7 @@
  *  PUPA  --  Preliminary Universal Programming Architecture for GRUB
  *  Copyright (C) 1999,2000,2001,2002  Free Software Foundation, Inc.
  *  Copyright (C) 2002 Yoshinori K. Okuji <address@hidden>
+ *  Copyright (C) 2003 Marco Gerards <address@hidden>
  *
  *  PUPA is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -159,7 +160,7 @@ pupa_biosdisk_open (const char *name, pu
          /* Clear out the DRP.  */
          pupa_memset (drp, 0, sizeof (*drp));
          drp->size = sizeof (*drp);
-         if (pupa_biosdisk_get_diskinfo_int13_extensions (drive, drp))
+         if (!pupa_biosdisk_get_diskinfo_int13_extensions (drive, drp))
            {
              data->flags = PUPA_BIOSDISK_FLAG_LBA;
 
@@ -317,6 +318,15 @@ pupa_biosdisk_write (pupa_disk_t disk, u
   return pupa_errno;
 }
 
+static pupa_err_t
+pupa_biosdisk_changed (pupa_disk_t disk, pupa_diskchange_t *change)
+{
+  struct pupa_biosdisk_data *data = disk->data;
+
+  *change = pupa_biosdisk_get_diskchange (data->drive);
+  return PUPA_ERR_NONE;
+}
+
 static struct pupa_disk_dev pupa_biosdisk_dev =
   {
     .name = "biosdisk",
@@ -325,6 +335,7 @@ static struct pupa_disk_dev pupa_biosdis
     .close = pupa_biosdisk_close,
     .read = pupa_biosdisk_read,
     .write = pupa_biosdisk_write,
+    .changed = pupa_biosdisk_changed,
     .next = 0
   };
 
Index: include/pupa/disk.h
===================================================================
RCS file: /cvsroot/pupa/pupa/include/pupa/disk.h,v
retrieving revision 1.1.1.1
diff -u -p -r1.1.1.1 disk.h
--- include/pupa/disk.h 27 Dec 2002 08:53:09 -0000      1.1.1.1
+++ include/pupa/disk.h 1 Nov 2003 16:37:11 -0000
@@ -1,6 +1,7 @@
 /*
  *  PUPA  --  Preliminary Universal Programming Architecture for GRUB
  *  Copyright (C) 2002 Yoshinori K. Okuji <address@hidden>
+ *  Copyright (C) 2003 Marco Gerards <address@hidden>
  *
  *  PUPA is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -24,6 +25,17 @@
 #include <pupa/err.h>
 #include <pupa/types.h>
 
+/* Keep the disk cache alive for about 5 seconds.  */
+#define        PUPA_CACHE_TIMEOUT      5
+
+/* Has the disk been changed?  */
+typedef enum
+  {
+    PUPA_DISKCHANGE_FALSE = 0,
+    PUPA_DISKCHANGE_TRUE,
+    PUPA_DISKCHANGE_UNKNOWN
+  } pupa_diskchange_t;
+
 struct pupa_disk;
 
 /* Disk device.  */
@@ -49,6 +61,10 @@ struct pupa_disk_dev
   pupa_err_t (*write) (struct pupa_disk *disk, unsigned long sector,
                       unsigned long size, const char *buf);
 
+  /* Return in CHANGE if the disk DISK was changed.  */
+  pupa_err_t (*changed) (struct pupa_disk *disk,
+                        pupa_diskchange_t *change);
+  
   /* The next disk device.  */
   struct pupa_disk_dev *next;
 };
Index: include/pupa/err.h
===================================================================
RCS file: /cvsroot/pupa/pupa/include/pupa/err.h,v
retrieving revision 1.4
diff -u -p -r1.4 err.h
--- include/pupa/err.h  29 Oct 2003 18:44:28 -0000      1.4
+++ include/pupa/err.h  1 Nov 2003 16:37:11 -0000
@@ -2,7 +2,7 @@
 /*
  *  PUPA  --  Preliminary Universal Programming Architecture for GRUB
  *  Copyright (C) 2002 Yoshinori K. Okuji <address@hidden>
- *  Copyright (C) 2002 Marco Gerards <address@hidden>
+ *  Copyright (C) 2003 Marco Gerards <address@hidden>
  *
  *  PUPA is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
Index: include/pupa/i386/pc/biosdisk.h
===================================================================
RCS file: /cvsroot/pupa/pupa/include/pupa/i386/pc/biosdisk.h,v
retrieving revision 1.1.1.1
diff -u -p -r1.1.1.1 biosdisk.h
--- include/pupa/i386/pc/biosdisk.h     27 Dec 2002 08:53:09 -0000      1.1.1.1
+++ include/pupa/i386/pc/biosdisk.h     1 Nov 2003 16:37:11 -0000
@@ -1,6 +1,7 @@
 /*
  *  PUPA  --  Preliminary Universal Programming Architecture for GRUB
  *  Copyright (C) 2002 Yoshinori K. Okuji <address@hidden>
+ *  Copyright (C) 2003 Marco Gerards <address@hidden>
  *
  *  PUPA is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -41,6 +42,7 @@ int pupa_biosdisk_get_diskinfo_standard 
                                         unsigned long *heads,
                                         unsigned long *sectors);
 int pupa_biosdisk_get_num_floppies (void);
+int pupa_biosdisk_get_diskchange (int drive);
 
 void pupa_biosdisk_init (void);
 
Index: include/pupa/i386/pc/kernel.h
===================================================================
RCS file: /cvsroot/pupa/pupa/include/pupa/i386/pc/kernel.h,v
retrieving revision 1.3
diff -u -p -r1.3 kernel.h
--- include/pupa/i386/pc/kernel.h       31 Jan 2003 03:26:56 -0000      1.3
+++ include/pupa/i386/pc/kernel.h       1 Nov 2003 16:37:11 -0000
@@ -1,6 +1,7 @@
 /*
  *  PUPA  --  Preliminary Universal Programming Architecture for GRUB
  *  Copyright (C) 2002,2003  Yoshinori K. Okuji <address@hidden>
+ *  Copyright (C) 2003 Marco Gerards <address@hidden>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -57,6 +58,16 @@ extern char pupa_prefix[];
 
 /* The boot BIOS drive number.  */
 extern pupa_int32_t pupa_boot_drive;
+
+#ifdef PUPA_UTIL
+# include <time.h>
+# define PUPA_TICKS_PER_SECOND CLOCKS_PER_SEC
+#else
+# define PUPA_TICKS_PER_SECOND 18
+#endif
+
+/* Return the real time in ticks.  */
+pupa_uint32_t pupa_currticks (void);
 
 #endif /* ! ASM_FILE */
 
Index: kern/disk.c
===================================================================
RCS file: /cvsroot/pupa/pupa/kern/disk.c,v
retrieving revision 1.3
diff -u -p -r1.3 disk.c
--- kern/disk.c 29 Oct 2003 18:44:29 -0000      1.3
+++ kern/disk.c 1 Nov 2003 16:37:11 -0000
@@ -24,6 +24,7 @@
 #include <pupa/types.h>
 #include <pupa/machine/partition.h>
 #include <pupa/misc.h>
+#include <pupa/machine/kernel.h>
 
 /* Disk cache.  */
 struct pupa_disk_cache
@@ -91,6 +92,23 @@ pupa_disk_cache_invalidate_all (void)
     }
 }
 
+static void
+pupa_disk_cache_invalidate_disk (unsigned long id)
+{
+  unsigned i;
+
+  for (i = 0; i < PUPA_DISK_CACHE_NUM; i++)
+    {
+      struct pupa_disk_cache *cache = pupa_disk_cache_table + i;
+
+      if (cache->id == id && cache->data && ! cache->lock)
+       {
+         pupa_free (cache->data);
+         cache->data = 0;
+       }
+    }
+}
+
 static char *
 pupa_disk_cache_fetch (unsigned long id, unsigned long sector)
 {
@@ -194,6 +212,7 @@ pupa_disk_open (const char *name)
   pupa_disk_t disk;
   pupa_disk_dev_t dev;
   char *raw = (char *) name;
+  pupa_diskchange_t change;
   
   disk = (pupa_disk_t) pupa_malloc (sizeof (*disk));
   if (! disk)
@@ -246,6 +265,26 @@ pupa_disk_open (const char *name)
 
   if (p)
     disk->partition = pupa_partition_probe (disk, p + 1);
+
+  /* Check if the caches should be remained intact.  */
+  if ((dev->changed) (disk, &change) != PUPA_ERR_NONE)
+    goto fail;
+
+  if (change == PUPA_DISKCHANGE_TRUE)
+    pupa_disk_cache_invalidate_disk (disk->id);
+  else if (change == PUPA_DISKCHANGE_UNKNOWN)
+    {
+      /* The cache of a swappable disk will be invalidated about 2
+        seconds after it was closed.  */
+      static unsigned long last_time = 0;
+      unsigned long current_time = pupa_currticks ();
+
+      /* XXX: Should this should be done on a per disk base?  */
+      if (current_time > last_time + PUPA_CACHE_TIMEOUT * 
PUPA_TICKS_PER_SECOND)
+       pupa_disk_cache_invalidate_all ();
+
+      last_time = current_time;
+    }
 
  fail:
   
Index: kern/i386/pc/startup.S
===================================================================
RCS file: /cvsroot/pupa/pupa/kern/i386/pc/startup.S,v
retrieving revision 1.9
diff -u -p -r1.9 startup.S
--- kern/i386/pc/startup.S      25 Sep 2003 20:15:52 -0000      1.9
+++ kern/i386/pc/startup.S      1 Nov 2003 16:37:12 -0000
@@ -2,6 +2,7 @@
  *  PUPA  --  Preliminary Universal Programming Architecture for GRUB
  *  Copyright (C) 1999,2000,2001,2002 Free Software Foundation, Inc.
  *  Copyright (C) 2002,2003  Yoshinori K. Okuji <address@hidden>
+ *  Copyright (C) 2003 Marco Gerards <address@hidden>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -934,7 +935,47 @@ FUNCTION(pupa_biosdisk_get_num_floppies)
        popl    %ebp
        ret
        
+/*
+ * int pupa_biosdisk_get_diskchange (int drive)
+ */
+FUNCTION(pupa_biosdisk_get_diskchange)
+
+       pushl   %ebp
+
+       /* drive */
+       movb    %al, %dl
+
+       /* Don't check if a harddisk is changed.  */
+       and     $0b10000000, %al
+       jz      1f
+       xorw    %eax, %eax
+       jmp     3f
+1:     
        
+       call    prot_to_real
+       .code16
+       movb    $0x16, %ah
+       int     $0x13           /* do the operation */
+       movw    $0, %dx
+       
+       /* If the disk was changed CF is set and AH=6.  */
+       jnc     2f
+       cmp     $6, %ah
+       jne     2f
+       mov     $1, %dx
+
+2:     
+       /* back to protected mode */
+       DATA32  call    real_to_prot
+       .code32
+
+       /* Set the return value.  */
+       movw    %dx, %ax
+
+3:
+       popl    %ebp
+       ret
+
 /*
  *
  * pupa_get_memsize(i) :  return the memory size in KB. i == 0 for conventional
Index: util/misc.c
===================================================================
RCS file: /cvsroot/pupa/pupa/util/misc.c,v
retrieving revision 1.3
diff -u -p -r1.3 misc.c
--- util/misc.c 31 Jan 2003 03:26:56 -0000      1.3
+++ util/misc.c 1 Nov 2003 16:37:13 -0000
@@ -23,6 +23,7 @@
 #include <string.h>
 #include <sys/types.h>
 #include <sys/stat.h>
+#include <sys/times.h>
 
 #include <pupa/util/misc.h>
 #include <pupa/mm.h>
@@ -197,4 +198,12 @@ void
 pupa_putchar (int c)
 {
   putchar (c);
+}
+
+unsigned long
+pupa_currticks (void)
+{
+  struct tms currtime;
+
+  return times (&currtime);
 }





reply via email to

[Prev in Thread] Current Thread [Next in Thread]