4040 ****************************************************************************/
4141
4242#include <tinyara/config.h>
43-
4443#include <errno.h>
4544#include <debug.h>
4645#include <stdio.h>
47-
4846#include <tinyara/kmalloc.h>
4947#include <tinyara/fs/mtd.h>
50-
5148#include "dhara/map.h"
5249#include "dhara/nand.h"
5350
5754/****************************************************************************
5855 * Pre-processor Definitions
5956 ****************************************************************************/
60-
57+ #define CONFIG_DHARA_METADATA_NCACHES 8
6158/****************************************************************************
6259 * Private Types
6360 ****************************************************************************/
64-
6561struct dhara_pagecache_s {
6662 dq_entry_t node ;
6763 dhara_page_t page ;
6864 FAR uint8_t * buffer ;
6965};
7066
7167typedef struct dhara_pagecache_s dhara_pagecache_t ;
68+ struct dhara_metadatacache_s {
69+ dq_entry_t node ;
70+ dhara_page_t page ; /* Page number for this metadata */
71+ FAR uint8_t * buffer ; /* 132-byte metadata buffer */
72+ };
7273
74+ typedef struct dhara_metadatacache_s dhara_metadatacache_t ;
7375struct dhara_dev_s {
7476 struct dhara_nand nand ;
7577 struct dhara_map map ;
@@ -91,6 +93,8 @@ struct dhara_dev_s {
9193
9294 struct dq_queue_s readcache ;
9395 dhara_pagecache_t readpage [CONFIG_DHARA_READ_NCACHES ];
96+ struct dq_queue_s metadatacache ;
97+ dhara_metadatacache_t metadata [CONFIG_DHARA_METADATA_NCACHES ];
9498};
9599
96100typedef struct dhara_dev_s dhara_dev_t ;
@@ -269,7 +273,6 @@ static void dhara_discard_readcache(FAR dhara_dev_t *dev, dhara_page_t page)
269273 }
270274 }
271275}
272-
273276static void dhara_update_readcache (FAR dhara_dev_t * dev , dhara_page_t page , FAR const uint8_t * data )
274277{
275278 FAR dhara_pagecache_t * cache ;
@@ -294,6 +297,129 @@ static void dhara_update_readcache(FAR dhara_dev_t *dev, dhara_page_t page, FAR
294297 * Description: Open the block device
295298 *
296299 ****************************************************************************/
300+ /****************************************************************************
301+ * Name: dhara_init_metadatacache
302+ ****************************************************************************/
303+ static int dhara_init_metadatacache (FAR dhara_dev_t * dev )
304+ {
305+ FAR dq_queue_t * q = & dev -> metadatacache ;
306+ int i = 0 ;
307+
308+ dq_init (q );
309+
310+ do {
311+ dev -> metadata [i ].page = DHARA_PAGE_NONE ;
312+ dev -> metadata [i ].buffer = kmm_malloc (2048 );
313+ dq_addfirst (& dev -> metadata [i ].node , q );
314+ } while (dev -> metadata [i ++ ].buffer && i < CONFIG_DHARA_METADATA_NCACHES );
315+ return i == CONFIG_DHARA_METADATA_NCACHES ? 0 : - ENOMEM ;
316+ }
317+
318+ /****************************************************************************
319+ * Name: dhara_deinit_metadatacache
320+ ****************************************************************************/
321+ static void dhara_deinit_metadatacache (FAR dhara_dev_t * dev )
322+ {
323+ int i ;
324+
325+ for (i = 0 ; i < CONFIG_DHARA_METADATA_NCACHES ; i ++ ) {
326+ if (dev -> metadata [i ].buffer ) {
327+ kmm_free (dev -> metadata [i ].buffer );
328+ }
329+ }
330+ }
331+
332+ /****************************************************************************
333+ * Name: dhara_find_metadatacache
334+ ****************************************************************************/
335+ static uint8_t * dhara_find_metadatacache (FAR dhara_dev_t * dev , dhara_page_t page )
336+ {
337+ FAR dq_queue_t * q = & dev -> metadatacache ;
338+ FAR dhara_metadatacache_t * cache ;
339+ FAR dq_entry_t * c ;
340+
341+ for (c = dq_peek (q ); c ; c = dq_next (c )) {
342+ cache = (FAR dhara_metadatacache_t * ) c ;
343+ if (cache -> page == page ) {
344+ dq_rem (c , q );
345+ dq_addfirst (c , q );
346+ return cache -> buffer ;
347+ }
348+ }
349+
350+ return NULL ;
351+ }
352+
353+ /****************************************************************************
354+ * Name: dhara_grab_metadatacache
355+ ****************************************************************************/
356+ static dhara_metadatacache_t * dhara_grab_metadatacache (FAR dhara_dev_t * dev )
357+ {
358+ FAR dq_queue_t * q = & dev -> metadatacache ;
359+ FAR dhara_metadatacache_t * cache ;
360+ FAR dq_entry_t * c ;
361+
362+ c = dq_tail (q );
363+ dq_rem (c , q );
364+ cache = (FAR dhara_metadatacache_t * ) c ;
365+ cache -> page = DHARA_PAGE_NONE ;
366+ return cache ;
367+ }
368+
369+ /****************************************************************************
370+ * Name: dhara_insert_metadatacache
371+ ****************************************************************************/
372+ static void dhara_insert_metadatacache (FAR dhara_dev_t * dev , dhara_metadatacache_t * cache )
373+ {
374+ FAR dq_queue_t * q = & dev -> metadatacache ;
375+
376+ if (cache -> page != DHARA_PAGE_NONE ) {
377+ dq_addfirst ((dq_entry_t * ) cache , q );
378+ } else {
379+ dq_addlast ((dq_entry_t * ) cache , q );
380+ }
381+ }
382+
383+ /****************************************************************************
384+ * Name: dhara_update_metadatacache
385+ ****************************************************************************/
386+ static void dhara_update_metadatacache (FAR dhara_dev_t * dev , dhara_page_t page , FAR const uint8_t * data )
387+ {
388+ FAR dq_queue_t * q = & dev -> metadatacache ;
389+ FAR dhara_metadatacache_t * cache ;
390+ FAR dq_entry_t * c ;
391+
392+ for (c = dq_peek (q ); c ; c = dq_next (c )) {
393+ cache = (FAR dhara_metadatacache_t * ) c ;
394+ if (cache -> page == page ) {
395+ cache -> page = page ;
396+ memcpy (cache -> buffer , data , dev -> geo .blocksize );
397+ dq_rem (c , q );
398+ dq_addfirst (c , q );
399+ break ;
400+ }
401+ }
402+ }
403+
404+ /****************************************************************************
405+ * Name: dhara_discard_metadatacache
406+ ****************************************************************************/
407+ static void dhara_discard_metadatacache (FAR dhara_dev_t * dev , dhara_page_t page )
408+ {
409+ FAR dq_queue_t * q = & dev -> metadatacache ;
410+ FAR dhara_metadatacache_t * cache ;
411+ FAR dq_entry_t * c ;
412+
413+ for (c = dq_peek (q ); c ; c = dq_next (c )) {
414+ cache = (FAR dhara_metadatacache_t * ) c ;
415+ if (cache -> page == page ) {
416+ cache -> page = DHARA_PAGE_NONE ;
417+ dq_rem (c , q );
418+ dq_addlast (c , q );
419+ break ;
420+ }
421+ }
422+ }
297423
298424static int dhara_open (FAR struct inode * inode )
299425{
@@ -525,22 +651,30 @@ int dhara_nand_erase(FAR const struct dhara_nand *n, dhara_block_t bno, FAR dhar
525651 for (i = 0 ; i < dev -> blkper ; i ++ ) {
526652 dhara_discard_readcache (dev , pno + i );
527653 }
528-
654+ dhara_page_t metadata_page = pno + dev -> blkper - 1 ;
655+ dhara_discard_metadatacache (dev , metadata_page );
529656 return 0 ;
530657}
531658
532659int dhara_nand_prog (FAR const struct dhara_nand * n , dhara_page_t p , FAR const uint8_t * data , FAR dhara_error_t * err )
533660{
534661 FAR dhara_dev_t * dev = (FAR dhara_dev_t * ) n ;
535662 int ret ;
663+ int page_in_block = p %64 ;
536664
537665 ret = MTD_BWRITE (dev -> mtd , p , 1 , data );
538666 if (ret < 0 ) {
539667 dhara_set_error (err , DHARA_E_BAD_BLOCK );
540668 return ret ;
541669 }
542-
670+ if (ret < 0 ) {
671+ dhara_set_error (err , DHARA_E_BAD_BLOCK );
672+ return ret ;
673+ }
543674 dhara_update_readcache (dev , p , data );
675+ if (page_in_block == 15 || page_in_block == 31 || page_in_block == 47 || page_in_block == 63 ) {
676+ dhara_update_metadatacache (dev , p , data );
677+ }
544678 return 0 ;
545679}
546680
@@ -550,53 +684,84 @@ int dhara_nand_is_free(FAR const struct dhara_nand *n, dhara_page_t p)
550684 size_t page_size = 1 << n -> log2_page_size ;
551685 FAR uint8_t * buf = dev -> pagebuf ;
552686 dhara_error_t err ;
553-
554687 if (dhara_nand_read (n , p , 0 , page_size , buf , & err ) < 0 ) {
555688 ferr ("Fail to read page for free check err %s\n" , dhara_strerror (err ));
556689 return 0 ;
557690 }
558691
559692 return dhara_check_ff (buf , page_size );
560693}
561-
562694int dhara_nand_read (FAR const struct dhara_nand * n , dhara_page_t p , size_t offset , size_t length , FAR uint8_t * data , dhara_error_t * err )
563695{
564696 FAR dhara_dev_t * dev = (FAR dhara_dev_t * ) n ;
565697 FAR dhara_pagecache_t * cache ;
698+ FAR dhara_metadatacache_t * mcache ;
699+
566700 FAR uint8_t * buf ;
567701 int ret ;
702+ int page_in_block = p % 64 ;
568703
704+ if (page_in_block == 15 || page_in_block == 31 || page_in_block == 47 || page_in_block == 63 ) {
705+
706+ /* Check metadata cache */
707+ buf = dhara_find_metadatacache (dev , p );
708+ if (buf ) {
709+ memcpy (data , buf + offset , length );
710+ return 0 ;
711+ }
712+ mcache = dhara_grab_metadatacache (dev );
713+ ret = MTD_BREAD (dev -> mtd , p , 1 , mcache -> buffer );
714+ if (ret == - EUCLEAN ) {
715+ ret = 0 ;
716+ }
717+ if (ret < 0 ) {
718+ dhara_insert_metadatacache (dev , mcache );
719+ dhara_set_error (err , DHARA_E_ECC );
720+ return ret ;
721+ }
722+ memcpy (data , mcache -> buffer + offset , length );
723+ mcache -> page = p ;
724+ dhara_insert_metadatacache (dev , mcache );
725+
726+ } else {
727+ /* Check data page cache first */
569728 buf = dhara_find_readcache (dev , p );
570729 if (buf ) {
571730 memcpy (data , buf + offset , length );
572731 return 0 ;
573732 }
574733
734+ /* Grab a cache entry */
575735 cache = dhara_grab_readcache (dev );
736+
737+ /* Read page from flash */
576738 ret = MTD_BREAD (dev -> mtd , p , 1 , cache -> buffer );
577- if (ret == - EUCLEAN ) {
578- ret = 0 ; /* Ignore the correctable ECC error */
579- }
739+ if (ret == - EUCLEAN )
740+ ret = 0 ; /* Ignore correctable ECC error */
580741
581742 if (ret < 0 ) {
582743 dhara_insert_readcache (dev , cache );
583744 dhara_set_error (err , DHARA_E_ECC );
584745 return ret ;
585746 }
586747
748+ /* Copy requested data */
587749 memcpy (data , cache -> buffer + offset , length );
588750 cache -> page = p ;
589751 dhara_insert_readcache (dev , cache );
752+
753+ /* Check if this is a metadata page and cache it */
754+ }
590755 return ret >= 0 ? OK : ret ;
591756}
592757
758+
593759int dhara_nand_copy (FAR const struct dhara_nand * n , dhara_page_t src , dhara_page_t dst , FAR dhara_error_t * err )
594760{
595761 FAR dhara_dev_t * dev = (FAR dhara_dev_t * ) n ;
596762 size_t page_size = 1 << n -> log2_page_size ;
597763 FAR uint8_t * buf = dev -> pagebuf ;
598764 int ret ;
599-
600765 ret = dhara_nand_read (n , src , 0 , page_size , buf , err );
601766 if (ret < 0 ) {
602767 ferr ("src_page %d, ret %d failed: %s\n" , src , ret , dhara_strerror (* err ));
@@ -682,7 +847,7 @@ int dhara_initialize_by_path(FAR const char *path, FAR struct mtd_dev_s *mtd)
682847 if (ret != 0 ) {
683848 goto err ;
684849 }
685-
850+ ret = dhara_init_metadatacache ( dev );
686851 dhara_map_init (& dev -> map , & dev -> nand , dev -> pagebuf + dev -> geo .blocksize , CONFIG_DHARA_GC_RATIO );
687852
688853 dhara_map_resume (& dev -> map , NULL );
@@ -702,6 +867,7 @@ int dhara_initialize_by_path(FAR const char *path, FAR struct mtd_dev_s *mtd)
702867err :
703868 sem_destroy (& dev -> lock );
704869 dhara_deinit_readcache (dev );
870+ dhara_deinit_metadatacache (dev );
705871 kmm_free (dev -> pagebuf );
706872 kmm_free (dev );
707873 return ret ;
@@ -719,7 +885,7 @@ int dhara_initialize_by_path(FAR const char *path, FAR struct mtd_dev_s *mtd)
719885 * mtd - The MTD device that supports the FLASH interface.
720886 *
721887 ****************************************************************************/
722-
888+ //extern int cache_init(FAR const struct dhara_nand *n,FAR uint8_t *data);
723889int dhara_initialize (int minor , FAR struct mtd_dev_s * mtd )
724890{
725891 char path [PATH_MAX ];
0 commit comments