Use generic block layer to access the drives and do partition parsing
Change all relevant blockdevice users to the simplified interface. Signed-off-by: Juergen Beisert <jbe@pengutronix.de> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
This commit is contained in:
parent
967a2675ba
commit
82db23d3f4
|
@ -1,5 +1,7 @@
|
|||
menuconfig DISK
|
||||
select BLOCK
|
||||
select PARTITION
|
||||
select PARTITION_DISK
|
||||
bool "Disk support "
|
||||
help
|
||||
Add support for disk like drives like harddisks, CDROMs, SD cards and
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2009 Juergen Beisert, Pengutronix
|
||||
* Copyright (C) 2009...2011 Juergen Beisert, Pengutronix
|
||||
*
|
||||
* Mostly stolen from the GRUB2 project
|
||||
* Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2006,2007,2008 Free Software Foundation, Inc.
|
||||
|
@ -43,15 +43,13 @@
|
|||
* Note: This driver does only support LBA addressing. Currently no CHS!
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <linux/types.h>
|
||||
#include <common.h>
|
||||
#include <init.h>
|
||||
#include <driver.h>
|
||||
#include <string.h>
|
||||
#include <xfuncs.h>
|
||||
#include <asm/syslib.h>
|
||||
#include <ata.h>
|
||||
#include <errno.h>
|
||||
#include <block.h>
|
||||
#include <disks.h>
|
||||
#include <malloc.h>
|
||||
|
||||
/**
|
||||
* Sector count handled in one count
|
||||
|
@ -61,9 +59,6 @@
|
|||
*/
|
||||
#define SECTORS_AT_ONCE 64
|
||||
|
||||
/** Size of one sector in bytes */
|
||||
#define SECTOR_SIZE 512
|
||||
|
||||
/** Command to read sectors from media */
|
||||
#define BIOS_READ_CMD 0
|
||||
|
||||
|
@ -89,10 +84,13 @@ struct DAPS
|
|||
* Collection of data we need to know about the connected drive
|
||||
*/
|
||||
struct media_access {
|
||||
struct block_device blk; /**< the main device */
|
||||
int drive_no; /**< drive number used by the BIOS */
|
||||
int is_cdrom; /**< drive is a CDROM e.g. no write support */
|
||||
};
|
||||
|
||||
#define to_media_access(x) container_of((x), struct media_access, blk)
|
||||
|
||||
/**
|
||||
* Scratch memory for BIOS communication to handle data in chunks of 32 kiB
|
||||
*
|
||||
|
@ -146,19 +144,23 @@ static int biosdisk_bios_call(struct media_access *media, int cmd, uint64_t sect
|
|||
|
||||
/**
|
||||
* Read a chunk of sectors from media
|
||||
* @param dev our data we need to do the access
|
||||
* @param sector_start Sector's LBA number to start read from
|
||||
* @param sector_count Sectors to read
|
||||
* @param blk All info about the block device we need
|
||||
* @param buffer Buffer to read into
|
||||
* @param block Sector's LBA number to start read from
|
||||
* @param num_blocks Sector count to read
|
||||
* @return 0 on success, anything else on failure
|
||||
*
|
||||
* This routine expects the buffer has the correct size to store all data!
|
||||
*
|
||||
* @note Due to 'block' is of type 'int' only small disks can be handled!
|
||||
*/
|
||||
static int biosdisk_read(struct device_d *dev, uint64_t sector_start, unsigned sector_count, void *buffer)
|
||||
static int biosdisk_read(struct block_device *blk, void *buffer, int block,
|
||||
int num_blocks)
|
||||
{
|
||||
int rc;
|
||||
struct ata_interface *intf = dev->platform_data;
|
||||
struct media_access *media = intf->priv;
|
||||
uint64_t sector_start = block;
|
||||
unsigned sector_count = num_blocks;
|
||||
struct media_access *media = to_media_access(blk);
|
||||
|
||||
while (sector_count >= SECTORS_AT_ONCE) {
|
||||
rc = biosdisk_bios_call(media, BIOS_READ_CMD, sector_start, SECTORS_AT_ONCE, scratch_buffer);
|
||||
|
@ -182,19 +184,23 @@ static int biosdisk_read(struct device_d *dev, uint64_t sector_start, unsigned s
|
|||
|
||||
/**
|
||||
* Write a chunk of sectors to media
|
||||
* @param dev our data we need to do the access
|
||||
* @param sector_start Sector's LBA number to start write to
|
||||
* @param sector_count Sectors to write
|
||||
* @param blk All info about the block device we need
|
||||
* @param buffer Buffer to write from
|
||||
* @param block Sector's LBA number to start write to
|
||||
* @param num_blocks Sector count to write
|
||||
* @return 0 on success, anything else on failure
|
||||
*
|
||||
* This routine expects the buffer has the correct size to read all data!
|
||||
*
|
||||
* @note Due to 'block' is of type 'int' only small disks can be handled!
|
||||
*/
|
||||
static int biosdisk_write(struct device_d *dev, uint64_t sector_start, unsigned sector_count, const void *buffer)
|
||||
static int __maybe_unused biosdisk_write(struct block_device *blk,
|
||||
const void *buffer, int block, int num_blocks)
|
||||
{
|
||||
int rc;
|
||||
struct ata_interface *intf = dev->platform_data;
|
||||
struct media_access *media = intf->priv;
|
||||
uint64_t sector_start = block;
|
||||
unsigned sector_count = num_blocks;
|
||||
struct media_access *media = to_media_access(blk);
|
||||
|
||||
while (sector_count >= SECTORS_AT_ONCE) {
|
||||
__builtin_memcpy(scratch_buffer, buffer, sizeof(scratch_buffer));
|
||||
|
@ -216,6 +222,13 @@ static int biosdisk_write(struct device_d *dev, uint64_t sector_start, unsigned
|
|||
return rc;
|
||||
}
|
||||
|
||||
static struct block_device_ops bios_ata = {
|
||||
.read = biosdisk_read,
|
||||
#ifdef CONFIG_BLOCK_WRITE
|
||||
.write = biosdisk_write,
|
||||
#endif
|
||||
};
|
||||
|
||||
/**
|
||||
* Probe for connected drives and register them
|
||||
*
|
||||
|
@ -228,8 +241,6 @@ static int biosdisk_probe(struct device_d *dev)
|
|||
{
|
||||
int drive, rc;
|
||||
struct media_access media, *m;
|
||||
struct device_d *drive_dev;
|
||||
struct ata_interface *p;
|
||||
|
||||
for (drive = 0x80; drive < 0x90; drive++) {
|
||||
media.drive_no = drive;
|
||||
|
@ -240,27 +251,32 @@ static int biosdisk_probe(struct device_d *dev)
|
|||
|
||||
printf("BIOSdrive %d seems valid. Registering...\n", media.drive_no);
|
||||
|
||||
drive_dev = xzalloc(sizeof(struct device_d) + sizeof(struct media_access) + sizeof(struct ata_interface));
|
||||
if (drive_dev == NULL) {
|
||||
dev_err(dev, "Out of memory\n");
|
||||
return -1;
|
||||
m = xzalloc(sizeof(struct media_access));
|
||||
|
||||
m->blk.dev = dev;
|
||||
m->blk.ops = &bios_ata;
|
||||
/*
|
||||
* keep the 'blk.num_blocks' member 0, as we don't know
|
||||
* the size of this disk yet!
|
||||
*/
|
||||
rc = cdev_find_free_index("disk");
|
||||
if (rc < 0)
|
||||
pr_err("Cannot find a free number for the disk node\n");
|
||||
m->blk.cdev.name = asprintf("disk%d", rc);
|
||||
m->blk.blockbits = SECTOR_SHIFT;
|
||||
|
||||
rc = blockdevice_register(&m->blk);
|
||||
if (rc != 0) {
|
||||
dev_err(dev, "Cannot register BIOSdrive %d\n",
|
||||
media.drive_no);
|
||||
free(m);
|
||||
return rc;
|
||||
}
|
||||
m = (struct media_access*)&drive_dev[1];
|
||||
p = (struct ata_interface*)&m[1];
|
||||
|
||||
m->drive_no = drive;
|
||||
m->is_cdrom = 0;
|
||||
|
||||
p->write = biosdisk_write;
|
||||
p->read = biosdisk_read;
|
||||
p->priv = m;
|
||||
|
||||
strcpy(drive_dev->name, "biosdisk");
|
||||
drive_dev->id = drive - 0x80;
|
||||
drive_dev->resource[0].start = 0;
|
||||
drive_dev->platform_data = p;
|
||||
|
||||
register_device(drive_dev);
|
||||
/* create partitions on demand */
|
||||
rc = parse_partition_table(&m->blk);
|
||||
if (rc != 0)
|
||||
dev_warn(dev, "No partition table found\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
menuconfig MCI
|
||||
bool "MCI drivers "
|
||||
select DISK
|
||||
select DISK_DRIVE
|
||||
help
|
||||
Add support for MCI drivers, used to handle MMC and SD cards
|
||||
|
||||
|
|
|
@ -36,7 +36,8 @@
|
|||
#include <errno.h>
|
||||
#include <asm-generic/div64.h>
|
||||
#include <asm/byteorder.h>
|
||||
#include <ata.h>
|
||||
#include <block.h>
|
||||
#include <disks.h>
|
||||
|
||||
#define MAX_BUFFER_NUMBER 0xffffffff
|
||||
|
||||
|
@ -104,10 +105,10 @@ static void *sector_buf;
|
|||
* @param mci_dev MCI instance
|
||||
* @param src Where to read from to write to the card
|
||||
* @param blocknum Block number to write
|
||||
* @param blocks Block count to write
|
||||
* @return Transaction status (0 on success)
|
||||
*/
|
||||
#ifdef CONFIG_MCI_WRITE
|
||||
static int mci_block_write(struct device_d *mci_dev, const void *src, unsigned blocknum,
|
||||
static int mci_block_write(struct device_d *mci_dev, const void *src, int blocknum,
|
||||
int blocks)
|
||||
{
|
||||
struct mci *mci = GET_MCI_DATA(mci_dev);
|
||||
|
@ -154,7 +155,6 @@ static int mci_block_write(struct device_d *mci_dev, const void *src, unsigned b
|
|||
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Read one block of data from the card
|
||||
|
@ -163,7 +163,7 @@ static int mci_block_write(struct device_d *mci_dev, const void *src, unsigned b
|
|||
* @param blocknum Block number to read
|
||||
* @param blocks number of blocks to read
|
||||
*/
|
||||
static int mci_read_block(struct device_d *mci_dev, void *dst, unsigned blocknum,
|
||||
static int mci_read_block(struct device_d *mci_dev, void *dst, int blocknum,
|
||||
int blocks)
|
||||
{
|
||||
struct mci *mci = GET_MCI_DATA(mci_dev);
|
||||
|
@ -856,14 +856,14 @@ static int mci_startup(struct device_d *mci_dev)
|
|||
mci_extract_card_capacity_from_csd(mci_dev);
|
||||
|
||||
/* sanitiy? */
|
||||
if (mci->read_bl_len > 512) {
|
||||
mci->read_bl_len = 512;
|
||||
if (mci->read_bl_len > SECTOR_SIZE) {
|
||||
mci->read_bl_len = SECTOR_SIZE;
|
||||
pr_debug("Limiting max. read block size down to %u\n",
|
||||
mci->read_bl_len);
|
||||
}
|
||||
|
||||
if (mci->write_bl_len > 512) {
|
||||
mci->write_bl_len = 512;
|
||||
if (mci->write_bl_len > SECTOR_SIZE) {
|
||||
mci->write_bl_len = SECTOR_SIZE;
|
||||
pr_debug("Limiting max. write block size down to %u\n",
|
||||
mci->read_bl_len);
|
||||
}
|
||||
|
@ -994,73 +994,68 @@ static int sd_send_if_cond(struct device_d *mci_dev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* ------------------ attach to the ATA API --------------------------- */
|
||||
/* ------------------ attach to the blocklayer --------------------------- */
|
||||
|
||||
/**
|
||||
* Write a chunk of sectors to media
|
||||
* @param disk_dev Disk device instance
|
||||
* @param sector_start Sector's number to start write to
|
||||
* @param sector_count Sectors to write
|
||||
* @param blk All info about the block device we need
|
||||
* @param buffer Buffer to write from
|
||||
* @param block Sector's number to start write to
|
||||
* @param num_blocks Sector count to write
|
||||
* @return 0 on success, anything else on failure
|
||||
*
|
||||
* This routine expects the buffer has the correct size to read all data!
|
||||
*/
|
||||
#ifdef CONFIG_MCI_WRITE
|
||||
static int mci_sd_write(struct device_d *disk_dev, uint64_t sector_start,
|
||||
unsigned sector_count, const void *buffer)
|
||||
static int __maybe_unused mci_sd_write(struct block_device *blk,
|
||||
const void *buffer, int block, int num_blocks)
|
||||
{
|
||||
struct ata_interface *intf = disk_dev->platform_data;
|
||||
struct device_d *mci_dev = intf->priv;
|
||||
struct device_d *mci_dev = blk->dev;
|
||||
struct mci *mci = GET_MCI_DATA(mci_dev);
|
||||
int rc;
|
||||
|
||||
pr_debug("%s: Write %u block(s), starting at %u\n",
|
||||
__func__, sector_count, (unsigned)sector_start);
|
||||
pr_debug("%s: Write %d block(s), starting at %d\n",
|
||||
__func__, num_blocks, block);
|
||||
|
||||
if (mci->write_bl_len != 512) {
|
||||
pr_debug("MMC/SD block size is not 512 bytes (its %u bytes instead)\n",
|
||||
mci->read_bl_len);
|
||||
if (mci->write_bl_len != SECTOR_SIZE) {
|
||||
pr_debug("MMC/SD block size is not %d bytes (its %u bytes instead)\n",
|
||||
SECTOR_SIZE, mci->read_bl_len);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* size of the block number field in the MMC/SD command is 32 bit only */
|
||||
if (sector_start > MAX_BUFFER_NUMBER) {
|
||||
pr_debug("Cannot handle block number %llu. Too large!\n",
|
||||
sector_start);
|
||||
if (block > MAX_BUFFER_NUMBER) {
|
||||
pr_debug("Cannot handle block number %d. Too large!\n", block);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
rc = mci_block_write(mci_dev, buffer, sector_start, sector_count);
|
||||
rc = mci_block_write(mci_dev, buffer, block, num_blocks);
|
||||
if (rc != 0) {
|
||||
pr_debug("Writing block %u failed with %d\n", (unsigned)sector_start, rc);
|
||||
pr_debug("Writing block %d failed with %d\n", block, rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Read a chunk of sectors from media
|
||||
* @param disk_dev Disk device instance
|
||||
* @param sector_start Sector's number to start read from
|
||||
* @param sector_count Sectors to read
|
||||
* Read a chunk of sectors from the drive
|
||||
* @param blk All info about the block device we need
|
||||
* @param buffer Buffer to read into
|
||||
* @param block Sector's LBA number to start read from
|
||||
* @param num_blocks Sector count to read
|
||||
* @return 0 on success, anything else on failure
|
||||
*
|
||||
* This routine expects the buffer has the correct size to store all data!
|
||||
*/
|
||||
static int mci_sd_read(struct device_d *disk_dev, uint64_t sector_start,
|
||||
unsigned sector_count, void *buffer)
|
||||
static int mci_sd_read(struct block_device *blk, void *buffer, int block,
|
||||
int num_blocks)
|
||||
{
|
||||
struct ata_interface *intf = disk_dev->platform_data;
|
||||
struct device_d *mci_dev = intf->priv;
|
||||
struct device_d *mci_dev = blk->dev;
|
||||
struct mci *mci = GET_MCI_DATA(mci_dev);
|
||||
int rc;
|
||||
|
||||
pr_debug("%s: Read %u block(s), starting at %u\n",
|
||||
__func__, sector_count, (unsigned)sector_start);
|
||||
pr_debug("%s: Read %d block(s), starting at %d\n",
|
||||
__func__, num_blocks, block);
|
||||
|
||||
if (mci->read_bl_len != 512) {
|
||||
pr_debug("MMC/SD block size is not 512 bytes (its %u bytes instead)\n",
|
||||
|
@ -1068,15 +1063,14 @@ static int mci_sd_read(struct device_d *disk_dev, uint64_t sector_start,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (sector_start > MAX_BUFFER_NUMBER) {
|
||||
pr_err("Cannot handle block number %u. Too large!\n",
|
||||
(unsigned)sector_start);
|
||||
if (block > MAX_BUFFER_NUMBER) {
|
||||
pr_err("Cannot handle block number %d. Too large!\n", block);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
rc = mci_read_block(mci_dev, buffer, (unsigned)sector_start, sector_count);
|
||||
rc = mci_read_block(mci_dev, buffer, block, num_blocks);
|
||||
if (rc != 0) {
|
||||
pr_debug("Reading block %u failed with %d\n", (unsigned)sector_start, rc);
|
||||
pr_debug("Reading block %d failed with %d\n", block, rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
@ -1215,6 +1209,25 @@ static int mci_check_if_already_initialized(struct device_d *mci_dev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int mci_calc_blk_cnt(uint64_t cap, unsigned shift)
|
||||
{
|
||||
unsigned ret = cap >> shift;
|
||||
|
||||
if (ret > 0x7fffffff) {
|
||||
pr_warn("Limiting card size due to 31 bit contraints\n");
|
||||
return 0x7fffffff;
|
||||
}
|
||||
|
||||
return (int)ret;
|
||||
}
|
||||
|
||||
static struct block_device_ops mci_ops = {
|
||||
.read = mci_sd_read,
|
||||
#ifdef CONFIG_BLOCK_WRITE
|
||||
.write = mci_sd_write,
|
||||
#endif
|
||||
};
|
||||
|
||||
/**
|
||||
* Probe an MCI card at the given host interface
|
||||
* @param mci_dev MCI device instance
|
||||
|
@ -1224,9 +1237,7 @@ static int mci_card_probe(struct device_d *mci_dev)
|
|||
{
|
||||
struct mci *mci = GET_MCI_DATA(mci_dev);
|
||||
struct mci_host *host = GET_MCI_PDATA(mci_dev);
|
||||
struct ata_interface *p;
|
||||
int rc;
|
||||
struct device_d *dev;
|
||||
|
||||
/* start with a host interface reset */
|
||||
rc = (host->init)(host, mci_dev);
|
||||
|
@ -1270,16 +1281,29 @@ static int mci_card_probe(struct device_d *mci_dev)
|
|||
* An MMC/SD card acts like an ordinary disk.
|
||||
* So, re-use the disk driver to gain access to this media
|
||||
*/
|
||||
p = xzalloc(sizeof(struct ata_interface));
|
||||
mci->blk.dev = mci_dev;
|
||||
mci->blk.ops = &mci_ops;
|
||||
|
||||
#ifdef CONFIG_MCI_WRITE
|
||||
p->write = mci_sd_write;
|
||||
#endif
|
||||
p->read = mci_sd_read;
|
||||
p->priv = mci_dev;
|
||||
rc = cdev_find_free_index("disk");
|
||||
if (rc == -1)
|
||||
pr_err("Cannot find a free number for the disk node\n");
|
||||
|
||||
dev = add_generic_device("disk", -1, NULL, 0, mci->capacity, IORESOURCE_MEM, p);
|
||||
dev_add_child(&host->dev, dev);
|
||||
mci->blk.cdev.name = asprintf("disk%d", rc);
|
||||
mci->blk.blockbits = SECTOR_SHIFT;
|
||||
mci->blk.num_blocks = mci_calc_blk_cnt(mci->capacity, mci->blk.blockbits);
|
||||
|
||||
rc = blockdevice_register(&mci->blk);
|
||||
if (rc != 0) {
|
||||
dev_err(mci_dev, "Failed to register MCI/SD blockdevice\n");
|
||||
goto on_error;
|
||||
}
|
||||
|
||||
/* create partitions on demand */
|
||||
rc = parse_partition_table(&mci->blk);
|
||||
if (rc != 0) {
|
||||
dev_warn(mci_dev, "No partition table found\n");
|
||||
rc = 0; /* it's not a failure */
|
||||
}
|
||||
|
||||
pr_debug("SD Card successfully added\n");
|
||||
|
||||
|
@ -1410,8 +1434,9 @@ device_initcall(mci_init);
|
|||
*/
|
||||
int mci_register(struct mci_host *host)
|
||||
{
|
||||
struct device_d *mci_dev = &host->dev;
|
||||
struct device_d *mci_dev = xzalloc(sizeof(struct device_d));
|
||||
|
||||
mci_dev->id = -1;
|
||||
strcpy(mci_dev->name, mci_driver.name);
|
||||
mci_dev->platform_data = (void*)host;
|
||||
dev_add_child(host->hw_dev, mci_dev);
|
||||
|
|
|
@ -1,2 +1,3 @@
|
|||
config USB_STORAGE
|
||||
tristate "USB Mass Storage support"
|
||||
select DISK
|
||||
|
|
|
@ -195,33 +195,32 @@ static int usb_stor_write_10(ccb *srb, struct us_data *us,
|
|||
|
||||
#define US_MAX_IO_BLK 32
|
||||
|
||||
#define to_usb_mass_storage(x) container_of((x), struct us_blk_dev, blk)
|
||||
|
||||
enum { io_rd, io_wr };
|
||||
|
||||
/* Read / write a chunk of sectors on media */
|
||||
static int usb_stor_blk_io(int io_op, struct device_d *disk_dev,
|
||||
uint64_t sector_start, unsigned sector_count,
|
||||
void *buffer)
|
||||
static int usb_stor_blk_io(int io_op, struct block_device *disk_dev,
|
||||
int sector_start, int sector_count, void *buffer)
|
||||
{
|
||||
struct ata_interface *pata_if = disk_dev->platform_data;
|
||||
struct us_blk_dev *pblk_dev = (struct us_blk_dev *)pata_if->priv;
|
||||
struct us_blk_dev *pblk_dev = to_usb_mass_storage(disk_dev);
|
||||
struct us_data *us = pblk_dev->us;
|
||||
ccb us_ccb;
|
||||
ushort const sector_size = 512;
|
||||
unsigned sectors_done;
|
||||
|
||||
if (sector_count == 0)
|
||||
return 0;
|
||||
|
||||
/* check for unsupported block size */
|
||||
if (pblk_dev->blksz != sector_size) {
|
||||
US_DEBUGP("%s: unsupported block size %lu\n",
|
||||
__func__, pblk_dev->blksz);
|
||||
if (pblk_dev->blk.blockbits != SECTOR_SHIFT) {
|
||||
US_DEBUGP("%s: unsupported block shift %d\n",
|
||||
__func__, pblk_dev->blk.blockbits);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* check for invalid sector_start */
|
||||
if (sector_start >= pblk_dev->blknum || sector_start > (ulong)-1) {
|
||||
US_DEBUGP("%s: start sector %llu too large\n",
|
||||
if (sector_start >= pblk_dev->blk.num_blocks || sector_start > (ulong)-1) {
|
||||
US_DEBUGP("%s: start sector %d too large\n",
|
||||
__func__, sector_start);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
@ -242,21 +241,21 @@ static int usb_stor_blk_io(int io_op, struct device_d *disk_dev,
|
|||
sector_count = INT_MAX;
|
||||
US_DEBUGP("Restricting I/O to %u blocks\n", sector_count);
|
||||
}
|
||||
if (sector_start + sector_count > pblk_dev->blknum) {
|
||||
sector_count = pblk_dev->blknum - sector_start;
|
||||
if (sector_start + sector_count > pblk_dev->blk.num_blocks) {
|
||||
sector_count = pblk_dev->blk.num_blocks - sector_start;
|
||||
US_DEBUGP("Restricting I/O to %u blocks\n", sector_count);
|
||||
}
|
||||
|
||||
/* read / write the requested data */
|
||||
US_DEBUGP("%s %u block(s), starting from %llu\n",
|
||||
US_DEBUGP("%s %u block(s), starting from %d\n",
|
||||
((io_op == io_rd) ? "Read" : "Write"),
|
||||
sector_count, sector_start);
|
||||
sectors_done = 0;
|
||||
while (sector_count > 0) {
|
||||
int result;
|
||||
ushort n = (ushort)min(sector_count, US_MAX_IO_BLK);
|
||||
us_ccb.pdata = buffer + sectors_done * sector_size;
|
||||
us_ccb.datalen = n * (ulong)sector_size;
|
||||
unsigned n = min(sector_count, US_MAX_IO_BLK);
|
||||
us_ccb.pdata = buffer + (sectors_done * SECTOR_SIZE);
|
||||
us_ccb.datalen = n * SECTOR_SIZE;
|
||||
if (io_op == io_rd)
|
||||
result = usb_stor_read_10(&us_ccb, us,
|
||||
(ulong)sector_start, n);
|
||||
|
@ -264,7 +263,7 @@ static int usb_stor_blk_io(int io_op, struct device_d *disk_dev,
|
|||
result = usb_stor_write_10(&us_ccb, us,
|
||||
(ulong)sector_start, n);
|
||||
if (result != 0) {
|
||||
US_DEBUGP("I/O error at sector %llu\n", sector_start);
|
||||
US_DEBUGP("I/O error at sector %d\n", sector_start);
|
||||
break;
|
||||
}
|
||||
sector_start += n;
|
||||
|
@ -274,27 +273,31 @@ static int usb_stor_blk_io(int io_op, struct device_d *disk_dev,
|
|||
|
||||
usb_disable_asynch(0);
|
||||
|
||||
US_DEBUGP("Successful I/O of %u blocks\n", sectors_done);
|
||||
US_DEBUGP("Successful I/O of %d blocks\n", sectors_done);
|
||||
|
||||
return (sector_count != 0) ? -EIO : 0;
|
||||
}
|
||||
|
||||
/* Write a chunk of sectors to media */
|
||||
static int usb_stor_blk_write(struct device_d *disk_dev, uint64_t sector_start,
|
||||
unsigned sector_count, const void *buffer)
|
||||
static int __maybe_unused usb_stor_blk_write(struct block_device *blk,
|
||||
const void *buffer, int block, int num_blocks)
|
||||
{
|
||||
return usb_stor_blk_io(io_wr, disk_dev, sector_start, sector_count,
|
||||
(void *)buffer);
|
||||
return usb_stor_blk_io(io_wr, blk, block, num_blocks, (void *)buffer);
|
||||
}
|
||||
|
||||
/* Read a chunk of sectors from media */
|
||||
static int usb_stor_blk_read(struct device_d *disk_dev, uint64_t sector_start,
|
||||
unsigned sector_count, void *buffer)
|
||||
static int usb_stor_blk_read(struct block_device *blk, void *buffer, int block,
|
||||
int num_blocks)
|
||||
{
|
||||
return usb_stor_blk_io(io_rd, disk_dev, sector_start, sector_count,
|
||||
buffer);
|
||||
return usb_stor_blk_io(io_rd, blk, block, num_blocks, buffer);
|
||||
}
|
||||
|
||||
static struct block_device_ops usb_mass_storage_ops = {
|
||||
.read = usb_stor_blk_read,
|
||||
#ifdef CONFIG_BLOCK_WRITE
|
||||
.write = usb_stor_blk_write,
|
||||
#endif
|
||||
};
|
||||
|
||||
/***********************************************************************
|
||||
* Block device routines
|
||||
|
@ -302,6 +305,16 @@ static int usb_stor_blk_read(struct device_d *disk_dev, uint64_t sector_start,
|
|||
|
||||
static unsigned char us_io_buf[512];
|
||||
|
||||
static int usb_limit_blk_cnt(unsigned cnt)
|
||||
{
|
||||
if (cnt > 0x7fffffff) {
|
||||
pr_warn("Limiting device size due to 31 bit contraints\n");
|
||||
return 0x7fffffff;
|
||||
}
|
||||
|
||||
return (int)cnt;
|
||||
}
|
||||
|
||||
/* Prepare a disk device */
|
||||
static int usb_stor_init_blkdev(struct us_blk_dev *pblk_dev)
|
||||
{
|
||||
|
@ -313,7 +326,7 @@ static int usb_stor_init_blkdev(struct us_blk_dev *pblk_dev)
|
|||
us_ccb.pdata = us_io_buf;
|
||||
us_ccb.lun = pblk_dev->lun;
|
||||
|
||||
pblk_dev->blknum = 0;
|
||||
pblk_dev->blk.num_blocks = 0;
|
||||
usb_disable_asynch(1);
|
||||
|
||||
/* get device info */
|
||||
|
@ -350,11 +363,12 @@ static int usb_stor_init_blkdev(struct us_blk_dev *pblk_dev)
|
|||
}
|
||||
pcap = (unsigned long *)us_ccb.pdata;
|
||||
US_DEBUGP("Read Capacity returns: 0x%lx, 0x%lx\n", pcap[0], pcap[1]);
|
||||
pblk_dev->blknum = be32_to_cpu(pcap[0]);
|
||||
pblk_dev->blksz = be32_to_cpu(pcap[1]);
|
||||
pblk_dev->blknum++;
|
||||
US_DEBUGP("Capacity = 0x%llx, blocksz = 0x%lx\n",
|
||||
pblk_dev->blknum, pblk_dev->blksz);
|
||||
pblk_dev->blk.num_blocks = usb_limit_blk_cnt(be32_to_cpu(pcap[0]) + 1);
|
||||
if (be32_to_cpu(pcap[1]) != SECTOR_SIZE)
|
||||
pr_warn("Support only %d bytes sectors\n", SECTOR_SIZE);
|
||||
pblk_dev->blk.blockbits = SECTOR_SHIFT;
|
||||
US_DEBUGP("Capacity = 0x%x, blockshift = 0x%x\n",
|
||||
pblk_dev->blk.num_blocks, pblk_dev->blk.blockbits);
|
||||
|
||||
Exit:
|
||||
usb_disable_asynch(0);
|
||||
|
@ -362,39 +376,45 @@ Exit:
|
|||
}
|
||||
|
||||
/* Create and register a disk device for the specified LUN */
|
||||
static int usb_stor_add_blkdev(struct us_data *us, unsigned char lun)
|
||||
static int usb_stor_add_blkdev(struct us_data *us, struct device_d *dev,
|
||||
unsigned char lun)
|
||||
{
|
||||
struct us_blk_dev *pblk_dev;
|
||||
struct device_d *pdev;
|
||||
struct ata_interface *pata_if;
|
||||
int result;
|
||||
|
||||
/* allocate blk dev data */
|
||||
pblk_dev = (struct us_blk_dev *)malloc(sizeof(struct us_blk_dev));
|
||||
if (!pblk_dev)
|
||||
return -ENOMEM;
|
||||
memset(pblk_dev, 0, sizeof(struct us_blk_dev));
|
||||
/* allocate a new USB block device */
|
||||
pblk_dev = xzalloc(sizeof(struct us_blk_dev));
|
||||
|
||||
/* initialize blk dev data */
|
||||
pblk_dev->blk.dev = dev;
|
||||
pblk_dev->blk.ops = &usb_mass_storage_ops;
|
||||
pblk_dev->us = us;
|
||||
pblk_dev->lun = lun;
|
||||
pata_if = &pblk_dev->ata_if;
|
||||
pata_if->read = &usb_stor_blk_read;
|
||||
pata_if->write = &usb_stor_blk_write;
|
||||
pata_if->priv = pblk_dev;
|
||||
pdev = &pblk_dev->dev;
|
||||
strcpy(pdev->name, "disk");
|
||||
pdev->platform_data = pata_if;
|
||||
|
||||
/* read some info and get the unit ready */
|
||||
result = usb_stor_init_blkdev(pblk_dev);
|
||||
if (result < 0)
|
||||
goto BadDevice;
|
||||
|
||||
/* register disk device */
|
||||
result = register_device(pdev);
|
||||
if (result < 0)
|
||||
result = cdev_find_free_index("disk");
|
||||
if (result == -1)
|
||||
pr_err("Cannot find a free number for the disk node\n");
|
||||
pr_info("Using index %d for the new disk\n", result);
|
||||
|
||||
pblk_dev->blk.cdev.name = asprintf("disk%d", result);
|
||||
pblk_dev->blk.blockbits = SECTOR_SHIFT;
|
||||
|
||||
result = blockdevice_register(&pblk_dev->blk);
|
||||
if (result != 0) {
|
||||
dev_err(dev, "Failed to register blockdevice\n");
|
||||
goto BadDevice;
|
||||
}
|
||||
|
||||
/* create partitions on demand */
|
||||
result = parse_partition_table(&pblk_dev->blk);
|
||||
if (result != 0)
|
||||
dev_warn(dev, "No partition table found\n");
|
||||
|
||||
list_add_tail(&pblk_dev->list, &us_blkdev_list);
|
||||
US_DEBUGP("USB disk device successfully added\n");
|
||||
|
||||
|
@ -485,7 +505,7 @@ static int usb_stor_scan(struct usb_device *usbdev, struct us_data *us)
|
|||
|
||||
/* register a disk device for each active LUN */
|
||||
for (lun=0; lun<=us->max_lun; lun++) {
|
||||
if (usb_stor_add_blkdev(us, lun) == 0)
|
||||
if (usb_stor_add_blkdev(us, &usbdev->dev, lun) == 0)
|
||||
num_devs++;
|
||||
}
|
||||
|
||||
|
|
|
@ -26,7 +26,8 @@
|
|||
#define _STORAGE_USB_H_
|
||||
|
||||
#include <usb/usb.h>
|
||||
#include <ata.h>
|
||||
#include <block.h>
|
||||
#include <disks.h>
|
||||
#include <scsi.h>
|
||||
#include <linux/list.h>
|
||||
|
||||
|
@ -85,10 +86,7 @@ struct us_data {
|
|||
/* one us_blk_dev object allocated per LUN */
|
||||
struct us_blk_dev {
|
||||
struct us_data *us; /* LUN's enclosing dev */
|
||||
struct device_d dev; /* intf to generic driver */
|
||||
struct ata_interface ata_if; /* intf to "disk" driver */
|
||||
uint64_t blknum; /* capacity */
|
||||
unsigned long blksz; /* block size */
|
||||
struct block_device blk; /* the blockdevice for the dev */
|
||||
unsigned char lun; /* the LUN of this blk dev */
|
||||
struct list_head list; /* siblings */
|
||||
};
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#define _MCI_H_
|
||||
|
||||
#include <linux/list.h>
|
||||
#include <block.h>
|
||||
|
||||
/* Firmware revisions for SD cards */
|
||||
#define SD_VERSION_SD 0x20000
|
||||
|
@ -212,7 +213,6 @@ struct mci_data {
|
|||
/** host information */
|
||||
struct mci_host {
|
||||
struct device_d *hw_dev; /**< the host MCI hardware device */
|
||||
struct device_d dev; /**< our device */
|
||||
unsigned voltages;
|
||||
unsigned host_caps; /**< Host's interface capabilities, refer MMC_VDD_* */
|
||||
unsigned f_min; /**< host interface lower limit */
|
||||
|
@ -230,6 +230,7 @@ struct mci_host {
|
|||
|
||||
/** MMC/SD and interface instance information */
|
||||
struct mci {
|
||||
struct block_device blk; /**< the blockdevice for the card */
|
||||
unsigned version;
|
||||
/** != 0 when a high capacity card is connected (OCR -> OCR_HCS) */
|
||||
int high_capacity;
|
||||
|
|
Loading…
Reference in New Issue