1baf8532aSAlex Dubov /* 2baf8532aSAlex Dubov * Sony MemoryStick Pro storage support 3baf8532aSAlex Dubov * 4baf8532aSAlex Dubov * Copyright (C) 2007 Alex Dubov <oakad@yahoo.com> 5baf8532aSAlex Dubov * 6baf8532aSAlex Dubov * This program is free software; you can redistribute it and/or modify 7baf8532aSAlex Dubov * it under the terms of the GNU General Public License version 2 as 8baf8532aSAlex Dubov * published by the Free Software Foundation. 9baf8532aSAlex Dubov * 10baf8532aSAlex Dubov * Special thanks to Carlos Corbacho for providing various MemoryStick cards 11baf8532aSAlex Dubov * that made this driver possible. 12baf8532aSAlex Dubov * 13baf8532aSAlex Dubov */ 14baf8532aSAlex Dubov 15baf8532aSAlex Dubov #include <linux/blkdev.h> 16baf8532aSAlex Dubov #include <linux/idr.h> 17baf8532aSAlex Dubov #include <linux/hdreg.h> 18baf8532aSAlex Dubov #include <linux/kthread.h> 1959367258SAlex Dubov #include <linux/delay.h> 20baf8532aSAlex Dubov #include <linux/memstick.h> 21baf8532aSAlex Dubov 22baf8532aSAlex Dubov #define DRIVER_NAME "mspro_block" 23baf8532aSAlex Dubov 24baf8532aSAlex Dubov static int major; 25baf8532aSAlex Dubov module_param(major, int, 0644); 26baf8532aSAlex Dubov 27baf8532aSAlex Dubov #define MSPRO_BLOCK_MAX_SEGS 32 28baf8532aSAlex Dubov #define MSPRO_BLOCK_MAX_PAGES ((2 << 16) - 1) 29baf8532aSAlex Dubov 30baf8532aSAlex Dubov #define MSPRO_BLOCK_SIGNATURE 0xa5c3 31baf8532aSAlex Dubov #define MSPRO_BLOCK_MAX_ATTRIBUTES 41 32baf8532aSAlex Dubov 33baf8532aSAlex Dubov enum { 34baf8532aSAlex Dubov MSPRO_BLOCK_ID_SYSINFO = 0x10, 35baf8532aSAlex Dubov MSPRO_BLOCK_ID_MODELNAME = 0x15, 36baf8532aSAlex Dubov MSPRO_BLOCK_ID_MBR = 0x20, 37baf8532aSAlex Dubov MSPRO_BLOCK_ID_PBR16 = 0x21, 38baf8532aSAlex Dubov MSPRO_BLOCK_ID_PBR32 = 0x22, 39baf8532aSAlex Dubov MSPRO_BLOCK_ID_SPECFILEVALUES1 = 0x25, 40baf8532aSAlex Dubov MSPRO_BLOCK_ID_SPECFILEVALUES2 = 0x26, 41baf8532aSAlex Dubov MSPRO_BLOCK_ID_DEVINFO = 0x30 42baf8532aSAlex Dubov }; 43baf8532aSAlex Dubov 44baf8532aSAlex Dubov struct mspro_sys_attr { 45baf8532aSAlex Dubov size_t size; 46baf8532aSAlex Dubov void *data; 47baf8532aSAlex Dubov unsigned char id; 48baf8532aSAlex Dubov char name[32]; 49baf8532aSAlex Dubov struct device_attribute dev_attr; 50baf8532aSAlex Dubov }; 51baf8532aSAlex Dubov 52baf8532aSAlex Dubov struct mspro_attr_entry { 53baf8532aSAlex Dubov unsigned int address; 54baf8532aSAlex Dubov unsigned int size; 55baf8532aSAlex Dubov unsigned char id; 56baf8532aSAlex Dubov unsigned char reserved[3]; 57baf8532aSAlex Dubov } __attribute__((packed)); 58baf8532aSAlex Dubov 59baf8532aSAlex Dubov struct mspro_attribute { 60baf8532aSAlex Dubov unsigned short signature; 61baf8532aSAlex Dubov unsigned short version; 62baf8532aSAlex Dubov unsigned char count; 63baf8532aSAlex Dubov unsigned char reserved[11]; 64baf8532aSAlex Dubov struct mspro_attr_entry entries[]; 65baf8532aSAlex Dubov } __attribute__((packed)); 66baf8532aSAlex Dubov 67baf8532aSAlex Dubov struct mspro_sys_info { 68baf8532aSAlex Dubov unsigned char class; 69baf8532aSAlex Dubov unsigned char reserved0; 70baf8532aSAlex Dubov unsigned short block_size; 71baf8532aSAlex Dubov unsigned short block_count; 72baf8532aSAlex Dubov unsigned short user_block_count; 73baf8532aSAlex Dubov unsigned short page_size; 74baf8532aSAlex Dubov unsigned char reserved1[2]; 75baf8532aSAlex Dubov unsigned char assembly_date[8]; 76baf8532aSAlex Dubov unsigned int serial_number; 77baf8532aSAlex Dubov unsigned char assembly_maker_code; 78baf8532aSAlex Dubov unsigned char assembly_model_code[3]; 79baf8532aSAlex Dubov unsigned short memory_maker_code; 80baf8532aSAlex Dubov unsigned short memory_model_code; 81baf8532aSAlex Dubov unsigned char reserved2[4]; 82baf8532aSAlex Dubov unsigned char vcc; 83baf8532aSAlex Dubov unsigned char vpp; 84baf8532aSAlex Dubov unsigned short controller_number; 85baf8532aSAlex Dubov unsigned short controller_function; 86baf8532aSAlex Dubov unsigned short start_sector; 87baf8532aSAlex Dubov unsigned short unit_size; 88baf8532aSAlex Dubov unsigned char ms_sub_class; 89baf8532aSAlex Dubov unsigned char reserved3[4]; 90baf8532aSAlex Dubov unsigned char interface_type; 91baf8532aSAlex Dubov unsigned short controller_code; 92baf8532aSAlex Dubov unsigned char format_type; 93baf8532aSAlex Dubov unsigned char reserved4; 94baf8532aSAlex Dubov unsigned char device_type; 95baf8532aSAlex Dubov unsigned char reserved5[7]; 96baf8532aSAlex Dubov unsigned char mspro_id[16]; 97baf8532aSAlex Dubov unsigned char reserved6[16]; 98baf8532aSAlex Dubov } __attribute__((packed)); 99baf8532aSAlex Dubov 100baf8532aSAlex Dubov struct mspro_mbr { 101baf8532aSAlex Dubov unsigned char boot_partition; 102baf8532aSAlex Dubov unsigned char start_head; 103baf8532aSAlex Dubov unsigned char start_sector; 104baf8532aSAlex Dubov unsigned char start_cylinder; 105baf8532aSAlex Dubov unsigned char partition_type; 106baf8532aSAlex Dubov unsigned char end_head; 107baf8532aSAlex Dubov unsigned char end_sector; 108baf8532aSAlex Dubov unsigned char end_cylinder; 109baf8532aSAlex Dubov unsigned int start_sectors; 110baf8532aSAlex Dubov unsigned int sectors_per_partition; 111baf8532aSAlex Dubov } __attribute__((packed)); 112baf8532aSAlex Dubov 113efb2742eSAlex Dubov struct mspro_specfile { 114efb2742eSAlex Dubov char name[8]; 115efb2742eSAlex Dubov char ext[3]; 116efb2742eSAlex Dubov unsigned char attr; 117efb2742eSAlex Dubov unsigned char reserved[10]; 118efb2742eSAlex Dubov unsigned short time; 119efb2742eSAlex Dubov unsigned short date; 120efb2742eSAlex Dubov unsigned short cluster; 121efb2742eSAlex Dubov unsigned int size; 122efb2742eSAlex Dubov } __attribute__((packed)); 123efb2742eSAlex Dubov 124baf8532aSAlex Dubov struct mspro_devinfo { 125baf8532aSAlex Dubov unsigned short cylinders; 126baf8532aSAlex Dubov unsigned short heads; 127baf8532aSAlex Dubov unsigned short bytes_per_track; 128baf8532aSAlex Dubov unsigned short bytes_per_sector; 129baf8532aSAlex Dubov unsigned short sectors_per_track; 130baf8532aSAlex Dubov unsigned char reserved[6]; 131baf8532aSAlex Dubov } __attribute__((packed)); 132baf8532aSAlex Dubov 133baf8532aSAlex Dubov struct mspro_block_data { 134baf8532aSAlex Dubov struct memstick_dev *card; 135baf8532aSAlex Dubov unsigned int usage_count; 136ead70773SAlex Dubov unsigned int caps; 137baf8532aSAlex Dubov struct gendisk *disk; 138baf8532aSAlex Dubov struct request_queue *queue; 139baf8532aSAlex Dubov spinlock_t q_lock; 140baf8532aSAlex Dubov wait_queue_head_t q_wait; 141baf8532aSAlex Dubov struct task_struct *q_thread; 142baf8532aSAlex Dubov 143baf8532aSAlex Dubov unsigned short page_size; 144baf8532aSAlex Dubov unsigned short cylinders; 145baf8532aSAlex Dubov unsigned short heads; 146baf8532aSAlex Dubov unsigned short sectors_per_track; 147baf8532aSAlex Dubov 148baf8532aSAlex Dubov unsigned char system; 149baf8532aSAlex Dubov unsigned char read_only:1, 150baf8532aSAlex Dubov active:1, 151baf8532aSAlex Dubov has_request:1, 152baf8532aSAlex Dubov data_dir:1; 153baf8532aSAlex Dubov unsigned char transfer_cmd; 154baf8532aSAlex Dubov 155baf8532aSAlex Dubov int (*mrq_handler)(struct memstick_dev *card, 156baf8532aSAlex Dubov struct memstick_request **mrq); 157baf8532aSAlex Dubov 158baf8532aSAlex Dubov struct attribute_group attr_group; 159baf8532aSAlex Dubov 160baf8532aSAlex Dubov struct scatterlist req_sg[MSPRO_BLOCK_MAX_SEGS]; 161baf8532aSAlex Dubov unsigned int seg_count; 162baf8532aSAlex Dubov unsigned int current_seg; 163baf8532aSAlex Dubov unsigned short current_page; 164baf8532aSAlex Dubov }; 165baf8532aSAlex Dubov 166baf8532aSAlex Dubov static DEFINE_IDR(mspro_block_disk_idr); 167baf8532aSAlex Dubov static DEFINE_MUTEX(mspro_block_disk_lock); 168baf8532aSAlex Dubov 169baf8532aSAlex Dubov /*** Block device ***/ 170baf8532aSAlex Dubov 171baf8532aSAlex Dubov static int mspro_block_bd_open(struct inode *inode, struct file *filp) 172baf8532aSAlex Dubov { 173baf8532aSAlex Dubov struct gendisk *disk = inode->i_bdev->bd_disk; 174baf8532aSAlex Dubov struct mspro_block_data *msb = disk->private_data; 175baf8532aSAlex Dubov int rc = -ENXIO; 176baf8532aSAlex Dubov 177baf8532aSAlex Dubov mutex_lock(&mspro_block_disk_lock); 178baf8532aSAlex Dubov 179baf8532aSAlex Dubov if (msb && msb->card) { 180baf8532aSAlex Dubov msb->usage_count++; 181baf8532aSAlex Dubov if ((filp->f_mode & FMODE_WRITE) && msb->read_only) 182baf8532aSAlex Dubov rc = -EROFS; 183baf8532aSAlex Dubov else 184baf8532aSAlex Dubov rc = 0; 185baf8532aSAlex Dubov } 186baf8532aSAlex Dubov 187baf8532aSAlex Dubov mutex_unlock(&mspro_block_disk_lock); 188baf8532aSAlex Dubov 189baf8532aSAlex Dubov return rc; 190baf8532aSAlex Dubov } 191baf8532aSAlex Dubov 192baf8532aSAlex Dubov 193baf8532aSAlex Dubov static int mspro_block_disk_release(struct gendisk *disk) 194baf8532aSAlex Dubov { 195baf8532aSAlex Dubov struct mspro_block_data *msb = disk->private_data; 196baf8532aSAlex Dubov int disk_id = disk->first_minor >> MEMSTICK_PART_SHIFT; 197baf8532aSAlex Dubov 198baf8532aSAlex Dubov mutex_lock(&mspro_block_disk_lock); 199baf8532aSAlex Dubov 200baf8532aSAlex Dubov if (msb->usage_count) { 201baf8532aSAlex Dubov msb->usage_count--; 202baf8532aSAlex Dubov if (!msb->usage_count) { 203baf8532aSAlex Dubov kfree(msb); 204baf8532aSAlex Dubov disk->private_data = NULL; 205baf8532aSAlex Dubov idr_remove(&mspro_block_disk_idr, disk_id); 206baf8532aSAlex Dubov put_disk(disk); 207baf8532aSAlex Dubov } 208baf8532aSAlex Dubov } 209baf8532aSAlex Dubov 210baf8532aSAlex Dubov mutex_unlock(&mspro_block_disk_lock); 211baf8532aSAlex Dubov 212baf8532aSAlex Dubov return 0; 213baf8532aSAlex Dubov } 214baf8532aSAlex Dubov 215baf8532aSAlex Dubov static int mspro_block_bd_release(struct inode *inode, struct file *filp) 216baf8532aSAlex Dubov { 217baf8532aSAlex Dubov struct gendisk *disk = inode->i_bdev->bd_disk; 218baf8532aSAlex Dubov return mspro_block_disk_release(disk); 219baf8532aSAlex Dubov } 220baf8532aSAlex Dubov 221baf8532aSAlex Dubov static int mspro_block_bd_getgeo(struct block_device *bdev, 222baf8532aSAlex Dubov struct hd_geometry *geo) 223baf8532aSAlex Dubov { 224baf8532aSAlex Dubov struct mspro_block_data *msb = bdev->bd_disk->private_data; 225baf8532aSAlex Dubov 226baf8532aSAlex Dubov geo->heads = msb->heads; 227baf8532aSAlex Dubov geo->sectors = msb->sectors_per_track; 228baf8532aSAlex Dubov geo->cylinders = msb->cylinders; 229baf8532aSAlex Dubov 230baf8532aSAlex Dubov return 0; 231baf8532aSAlex Dubov } 232baf8532aSAlex Dubov 233baf8532aSAlex Dubov static struct block_device_operations ms_block_bdops = { 234baf8532aSAlex Dubov .open = mspro_block_bd_open, 235baf8532aSAlex Dubov .release = mspro_block_bd_release, 236baf8532aSAlex Dubov .getgeo = mspro_block_bd_getgeo, 237baf8532aSAlex Dubov .owner = THIS_MODULE 238baf8532aSAlex Dubov }; 239baf8532aSAlex Dubov 240baf8532aSAlex Dubov /*** Information ***/ 241baf8532aSAlex Dubov 242baf8532aSAlex Dubov static struct mspro_sys_attr *mspro_from_sysfs_attr(struct attribute *attr) 243baf8532aSAlex Dubov { 244baf8532aSAlex Dubov struct device_attribute *dev_attr 245baf8532aSAlex Dubov = container_of(attr, struct device_attribute, attr); 246baf8532aSAlex Dubov return container_of(dev_attr, struct mspro_sys_attr, dev_attr); 247baf8532aSAlex Dubov } 248baf8532aSAlex Dubov 249baf8532aSAlex Dubov static const char *mspro_block_attr_name(unsigned char tag) 250baf8532aSAlex Dubov { 251baf8532aSAlex Dubov switch (tag) { 252baf8532aSAlex Dubov case MSPRO_BLOCK_ID_SYSINFO: 253baf8532aSAlex Dubov return "attr_sysinfo"; 254baf8532aSAlex Dubov case MSPRO_BLOCK_ID_MODELNAME: 255baf8532aSAlex Dubov return "attr_modelname"; 256baf8532aSAlex Dubov case MSPRO_BLOCK_ID_MBR: 257baf8532aSAlex Dubov return "attr_mbr"; 258baf8532aSAlex Dubov case MSPRO_BLOCK_ID_PBR16: 259baf8532aSAlex Dubov return "attr_pbr16"; 260baf8532aSAlex Dubov case MSPRO_BLOCK_ID_PBR32: 261baf8532aSAlex Dubov return "attr_pbr32"; 262baf8532aSAlex Dubov case MSPRO_BLOCK_ID_SPECFILEVALUES1: 263baf8532aSAlex Dubov return "attr_specfilevalues1"; 264baf8532aSAlex Dubov case MSPRO_BLOCK_ID_SPECFILEVALUES2: 265baf8532aSAlex Dubov return "attr_specfilevalues2"; 266baf8532aSAlex Dubov case MSPRO_BLOCK_ID_DEVINFO: 267baf8532aSAlex Dubov return "attr_devinfo"; 268baf8532aSAlex Dubov default: 269baf8532aSAlex Dubov return NULL; 270baf8532aSAlex Dubov }; 271baf8532aSAlex Dubov } 272baf8532aSAlex Dubov 273baf8532aSAlex Dubov typedef ssize_t (*sysfs_show_t)(struct device *dev, 274baf8532aSAlex Dubov struct device_attribute *attr, 275baf8532aSAlex Dubov char *buffer); 276baf8532aSAlex Dubov 277baf8532aSAlex Dubov static ssize_t mspro_block_attr_show_default(struct device *dev, 278baf8532aSAlex Dubov struct device_attribute *attr, 279baf8532aSAlex Dubov char *buffer) 280baf8532aSAlex Dubov { 281baf8532aSAlex Dubov struct mspro_sys_attr *s_attr = container_of(attr, 282baf8532aSAlex Dubov struct mspro_sys_attr, 283baf8532aSAlex Dubov dev_attr); 284baf8532aSAlex Dubov 285baf8532aSAlex Dubov ssize_t cnt, rc = 0; 286baf8532aSAlex Dubov 287baf8532aSAlex Dubov for (cnt = 0; cnt < s_attr->size; cnt++) { 288baf8532aSAlex Dubov if (cnt && !(cnt % 16)) { 289baf8532aSAlex Dubov if (PAGE_SIZE - rc) 290baf8532aSAlex Dubov buffer[rc++] = '\n'; 291baf8532aSAlex Dubov } 292baf8532aSAlex Dubov 293baf8532aSAlex Dubov rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "%02x ", 294baf8532aSAlex Dubov ((unsigned char *)s_attr->data)[cnt]); 295baf8532aSAlex Dubov } 296baf8532aSAlex Dubov return rc; 297baf8532aSAlex Dubov } 298baf8532aSAlex Dubov 299baf8532aSAlex Dubov static ssize_t mspro_block_attr_show_sysinfo(struct device *dev, 300baf8532aSAlex Dubov struct device_attribute *attr, 301baf8532aSAlex Dubov char *buffer) 302baf8532aSAlex Dubov { 303baf8532aSAlex Dubov struct mspro_sys_attr *x_attr = container_of(attr, 304baf8532aSAlex Dubov struct mspro_sys_attr, 305baf8532aSAlex Dubov dev_attr); 306baf8532aSAlex Dubov struct mspro_sys_info *x_sys = x_attr->data; 307baf8532aSAlex Dubov ssize_t rc = 0; 308251cc9b9SAlex Dubov int date_tz = 0, date_tz_f = 0; 309251cc9b9SAlex Dubov 310251cc9b9SAlex Dubov if (x_sys->assembly_date[0] > 0x80U) { 311251cc9b9SAlex Dubov date_tz = (~x_sys->assembly_date[0]) + 1; 312251cc9b9SAlex Dubov date_tz_f = date_tz & 3; 313251cc9b9SAlex Dubov date_tz >>= 2; 314251cc9b9SAlex Dubov date_tz = -date_tz; 315251cc9b9SAlex Dubov date_tz_f *= 15; 316251cc9b9SAlex Dubov } else if (x_sys->assembly_date[0] < 0x80U) { 317251cc9b9SAlex Dubov date_tz = x_sys->assembly_date[0]; 318251cc9b9SAlex Dubov date_tz_f = date_tz & 3; 319251cc9b9SAlex Dubov date_tz >>= 2; 320251cc9b9SAlex Dubov date_tz_f *= 15; 321251cc9b9SAlex Dubov } 322baf8532aSAlex Dubov 323baf8532aSAlex Dubov rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "class: %x\n", 324baf8532aSAlex Dubov x_sys->class); 325baf8532aSAlex Dubov rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "block size: %x\n", 326baf8532aSAlex Dubov be16_to_cpu(x_sys->block_size)); 327baf8532aSAlex Dubov rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "block count: %x\n", 328baf8532aSAlex Dubov be16_to_cpu(x_sys->block_count)); 329baf8532aSAlex Dubov rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "user block count: %x\n", 330baf8532aSAlex Dubov be16_to_cpu(x_sys->user_block_count)); 331baf8532aSAlex Dubov rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "page size: %x\n", 332baf8532aSAlex Dubov be16_to_cpu(x_sys->page_size)); 333baf8532aSAlex Dubov rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "assembly date: " 334251cc9b9SAlex Dubov "GMT%+d:%d %04u-%02u-%02u %02u:%02u:%02u\n", 335251cc9b9SAlex Dubov date_tz, date_tz_f, 336baf8532aSAlex Dubov be16_to_cpu(*(unsigned short *) 337baf8532aSAlex Dubov &x_sys->assembly_date[1]), 338baf8532aSAlex Dubov x_sys->assembly_date[3], x_sys->assembly_date[4], 339baf8532aSAlex Dubov x_sys->assembly_date[5], x_sys->assembly_date[6], 340baf8532aSAlex Dubov x_sys->assembly_date[7]); 341baf8532aSAlex Dubov rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "serial number: %x\n", 342baf8532aSAlex Dubov be32_to_cpu(x_sys->serial_number)); 343baf8532aSAlex Dubov rc += scnprintf(buffer + rc, PAGE_SIZE - rc, 344baf8532aSAlex Dubov "assembly maker code: %x\n", 345baf8532aSAlex Dubov x_sys->assembly_maker_code); 346baf8532aSAlex Dubov rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "assembly model code: " 347baf8532aSAlex Dubov "%02x%02x%02x\n", x_sys->assembly_model_code[0], 348baf8532aSAlex Dubov x_sys->assembly_model_code[1], 349baf8532aSAlex Dubov x_sys->assembly_model_code[2]); 350baf8532aSAlex Dubov rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "memory maker code: %x\n", 351baf8532aSAlex Dubov be16_to_cpu(x_sys->memory_maker_code)); 352baf8532aSAlex Dubov rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "memory model code: %x\n", 353baf8532aSAlex Dubov be16_to_cpu(x_sys->memory_model_code)); 354baf8532aSAlex Dubov rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "vcc: %x\n", 355baf8532aSAlex Dubov x_sys->vcc); 356baf8532aSAlex Dubov rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "vpp: %x\n", 357baf8532aSAlex Dubov x_sys->vpp); 358baf8532aSAlex Dubov rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "controller number: %x\n", 359baf8532aSAlex Dubov be16_to_cpu(x_sys->controller_number)); 360baf8532aSAlex Dubov rc += scnprintf(buffer + rc, PAGE_SIZE - rc, 361baf8532aSAlex Dubov "controller function: %x\n", 362baf8532aSAlex Dubov be16_to_cpu(x_sys->controller_function)); 363baf8532aSAlex Dubov rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "start sector: %x\n", 364baf8532aSAlex Dubov be16_to_cpu(x_sys->start_sector)); 365baf8532aSAlex Dubov rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "unit size: %x\n", 366baf8532aSAlex Dubov be16_to_cpu(x_sys->unit_size)); 367baf8532aSAlex Dubov rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "sub class: %x\n", 368baf8532aSAlex Dubov x_sys->ms_sub_class); 369baf8532aSAlex Dubov rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "interface type: %x\n", 370baf8532aSAlex Dubov x_sys->interface_type); 371baf8532aSAlex Dubov rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "controller code: %x\n", 372baf8532aSAlex Dubov be16_to_cpu(x_sys->controller_code)); 373baf8532aSAlex Dubov rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "format type: %x\n", 374baf8532aSAlex Dubov x_sys->format_type); 375baf8532aSAlex Dubov rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "device type: %x\n", 376baf8532aSAlex Dubov x_sys->device_type); 377baf8532aSAlex Dubov rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "mspro id: %s\n", 378baf8532aSAlex Dubov x_sys->mspro_id); 379baf8532aSAlex Dubov return rc; 380baf8532aSAlex Dubov } 381baf8532aSAlex Dubov 382baf8532aSAlex Dubov static ssize_t mspro_block_attr_show_modelname(struct device *dev, 383baf8532aSAlex Dubov struct device_attribute *attr, 384baf8532aSAlex Dubov char *buffer) 385baf8532aSAlex Dubov { 386baf8532aSAlex Dubov struct mspro_sys_attr *s_attr = container_of(attr, 387baf8532aSAlex Dubov struct mspro_sys_attr, 388baf8532aSAlex Dubov dev_attr); 389baf8532aSAlex Dubov 390baf8532aSAlex Dubov return scnprintf(buffer, PAGE_SIZE, "%s", (char *)s_attr->data); 391baf8532aSAlex Dubov } 392baf8532aSAlex Dubov 393baf8532aSAlex Dubov static ssize_t mspro_block_attr_show_mbr(struct device *dev, 394baf8532aSAlex Dubov struct device_attribute *attr, 395baf8532aSAlex Dubov char *buffer) 396baf8532aSAlex Dubov { 397baf8532aSAlex Dubov struct mspro_sys_attr *x_attr = container_of(attr, 398baf8532aSAlex Dubov struct mspro_sys_attr, 399baf8532aSAlex Dubov dev_attr); 400baf8532aSAlex Dubov struct mspro_mbr *x_mbr = x_attr->data; 401baf8532aSAlex Dubov ssize_t rc = 0; 402baf8532aSAlex Dubov 403baf8532aSAlex Dubov rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "boot partition: %x\n", 404baf8532aSAlex Dubov x_mbr->boot_partition); 405baf8532aSAlex Dubov rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "start head: %x\n", 406baf8532aSAlex Dubov x_mbr->start_head); 407baf8532aSAlex Dubov rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "start sector: %x\n", 408baf8532aSAlex Dubov x_mbr->start_sector); 409baf8532aSAlex Dubov rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "start cylinder: %x\n", 410baf8532aSAlex Dubov x_mbr->start_cylinder); 411baf8532aSAlex Dubov rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "partition type: %x\n", 412baf8532aSAlex Dubov x_mbr->partition_type); 413baf8532aSAlex Dubov rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "end head: %x\n", 414baf8532aSAlex Dubov x_mbr->end_head); 415baf8532aSAlex Dubov rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "end sector: %x\n", 416baf8532aSAlex Dubov x_mbr->end_sector); 417baf8532aSAlex Dubov rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "end cylinder: %x\n", 418baf8532aSAlex Dubov x_mbr->end_cylinder); 419baf8532aSAlex Dubov rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "start sectors: %x\n", 420baf8532aSAlex Dubov x_mbr->start_sectors); 421baf8532aSAlex Dubov rc += scnprintf(buffer + rc, PAGE_SIZE - rc, 422baf8532aSAlex Dubov "sectors per partition: %x\n", 423baf8532aSAlex Dubov x_mbr->sectors_per_partition); 424baf8532aSAlex Dubov return rc; 425baf8532aSAlex Dubov } 426baf8532aSAlex Dubov 427efb2742eSAlex Dubov static ssize_t mspro_block_attr_show_specfile(struct device *dev, 428efb2742eSAlex Dubov struct device_attribute *attr, 429efb2742eSAlex Dubov char *buffer) 430efb2742eSAlex Dubov { 431efb2742eSAlex Dubov struct mspro_sys_attr *x_attr = container_of(attr, 432efb2742eSAlex Dubov struct mspro_sys_attr, 433efb2742eSAlex Dubov dev_attr); 434efb2742eSAlex Dubov struct mspro_specfile *x_spfile = x_attr->data; 435efb2742eSAlex Dubov char name[9], ext[4]; 436efb2742eSAlex Dubov ssize_t rc = 0; 437efb2742eSAlex Dubov 438efb2742eSAlex Dubov memcpy(name, x_spfile->name, 8); 439efb2742eSAlex Dubov name[8] = 0; 440efb2742eSAlex Dubov memcpy(ext, x_spfile->ext, 3); 441efb2742eSAlex Dubov ext[3] = 0; 442efb2742eSAlex Dubov 443efb2742eSAlex Dubov rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "name: %s\n", name); 444efb2742eSAlex Dubov rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "ext: %s\n", ext); 445efb2742eSAlex Dubov rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "attribute: %x\n", 446efb2742eSAlex Dubov x_spfile->attr); 447efb2742eSAlex Dubov rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "time: %d:%d:%d\n", 448efb2742eSAlex Dubov x_spfile->time >> 11, 449efb2742eSAlex Dubov (x_spfile->time >> 5) & 0x3f, 450efb2742eSAlex Dubov (x_spfile->time & 0x1f) * 2); 451efb2742eSAlex Dubov rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "date: %d-%d-%d\n", 452efb2742eSAlex Dubov (x_spfile->date >> 9) + 1980, 453efb2742eSAlex Dubov (x_spfile->date >> 5) & 0xf, 454efb2742eSAlex Dubov x_spfile->date & 0x1f); 455efb2742eSAlex Dubov rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "start cluster: %x\n", 456efb2742eSAlex Dubov x_spfile->cluster); 457efb2742eSAlex Dubov rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "size: %x\n", 458efb2742eSAlex Dubov x_spfile->size); 459efb2742eSAlex Dubov return rc; 460efb2742eSAlex Dubov } 461efb2742eSAlex Dubov 462baf8532aSAlex Dubov static ssize_t mspro_block_attr_show_devinfo(struct device *dev, 463baf8532aSAlex Dubov struct device_attribute *attr, 464baf8532aSAlex Dubov char *buffer) 465baf8532aSAlex Dubov { 466baf8532aSAlex Dubov struct mspro_sys_attr *x_attr = container_of(attr, 467baf8532aSAlex Dubov struct mspro_sys_attr, 468baf8532aSAlex Dubov dev_attr); 469baf8532aSAlex Dubov struct mspro_devinfo *x_devinfo = x_attr->data; 470baf8532aSAlex Dubov ssize_t rc = 0; 471baf8532aSAlex Dubov 472baf8532aSAlex Dubov rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "cylinders: %x\n", 473baf8532aSAlex Dubov be16_to_cpu(x_devinfo->cylinders)); 474baf8532aSAlex Dubov rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "heads: %x\n", 475baf8532aSAlex Dubov be16_to_cpu(x_devinfo->heads)); 476baf8532aSAlex Dubov rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "bytes per track: %x\n", 477baf8532aSAlex Dubov be16_to_cpu(x_devinfo->bytes_per_track)); 478baf8532aSAlex Dubov rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "bytes per sector: %x\n", 479baf8532aSAlex Dubov be16_to_cpu(x_devinfo->bytes_per_sector)); 480baf8532aSAlex Dubov rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "sectors per track: %x\n", 481baf8532aSAlex Dubov be16_to_cpu(x_devinfo->sectors_per_track)); 482baf8532aSAlex Dubov return rc; 483baf8532aSAlex Dubov } 484baf8532aSAlex Dubov 485baf8532aSAlex Dubov static sysfs_show_t mspro_block_attr_show(unsigned char tag) 486baf8532aSAlex Dubov { 487baf8532aSAlex Dubov switch (tag) { 488baf8532aSAlex Dubov case MSPRO_BLOCK_ID_SYSINFO: 489baf8532aSAlex Dubov return mspro_block_attr_show_sysinfo; 490baf8532aSAlex Dubov case MSPRO_BLOCK_ID_MODELNAME: 491baf8532aSAlex Dubov return mspro_block_attr_show_modelname; 492baf8532aSAlex Dubov case MSPRO_BLOCK_ID_MBR: 493baf8532aSAlex Dubov return mspro_block_attr_show_mbr; 494efb2742eSAlex Dubov case MSPRO_BLOCK_ID_SPECFILEVALUES1: 495efb2742eSAlex Dubov case MSPRO_BLOCK_ID_SPECFILEVALUES2: 496efb2742eSAlex Dubov return mspro_block_attr_show_specfile; 497baf8532aSAlex Dubov case MSPRO_BLOCK_ID_DEVINFO: 498baf8532aSAlex Dubov return mspro_block_attr_show_devinfo; 499baf8532aSAlex Dubov default: 500baf8532aSAlex Dubov return mspro_block_attr_show_default; 501baf8532aSAlex Dubov } 502baf8532aSAlex Dubov } 503baf8532aSAlex Dubov 504baf8532aSAlex Dubov /*** Protocol handlers ***/ 505baf8532aSAlex Dubov 506baf8532aSAlex Dubov /* 507baf8532aSAlex Dubov * Functions prefixed with "h_" are protocol callbacks. They can be called from 508baf8532aSAlex Dubov * interrupt context. Return value of 0 means that request processing is still 509baf8532aSAlex Dubov * ongoing, while special error value of -EAGAIN means that current request is 510baf8532aSAlex Dubov * finished (and request processor should come back some time later). 511baf8532aSAlex Dubov */ 512baf8532aSAlex Dubov 513baf8532aSAlex Dubov static int h_mspro_block_req_init(struct memstick_dev *card, 514baf8532aSAlex Dubov struct memstick_request **mrq) 515baf8532aSAlex Dubov { 516baf8532aSAlex Dubov struct mspro_block_data *msb = memstick_get_drvdata(card); 517baf8532aSAlex Dubov 518baf8532aSAlex Dubov *mrq = &card->current_mrq; 519baf8532aSAlex Dubov card->next_request = msb->mrq_handler; 520baf8532aSAlex Dubov return 0; 521baf8532aSAlex Dubov } 522baf8532aSAlex Dubov 523baf8532aSAlex Dubov static int h_mspro_block_default(struct memstick_dev *card, 524baf8532aSAlex Dubov struct memstick_request **mrq) 525baf8532aSAlex Dubov { 526baf8532aSAlex Dubov complete(&card->mrq_complete); 527baf8532aSAlex Dubov if (!(*mrq)->error) 528baf8532aSAlex Dubov return -EAGAIN; 529baf8532aSAlex Dubov else 530baf8532aSAlex Dubov return (*mrq)->error; 531baf8532aSAlex Dubov } 532baf8532aSAlex Dubov 533baf8532aSAlex Dubov static int h_mspro_block_get_ro(struct memstick_dev *card, 534baf8532aSAlex Dubov struct memstick_request **mrq) 535baf8532aSAlex Dubov { 536baf8532aSAlex Dubov struct mspro_block_data *msb = memstick_get_drvdata(card); 537baf8532aSAlex Dubov 538baf8532aSAlex Dubov if ((*mrq)->error) { 539baf8532aSAlex Dubov complete(&card->mrq_complete); 540baf8532aSAlex Dubov return (*mrq)->error; 541baf8532aSAlex Dubov } 542baf8532aSAlex Dubov 543baf8532aSAlex Dubov if ((*mrq)->data[offsetof(struct ms_status_register, status0)] 544baf8532aSAlex Dubov & MEMSTICK_STATUS0_WP) 545baf8532aSAlex Dubov msb->read_only = 1; 546baf8532aSAlex Dubov else 547baf8532aSAlex Dubov msb->read_only = 0; 548baf8532aSAlex Dubov 549baf8532aSAlex Dubov complete(&card->mrq_complete); 550baf8532aSAlex Dubov return -EAGAIN; 551baf8532aSAlex Dubov } 552baf8532aSAlex Dubov 553baf8532aSAlex Dubov static int h_mspro_block_wait_for_ced(struct memstick_dev *card, 554baf8532aSAlex Dubov struct memstick_request **mrq) 555baf8532aSAlex Dubov { 556baf8532aSAlex Dubov if ((*mrq)->error) { 557baf8532aSAlex Dubov complete(&card->mrq_complete); 558baf8532aSAlex Dubov return (*mrq)->error; 559baf8532aSAlex Dubov } 560baf8532aSAlex Dubov 561baf8532aSAlex Dubov dev_dbg(&card->dev, "wait for ced: value %x\n", (*mrq)->data[0]); 562baf8532aSAlex Dubov 563baf8532aSAlex Dubov if ((*mrq)->data[0] & (MEMSTICK_INT_CMDNAK | MEMSTICK_INT_ERR)) { 564baf8532aSAlex Dubov card->current_mrq.error = -EFAULT; 565baf8532aSAlex Dubov complete(&card->mrq_complete); 566baf8532aSAlex Dubov return card->current_mrq.error; 567baf8532aSAlex Dubov } 568baf8532aSAlex Dubov 569baf8532aSAlex Dubov if (!((*mrq)->data[0] & MEMSTICK_INT_CED)) 570baf8532aSAlex Dubov return 0; 571baf8532aSAlex Dubov else { 572baf8532aSAlex Dubov card->current_mrq.error = 0; 573baf8532aSAlex Dubov complete(&card->mrq_complete); 574baf8532aSAlex Dubov return -EAGAIN; 575baf8532aSAlex Dubov } 576baf8532aSAlex Dubov } 577baf8532aSAlex Dubov 578baf8532aSAlex Dubov static int h_mspro_block_transfer_data(struct memstick_dev *card, 579baf8532aSAlex Dubov struct memstick_request **mrq) 580baf8532aSAlex Dubov { 581baf8532aSAlex Dubov struct mspro_block_data *msb = memstick_get_drvdata(card); 582baf8532aSAlex Dubov unsigned char t_val = 0; 583baf8532aSAlex Dubov struct scatterlist t_sg = { 0 }; 584baf8532aSAlex Dubov size_t t_offset; 585baf8532aSAlex Dubov 586baf8532aSAlex Dubov if ((*mrq)->error) { 587baf8532aSAlex Dubov complete(&card->mrq_complete); 588baf8532aSAlex Dubov return (*mrq)->error; 589baf8532aSAlex Dubov } 590baf8532aSAlex Dubov 591baf8532aSAlex Dubov switch ((*mrq)->tpc) { 592baf8532aSAlex Dubov case MS_TPC_WRITE_REG: 593baf8532aSAlex Dubov memstick_init_req(*mrq, MS_TPC_SET_CMD, &msb->transfer_cmd, 1); 594ead70773SAlex Dubov (*mrq)->need_card_int = 1; 595baf8532aSAlex Dubov return 0; 596baf8532aSAlex Dubov case MS_TPC_SET_CMD: 597baf8532aSAlex Dubov t_val = (*mrq)->int_reg; 598baf8532aSAlex Dubov memstick_init_req(*mrq, MS_TPC_GET_INT, NULL, 1); 599ead70773SAlex Dubov if (msb->caps & MEMSTICK_CAP_AUTO_GET_INT) 600baf8532aSAlex Dubov goto has_int_reg; 601baf8532aSAlex Dubov return 0; 602baf8532aSAlex Dubov case MS_TPC_GET_INT: 603baf8532aSAlex Dubov t_val = (*mrq)->data[0]; 604baf8532aSAlex Dubov has_int_reg: 605baf8532aSAlex Dubov if (t_val & (MEMSTICK_INT_CMDNAK | MEMSTICK_INT_ERR)) { 606baf8532aSAlex Dubov t_val = MSPRO_CMD_STOP; 607baf8532aSAlex Dubov memstick_init_req(*mrq, MS_TPC_SET_CMD, &t_val, 1); 608baf8532aSAlex Dubov card->next_request = h_mspro_block_default; 609baf8532aSAlex Dubov return 0; 610baf8532aSAlex Dubov } 611baf8532aSAlex Dubov 612baf8532aSAlex Dubov if (msb->current_page 613baf8532aSAlex Dubov == (msb->req_sg[msb->current_seg].length 614baf8532aSAlex Dubov / msb->page_size)) { 615baf8532aSAlex Dubov msb->current_page = 0; 616baf8532aSAlex Dubov msb->current_seg++; 617baf8532aSAlex Dubov 618baf8532aSAlex Dubov if (msb->current_seg == msb->seg_count) { 619baf8532aSAlex Dubov if (t_val & MEMSTICK_INT_CED) { 620baf8532aSAlex Dubov complete(&card->mrq_complete); 621baf8532aSAlex Dubov return -EAGAIN; 622baf8532aSAlex Dubov } else { 623baf8532aSAlex Dubov card->next_request 624baf8532aSAlex Dubov = h_mspro_block_wait_for_ced; 625baf8532aSAlex Dubov memstick_init_req(*mrq, MS_TPC_GET_INT, 626baf8532aSAlex Dubov NULL, 1); 627baf8532aSAlex Dubov return 0; 628baf8532aSAlex Dubov } 629baf8532aSAlex Dubov } 630baf8532aSAlex Dubov } 631baf8532aSAlex Dubov 632baf8532aSAlex Dubov if (!(t_val & MEMSTICK_INT_BREQ)) { 633baf8532aSAlex Dubov memstick_init_req(*mrq, MS_TPC_GET_INT, NULL, 1); 634baf8532aSAlex Dubov return 0; 635baf8532aSAlex Dubov } 636baf8532aSAlex Dubov 637baf8532aSAlex Dubov t_offset = msb->req_sg[msb->current_seg].offset; 638baf8532aSAlex Dubov t_offset += msb->current_page * msb->page_size; 639baf8532aSAlex Dubov 640baf8532aSAlex Dubov sg_set_page(&t_sg, 641baf8532aSAlex Dubov nth_page(sg_page(&(msb->req_sg[msb->current_seg])), 642baf8532aSAlex Dubov t_offset >> PAGE_SHIFT), 643baf8532aSAlex Dubov msb->page_size, offset_in_page(t_offset)); 644baf8532aSAlex Dubov 645baf8532aSAlex Dubov memstick_init_req_sg(*mrq, msb->data_dir == READ 646baf8532aSAlex Dubov ? MS_TPC_READ_LONG_DATA 647baf8532aSAlex Dubov : MS_TPC_WRITE_LONG_DATA, 648baf8532aSAlex Dubov &t_sg); 649ead70773SAlex Dubov (*mrq)->need_card_int = 1; 650baf8532aSAlex Dubov return 0; 651baf8532aSAlex Dubov case MS_TPC_READ_LONG_DATA: 652baf8532aSAlex Dubov case MS_TPC_WRITE_LONG_DATA: 653baf8532aSAlex Dubov msb->current_page++; 654ead70773SAlex Dubov if (msb->caps & MEMSTICK_CAP_AUTO_GET_INT) { 655baf8532aSAlex Dubov t_val = (*mrq)->int_reg; 656baf8532aSAlex Dubov goto has_int_reg; 657baf8532aSAlex Dubov } else { 658baf8532aSAlex Dubov memstick_init_req(*mrq, MS_TPC_GET_INT, NULL, 1); 659baf8532aSAlex Dubov return 0; 660baf8532aSAlex Dubov } 661baf8532aSAlex Dubov 662baf8532aSAlex Dubov default: 663baf8532aSAlex Dubov BUG(); 664baf8532aSAlex Dubov } 665baf8532aSAlex Dubov } 666baf8532aSAlex Dubov 667baf8532aSAlex Dubov /*** Data transfer ***/ 668baf8532aSAlex Dubov 669baf8532aSAlex Dubov static void mspro_block_process_request(struct memstick_dev *card, 670baf8532aSAlex Dubov struct request *req) 671baf8532aSAlex Dubov { 672baf8532aSAlex Dubov struct mspro_block_data *msb = memstick_get_drvdata(card); 673baf8532aSAlex Dubov struct mspro_param_register param; 674baf8532aSAlex Dubov int rc, chunk, cnt; 675baf8532aSAlex Dubov unsigned short page_count; 676baf8532aSAlex Dubov sector_t t_sec; 677baf8532aSAlex Dubov unsigned long flags; 678baf8532aSAlex Dubov 679baf8532aSAlex Dubov do { 680baf8532aSAlex Dubov page_count = 0; 681baf8532aSAlex Dubov msb->current_seg = 0; 682baf8532aSAlex Dubov msb->seg_count = blk_rq_map_sg(req->q, req, msb->req_sg); 683baf8532aSAlex Dubov 684baf8532aSAlex Dubov if (msb->seg_count) { 685baf8532aSAlex Dubov msb->current_page = 0; 686baf8532aSAlex Dubov for (rc = 0; rc < msb->seg_count; rc++) 687baf8532aSAlex Dubov page_count += msb->req_sg[rc].length 688baf8532aSAlex Dubov / msb->page_size; 689baf8532aSAlex Dubov 690baf8532aSAlex Dubov t_sec = req->sector; 691baf8532aSAlex Dubov sector_div(t_sec, msb->page_size >> 9); 692baf8532aSAlex Dubov param.system = msb->system; 693baf8532aSAlex Dubov param.data_count = cpu_to_be16(page_count); 694baf8532aSAlex Dubov param.data_address = cpu_to_be32((uint32_t)t_sec); 695e1f19995SAlex Dubov param.tpc_param = 0; 696baf8532aSAlex Dubov 697baf8532aSAlex Dubov msb->data_dir = rq_data_dir(req); 698baf8532aSAlex Dubov msb->transfer_cmd = msb->data_dir == READ 699baf8532aSAlex Dubov ? MSPRO_CMD_READ_DATA 700baf8532aSAlex Dubov : MSPRO_CMD_WRITE_DATA; 701baf8532aSAlex Dubov 702baf8532aSAlex Dubov dev_dbg(&card->dev, "data transfer: cmd %x, " 703baf8532aSAlex Dubov "lba %x, count %x\n", msb->transfer_cmd, 704baf8532aSAlex Dubov be32_to_cpu(param.data_address), 705baf8532aSAlex Dubov page_count); 706baf8532aSAlex Dubov 707baf8532aSAlex Dubov card->next_request = h_mspro_block_req_init; 708baf8532aSAlex Dubov msb->mrq_handler = h_mspro_block_transfer_data; 709baf8532aSAlex Dubov memstick_init_req(&card->current_mrq, MS_TPC_WRITE_REG, 710baf8532aSAlex Dubov ¶m, sizeof(param)); 711baf8532aSAlex Dubov memstick_new_req(card->host); 712baf8532aSAlex Dubov wait_for_completion(&card->mrq_complete); 713baf8532aSAlex Dubov rc = card->current_mrq.error; 714baf8532aSAlex Dubov 715baf8532aSAlex Dubov if (rc || (card->current_mrq.tpc == MSPRO_CMD_STOP)) { 716baf8532aSAlex Dubov for (cnt = 0; cnt < msb->current_seg; cnt++) 717baf8532aSAlex Dubov page_count += msb->req_sg[cnt].length 718baf8532aSAlex Dubov / msb->page_size; 719baf8532aSAlex Dubov 720baf8532aSAlex Dubov if (msb->current_page) 721baf8532aSAlex Dubov page_count += msb->current_page - 1; 722baf8532aSAlex Dubov 723baf8532aSAlex Dubov if (page_count && (msb->data_dir == READ)) 724baf8532aSAlex Dubov rc = msb->page_size * page_count; 725baf8532aSAlex Dubov else 726baf8532aSAlex Dubov rc = -EIO; 727baf8532aSAlex Dubov } else 728baf8532aSAlex Dubov rc = msb->page_size * page_count; 729baf8532aSAlex Dubov } else 730baf8532aSAlex Dubov rc = -EFAULT; 731baf8532aSAlex Dubov 732baf8532aSAlex Dubov spin_lock_irqsave(&msb->q_lock, flags); 733baf8532aSAlex Dubov if (rc >= 0) 734baf8532aSAlex Dubov chunk = __blk_end_request(req, 0, rc); 735baf8532aSAlex Dubov else 736baf8532aSAlex Dubov chunk = __blk_end_request(req, rc, 0); 737baf8532aSAlex Dubov 738baf8532aSAlex Dubov dev_dbg(&card->dev, "end chunk %d, %d\n", rc, chunk); 739baf8532aSAlex Dubov spin_unlock_irqrestore(&msb->q_lock, flags); 740baf8532aSAlex Dubov } while (chunk); 741baf8532aSAlex Dubov } 742baf8532aSAlex Dubov 743baf8532aSAlex Dubov static int mspro_block_has_request(struct mspro_block_data *msb) 744baf8532aSAlex Dubov { 745baf8532aSAlex Dubov int rc = 0; 746baf8532aSAlex Dubov unsigned long flags; 747baf8532aSAlex Dubov 748baf8532aSAlex Dubov spin_lock_irqsave(&msb->q_lock, flags); 749baf8532aSAlex Dubov if (kthread_should_stop() || msb->has_request) 750baf8532aSAlex Dubov rc = 1; 751baf8532aSAlex Dubov spin_unlock_irqrestore(&msb->q_lock, flags); 752baf8532aSAlex Dubov return rc; 753baf8532aSAlex Dubov } 754baf8532aSAlex Dubov 755baf8532aSAlex Dubov static int mspro_block_queue_thread(void *data) 756baf8532aSAlex Dubov { 757baf8532aSAlex Dubov struct memstick_dev *card = data; 758baf8532aSAlex Dubov struct memstick_host *host = card->host; 759baf8532aSAlex Dubov struct mspro_block_data *msb = memstick_get_drvdata(card); 760baf8532aSAlex Dubov struct request *req; 761baf8532aSAlex Dubov unsigned long flags; 762baf8532aSAlex Dubov 763baf8532aSAlex Dubov while (1) { 764baf8532aSAlex Dubov wait_event(msb->q_wait, mspro_block_has_request(msb)); 765baf8532aSAlex Dubov dev_dbg(&card->dev, "thread iter\n"); 766baf8532aSAlex Dubov 767baf8532aSAlex Dubov spin_lock_irqsave(&msb->q_lock, flags); 768baf8532aSAlex Dubov req = elv_next_request(msb->queue); 769baf8532aSAlex Dubov dev_dbg(&card->dev, "next req %p\n", req); 770baf8532aSAlex Dubov if (!req) { 771baf8532aSAlex Dubov msb->has_request = 0; 772baf8532aSAlex Dubov if (kthread_should_stop()) { 773baf8532aSAlex Dubov spin_unlock_irqrestore(&msb->q_lock, flags); 774baf8532aSAlex Dubov break; 775baf8532aSAlex Dubov } 776baf8532aSAlex Dubov } else 777baf8532aSAlex Dubov msb->has_request = 1; 778baf8532aSAlex Dubov spin_unlock_irqrestore(&msb->q_lock, flags); 779baf8532aSAlex Dubov 780baf8532aSAlex Dubov if (req) { 781baf8532aSAlex Dubov mutex_lock(&host->lock); 782baf8532aSAlex Dubov mspro_block_process_request(card, req); 783baf8532aSAlex Dubov mutex_unlock(&host->lock); 784baf8532aSAlex Dubov } 785baf8532aSAlex Dubov } 786baf8532aSAlex Dubov dev_dbg(&card->dev, "thread finished\n"); 787baf8532aSAlex Dubov return 0; 788baf8532aSAlex Dubov } 789baf8532aSAlex Dubov 790baf8532aSAlex Dubov static void mspro_block_request(struct request_queue *q) 791baf8532aSAlex Dubov { 792baf8532aSAlex Dubov struct memstick_dev *card = q->queuedata; 793baf8532aSAlex Dubov struct mspro_block_data *msb = memstick_get_drvdata(card); 794baf8532aSAlex Dubov struct request *req = NULL; 795baf8532aSAlex Dubov 796baf8532aSAlex Dubov if (msb->q_thread) { 797baf8532aSAlex Dubov msb->has_request = 1; 798baf8532aSAlex Dubov wake_up_all(&msb->q_wait); 799baf8532aSAlex Dubov } else { 800baf8532aSAlex Dubov while ((req = elv_next_request(q)) != NULL) 801baf8532aSAlex Dubov end_queued_request(req, -ENODEV); 802baf8532aSAlex Dubov } 803baf8532aSAlex Dubov } 804baf8532aSAlex Dubov 805baf8532aSAlex Dubov /*** Initialization ***/ 806baf8532aSAlex Dubov 807baf8532aSAlex Dubov static int mspro_block_wait_for_ced(struct memstick_dev *card) 808baf8532aSAlex Dubov { 809baf8532aSAlex Dubov struct mspro_block_data *msb = memstick_get_drvdata(card); 810baf8532aSAlex Dubov 811baf8532aSAlex Dubov card->next_request = h_mspro_block_req_init; 812baf8532aSAlex Dubov msb->mrq_handler = h_mspro_block_wait_for_ced; 813baf8532aSAlex Dubov memstick_init_req(&card->current_mrq, MS_TPC_GET_INT, NULL, 1); 814baf8532aSAlex Dubov memstick_new_req(card->host); 815baf8532aSAlex Dubov wait_for_completion(&card->mrq_complete); 816baf8532aSAlex Dubov return card->current_mrq.error; 817baf8532aSAlex Dubov } 818baf8532aSAlex Dubov 819baf8532aSAlex Dubov static int mspro_block_switch_to_parallel(struct memstick_dev *card) 820baf8532aSAlex Dubov { 821baf8532aSAlex Dubov struct memstick_host *host = card->host; 822baf8532aSAlex Dubov struct mspro_block_data *msb = memstick_get_drvdata(card); 823baf8532aSAlex Dubov struct mspro_param_register param = { 82459367258SAlex Dubov .system = MEMSTICK_SYS_PAR4, 825baf8532aSAlex Dubov .data_count = 0, 826baf8532aSAlex Dubov .data_address = 0, 827e1f19995SAlex Dubov .tpc_param = 0 828baf8532aSAlex Dubov }; 829baf8532aSAlex Dubov 830baf8532aSAlex Dubov card->next_request = h_mspro_block_req_init; 831baf8532aSAlex Dubov msb->mrq_handler = h_mspro_block_default; 832baf8532aSAlex Dubov memstick_init_req(&card->current_mrq, MS_TPC_WRITE_REG, ¶m, 833baf8532aSAlex Dubov sizeof(param)); 834baf8532aSAlex Dubov memstick_new_req(host); 835baf8532aSAlex Dubov wait_for_completion(&card->mrq_complete); 836baf8532aSAlex Dubov if (card->current_mrq.error) 837baf8532aSAlex Dubov return card->current_mrq.error; 838baf8532aSAlex Dubov 839e1f19995SAlex Dubov msb->system = MEMSTICK_SYS_PAR4; 840e1f19995SAlex Dubov host->set_param(host, MEMSTICK_INTERFACE, MEMSTICK_PAR4); 841baf8532aSAlex Dubov 842baf8532aSAlex Dubov card->next_request = h_mspro_block_req_init; 843baf8532aSAlex Dubov msb->mrq_handler = h_mspro_block_default; 844baf8532aSAlex Dubov memstick_init_req(&card->current_mrq, MS_TPC_GET_INT, NULL, 1); 845baf8532aSAlex Dubov memstick_new_req(card->host); 846baf8532aSAlex Dubov wait_for_completion(&card->mrq_complete); 847baf8532aSAlex Dubov 848baf8532aSAlex Dubov if (card->current_mrq.error) { 84959367258SAlex Dubov msb->system = MEMSTICK_SYS_SERIAL; 85059367258SAlex Dubov host->set_param(host, MEMSTICK_POWER, MEMSTICK_POWER_OFF); 85159367258SAlex Dubov msleep(1000); 85259367258SAlex Dubov host->set_param(host, MEMSTICK_POWER, MEMSTICK_POWER_ON); 853baf8532aSAlex Dubov host->set_param(host, MEMSTICK_INTERFACE, MEMSTICK_SERIAL); 85459367258SAlex Dubov 85559367258SAlex Dubov if (memstick_set_rw_addr(card)) 85659367258SAlex Dubov return card->current_mrq.error; 85759367258SAlex Dubov 85859367258SAlex Dubov param.system = msb->system; 85959367258SAlex Dubov 86059367258SAlex Dubov card->next_request = h_mspro_block_req_init; 86159367258SAlex Dubov msb->mrq_handler = h_mspro_block_default; 86259367258SAlex Dubov memstick_init_req(&card->current_mrq, MS_TPC_WRITE_REG, ¶m, 86359367258SAlex Dubov sizeof(param)); 86459367258SAlex Dubov memstick_new_req(host); 86559367258SAlex Dubov wait_for_completion(&card->mrq_complete); 86659367258SAlex Dubov 867baf8532aSAlex Dubov return -EFAULT; 868baf8532aSAlex Dubov } 869baf8532aSAlex Dubov 870baf8532aSAlex Dubov return 0; 871baf8532aSAlex Dubov } 872baf8532aSAlex Dubov 873baf8532aSAlex Dubov /* Memory allocated for attributes by this function should be freed by 874baf8532aSAlex Dubov * mspro_block_data_clear, no matter if the initialization process succeded 875baf8532aSAlex Dubov * or failed. 876baf8532aSAlex Dubov */ 877baf8532aSAlex Dubov static int mspro_block_read_attributes(struct memstick_dev *card) 878baf8532aSAlex Dubov { 879baf8532aSAlex Dubov struct mspro_block_data *msb = memstick_get_drvdata(card); 880baf8532aSAlex Dubov struct mspro_param_register param = { 881baf8532aSAlex Dubov .system = msb->system, 882baf8532aSAlex Dubov .data_count = cpu_to_be16(1), 883baf8532aSAlex Dubov .data_address = 0, 884e1f19995SAlex Dubov .tpc_param = 0 885baf8532aSAlex Dubov }; 886baf8532aSAlex Dubov struct mspro_attribute *attr = NULL; 887baf8532aSAlex Dubov struct mspro_sys_attr *s_attr = NULL; 888baf8532aSAlex Dubov unsigned char *buffer = NULL; 889baf8532aSAlex Dubov int cnt, rc, attr_count; 890baf8532aSAlex Dubov unsigned int addr; 891baf8532aSAlex Dubov unsigned short page_count; 892baf8532aSAlex Dubov 893baf8532aSAlex Dubov attr = kmalloc(msb->page_size, GFP_KERNEL); 894baf8532aSAlex Dubov if (!attr) 895baf8532aSAlex Dubov return -ENOMEM; 896baf8532aSAlex Dubov 897baf8532aSAlex Dubov sg_init_one(&msb->req_sg[0], attr, msb->page_size); 898baf8532aSAlex Dubov msb->seg_count = 1; 899baf8532aSAlex Dubov msb->current_seg = 0; 900baf8532aSAlex Dubov msb->current_page = 0; 901baf8532aSAlex Dubov msb->data_dir = READ; 902baf8532aSAlex Dubov msb->transfer_cmd = MSPRO_CMD_READ_ATRB; 903baf8532aSAlex Dubov 904baf8532aSAlex Dubov card->next_request = h_mspro_block_req_init; 905baf8532aSAlex Dubov msb->mrq_handler = h_mspro_block_transfer_data; 906baf8532aSAlex Dubov memstick_init_req(&card->current_mrq, MS_TPC_WRITE_REG, ¶m, 907baf8532aSAlex Dubov sizeof(param)); 908baf8532aSAlex Dubov memstick_new_req(card->host); 909baf8532aSAlex Dubov wait_for_completion(&card->mrq_complete); 910baf8532aSAlex Dubov if (card->current_mrq.error) { 911baf8532aSAlex Dubov rc = card->current_mrq.error; 912baf8532aSAlex Dubov goto out_free_attr; 913baf8532aSAlex Dubov } 914baf8532aSAlex Dubov 915baf8532aSAlex Dubov if (be16_to_cpu(attr->signature) != MSPRO_BLOCK_SIGNATURE) { 916baf8532aSAlex Dubov printk(KERN_ERR "%s: unrecognized device signature %x\n", 917baf8532aSAlex Dubov card->dev.bus_id, be16_to_cpu(attr->signature)); 918baf8532aSAlex Dubov rc = -ENODEV; 919baf8532aSAlex Dubov goto out_free_attr; 920baf8532aSAlex Dubov } 921baf8532aSAlex Dubov 922baf8532aSAlex Dubov if (attr->count > MSPRO_BLOCK_MAX_ATTRIBUTES) { 923baf8532aSAlex Dubov printk(KERN_WARNING "%s: way too many attribute entries\n", 924baf8532aSAlex Dubov card->dev.bus_id); 925baf8532aSAlex Dubov attr_count = MSPRO_BLOCK_MAX_ATTRIBUTES; 926baf8532aSAlex Dubov } else 927baf8532aSAlex Dubov attr_count = attr->count; 928baf8532aSAlex Dubov 929baf8532aSAlex Dubov msb->attr_group.attrs = kzalloc((attr_count + 1) 930baf8532aSAlex Dubov * sizeof(struct attribute), 931baf8532aSAlex Dubov GFP_KERNEL); 932baf8532aSAlex Dubov if (!msb->attr_group.attrs) { 933baf8532aSAlex Dubov rc = -ENOMEM; 934baf8532aSAlex Dubov goto out_free_attr; 935baf8532aSAlex Dubov } 936baf8532aSAlex Dubov msb->attr_group.name = "media_attributes"; 937baf8532aSAlex Dubov 938baf8532aSAlex Dubov buffer = kmalloc(msb->page_size, GFP_KERNEL); 939baf8532aSAlex Dubov if (!buffer) { 940baf8532aSAlex Dubov rc = -ENOMEM; 941baf8532aSAlex Dubov goto out_free_attr; 942baf8532aSAlex Dubov } 943baf8532aSAlex Dubov memcpy(buffer, (char *)attr, msb->page_size); 944baf8532aSAlex Dubov page_count = 1; 945baf8532aSAlex Dubov 946baf8532aSAlex Dubov for (cnt = 0; cnt < attr_count; ++cnt) { 947baf8532aSAlex Dubov s_attr = kzalloc(sizeof(struct mspro_sys_attr), GFP_KERNEL); 948baf8532aSAlex Dubov if (!s_attr) { 949baf8532aSAlex Dubov rc = -ENOMEM; 950baf8532aSAlex Dubov goto out_free_buffer; 951baf8532aSAlex Dubov } 952baf8532aSAlex Dubov 953baf8532aSAlex Dubov msb->attr_group.attrs[cnt] = &s_attr->dev_attr.attr; 954baf8532aSAlex Dubov addr = be32_to_cpu(attr->entries[cnt].address); 955baf8532aSAlex Dubov rc = be32_to_cpu(attr->entries[cnt].size); 956baf8532aSAlex Dubov dev_dbg(&card->dev, "adding attribute %d: id %x, address %x, " 957baf8532aSAlex Dubov "size %x\n", cnt, attr->entries[cnt].id, addr, rc); 958baf8532aSAlex Dubov s_attr->id = attr->entries[cnt].id; 959baf8532aSAlex Dubov if (mspro_block_attr_name(s_attr->id)) 960baf8532aSAlex Dubov snprintf(s_attr->name, sizeof(s_attr->name), "%s", 961baf8532aSAlex Dubov mspro_block_attr_name(attr->entries[cnt].id)); 962baf8532aSAlex Dubov else 963baf8532aSAlex Dubov snprintf(s_attr->name, sizeof(s_attr->name), 964baf8532aSAlex Dubov "attr_x%02x", attr->entries[cnt].id); 965baf8532aSAlex Dubov 966baf8532aSAlex Dubov s_attr->dev_attr.attr.name = s_attr->name; 967baf8532aSAlex Dubov s_attr->dev_attr.attr.mode = S_IRUGO; 968baf8532aSAlex Dubov s_attr->dev_attr.attr.owner = THIS_MODULE; 969baf8532aSAlex Dubov s_attr->dev_attr.show = mspro_block_attr_show(s_attr->id); 970baf8532aSAlex Dubov 971baf8532aSAlex Dubov if (!rc) 972baf8532aSAlex Dubov continue; 973baf8532aSAlex Dubov 974baf8532aSAlex Dubov s_attr->size = rc; 975baf8532aSAlex Dubov s_attr->data = kmalloc(rc, GFP_KERNEL); 976baf8532aSAlex Dubov if (!s_attr->data) { 977baf8532aSAlex Dubov rc = -ENOMEM; 978baf8532aSAlex Dubov goto out_free_buffer; 979baf8532aSAlex Dubov } 980baf8532aSAlex Dubov 981baf8532aSAlex Dubov if (((addr / msb->page_size) 982baf8532aSAlex Dubov == be32_to_cpu(param.data_address)) 983baf8532aSAlex Dubov && (((addr + rc - 1) / msb->page_size) 984baf8532aSAlex Dubov == be32_to_cpu(param.data_address))) { 985baf8532aSAlex Dubov memcpy(s_attr->data, buffer + addr % msb->page_size, 986baf8532aSAlex Dubov rc); 987baf8532aSAlex Dubov continue; 988baf8532aSAlex Dubov } 989baf8532aSAlex Dubov 990baf8532aSAlex Dubov if (page_count <= (rc / msb->page_size)) { 991baf8532aSAlex Dubov kfree(buffer); 992baf8532aSAlex Dubov page_count = (rc / msb->page_size) + 1; 993baf8532aSAlex Dubov buffer = kmalloc(page_count * msb->page_size, 994baf8532aSAlex Dubov GFP_KERNEL); 995baf8532aSAlex Dubov if (!buffer) { 996baf8532aSAlex Dubov rc = -ENOMEM; 997baf8532aSAlex Dubov goto out_free_attr; 998baf8532aSAlex Dubov } 999baf8532aSAlex Dubov } 1000baf8532aSAlex Dubov 1001baf8532aSAlex Dubov param.system = msb->system; 1002baf8532aSAlex Dubov param.data_count = cpu_to_be16((rc / msb->page_size) + 1); 1003baf8532aSAlex Dubov param.data_address = cpu_to_be32(addr / msb->page_size); 1004e1f19995SAlex Dubov param.tpc_param = 0; 1005baf8532aSAlex Dubov 1006baf8532aSAlex Dubov sg_init_one(&msb->req_sg[0], buffer, 1007baf8532aSAlex Dubov be16_to_cpu(param.data_count) * msb->page_size); 1008baf8532aSAlex Dubov msb->seg_count = 1; 1009baf8532aSAlex Dubov msb->current_seg = 0; 1010baf8532aSAlex Dubov msb->current_page = 0; 1011baf8532aSAlex Dubov msb->data_dir = READ; 1012baf8532aSAlex Dubov msb->transfer_cmd = MSPRO_CMD_READ_ATRB; 1013baf8532aSAlex Dubov 1014baf8532aSAlex Dubov dev_dbg(&card->dev, "reading attribute pages %x, %x\n", 1015baf8532aSAlex Dubov be32_to_cpu(param.data_address), 1016baf8532aSAlex Dubov be16_to_cpu(param.data_count)); 1017baf8532aSAlex Dubov 1018baf8532aSAlex Dubov card->next_request = h_mspro_block_req_init; 1019baf8532aSAlex Dubov msb->mrq_handler = h_mspro_block_transfer_data; 1020baf8532aSAlex Dubov memstick_init_req(&card->current_mrq, MS_TPC_WRITE_REG, 1021baf8532aSAlex Dubov (char *)¶m, sizeof(param)); 1022baf8532aSAlex Dubov memstick_new_req(card->host); 1023baf8532aSAlex Dubov wait_for_completion(&card->mrq_complete); 1024baf8532aSAlex Dubov if (card->current_mrq.error) { 1025baf8532aSAlex Dubov rc = card->current_mrq.error; 1026baf8532aSAlex Dubov goto out_free_buffer; 1027baf8532aSAlex Dubov } 1028baf8532aSAlex Dubov 1029baf8532aSAlex Dubov memcpy(s_attr->data, buffer + addr % msb->page_size, rc); 1030baf8532aSAlex Dubov } 1031baf8532aSAlex Dubov 1032baf8532aSAlex Dubov rc = 0; 1033baf8532aSAlex Dubov out_free_buffer: 1034baf8532aSAlex Dubov kfree(buffer); 1035baf8532aSAlex Dubov out_free_attr: 1036baf8532aSAlex Dubov kfree(attr); 1037baf8532aSAlex Dubov return rc; 1038baf8532aSAlex Dubov } 1039baf8532aSAlex Dubov 1040baf8532aSAlex Dubov static int mspro_block_init_card(struct memstick_dev *card) 1041baf8532aSAlex Dubov { 1042baf8532aSAlex Dubov struct mspro_block_data *msb = memstick_get_drvdata(card); 1043baf8532aSAlex Dubov struct memstick_host *host = card->host; 1044baf8532aSAlex Dubov int rc = 0; 1045baf8532aSAlex Dubov 1046e1f19995SAlex Dubov msb->system = MEMSTICK_SYS_SERIAL; 1047baf8532aSAlex Dubov card->reg_addr.r_offset = offsetof(struct mspro_register, status); 1048baf8532aSAlex Dubov card->reg_addr.r_length = sizeof(struct ms_status_register); 1049baf8532aSAlex Dubov card->reg_addr.w_offset = offsetof(struct mspro_register, param); 1050baf8532aSAlex Dubov card->reg_addr.w_length = sizeof(struct mspro_param_register); 1051baf8532aSAlex Dubov 1052baf8532aSAlex Dubov if (memstick_set_rw_addr(card)) 1053baf8532aSAlex Dubov return -EIO; 1054baf8532aSAlex Dubov 1055ead70773SAlex Dubov msb->caps = host->caps; 1056ead70773SAlex Dubov if (msb->caps & MEMSTICK_CAP_PAR4) { 1057baf8532aSAlex Dubov if (mspro_block_switch_to_parallel(card)) 1058baf8532aSAlex Dubov printk(KERN_WARNING "%s: could not switch to " 1059baf8532aSAlex Dubov "parallel interface\n", card->dev.bus_id); 1060baf8532aSAlex Dubov } 1061baf8532aSAlex Dubov 1062baf8532aSAlex Dubov rc = mspro_block_wait_for_ced(card); 1063baf8532aSAlex Dubov if (rc) 1064baf8532aSAlex Dubov return rc; 1065baf8532aSAlex Dubov dev_dbg(&card->dev, "card activated\n"); 1066ead70773SAlex Dubov if (msb->system != MEMSTICK_SYS_SERIAL) 1067ead70773SAlex Dubov msb->caps |= MEMSTICK_CAP_AUTO_GET_INT; 1068baf8532aSAlex Dubov 1069baf8532aSAlex Dubov card->next_request = h_mspro_block_req_init; 1070baf8532aSAlex Dubov msb->mrq_handler = h_mspro_block_get_ro; 1071baf8532aSAlex Dubov memstick_init_req(&card->current_mrq, MS_TPC_READ_REG, NULL, 1072baf8532aSAlex Dubov sizeof(struct ms_status_register)); 1073baf8532aSAlex Dubov memstick_new_req(card->host); 1074baf8532aSAlex Dubov wait_for_completion(&card->mrq_complete); 1075baf8532aSAlex Dubov if (card->current_mrq.error) 1076baf8532aSAlex Dubov return card->current_mrq.error; 1077baf8532aSAlex Dubov 1078baf8532aSAlex Dubov dev_dbg(&card->dev, "card r/w status %d\n", msb->read_only ? 0 : 1); 1079baf8532aSAlex Dubov 1080baf8532aSAlex Dubov msb->page_size = 512; 1081baf8532aSAlex Dubov rc = mspro_block_read_attributes(card); 1082baf8532aSAlex Dubov if (rc) 1083baf8532aSAlex Dubov return rc; 1084baf8532aSAlex Dubov 1085baf8532aSAlex Dubov dev_dbg(&card->dev, "attributes loaded\n"); 1086baf8532aSAlex Dubov return 0; 1087baf8532aSAlex Dubov 1088baf8532aSAlex Dubov } 1089baf8532aSAlex Dubov 1090baf8532aSAlex Dubov static int mspro_block_init_disk(struct memstick_dev *card) 1091baf8532aSAlex Dubov { 1092baf8532aSAlex Dubov struct mspro_block_data *msb = memstick_get_drvdata(card); 1093baf8532aSAlex Dubov struct memstick_host *host = card->host; 1094baf8532aSAlex Dubov struct mspro_devinfo *dev_info = NULL; 1095baf8532aSAlex Dubov struct mspro_sys_info *sys_info = NULL; 1096baf8532aSAlex Dubov struct mspro_sys_attr *s_attr = NULL; 1097baf8532aSAlex Dubov int rc, disk_id; 1098baf8532aSAlex Dubov u64 limit = BLK_BOUNCE_HIGH; 1099baf8532aSAlex Dubov unsigned long capacity; 1100baf8532aSAlex Dubov 1101baf8532aSAlex Dubov if (host->cdev.dev->dma_mask && *(host->cdev.dev->dma_mask)) 1102baf8532aSAlex Dubov limit = *(host->cdev.dev->dma_mask); 1103baf8532aSAlex Dubov 1104baf8532aSAlex Dubov for (rc = 0; msb->attr_group.attrs[rc]; ++rc) { 1105baf8532aSAlex Dubov s_attr = mspro_from_sysfs_attr(msb->attr_group.attrs[rc]); 1106baf8532aSAlex Dubov 1107baf8532aSAlex Dubov if (s_attr->id == MSPRO_BLOCK_ID_DEVINFO) 1108baf8532aSAlex Dubov dev_info = s_attr->data; 1109baf8532aSAlex Dubov else if (s_attr->id == MSPRO_BLOCK_ID_SYSINFO) 1110baf8532aSAlex Dubov sys_info = s_attr->data; 1111baf8532aSAlex Dubov } 1112baf8532aSAlex Dubov 1113baf8532aSAlex Dubov if (!dev_info || !sys_info) 1114baf8532aSAlex Dubov return -ENODEV; 1115baf8532aSAlex Dubov 1116baf8532aSAlex Dubov msb->cylinders = be16_to_cpu(dev_info->cylinders); 1117baf8532aSAlex Dubov msb->heads = be16_to_cpu(dev_info->heads); 1118baf8532aSAlex Dubov msb->sectors_per_track = be16_to_cpu(dev_info->sectors_per_track); 1119baf8532aSAlex Dubov 1120baf8532aSAlex Dubov msb->page_size = be16_to_cpu(sys_info->unit_size); 1121baf8532aSAlex Dubov 1122baf8532aSAlex Dubov if (!idr_pre_get(&mspro_block_disk_idr, GFP_KERNEL)) 1123baf8532aSAlex Dubov return -ENOMEM; 1124baf8532aSAlex Dubov 1125baf8532aSAlex Dubov mutex_lock(&mspro_block_disk_lock); 1126baf8532aSAlex Dubov rc = idr_get_new(&mspro_block_disk_idr, card, &disk_id); 1127baf8532aSAlex Dubov mutex_unlock(&mspro_block_disk_lock); 1128baf8532aSAlex Dubov 1129baf8532aSAlex Dubov if (rc) 1130baf8532aSAlex Dubov return rc; 1131baf8532aSAlex Dubov 1132baf8532aSAlex Dubov if ((disk_id << MEMSTICK_PART_SHIFT) > 255) { 1133baf8532aSAlex Dubov rc = -ENOSPC; 1134baf8532aSAlex Dubov goto out_release_id; 1135baf8532aSAlex Dubov } 1136baf8532aSAlex Dubov 1137baf8532aSAlex Dubov msb->disk = alloc_disk(1 << MEMSTICK_PART_SHIFT); 1138baf8532aSAlex Dubov if (!msb->disk) { 1139baf8532aSAlex Dubov rc = -ENOMEM; 1140baf8532aSAlex Dubov goto out_release_id; 1141baf8532aSAlex Dubov } 1142baf8532aSAlex Dubov 1143baf8532aSAlex Dubov spin_lock_init(&msb->q_lock); 1144baf8532aSAlex Dubov init_waitqueue_head(&msb->q_wait); 1145baf8532aSAlex Dubov 1146baf8532aSAlex Dubov msb->queue = blk_init_queue(mspro_block_request, &msb->q_lock); 1147baf8532aSAlex Dubov if (!msb->queue) { 1148baf8532aSAlex Dubov rc = -ENOMEM; 1149baf8532aSAlex Dubov goto out_put_disk; 1150baf8532aSAlex Dubov } 1151baf8532aSAlex Dubov 1152baf8532aSAlex Dubov msb->queue->queuedata = card; 1153baf8532aSAlex Dubov 1154baf8532aSAlex Dubov blk_queue_bounce_limit(msb->queue, limit); 1155baf8532aSAlex Dubov blk_queue_max_sectors(msb->queue, MSPRO_BLOCK_MAX_PAGES); 1156baf8532aSAlex Dubov blk_queue_max_phys_segments(msb->queue, MSPRO_BLOCK_MAX_SEGS); 1157baf8532aSAlex Dubov blk_queue_max_hw_segments(msb->queue, MSPRO_BLOCK_MAX_SEGS); 1158baf8532aSAlex Dubov blk_queue_max_segment_size(msb->queue, 1159baf8532aSAlex Dubov MSPRO_BLOCK_MAX_PAGES * msb->page_size); 1160baf8532aSAlex Dubov 1161baf8532aSAlex Dubov msb->disk->major = major; 1162baf8532aSAlex Dubov msb->disk->first_minor = disk_id << MEMSTICK_PART_SHIFT; 1163baf8532aSAlex Dubov msb->disk->fops = &ms_block_bdops; 1164baf8532aSAlex Dubov msb->usage_count = 1; 1165baf8532aSAlex Dubov msb->disk->private_data = msb; 1166baf8532aSAlex Dubov msb->disk->queue = msb->queue; 1167baf8532aSAlex Dubov msb->disk->driverfs_dev = &card->dev; 1168baf8532aSAlex Dubov 1169baf8532aSAlex Dubov sprintf(msb->disk->disk_name, "mspblk%d", disk_id); 1170baf8532aSAlex Dubov 1171baf8532aSAlex Dubov blk_queue_hardsect_size(msb->queue, msb->page_size); 1172baf8532aSAlex Dubov 1173baf8532aSAlex Dubov capacity = be16_to_cpu(sys_info->user_block_count); 1174baf8532aSAlex Dubov capacity *= be16_to_cpu(sys_info->block_size); 1175baf8532aSAlex Dubov capacity *= msb->page_size >> 9; 1176baf8532aSAlex Dubov set_capacity(msb->disk, capacity); 1177baf8532aSAlex Dubov dev_dbg(&card->dev, "capacity set %ld\n", capacity); 1178baf8532aSAlex Dubov msb->q_thread = kthread_run(mspro_block_queue_thread, card, 1179baf8532aSAlex Dubov DRIVER_NAME"d"); 1180baf8532aSAlex Dubov if (IS_ERR(msb->q_thread)) 1181baf8532aSAlex Dubov goto out_put_disk; 1182baf8532aSAlex Dubov 1183baf8532aSAlex Dubov mutex_unlock(&host->lock); 1184baf8532aSAlex Dubov add_disk(msb->disk); 1185baf8532aSAlex Dubov mutex_lock(&host->lock); 1186baf8532aSAlex Dubov msb->active = 1; 1187baf8532aSAlex Dubov return 0; 1188baf8532aSAlex Dubov 1189baf8532aSAlex Dubov out_put_disk: 1190baf8532aSAlex Dubov put_disk(msb->disk); 1191baf8532aSAlex Dubov out_release_id: 1192baf8532aSAlex Dubov mutex_lock(&mspro_block_disk_lock); 1193baf8532aSAlex Dubov idr_remove(&mspro_block_disk_idr, disk_id); 1194baf8532aSAlex Dubov mutex_unlock(&mspro_block_disk_lock); 1195baf8532aSAlex Dubov return rc; 1196baf8532aSAlex Dubov } 1197baf8532aSAlex Dubov 1198baf8532aSAlex Dubov static void mspro_block_data_clear(struct mspro_block_data *msb) 1199baf8532aSAlex Dubov { 1200baf8532aSAlex Dubov int cnt; 1201baf8532aSAlex Dubov struct mspro_sys_attr *s_attr; 1202baf8532aSAlex Dubov 1203baf8532aSAlex Dubov if (msb->attr_group.attrs) { 1204baf8532aSAlex Dubov for (cnt = 0; msb->attr_group.attrs[cnt]; ++cnt) { 1205baf8532aSAlex Dubov s_attr = mspro_from_sysfs_attr(msb->attr_group 1206baf8532aSAlex Dubov .attrs[cnt]); 1207baf8532aSAlex Dubov kfree(s_attr->data); 1208baf8532aSAlex Dubov kfree(s_attr); 1209baf8532aSAlex Dubov } 1210baf8532aSAlex Dubov kfree(msb->attr_group.attrs); 1211baf8532aSAlex Dubov } 1212baf8532aSAlex Dubov 1213baf8532aSAlex Dubov msb->card = NULL; 1214baf8532aSAlex Dubov } 1215baf8532aSAlex Dubov 1216baf8532aSAlex Dubov static int mspro_block_check_card(struct memstick_dev *card) 1217baf8532aSAlex Dubov { 1218baf8532aSAlex Dubov struct mspro_block_data *msb = memstick_get_drvdata(card); 1219baf8532aSAlex Dubov 1220baf8532aSAlex Dubov return (msb->active == 1); 1221baf8532aSAlex Dubov } 1222baf8532aSAlex Dubov 1223baf8532aSAlex Dubov static int mspro_block_probe(struct memstick_dev *card) 1224baf8532aSAlex Dubov { 1225baf8532aSAlex Dubov struct mspro_block_data *msb; 1226baf8532aSAlex Dubov int rc = 0; 1227baf8532aSAlex Dubov 1228baf8532aSAlex Dubov msb = kzalloc(sizeof(struct mspro_block_data), GFP_KERNEL); 1229baf8532aSAlex Dubov if (!msb) 1230baf8532aSAlex Dubov return -ENOMEM; 1231baf8532aSAlex Dubov memstick_set_drvdata(card, msb); 1232baf8532aSAlex Dubov msb->card = card; 1233baf8532aSAlex Dubov 1234baf8532aSAlex Dubov rc = mspro_block_init_card(card); 1235baf8532aSAlex Dubov 1236baf8532aSAlex Dubov if (rc) 1237baf8532aSAlex Dubov goto out_free; 1238baf8532aSAlex Dubov 1239baf8532aSAlex Dubov rc = sysfs_create_group(&card->dev.kobj, &msb->attr_group); 1240baf8532aSAlex Dubov if (rc) 1241baf8532aSAlex Dubov goto out_free; 1242baf8532aSAlex Dubov 1243baf8532aSAlex Dubov rc = mspro_block_init_disk(card); 1244baf8532aSAlex Dubov if (!rc) { 1245baf8532aSAlex Dubov card->check = mspro_block_check_card; 1246baf8532aSAlex Dubov return 0; 1247baf8532aSAlex Dubov } 1248baf8532aSAlex Dubov 1249baf8532aSAlex Dubov sysfs_remove_group(&card->dev.kobj, &msb->attr_group); 1250baf8532aSAlex Dubov out_free: 1251baf8532aSAlex Dubov memstick_set_drvdata(card, NULL); 1252baf8532aSAlex Dubov mspro_block_data_clear(msb); 1253baf8532aSAlex Dubov kfree(msb); 1254baf8532aSAlex Dubov return rc; 1255baf8532aSAlex Dubov } 1256baf8532aSAlex Dubov 1257baf8532aSAlex Dubov static void mspro_block_remove(struct memstick_dev *card) 1258baf8532aSAlex Dubov { 1259baf8532aSAlex Dubov struct mspro_block_data *msb = memstick_get_drvdata(card); 1260baf8532aSAlex Dubov struct task_struct *q_thread = NULL; 1261baf8532aSAlex Dubov unsigned long flags; 1262baf8532aSAlex Dubov 1263baf8532aSAlex Dubov del_gendisk(msb->disk); 1264baf8532aSAlex Dubov dev_dbg(&card->dev, "mspro block remove\n"); 1265baf8532aSAlex Dubov spin_lock_irqsave(&msb->q_lock, flags); 1266baf8532aSAlex Dubov q_thread = msb->q_thread; 1267baf8532aSAlex Dubov msb->q_thread = NULL; 1268baf8532aSAlex Dubov msb->active = 0; 1269baf8532aSAlex Dubov spin_unlock_irqrestore(&msb->q_lock, flags); 1270baf8532aSAlex Dubov 1271baf8532aSAlex Dubov if (q_thread) { 1272baf8532aSAlex Dubov mutex_unlock(&card->host->lock); 1273baf8532aSAlex Dubov kthread_stop(q_thread); 1274baf8532aSAlex Dubov mutex_lock(&card->host->lock); 1275baf8532aSAlex Dubov } 1276baf8532aSAlex Dubov 1277baf8532aSAlex Dubov dev_dbg(&card->dev, "queue thread stopped\n"); 1278baf8532aSAlex Dubov 1279baf8532aSAlex Dubov blk_cleanup_queue(msb->queue); 1280baf8532aSAlex Dubov 1281baf8532aSAlex Dubov sysfs_remove_group(&card->dev.kobj, &msb->attr_group); 1282baf8532aSAlex Dubov 1283baf8532aSAlex Dubov mutex_lock(&mspro_block_disk_lock); 1284baf8532aSAlex Dubov mspro_block_data_clear(msb); 1285baf8532aSAlex Dubov mutex_unlock(&mspro_block_disk_lock); 1286baf8532aSAlex Dubov 1287baf8532aSAlex Dubov mspro_block_disk_release(msb->disk); 1288baf8532aSAlex Dubov memstick_set_drvdata(card, NULL); 1289baf8532aSAlex Dubov } 1290baf8532aSAlex Dubov 1291baf8532aSAlex Dubov #ifdef CONFIG_PM 1292baf8532aSAlex Dubov 1293baf8532aSAlex Dubov static int mspro_block_suspend(struct memstick_dev *card, pm_message_t state) 1294baf8532aSAlex Dubov { 1295baf8532aSAlex Dubov struct mspro_block_data *msb = memstick_get_drvdata(card); 1296baf8532aSAlex Dubov struct task_struct *q_thread = NULL; 1297baf8532aSAlex Dubov unsigned long flags; 1298baf8532aSAlex Dubov 1299baf8532aSAlex Dubov spin_lock_irqsave(&msb->q_lock, flags); 1300baf8532aSAlex Dubov q_thread = msb->q_thread; 1301baf8532aSAlex Dubov msb->q_thread = NULL; 1302baf8532aSAlex Dubov msb->active = 0; 1303baf8532aSAlex Dubov blk_stop_queue(msb->queue); 1304baf8532aSAlex Dubov spin_unlock_irqrestore(&msb->q_lock, flags); 1305baf8532aSAlex Dubov 1306baf8532aSAlex Dubov if (q_thread) 1307baf8532aSAlex Dubov kthread_stop(q_thread); 1308baf8532aSAlex Dubov 1309baf8532aSAlex Dubov return 0; 1310baf8532aSAlex Dubov } 1311baf8532aSAlex Dubov 1312baf8532aSAlex Dubov static int mspro_block_resume(struct memstick_dev *card) 1313baf8532aSAlex Dubov { 1314baf8532aSAlex Dubov struct mspro_block_data *msb = memstick_get_drvdata(card); 1315baf8532aSAlex Dubov unsigned long flags; 1316baf8532aSAlex Dubov int rc = 0; 1317baf8532aSAlex Dubov 1318baf8532aSAlex Dubov #ifdef CONFIG_MEMSTICK_UNSAFE_RESUME 1319baf8532aSAlex Dubov 1320baf8532aSAlex Dubov struct mspro_block_data *new_msb; 1321baf8532aSAlex Dubov struct memstick_host *host = card->host; 1322baf8532aSAlex Dubov struct mspro_sys_attr *s_attr, *r_attr; 1323baf8532aSAlex Dubov unsigned char cnt; 1324baf8532aSAlex Dubov 1325baf8532aSAlex Dubov mutex_lock(&host->lock); 1326baf8532aSAlex Dubov new_msb = kzalloc(sizeof(struct mspro_block_data), GFP_KERNEL); 1327baf8532aSAlex Dubov if (!new_msb) { 1328baf8532aSAlex Dubov rc = -ENOMEM; 1329baf8532aSAlex Dubov goto out_unlock; 1330baf8532aSAlex Dubov } 1331baf8532aSAlex Dubov 1332baf8532aSAlex Dubov new_msb->card = card; 1333baf8532aSAlex Dubov memstick_set_drvdata(card, new_msb); 1334baf8532aSAlex Dubov if (mspro_block_init_card(card)) 1335baf8532aSAlex Dubov goto out_free; 1336baf8532aSAlex Dubov 1337baf8532aSAlex Dubov for (cnt = 0; new_msb->attr_group.attrs[cnt] 1338baf8532aSAlex Dubov && msb->attr_group.attrs[cnt]; ++cnt) { 1339baf8532aSAlex Dubov s_attr = mspro_from_sysfs_attr(new_msb->attr_group.attrs[cnt]); 1340baf8532aSAlex Dubov r_attr = mspro_from_sysfs_attr(msb->attr_group.attrs[cnt]); 1341baf8532aSAlex Dubov 1342baf8532aSAlex Dubov if (s_attr->id == MSPRO_BLOCK_ID_SYSINFO 1343baf8532aSAlex Dubov && r_attr->id == s_attr->id) { 1344baf8532aSAlex Dubov if (memcmp(s_attr->data, r_attr->data, s_attr->size)) 1345baf8532aSAlex Dubov break; 1346baf8532aSAlex Dubov 1347baf8532aSAlex Dubov memstick_set_drvdata(card, msb); 1348baf8532aSAlex Dubov msb->q_thread = kthread_run(mspro_block_queue_thread, 1349baf8532aSAlex Dubov card, DRIVER_NAME"d"); 1350baf8532aSAlex Dubov if (IS_ERR(msb->q_thread)) 1351baf8532aSAlex Dubov msb->q_thread = NULL; 1352baf8532aSAlex Dubov else 1353baf8532aSAlex Dubov msb->active = 1; 1354baf8532aSAlex Dubov 1355baf8532aSAlex Dubov break; 1356baf8532aSAlex Dubov } 1357baf8532aSAlex Dubov } 1358baf8532aSAlex Dubov 1359baf8532aSAlex Dubov out_free: 1360baf8532aSAlex Dubov memstick_set_drvdata(card, msb); 1361baf8532aSAlex Dubov mspro_block_data_clear(new_msb); 1362baf8532aSAlex Dubov kfree(new_msb); 1363baf8532aSAlex Dubov out_unlock: 1364baf8532aSAlex Dubov mutex_unlock(&host->lock); 1365baf8532aSAlex Dubov 1366baf8532aSAlex Dubov #endif /* CONFIG_MEMSTICK_UNSAFE_RESUME */ 1367baf8532aSAlex Dubov 1368baf8532aSAlex Dubov spin_lock_irqsave(&msb->q_lock, flags); 1369baf8532aSAlex Dubov blk_start_queue(msb->queue); 1370baf8532aSAlex Dubov spin_unlock_irqrestore(&msb->q_lock, flags); 1371baf8532aSAlex Dubov return rc; 1372baf8532aSAlex Dubov } 1373baf8532aSAlex Dubov 1374baf8532aSAlex Dubov #else 1375baf8532aSAlex Dubov 1376baf8532aSAlex Dubov #define mspro_block_suspend NULL 1377baf8532aSAlex Dubov #define mspro_block_resume NULL 1378baf8532aSAlex Dubov 1379baf8532aSAlex Dubov #endif /* CONFIG_PM */ 1380baf8532aSAlex Dubov 1381baf8532aSAlex Dubov static struct memstick_device_id mspro_block_id_tbl[] = { 1382baf8532aSAlex Dubov {MEMSTICK_MATCH_ALL, MEMSTICK_TYPE_PRO, MEMSTICK_CATEGORY_STORAGE_DUO, 1383baf8532aSAlex Dubov MEMSTICK_CLASS_GENERIC_DUO}, 1384baf8532aSAlex Dubov {} 1385baf8532aSAlex Dubov }; 1386baf8532aSAlex Dubov 1387baf8532aSAlex Dubov 1388baf8532aSAlex Dubov static struct memstick_driver mspro_block_driver = { 1389baf8532aSAlex Dubov .driver = { 1390baf8532aSAlex Dubov .name = DRIVER_NAME, 1391baf8532aSAlex Dubov .owner = THIS_MODULE 1392baf8532aSAlex Dubov }, 1393baf8532aSAlex Dubov .id_table = mspro_block_id_tbl, 1394baf8532aSAlex Dubov .probe = mspro_block_probe, 1395baf8532aSAlex Dubov .remove = mspro_block_remove, 1396baf8532aSAlex Dubov .suspend = mspro_block_suspend, 1397baf8532aSAlex Dubov .resume = mspro_block_resume 1398baf8532aSAlex Dubov }; 1399baf8532aSAlex Dubov 1400baf8532aSAlex Dubov static int __init mspro_block_init(void) 1401baf8532aSAlex Dubov { 1402baf8532aSAlex Dubov int rc = -ENOMEM; 1403baf8532aSAlex Dubov 1404baf8532aSAlex Dubov rc = register_blkdev(major, DRIVER_NAME); 1405baf8532aSAlex Dubov if (rc < 0) { 1406baf8532aSAlex Dubov printk(KERN_ERR DRIVER_NAME ": failed to register " 1407baf8532aSAlex Dubov "major %d, error %d\n", major, rc); 1408baf8532aSAlex Dubov return rc; 1409baf8532aSAlex Dubov } 1410baf8532aSAlex Dubov if (!major) 1411baf8532aSAlex Dubov major = rc; 1412baf8532aSAlex Dubov 1413baf8532aSAlex Dubov rc = memstick_register_driver(&mspro_block_driver); 1414baf8532aSAlex Dubov if (rc) 1415baf8532aSAlex Dubov unregister_blkdev(major, DRIVER_NAME); 1416baf8532aSAlex Dubov return rc; 1417baf8532aSAlex Dubov } 1418baf8532aSAlex Dubov 1419baf8532aSAlex Dubov static void __exit mspro_block_exit(void) 1420baf8532aSAlex Dubov { 1421baf8532aSAlex Dubov memstick_unregister_driver(&mspro_block_driver); 1422baf8532aSAlex Dubov unregister_blkdev(major, DRIVER_NAME); 1423baf8532aSAlex Dubov idr_destroy(&mspro_block_disk_idr); 1424baf8532aSAlex Dubov } 1425baf8532aSAlex Dubov 1426baf8532aSAlex Dubov module_init(mspro_block_init); 1427baf8532aSAlex Dubov module_exit(mspro_block_exit); 1428baf8532aSAlex Dubov 1429baf8532aSAlex Dubov MODULE_LICENSE("GPL"); 1430baf8532aSAlex Dubov MODULE_AUTHOR("Alex Dubov"); 1431baf8532aSAlex Dubov MODULE_DESCRIPTION("Sony MemoryStickPro block device driver"); 1432baf8532aSAlex Dubov MODULE_DEVICE_TABLE(memstick, mspro_block_id_tbl); 1433