Mercurial > nand-ecoscentric
changeset 3397:4cce65f46b89
io/nand: Add mechanism for devices to provide partition geometry later than device init time
| author | Ross Younger <wry@ecoscentric.com> |
|---|---|
| date | Sat, 06 Dec 2014 13:13:54 +1300 |
| parents | ca49a7404897 |
| children | aecb165864c8 |
| files | packages/io/nand/current/ChangeLog packages/io/nand/current/include/nand_device.h packages/io/nand/current/src/nand.c |
| diffstat | 3 files changed, 54 insertions(+), 11 deletions(-) [+] |
line wrap: on
line diff
--- a/packages/io/nand/current/ChangeLog +++ b/packages/io/nand/current/ChangeLog @@ -1,6 +1,8 @@ 2014-12-06 Ross Younger <wry@ecoscentric.com> * src/nandinit.cxx: Another tweak to initialiser priority + * include/nand_device.h src/nand.c: Add mechanism for devices to + provide partition geometry later than device init time 2014-12-02 Ross Younger <wry@ecoscentric.com>
--- a/packages/io/nand/current/include/nand_device.h +++ b/packages/io/nand/current/include/nand_device.h @@ -230,9 +230,35 @@ struct _cyg_nand_device_t { /* Data about the device need not be defined statically. Indeed * it is usually preferable to autodetect parameters when the chip * is initialised. The details here need only be set at some point - * before fns->devinit() returns. */ + * before fns->devinit() returns. + * Some devices may wish to store a partition table on the device + * itself, which is harder as it leads to a chicken-and-egg problem; + * in that case, fns->devinit() should set dev->plf_update_partitions, + * which the infrastructure will call later. + */ + cyg_nand_partition partition[CYGNUM_NAND_MAX_PARTITIONS]; - cyg_nand_partition partition[CYGNUM_NAND_MAX_PARTITIONS]; + /* If present (set up by dev->devinit()) this function will be + * called on the first call to cyg_nand_get_partition(). + * On exit it is expected to have updated dev->partition[]. + * + * Return 0 if OK, or a negative error code if something went wrong. + * + * NOTE: This function will be called WITHOUT the device lock held + * and is expected to assert that lock only as far as necessary + * (in particular, when updating the partition table contents). + * + * NOTE: If something happens that makes it desirable to update + * the in-RAM partition table at runtime, you can call this + * function directly. If you do this, BEWARE: any existing + * clients will start using the updated geometry immediately. + * If a partition has ceased to be valid then its clients will + * immediately start returning errors! + */ + int (*plf_update_partitions)(cyg_nand_device *dev); + + /* Used by the infrastructure. */ + cyg_bool plf_update_partitions_called; size_t page_bits; /* log2 of no of regular bytes per page */ size_t spare_per_page; /* OOB area size in bytes */
--- a/packages/io/nand/current/src/nand.c +++ b/packages/io/nand/current/src/nand.c @@ -166,11 +166,33 @@ static cyg_nand_printf nand_default_pf; nand_default_pf = pf; } +static void announce_partitions(cyg_nand_device *dev) +{ + int i, live_partitions = 0; + for (i=0; i<CYGNUM_NAND_MAX_PARTITIONS; i++) + if (dev->partition[i].dev) ++live_partitions; + if (live_partitions) + NAND_CHATTER(1,dev, "%s: %u partition%c configured\n", dev->devname, live_partitions, live_partitions==1 ? ' ' : 's' ); + else + NAND_CHATTER(1,dev, "%s: NO partitions configured!\n", dev->devname); // hope they know what they're doing. +} + __externC cyg_nand_partition* cyg_nand_get_partition(cyg_nand_device *dev, unsigned partno) { if ((partno < 0) || (partno >= CYGNUM_NAND_MAX_PARTITIONS)) return NULL; + if (!dev->plf_update_partitions_called) { + dev->plf_update_partitions_called = true; // Set this before the actual call, to kill a chicken-and-egg recursion where partition 0 needs to be read in order to determine the geometry of the other partitions. + if (dev->plf_update_partitions != NULL) { + int st = dev->plf_update_partitions(dev); + if (st != 0) { + NAND_ERROR(dev, "%s: Partition table update failed (code %d)\n", dev->devname, st); + // Well, we tried. + } + } + announce_partitions(dev); + } LOCK_DEV(dev); cyg_nand_partition *rv = &(dev->partition[partno]); UNLOCK_DEV(dev); @@ -279,17 +301,10 @@ int cyg_nand_lookup(const char *devname, goto done; } #endif - cyg_drv_mutex_init(&dev->devlock); + dev->plf_update_partitions_called = false; dev->is_inited = 1; - - int live_partitions = 0; - for (i=0; i<CYGNUM_NAND_MAX_PARTITIONS; i++) - if (dev->partition[i].dev) ++live_partitions; - if (live_partitions) - NAND_CHATTER(1,dev, "%s devinit complete, %u partition%c configured\n", devname, live_partitions, live_partitions==1 ? ' ' : 's' ); - else - NAND_CHATTER(1,dev, "%s devinit complete, NO partitions configured!\n", devname); // hope they know what they're doing. + announce_partitions(dev); } if (dev_o) *dev_o = dev; }
