summaryrefslogtreecommitdiffstats
path: root/target/linux/realtek/files/drivers/usb/misc/rts51xx/rts51x_common.c
diff options
context:
space:
mode:
authorRoman Yeryomin <roman@advem.lv>2013-05-17 20:40:24 +0300
committerRoman Yeryomin <roman@advem.lv>2013-05-26 00:48:34 +0300
commit7e810011201bf926cba09ec07424893e4cd8ce67 (patch)
tree202fc7a42607e366848ca59c7a61a8f9fa2712ca /target/linux/realtek/files/drivers/usb/misc/rts51xx/rts51x_common.c
parenta45894b5a0f65585440d98bf71ef3e919c84cb5f (diff)
Move to rsdk 3.2.4. Compiles cleanly.
Signed-off-by: Roman Yeryomin <roman@advem.lv>
Diffstat (limited to 'target/linux/realtek/files/drivers/usb/misc/rts51xx/rts51x_common.c')
-rw-r--r--target/linux/realtek/files/drivers/usb/misc/rts51xx/rts51x_common.c222
1 files changed, 222 insertions, 0 deletions
diff --git a/target/linux/realtek/files/drivers/usb/misc/rts51xx/rts51x_common.c b/target/linux/realtek/files/drivers/usb/misc/rts51xx/rts51x_common.c
new file mode 100644
index 000000000..1922c4cf4
--- /dev/null
+++ b/target/linux/realtek/files/drivers/usb/misc/rts51xx/rts51x_common.c
@@ -0,0 +1,222 @@
+/* Driver for Realtek RTS51xx USB card reader
+ *
+ * Copyright(c) 2009 Realtek Semiconductor Corp. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http:
+ *
+ * Author:
+ * wwang (wei_wang@realsil.com.cn)
+ * No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China
+ */
+
+#include <linux/blkdev.h>
+#include <linux/kthread.h>
+#include <linux/sched.h>
+#include <linux/workqueue.h>
+
+#include "timestamp.h"
+#include "rts51x.h"
+#include "rts51x_chip.h"
+
+/***********************************************************************
+ * Host functions
+ ***********************************************************************/
+
+const char* host_info(struct Scsi_Host *host)
+{
+ return "SCSI emulation for RTS51xx USB driver-based card reader";
+}
+
+int slave_alloc (struct scsi_device *sdev)
+{
+ /*
+ * Set the INQUIRY transfer length to 36. We don't use any of
+ * the extra data and many devices choke if asked for more or
+ * less than 36 bytes.
+ */
+ sdev->inquiry_len = 36;
+ return 0;
+}
+
+int slave_configure(struct scsi_device *sdev)
+{
+ /* Scatter-gather buffers (all but the last) must have a length
+ * divisible by the bulk maxpacket size. Otherwise a data packet
+ * would end up being short, causing a premature end to the data
+ * transfer. Since high-speed bulk pipes have a maxpacket size
+ * of 512, we'll use that as the scsi device queue's DMA alignment
+ * mask. Guaranteeing proper alignment of the first buffer will
+ * have the desired effect because, except at the beginning and
+ * the end, scatter-gather buffers follow page boundaries. */
+ blk_queue_dma_alignment(sdev->request_queue, (512 - 1));
+
+ /* Set the SCSI level to at least 2. We'll leave it at 3 if that's
+ * what is originally reported. We need this to avoid confusing
+ * the SCSI layer with devices that report 0 or 1, but need 10-byte
+ * commands (ala ATAPI devices behind certain bridges, or devices
+ * which simply have broken INQUIRY data).
+ *
+ * NOTE: This means /dev/sg programs (ala cdrecord) will get the
+ * actual information. This seems to be the preference for
+ * programs like that.
+ *
+ * NOTE: This also means that /proc/scsi/scsi and sysfs may report
+ * the actual value or the modified one, depending on where the
+ * data comes from.
+ */
+ if (sdev->scsi_level < SCSI_2)
+ sdev->scsi_level = sdev->sdev_target->scsi_level = SCSI_2;
+
+ return 0;
+}
+
+
+/***********************************************************************
+ * /proc/scsi/ functions
+ ***********************************************************************/
+
+
+#undef SPRINTF
+#define SPRINTF(args...) \
+ do { if (pos < buffer+length) pos += sprintf(pos, ## args); } while (0)
+
+int proc_info (struct Scsi_Host *host, char *buffer,
+ char **start, off_t offset, int length, int inout)
+{
+ char *pos = buffer;
+
+
+ if (inout)
+ return length;
+
+
+ SPRINTF(" Host scsi%d: %s\n", host->host_no, RTS51X_NAME);
+
+
+ SPRINTF(" Vendor: Realtek Corp.\n");
+ SPRINTF(" Product: RTS51xx USB Card Reader\n");
+ SPRINTF(" Version: %s\n", DRIVER_VERSION);
+ SPRINTF(" Build: %s\n", DRIVER_MAKE_TIME);
+
+ /*
+ * Calculate start of next buffer, and return value.
+ */
+ *start = buffer + offset;
+
+ if ((pos - buffer) < offset)
+ return (0);
+ else if ((pos - buffer - offset) < length)
+ return (pos - buffer - offset);
+ else
+ return (length);
+}
+
+
+
+int queuecommand_lck(struct scsi_cmnd *srb,
+ void (*done)(struct scsi_cmnd *))
+{
+ struct rts51x_chip *chip = host_to_rts51x(srb->device->host);
+
+
+ if (chip->srb != NULL) {
+ RTS51X_DEBUGP(("Error in %s: chip->srb = %p\n",
+ __FUNCTION__, chip->srb));
+ return SCSI_MLQUEUE_HOST_BUSY;
+ }
+
+
+ if (test_bit(FLIDX_DISCONNECTING, &chip->usb->dflags)) {
+ RTS51X_DEBUGP(("Fail command during disconnect\n"));
+ srb->result = DID_NO_CONNECT << 16;
+ done(srb);
+ return 0;
+ }
+
+
+ srb->scsi_done = done;
+ chip->srb = srb;
+ complete(&chip->usb->cmnd_ready);
+
+ return 0;
+}
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 37)
+int queuecommand(struct scsi_cmnd *srb,
+ void (*done)(struct scsi_cmnd *))
+{
+ return queuecommand_lck(srb, done);
+}
+#else
+DEF_SCSI_QCMD(queuecommand)
+#endif
+
+/***********************************************************************
+ * Error handling functions
+ ***********************************************************************/
+
+
+int command_abort(struct scsi_cmnd *srb)
+{
+ struct rts51x_chip *chip = host_to_rts51x(srb->device->host);
+
+ RTS51X_DEBUGP(("%s called\n", __func__));
+
+ /* us->srb together with the TIMED_OUT, RESETTING, and ABORTING
+ * bits are protected by the host lock. */
+ scsi_lock(rts51x_to_host(chip));
+
+
+ if (chip->srb != srb) {
+ scsi_unlock(rts51x_to_host(chip));
+ RTS51X_DEBUGP(("-- nothing to abort\n"));
+ return FAILED;
+ }
+
+ /* Set the TIMED_OUT bit. Also set the ABORTING bit, but only if
+ * a device reset isn't already in progress (to avoid interfering
+ * with the reset). Note that we must retain the host lock while
+ * calling usb_stor_stop_transport(); otherwise it might interfere
+ * with an auto-reset that begins as soon as we release the lock. */
+ set_bit(FLIDX_TIMED_OUT, &chip->usb->dflags);
+ if (!test_bit(FLIDX_RESETTING, &chip->usb->dflags)) {
+ set_bit(FLIDX_ABORTING, &chip->usb->dflags);
+ }
+ scsi_unlock(rts51x_to_host(chip));
+
+
+ wait_for_completion(&chip->usb->notify);
+ return SUCCESS;
+}
+
+/* This invokes the transport reset mechanism to reset the state of the
+ * device */
+int device_reset(struct scsi_cmnd *srb)
+{
+ int result = 0;
+
+ RTS51X_DEBUGP(("%s called\n", __FUNCTION__));
+
+ return result < 0 ? FAILED : SUCCESS;
+}
+
+
+int bus_reset(struct scsi_cmnd *srb)
+{
+ int result = 0;
+
+ RTS51X_DEBUGP(("%s called\n", __FUNCTION__));
+
+ return result < 0 ? FAILED : SUCCESS;
+}