linux/drivers/memstick/core/ms_block.c

// SPDX-License-Identifier: GPL-2.0-only
/*
 *  ms_block.c - Sony MemoryStick (legacy) storage support

 *  Copyright (C) 2013 Maxim Levitsky <[email protected]>
 *
 * Minor portions of the driver were copied from mspro_block.c which is
 * Copyright (C) 2007 Alex Dubov <[email protected]>
 */
#define DRIVER_NAME
#define pr_fmt(fmt)

#include <linux/module.h>
#include <linux/blk-mq.h>
#include <linux/memstick.h>
#include <linux/idr.h>
#include <linux/hdreg.h>
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/random.h>
#include <linux/bitmap.h>
#include <linux/scatterlist.h>
#include <linux/jiffies.h>
#include <linux/workqueue.h>
#include <linux/mutex.h>
#include "ms_block.h"

static int debug;
static int cache_flush_timeout =;
static bool verify_writes;

/*
 * Copies section of 'sg_from' starting from offset 'offset' and with length
 * 'len' To another scatterlist of to_nents enties
 */
static size_t msb_sg_copy(struct scatterlist *sg_from,
	struct scatterlist *sg_to, int to_nents, size_t offset, size_t len)
{}

/*
 * Compares section of 'sg' starting from offset 'offset' and with length 'len'
 * to linear buffer of length 'len' at address 'buffer'
 * Returns 0 if equal and  -1 otherwice
 */
static int msb_sg_compare_to_buffer(struct scatterlist *sg,
					size_t offset, u8 *buffer, size_t len)
{}


/* Get zone at which block with logical address 'lba' lives
 * Flash is broken into zones.
 * Each zone consists of 512 eraseblocks, out of which in first
 * zone 494 are used and 496 are for all following zones.
 * Therefore zone #0 hosts blocks 0-493, zone #1 blocks 494-988, etc...
 */
static int msb_get_zone_from_lba(int lba)
{}

/* Get zone of physical block. Trivial */
static int msb_get_zone_from_pba(int pba)
{}

/* Debug test to validate free block counts */
static int msb_validate_used_block_bitmap(struct msb_data *msb)
{}

/* Mark physical block as used */
static void msb_mark_block_used(struct msb_data *msb, int pba)
{}

/* Mark physical block as free */
static void msb_mark_block_unused(struct msb_data *msb, int pba)
{}

/* Invalidate current register window */
static void msb_invalidate_reg_window(struct msb_data *msb)
{}

/* Start a state machine */
static int msb_run_state_machine(struct msb_data *msb, int   (*state_func)
		(struct memstick_dev *card, struct memstick_request **req))
{}

/* State machines call that to exit */
static int msb_exit_state_machine(struct msb_data *msb, int error)
{}

/* read INT register */
static int msb_read_int_reg(struct msb_data *msb, long timeout)
{}

/* Read a register */
static int msb_read_regs(struct msb_data *msb, int offset, int len)
{}

/* Write a card register */
static int msb_write_regs(struct msb_data *msb, int offset, int len, void *buf)
{}

/* Handler for absence of IO */
static int h_msb_default_bad(struct memstick_dev *card,
						struct memstick_request **mrq)
{}

/*
 * This function is a handler for reads of one page from device.
 * Writes output to msb->current_sg, takes sector address from msb->reg.param
 * Can also be used to read extra data only. Set params accordintly.
 */
static int h_msb_read_page(struct memstick_dev *card,
					struct memstick_request **out_mrq)
{}

/*
 * Handler of writes of exactly one block.
 * Takes address from msb->regs.param.
 * Writes same extra data to blocks, also taken
 * from msb->regs.extra
 * Returns -EBADMSG if write fails due to uncorrectable error, or -EIO if
 * device refuses to take the command or something else
 */
static int h_msb_write_block(struct memstick_dev *card,
					struct memstick_request **out_mrq)
{}

/*
 * This function is used to send simple IO requests to device that consist
 * of register write + command
 */
static int h_msb_send_command(struct memstick_dev *card,
					struct memstick_request **out_mrq)
{}

/* Small handler for card reset */
static int h_msb_reset(struct memstick_dev *card,
					struct memstick_request **out_mrq)
{}

/* This handler is used to do serial->parallel switch */
static int h_msb_parallel_switch(struct memstick_dev *card,
					struct memstick_request **out_mrq)
{}

static int msb_switch_to_parallel(struct msb_data *msb);

/* Reset the card, to guard against hw errors beeing treated as bad blocks */
static int msb_reset(struct msb_data *msb, bool full)
{}

/* Attempts to switch interface to parallel mode */
static int msb_switch_to_parallel(struct msb_data *msb)
{}

/* Changes overwrite flag on a page */
static int msb_set_overwrite_flag(struct msb_data *msb,
						u16 pba, u8 page, u8 flag)
{}

static int msb_mark_bad(struct msb_data *msb, int pba)
{}

static int msb_mark_page_bad(struct msb_data *msb, int pba, int page)
{}

/* Erases one physical block */
static int msb_erase_block(struct msb_data *msb, u16 pba)
{}

/* Reads one page from device */
static int msb_read_page(struct msb_data *msb,
	u16 pba, u8 page, struct ms_extra_data_register *extra,
					struct scatterlist *sg,  int offset)
{}

/* Reads oob of page only */
static int msb_read_oob(struct msb_data *msb, u16 pba, u16 page,
	struct ms_extra_data_register *extra)
{}

/* Reads a block and compares it with data contained in scatterlist orig_sg */
static int msb_verify_block(struct msb_data *msb, u16 pba,
				struct scatterlist *orig_sg,  int offset)
{}

/* Writes exectly one block + oob */
static int msb_write_block(struct msb_data *msb,
			u16 pba, u32 lba, struct scatterlist *sg, int offset)
{}

/* Finds a free block for write replacement */
static u16 msb_get_free_block(struct msb_data *msb, int zone)
{}

static int msb_update_block(struct msb_data *msb, u16 lba,
	struct scatterlist *sg, int offset)
{}

/* Converts endiannes in the boot block for easy use */
static void msb_fix_boot_page_endianness(struct ms_boot_page *p)
{}

static int msb_read_boot_blocks(struct msb_data *msb)
{}

static int msb_read_bad_block_table(struct msb_data *msb, int block_nr)
{}

static int msb_ftl_initialize(struct msb_data *msb)
{}

static int msb_ftl_scan(struct msb_data *msb)
{}

static void msb_cache_flush_timer(struct timer_list *t)
{}


static void msb_cache_discard(struct msb_data *msb)
{}

static int msb_cache_init(struct msb_data *msb)
{}

static int msb_cache_flush(struct msb_data *msb)
{}

static int msb_cache_write(struct msb_data *msb, int lba,
	int page, bool add_to_cache_only, struct scatterlist *sg, int offset)
{}

static int msb_cache_read(struct msb_data *msb, int lba,
				int page, struct scatterlist *sg, int offset)
{}

/* Emulated geometry table
 * This table content isn't that importaint,
 * One could put here different values, providing that they still
 * cover whole disk.
 * 64 MB entry is what windows reports for my 64M memstick
 */

static const struct chs_entry chs_table[] =;

/* Load information about the card */
static int msb_init_card(struct memstick_dev *card)
{}

static int msb_do_write_request(struct msb_data *msb, int lba,
	int page, struct scatterlist *sg, size_t len, int *sucessfuly_written)
{}

static int msb_do_read_request(struct msb_data *msb, int lba,
		int page, struct scatterlist *sg, int len, int *sucessfuly_read)
{}

static void msb_io_work(struct work_struct *work)
{}

static DEFINE_IDR(msb_disk_idr); /*set of used disk numbers */
static DEFINE_MUTEX(msb_disk_lock); /* protects against races in open/release */

static void msb_data_clear(struct msb_data *msb)
{}

static int msb_bd_getgeo(struct block_device *bdev,
				 struct hd_geometry *geo)
{}

static void msb_bd_free_disk(struct gendisk *disk)
{}

static blk_status_t msb_queue_rq(struct blk_mq_hw_ctx *hctx,
				 const struct blk_mq_queue_data *bd)
{}

static int msb_check_card(struct memstick_dev *card)
{}

static void msb_stop(struct memstick_dev *card)
{}

static void msb_start(struct memstick_dev *card)
{}

static const struct block_device_operations msb_bdops =;

static const struct blk_mq_ops msb_mq_ops =;

/* Registers the block device */
static int msb_init_disk(struct memstick_dev *card)
{}

static int msb_probe(struct memstick_dev *card)
{}

static void msb_remove(struct memstick_dev *card)
{}

#ifdef CONFIG_PM

static int msb_suspend(struct memstick_dev *card, pm_message_t state)
{}

static int msb_resume(struct memstick_dev *card)
{}
#else

#define msb_suspend
#define msb_resume

#endif /* CONFIG_PM */

static struct memstick_device_id msb_id_tbl[] =;
MODULE_DEVICE_TABLE(memstick, msb_id_tbl);


static struct memstick_driver msb_driver =;

static int __init msb_init(void)
{}

static void __exit msb_exit(void)
{}

module_init();
module_exit(msb_exit);

module_param(cache_flush_timeout, int, S_IRUGO);
MODULE_PARM_DESC();
module_param(debug, int, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC();

module_param(verify_writes, bool, S_IRUGO);
MODULE_PARM_DESC();

MODULE_LICENSE();
MODULE_AUTHOR();
MODULE_DESCRIPTION();