Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0+
0002 /*
0003  * Driver for Freecom USB/IDE adaptor
0004  *
0005  * Freecom v0.1:
0006  *
0007  * First release
0008  *
0009  * Current development and maintenance by:
0010  *   (C) 2000 David Brown <usb-storage@davidb.org>
0011  *
0012  * This driver was developed with information provided in FREECOM's USB
0013  * Programmers Reference Guide.  For further information contact Freecom
0014  * (https://www.freecom.de/)
0015  */
0016 
0017 #include <linux/module.h>
0018 #include <scsi/scsi.h>
0019 #include <scsi/scsi_cmnd.h>
0020 
0021 #include "usb.h"
0022 #include "transport.h"
0023 #include "protocol.h"
0024 #include "debug.h"
0025 #include "scsiglue.h"
0026 
0027 #define DRV_NAME "ums-freecom"
0028 
0029 MODULE_DESCRIPTION("Driver for Freecom USB/IDE adaptor");
0030 MODULE_AUTHOR("David Brown <usb-storage@davidb.org>");
0031 MODULE_LICENSE("GPL");
0032 MODULE_IMPORT_NS(USB_STORAGE);
0033 
0034 #ifdef CONFIG_USB_STORAGE_DEBUG
0035 static void pdump(struct us_data *us, void *ibuffer, int length);
0036 #endif
0037 
0038 /* Bits of HD_STATUS */
0039 #define ERR_STAT        0x01
0040 #define DRQ_STAT        0x08
0041 
0042 /* All of the outgoing packets are 64 bytes long. */
0043 struct freecom_cb_wrap {
0044     u8    Type;     /* Command type. */
0045     u8    Timeout;      /* Timeout in seconds. */
0046     u8    Atapi[12];    /* An ATAPI packet. */
0047     u8    Filler[50];   /* Padding Data. */
0048 };
0049 
0050 struct freecom_xfer_wrap {
0051     u8    Type;     /* Command type. */
0052     u8    Timeout;      /* Timeout in seconds. */
0053     __le32   Count;     /* Number of bytes to transfer. */
0054     u8    Pad[58];
0055 } __attribute__ ((packed));
0056 
0057 struct freecom_ide_out {
0058     u8    Type;     /* Type + IDE register. */
0059     u8    Pad;
0060     __le16   Value;     /* Value to write. */
0061     u8    Pad2[60];
0062 };
0063 
0064 struct freecom_ide_in {
0065     u8    Type;     /* Type | IDE register. */
0066     u8    Pad[63];
0067 };
0068 
0069 struct freecom_status {
0070     u8    Status;
0071     u8    Reason;
0072     __le16   Count;
0073     u8    Pad[60];
0074 };
0075 
0076 /*
0077  * Freecom stuffs the interrupt status in the INDEX_STAT bit of the ide
0078  * register.
0079  */
0080 #define FCM_INT_STATUS      0x02 /* INDEX_STAT */
0081 #define FCM_STATUS_BUSY     0x80
0082 
0083 /*
0084  * These are the packet types.  The low bit indicates that this command
0085  * should wait for an interrupt.
0086  */
0087 #define FCM_PACKET_ATAPI    0x21
0088 #define FCM_PACKET_STATUS   0x20
0089 
0090 /*
0091  * Receive data from the IDE interface.  The ATAPI packet has already
0092  * waited, so the data should be immediately available.
0093  */
0094 #define FCM_PACKET_INPUT    0x81
0095 
0096 /* Send data to the IDE interface. */
0097 #define FCM_PACKET_OUTPUT   0x01
0098 
0099 /*
0100  * Write a value to an ide register.  Or the ide register to write after
0101  * munging the address a bit.
0102  */
0103 #define FCM_PACKET_IDE_WRITE    0x40
0104 #define FCM_PACKET_IDE_READ 0xC0
0105 
0106 /* All packets (except for status) are 64 bytes long. */
0107 #define FCM_PACKET_LENGTH       64
0108 #define FCM_STATUS_PACKET_LENGTH    4
0109 
0110 static int init_freecom(struct us_data *us);
0111 
0112 
0113 /*
0114  * The table of devices
0115  */
0116 #define UNUSUAL_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \
0117             vendorName, productName, useProtocol, useTransport, \
0118             initFunction, flags) \
0119 { USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax), \
0120   .driver_info = (flags) }
0121 
0122 static struct usb_device_id freecom_usb_ids[] = {
0123 #   include "unusual_freecom.h"
0124     { }     /* Terminating entry */
0125 };
0126 MODULE_DEVICE_TABLE(usb, freecom_usb_ids);
0127 
0128 #undef UNUSUAL_DEV
0129 
0130 /*
0131  * The flags table
0132  */
0133 #define UNUSUAL_DEV(idVendor, idProduct, bcdDeviceMin, bcdDeviceMax, \
0134             vendor_name, product_name, use_protocol, use_transport, \
0135             init_function, Flags) \
0136 { \
0137     .vendorName = vendor_name,  \
0138     .productName = product_name,    \
0139     .useProtocol = use_protocol,    \
0140     .useTransport = use_transport,  \
0141     .initFunction = init_function,  \
0142 }
0143 
0144 static struct us_unusual_dev freecom_unusual_dev_list[] = {
0145 #   include "unusual_freecom.h"
0146     { }     /* Terminating entry */
0147 };
0148 
0149 #undef UNUSUAL_DEV
0150 
0151 static int
0152 freecom_readdata (struct scsi_cmnd *srb, struct us_data *us,
0153         unsigned int ipipe, unsigned int opipe, int count)
0154 {
0155     struct freecom_xfer_wrap *fxfr =
0156         (struct freecom_xfer_wrap *) us->iobuf;
0157     int result;
0158 
0159     fxfr->Type = FCM_PACKET_INPUT | 0x00;
0160     fxfr->Timeout = 0;    /* Short timeout for debugging. */
0161     fxfr->Count = cpu_to_le32 (count);
0162     memset (fxfr->Pad, 0, sizeof (fxfr->Pad));
0163 
0164     usb_stor_dbg(us, "Read data Freecom! (c=%d)\n", count);
0165 
0166     /* Issue the transfer command. */
0167     result = usb_stor_bulk_transfer_buf (us, opipe, fxfr,
0168             FCM_PACKET_LENGTH, NULL);
0169     if (result != USB_STOR_XFER_GOOD) {
0170         usb_stor_dbg(us, "Freecom readdata transport error\n");
0171         return USB_STOR_TRANSPORT_ERROR;
0172     }
0173 
0174     /* Now transfer all of our blocks. */
0175     usb_stor_dbg(us, "Start of read\n");
0176     result = usb_stor_bulk_srb(us, ipipe, srb);
0177     usb_stor_dbg(us, "freecom_readdata done!\n");
0178 
0179     if (result > USB_STOR_XFER_SHORT)
0180         return USB_STOR_TRANSPORT_ERROR;
0181     return USB_STOR_TRANSPORT_GOOD;
0182 }
0183 
0184 static int
0185 freecom_writedata (struct scsi_cmnd *srb, struct us_data *us,
0186         int unsigned ipipe, unsigned int opipe, int count)
0187 {
0188     struct freecom_xfer_wrap *fxfr =
0189         (struct freecom_xfer_wrap *) us->iobuf;
0190     int result;
0191 
0192     fxfr->Type = FCM_PACKET_OUTPUT | 0x00;
0193     fxfr->Timeout = 0;    /* Short timeout for debugging. */
0194     fxfr->Count = cpu_to_le32 (count);
0195     memset (fxfr->Pad, 0, sizeof (fxfr->Pad));
0196 
0197     usb_stor_dbg(us, "Write data Freecom! (c=%d)\n", count);
0198 
0199     /* Issue the transfer command. */
0200     result = usb_stor_bulk_transfer_buf (us, opipe, fxfr,
0201             FCM_PACKET_LENGTH, NULL);
0202     if (result != USB_STOR_XFER_GOOD) {
0203         usb_stor_dbg(us, "Freecom writedata transport error\n");
0204         return USB_STOR_TRANSPORT_ERROR;
0205     }
0206 
0207     /* Now transfer all of our blocks. */
0208     usb_stor_dbg(us, "Start of write\n");
0209     result = usb_stor_bulk_srb(us, opipe, srb);
0210 
0211     usb_stor_dbg(us, "freecom_writedata done!\n");
0212     if (result > USB_STOR_XFER_SHORT)
0213         return USB_STOR_TRANSPORT_ERROR;
0214     return USB_STOR_TRANSPORT_GOOD;
0215 }
0216 
0217 /*
0218  * Transport for the Freecom USB/IDE adaptor.
0219  *
0220  */
0221 static int freecom_transport(struct scsi_cmnd *srb, struct us_data *us)
0222 {
0223     struct freecom_cb_wrap *fcb;
0224     struct freecom_status  *fst;
0225     unsigned int ipipe, opipe;      /* We need both pipes. */
0226     int result;
0227     unsigned int partial;
0228     int length;
0229 
0230     fcb = (struct freecom_cb_wrap *) us->iobuf;
0231     fst = (struct freecom_status *) us->iobuf;
0232 
0233     usb_stor_dbg(us, "Freecom TRANSPORT STARTED\n");
0234 
0235     /* Get handles for both transports. */
0236     opipe = us->send_bulk_pipe;
0237     ipipe = us->recv_bulk_pipe;
0238 
0239     /* The ATAPI Command always goes out first. */
0240     fcb->Type = FCM_PACKET_ATAPI | 0x00;
0241     fcb->Timeout = 0;
0242     memcpy (fcb->Atapi, srb->cmnd, 12);
0243     memset (fcb->Filler, 0, sizeof (fcb->Filler));
0244 
0245     US_DEBUG(pdump(us, srb->cmnd, 12));
0246 
0247     /* Send it out. */
0248     result = usb_stor_bulk_transfer_buf (us, opipe, fcb,
0249             FCM_PACKET_LENGTH, NULL);
0250 
0251     /*
0252      * The Freecom device will only fail if there is something wrong in
0253      * USB land.  It returns the status in its own registers, which
0254      * come back in the bulk pipe.
0255      */
0256     if (result != USB_STOR_XFER_GOOD) {
0257         usb_stor_dbg(us, "freecom transport error\n");
0258         return USB_STOR_TRANSPORT_ERROR;
0259     }
0260 
0261     /*
0262      * There are times we can optimize out this status read, but it
0263      * doesn't hurt us to always do it now.
0264      */
0265     result = usb_stor_bulk_transfer_buf (us, ipipe, fst,
0266             FCM_STATUS_PACKET_LENGTH, &partial);
0267     usb_stor_dbg(us, "foo Status result %d %u\n", result, partial);
0268     if (result != USB_STOR_XFER_GOOD)
0269         return USB_STOR_TRANSPORT_ERROR;
0270 
0271     US_DEBUG(pdump(us, (void *)fst, partial));
0272 
0273     /*
0274      * The firmware will time-out commands after 20 seconds. Some commands
0275      * can legitimately take longer than this, so we use a different
0276      * command that only waits for the interrupt and then sends status,
0277      * without having to send a new ATAPI command to the device.
0278      *
0279      * NOTE: There is some indication that a data transfer after a timeout
0280      * may not work, but that is a condition that should never happen.
0281      */
0282     while (fst->Status & FCM_STATUS_BUSY) {
0283         usb_stor_dbg(us, "20 second USB/ATAPI bridge TIMEOUT occurred!\n");
0284         usb_stor_dbg(us, "fst->Status is %x\n", fst->Status);
0285 
0286         /* Get the status again */
0287         fcb->Type = FCM_PACKET_STATUS;
0288         fcb->Timeout = 0;
0289         memset (fcb->Atapi, 0, sizeof(fcb->Atapi));
0290         memset (fcb->Filler, 0, sizeof (fcb->Filler));
0291 
0292         /* Send it out. */
0293         result = usb_stor_bulk_transfer_buf (us, opipe, fcb,
0294                 FCM_PACKET_LENGTH, NULL);
0295 
0296         /*
0297          * The Freecom device will only fail if there is something
0298          * wrong in USB land.  It returns the status in its own
0299          * registers, which come back in the bulk pipe.
0300          */
0301         if (result != USB_STOR_XFER_GOOD) {
0302             usb_stor_dbg(us, "freecom transport error\n");
0303             return USB_STOR_TRANSPORT_ERROR;
0304         }
0305 
0306         /* get the data */
0307         result = usb_stor_bulk_transfer_buf (us, ipipe, fst,
0308                 FCM_STATUS_PACKET_LENGTH, &partial);
0309 
0310         usb_stor_dbg(us, "bar Status result %d %u\n", result, partial);
0311         if (result != USB_STOR_XFER_GOOD)
0312             return USB_STOR_TRANSPORT_ERROR;
0313 
0314         US_DEBUG(pdump(us, (void *)fst, partial));
0315     }
0316 
0317     if (partial != 4)
0318         return USB_STOR_TRANSPORT_ERROR;
0319     if ((fst->Status & 1) != 0) {
0320         usb_stor_dbg(us, "operation failed\n");
0321         return USB_STOR_TRANSPORT_FAILED;
0322     }
0323 
0324     /*
0325      * The device might not have as much data available as we
0326      * requested.  If you ask for more than the device has, this reads
0327      * and such will hang.
0328      */
0329     usb_stor_dbg(us, "Device indicates that it has %d bytes available\n",
0330              le16_to_cpu(fst->Count));
0331     usb_stor_dbg(us, "SCSI requested %d\n", scsi_bufflen(srb));
0332 
0333     /* Find the length we desire to read. */
0334     switch (srb->cmnd[0]) {
0335     case INQUIRY:
0336     case REQUEST_SENSE: /* 16 or 18 bytes? spec says 18, lots of devices only have 16 */
0337     case MODE_SENSE:
0338     case MODE_SENSE_10:
0339         length = le16_to_cpu(fst->Count);
0340         break;
0341     default:
0342         length = scsi_bufflen(srb);
0343     }
0344 
0345     /* verify that this amount is legal */
0346     if (length > scsi_bufflen(srb)) {
0347         length = scsi_bufflen(srb);
0348         usb_stor_dbg(us, "Truncating request to match buffer length: %d\n",
0349                  length);
0350     }
0351 
0352     /*
0353      * What we do now depends on what direction the data is supposed to
0354      * move in.
0355      */
0356 
0357     switch (us->srb->sc_data_direction) {
0358     case DMA_FROM_DEVICE:
0359         /* catch bogus "read 0 length" case */
0360         if (!length)
0361             break;
0362         /*
0363          * Make sure that the status indicates that the device
0364          * wants data as well.
0365          */
0366         if ((fst->Status & DRQ_STAT) == 0 || (fst->Reason & 3) != 2) {
0367             usb_stor_dbg(us, "SCSI wants data, drive doesn't have any\n");
0368             return USB_STOR_TRANSPORT_FAILED;
0369         }
0370         result = freecom_readdata (srb, us, ipipe, opipe, length);
0371         if (result != USB_STOR_TRANSPORT_GOOD)
0372             return result;
0373 
0374         usb_stor_dbg(us, "Waiting for status\n");
0375         result = usb_stor_bulk_transfer_buf (us, ipipe, fst,
0376                 FCM_PACKET_LENGTH, &partial);
0377         US_DEBUG(pdump(us, (void *)fst, partial));
0378 
0379         if (partial != 4 || result > USB_STOR_XFER_SHORT)
0380             return USB_STOR_TRANSPORT_ERROR;
0381         if ((fst->Status & ERR_STAT) != 0) {
0382             usb_stor_dbg(us, "operation failed\n");
0383             return USB_STOR_TRANSPORT_FAILED;
0384         }
0385         if ((fst->Reason & 3) != 3) {
0386             usb_stor_dbg(us, "Drive seems still hungry\n");
0387             return USB_STOR_TRANSPORT_FAILED;
0388         }
0389         usb_stor_dbg(us, "Transfer happy\n");
0390         break;
0391 
0392     case DMA_TO_DEVICE:
0393         /* catch bogus "write 0 length" case */
0394         if (!length)
0395             break;
0396         /*
0397          * Make sure the status indicates that the device wants to
0398          * send us data.
0399          */
0400         /* !!IMPLEMENT!! */
0401         result = freecom_writedata (srb, us, ipipe, opipe, length);
0402         if (result != USB_STOR_TRANSPORT_GOOD)
0403             return result;
0404 
0405         usb_stor_dbg(us, "Waiting for status\n");
0406         result = usb_stor_bulk_transfer_buf (us, ipipe, fst,
0407                 FCM_PACKET_LENGTH, &partial);
0408 
0409         if (partial != 4 || result > USB_STOR_XFER_SHORT)
0410             return USB_STOR_TRANSPORT_ERROR;
0411         if ((fst->Status & ERR_STAT) != 0) {
0412             usb_stor_dbg(us, "operation failed\n");
0413             return USB_STOR_TRANSPORT_FAILED;
0414         }
0415         if ((fst->Reason & 3) != 3) {
0416             usb_stor_dbg(us, "Drive seems still hungry\n");
0417             return USB_STOR_TRANSPORT_FAILED;
0418         }
0419 
0420         usb_stor_dbg(us, "Transfer happy\n");
0421         break;
0422 
0423 
0424     case DMA_NONE:
0425         /* Easy, do nothing. */
0426         break;
0427 
0428     default:
0429         /* should never hit here -- filtered in usb.c */
0430         usb_stor_dbg(us, "freecom unimplemented direction: %d\n",
0431                  us->srb->sc_data_direction);
0432         /* Return fail, SCSI seems to handle this better. */
0433         return USB_STOR_TRANSPORT_FAILED;
0434     }
0435 
0436     return USB_STOR_TRANSPORT_GOOD;
0437 }
0438 
0439 static int init_freecom(struct us_data *us)
0440 {
0441     int result;
0442     char *buffer = us->iobuf;
0443 
0444     /*
0445      * The DMA-mapped I/O buffer is 64 bytes long, just right for
0446      * all our packets.  No need to allocate any extra buffer space.
0447      */
0448 
0449     result = usb_stor_control_msg(us, us->recv_ctrl_pipe,
0450             0x4c, 0xc0, 0x4346, 0x0, buffer, 0x20, 3*HZ);
0451     buffer[32] = '\0';
0452     usb_stor_dbg(us, "String returned from FC init is: %s\n", buffer);
0453 
0454     /*
0455      * Special thanks to the people at Freecom for providing me with
0456      * this "magic sequence", which they use in their Windows and MacOS
0457      * drivers to make sure that all the attached perhiperals are
0458      * properly reset.
0459      */
0460 
0461     /* send reset */
0462     result = usb_stor_control_msg(us, us->send_ctrl_pipe,
0463             0x4d, 0x40, 0x24d8, 0x0, NULL, 0x0, 3*HZ);
0464     usb_stor_dbg(us, "result from activate reset is %d\n", result);
0465 
0466     /* wait 250ms */
0467     msleep(250);
0468 
0469     /* clear reset */
0470     result = usb_stor_control_msg(us, us->send_ctrl_pipe,
0471             0x4d, 0x40, 0x24f8, 0x0, NULL, 0x0, 3*HZ);
0472     usb_stor_dbg(us, "result from clear reset is %d\n", result);
0473 
0474     /* wait 3 seconds */
0475     msleep(3 * 1000);
0476 
0477     return USB_STOR_TRANSPORT_GOOD;
0478 }
0479 
0480 static int usb_stor_freecom_reset(struct us_data *us)
0481 {
0482     printk (KERN_CRIT "freecom reset called\n");
0483 
0484     /* We don't really have this feature. */
0485     return FAILED;
0486 }
0487 
0488 #ifdef CONFIG_USB_STORAGE_DEBUG
0489 static void pdump(struct us_data *us, void *ibuffer, int length)
0490 {
0491     static char line[80];
0492     int offset = 0;
0493     unsigned char *buffer = (unsigned char *) ibuffer;
0494     int i, j;
0495     int from, base;
0496 
0497     offset = 0;
0498     for (i = 0; i < length; i++) {
0499         if ((i & 15) == 0) {
0500             if (i > 0) {
0501                 offset += sprintf (line+offset, " - ");
0502                 for (j = i - 16; j < i; j++) {
0503                     if (buffer[j] >= 32 && buffer[j] <= 126)
0504                         line[offset++] = buffer[j];
0505                     else
0506                         line[offset++] = '.';
0507                 }
0508                 line[offset] = 0;
0509                 usb_stor_dbg(us, "%s\n", line);
0510                 offset = 0;
0511             }
0512             offset += sprintf (line+offset, "%08x:", i);
0513         } else if ((i & 7) == 0) {
0514             offset += sprintf (line+offset, " -");
0515         }
0516         offset += sprintf (line+offset, " %02x", buffer[i] & 0xff);
0517     }
0518 
0519     /* Add the last "chunk" of data. */
0520     from = (length - 1) % 16;
0521     base = ((length - 1) / 16) * 16;
0522 
0523     for (i = from + 1; i < 16; i++)
0524         offset += sprintf (line+offset, "   ");
0525     if (from < 8)
0526         offset += sprintf (line+offset, "  ");
0527     offset += sprintf (line+offset, " - ");
0528 
0529     for (i = 0; i <= from; i++) {
0530         if (buffer[base+i] >= 32 && buffer[base+i] <= 126)
0531             line[offset++] = buffer[base+i];
0532         else
0533             line[offset++] = '.';
0534     }
0535     line[offset] = 0;
0536     usb_stor_dbg(us, "%s\n", line);
0537     offset = 0;
0538 }
0539 #endif
0540 
0541 static struct scsi_host_template freecom_host_template;
0542 
0543 static int freecom_probe(struct usb_interface *intf,
0544              const struct usb_device_id *id)
0545 {
0546     struct us_data *us;
0547     int result;
0548 
0549     result = usb_stor_probe1(&us, intf, id,
0550             (id - freecom_usb_ids) + freecom_unusual_dev_list,
0551             &freecom_host_template);
0552     if (result)
0553         return result;
0554 
0555     us->transport_name = "Freecom";
0556     us->transport = freecom_transport;
0557     us->transport_reset = usb_stor_freecom_reset;
0558     us->max_lun = 0;
0559 
0560     result = usb_stor_probe2(us);
0561     return result;
0562 }
0563 
0564 static struct usb_driver freecom_driver = {
0565     .name =     DRV_NAME,
0566     .probe =    freecom_probe,
0567     .disconnect =   usb_stor_disconnect,
0568     .suspend =  usb_stor_suspend,
0569     .resume =   usb_stor_resume,
0570     .reset_resume = usb_stor_reset_resume,
0571     .pre_reset =    usb_stor_pre_reset,
0572     .post_reset =   usb_stor_post_reset,
0573     .id_table = freecom_usb_ids,
0574     .soft_unbind =  1,
0575     .no_dynamic_id = 1,
0576 };
0577 
0578 module_usb_stor_driver(freecom_driver, freecom_host_template, DRV_NAME);