diff packages/io/disk/current/include/disk.h @ 2300:654c837cc618

* 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. * 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. * 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. * include/disk.h (DISK_CHANNEL_INIT): New macro. Allows a DISK_CHANNEL to be defined dynamically. * src/disk.c (disk_bread, disk_bwrite): Made calls to cyg_thread_yield() dependent on presence ok kernel. * 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. * 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. * 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. * 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. * 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.
author jlarmour
date Thu, 21 Sep 2006 16:38:38 +0000
parents b1d2762b2eec
children 21a641579915
line wrap: on
line diff
--- a/packages/io/disk/current/include/disk.h
+++ b/packages/io/disk/current/include/disk.h
@@ -11,7 +11,8 @@
 // -------------------------------------------
 // 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
@@ -59,12 +60,22 @@
 #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 disk_channel disk_channel;
-typedef struct disk_funs    disk_funs;
+// ---------------------------------------------------------------------------
+
+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_controller disk_controller;
+typedef struct disk_funs       disk_funs;
+
+// ---------------------------------------------------------------------------
 
 // Pointers into upper-level driver
 typedef struct {
@@ -77,33 +88,62 @@ typedef struct {
                                 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 
@@ -111,12 +151,14 @@ struct disk_channel {
     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];          \
@@ -130,16 +172,49 @@ 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
@@ -168,7 +243,7 @@ struct disk_funs {
 };
 
 #define DISK_FUNS(_l,_read,_write,_get_config,_set_config)           \
-disk_funs _l = {                                                     \
+static disk_funs _l = {                                              \
   _read,                                                             \
   _write,                                                            \
   _get_config,                                                       \
@@ -177,4 +252,9 @@ disk_funs _l = {                        
 
 extern cyg_devio_table_t cyg_io_disk_devio;
 
+// ---------------------------------------------------------------------------
+
+#include <cyg/io/diskio.h>
+
+// ---------------------------------------------------------------------------
 #endif // CYGONCE_DISK_H