linux-old/drivers/usb/storage/datafab.c
<<
>>
Prefs
   1/* Driver for Datafab USB Compact Flash reader
   2 *
   3 * $Id: datafab.c,v 1.7 2002/02/25 00:40:13 mdharm Exp $
   4 *
   5 * datafab driver v0.1:
   6 *
   7 * First release
   8 *
   9 * Current development and maintenance by:
  10 *   (c) 2000 Jimmie Mayfield (mayfield+datafab@sackheads.org)
  11 *
  12 *   Many thanks to Robert Baruch for the SanDisk SmartMedia reader driver
  13 *   which I used as a template for this driver.
  14 *
  15 *   Some bugfixes and scatter-gather code by Gregory P. Smith 
  16 *   (greg-usb@electricrain.com)
  17 *
  18 *   Fix for media change by Joerg Schneider (js@joergschneider.com)
  19 *
  20 * Other contributors:
  21 *   (c) 2002 Alan Stern <stern@rowland.org>
  22 *
  23 * This program is free software; you can redistribute it and/or modify it
  24 * under the terms of the GNU General Public License as published by the
  25 * Free Software Foundation; either version 2, or (at your option) any
  26 * later version.
  27 *
  28 * This program is distributed in the hope that it will be useful, but
  29 * WITHOUT ANY WARRANTY; without even the implied warranty of
  30 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  31 * General Public License for more details.
  32 *
  33 * You should have received a copy of the GNU General Public License along
  34 * with this program; if not, write to the Free Software Foundation, Inc.,
  35 * 675 Mass Ave, Cambridge, MA 02139, USA.
  36 */
  37
  38/*
  39 * This driver attempts to support USB CompactFlash reader/writer devices
  40 * based on Datafab USB-to-ATA chips.  It was specifically developed for the 
  41 * Datafab MDCFE-B USB CompactFlash reader but has since been found to work 
  42 * with a variety of Datafab-based devices from a number of manufacturers.
  43 * I've received a report of this driver working with a Datafab-based
  44 * SmartMedia device though please be aware that I'm personally unable to
  45 * test SmartMedia support.
  46 *
  47 * This driver supports reading and writing.  If you're truly paranoid,
  48 * however, you can force the driver into a write-protected state by setting
  49 * the WP enable bits in datafab_handle_mode_sense().  Basically this means
  50 * setting mode_param_header[3] = 0x80.
  51 */
  52
  53#include "transport.h"
  54#include "protocol.h"
  55#include "usb.h"
  56#include "debug.h"
  57#include "datafab.h"
  58
  59#include <linux/sched.h>
  60#include <linux/errno.h>
  61#include <linux/slab.h>
  62
  63extern int usb_stor_bulk_msg(struct us_data *us, void *data, int pipe,
  64                             unsigned int len, unsigned int *act_len);
  65
  66static int datafab_determine_lun(struct us_data *us, struct datafab_info *info);
  67
  68
  69static void datafab_dump_data(unsigned char *data, int len)
  70{
  71        unsigned char buf[80];
  72        int sofar = 0;
  73
  74        if (!data)
  75                return;
  76
  77        memset(buf, 0, sizeof(buf));
  78
  79        for (sofar = 0; sofar < len; sofar++) {
  80                sprintf(buf + strlen(buf), "%02x ",
  81                        ((unsigned int) data[sofar]) & 0xFF);
  82
  83                if (sofar % 16 == 15) {
  84                        US_DEBUGP("datafab:  %s\n", buf);
  85                        memset(buf, 0, sizeof(buf));
  86                }
  87        }
  88
  89        if (strlen(buf) != 0)
  90                US_DEBUGP("datafab:  %s\n", buf);
  91}
  92
  93
  94static int datafab_raw_bulk(int direction,
  95                            struct us_data *us,
  96                            unsigned char *data, 
  97                            unsigned int len)
  98{
  99        int result;
 100        int act_len;
 101        int pipe;
 102
 103        if (direction == SCSI_DATA_READ)
 104                pipe = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);
 105        else
 106                pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
 107
 108        result = usb_stor_bulk_msg(us, data, pipe, len, &act_len);
 109
 110        // if we stall, we need to clear it before we go on 
 111        if (result == -EPIPE) {
 112                US_DEBUGP("datafab_raw_bulk: EPIPE. clearing endpoint halt for"
 113                          " pipe 0x%x, stalled at %d bytes\n", pipe, act_len);
 114                usb_stor_clear_halt(us, pipe);
 115        }
 116
 117        if (result) {
 118                // NAK - that means we've retried a few times already 
 119                if (result == -ETIMEDOUT) {
 120                        US_DEBUGP("datafab_raw_bulk:  device NAKed\n");
 121                        return US_BULK_TRANSFER_FAILED;
 122                }
 123
 124                // -ECONNRESET -- we canceled this transfer
 125                if (result == -ECONNRESET) {
 126                        US_DEBUGP("datafab_raw_bulk:  transfer aborted\n");
 127                        return US_BULK_TRANSFER_ABORTED;
 128                }
 129
 130                if (result == -EPIPE) {
 131                        US_DEBUGP("datafab_raw_bulk:  output pipe stalled\n");
 132                        return USB_STOR_TRANSPORT_FAILED;
 133                }
 134
 135                // the catch-all case
 136                US_DEBUGP("datafab_raw_bulk:  unknown error\n");
 137                return US_BULK_TRANSFER_FAILED;
 138        }
 139
 140        if (act_len != len) {
 141                US_DEBUGP("datafab_raw_bulk:  Warning. Transferred only %d bytes\n", act_len);
 142                return US_BULK_TRANSFER_SHORT;
 143        }
 144
 145        US_DEBUGP("datafab_raw_bulk:  Transfered %d of %d bytes\n", act_len, len);
 146        return US_BULK_TRANSFER_GOOD;
 147}
 148
 149static inline int datafab_bulk_read(struct us_data *us,
 150                                    unsigned char *data, 
 151                                    unsigned int len)
 152{
 153        if (len == 0)
 154                return USB_STOR_TRANSPORT_GOOD;
 155
 156        US_DEBUGP("datafab_bulk_read:  len = %d\n", len);
 157        return datafab_raw_bulk(SCSI_DATA_READ, us, data, len);
 158}
 159
 160
 161static inline int datafab_bulk_write(struct us_data *us,
 162                                     unsigned char *data, 
 163                                     unsigned int len)
 164{
 165        if (len == 0)
 166                return USB_STOR_TRANSPORT_GOOD;
 167
 168        US_DEBUGP("datafab_bulk_write:  len = %d\n", len);
 169        return datafab_raw_bulk(SCSI_DATA_WRITE, us, data, len);
 170}
 171
 172
 173static int datafab_read_data(struct us_data *us,
 174                             struct datafab_info *info,
 175                             u32 sector,
 176                             u32 sectors, 
 177                             unsigned char *dest, 
 178                             int use_sg)
 179{
 180        unsigned char command[8] = { 0, 0, 0, 0, 0, 0xE0, 0x20, 0x01 };
 181        unsigned char *buffer = NULL;
 182        unsigned char *ptr;
 183        unsigned char  thistime;
 184        struct scatterlist *sg = NULL;
 185        int totallen, len, result;
 186        int sg_idx = 0, current_sg_offset = 0;
 187        int transferred, rc;
 188
 189        // we're working in LBA mode.  according to the ATA spec, 
 190        // we can support up to 28-bit addressing.  I don't know if Datafab
 191        // supports beyond 24-bit addressing.  It's kind of hard to test 
 192        // since it requires > 8GB CF card.
 193        //
 194        if (sectors > 0x0FFFFFFF)
 195                return USB_STOR_TRANSPORT_ERROR;
 196
 197        if (info->lun == -1) {
 198                rc = datafab_determine_lun(us, info);
 199                if (rc != USB_STOR_TRANSPORT_GOOD)
 200                        return rc;
 201        }
 202
 203        command[5] += (info->lun << 4);
 204
 205        // If we're using scatter-gather, we have to create a new
 206        // buffer to read all of the data in first, since a
 207        // scatter-gather buffer could in theory start in the middle
 208        // of a page, which would be bad. A developer who wants a
 209        // challenge might want to write a limited-buffer
 210        // version of this code.
 211
 212        totallen = sectors * info->ssize;
 213
 214        do {
 215                // loop, never allocate or transfer more than 64k at once (min(128k, 255*info->ssize) is the real limit)
 216                len = min_t(int, totallen, 65536);
 217
 218                if (use_sg) {
 219                        sg = (struct scatterlist *) dest;
 220                        buffer = kmalloc(len, GFP_NOIO);
 221                        if (buffer == NULL)
 222                                return USB_STOR_TRANSPORT_ERROR;
 223                        ptr = buffer;
 224                } else {
 225                        ptr = dest;
 226                }
 227
 228                thistime = (len / info->ssize) & 0xff;
 229
 230                command[0] = 0;
 231                command[1] = thistime;
 232                command[2] = sector & 0xFF;
 233                command[3] = (sector >> 8) & 0xFF;
 234                command[4] = (sector >> 16) & 0xFF;
 235        
 236                command[5] |= (sector >> 24) & 0x0F;
 237
 238                // send the command
 239                US_DEBUGP("datafab_read_data:  sending following command\n");
 240                datafab_dump_data(command, sizeof(command));
 241
 242                result = datafab_bulk_write(us, command, sizeof(command));
 243                if (result != USB_STOR_TRANSPORT_GOOD) {
 244                        if (use_sg)
 245                                kfree(buffer);
 246                        return result;
 247                }
 248
 249                // read the result
 250                result = datafab_bulk_read(us, ptr, len);
 251                if (result != USB_STOR_TRANSPORT_GOOD) {
 252                        if (use_sg)
 253                                kfree(buffer);
 254                        return result;
 255                }
 256
 257                US_DEBUGP("datafab_read_data results:  %d bytes\n", len);
 258                // datafab_dump_data(ptr, len);
 259
 260                sectors -= thistime;
 261                sector  += thistime;
 262
 263                if (use_sg) {
 264                        transferred = 0;
 265                        while (sg_idx < use_sg && transferred < len) {
 266                                if (len - transferred >= sg[sg_idx].length - current_sg_offset) {
 267                                        US_DEBUGP("datafab_read_data:  adding %d bytes to %d byte sg buffer\n", sg[sg_idx].length - current_sg_offset, sg[sg_idx].length);
 268                                        memcpy(sg[sg_idx].address + current_sg_offset,
 269                                               buffer + transferred,
 270                                               sg[sg_idx].length - current_sg_offset);
 271                                        transferred += sg[sg_idx].length - current_sg_offset;
 272                                        current_sg_offset = 0;
 273                                        // on to the next sg buffer
 274                                        ++sg_idx;
 275                                } else {
 276                                        US_DEBUGP("datafab_read_data:  adding %d bytes to %d byte sg buffer\n", len - transferred, sg[sg_idx].length);
 277                                        memcpy(sg[sg_idx].address + current_sg_offset,
 278                                               buffer + transferred,
 279                                               len - transferred);
 280                                        current_sg_offset += len - transferred;
 281                                        // this sg buffer is only partially full and we're out of data to copy in
 282                                        break;
 283                                }
 284                        }
 285                        kfree(buffer);
 286                } else {
 287                        dest += len;
 288                }
 289
 290                totallen -= len;
 291        } while (totallen > 0);
 292
 293        return USB_STOR_TRANSPORT_GOOD;
 294}
 295
 296
 297static int datafab_write_data(struct us_data *us,
 298                              struct datafab_info *info,
 299                              u32 sector,
 300                              u32 sectors, 
 301                              unsigned char *src, 
 302                              int use_sg)
 303{
 304        unsigned char command[8] = { 0, 0, 0, 0, 0, 0xE0, 0x30, 0x02 };
 305        unsigned char reply[2] = { 0, 0 };
 306        unsigned char *buffer = NULL;
 307        unsigned char *ptr;
 308        unsigned char thistime;
 309        struct scatterlist *sg = NULL;
 310        int totallen, len, result;
 311        int sg_idx = 0, current_sg_offset = 0;
 312        int transferred, rc;
 313
 314        // we're working in LBA mode.  according to the ATA spec, 
 315        // we can support up to 28-bit addressing.  I don't know if Datafab
 316        // supports beyond 24-bit addressing.  It's kind of hard to test 
 317        // since it requires > 8GB CF card.
 318        //
 319        if (sectors > 0x0FFFFFFF)
 320                return USB_STOR_TRANSPORT_ERROR;
 321
 322        if (info->lun == -1) {
 323                rc = datafab_determine_lun(us, info);
 324                if (rc != USB_STOR_TRANSPORT_GOOD)
 325                        return rc;
 326        }
 327
 328        command[5] += (info->lun << 4);
 329
 330        // If we're using scatter-gather, we have to create a new
 331        // buffer to read all of the data in first, since a
 332        // scatter-gather buffer could in theory start in the middle
 333        // of a page, which would be bad. A developer who wants a
 334        // challenge might want to write a limited-buffer
 335        // version of this code.
 336
 337        totallen = sectors * info->ssize;
 338
 339        do {
 340                // loop, never allocate or transfer more than 64k at once (min(128k, 255*info->ssize) is the real limit)
 341                len = min_t(int, totallen, 65536);
 342
 343                if (use_sg) {
 344                        sg = (struct scatterlist *) src;
 345                        buffer = kmalloc(len, GFP_NOIO);
 346                        if (buffer == NULL)
 347                                return USB_STOR_TRANSPORT_ERROR;
 348                        ptr = buffer;
 349
 350                        memset(buffer, 0, len);
 351
 352                        // copy the data from the sg bufs into the big contiguous buf
 353                        //
 354                        transferred = 0;
 355                        while (transferred < len) {
 356                                if (len - transferred >= sg[sg_idx].length - current_sg_offset) {
 357                                        US_DEBUGP("datafab_write_data:  getting %d bytes from %d byte sg buffer\n", sg[sg_idx].length - current_sg_offset, sg[sg_idx].length);
 358                                        memcpy(ptr + transferred,
 359                                               sg[sg_idx].address + current_sg_offset,
 360                                               sg[sg_idx].length - current_sg_offset);
 361                                        transferred += sg[sg_idx].length - current_sg_offset;
 362                                        current_sg_offset = 0;
 363                                        // on to the next sg buffer
 364                                        ++sg_idx;
 365                                } else {
 366                                        US_DEBUGP("datafab_write_data:  getting %d bytes from %d byte sg buffer\n", len - transferred, sg[sg_idx].length);
 367                                        memcpy(ptr + transferred,
 368                                               sg[sg_idx].address + current_sg_offset,
 369                                               len - transferred);
 370                                        current_sg_offset += len - transferred;
 371                                        // we only copied part of this sg buffer
 372                                        break;
 373                                }
 374                        }
 375                } else {
 376                        ptr = src;
 377                }
 378
 379                thistime = (len / info->ssize) & 0xff;
 380
 381                command[0] = 0;
 382                command[1] = thistime;
 383                command[2] = sector & 0xFF;
 384                command[3] = (sector >> 8) & 0xFF;
 385                command[4] = (sector >> 16) & 0xFF;
 386
 387                command[5] |= (sector >> 24) & 0x0F;
 388
 389                // send the command
 390                US_DEBUGP("datafab_write_data:  sending following command\n");
 391                datafab_dump_data(command, sizeof(command));
 392
 393                result = datafab_bulk_write(us, command, sizeof(command));
 394                if (result != USB_STOR_TRANSPORT_GOOD) {
 395                        if (use_sg)
 396                                kfree(buffer);
 397                        return result;
 398                }
 399
 400                // send the data
 401                result = datafab_bulk_write(us, ptr, len);
 402                if (result != USB_STOR_TRANSPORT_GOOD) {
 403                        if (use_sg)
 404                                kfree(buffer);
 405                        return result;
 406                }
 407
 408                // read the result
 409                result = datafab_bulk_read(us, reply, sizeof(reply));
 410                if (result != USB_STOR_TRANSPORT_GOOD) {
 411                        if (use_sg)
 412                                kfree(buffer);
 413                        return result;
 414                }
 415
 416                if (reply[0] != 0x50 && reply[1] != 0) {
 417                        US_DEBUGP("datafab_write_data:  Gah! write return code: %02x %02x\n", reply[0], reply[1]);
 418                        if (use_sg)
 419                                kfree(buffer);
 420                        return USB_STOR_TRANSPORT_ERROR;
 421                }
 422
 423                sectors -= thistime;
 424                sector  += thistime;
 425
 426                if (use_sg) {
 427                        kfree(buffer);
 428                } else {
 429                        src += len;
 430                }
 431
 432                totallen -= len;
 433        } while (totallen > 0);
 434
 435        return USB_STOR_TRANSPORT_GOOD;
 436}
 437
 438
 439static int datafab_determine_lun(struct us_data *us,
 440                                 struct datafab_info *info)
 441{
 442        // dual-slot readers can be thought of as dual-LUN devices.  we need to
 443        // determine which card slot is being used.  we'll send an IDENTIFY DEVICE
 444        // command and see which LUN responds...
 445        //
 446        // there might be a better way of doing this?
 447        //
 448        unsigned char command[8] = { 0, 1, 0, 0, 0, 0xa0, 0xec, 1 };
 449        unsigned char buf[512];
 450        int count = 0, rc;
 451
 452        if (!us || !info)
 453                return USB_STOR_TRANSPORT_ERROR;
 454
 455        US_DEBUGP("datafab_determine_lun:  locating...\n");
 456
 457        // we'll try 10 times before giving up...
 458        //
 459        while (count++ < 10) {
 460                command[5] = 0xa0;
 461
 462                rc = datafab_bulk_write(us, command, 8);
 463                if (rc != USB_STOR_TRANSPORT_GOOD) 
 464                        return rc;
 465
 466                rc = datafab_bulk_read(us, buf, sizeof(buf));
 467                if (rc == USB_STOR_TRANSPORT_GOOD) {
 468                        info->lun = 0;
 469                        return USB_STOR_TRANSPORT_GOOD;
 470                }
 471
 472                command[5] = 0xb0;
 473
 474                rc = datafab_bulk_write(us, command, 8);
 475                if (rc != USB_STOR_TRANSPORT_GOOD) 
 476                        return rc;
 477
 478                rc = datafab_bulk_read(us, buf, sizeof(buf));
 479                if (rc == USB_STOR_TRANSPORT_GOOD) {
 480                        info->lun = 1;
 481                        return USB_STOR_TRANSPORT_GOOD;
 482                }
 483
 484                wait_ms(20);
 485        }
 486
 487        return USB_STOR_TRANSPORT_FAILED;
 488}
 489
 490static int datafab_id_device(struct us_data *us,
 491                             struct datafab_info *info)
 492{
 493        // this is a variation of the ATA "IDENTIFY DEVICE" command...according
 494        // to the ATA spec, 'Sector Count' isn't used but the Windows driver
 495        // sets this bit so we do too...
 496        //
 497        unsigned char command[8] = { 0, 1, 0, 0, 0, 0xa0, 0xec, 1 };
 498        unsigned char reply[512];
 499        int rc;
 500
 501        if (!us || !info)
 502                return USB_STOR_TRANSPORT_ERROR;
 503
 504        if (info->lun == -1) {
 505                rc = datafab_determine_lun(us, info);
 506                if (rc != USB_STOR_TRANSPORT_GOOD)
 507                        return rc;
 508        }
 509
 510        command[5] += (info->lun << 4);
 511
 512        rc = datafab_bulk_write(us, command, 8);
 513        if (rc != USB_STOR_TRANSPORT_GOOD) 
 514                return rc;
 515
 516        // we'll go ahead and extract the media capacity while we're here...
 517        //
 518        rc = datafab_bulk_read(us, reply, sizeof(reply));
 519        if (rc == USB_STOR_TRANSPORT_GOOD) {
 520                // capacity is at word offset 57-58
 521                //
 522                info->sectors = ((u32)(reply[117]) << 24) | 
 523                                ((u32)(reply[116]) << 16) |
 524                                ((u32)(reply[115]) <<  8) | 
 525                                ((u32)(reply[114])      );
 526        }
 527                
 528        return rc;
 529}
 530
 531
 532static int datafab_handle_mode_sense(struct us_data *us,
 533                                     Scsi_Cmnd * srb, 
 534                                     unsigned char *ptr,
 535                                     int sense_6)
 536{
 537        unsigned char mode_param_header[8] = {
 538                0, 0, 0, 0, 0, 0, 0, 0
 539        };
 540        unsigned char rw_err_page[12] = {
 541                0x1, 0xA, 0x21, 1, 0, 0, 0, 0, 1, 0, 0, 0
 542        };
 543        unsigned char cache_page[12] = {
 544                0x8, 0xA, 0x1, 0, 0, 0, 0, 0, 0, 0, 0, 0
 545        };
 546        unsigned char rbac_page[12] = {
 547                0x1B, 0xA, 0, 0x81, 0, 0, 0, 0, 0, 0, 0, 0
 548        };
 549        unsigned char timer_page[8] = {
 550                0x1C, 0x6, 0, 0, 0, 0
 551        };
 552        unsigned char pc, page_code;
 553        unsigned short total_len = 0;
 554        unsigned short param_len, i = 0;
 555
 556        // most of this stuff is just a hack to get things working.  the
 557        // datafab reader doesn't present a SCSI interface so we
 558        // fudge the SCSI commands...
 559        //
 560        
 561        if (sense_6)
 562                param_len = srb->cmnd[4];
 563        else
 564                param_len = ((u16) (srb->cmnd[7]) >> 8) | ((u16) (srb->cmnd[8]));
 565
 566        pc = srb->cmnd[2] >> 6;
 567        page_code = srb->cmnd[2] & 0x3F;
 568
 569        switch (pc) {
 570           case 0x0:
 571                US_DEBUGP("datafab_handle_mode_sense:  Current values\n");
 572                break;
 573           case 0x1:
 574                US_DEBUGP("datafab_handle_mode_sense:  Changeable values\n");
 575                break;
 576           case 0x2:
 577                US_DEBUGP("datafab_handle_mode_sense:  Default values\n");
 578                break;
 579           case 0x3:
 580                US_DEBUGP("datafab_handle_mode_sense:  Saves values\n");
 581                break;
 582        }
 583
 584        mode_param_header[3] = 0x80;    // write enable
 585
 586        switch (page_code) {
 587           case 0x0:
 588                // vendor-specific mode
 589                return USB_STOR_TRANSPORT_ERROR;
 590
 591           case 0x1:
 592                total_len = sizeof(rw_err_page);
 593                mode_param_header[0] = total_len >> 8;
 594                mode_param_header[1] = total_len & 0xFF;
 595                mode_param_header[3] = 0x00;    // WP enable: 0x80
 596
 597                memcpy(ptr, mode_param_header, sizeof(mode_param_header));
 598                i += sizeof(mode_param_header);
 599                memcpy(ptr + i, rw_err_page, sizeof(rw_err_page));
 600                break;
 601
 602           case 0x8:
 603                total_len = sizeof(cache_page);
 604                mode_param_header[0] = total_len >> 8;
 605                mode_param_header[1] = total_len & 0xFF;
 606                mode_param_header[3] = 0x00;    // WP enable: 0x80
 607
 608                memcpy(ptr, mode_param_header, sizeof(mode_param_header));
 609                i += sizeof(mode_param_header);
 610                memcpy(ptr + i, cache_page, sizeof(cache_page));
 611                break;
 612
 613           case 0x1B:
 614                total_len = sizeof(rbac_page);
 615                mode_param_header[0] = total_len >> 8;
 616                mode_param_header[1] = total_len & 0xFF;
 617                mode_param_header[3] = 0x00;    // WP enable: 0x80
 618
 619                memcpy(ptr, mode_param_header, sizeof(mode_param_header));
 620                i += sizeof(mode_param_header);
 621                memcpy(ptr + i, rbac_page, sizeof(rbac_page));
 622                break;
 623
 624           case 0x1C:
 625                total_len = sizeof(timer_page);
 626                mode_param_header[0] = total_len >> 8;
 627                mode_param_header[1] = total_len & 0xFF;
 628                mode_param_header[3] = 0x00;    // WP enable: 0x80
 629
 630                memcpy(ptr, mode_param_header, sizeof(mode_param_header));
 631                i += sizeof(mode_param_header);
 632                memcpy(ptr + i, timer_page, sizeof(timer_page));
 633                break;
 634
 635           case 0x3F:           // retrieve all pages
 636                total_len = sizeof(timer_page) + sizeof(rbac_page) +
 637                    sizeof(cache_page) + sizeof(rw_err_page);
 638                mode_param_header[0] = total_len >> 8;
 639                mode_param_header[1] = total_len & 0xFF;
 640                mode_param_header[3] = 0x00;    // WP enable
 641
 642                memcpy(ptr, mode_param_header, sizeof(mode_param_header));
 643                i += sizeof(mode_param_header);
 644                memcpy(ptr + i, timer_page, sizeof(timer_page));
 645                i += sizeof(timer_page);
 646                memcpy(ptr + i, rbac_page, sizeof(rbac_page));
 647                i += sizeof(rbac_page);
 648                memcpy(ptr + i, cache_page, sizeof(cache_page));
 649                i += sizeof(cache_page);
 650                memcpy(ptr + i, rw_err_page, sizeof(rw_err_page));
 651                break;
 652        }
 653
 654        return USB_STOR_TRANSPORT_GOOD;
 655}
 656
 657void datafab_info_destructor(void *extra)
 658{
 659        // this routine is a placeholder...
 660        // currently, we don't allocate any extra memory so we're okay
 661}
 662
 663
 664// Transport for the Datafab MDCFE-B
 665//
 666int datafab_transport(Scsi_Cmnd * srb, struct us_data *us)
 667{
 668        struct datafab_info *info;
 669        int rc;
 670        unsigned long block, blocks;
 671        unsigned char *ptr = NULL;
 672        unsigned char inquiry_reply[36] = {
 673                0x00, 0x80, 0x00, 0x01, 0x1F, 0x00, 0x00, 0x00
 674        };
 675
 676        if (!us->extra) {
 677                us->extra = kmalloc(sizeof(struct datafab_info), GFP_NOIO);
 678                if (!us->extra) {
 679                        US_DEBUGP("datafab_transport:  Gah! Can't allocate storage for Datafab info struct!\n");
 680                        return USB_STOR_TRANSPORT_ERROR;
 681                }
 682                memset(us->extra, 0, sizeof(struct datafab_info));
 683                us->extra_destructor = datafab_info_destructor;
 684                ((struct datafab_info *)us->extra)->lun = -1;
 685        }
 686
 687        info = (struct datafab_info *) (us->extra);
 688        ptr = (unsigned char *) srb->request_buffer;
 689
 690        if (srb->cmnd[0] == INQUIRY) {
 691                US_DEBUGP("datafab_transport:  INQUIRY.  Returning bogus response");
 692                memset( inquiry_reply + 8, 0, 28 );
 693                fill_inquiry_response(us, inquiry_reply, 36);
 694                return USB_STOR_TRANSPORT_GOOD;
 695        }
 696
 697        if (srb->cmnd[0] == READ_CAPACITY) {
 698                info->ssize = 0x200;  // hard coded 512 byte sectors as per ATA spec
 699                rc = datafab_id_device(us, info);
 700                if (rc != USB_STOR_TRANSPORT_GOOD)
 701                        return rc;
 702
 703                US_DEBUGP("datafab_transport:  READ_CAPACITY:  %ld sectors, %ld bytes per sector\n",
 704                          info->sectors, info->ssize);
 705
 706                // build the reply
 707                //
 708                ptr[0] = (info->sectors >> 24) & 0xFF;
 709                ptr[1] = (info->sectors >> 16) & 0xFF;
 710                ptr[2] = (info->sectors >> 8) & 0xFF;
 711                ptr[3] = (info->sectors) & 0xFF;
 712
 713                ptr[4] = (info->ssize >> 24) & 0xFF;
 714                ptr[5] = (info->ssize >> 16) & 0xFF;
 715                ptr[6] = (info->ssize >> 8) & 0xFF;
 716                ptr[7] = (info->ssize) & 0xFF;
 717
 718                return USB_STOR_TRANSPORT_GOOD;
 719        }
 720
 721        if (srb->cmnd[0] == MODE_SELECT_10) {
 722                US_DEBUGP("datafab_transport:  Gah! MODE_SELECT_10.\n");
 723                return USB_STOR_TRANSPORT_ERROR;
 724        }
 725
 726        // don't bother implementing READ_6 or WRITE_6.  Just set MODE_XLATE and
 727        // let the usb storage code convert to READ_10/WRITE_10
 728        //
 729        if (srb->cmnd[0] == READ_10) {
 730                block = ((u32)(srb->cmnd[2]) << 24) | ((u32)(srb->cmnd[3]) << 16) |
 731                        ((u32)(srb->cmnd[4]) <<  8) | ((u32)(srb->cmnd[5]));
 732
 733                blocks = ((u32)(srb->cmnd[7]) << 8) | ((u32)(srb->cmnd[8]));
 734
 735                US_DEBUGP("datafab_transport:  READ_10: read block 0x%04lx  count %ld\n", block, blocks);
 736                return datafab_read_data(us, info, block, blocks, ptr, srb->use_sg);
 737        }
 738
 739        if (srb->cmnd[0] == READ_12) {
 740                // we'll probably never see a READ_12 but we'll do it anyway...
 741                //
 742                block = ((u32)(srb->cmnd[2]) << 24) | ((u32)(srb->cmnd[3]) << 16) |
 743                        ((u32)(srb->cmnd[4]) <<  8) | ((u32)(srb->cmnd[5]));
 744
 745                blocks = ((u32)(srb->cmnd[6]) << 24) | ((u32)(srb->cmnd[7]) << 16) |
 746                         ((u32)(srb->cmnd[8]) <<  8) | ((u32)(srb->cmnd[9]));
 747
 748                US_DEBUGP("datafab_transport:  READ_12: read block 0x%04lx  count %ld\n", block, blocks);
 749                return datafab_read_data(us, info, block, blocks, ptr, srb->use_sg);
 750        }
 751
 752        if (srb->cmnd[0] == WRITE_10) {
 753                block = ((u32)(srb->cmnd[2]) << 24) | ((u32)(srb->cmnd[3]) << 16) |
 754                        ((u32)(srb->cmnd[4]) <<  8) | ((u32)(srb->cmnd[5]));
 755
 756                blocks = ((u32)(srb->cmnd[7]) << 8) | ((u32)(srb->cmnd[8]));
 757
 758                US_DEBUGP("datafab_transport:  WRITE_10: write block 0x%04lx  count %ld\n", block, blocks);
 759                return datafab_write_data(us, info, block, blocks, ptr, srb->use_sg);
 760        }
 761
 762        if (srb->cmnd[0] == WRITE_12) {
 763                // we'll probably never see a WRITE_12 but we'll do it anyway...
 764                //
 765                block = ((u32)(srb->cmnd[2]) << 24) | ((u32)(srb->cmnd[3]) << 16) |
 766                        ((u32)(srb->cmnd[4]) <<  8) | ((u32)(srb->cmnd[5]));
 767
 768                blocks = ((u32)(srb->cmnd[6]) << 24) | ((u32)(srb->cmnd[7]) << 16) |
 769                         ((u32)(srb->cmnd[8]) <<  8) | ((u32)(srb->cmnd[9]));
 770
 771                US_DEBUGP("datafab_transport:  WRITE_12: write block 0x%04lx  count %ld\n", block, blocks);
 772                return datafab_write_data(us, info, block, blocks, ptr, srb->use_sg);
 773        }
 774
 775        if (srb->cmnd[0] == TEST_UNIT_READY) {
 776                US_DEBUGP("datafab_transport:  TEST_UNIT_READY.\n");
 777                return datafab_id_device(us, info);
 778        }
 779
 780        if (srb->cmnd[0] == REQUEST_SENSE) {
 781                US_DEBUGP("datafab_transport:  REQUEST_SENSE.  Returning faked response\n");
 782
 783                // this response is pretty bogus right now.  eventually if necessary
 784                // we can set the correct sense data.  so far though it hasn't been
 785                // necessary
 786                //
 787                ptr[0] = 0xF0;
 788                ptr[2] = info->sense_key;
 789                ptr[7] = 11;
 790                ptr[12] = info->sense_asc;
 791                ptr[13] = info->sense_ascq;
 792
 793                return USB_STOR_TRANSPORT_GOOD;
 794        }
 795
 796        if (srb->cmnd[0] == MODE_SENSE) {
 797                US_DEBUGP("datafab_transport:  MODE_SENSE_6 detected\n");
 798                return datafab_handle_mode_sense(us, srb, ptr, TRUE);
 799        }
 800
 801        if (srb->cmnd[0] == MODE_SENSE_10) {
 802                US_DEBUGP("datafab_transport:  MODE_SENSE_10 detected\n");
 803                return datafab_handle_mode_sense(us, srb, ptr, FALSE);
 804        }
 805
 806        if (srb->cmnd[0] == ALLOW_MEDIUM_REMOVAL) {
 807                // sure.  whatever.  not like we can stop the user from
 808                // popping the media out of the device (no locking doors, etc)
 809                //
 810                return USB_STOR_TRANSPORT_GOOD;
 811        }
 812
 813        if (srb->cmnd[0] == START_STOP) {
 814                /* this is used by sd.c'check_scsidisk_media_change to detect
 815                   media change */
 816                US_DEBUGP("datafab_transport:  START_STOP.\n");
 817                /* the first datafab_id_device after a media change returns
 818                   an error (determined experimentally) */
 819                rc = datafab_id_device(us, info);
 820                if (rc == USB_STOR_TRANSPORT_GOOD) {
 821                        info->sense_key = NO_SENSE;
 822                        srb->result = SUCCESS;
 823                } else {
 824                        info->sense_key = UNIT_ATTENTION;
 825                        srb->result = CHECK_CONDITION;
 826                }
 827                return rc;
 828        }
 829
 830        US_DEBUGP("datafab_transport:  Gah! Unknown command: %d (0x%x)\n", srb->cmnd[0], srb->cmnd[0]);
 831        return USB_STOR_TRANSPORT_ERROR;
 832}
 833
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.