linux/drivers/usb/storage/karma.c
<<
>>
Prefs
   1/* Driver for Rio Karma
   2 *
   3 *   (c) 2006 Bob Copeland <me@bobcopeland.com>
   4 *   (c) 2006 Keith Bennett <keith@mcs.st-and.ac.uk>
   5 *
   6 * This program is free software; you can redistribute it and/or modify it
   7 * under the terms of the GNU General Public License as published by the
   8 * Free Software Foundation; either version 2, or (at your option) any
   9 * later version.
  10 *
  11 * This program is distributed in the hope that it will be useful, but
  12 * WITHOUT ANY WARRANTY; without even the implied warranty of
  13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14 * General Public License for more details.
  15 *
  16 * You should have received a copy of the GNU General Public License along
  17 * with this program; if not, write to the Free Software Foundation, Inc.,
  18 * 675 Mass Ave, Cambridge, MA 02139, USA.
  19 */
  20
  21#include <scsi/scsi.h>
  22#include <scsi/scsi_cmnd.h>
  23#include <scsi/scsi_device.h>
  24
  25#include "usb.h"
  26#include "transport.h"
  27#include "debug.h"
  28#include "karma.h"
  29
  30#define RIO_PREFIX "RIOP\x00"
  31#define RIO_PREFIX_LEN 5
  32#define RIO_SEND_LEN 40
  33#define RIO_RECV_LEN 0x200
  34
  35#define RIO_ENTER_STORAGE 0x1
  36#define RIO_LEAVE_STORAGE 0x2
  37#define RIO_RESET 0xC
  38
  39extern int usb_stor_Bulk_transport(struct scsi_cmnd *, struct us_data *);
  40
  41struct karma_data {
  42        int in_storage;
  43        char *recv;
  44};
  45
  46/*
  47 * Send commands to Rio Karma.
  48 *
  49 * For each command we send 40 bytes starting 'RIOP\0' followed by
  50 * the command number and a sequence number, which the device will ack
  51 * with a 512-byte packet with the high four bits set and everything
  52 * else null.  Then we send 'RIOP\x80' followed by a zero and the
  53 * sequence number, until byte 5 in the response repeats the sequence
  54 * number.
  55 */
  56static int rio_karma_send_command(char cmd, struct us_data *us)
  57{
  58        int result, partial;
  59        unsigned long timeout;
  60        static unsigned char seq = 1;
  61        struct karma_data *data = (struct karma_data *) us->extra;
  62
  63        US_DEBUGP("karma: sending command %04x\n", cmd);
  64        memset(us->iobuf, 0, RIO_SEND_LEN);
  65        memcpy(us->iobuf, RIO_PREFIX, RIO_PREFIX_LEN);
  66        us->iobuf[5] = cmd;
  67        us->iobuf[6] = seq;
  68
  69        timeout = jiffies + msecs_to_jiffies(6000);
  70        for (;;) {
  71                result = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe,
  72                        us->iobuf, RIO_SEND_LEN, &partial);
  73                if (result != USB_STOR_XFER_GOOD)
  74                        goto err;
  75
  76                result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe,
  77                        data->recv, RIO_RECV_LEN, &partial);
  78                if (result != USB_STOR_XFER_GOOD)
  79                        goto err;
  80
  81                if (data->recv[5] == seq)
  82                        break;
  83
  84                if (time_after(jiffies, timeout))
  85                        goto err;
  86
  87                us->iobuf[4] = 0x80;
  88                us->iobuf[5] = 0;
  89                msleep(50);
  90        }
  91
  92        seq++;
  93        if (seq == 0)
  94                seq = 1;
  95
  96        US_DEBUGP("karma: sent command %04x\n", cmd);
  97        return 0;
  98err:
  99        US_DEBUGP("karma: command %04x failed\n", cmd);
 100        return USB_STOR_TRANSPORT_FAILED;
 101}
 102
 103/*
 104 * Trap START_STOP and READ_10 to leave/re-enter storage mode.
 105 * Everything else is propagated to the normal bulk layer.
 106 */
 107int rio_karma_transport(struct scsi_cmnd *srb, struct us_data *us)
 108{
 109        int ret;
 110        struct karma_data *data = (struct karma_data *) us->extra;
 111
 112        if (srb->cmnd[0] == READ_10 && !data->in_storage) {
 113                ret = rio_karma_send_command(RIO_ENTER_STORAGE, us);
 114                if (ret)
 115                        return ret;
 116
 117                data->in_storage = 1;
 118                return usb_stor_Bulk_transport(srb, us);
 119        } else if (srb->cmnd[0] == START_STOP) {
 120                ret = rio_karma_send_command(RIO_LEAVE_STORAGE, us);
 121                if (ret)
 122                        return ret;
 123
 124                data->in_storage = 0;
 125                return rio_karma_send_command(RIO_RESET, us);
 126        }
 127        return usb_stor_Bulk_transport(srb, us);
 128}
 129
 130static void rio_karma_destructor(void *extra)
 131{
 132        struct karma_data *data = (struct karma_data *) extra;
 133        kfree(data->recv);
 134}
 135
 136int rio_karma_init(struct us_data *us)
 137{
 138        int ret = 0;
 139        struct karma_data *data = kzalloc(sizeof(struct karma_data), GFP_NOIO);
 140        if (!data)
 141                goto out;
 142
 143        data->recv = kmalloc(RIO_RECV_LEN, GFP_NOIO);
 144        if (!data->recv) {
 145                kfree(data);
 146                goto out;
 147        }
 148
 149        us->extra = data;
 150        us->extra_destructor = rio_karma_destructor;
 151        ret = rio_karma_send_command(RIO_ENTER_STORAGE, us);
 152        data->in_storage = (ret == 0);
 153out:
 154        return ret;
 155}
 156