diff options
Diffstat (limited to 'drivers/staging/westbridge/astoria/block/cyasblkdev_block.c')
-rw-r--r-- | drivers/staging/westbridge/astoria/block/cyasblkdev_block.c | 1631 |
1 files changed, 0 insertions, 1631 deletions
diff --git a/drivers/staging/westbridge/astoria/block/cyasblkdev_block.c b/drivers/staging/westbridge/astoria/block/cyasblkdev_block.c deleted file mode 100644 index 87452bde7c9..00000000000 --- a/drivers/staging/westbridge/astoria/block/cyasblkdev_block.c +++ /dev/null @@ -1,1631 +0,0 @@ -/* cyanblkdev_block.c - West Bridge Linux Block Driver source file -## =========================== -## Copyright (C) 2010 Cypress Semiconductor -## -## This program is free software; you can redistribute it and/or -## modify it under the terms of the GNU General Public License -## as published by the Free Software Foundation; either version 2 -## of the License, or (at your option) any later version. -## -## This program is distributed in the hope that it will be useful, -## but WITHOUT ANY WARRANTY; without even the implied warranty of -## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -## GNU General Public License for more details. -## -## You should have received a copy of the GNU General Public License -## along with this program; if not, write to the Free Software -## Foundation, Inc., 51 Franklin Street, Fifth Floor -## Boston, MA 02110-1301, USA. -## =========================== -*/ - -/* - * Linux block driver implementation for Cypress West Bridge. - * Based on the mmc block driver implementation by Andrew Christian - * for the linux 2.6.26 kernel. - * mmc_block.c, 5/28/2002 - */ - -/* - * Block driver for media (i.e., flash cards) - * - * Copyright 2002 Hewlett-Packard Company - * - * Use consistent with the GNU GPL is permitted, - * provided that this copyright notice is - * preserved in its entirety in all copies and derived works. - * - * HEWLETT-PACKARD COMPANY MAKES NO WARRANTIES, EXPRESSED OR IMPLIED, - * AS TO THE USEFULNESS OR CORRECTNESS OF THIS CODE OR ITS - * FITNESS FOR ANY PARTICULAR PURPOSE. - * - * Many thanks to Alessandro Rubini and Jonathan Corbet! - * - * Author: Andrew Christian - * 28 May 2002 - */ - -#include <linux/moduleparam.h> -#include <linux/module.h> -#include <linux/init.h> -#include <linux/slab.h> -#include <linux/sched.h> -#include <linux/kernel.h> -#include <linux/fs.h> -#include <linux/errno.h> -#include <linux/hdreg.h> -#include <linux/kdev_t.h> -#include <linux/blkdev.h> - -#include <asm/system.h> -#include <linux/uaccess.h> - -#include <linux/scatterlist.h> -#include <linux/time.h> -#include <linux/signal.h> -#include <linux/delay.h> - -#include "cyasblkdev_queue.h" - -#define CYASBLKDEV_SHIFT 0 /* Only a single partition. */ -#define CYASBLKDEV_MAX_REQ_LEN (256) -#define CYASBLKDEV_NUM_MINORS (256 >> CYASBLKDEV_SHIFT) -#define CY_AS_TEST_NUM_BLOCKS (64) -#define CYASBLKDEV_MINOR_0 1 -#define CYASBLKDEV_MINOR_1 2 -#define CYASBLKDEV_MINOR_2 3 - -static int major; -module_param(major, int, 0444); -MODULE_PARM_DESC(major, - "specify the major device number for cyasblkdev block driver"); - -/* parameters passed from the user space */ -static int vfat_search; -module_param(vfat_search, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(vfat_search, - "dynamically find the location of the first sector"); - -static int private_partition_bus = -1; -module_param(private_partition_bus, int, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(private_partition_bus, - "bus number for private partition"); - -static int private_partition_size = -1; -module_param(private_partition_size, int, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(private_partition_size, - "size of the private partition"); - -/* - * There is one cyasblkdev_blk_data per slot. - */ -struct cyasblkdev_blk_data { - spinlock_t lock; - int media_count[2]; - const struct block_device_operations *blkops; - unsigned int usage; - unsigned int suspended; - - /* handle to the west bridge device this handle, typdefed as *void */ - cy_as_device_handle dev_handle; - - /* our custom structure, in addition to request queue, - * adds lock & semaphore items*/ - struct cyasblkdev_queue queue; - - /* 16 entries is enough given max request size - * 16 * 4K (64 K per request)*/ - struct scatterlist sg[16]; - - /* non-zero enables printk of executed reqests */ - unsigned int dbgprn_flags; - - /*gen_disk for private, system disk */ - struct gendisk *system_disk; - cy_as_media_type system_disk_type; - cy_bool system_disk_read_only; - cy_bool system_disk_bus_num; - - /* sector size for the medium */ - unsigned int system_disk_blk_size; - unsigned int system_disk_first_sector; - unsigned int system_disk_unit_no; - - /*gen_disk for bus 0 */ - struct gendisk *user_disk_0; - cy_as_media_type user_disk_0_type; - cy_bool user_disk_0_read_only; - cy_bool user_disk_0_bus_num; - - /* sector size for the medium */ - unsigned int user_disk_0_blk_size; - unsigned int user_disk_0_first_sector; - unsigned int user_disk_0_unit_no; - - /*gen_disk for bus 1 */ - struct gendisk *user_disk_1; - cy_as_media_type user_disk_1_type; - cy_bool user_disk_1_read_only; - cy_bool user_disk_1_bus_num; - - /* sector size for the medium */ - unsigned int user_disk_1_blk_size; - unsigned int user_disk_1_first_sector; - unsigned int user_disk_1_unit_no; -}; - -/* pointer to west bridge block data device superstructure */ -static struct cyasblkdev_blk_data *gl_bd; - -static DEFINE_SEMAPHORE(open_lock); - -/* local forwardd declarationss */ -static cy_as_device_handle *cyas_dev_handle; -static void cyasblkdev_blk_deinit(struct cyasblkdev_blk_data *bd); - -/*change debug print options */ - #define DBGPRN_RD_RQ (1 < 0) - #define DBGPRN_WR_RQ (1 < 1) - #define DBGPRN_RQ_END (1 < 2) - -int blkdev_ctl_dbgprn( - int prn_flags - ) -{ - int cur_options = gl_bd->dbgprn_flags; - - DBGPRN_FUNC_NAME; - - /* set new debug print options */ - gl_bd->dbgprn_flags = prn_flags; - - /* return previous */ - return cur_options; -} -EXPORT_SYMBOL(blkdev_ctl_dbgprn); - -static struct cyasblkdev_blk_data *cyasblkdev_blk_get( - struct gendisk *disk - ) -{ - struct cyasblkdev_blk_data *bd; - - DBGPRN_FUNC_NAME; - - down(&open_lock); - - bd = disk->private_data; - - if (bd && (bd->usage == 0)) - bd = NULL; - - if (bd) { - bd->usage++; - #ifndef NBDEBUG - cy_as_hal_print_message( - "cyasblkdev_blk_get: usage = %d\n", bd->usage); - #endif - } - up(&open_lock); - - return bd; -} - -static void cyasblkdev_blk_put( - struct cyasblkdev_blk_data *bd - ) -{ - DBGPRN_FUNC_NAME; - - down(&open_lock); - - if (bd) { - bd->usage--; - #ifndef WESTBRIDGE_NDEBUG - cy_as_hal_print_message( - " cyasblkdev_blk_put , bd->usage= %d\n", bd->usage); - #endif - } else { - #ifndef WESTBRIDGE_NDEBUG - cy_as_hal_print_message( - "cyasblkdev: blk_put(bd) on bd = NULL!: usage = %d\n", - bd->usage); - #endif - up(&open_lock); - return; - } - - if (bd->usage == 0) { - put_disk(bd->user_disk_0); - put_disk(bd->user_disk_1); - put_disk(bd->system_disk); - cyasblkdev_cleanup_queue(&bd->queue); - - if (CY_AS_ERROR_SUCCESS != - cy_as_storage_release(bd->dev_handle, 0, 0, 0, 0)) { - #ifndef WESTBRIDGE_NDEBUG - cy_as_hal_print_message( - "cyasblkdev: cannot release bus 0\n"); - #endif - } - - if (CY_AS_ERROR_SUCCESS != - cy_as_storage_release(bd->dev_handle, 1, 0, 0, 0)) { - #ifndef WESTBRIDGE_NDEBUG - cy_as_hal_print_message( - "cyasblkdev: cannot release bus 1\n"); - #endif - } - - if (CY_AS_ERROR_SUCCESS != - cy_as_storage_stop(bd->dev_handle, 0, 0)) { - #ifndef WESTBRIDGE_NDEBUG - cy_as_hal_print_message( - "cyasblkdev: cannot stop storage stack\n"); - #endif - } - - #ifdef __CY_ASTORIA_SCM_KERNEL_HAL__ - /* If the SCM Kernel HAL is being used, disable the use - * of scatter/gather lists at the end of block driver usage. - */ - cy_as_hal_disable_scatter_list(cyasdevice_gethaltag()); - #endif - - /*ptr to global struct cyasblkdev_blk_data */ - gl_bd = NULL; - kfree(bd); - } - - #ifndef WESTBRIDGE_NDEBUG - cy_as_hal_print_message( - "cyasblkdev (blk_put): usage = %d\n", - bd->usage); - #endif - up(&open_lock); -} - -static int cyasblkdev_blk_open( - struct block_device *bdev, - fmode_t mode - ) -{ - struct cyasblkdev_blk_data *bd = cyasblkdev_blk_get(bdev->bd_disk); - int ret = -ENXIO; - - DBGPRN_FUNC_NAME; - - if (bd) { - if (bd->usage == 2) - check_disk_change(bdev); - - ret = 0; - - if (bdev->bd_disk == bd->user_disk_0) { - if ((mode & FMODE_WRITE) && bd->user_disk_0_read_only) { - #ifndef WESTBRIDGE_NDEBUG - cy_as_hal_print_message( - "device marked as readonly " - "and write requested\n"); - #endif - - cyasblkdev_blk_put(bd); - ret = -EROFS; - } - } else if (bdev->bd_disk == bd->user_disk_1) { - if ((mode & FMODE_WRITE) && bd->user_disk_1_read_only) { - #ifndef WESTBRIDGE_NDEBUG - cy_as_hal_print_message( - "device marked as readonly " - "and write requested\n"); - #endif - - cyasblkdev_blk_put(bd); - ret = -EROFS; - } - } else if (bdev->bd_disk == bd->system_disk) { - if ((mode & FMODE_WRITE) && bd->system_disk_read_only) { - #ifndef WESTBRIDGE_NDEBUG - cy_as_hal_print_message( - "device marked as readonly " - "and write requested\n"); - #endif - - cyasblkdev_blk_put(bd); - ret = -EROFS; - } - } - } - - return ret; -} - -static int cyasblkdev_blk_release( - struct gendisk *disk, - fmode_t mode - ) -{ - struct cyasblkdev_blk_data *bd = disk->private_data; - - DBGPRN_FUNC_NAME; - - cyasblkdev_blk_put(bd); - return 0; -} - -static int cyasblkdev_blk_ioctl( - struct block_device *bdev, - fmode_t mode, - unsigned int cmd, - unsigned long arg - ) -{ - DBGPRN_FUNC_NAME; - - if (cmd == HDIO_GETGEO) { - /*for now we only process geometry IOCTL*/ - struct hd_geometry geo; - - memset(&geo, 0, sizeof(struct hd_geometry)); - - geo.cylinders = get_capacity(bdev->bd_disk) / (4 * 16); - geo.heads = 4; - geo.sectors = 16; - geo.start = get_start_sect(bdev); - - /* copy to user space */ - return copy_to_user((void __user *)arg, &geo, sizeof(geo)) - ? -EFAULT : 0; - } - - return -ENOTTY; -} - -/* check_events block_device opp - * this one is called by kernel to confirm if the media really changed - * as we indicated by issuing check_disk_change() call */ -unsigned int cyasblkdev_check_events(struct gendisk *gd, unsigned int clearing) -{ - struct cyasblkdev_blk_data *bd; - - #ifndef WESTBRIDGE_NDEBUG - cy_as_hal_print_message("cyasblkdev_media_changed() is called\n"); - #endif - - if (gd) - bd = gd->private_data; - else { - #ifndef WESTBRIDGE_NDEBUG - cy_as_hal_print_message( - "cyasblkdev_media_changed() is called, " - "but gd is null\n"); - #endif - } - - /* return media change state - DISK_EVENT_MEDIA_CHANGE yes, 0 no */ - return 0; -} - -/* this one called by kernel to give us a chence - * to prep the new media before it starts to rescaning - * of the newlly inserted SD media */ -int cyasblkdev_revalidate_disk(struct gendisk *gd) -{ - /*int (*revalidate_disk) (struct gendisk *); */ - - #ifndef WESTBRIDGE_NDEBUG - if (gd) - cy_as_hal_print_message( - "cyasblkdev_revalidate_disk() is called, " - "(gl_bd->usage:%d)\n", gl_bd->usage); - #endif - - /* 0 means ok, kern can go ahead with partition rescan */ - return 0; -} - - -/*standard block device driver interface */ -static struct block_device_operations cyasblkdev_bdops = { - .open = cyasblkdev_blk_open, - .release = cyasblkdev_blk_release, - .ioctl = cyasblkdev_blk_ioctl, - /* .getgeo = cyasblkdev_blk_getgeo, */ - /* added to support media removal( real and simulated) media */ - .check_events = cyasblkdev_check_events, - /* added to support media removal( real and simulated) media */ - .revalidate_disk = cyasblkdev_revalidate_disk, - .owner = THIS_MODULE, -}; - -/* west bridge block device prep request function */ -static int cyasblkdev_blk_prep_rq( - struct cyasblkdev_queue *bq, - struct request *req - ) -{ - struct cyasblkdev_blk_data *bd = bq->data; - int stat = BLKPREP_OK; - - DBGPRN_FUNC_NAME; - - /* If we have no device, we haven't finished initialising. */ - if (!bd || !bd->dev_handle) { - #ifndef WESTBRIDGE_NDEBUG - cy_as_hal_print_message(KERN_ERR - "cyasblkdev %s: killing request - no device/host\n", - req->rq_disk->disk_name); - #endif - stat = BLKPREP_KILL; - } - - if (bd->suspended) { - blk_plug_device(bd->queue.queue); - stat = BLKPREP_DEFER; - } - - /* Check for excessive requests.*/ - if (blk_rq_pos(req) + blk_rq_sectors(req) > get_capacity(req->rq_disk)) { - cy_as_hal_print_message("cyasblkdev: bad request address\n"); - stat = BLKPREP_KILL; - } - - return stat; -} - -/*west bridge storage async api on_completed callback */ -static void cyasblkdev_issuecallback( - /* Handle to the device completing the storage operation */ - cy_as_device_handle handle, - /* The media type completing the operation */ - cy_as_media_type type, - /* The device completing the operation */ - uint32_t device, - /* The unit completing the operation */ - uint32_t unit, - /* The block number of the completed operation */ - uint32_t block_number, - /* The type of operation */ - cy_as_oper_type op, - /* The error status */ - cy_as_return_status_t status - ) -{ - int retry_cnt = 0; - DBGPRN_FUNC_NAME; - - if (status != CY_AS_ERROR_SUCCESS) { - #ifndef WESTBRIDGE_NDEBUG - cy_as_hal_print_message( - "%s: async r/w: op:%d failed with error %d at address %d\n", - __func__, op, status, block_number); - #endif - } - - #ifndef WESTBRIDGE_NDEBUG - cy_as_hal_print_message( - "%s calling blk_end_request from issue_callback " - "req=0x%x, status=0x%x, nr_sectors=0x%x\n", - __func__, (unsigned int) gl_bd->queue.req, status, - (unsigned int) blk_rq_sectors(gl_bd->queue.req)); - #endif - - /* note: blk_end_request w/o __ prefix should - * not require spinlocks on the queue*/ - while (blk_end_request(gl_bd->queue.req, - status, blk_rq_sectors(gl_bd->queue.req)*512)) { - retry_cnt++; - } - - #ifndef WESTBRIDGE_NDEBUG - cy_as_hal_print_message( - "%s blkdev_callback: ended rq on %d sectors, " - "with err:%d, n:%d times\n", __func__, - (int)blk_rq_sectors(gl_bd->queue.req), status, - retry_cnt - ); - #endif - - spin_lock_irq(&gl_bd->lock); - - /*elevate next request, if there is one*/ - if (!blk_queue_plugged(gl_bd->queue.queue)) { - /* queue is not plugged */ - gl_bd->queue.req = blk_fetch_request(gl_bd->queue.queue); - #ifndef WESTBRIDGE_NDEBUG - cy_as_hal_print_message("%s blkdev_callback: " - "blk_fetch_request():%p\n", - __func__, gl_bd->queue.req); - #endif - } - - if (gl_bd->queue.req) { - spin_unlock_irq(&gl_bd->lock); - - #ifndef WESTBRIDGE_NDEBUG - cy_as_hal_print_message("%s blkdev_callback: about to " - "call issue_fn:%p\n", __func__, gl_bd->queue.req); - #endif - - gl_bd->queue.issue_fn(&gl_bd->queue, gl_bd->queue.req); - } else { - spin_unlock_irq(&gl_bd->lock); - } -} - -/* issue astoria blkdev request (issue_fn) */ -static int cyasblkdev_blk_issue_rq( - struct cyasblkdev_queue *bq, - struct request *req - ) -{ - struct cyasblkdev_blk_data *bd = bq->data; - int index = 0; - int ret = CY_AS_ERROR_SUCCESS; - uint32_t req_sector = 0; - uint32_t req_nr_sectors = 0; - int bus_num = 0; - int lcl_unit_no = 0; - - DBGPRN_FUNC_NAME; - - /* - * will construct a scatterlist for the given request; - * the return value is the number of actually used - * entries in the resulting list. Then, this scatterlist - * can be used for the actual DMA prep operation. - */ - spin_lock_irq(&bd->lock); - index = blk_rq_map_sg(bq->queue, req, bd->sg); - - if (req->rq_disk == bd->user_disk_0) { - bus_num = bd->user_disk_0_bus_num; - req_sector = blk_rq_pos(req) + gl_bd->user_disk_0_first_sector; - req_nr_sectors = blk_rq_sectors(req); - lcl_unit_no = gl_bd->user_disk_0_unit_no; - - #ifndef WESTBRIDGE_NDEBUG - cy_as_hal_print_message("%s: request made to disk 0 " - "for sector=%d, num_sectors=%d, unit_no=%d\n", - __func__, req_sector, (int) blk_rq_sectors(req), - lcl_unit_no); - #endif - } else if (req->rq_disk == bd->user_disk_1) { - bus_num = bd->user_disk_1_bus_num; - req_sector = blk_rq_pos(req) + gl_bd->user_disk_1_first_sector; - /*SECT_NUM_TRANSLATE(blk_rq_sectors(req));*/ - req_nr_sectors = blk_rq_sectors(req); - lcl_unit_no = gl_bd->user_disk_1_unit_no; - - #ifndef WESTBRIDGE_NDEBUG - cy_as_hal_print_message("%s: request made to disk 1 for " - "sector=%d, num_sectors=%d, unit_no=%d\n", __func__, - req_sector, (int) blk_rq_sectors(req), lcl_unit_no); - #endif - } else if (req->rq_disk == bd->system_disk) { - bus_num = bd->system_disk_bus_num; - req_sector = blk_rq_pos(req) + gl_bd->system_disk_first_sector; - req_nr_sectors = blk_rq_sectors(req); - lcl_unit_no = gl_bd->system_disk_unit_no; - - #ifndef WESTBRIDGE_NDEBUG - cy_as_hal_print_message("%s: request made to system disk " - "for sector=%d, num_sectors=%d, unit_no=%d\n", __func__, - req_sector, (int) blk_rq_sectors(req), lcl_unit_no); - #endif - } - #ifndef WESTBRIDGE_NDEBUG - else { - cy_as_hal_print_message( - "%s: invalid disk used for request\n", __func__); - } - #endif - - spin_unlock_irq(&bd->lock); - - if (rq_data_dir(req) == READ) { - #ifndef WESTBRIDGE_NDEBUG - cy_as_hal_print_message("%s: calling readasync() " - "req_sector=0x%x, req_nr_sectors=0x%x, bd->sg:%x\n\n", - __func__, req_sector, req_nr_sectors, (uint32_t)bd->sg); - #endif - - ret = cy_as_storage_read_async(bd->dev_handle, bus_num, 0, - lcl_unit_no, req_sector, bd->sg, req_nr_sectors, - (cy_as_storage_callback)cyasblkdev_issuecallback); - - if (ret != CY_AS_ERROR_SUCCESS) { - #ifndef WESTBRIDGE_NDEBUG - cy_as_hal_print_message("%s:readasync() error %d at " - "address %ld, unit no %d\n", __func__, ret, - blk_rq_pos(req), lcl_unit_no); - cy_as_hal_print_message("%s:ending i/o request " - "on reg:%x\n", __func__, (uint32_t)req); - #endif - - while (blk_end_request(req, - (ret == CY_AS_ERROR_SUCCESS), - req_nr_sectors*512)) - ; - - bq->req = NULL; - } - } else { - ret = cy_as_storage_write_async(bd->dev_handle, bus_num, 0, - lcl_unit_no, req_sector, bd->sg, req_nr_sectors, - (cy_as_storage_callback)cyasblkdev_issuecallback); - - if (ret != CY_AS_ERROR_SUCCESS) { - #ifndef WESTBRIDGE_NDEBUG - cy_as_hal_print_message("%s: write failed with " - "error %d at address %ld, unit no %d\n", - __func__, ret, blk_rq_pos(req), lcl_unit_no); - #endif - - /*end IO op on this request(does both - * end_that_request_... _first & _last) */ - while (blk_end_request(req, - (ret == CY_AS_ERROR_SUCCESS), - req_nr_sectors*512)) - ; - - bq->req = NULL; - } - } - - return ret; -} - -static unsigned long -dev_use[CYASBLKDEV_NUM_MINORS / (8 * sizeof(unsigned long))]; - - -/* storage event callback (note: called in astoria isr context) */ -static void cyasblkdev_storage_callback( - cy_as_device_handle dev_h, - cy_as_bus_number_t bus, - uint32_t device, - cy_as_storage_event evtype, - void *evdata - ) -{ - #ifndef WESTBRIDGE_NDEBUG - cy_as_hal_print_message("%s: bus:%d, device:%d, evtype:%d, " - "evdata:%p\n ", __func__, bus, device, evtype, evdata); - #endif - - switch (evtype) { - case cy_as_storage_processor: - break; - - case cy_as_storage_removed: - break; - - case cy_as_storage_inserted: - break; - - default: - break; - } -} - -#define SECTORS_TO_SCAN 4096 - -uint32_t cyasblkdev_get_vfat_offset(int bus_num, int unit_no) -{ - /* - * for sd media, vfat partition boot record is not always - * located at sector it greatly depends on the system and - * software that was used to format the sd however, linux - * fs layer always expects it at sector 0, this function - * finds the offset and then uses it in all media r/w - * operations - */ - int sect_no, stat; - uint8_t *sect_buf; - bool br_found = false; - - DBGPRN_FUNC_NAME; - - sect_buf = kmalloc(1024, GFP_KERNEL); - - /* since HAL layer always uses sg lists instead of the - * buffer (for hw dmas) we need to initialize the sg list - * for local buffer*/ - sg_init_one(gl_bd->sg, sect_buf, 512); - - /* - * Check MPR partition table 1st, then try to scan through - * 1st 384 sectors until BR signature(intel JMP istruction - * code and ,0x55AA) is found - */ - #ifndef WESTBRIDGE_NDEBUG - cy_as_hal_print_message( - "%s scanning media for vfat partition...\n", __func__); - #endif - - for (sect_no = 0; sect_no < SECTORS_TO_SCAN; sect_no++) { - #ifndef WESTBRIDGE_NDEBUG - cy_as_hal_print_message("%s before cyasstorageread " - "gl_bd->sg addr=0x%x\n", __func__, - (unsigned int) gl_bd->sg); - #endif - - stat = cy_as_storage_read( - /* Handle to the device of interest */ - gl_bd->dev_handle, - /* The bus to access */ - bus_num, - /* The device to access */ - 0, - /* The unit to access */ - unit_no, - /* absolute sector number */ - sect_no, - /* sg structure */ - gl_bd->sg, - /* The number of blocks to be read */ - 1 - ); - - /* try only sectors with boot signature */ - if ((sect_buf[510] == 0x55) && (sect_buf[511] == 0xaa)) { - /* vfat boot record may also be located at - * sector 0, check it first */ - if (sect_buf[0] == 0xEB) { - #ifndef WESTBRIDGE_NDEBUG - cy_as_hal_print_message( - "%s vfat partition found " - "at sector:%d\n", - __func__, sect_no); - #endif - - br_found = true; - break; - } - } - - if (stat != 0) { - #ifndef WESTBRIDGE_NDEBUG - cy_as_hal_print_message("%s sector scan error\n", - __func__); - #endif - break; - } - } - - kfree(sect_buf); - - if (br_found) { - return sect_no; - } else { - #ifndef WESTBRIDGE_NDEBUG - cy_as_hal_print_message( - "%s vfat partition is not found, using 0 offset\n", - __func__); - #endif - return 0; - } -} - -cy_as_storage_query_device_data dev_data = {0}; - -static int cyasblkdev_add_disks(int bus_num, - struct cyasblkdev_blk_data *bd, - int total_media_count, - int devidx) -{ - int ret = 0; - uint64_t disk_cap; - int lcl_unit_no; - cy_as_storage_query_unit_data unit_data = {0}; - - #ifndef WESTBRIDGE_NDEBUG - cy_as_hal_print_message("%s:query device: " - "type:%d, removable:%d, writable:%d, " - "blksize %d, units:%d, locked:%d, " - "erase_sz:%d\n", - __func__, - dev_data.desc_p.type, - dev_data.desc_p.removable, - dev_data.desc_p.writeable, - dev_data.desc_p.block_size, - dev_data.desc_p.number_units, - dev_data.desc_p.locked, - dev_data.desc_p.erase_unit_size - ); - #endif - - /* make sure that device is not locked */ - if (dev_data.desc_p.locked) { - #ifndef WESTBRIDGE_NDEBUG - cy_as_hal_print_message( - "%s: device is locked\n", __func__); - #endif - ret = cy_as_storage_release( - bd->dev_handle, bus_num, 0, 0, 0); - if (ret != CY_AS_ERROR_SUCCESS) { - #ifndef WESTBRIDGE_NDEBUG - cy_as_hal_print_message("%s cannot release" - " storage\n", __func__); - #endif - goto out; - } - goto out; - } - - unit_data.device = 0; - unit_data.unit = 0; - unit_data.bus = bus_num; - ret = cy_as_storage_query_unit(bd->dev_handle, - &unit_data, 0, 0); - if (ret != CY_AS_ERROR_SUCCESS) { - #ifndef WESTBRIDGE_NDEBUG - cy_as_hal_print_message("%s: cannot query " - "%d device unit - reason code %d\n", - __func__, bus_num, ret); - #endif - goto out; - } - - if (private_partition_bus == bus_num) { - if (private_partition_size > 0) { - ret = cy_as_storage_create_p_partition( - bd->dev_handle, bus_num, 0, - private_partition_size, 0, 0); - if ((ret != CY_AS_ERROR_SUCCESS) && - (ret != CY_AS_ERROR_ALREADY_PARTITIONED)) { - #ifndef WESTBRIDGE_NDEBUG - cy_as_hal_print_message("%s: cy_as_storage_" - "create_p_partition after size > 0 check " - "failed with error code %d\n", - __func__, ret); - #endif - - disk_cap = (uint64_t) - (unit_data.desc_p.unit_size); - lcl_unit_no = 0; - - } else if (ret == CY_AS_ERROR_ALREADY_PARTITIONED) { - #ifndef WESTBRIDGE_NDEBUG - cy_as_hal_print_message( - "%s: cy_as_storage_create_p_partition " - "indicates memory already partitioned\n", - __func__); - #endif - - /*check to see that partition - * matches size */ - if (unit_data.desc_p.unit_size != - private_partition_size) { - ret = cy_as_storage_remove_p_partition( - bd->dev_handle, - bus_num, 0, 0, 0); - if (ret == CY_AS_ERROR_SUCCESS) { - ret = cy_as_storage_create_p_partition( - bd->dev_handle, bus_num, 0, - private_partition_size, 0, 0); - if (ret == CY_AS_ERROR_SUCCESS) { - unit_data.bus = bus_num; - unit_data.device = 0; - unit_data.unit = 1; - } else { - #ifndef WESTBRIDGE_NDEBUG - cy_as_hal_print_message( - "%s: cy_as_storage_create_p_partition " - "after removal unexpectedly failed " - "with error %d\n", __func__, ret); - #endif - - /* need to requery bus - * seeing as delete - * successful and create - * failed we have changed - * the disk properties */ - unit_data.bus = bus_num; - unit_data.device = 0; - unit_data.unit = 0; - } - - ret = cy_as_storage_query_unit( - bd->dev_handle, - &unit_data, 0, 0); - if (ret != CY_AS_ERROR_SUCCESS) { - #ifndef WESTBRIDGE_NDEBUG - cy_as_hal_print_message( - "%s: cannot query %d " - "device unit - reason code %d\n", - __func__, bus_num, ret); - #endif - goto out; - } else { - disk_cap = (uint64_t) - (unit_data.desc_p.unit_size); - lcl_unit_no = - unit_data.unit; - } - } else { - #ifndef WESTBRIDGE_NDEBUG - cy_as_hal_print_message( - "%s: cy_as_storage_remove_p_partition " - "failed with error %d\n", - __func__, ret); - #endif - - unit_data.bus = bus_num; - unit_data.device = 0; - unit_data.unit = 1; - - ret = cy_as_storage_query_unit( - bd->dev_handle, &unit_data, 0, 0); - if (ret != CY_AS_ERROR_SUCCESS) { - #ifndef WESTBRIDGE_NDEBUG - cy_as_hal_print_message( - "%s: cannot query %d " - "device unit - reason " - "code %d\n", __func__, - bus_num, ret); - #endif - goto out; - } - - disk_cap = (uint64_t) - (unit_data.desc_p.unit_size); - lcl_unit_no = - unit_data.unit; - } - } else { - #ifndef WESTBRIDGE_NDEBUG - cy_as_hal_print_message("%s: partition " - "exists and sizes equal\n", - __func__); - #endif - - /*partition already existed, - * need to query second unit*/ - unit_data.bus = bus_num; - unit_data.device = 0; - unit_data.unit = 1; - - ret = cy_as_storage_query_unit( - bd->dev_handle, &unit_data, 0, 0); - if (ret != CY_AS_ERROR_SUCCESS) { - #ifndef WESTBRIDGE_NDEBUG - cy_as_hal_print_message( - "%s: cannot query %d " - "device unit " - "- reason code %d\n", - __func__, bus_num, ret); - #endif - goto out; - } else { - disk_cap = (uint64_t) - (unit_data.desc_p.unit_size); - lcl_unit_no = unit_data.unit; - } - } - } else { - #ifndef WESTBRIDGE_NDEBUG - cy_as_hal_print_message( - "%s: cy_as_storage_create_p_partition " - "created successfully\n", __func__); - #endif - - disk_cap = (uint64_t) - (unit_data.desc_p.unit_size - - private_partition_size); - - lcl_unit_no = 1; - } - } - #ifndef WESTBRIDGE_NDEBUG - else { - cy_as_hal_print_message( - "%s: invalid partition_size%d\n", __func__, - private_partition_size); - - disk_cap = (uint64_t) - (unit_data.desc_p.unit_size); - lcl_unit_no = 0; - } - #endif - } else { - disk_cap = (uint64_t) - (unit_data.desc_p.unit_size); - lcl_unit_no = 0; - } - - if ((bus_num == 0) || - (total_media_count == 1)) { - sprintf(bd->user_disk_0->disk_name, - "cyasblkdevblk%d", devidx); - - #ifndef WESTBRIDGE_NDEBUG - cy_as_hal_print_message( - "%s: disk unit_sz:%lu blk_sz:%d, " - "start_blk:%lu, capacity:%llu\n", - __func__, (unsigned long) - unit_data.desc_p.unit_size, - unit_data.desc_p.block_size, - (unsigned long) - unit_data.desc_p.start_block, - (uint64_t)disk_cap - ); - #endif - - #ifndef WESTBRIDGE_NDEBUG - cy_as_hal_print_message("%s: setting gendisk disk " - "capacity to %d\n", __func__, (int) disk_cap); - #endif - - /* initializing bd->queue */ - #ifndef WESTBRIDGE_NDEBUG - cy_as_hal_print_message("%s: init bd->queue\n", - __func__); - #endif - - /* this will create a - * queue kernel thread */ - cyasblkdev_init_queue( - &bd->queue, &bd->lock); - - bd->queue.prep_fn = cyasblkdev_blk_prep_rq; - bd->queue.issue_fn = cyasblkdev_blk_issue_rq; - bd->queue.data = bd; - - /*blk_size should always - * be a multiple of 512, - * set to the max to ensure - * that all accesses aligned - * to the greatest multiple, - * can adjust request to - * smaller block sizes - * dynamically*/ - - bd->user_disk_0_read_only = !dev_data.desc_p.writeable; - bd->user_disk_0_blk_size = dev_data.desc_p.block_size; - bd->user_disk_0_type = dev_data.desc_p.type; - bd->user_disk_0_bus_num = bus_num; - bd->user_disk_0->major = major; - bd->user_disk_0->first_minor = devidx << CYASBLKDEV_SHIFT; - bd->user_disk_0->minors = 8; - bd->user_disk_0->fops = &cyasblkdev_bdops; - bd->user_disk_0->events = DISK_EVENT_MEDIA_CHANGE; - bd->user_disk_0->private_data = bd; - bd->user_disk_0->queue = bd->queue.queue; - bd->dbgprn_flags = DBGPRN_RD_RQ; - bd->user_disk_0_unit_no = lcl_unit_no; - - blk_queue_logical_block_size(bd->queue.queue, - bd->user_disk_0_blk_size); - - set_capacity(bd->user_disk_0, - disk_cap); - - #ifndef WESTBRIDGE_NDEBUG - cy_as_hal_print_message( - "%s: returned from set_capacity %d\n", - __func__, (int) disk_cap); - #endif - - /* need to start search from - * public partition beginning */ - if (vfat_search) { - bd->user_disk_0_first_sector = - cyasblkdev_get_vfat_offset( - bd->user_disk_0_bus_num, - bd->user_disk_0_unit_no); - } else { - bd->user_disk_0_first_sector = 0; - } - - #ifndef WESTBRIDGE_NDEBUG - cy_as_hal_print_message( - "%s: set user_disk_0_first " - "sector to %d\n", __func__, - bd->user_disk_0_first_sector); - cy_as_hal_print_message( - "%s: add_disk: disk->major=0x%x\n", - __func__, - bd->user_disk_0->major); - cy_as_hal_print_message( - "%s: add_disk: " - "disk->first_minor=0x%x\n", __func__, - bd->user_disk_0->first_minor); - cy_as_hal_print_message( - "%s: add_disk: " - "disk->minors=0x%x\n", __func__, - bd->user_disk_0->minors); - cy_as_hal_print_message( - "%s: add_disk: " - "disk->disk_name=%s\n", - __func__, - bd->user_disk_0->disk_name); - cy_as_hal_print_message( - "%s: add_disk: " - "disk->part_tbl=0x%x\n", __func__, - (unsigned int) - bd->user_disk_0->part_tbl); - cy_as_hal_print_message( - "%s: add_disk: " - "disk->queue=0x%x\n", __func__, - (unsigned int) - bd->user_disk_0->queue); - cy_as_hal_print_message( - "%s: add_disk: " - "disk->flags=0x%x\n", - __func__, (unsigned int) - bd->user_disk_0->flags); - cy_as_hal_print_message( - "%s: add_disk: " - "disk->driverfs_dev=0x%x\n", - __func__, (unsigned int) - bd->user_disk_0->driverfs_dev); - cy_as_hal_print_message( - "%s: add_disk: " - "disk->slave_dir=0x%x\n", - __func__, (unsigned int) - bd->user_disk_0->slave_dir); - cy_as_hal_print_message( - "%s: add_disk: " - "disk->random=0x%x\n", - __func__, (unsigned int) - bd->user_disk_0->random); - cy_as_hal_print_message( - "%s: add_disk: " - "disk->node_id=0x%x\n", - __func__, (unsigned int) - bd->user_disk_0->node_id); - - #endif - - add_disk(bd->user_disk_0); - - } else if ((bus_num == 1) && - (total_media_count == 2)) { - bd->user_disk_1_read_only = !dev_data.desc_p.writeable; - bd->user_disk_1_blk_size = dev_data.desc_p.block_size; - bd->user_disk_1_type = dev_data.desc_p.type; - bd->user_disk_1_bus_num = bus_num; - bd->user_disk_1->major = major; - bd->user_disk_1->first_minor = (devidx + 1) << CYASBLKDEV_SHIFT; - bd->user_disk_1->minors = 8; - bd->user_disk_1->fops = &cyasblkdev_bdops; - bd->user_disk_1->events = DISK_EVENT_MEDIA_CHANGE; - bd->user_disk_1->private_data = bd; - bd->user_disk_1->queue = bd->queue.queue; - bd->dbgprn_flags = DBGPRN_RD_RQ; - bd->user_disk_1_unit_no = lcl_unit_no; - - sprintf(bd->user_disk_1->disk_name, - "cyasblkdevblk%d", (devidx + 1)); - - #ifndef WESTBRIDGE_NDEBUG - cy_as_hal_print_message( - "%s: disk unit_sz:%lu " - "blk_sz:%d, " - "start_blk:%lu, " - "capacity:%llu\n", - __func__, - (unsigned long) - unit_data.desc_p.unit_size, - unit_data.desc_p.block_size, - (unsigned long) - unit_data.desc_p.start_block, - (uint64_t)disk_cap - ); - #endif - - /*blk_size should always be a - * multiple of 512, set to the max - * to ensure that all accesses - * aligned to the greatest multiple, - * can adjust request to smaller - * block sizes dynamically*/ - if (bd->user_disk_0_blk_size > - bd->user_disk_1_blk_size) { - blk_queue_logical_block_size(bd->queue.queue, - bd->user_disk_0_blk_size); - #ifndef WESTBRIDGE_NDEBUG - cy_as_hal_print_message( - "%s: set hard sect_sz:%d\n", - __func__, - bd->user_disk_0_blk_size); - #endif - } else { - blk_queue_logical_block_size(bd->queue.queue, - bd->user_disk_1_blk_size); - #ifndef WESTBRIDGE_NDEBUG - cy_as_hal_print_message( - "%s: set hard sect_sz:%d\n", - __func__, - bd->user_disk_1_blk_size); - #endif - } - - set_capacity(bd->user_disk_1, disk_cap); - if (vfat_search) { - bd->user_disk_1_first_sector = - cyasblkdev_get_vfat_offset( - bd->user_disk_1_bus_num, - bd->user_disk_1_unit_no); - } else { - bd->user_disk_1_first_sector - = 0; - } - - add_disk(bd->user_disk_1); - } - - if (lcl_unit_no > 0) { - if (bd->system_disk == NULL) { - bd->system_disk = - alloc_disk(8); - - if (bd->system_disk == NULL) { - kfree(bd); - bd = ERR_PTR(-ENOMEM); - return bd; - } - disk_cap = (uint64_t) - (private_partition_size); - - /* set properties of - * system disk */ - bd->system_disk_read_only = !dev_data.desc_p.writeable; - bd->system_disk_blk_size = dev_data.desc_p.block_size; - bd->system_disk_bus_num = bus_num; - bd->system_disk->major = major; - bd->system_disk->first_minor = - (devidx + 2) << CYASBLKDEV_SHIFT; - bd->system_disk->minors = 8; - bd->system_disk->fops = &cyasblkdev_bdops; - bd->system_disk->events = DISK_EVENT_MEDIA_CHANGE; - bd->system_disk->private_data = bd; - bd->system_disk->queue = bd->queue.queue; - /* don't search for vfat - * with system disk */ - bd->system_disk_first_sector = 0; - sprintf( - bd->system_disk->disk_name, - "cyasblkdevblk%d", (devidx + 2)); - - set_capacity(bd->system_disk, - disk_cap); - - add_disk(bd->system_disk); - } - #ifndef WESTBRIDGE_NDEBUG - else { - cy_as_hal_print_message( - "%s: system disk already allocated %d\n", - __func__, bus_num); - } - #endif - } -out: - return ret; -} - -static struct cyasblkdev_blk_data *cyasblkdev_blk_alloc(void) -{ - struct cyasblkdev_blk_data *bd; - int ret = 0; - cy_as_return_status_t stat = -1; - int bus_num = 0; - int total_media_count = 0; - int devidx = 0; - DBGPRN_FUNC_NAME; - - total_media_count = 0; - devidx = find_first_zero_bit(dev_use, CYASBLKDEV_NUM_MINORS); - if (devidx >= CYASBLKDEV_NUM_MINORS) - return ERR_PTR(-ENOSPC); - - __set_bit(devidx, dev_use); - __set_bit(devidx + 1, dev_use); - - bd = kzalloc(sizeof(struct cyasblkdev_blk_data), GFP_KERNEL); - if (bd) { - gl_bd = bd; - - spin_lock_init(&bd->lock); - bd->usage = 1; - - /* setup the block_dev_ops pointer*/ - bd->blkops = &cyasblkdev_bdops; - - /* Get the device handle */ - bd->dev_handle = cyasdevice_getdevhandle(); - if (0 == bd->dev_handle) { - #ifndef WESTBRIDGE_NDEBUG - cy_as_hal_print_message( - "%s: get device failed\n", __func__); - #endif - ret = ENODEV; - goto out; - } - - #ifndef WESTBRIDGE_NDEBUG - cy_as_hal_print_message("%s west bridge device handle:%x\n", - __func__, (uint32_t)bd->dev_handle); - #endif - - /* start the storage api and get a handle to the - * device we are interested in. */ - - /* Error code to use if the conditions are not satisfied. */ - ret = ENOMEDIUM; - - stat = cy_as_misc_release_resource(bd->dev_handle, cy_as_bus_0); - if ((stat != CY_AS_ERROR_SUCCESS) && - (stat != CY_AS_ERROR_RESOURCE_NOT_OWNED)) { - #ifndef WESTBRIDGE_NDEBUG - cy_as_hal_print_message("%s: cannot release " - "resource bus 0 - reason code %d\n", - __func__, stat); - #endif - } - - stat = cy_as_misc_release_resource(bd->dev_handle, cy_as_bus_1); - if ((stat != CY_AS_ERROR_SUCCESS) && - (stat != CY_AS_ERROR_RESOURCE_NOT_OWNED)) { - #ifndef WESTBRIDGE_NDEBUG - cy_as_hal_print_message("%s: cannot release " - "resource bus 0 - reason code %d\n", - __func__, stat); - #endif - } - - /* start storage stack*/ - stat = cy_as_storage_start(bd->dev_handle, 0, 0x101); - if (stat != CY_AS_ERROR_SUCCESS) { - #ifndef WESTBRIDGE_NDEBUG - cy_as_hal_print_message("%s: cannot start storage " - "stack - reason code %d\n", __func__, stat); - #endif - goto out; - } - - #ifndef WESTBRIDGE_NDEBUG - cy_as_hal_print_message("%s: storage started:%d ok\n", - __func__, stat); - #endif - - stat = cy_as_storage_register_callback(bd->dev_handle, - cyasblkdev_storage_callback); - if (stat != CY_AS_ERROR_SUCCESS) { - #ifndef WESTBRIDGE_NDEBUG - cy_as_hal_print_message("%s: cannot register callback " - "- reason code %d\n", __func__, stat); - #endif - goto out; - } - - for (bus_num = 0; bus_num < 2; bus_num++) { - stat = cy_as_storage_query_bus(bd->dev_handle, - bus_num, &bd->media_count[bus_num], 0, 0); - if (stat == CY_AS_ERROR_SUCCESS) { - total_media_count = total_media_count + - bd->media_count[bus_num]; - } else { - #ifndef WESTBRIDGE_NDEBUG - cy_as_hal_print_message("%s: cannot query %d, " - "reason code: %d\n", - __func__, bus_num, stat); - #endif - goto out; - } - } - - if (total_media_count == 0) { - #ifndef WESTBRIDGE_NDEBUG - cy_as_hal_print_message( - "%s: no storage media was found\n", __func__); - #endif - goto out; - } else if (total_media_count >= 1) { - if (bd->user_disk_0 == NULL) { - - bd->user_disk_0 = - alloc_disk(8); - if (bd->user_disk_0 == NULL) { - kfree(bd); - bd = ERR_PTR(-ENOMEM); - return bd; - } - } - #ifndef WESTBRIDGE_NDEBUG - else { - cy_as_hal_print_message("%s: no available " - "gen_disk for disk 0, " - "physically inconsistent\n", __func__); - } - #endif - } - - if (total_media_count == 2) { - if (bd->user_disk_1 == NULL) { - bd->user_disk_1 = - alloc_disk(8); - if (bd->user_disk_1 == NULL) { - kfree(bd); - bd = ERR_PTR(-ENOMEM); - return bd; - } - } - #ifndef WESTBRIDGE_NDEBUG - else { - cy_as_hal_print_message("%s: no available " - "gen_disk for media, " - "physically inconsistent\n", __func__); - } - #endif - } - #ifndef WESTBRIDGE_NDEBUG - else if (total_media_count > 2) { - cy_as_hal_print_message("%s: count corrupted = 0x%d\n", - __func__, total_media_count); - } - #endif - - #ifndef WESTBRIDGE_NDEBUG - cy_as_hal_print_message("%s: %d device(s) found\n", - __func__, total_media_count); - #endif - - for (bus_num = 0; bus_num <= 1; bus_num++) { - /*claim storage for cpu */ - stat = cy_as_storage_claim(bd->dev_handle, - bus_num, 0, 0, 0); - if (stat != CY_AS_ERROR_SUCCESS) { - cy_as_hal_print_message("%s: cannot claim " - "%d bus - reason code %d\n", - __func__, bus_num, stat); - goto out; - } - - dev_data.bus = bus_num; - dev_data.device = 0; - - stat = cy_as_storage_query_device(bd->dev_handle, - &dev_data, 0, 0); - if (stat == CY_AS_ERROR_SUCCESS) { - cyasblkdev_add_disks(bus_num, bd, - total_media_count, devidx); - } else if (stat == CY_AS_ERROR_NO_SUCH_DEVICE) { - #ifndef WESTBRIDGE_NDEBUG - cy_as_hal_print_message( - "%s: no device on bus %d\n", - __func__, bus_num); - #endif - } else { - #ifndef WESTBRIDGE_NDEBUG - cy_as_hal_print_message( - "%s: cannot query %d device " - "- reason code %d\n", - __func__, bus_num, stat); - #endif - goto out; - } - } /* end for (bus_num = 0; bus_num <= 1; bus_num++)*/ - - return bd; - } -out: - #ifndef WESTBRIDGE_NDEBUG - cy_as_hal_print_message( - "%s: bd failed to initialize\n", __func__); - #endif - - kfree(bd); - bd = ERR_PTR(-ret); - return bd; -} - - -/*init west bridge block device */ -static int cyasblkdev_blk_initialize(void) -{ - struct cyasblkdev_blk_data *bd; - int res; - - DBGPRN_FUNC_NAME; - - res = register_blkdev(major, "cyasblkdev"); - - if (res < 0) { - #ifndef WESTBRIDGE_NDEBUG - cy_as_hal_print_message(KERN_WARNING - "%s unable to get major %d for cyasblkdev media: %d\n", - __func__, major, res); - #endif - return res; - } - - if (major == 0) - major = res; - - #ifndef WESTBRIDGE_NDEBUG - cy_as_hal_print_message( - "%s cyasblkdev registered with major number: %d\n", - __func__, major); - #endif - - bd = cyasblkdev_blk_alloc(); - if (IS_ERR(bd)) - return PTR_ERR(bd); - - return 0; -} - -/* start block device */ -static int __init cyasblkdev_blk_init(void) -{ - int res = -ENOMEM; - - DBGPRN_FUNC_NAME; - - /* get the cyasdev handle for future use*/ - cyas_dev_handle = cyasdevice_getdevhandle(); - - if (cyasblkdev_blk_initialize() == 0) - return 0; - - #ifndef WESTBRIDGE_NDEBUG - cy_as_hal_print_message("cyasblkdev init error:%d\n", res); - #endif - return res; -} - - -static void cyasblkdev_blk_deinit(struct cyasblkdev_blk_data *bd) -{ - DBGPRN_FUNC_NAME; - - if (bd) { - int devidx; - - if (bd->user_disk_0 != NULL) { - del_gendisk(bd->user_disk_0); - devidx = bd->user_disk_0->first_minor - >> CYASBLKDEV_SHIFT; - __clear_bit(devidx, dev_use); - } - - if (bd->user_disk_1 != NULL) { - del_gendisk(bd->user_disk_1); - devidx = bd->user_disk_1->first_minor - >> CYASBLKDEV_SHIFT; - __clear_bit(devidx, dev_use); - } - - if (bd->system_disk != NULL) { - del_gendisk(bd->system_disk); - devidx = bd->system_disk->first_minor - >> CYASBLKDEV_SHIFT; - __clear_bit(devidx, dev_use); - } - - cyasblkdev_blk_put(bd); - } -} - -/* block device exit */ -static void __exit cyasblkdev_blk_exit(void) -{ - DBGPRN_FUNC_NAME; - - cyasblkdev_blk_deinit(gl_bd); - unregister_blkdev(major, "cyasblkdev"); - -} - -module_init(cyasblkdev_blk_init); -module_exit(cyasblkdev_blk_exit); - -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("antioch (cyasblkdev) block device driver"); -MODULE_AUTHOR("cypress semiconductor"); - -/*[]*/ |