This is the mail archive of the ecos-patches@sourceware.org mailing list for the eCos project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

eCosCentric disk infrastructure updates


As promised/threatened, here is the patch I'm checking in to extend and improve the disk API and its infrastructural capabilities, based on what we have been using successfully within eCosCentric. We want to keep our APIs in sync with anoncvs.

It also involves changes to the (anoncvs) IDE disk driver, edb_v850 disk driver and synthetic target disk driver, along with a few config keys in io/common.

I did have to make changes in order to merge the two code bases, which might have had a minor destabilising effect, and I have not been able to test the hardware-specific driver changes as I don't have the hardware. However I have successfully tested it with an MMC driver. The rest is caveat emptor, but it's a good guess ;).

Of course one result of this is that anyone with their own drivers outside of anoncvs will find the API has changed. But that's CVS for you. At least it's obvious.

Jifl
--
eCosCentric    http://www.eCosCentric.com/    The eCos and RedBoot experts
------["The best things in life aren't things."]------      Opinions==mine
Index: devs/disk/ide/current/ChangeLog
===================================================================
RCS file: /cvs/ecos/ecos/packages/devs/disk/ide/current/ChangeLog,v
retrieving revision 1.2
diff -u -5 -p -r1.2 ChangeLog
--- devs/disk/ide/current/ChangeLog	8 Feb 2005 10:08:00 -0000	1.2
+++ devs/disk/ide/current/ChangeLog	21 Sep 2006 16:14:04 -0000
@@ -1,5 +1,15 @@
+2006-09-21  Jonathan Larmour  <jifl@eCosCentric.com>
+
+	* src/ide_disk.h: DISK_FUNS is now implicitly static.
+	(IDE_DISK_INSTANCE): Reflect updated io/disk API by using
+	ide_disk_controller.
+	* src/ide_disk.c: Define ide_disk_controller (even though unused
+	in practice).
+	(ide_disk_init): Provide phys_block_size and max_transfer disk ident
+	members.	
+
 2005-02-02 Knud Woehler <knud.woehler@microplex.de>
 
 	* src/ide_disk.c: Check the device is not busy before sending a
 	command to the device. 
 	
Index: devs/disk/ide/current/src/ide_disk.c
===================================================================
RCS file: /cvs/ecos/ecos/packages/devs/disk/ide/current/src/ide_disk.c,v
retrieving revision 1.2
diff -u -5 -p -r1.2 ide_disk.c
--- devs/disk/ide/current/src/ide_disk.c	8 Feb 2005 10:08:00 -0000	1.2
+++ devs/disk/ide/current/src/ide_disk.c	21 Sep 2006 16:14:04 -0000
@@ -72,10 +72,14 @@
 # define D(fmt,args...)
 #endif
 
 // ----------------------------------------------------------------------------
 
+// No h/w controller structure is needed in this driver, but the address of the
+// second argument is taken anyway.
+DISK_CONTROLLER(ide_disk_controller, ide_disk_controller);
+
 #ifdef CYGVAR_DEVS_DISK_IDE_DISK0
 IDE_DISK_INSTANCE(0, 0, 0, true, CYGDAT_IO_DISK_IDE_DISK0_NAME);
 #endif
 
 #ifdef CYGVAR_DEVS_DISK_IDE_DISK1
@@ -353,10 +357,12 @@ ide_disk_init(struct cyg_devtab_entry *t
     ident.cylinders_num  = ide_idData->num_cylinders;
     ident.heads_num = ide_idData->num_heads;
     ident.sectors_num = ide_idData->num_sectors;
     ident.lba_sectors_num = ide_idData->lba_total_sectors[1] << 16 | 
                             ide_idData->lba_total_sectors[0];
+    ident.phys_block_size = 1;
+    ident.max_transfer = 512;
     
     D("\tSerial : %s\n", ident.serial);
     D("\tFirmware rev. : %s\n", ident.firmware_rev);
     D("\tModel : %s\n", ident.model_num);
     D("\tC/H/S : %d/%d/%d\n", ident.cylinders_num, 
Index: devs/disk/ide/current/src/ide_disk.h
===================================================================
RCS file: /cvs/ecos/ecos/packages/devs/disk/ide/current/src/ide_disk.h,v
retrieving revision 1.1
diff -u -5 -p -r1.1 ide_disk.h
--- devs/disk/ide/current/src/ide_disk.h	18 Oct 2004 09:03:45 -0000	1.1
+++ devs/disk/ide/current/src/ide_disk.h	21 Sep 2006 16:14:04 -0000
@@ -150,15 +150,15 @@ static Cyg_ErrNo ide_disk_set_config(dis
 
 static Cyg_ErrNo ide_disk_lookup(struct cyg_devtab_entry **tab,
                                 struct cyg_devtab_entry  *sub_tab,
                                 const char               *name);
 
-static DISK_FUNS(ide_disk_funs, 
-                 ide_disk_read, 
-                 ide_disk_write, 
-                 ide_disk_get_config,
-                 ide_disk_set_config
+DISK_FUNS(ide_disk_funs, 
+          ide_disk_read, 
+          ide_disk_write, 
+          ide_disk_get_config,
+          ide_disk_set_config
 );
 
 // ----------------------------------------------------------------------------
 
 #define IDE_DISK_INSTANCE(_number_,_port_,_chan_,_mbr_supp_,_name_)     \
@@ -167,10 +167,11 @@ static ide_disk_info_t ide_disk_info##_n
     chan: (cyg_uint8) _chan_                                            \
 };                                                                      \
 DISK_CHANNEL(ide_disk_channel##_number_,                                \
              ide_disk_funs,                                             \
              ide_disk_info##_number_,                                   \
+             ide_disk_controller,                                       \
              _mbr_supp_,                                                \
              4                                                          \
 );                                                                      \
 BLOCK_DEVTAB_ENTRY(ide_disk_io##_number_,                               \
                    _name_,                                              \
Index: devs/disk/synth/current/ChangeLog
===================================================================
RCS file: /cvs/ecos/ecos/packages/devs/disk/synth/current/ChangeLog,v
retrieving revision 1.2
diff -u -5 -p -r1.2 ChangeLog
--- devs/disk/synth/current/ChangeLog	1 Jul 2004 13:02:08 -0000	1.2
+++ devs/disk/synth/current/ChangeLog	21 Sep 2006 16:14:04 -0000
@@ -1,16 +1,35 @@
+2006-02-03  Nick Garnett  <nickg@ecoscentric.com>
+
+	* src/synthdisk.c: Updated to match changes in io/disk package.
+
 2004-07-01  Savin Zlobec  <savin@elatec.si> 
 
         * src/synthdisk.c:
         Updated to work with the new DISK_CHANNEL macro definition.
 
-2004-01-15  Nick Garnett  <nickg@calivar.com>
+2004-04-15  Nick Garnett  <nickg@ecoscentric.com>
+
+	* src/synthdisk.c: Mildly reorganized to support changeable
+	media. Added synth_disk_change() function to allow us to fake a
+	disk change for testing purposes.
+
+2004-02-05  Nick Garnett  <nickg@ecoscentric.com>
+
+	* cdl/synthdisk.cdl: Added testing config options, plus
+	define_proc to export CYGDAT_DEVS_DISK_CFG include file name.
+
+2004-01-30  Nick Garnett  <nickg@ecoscentric.com>
+
+	* src/synthdisk.c: Updated to latest disk device specification.
+
+2004-01-15  Nick Garnett  <nickg@ecoscentric.com>
 
 	* cdl/synthdisk.cdl:
 	* src/synthdisk.c: 	
 	Added _FILENAME option for disk instances to map device to an
-	arbitrary cinfigured file.
+	arbitrary configured file.
 	
 	* src/synthdisk.c: Removed block_pos arguments from read
 	and write calls: it is not necessary.
 
 2003-09-01 Savin Zlobec <savin@elatec.si>
@@ -29,11 +48,12 @@
 
 //===========================================================================
 //####ECOSGPLCOPYRIGHTBEGIN####
 // -------------------------------------------
 // This file is part of eCos, the Embedded Configurable Operating System.
-// Copyright (C) 2003 Savin Zlobec 
+// Copyright (C) 2003 Savin Zlobec
+// Copyright (C) 2004, 2006 eCosCentric Limited
 //
 // eCos is free software; you can redistribute it and/or modify it under
 // the terms of the GNU General Public License as published by the Free
 // Software Foundation; either version 2 or (at your option) any later version.
 //
Index: devs/disk/synth/current/cdl/synthdisk.cdl
===================================================================
RCS file: /cvs/ecos/ecos/packages/devs/disk/synth/current/cdl/synthdisk.cdl,v
retrieving revision 1.1
diff -u -5 -p -r1.1 synthdisk.cdl
--- devs/disk/synth/current/cdl/synthdisk.cdl	19 Jan 2004 14:35:01 -0000	1.1
+++ devs/disk/synth/current/cdl/synthdisk.cdl	21 Sep 2006 16:14:04 -0000
@@ -6,11 +6,12 @@
 #
 # ====================================================================
 #####ECOSGPLCOPYRIGHTBEGIN####
 ## -------------------------------------------
 ## This file is part of eCos, the Embedded Configurable Operating System.
-## Copyright (C) 2003 Savin Zlobec 
+## Copyright (C) 2003 Savin Zlobec
+## Copyright (C) 2004 eCosCentric Limited
 ##
 ## eCos is free software; you can redistribute it and/or modify it under
 ## the terms of the GNU General Public License as published by the Free
 ## Software Foundation; either version 2 or (at your option) any later version.
 ##
@@ -50,20 +51,26 @@ cdl_package CYGPKG_DEVS_DISK_ECOSYNTH {
     
     parent      CYGPKG_IO_DISK_DEVICES
     active_if   CYGPKG_IO_DISK
     active_if   CYGPKG_HAL_SYNTH
 
+    define_proc {
+        puts $::cdl_system_header "/***** Synthdisk driver proc output start *****/"
+        puts $::cdl_system_header "#define CYGDAT_DEVS_DISK_CFG <pkgconf/devs_disk_ecosynth.h>"
+        puts $::cdl_system_header "/***** Synthdisk driver proc output end  *****/"        
+    }
+
     cdl_component CYGVAR_DEVS_DISK_ECOSYNTH_DISK0 {
     	display         "Provide disk 0 device"
         flavor          bool
         default_value   0
         description     "Synthetic disk 0 driver."
         
         cdl_option CYGDAT_IO_DISK_ECOSYNTH_DISK0_NAME {
             display       "Device name for ecosynth disk 0 device"
             flavor        data
-            default_value {"\"/dev/disk0/\""}
+            default_value {"\"/dev/hd0/\""}
             description   "This is the device name used to access this
                            device in eCos. Note that the trailing slash
                            character must be present."
         }
 
@@ -161,6 +168,50 @@ cdl_package CYGPKG_DEVS_DISK_ECOSYNTH {
                 This option modifies the set of compiler flags for
                 building this package. These flags are removed from
                 the set of global flags if present."
         }
     }
+
+    cdl_component CYGPKG_DEVS_DISK_ECOSYNTH_TESTING {
+        display          "Testing configuration"
+        default_value    1
+        
+        cdl_option CYGDAT_DEVS_DISK_TEST_DEVICE {
+            display      "Test device driver"
+            flavor       data
+            default_value {"\"/dev/hd0/1\"" }
+        }
+
+        cdl_option CYGDAT_DEVS_DISK_TEST_MOUNTPOINT {
+            display      "Test filesystem mountpoint"
+            flavor       data
+            default_value {"\"/dosfs\"" }
+        }
+
+        cdl_option CYGDAT_DEVS_DISK_TEST_DIRECTORY {
+            display      "Test directory on test device"
+            flavor       data
+            default_value {"\"/test\"" }
+        }
+
+        
+        cdl_option CYGDAT_DEVS_DISK_TEST_DEVICE2 {
+            display      "Second Test device driver"
+            flavor       data
+            default_value {"\"/dev/hd0/2\"" }
+        }
+
+        cdl_option CYGDAT_DEVS_DISK_TEST_MOUNTPOINT2 {
+            display      "Second Test filesystem mountpoint"
+            flavor       data
+            default_value {"\"/dosfs2\"" }
+        }
+
+        cdl_option CYGDAT_DEVS_DISK_TEST_DIRECTORY2 {
+            display      "Test directory on second test device"
+            flavor       data
+            default_value {"\"/test\"" }
+        }
+
+    }
+
 }
Index: devs/disk/synth/current/src/synthdisk.c
===================================================================
RCS file: /cvs/ecos/ecos/packages/devs/disk/synth/current/src/synthdisk.c,v
retrieving revision 1.2
diff -u -5 -p -r1.2 synthdisk.c
--- devs/disk/synth/current/src/synthdisk.c	1 Jul 2004 13:02:10 -0000	1.2
+++ devs/disk/synth/current/src/synthdisk.c	21 Sep 2006 16:14:05 -0000
@@ -6,11 +6,12 @@
 //
 //==========================================================================
 //####ECOSGPLCOPYRIGHTBEGIN####
 // -------------------------------------------
 // This file is part of eCos, the Embedded Configurable Operating System.
-// Copyright (C) 2003 Savin Zlobec.
+// Copyright (C) 2003 Savin Zlobec
+// Copyright (C) 2004, 2006 eCosCentric Limited
 //
 // eCos is free software; you can redistribute it and/or modify it under
 // the terms of the GNU General Public License as published by the Free
 // Software Foundation; either version 2 or (at your option) any later version.
 //
@@ -74,10 +75,12 @@ typedef struct {
     cyg_uint32 size;
     int        filefd;
     char       *filename;
 } synth_disk_info_t;
 
+typedef struct { int dummy; } synth_controller_t;
+
 // ----------------------------------------------------------------------------
 
 static cyg_bool synth_disk_init(struct cyg_devtab_entry *tab);
 
 static Cyg_ErrNo synth_disk_read(disk_channel *chan, 
@@ -102,42 +105,46 @@ static Cyg_ErrNo synth_disk_set_config(d
 
 static Cyg_ErrNo synth_disk_lookup(struct cyg_devtab_entry  **tab,
                                    struct cyg_devtab_entry   *sub_tab,
                                    const char                *name);
 
-static DISK_FUNS(synth_disk_funs, 
-                 synth_disk_read, 
-                 synth_disk_write, 
-                 synth_disk_get_config,
-                 synth_disk_set_config
+DISK_FUNS(synth_disk_funs, 
+          synth_disk_read, 
+          synth_disk_write, 
+          synth_disk_get_config,
+          synth_disk_set_config
 );
 
 // ----------------------------------------------------------------------------
 
-#define SYNTH_DISK_INSTANCE(_number_,_mbr_supp_, _cyl_,_hpt_,_spt_)        \
-static synth_disk_info_t synth_disk_info##_number_ = {                     \
-    num:           _number_,                                               \
-    cylinders_num: _cyl_,                                                  \
-    heads_num:     _hpt_,                                                  \
-    sectors_num:   _spt_,                                                  \
-    size:          CYGNUM_IO_DISK_ECOSYNTH_DISK##_number_##_SIZE,          \
-    filefd:        -1,                                                     \
-    filename:      CYGDAT_IO_DISK_ECOSYNTH_DISK##_number_##_FILENAME       \
-};                                                                         \
-DISK_CHANNEL(synth_disk_channel##_number_,                                 \
-             synth_disk_funs,                                              \
-             synth_disk_info##_number_,                                    \
-             _mbr_supp_,                                                   \
-             4                                                             \
-);                                                                         \
-BLOCK_DEVTAB_ENTRY(synth_disk_io##_number_,                                \
-             CYGDAT_IO_DISK_ECOSYNTH_DISK##_number_##_NAME,                \
-             0,                                                            \
-             &cyg_io_disk_devio,                                           \
-             synth_disk_init,                                              \
-             synth_disk_lookup,                                            \
-             &synth_disk_channel##_number_                                 \
+
+#define SYNTH_DISK_INSTANCE(_number_,_mbr_supp_, _cyl_,_hpt_,_spt_)                             \
+static synth_disk_info_t synth_disk_info##_number_ = {                                          \
+    num:           _number_,                                                                    \
+    cylinders_num: _cyl_,                                                                       \
+    heads_num:     _hpt_,                                                                       \
+    sectors_num:   _spt_,                                                                       \
+    size:          CYGNUM_IO_DISK_ECOSYNTH_DISK##_number_##_SIZE,                               \
+    filefd:        -1,                                                                          \
+    filename:      CYGDAT_IO_DISK_ECOSYNTH_DISK##_number_##_FILENAME                            \
+};                                                                                              \
+static synth_controller_t synth_controller_##_number_;                                          \
+DISK_CONTROLLER( synth_disk_controller_##_number_, synth_controller_##_number_ );               \
+DISK_CHANNEL(synth_disk_channel##_number_,                                                      \
+                    synth_disk_funs,                                                            \
+                    synth_disk_info##_number_,                                                  \
+                    synth_disk_controller_##_number_,                                           \
+                    _mbr_supp_,                                                                 \
+                    4                                                                           \
+);                                                                                              \
+BLOCK_DEVTAB_ENTRY(synth_disk_io##_number_,                                                     \
+             CYGDAT_IO_DISK_ECOSYNTH_DISK##_number_##_NAME,                                     \
+             0,                                                                                 \
+             &cyg_io_disk_devio,                                                                \
+             synth_disk_init,                                                                   \
+             synth_disk_lookup,                                                                 \
+             &synth_disk_channel##_number_                                                      \
 );
 
 // ----------------------------------------------------------------------------
 
 #ifdef CYGVAR_DEVS_DISK_ECOSYNTH_DISK0
@@ -192,37 +199,49 @@ synth_disk_init(struct cyg_devtab_entry 
         return false;
     }
    
     if (result)
     {
-        cyg_disk_identify_t ident;
-       
-        ident.serial[0]       = '\0';
-        ident.firmware_rev[0] = '\0';
-        ident.model_num[0]    = '\0';
-        ident.lba_sectors_num = synth_info->size / 512;
-        ident.cylinders_num   = synth_info->cylinders_num;
-        ident.heads_num       = synth_info->heads_num;
-        ident.sectors_num     = synth_info->sectors_num;
  
         if (!(chan->callbacks->disk_init)(tab))
             return false;
-        if (ENOERR != (chan->callbacks->disk_connected)(tab, &ident))
-            return false;
     }
     return result;
 }
 
+// ----------------------------------------------------------------------------
+
 static Cyg_ErrNo 
-synth_disk_lookup(struct cyg_devtab_entry **tab, 
+synth_disk_lookup(struct cyg_devtab_entry  **tab, 
                   struct cyg_devtab_entry  *sub_tab,
                   const char               *name)
 {
+    Cyg_ErrNo res;
     disk_channel *chan = (disk_channel *) (*tab)->priv;
-    return (chan->callbacks->disk_lookup(tab, sub_tab, name));
+    synth_disk_info_t *synth_info = (synth_disk_info_t *) chan->dev_priv;
+    cyg_disk_identify_t ident;
+       
+    ident.serial[0]       = '\0';
+    ident.firmware_rev[0] = '\0';
+    ident.model_num[0]    = '\0';
+    ident.lba_sectors_num = synth_info->size / 512;
+    ident.cylinders_num   = synth_info->cylinders_num;
+    ident.heads_num       = synth_info->heads_num;
+    ident.sectors_num     = synth_info->sectors_num;
+    ident.phys_block_size = 1;
+    ident.max_transfer    = 2048;
+    
+    res = (chan->callbacks->disk_connected)(*tab, &ident);
+
+    if( res == ENOERR )    
+        res = (chan->callbacks->disk_lookup(tab, sub_tab, name));
+
+    return res;
 }
 
+// ----------------------------------------------------------------------------
+
 static Cyg_ErrNo 
 synth_disk_read(disk_channel *chan, 
                 void         *buf,
                 cyg_uint32    len,
                 cyg_uint32    block_num)
@@ -236,16 +255,18 @@ synth_disk_read(disk_channel *chan, 
     if (synth_info->filefd >= 0)
     {
         cyg_hal_sys_lseek(synth_info->filefd, 
                           block_num * chan->info->block_size,
                           CYG_HAL_SYS_SEEK_SET);
-        cyg_hal_sys_read(synth_info->filefd, buf, len);
+        cyg_hal_sys_read(synth_info->filefd, buf, len*512);
         return ENOERR;
     }
     return -EIO; 
 }
 
+// ----------------------------------------------------------------------------
+
 static Cyg_ErrNo 
 synth_disk_write(disk_channel *chan,
                  const void   *buf,
                  cyg_uint32    len,
                  cyg_uint32    block_num)
@@ -259,17 +280,19 @@ synth_disk_write(disk_channel *chan,
     if (synth_info->filefd >= 0)
     {
         cyg_hal_sys_lseek(synth_info->filefd, 
                           block_num * chan->info->block_size,
                           CYG_HAL_SYS_SEEK_SET);
-        cyg_hal_sys_write(synth_info->filefd, buf, len);
+        cyg_hal_sys_write(synth_info->filefd, buf, len*512);
 //        cyg_hal_sys_fdatasync(synth_info->filefd);
         return ENOERR;
     }
     return -EIO; 
 }
 
+// ----------------------------------------------------------------------------
+
 static Cyg_ErrNo
 synth_disk_get_config(disk_channel *chan, 
                       cyg_uint32    key,
                       const void   *xbuf, 
                       cyg_uint32   *len)
@@ -280,21 +303,104 @@ synth_disk_get_config(disk_channel *chan
 #endif
     
     return -EINVAL;
 }
 
+// ----------------------------------------------------------------------------
+
 static Cyg_ErrNo
 synth_disk_set_config(disk_channel *chan, 
                       cyg_uint32    key,
                       const void   *xbuf, 
                       cyg_uint32   *len)
 {
-
+    Cyg_ErrNo res = ENOERR;
 #ifdef DEBUG
     diag_printf("synth disk set config\n");
 #endif
- 
-    return -EINVAL;
+
+    switch ( key )
+    {
+    case CYG_IO_SET_CONFIG_DISK_MOUNT:
+        // We have nothing to do here for this option.
+        break;
+            
+    case CYG_IO_SET_CONFIG_DISK_UMOUNT:
+        if( chan->info->mounts == 0 )
+        {
+            // If this is the last unmount of this disk, then disconnect it from
+            // the driver system so the user can swap it out if he wants.
+            res = (chan->callbacks->disk_disconnected)(chan);
+        }
+        break;
+            
+    default:
+        res = -EINVAL;
+        break;
+    }
+    
+    return res;
+}
+
+// ----------------------------------------------------------------------------
+
+externC cyg_bool synth_disk_change( int unit, char *filename, int size,
+                                    int cyls, int heads, int sectors)
+{
+    struct cyg_devtab_entry  *tab        = &synth_disk_io0;
+    disk_channel             *chan       = (disk_channel *) tab->priv;
+    synth_disk_info_t        *synth_info = (synth_disk_info_t *) chan->dev_priv;
+    int err = 0;
+    
+    if (!chan->init) 
+        return false;
+
+    synth_info->filename = filename;
+    synth_info->size = size;
+    synth_info->cylinders_num = cyls;
+    synth_info->heads_num = heads;
+    synth_info->sectors_num = sectors;
+    
+#ifdef DEBUG
+    diag_printf("synth disk %d change size=%d\n", 
+                synth_info->num, synth_info->size);
+#endif
+
+    err = cyg_hal_sys_close( synth_info->filefd );
+
+#ifdef DEBUG
+    if( err != 0 )
+    {
+        diag_printf("synth disk change, failed to close old image: %d\n",err);
+    }
+#endif
+    
+    synth_info->filefd = cyg_hal_sys_open(synth_info->filename, 
+            CYG_HAL_SYS_O_RDWR,
+            CYG_HAL_SYS_S_IRWXU|CYG_HAL_SYS_S_IRWXG|CYG_HAL_SYS_S_IRWXO);
+
+    if (-ENOENT == synth_info->filefd)
+    {
+        synth_info->filefd = cyg_hal_sys_open(synth_info->filename, 
+            CYG_HAL_SYS_O_RDWR|CYG_HAL_SYS_O_CREAT, 0644);
+        
+        if (synth_info->filefd >= 0)
+        {
+            unsigned char b = 0x00;
+            int i;
+        
+            for (i = 0; i < synth_info->size; i++)
+                cyg_hal_sys_write(synth_info->filefd, &b, 1);    
+        }
+    }
+
+    if (synth_info->filefd < 0)
+    {
+        CYG_ASSERT(false, "Can't open/create disk image file");
+        return false;
+    }
+
+    return true;
 }
 
 // ----------------------------------------------------------------------------
 // EOF synthdisk.c
Index: devs/disk/v85x/edb_v850/current/ChangeLog
===================================================================
RCS file: /cvs/ecos/ecos/packages/devs/disk/v85x/edb_v850/current/ChangeLog,v
retrieving revision 1.2
diff -u -5 -p -r1.2 ChangeLog
--- devs/disk/v85x/edb_v850/current/ChangeLog	2 Jul 2004 09:04:59 -0000	1.2
+++ devs/disk/v85x/edb_v850/current/ChangeLog	21 Sep 2006 16:14:05 -0000
@@ -1,5 +1,16 @@
+2006-09-21  Jonathan Larmour  <jifl@eCosCentric.com>
+
+	* src/v85x_edb_v850_disk.c (cf_disk_init): Provide phys_block_size
+	and max_transfer disk ident members.
+
+2006-09-20  Jonathan Larmour  <jifl@eCosCentric.com>
+
+	* src/v85x_edb_v850_disk.c:
+	DISK_CHANNEL and DISK_FUNS are now implicitly static.
+	Update DISK_CHANNEL for new io/disk macro.
+
 2004-07-02  Savin Zlobec  <savin@elatec.si> 
 
         * src/v85x_edb_v850_disk.c:
         Updated to work with the new DISK_CHANNEL macro definition
         and fixed read and write calls to honor the len parameter.
@@ -20,10 +31,11 @@
 
 //===========================================================================
 //####ECOSGPLCOPYRIGHTBEGIN####
 // -------------------------------------------
 // This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 2006 eCosCentric Ltd.
 // Copyright (C) 2003 Savin Zlobec 
 //
 // eCos is free software; you can redistribute it and/or modify it under
 // the terms of the GNU General Public License as published by the Free
 // Software Foundation; either version 2 or (at your option) any later version.
Index: devs/disk/v85x/edb_v850/current/src/v85x_edb_v850_disk.c
===================================================================
RCS file: /cvs/ecos/ecos/packages/devs/disk/v85x/edb_v850/current/src/v85x_edb_v850_disk.c,v
retrieving revision 1.2
diff -u -5 -p -r1.2 v85x_edb_v850_disk.c
--- devs/disk/v85x/edb_v850/current/src/v85x_edb_v850_disk.c	2 Jul 2004 09:05:00 -0000	1.2
+++ devs/disk/v85x/edb_v850/current/src/v85x_edb_v850_disk.c	21 Sep 2006 16:14:05 -0000
@@ -7,10 +7,11 @@
 //==========================================================================
 //####ECOSGPLCOPYRIGHTBEGIN####
 // -------------------------------------------
 // This file is part of eCos, the Embedded Configurable Operating System.
 // Copyright (C) 2003 Savin Zlobec.
+// Copyright (C) 2006 eCosCentric Ltd.
 //
 // eCos is free software; you can redistribute it and/or modify it under
 // the terms of the GNU General Public License as published by the Free
 // Software Foundation; either version 2 or (at your option) any later version.
 //
@@ -134,26 +135,31 @@ static Cyg_ErrNo cf_disk_set_config(disk
 
 static Cyg_ErrNo cf_disk_lookup(struct cyg_devtab_entry **tab,
                                 struct cyg_devtab_entry  *sub_tab,
                                 const char               *name);
 
-static DISK_FUNS(cf_disk_funs, 
-                 cf_disk_read, 
-                 cf_disk_write, 
-                 cf_disk_get_config,
-                 cf_disk_set_config
+DISK_FUNS(cf_disk_funs, 
+          cf_disk_read, 
+          cf_disk_write, 
+          cf_disk_get_config,
+          cf_disk_set_config
 );
 
 // ----------------------------------------------------------------------------
 
+// No h/w controller structure is needed, but the address of the
+// second argument is taken anyway.
+DISK_CONTROLLER(cf_disk_controller, cf_disk_controller);
+
 #define CF_DISK_INSTANCE(_number_,_base_,_mbr_supp_,_name_)           \
 static cf_disk_info_t cf_disk_info##_number_ = {                      \
     base: (volatile cyg_uint16 *)_base_,                              \
 };                                                                    \
 DISK_CHANNEL(cf_disk_channel##_number_,                               \
              cf_disk_funs,                                            \
              cf_disk_info##_number_,                                  \
+             cf_disk_controller,                                      \
              _mbr_supp_,                                              \
              4                                                        \
 );                                                                    \
 BLOCK_DEVTAB_ENTRY(cf_disk_io##_number_,                              \
                    _name_,                                            \
@@ -325,11 +331,12 @@ cf_disk_init(struct cyg_devtab_entry *ta
     ident.cylinders_num   = ata_id->num_cylinders;
     ident.heads_num       = ata_id->num_heads;
     ident.sectors_num     = ata_id->num_sectors;
     ident.lba_sectors_num = ata_id->lba_total_sectors[1] << 16 | 
                             ata_id->lba_total_sectors[0];
-    
+    ident.phys_block_size = 1;
+    ident.max_transfer    = 512;
     if (!(chan->callbacks->disk_init)(tab))
         return false;
 
     if (ENOERR != (chan->callbacks->disk_connected)(tab, &ident))
         return false;
Index: io/common/current/ChangeLog
===================================================================
RCS file: /cvs/ecos/ecos/packages/io/common/current/ChangeLog,v
retrieving revision 1.27
diff -u -5 -p -r1.27 ChangeLog
--- io/common/current/ChangeLog	13 Mar 2006 14:46:18 -0000	1.27
+++ io/common/current/ChangeLog	21 Sep 2006 16:14:22 -0000
@@ -1,23 +1,32 @@
-2006-02-15  Uwe Kindler  <uwe_kindler@web.de>
-
-	* include/config_keys.h Replaced CAN configuration keys
-	CYG_IO_SET_CONFIG_CAN_REMOTE_BUF, 
-	CYG_IO_SET_CONFIG_CAN_FILTER_ALL and
-	CYG_IO_SET_CONFIG_CAN_FILTER_MSG with new single config key
-	CYG_IO_SET_CONFIG_CAN_MSGBUF
-
+2006-09-21  Jonathan Larmour  <jifl@eCosCentric.com>
+
+	* include/config_keys.h: Merge from eCosCentric repository.
+	ChangeLogs incorporated in correct location below.
+
+2006-02-15  Uwe Kindler  <uwe_kindler@web.de>
+
+	* include/config_keys.h Replaced CAN configuration keys
+	CYG_IO_SET_CONFIG_CAN_REMOTE_BUF, 
+	CYG_IO_SET_CONFIG_CAN_FILTER_ALL and
+	CYG_IO_SET_CONFIG_CAN_FILTER_MSG with new single config key
+	CYG_IO_SET_CONFIG_CAN_MSGBUF
+
 2005-12-02  Andrew Lunn  <andrew.lunn@ascom.ch>
 
 	* src/iosys.c: 
 	* include/devtab.h: Add comments that bread/bwrite takes there
 	parameters in blocks, not bytes.
 
 2005-09-11  Uwe Kindler  <uwe_kindler@web.de>
 
 	* include/config_keys.h Configuration keys for CAN driver added. 
 	
+2005-01-19  Jonathan Larmour  <jifl@eCosCentric.com>
+
+	* include/config_keys.h: Add device close key.
+
 2004-12-23  Peter Korsgaard  <jacmet@sunsite.dk>
 
 	* doc/io.sgml: Match CYG_TTY_IN_FLAGS_ECHO and
 	CYG_TTY_IN_FLAGS_BINARY values with source code.
 
@@ -29,11 +38,16 @@
 2004-04-16  Jonathan Larmour  <jifl@eCosCentric.com>
 
 	* src/iosys.c (cyg_io_lookup): Use union to avoid aliasing problems
 	with compiler.
 
-2004-01-19  Nick Garnett  <nickg@calivar.com>
+2004-04-15  Nick Garnett  <nickg@ecoscentric.com>
+
+	* include/config_keys.h: Added CYG_IO_SET_CONFIG_DISK_MOUNT and
+	CYG_IO_SET_CONFIG_DISK_UMOUNT keys.
+
+2004-01-19  Nick Garnett  <nickg@ecoscentric.com>
 
 	* include/config_keys.h (CYG_IO_GET_CONFIG_DISK_INFO): Added DISK
 	IO config key base definition.
 
 2003-11-27  David Woodhouse  <dwmw2@infradead.org>
@@ -253,10 +267,11 @@
 //===========================================================================
 //####ECOSGPLCOPYRIGHTBEGIN####
 // -------------------------------------------
 // This file is part of eCos, the Embedded Configurable Operating System.
 // Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
+// Copyright (C) 2004, 2006 eCosCentric Limited
 //
 // eCos is free software; you can redistribute it and/or modify it under
 // the terms of the GNU General Public License as published by the Free
 // Software Foundation; either version 2 or (at your option) any later version.
 //
Index: io/common/current/include/config_keys.h
===================================================================
RCS file: /cvs/ecos/ecos/packages/io/common/current/include/config_keys.h,v
retrieving revision 1.13
diff -u -5 -p -r1.13 config_keys.h
--- io/common/current/include/config_keys.h	13 Mar 2006 14:46:18 -0000	1.13
+++ io/common/current/include/config_keys.h	21 Sep 2006 16:14:22 -0000
@@ -9,10 +9,11 @@
 // ====================================================================
 //####ECOSGPLCOPYRIGHTBEGIN####
 // -------------------------------------------
 // This file is part of eCos, the Embedded Configurable Operating System.
 // Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
+// Copyright (C) 2004 eCosCentric Limited
 //
 // eCos is free software; you can redistribute it and/or modify it under
 // the terms of the GNU General Public License as published by the Free
 // Software Foundation; either version 2 or (at your option) any later version.
 //
@@ -126,10 +127,12 @@
 // ======== 0x700 DISK =======================================================
 // Get/Set configuration 'key' values for DISK I/O 
 
 #define CYG_IO_GET_CONFIG_DISK_INFO              0x700
 
+#define CYG_IO_SET_CONFIG_DISK_MOUNT             0x781
+#define CYG_IO_SET_CONFIG_DISK_UMOUNT            0x782
 
 // ======== 0x800 CAN ========================================================
 // Get/Set configuration 'key' values for CAN I/O 
 #define CYG_IO_GET_CONFIG_CAN_INFO                  0x0801
 #define CYG_IO_GET_CONFIG_CAN_BUFFER_INFO           0x0802
@@ -141,14 +144,13 @@
 #define CYG_IO_SET_CONFIG_CAN_INFO                  0x0881
 #define CYG_IO_SET_CONFIG_CAN_OUTPUT_DRAIN          0x0882
 #define CYG_IO_SET_CONFIG_CAN_OUTPUT_FLUSH          0x0883
 #define CYG_IO_SET_CONFIG_CAN_INPUT_FLUSH           0x0884
 #define CYG_IO_SET_CONFIG_CAN_TIMEOUT               0x0885
-#define CYG_IO_SET_CONFIG_CAN_MSGBUF                0x0886
+#define CYG_IO_SET_CONFIG_CAN_MSGBUF                0x0886
 #define CYG_IO_SET_CONFIG_CAN_MODE                  0x0887
-#define CYG_IO_SET_CONFIG_CAN_ABORT                 0x0888
-
+#define CYG_IO_SET_CONFIG_CAN_ABORT                 0x0888
 
 
 // ======== 0x1000 Generic ===================================================
 // Get/Set configuration 'key' values that can apply to more than one
 // class of device.
@@ -157,8 +159,13 @@
 #define CYG_IO_GET_CONFIG_WRITE_BLOCKING        0x1002
 
 #define CYG_IO_SET_CONFIG_READ_BLOCKING         0x1081
 #define CYG_IO_SET_CONFIG_WRITE_BLOCKING        0x1082
 
+// Close the underlying device - primarily useful for io/fileio's devfs,
+// but probably more widely applicable. Note that this is not like UNIX
+// close in that there is no reference counting. If that is needed it must
+// be done at a higher level.
+#define CYG_IO_SET_CONFIG_CLOSE                 0x1100
 
 #endif  /* CYGONCE_CONFIG_KEYS_H */
 /* EOF config_keys.h */
Index: io/disk/current/ChangeLog
===================================================================
RCS file: /cvs/ecos/ecos/packages/io/disk/current/ChangeLog,v
retrieving revision 1.4
diff -u -5 -p -r1.4 ChangeLog
--- io/disk/current/ChangeLog	21 Aug 2006 21:10:31 -0000	1.4
+++ io/disk/current/ChangeLog	21 Sep 2006 16:14:22 -0000
@@ -1,26 +1,117 @@
+2006-09-21  Jonathan Larmour  <jifl@eCosCentric.com>
+
+	* include/disk.h (DISK_CHANNEL): No need for extra _part_dev
+	slot intended for entire disk's own devtab.
+
+	* src/disk.c (disk_lookup): Just access pdevs_dev directly
+	with no adjusted offset.
+	(disk_init): No longer set entry 0 from device devtab.
+	It's unnecessary.
+
+2006-09-20  Jonathan Larmour  <jifl@eCosCentric.com>
+
+	* include/disk.h: Merge eCosCentric CVS with public eCos CVS.
+	This merges (and therefore changes) the API. ChangeLog
+	entries have been incorporated in the correct places below.
+	* include/diskio.h: Also merged.
+	* cdl/io_disk.cdl: Also merged.
+	* src/disk.c: Also merged.
+
 2006-08-18  Andy Jackson  <andy@xylanta.com>
 
 	* cdl/io_disk.cdl: Made debugging CDL controlled. 
 	* src/disk.c: Added support to allow non-CHS disk devices to 
 	use LBA information in MBR.
 
+2006-02-03  Nick Garnett  <nickg@ecoscentric.com>
+
+	* src/disk.c (read_partition): Switched to favour LBA partition
+	information in partition tables. This also means we don't now rely
+	on the driver reporting a correct CHS size for the disk.
+	(disk_bread, disk_bwrite): API changed to take length in sectors
+	rather than bytes. Also call hardware driver to transfer in
+	(up to) max_transfer sized chunks, rather than a sector at a
+	time. Call in to driver now made with DSR lock claimed, to avoid a
+	race condition between the DSR and the calling thread.
+	(disk_get_config): Added phys_block_size to channel info.
+
+	* include/diskio.h (struct cyg_disk_identify_t): Added
+	phys_block_size and max_transfer fields. These must be filled in
+	by the driver.
+
+2005-12-12  Jonathan Larmour  <jifl@eCosCentric.com>
+
+	* include/disk.h (DISK_CHANNEL_INIT): New macro. Allows a
+	DISK_CHANNEL to be defined dynamically.
+
 2005-12-02  Andrew Lunn  <andrew.lunn@ascom.ch>
 
 	* src/disk.c: Add comments that bread/bwrite take the position and
 	len in terms of blocks, not bytes.
 
+2005-10-11  Nick Garnett  <nickg@ecoscentric.com>
+
+	* src/disk.c (disk_bread, disk_bwrite): Made calls to
+	cyg_thread_yield() dependent on presence ok kernel.
+
+2005-06-01  Jonathan Larmour  <jifl@eCosCentric.com>
+
+	* src/disk.c (disk_bwrite): Uncomment the cyg_thread_yield() at
+	the end to prevent thread starvation between threads at the same
+	priority.
+	(disk_bread): Ditto.
+
+2004-07-21  Nick Garnett  <nickg@ecoscentric.com>
+
+	* src/disk.c (read_partition): Changed to account for very large
+	disks which report bogus CHS geometry. We can only use the LBA
+	partition parameters in such disks.
+	(disk_set_config): Added some extra debug output.
+
 2004-07-01  Savin Zlobec  <savin@elatec.si> 
 
  	* src/disk.c:
  	* include/disk.h:
  	* include/diskio.h:
  	Use predefined arrays for partition devices and info 
  	radher than malloc. Extended DISK_CHANNEL macro to
   	support defining maximum number of partitions.
 
-2004-01-15  Nick Garnett  <nickg@calivar.com>
+2004-04-15  Nick Garnett  <nickg@ecoscentric.com>
+
+	* src/disk.c: 
+	Various changes to support disconnect/reconnect of changeable
+	media.
+
+	* include/diskio.h: Added mount counter to disk_info structure.
+
+	* include/disk.h: Changed disk_disconnected() function to take a
+	pointer to a struct disk_channel rather than a struct
+	cyg_devtab_entry. Added mount count to disk_channel structure.
+	Moved include of diskio.h to end to fix declaration problems.
+
+2004-02-04  Nick Garnett  <nickg@ecoscentric.com>
+
+	* src/disk.c: Fixed bug in write routine where controller result
+	field was not being initialized. Added signals on controller queue
+	condition variable after setting controller busy flag to false.
+
+	* include/disk.h: Made controller result and busy fields
+	volatile. Just in case.
+
+2004-01-23  Nick Garnett  <nickg@ecoscentric.com>
+
+	* include/disk.h: 
+	* src/disk.c:
+	Many changes. Added additional disk_controller data structure to
+	better reflect hardware structure. Added support for serialization
+	of multithreaded accesses to a single controller. Added support
+	for asynchronous, interrupt driven, IO operations. Various
+	tidies.
+
+2004-01-15  Nick Garnett  <nickg@ecoscentric.com>
 
 	* src/disk.c:
 	* include/disk.h: Removed block_pos arguments from
 	hardware driver read and write calls: it is not necessary.
 
@@ -46,11 +137,12 @@
 
 //===========================================================================
 //####ECOSGPLCOPYRIGHTBEGIN####
 // -------------------------------------------
 // This file is part of eCos, the Embedded Configurable Operating System.
-// Copyright (C) 2003 Savin Zlobec 
+// Copyright (C) 2003 Savin Zlobec
+// Copyright (C) 2004, 2005, 2006 eCosCentric Limited
 //
 // eCos is free software; you can redistribute it and/or modify it under
 // the terms of the GNU General Public License as published by the Free
 // Software Foundation; either version 2 or (at your option) any later version.
 //
Index: io/disk/current/include/disk.h
===================================================================
RCS file: /cvs/ecos/ecos/packages/io/disk/current/include/disk.h,v
retrieving revision 1.2
diff -u -5 -p -r1.2 disk.h
--- io/disk/current/include/disk.h	1 Jul 2004 13:03:20 -0000	1.2
+++ io/disk/current/include/disk.h	21 Sep 2006 16:14:22 -0000
@@ -9,11 +9,12 @@
 // ====================================================================
 //####ECOSGPLCOPYRIGHTBEGIN####
 // -------------------------------------------
 // This file is part of eCos, the Embedded Configurable Operating System.
 // Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
-// Copyright (C) 2003 Savin Zlobec 
+// Copyright (C) 2003 Savin Zlobec
+// Copyright (C) 2004, 2005 eCosCentric Limited
 //
 // eCos is free software; you can redistribute it and/or modify it under
 // the terms of the GNU General Public License as published by the Free
 // Software Foundation; either version 2 or (at your option) any later version.
 //
@@ -57,16 +58,26 @@
 
 #include <pkgconf/system.h>
 #include <pkgconf/io_disk.h>
 
 #include <cyg/infra/cyg_type.h>
+#include <cyg/io/devtab.h>
 #include <cyg/io/io.h>
-#include <cyg/io/diskio.h>
 #include <cyg/hal/drv_api.h>
+#include <string.h> /* memset() */
+
+// ---------------------------------------------------------------------------
+
+typedef struct cyg_disk_partition_t cyg_disk_partition_t;
+typedef struct cyg_disk_info_t cyg_disk_info_t;
+typedef struct cyg_disk_identify_t cyg_disk_identify_t;
 
-typedef struct disk_channel disk_channel;
-typedef struct disk_funs    disk_funs;
+typedef struct disk_channel    disk_channel;
+typedef struct disk_controller disk_controller;
+typedef struct disk_funs       disk_funs;
+
+// ---------------------------------------------------------------------------
 
 // Pointers into upper-level driver
 typedef struct {
     
     // Initialize the disk 
@@ -75,50 +86,81 @@ typedef struct {
     // Disk device has been connected
     Cyg_ErrNo (*disk_connected)(struct cyg_devtab_entry *tab,
                                 cyg_disk_identify_t     *ident);
 
     // Disk device has been disconnected
-    Cyg_ErrNo (*disk_disconnected)(struct cyg_devtab_entry *tab);
+    Cyg_ErrNo (*disk_disconnected)(struct disk_channel *chan);
 
     // Lookup disk device
     Cyg_ErrNo (*disk_lookup)(struct cyg_devtab_entry **tab,
                              struct cyg_devtab_entry  *sub_tab,
                              const char               *name);
+
+    // Asynchronous block transfer done
+    void (*disk_transfer_done)(struct disk_channel *chan, Cyg_ErrNo res);
+    
 } disk_callbacks_t;
 
-#define DISK_CALLBACKS(_l,                              \
-                       _init,                           \
-                       _connected,                      \
-                       _disconnected,                   \
-                       _lookup)                         \
-disk_callbacks_t _l = {                                 \
-    _init,                                              \
-    _connected,                                         \
-    _disconnected,                                      \
-    _lookup                                             \
+#define DISK_CALLBACKS(_l,                      \
+                       _init,                   \
+                       _connected,              \
+                       _disconnected,           \
+                       _lookup,                 \
+                       _transfer_done)          \
+disk_callbacks_t _l = {                         \
+    _init,                                      \
+    _connected,                                 \
+    _disconnected,                              \
+    _lookup,                                    \
+    _transfer_done                              \
 };
 
 extern disk_callbacks_t cyg_io_disk_callbacks;
 
+// ---------------------------------------------------------------------------
+// Private data which describes a disk controller
+
+struct disk_controller {
+    cyg_drv_mutex_t     lock;           // Per-controller lock
+    cyg_drv_cond_t      queue;          // Access wait list
+    cyg_drv_cond_t      async;          // Async transfer waits here
+    void                *priv;          // Private data
+    volatile Cyg_ErrNo  result;         // Last operation result
+    cyg_bool            init;           // Initialized?
+    volatile cyg_bool   busy;           // Busy?
+};
+
+#define DISK_CONTROLLER(_l, _priv)              \
+static disk_controller _l = {                   \
+    priv:       &_priv,                         \
+    init:       false,                          \
+    busy:       false                           \
+};
+
+// ---------------------------------------------------------------------------
 // Private data which describes this channel
+
 struct disk_channel {
     disk_funs               *funs;
     disk_callbacks_t        *callbacks;
     void                    *dev_priv;    // device private data
+    disk_controller         *controller;  // pointer to controller
     cyg_disk_info_t         *info;        // disk info 
     cyg_disk_partition_t    *partition;   // partition data 
     struct cyg_devtab_entry *pdevs_dev;   // partition devs devtab ents 
     disk_channel            *pdevs_chan;  // partition devs disk chans 
     cyg_bool                 mbr_support; // true if disk has MBR
     cyg_bool                 valid;       // true if device valid 
     cyg_bool                 init;        // true if initialized
+    cyg_ucount16             mounts;      // count of number of mounts
 };
 
 // Initialization macro for disk channel
 #define DISK_CHANNEL(_l,                                              \
                      _funs,                                           \
                      _dev_priv,                                       \
+                     _controller,                                     \
                      _mbr_supp,                                       \
                      _max_part_num)                                   \
 static struct cyg_devtab_entry _l##_part_dev[_max_part_num];          \
 static disk_channel            _l##_part_chan[_max_part_num];         \
 static cyg_disk_partition_t    _l##_part_tab[_max_part_num];          \
@@ -128,20 +170,53 @@ static cyg_disk_info_t         _l##_disk
 };                                                                    \
 static disk_channel _l = {                                            \
     &(_funs),                                                         \
     &cyg_io_disk_callbacks,                                           \
     &(_dev_priv),                                                     \
+    &(_controller),                                                   \
     &(_l##_disk_info),                                                \
     NULL,                                                             \
     _l##_part_dev,                                                    \
     _l##_part_chan,                                                   \
     _mbr_supp,                                                        \
     false,                                                            \
-    false                                                             \
+    false,                                                            \
+    0                                                                 \
 };
 
+// Initialization macro for disk channel allocated elsewhere.
+#define DISK_CHANNEL_INIT(_dc,                           \
+                          _funs,                         \
+                          _dev_priv,                     \
+                          _controller,                   \
+                          _disk_info,                    \
+                          _part_dev,                     \
+                          _part_chan,                    \
+                          _part_tab,                     \
+                          _mbr_supp,                     \
+                          _max_part_num)                 \
+    CYG_MACRO_START                                      \
+    memset((_disk_info), 0, sizeof(cyg_disk_info_t));    \
+    (_dc).funs = &(_funs);                               \
+    (_dc).callbacks = &cyg_io_disk_callbacks;            \
+    (_dc).dev_priv = (_dev_priv);                        \
+    (_dc).controller = &(_controller);                   \
+    (_dc).info = &(_disk_info);                          \
+    (_dc).info->partitions = (_part_tab);                \
+    (_dc).pdevs_dev = (_part_dev);                       \
+    (_dc).pdevs_chan = (_part_chan);                     \
+    (_dc).partition = NULL;                              \
+    (_dc).mbr_support = (_mbr_supp);                     \
+    (_dc).valid = false;                                 \
+    (_dc).init = false;                                  \
+    (_dc).mounts = 0;                                    \
+    (_dc).info->partitions_num = (_max_part_num);        \
+    CYG_MACRO_END
+
+// ---------------------------------------------------------------------------
 // Low level interface functions
+
 struct disk_funs {
 
     // Read block data into buf
     Cyg_ErrNo (*read)(disk_channel *priv, 
                       void         *buf, 
@@ -166,15 +241,20 @@ struct disk_funs {
                             const void   *xbuf, 
                             cyg_uint32   *len);
 };
 
 #define DISK_FUNS(_l,_read,_write,_get_config,_set_config)           \
-disk_funs _l = {                                                     \
+static disk_funs _l = {                                              \
   _read,                                                             \
   _write,                                                            \
   _get_config,                                                       \
   _set_config                                                        \
 };
 
 extern cyg_devio_table_t cyg_io_disk_devio;
 
+// ---------------------------------------------------------------------------
+
+#include <cyg/io/diskio.h>
+
+// ---------------------------------------------------------------------------
 #endif // CYGONCE_DISK_H
Index: io/disk/current/include/diskio.h
===================================================================
RCS file: /cvs/ecos/ecos/packages/io/disk/current/include/diskio.h,v
retrieving revision 1.2
diff -u -5 -p -r1.2 diskio.h
--- io/disk/current/include/diskio.h	1 Jul 2004 13:03:20 -0000	1.2
+++ io/disk/current/include/diskio.h	21 Sep 2006 16:14:22 -0000
@@ -8,11 +8,12 @@
 //
 // ====================================================================
 //####ECOSGPLCOPYRIGHTBEGIN####
 // -------------------------------------------
 // This file is part of eCos, the Embedded Configurable Operating System.
-// Copyright (C) 2003 Savin Zlobec 
+// Copyright (C) 2003 Savin Zlobec
+// Copyright (C) 2004, 2006 eCosCentric Limited
 //
 // eCos is free software; you can redistribute it and/or modify it under
 // the terms of the GNU General Public License as published by the Free
 // Software Foundation; either version 2 or (at your option) any later version.
 //
@@ -53,40 +54,49 @@
 
 #include <pkgconf/hal.h>
 #include <cyg/infra/cyg_type.h>
 #include <cyg/io/config_keys.h>
 
+#include <cyg/io/devtab.h>
+
 #ifdef __cplusplus
 extern "C" {
 #endif
-
-typedef struct {
+    
+struct cyg_disk_identify_t
+{
     char        serial[20+1];      // serial number
     char        firmware_rev[8+1]; // firmware revision
     char        model_num[40+1];   // model number 
     cyg_uint32  cylinders_num;     // number of cylinders         (CHS)
     cyg_uint32  heads_num;         // number of heads             (CHS)
     cyg_uint32  sectors_num;       // number of sectors per track (CHS)
     cyg_uint32  lba_sectors_num;   // total number of sectors in LBA mode
-} cyg_disk_identify_t;
+    cyg_uint32  phys_block_size;   // physical block size in sectors
+    cyg_uint32  max_transfer;      // Maximum transfer size in bytes
+};
 
-typedef struct {
+struct  cyg_disk_partition_t
+{
     cyg_uint8  type;    // partition type
     cyg_uint8  state;   // state 0x00 - inactive, 0x80 - active
     cyg_uint32 start;   // first sector number
     cyg_uint32 end;     // last sector number
     cyg_uint32 size;    // size in sectors
-} cyg_disk_partition_t;
+};
 
-typedef struct {
-    cyg_disk_partition_t *partitions;    // partition table
-    int                   partitions_num;// partition table size
-    cyg_disk_identify_t   ident;         // identify data
-    cyg_uint32            block_size;    // block size
-    cyg_uint32            blocks_num;    // number of blocks on disk
-    cyg_bool              connected;     // true if device connected
-} cyg_disk_info_t;
+struct  cyg_disk_info_t
+{
+    cyg_disk_partition_t       *partitions;    // partition table
+    int                         partitions_num;// partition table size
+    cyg_disk_identify_t         ident;         // identify data
+    cyg_uint32                  block_size;    // logical block size
+    cyg_uint32                  blocks_num;    // number of blocks on disk
+    cyg_uint32                  phys_block_size; // physical block size
+    cyg_bool                    connected;     // true if device connected
+    cyg_ucount16                mounts;        // total number of mounts for all partitions
+};
 
 #ifdef __cplusplus
 }
 #endif
 
Index: io/disk/current/src/disk.c
===================================================================
RCS file: /cvs/ecos/ecos/packages/io/disk/current/src/disk.c,v
retrieving revision 1.4
diff -u -5 -p -r1.4 disk.c
--- io/disk/current/src/disk.c	21 Aug 2006 21:10:31 -0000	1.4
+++ io/disk/current/src/disk.c	21 Sep 2006 16:14:22 -0000
@@ -6,11 +6,12 @@
 //
 //==========================================================================
 //####ECOSGPLCOPYRIGHTBEGIN####
 // -------------------------------------------
 // This file is part of eCos, the Embedded Configurable Operating System.
-// Copyright (C) 2003 Savin Zlobec 
+// Copyright (C) 2003 Savin Zlobec
+// Copyright (C) 2004, 2005, 2006 eCosCentric Limited
 //
 // eCos is free software; you can redistribute it and/or modify it under
 // the terms of the GNU General Public License as published by the Free
 // Software Foundation; either version 2 or (at your option) any later version.
 //
@@ -137,85 +138,154 @@ BLOCK_DEVIO_TABLE(cyg_io_disk_devio,
 static cyg_bool disk_init(struct cyg_devtab_entry *tab);
 
 static Cyg_ErrNo disk_connected(struct cyg_devtab_entry *tab,
                                 cyg_disk_identify_t     *ident);
 
-static Cyg_ErrNo disk_disconnected(struct cyg_devtab_entry *tab);
+static Cyg_ErrNo disk_disconnected(struct disk_channel *chan);
 
 static Cyg_ErrNo disk_lookup(struct cyg_devtab_entry **tab,
                              struct cyg_devtab_entry  *sub_tab,
                              const char               *name);
 
+static void disk_transfer_done(struct disk_channel *chan, Cyg_ErrNo res);
+
 DISK_CALLBACKS(cyg_io_disk_callbacks, 
                disk_init,
                disk_connected,
                disk_disconnected,
-               disk_lookup
+               disk_lookup,
+               disk_transfer_done
 ); 
 
 // ---------------------------------------------------------------------------
-
 //
 // Read partition from data
 // 
+
 static void 
 read_partition(cyg_uint8            *data,
                cyg_disk_info_t      *info,
                cyg_disk_partition_t *part)
 {
     cyg_disk_identify_t *ident = &info->ident;
     cyg_uint16 c, h, s;
+    cyg_uint32 start, end, size;
 
+#ifdef DEBUG
+    diag_printf("Partition data:\n");
+    diag_dump_buf( data, 16 );
+    diag_printf("Disk geometry: %d/%d/%d\n",info->ident.cylinders_num,
+                info->ident.heads_num, info->ident.sectors_num );
+#endif
+    
     // Retrieve basic information
     part->type  = data[4];
     part->state = data[0];
     READ_DWORD(&data[12], part->size);
 
-    // If disk doesn't have cylinders/heads, use LBA data rather than CHS
-    if (ident->cylinders_num == 0 && ident->heads_num == 0 &&
-        ident->sectors_num== 0)
-    {
-        // Use LBA data to determine disk size
-        READ_DWORD(&data[8], part->start);
-        part->end = (part->start + part->size) - 1;
-        D(("LBA partition data (%d,%d,%d)\n", 
-           part->start, part->end, part->size));
+    READ_DWORD(&data[8], start);        
+    READ_DWORD(&data[12], size);
+
+    // Use the LBA start and size fields if they are valid. Otherwise
+    // fall back to CHS.
+    
+    if( start > 0 && size > 0 )
+    {
+        READ_DWORD(&data[8], start);    
+        end = start + size - 1;
+
+#ifdef DEBUG
+        diag_printf("Using LBA partition parameters\n");
+        diag_printf("      LBA start %d\n",start);
+        diag_printf("      LBA size  %d\n",size);
+        diag_printf("      LBA end   %d\n",end);
+#endif
+        
     }
     else
     {
-        // Use CHS data to determine disk size
         READ_CHS(&data[1], c, h, s);
-        D(("partition start CHS %d,%d,%d\n", c, h, s));
-        CHS_TO_LBA(ident, c, h, s, part->start);
-
+        CHS_TO_LBA(ident, c, h, s, start);
+#ifdef DEBUG
+        diag_printf("Using CHS partition parameters\n");
+        diag_printf("      CHS start %d/%d/%d => %d\n",c,h,s,start);
+#endif
+    
         READ_CHS(&data[5], c, h, s);
-        D(("partition end CHS %d,%d,%d\n", c, h, s));
-        CHS_TO_LBA(ident, c, h, s, part->end);
-        D(("CHS partition data (%d,%d,%d)\n", 
-           part->start, part->end, part->size));
+        CHS_TO_LBA(ident, c, h, s, end);
+#ifdef DEBUG
+        diag_printf("      CHS end %d/%d/%d => %d\n",c,h,s,end);
+        diag_printf("      CHS size %d\n",size);
+#endif
+
     }
+
+    part->size = size;
+    part->start = start;
+    part->end = end;
 }
 
+// ---------------------------------------------------------------------------
 //
 // Read Master Boot Record (partitions)
 //
+
 static Cyg_ErrNo 
 read_mbr(disk_channel *chan)
 {
     cyg_disk_info_t *info = chan->info;
     disk_funs       *funs = chan->funs;
+    disk_controller *ctlr = chan->controller;
     cyg_uint8 buf[512];
     Cyg_ErrNo res = ENOERR;
     int i;
- 
+
+    D(("read MBR\n"));
+    
     for (i = 0; i < info->partitions_num; i++)
         info->partitions[i].type = 0x00;    
-   
-    res = (funs->read)(chan, (void *)buf, 512, 0);
+
+
+    
+    cyg_drv_mutex_lock( &ctlr->lock );
+
+    while( ctlr->busy )
+        cyg_drv_cond_wait( &ctlr->queue );
+
+    ctlr->busy = true;
+    
+    ctlr->result = -EWOULDBLOCK;
+
+    for( i = 0; i < sizeof(buf); i++ )
+        buf[i] = 0;
+    
+    res = (funs->read)(chan, (void *)buf, 1, 0);
+    
+    if( res == -EWOULDBLOCK )
+    {
+        // If the driver replys EWOULDBLOCK, then the transfer is
+        // being handled asynchronously and when it is finished it
+        // will call disk_transfer_done(). This will wake us up here
+        // to continue.
+
+        while( ctlr->result == -EWOULDBLOCK )
+            cyg_drv_cond_wait( &ctlr->async );
+
+        res = ctlr->result;
+    }
+        
+    ctlr->busy = false;
+    
+    cyg_drv_mutex_unlock( &ctlr->lock );
+
     if (ENOERR != res)
         return res;
 
+#ifdef DEBUG
+    diag_dump_buf_with_offset( buf, 512, buf );
+#endif
+    
     if (MBR_SIG_BYTE0 == buf[MBR_SIG_ADDR+0] && MBR_SIG_BYTE1 == buf[MBR_SIG_ADDR+1])
     {
         int npart;
 
         D(("disk MBR found\n")); 
@@ -242,52 +312,80 @@ read_mbr(disk_channel *chan)
         } 
     }
     return ENOERR;
 }
 
+// ---------------------------------------------------------------------------
+
 static cyg_bool 
 disk_init(struct cyg_devtab_entry *tab)
 {
     disk_channel    *chan = (disk_channel *) tab->priv;
     cyg_disk_info_t *info = chan->info;
     int i;
 
     if (!chan->init)
     {
+        disk_controller *controller = chan->controller;
+        
+        if( !controller->init )
+        {
+            cyg_drv_mutex_init( &controller->lock );
+            cyg_drv_cond_init( &controller->queue, &controller->lock );
+            cyg_drv_cond_init( &controller->async, &controller->lock );
+            
+            controller->init = true;
+        }
+        
         info->connected = false;
-
+        
         // clear partition data
         for (i = 0; i < info->partitions_num; i++)
             info->partitions[i].type = 0x00;
 
         chan->init = true;
     }
     return true;
 }
 
+// ---------------------------------------------------------------------------
+
 static Cyg_ErrNo
 disk_connected(struct cyg_devtab_entry *tab,
                cyg_disk_identify_t     *ident)
 {
     disk_channel    *chan = (disk_channel *) tab->priv;
     cyg_disk_info_t *info = chan->info;
     Cyg_ErrNo res = ENOERR;
  
     if (!chan->init)
         return -EINVAL;
+
+    // If the device is already connected, nothing more to do
+    if( info->connected )
+        return ENOERR;
+
+    // If any of these assertions fire, it is probable that the
+    // hardware driver has not been updated to match the current disk
+    // API.
+    CYG_ASSERT( ident->lba_sectors_num > 0, "Bad LBA sector count" );
+    CYG_ASSERT( ident->phys_block_size > 0, "Bad physical block size");
+    CYG_ASSERT( ident->max_transfer > 0, "Bad max transfer size");
     
     info->ident      = *ident;
     info->block_size = 512;
     info->blocks_num = ident->lba_sectors_num;
+    info->phys_block_size = ident->phys_block_size;
  
     D(("disk connected\n")); 
-    D(("    serial       = '%s'\n", ident->serial)); 
-    D(("    firmware rev = '%s'\n", ident->firmware_rev)); 
-    D(("    model num    = '%s'\n", ident->model_num)); 
-    D(("    block_size   = %d\n",   info->block_size));
-    D(("    blocks_num   = %d\n",   info->blocks_num));
-
+    D(("    serial            = '%s'\n", ident->serial)); 
+    D(("    firmware rev      = '%s'\n", ident->firmware_rev)); 
+    D(("    model num         = '%s'\n", ident->model_num)); 
+    D(("    block_size        = %d\n",   info->block_size));
+    D(("    blocks_num        = %u\n",   info->blocks_num));
+    D(("    phys_block_size   = %d\n",   info->phys_block_size));
+    
     if (chan->mbr_support)
     {    
         // read disk master boot record
         res = read_mbr(chan);
     }
@@ -299,20 +397,21 @@ disk_connected(struct cyg_devtab_entry *
         chan->valid     = true; 
     }
     return res;
 }
 
+// ---------------------------------------------------------------------------
+
 static Cyg_ErrNo
-disk_disconnected(struct cyg_devtab_entry *tab)
+disk_disconnected(disk_channel *chan)
 {
-    disk_channel    *chan = (disk_channel *) tab->priv;
     cyg_disk_info_t *info = chan->info;
     int i;
 
     if (!chan->init)
         return -EINVAL;
-    
+
     info->connected = false;
     chan->valid     = false;
      
     // clear partition data and invalidate partition devices 
     for (i = 0; i < info->partitions_num; i++)
@@ -325,10 +424,12 @@ disk_disconnected(struct cyg_devtab_entr
     D(("disk disconnected\n")); 
 
     return ENOERR;    
 }
     
+// ---------------------------------------------------------------------------
+
 static Cyg_ErrNo
 disk_lookup(struct cyg_devtab_entry **tab,
             struct cyg_devtab_entry  *sub_tab,
             const char *name)
 {
@@ -394,54 +495,100 @@ disk_bread(cyg_io_handle_t  handle, 
            cyg_uint32      *len,  // In blocks
            cyg_uint32       pos)  // In blocks
 {
     cyg_devtab_entry_t *t    = (cyg_devtab_entry_t *) handle;
     disk_channel       *chan = (disk_channel *) t->priv;
+    disk_controller    *ctlr = chan->controller;
     disk_funs          *funs = chan->funs;
     cyg_disk_info_t    *info = chan->info;
     cyg_uint32  size = *len;
     cyg_uint8  *bbuf = (cyg_uint8  *)buf;
     Cyg_ErrNo   res  = ENOERR;
     cyg_uint32  last;
 
-    if (!info->connected || !chan->valid)
-        return -EINVAL;
-    
-    if (NULL != chan->partition)
-    {
-        pos += chan->partition->start;
-        last = chan->partition->end;
-    }
-    else
-    {
-        last = info->blocks_num-1;
-    }
- 
-    D(("disk read block=%d len=%d buf=%p\n", pos, *len, buf)); 
- 
-    while (size > 0)
+    cyg_drv_mutex_lock( &ctlr->lock );
+
+    while( ctlr->busy )
+        cyg_drv_cond_wait( &ctlr->queue );
+
+    if (info->connected && chan->valid)
     {
-        if (pos > last)
+        ctlr->busy = true;
+    
+        if (NULL != chan->partition)
         {
-            res = -EIO;
-            break;
+            pos += chan->partition->start;
+            last = chan->partition->end;
         }
-        
-        res = (funs->read)(chan, (void*)bbuf, info->block_size, pos);
-        if (ENOERR != res)
-            break;
-
-        if (!info->connected)
+        else
         {
-            res = -EINVAL;
-            break;
+            last = info->blocks_num-1;
         }
+ 
+        D(("disk read block=%d len=%d buf=%p\n", pos, *len, buf));
+
+        while( size > 0 )
+        {
+            cyg_uint32 tfr = size;
             
-        bbuf += info->block_size;
-        pos++;
-        size--;
+            if (pos > last)
+            {
+                res = -EIO;
+                break;
+            }
+
+            if( tfr > info->ident.max_transfer )
+                tfr = info->ident.max_transfer;
+            
+            ctlr->result = -EWOULDBLOCK;
+
+            cyg_drv_dsr_lock();
+            
+            res = (funs->read)(chan, (void*)bbuf, tfr, pos);
+
+            if( res == -EWOULDBLOCK )
+            {
+                // If the driver replys EWOULDBLOCK, then the transfer is
+                // being handled asynchronously and when it is finished it
+                // will call disk_transfer_done(). This will wake us up here
+                // to continue.
+
+                while( ctlr->result == -EWOULDBLOCK )
+                    cyg_drv_cond_wait( &ctlr->async );
+
+                res = ctlr->result;
+            }
+
+            cyg_drv_dsr_unlock();
+            
+            if (ENOERR != res)
+                goto done;
+
+            if (!info->connected)
+            {
+                res = -EINVAL;
+                goto done;
+            }
+
+            bbuf        += tfr * info->block_size;
+            pos         += tfr;
+            size        -= tfr;
+        }
+
+        ctlr->busy = false;
+        cyg_drv_cond_signal( &ctlr->queue );
     }
+    else
+        res = -EINVAL;
+
+done:
+    
+    cyg_drv_mutex_unlock( &ctlr->lock );
+#ifdef CYGPKG_KERNEL
+    cyg_thread_yield();
+#endif
+    
     *len -= size;
     return res;
 }
 
 // ---------------------------------------------------------------------------
@@ -452,60 +599,118 @@ disk_bwrite(cyg_io_handle_t  handle, 
             cyg_uint32      *len,   // In blocks
             cyg_uint32       pos)   // In blocks
 {
     cyg_devtab_entry_t *t    = (cyg_devtab_entry_t *) handle;
     disk_channel       *chan = (disk_channel *) t->priv;
+    disk_controller    *ctlr = chan->controller;    
     disk_funs          *funs = chan->funs;
     cyg_disk_info_t    *info = chan->info;
     cyg_uint32  size = *len;
     cyg_uint8  *bbuf = (cyg_uint8 * const) buf;
     Cyg_ErrNo   res  = ENOERR;
     cyg_uint32  last;
 
-    if (!info->connected || !chan->valid)
-        return -EINVAL;
- 
-    if (NULL != chan->partition)
-    {
-        pos += chan->partition->start;
-        last = chan->partition->end;
-    }
-    else
-    {
-        last = info->blocks_num-1;
-    }
-    
-    D(("disk write block=%d len=%d buf=%p\n", pos, *len, buf)); 
-   
-    while (size > 0)
+    cyg_drv_mutex_lock( &ctlr->lock );
+
+    while( ctlr->busy )
+        cyg_drv_cond_wait( &ctlr->queue );
+
+    if (info->connected && chan->valid)
     {
-        if (pos > last)
+        ctlr->busy = true;
+        
+        if (NULL != chan->partition)
         {
-            res = -EIO;
-            break;
+            pos += chan->partition->start;
+            last = chan->partition->end;
         }
+        else
+        {
+            last = info->blocks_num-1;
+        }
+    
+        D(("disk write block=%d len=%d buf=%p\n", pos, *len, buf));
+
+        while( size > 0 )
+        {
+            cyg_uint32 tfr = size;
         
-        res = (funs->write)(chan, (void*)bbuf, info->block_size, pos);
-        if (ENOERR != res)
-            break;
+            if (pos > last)
+            {
+                res = -EIO;
+                goto done;
+            }
+
+            if( tfr > info->ident.max_transfer )
+                tfr = info->ident.max_transfer;
+
+            ctlr->result = -EWOULDBLOCK;
+
+            cyg_drv_dsr_lock();
+            
+            res = (funs->write)(chan, (void*)bbuf, tfr, pos);
+
+            if( res == -EWOULDBLOCK )
+            {
+                // If the driver replys EWOULDBLOCK, then the transfer is
+                // being handled asynchronously and when it is finished it
+                // will call disk_transfer_done(). This will wake us up here
+                // to continue.
+
+                while( ctlr->result == -EWOULDBLOCK )
+                    cyg_drv_cond_wait( &ctlr->async );
+
+                res = ctlr->result;
+            }
+
+            cyg_drv_dsr_unlock();
+            
+            if (ENOERR != res)
+                goto done;
  
-        if (!info->connected)
-        {
-            res = -EINVAL;
-            break;
+            if (!info->connected)
+            {
+                res = -EINVAL;
+                goto done;
+            }
+
+            bbuf        += tfr * info->block_size;
+            pos         += tfr;
+            size        -= tfr;
+            
         }
  
-        bbuf += info->block_size;
-        pos++;
-        size--;
+        ctlr->busy = false;
+        cyg_drv_cond_signal( &ctlr->queue );
     }
+    else
+        res = -EINVAL;
+
+done:
+    
+    cyg_drv_mutex_unlock( &ctlr->lock );
+#ifdef CYGPKG_KERNEL    
+    cyg_thread_yield();
+#endif
+    
     *len -= size;
     return res;
 }
 
 // ---------------------------------------------------------------------------
 
+static void disk_transfer_done(struct disk_channel *chan, Cyg_ErrNo res)
+{
+    disk_controller    *ctlr = chan->controller;    
+
+    ctlr->result = res;
+    
+    cyg_drv_cond_signal( &ctlr->async );
+}
+
+// ---------------------------------------------------------------------------
+
 static cyg_bool
 disk_select(cyg_io_handle_t handle, cyg_uint32 which, CYG_ADDRWORD info)
 {
     cyg_devtab_entry_t *t     = (cyg_devtab_entry_t *) handle;
     disk_channel       *chan  = (disk_channel *) t->priv;
@@ -525,34 +730,53 @@ disk_get_config(cyg_io_handle_t  handle,
                 void            *xbuf,
                 cyg_uint32      *len)
 {
     cyg_devtab_entry_t *t    = (cyg_devtab_entry_t *) handle;
     disk_channel       *chan = (disk_channel *) t->priv;
+    disk_controller    *ctlr = chan->controller;    
     cyg_disk_info_t    *info = chan->info;
     cyg_disk_info_t    *buf  = (cyg_disk_info_t *) xbuf;
     disk_funs          *funs = chan->funs;
     Cyg_ErrNo res = ENOERR;
  
-    if (!info->connected || !chan->valid)
-        return -EINVAL;
+    cyg_drv_mutex_lock( &ctlr->lock );
+
+    while( ctlr->busy )
+        cyg_drv_cond_wait( &ctlr->queue );
 
-    D(("disk get config key=%d\n", key)); 
+    if (info->connected && chan->valid)
+    {
+        ctlr->busy = true;
     
-    switch (key) {
-    case CYG_IO_GET_CONFIG_DISK_INFO:
-        if (*len < sizeof(cyg_disk_info_t)) {
-            return -EINVAL;
+        D(("disk get config key=%d\n", key)); 
+    
+        switch (key) {
+        case CYG_IO_GET_CONFIG_DISK_INFO:
+            if (*len < sizeof(cyg_disk_info_t)) {
+                res = -EINVAL;
+                break;
+            }
+            D(("chan->info->block_size %u\n", chan->info->block_size ));
+            D(("chan->info->blocks_num %u\n", chan->info->blocks_num ));
+            D(("chan->info->phys_block_size %u\n", chan->info->phys_block_size ));
+            *buf = *chan->info;
+            *len = sizeof(cyg_disk_info_t);
+            break;       
+
+        default:
+            // pass down to lower layers
+            res = (funs->get_config)(chan, key, xbuf, len);
         }
-        *buf = *chan->info;
-        *len = sizeof(cyg_disk_info_t);
-        break;       
-
-    default:
-        // pass down to lower layers
-        res = (funs->get_config)(chan, key, xbuf, len);
+        
+        ctlr->busy = false;
+        cyg_drv_cond_signal( &ctlr->queue );
     }
-   
+    else
+        res = -EINVAL;
+
+    cyg_drv_mutex_unlock( &ctlr->lock );    
+    
     return res;
 }
 
 // ---------------------------------------------------------------------------
 
@@ -562,19 +786,56 @@ disk_set_config(cyg_io_handle_t  handle,
                 const void      *xbuf, 
                 cyg_uint32      *len)
 {
     cyg_devtab_entry_t *t    = (cyg_devtab_entry_t *) handle;
     disk_channel       *chan = (disk_channel *) t->priv;
+    disk_controller    *ctlr = chan->controller;    
     cyg_disk_info_t    *info = chan->info;
     disk_funs          *funs = chan->funs;
+    Cyg_ErrNo res = ENOERR;
+    
+    cyg_drv_mutex_lock( &ctlr->lock );
 
-    if (!info->connected || !chan->valid)
-        return -EINVAL;
+    while( ctlr->busy )
+        cyg_drv_cond_wait( &ctlr->queue );
 
-    D(("disk set config key=%d\n", key)); 
- 
-    // pass down to lower layers
-    return (funs->set_config)(chan, key, xbuf, len);
+    if (info->connected && chan->valid)
+    {
+        ctlr->busy = true;
+        
+        D(("disk set config key=%d\n", key)); 
+
+        switch ( key )
+        {
+        case CYG_IO_SET_CONFIG_DISK_MOUNT:
+            chan->mounts++;
+            info->mounts++;
+            D(("disk mount: chan %d disk %d\n",chan->mounts, info->mounts));
+            break;
+            
+        case CYG_IO_SET_CONFIG_DISK_UMOUNT:
+            chan->mounts--;
+            info->mounts--;
+            D(("disk umount: chan %d disk %d\n",chan->mounts, info->mounts));            
+            break;
+            
+        default:
+            break;
+        }
+        
+        // pass down to lower layers
+        res = (funs->set_config)(chan, key, xbuf, len);
+        
+        ctlr->busy = false;
+        cyg_drv_cond_signal( &ctlr->queue );
+    }
+    else
+        res = -EINVAL;
+    
+    cyg_drv_mutex_unlock( &ctlr->lock );
+
+    return res;
+    
 }
 
 // ---------------------------------------------------------------------------
 // EOF disk.c

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]