^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /* SPDX-License-Identifier: GPL-2.0-only */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Copyright © 2009 - Maxim Levitsky
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * SmartMedia/xD translation layer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Based loosly on ssfdc.c which is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * © 2005 Eptar srl
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Author: Claudio Lanconelli <lanconelli.claudio@eptar.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/mtd/blktrans.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/kfifo.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/sched.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/completion.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/mtd/mtd.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) struct ftl_zone {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) bool initialized;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) int16_t *lba_to_phys_table; /* LBA to physical table */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) struct kfifo free_sectors; /* queue of free sectors */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) struct sm_ftl {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) struct mtd_blktrans_dev *trans;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) struct mutex mutex; /* protects the structure */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) struct ftl_zone *zones; /* FTL tables for each zone */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) /* Media information */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) int block_size; /* block size in bytes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) int zone_size; /* zone size in blocks */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) int zone_count; /* number of zones */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) int max_lba; /* maximum lba in a zone */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) int smallpagenand; /* 256 bytes/page nand */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) bool readonly; /* is FS readonly */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) bool unstable;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) int cis_block; /* CIS block location */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) int cis_boffset; /* CIS offset in the block */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) int cis_page_offset; /* CIS offset in the page */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) void *cis_buffer; /* tmp buffer for cis reads */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) /* Cache */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) int cache_block; /* block number of cached block */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) int cache_zone; /* zone of cached block */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) unsigned char *cache_data; /* cached block data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) long unsigned int cache_data_invalid_bitmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) bool cache_clean;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) struct work_struct flush_work;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) struct timer_list timer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) /* Geometry stuff */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) int heads;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) int sectors;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) int cylinders;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) struct attribute_group *disk_attributes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) struct chs_entry {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) unsigned long size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) unsigned short cyl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) unsigned char head;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) unsigned char sec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) #define SM_FTL_PARTN_BITS 3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) #define sm_printk(format, ...) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) printk(KERN_WARNING "sm_ftl" ": " format "\n", ## __VA_ARGS__)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) #define dbg(format, ...) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) if (debug) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) printk(KERN_DEBUG "sm_ftl" ": " format "\n", ## __VA_ARGS__)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) #define dbg_verbose(format, ...) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) if (debug > 1) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) printk(KERN_DEBUG "sm_ftl" ": " format "\n", ## __VA_ARGS__)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) static int sm_erase_block(struct sm_ftl *ftl, int zone_num, uint16_t block,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) int put_free);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) static void sm_mark_block_bad(struct sm_ftl *ftl, int zone_num, int block);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) static int sm_recheck_media(struct sm_ftl *ftl);