1 /* Driver for Realtek RTS51xx USB card reader
3 * Copyright(c) 2009 Realtek Semiconductor Corp. All rights reserved.
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2, or (at your option) any
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, see <http://www.gnu.org/licenses/>.
19 * wwang (wei_wang@realsil.com.cn)
20 * No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China
22 * Edwin Rong (edwin_rong@realsil.com.cn)
23 * No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China
28 #ifdef SUPPORT_FILE_OP
30 #include <linux/types.h>
31 #include <linux/stat.h>
32 #include <linux/kref.h>
33 #include <linux/slab.h>
35 #include "rts51x_chip.h"
36 #include "rts51x_card.h"
37 #include "rts51x_fop.h"
40 #define RTS5139_IOC_MAGIC 0x39
42 #define RTS5139_IOC_SD_DIRECT _IOWR(RTS5139_IOC_MAGIC, 0xA0, int)
43 #define RTS5139_IOC_SD_GET_RSP _IOWR(RTS5139_IOC_MAGIC, 0xA1, int)
45 static int rts51x_sd_direct_cmnd(struct rts51x_chip *chip,
46 struct sd_direct_cmnd *cmnd)
49 u8 dir, cmd12, standby, acmd, cmd_idx, rsp_code;
53 dir = (cmnd->cmnd[0] >> 3) & 0x03;
54 cmd12 = (cmnd->cmnd[0] >> 2) & 0x01;
55 standby = (cmnd->cmnd[0] >> 1) & 0x01;
56 acmd = cmnd->cmnd[0] & 0x01;
57 cmd_idx = cmnd->cmnd[1];
58 arg = ((u32) (cmnd->cmnd[2]) << 24) | ((u32) (cmnd->cmnd[3]) << 16) |
59 ((u32) (cmnd->cmnd[4]) << 8) | cmnd->cmnd[5];
61 ((u32) (cmnd->cmnd[6]) << 16) | ((u32) (cmnd->cmnd[7]) << 8) |
63 rsp_code = cmnd->cmnd[9];
66 if (!cmnd->buf || (cmnd->buf_len < len))
67 TRACE_RET(chip, STATUS_FAIL);
73 retval = ext_sd_execute_no_data(chip, chip->card2lun[SD_CARD],
74 cmd_idx, standby, acmd,
76 if (retval != TRANSPORT_GOOD)
77 TRACE_RET(chip, STATUS_FAIL);
82 buf = kmalloc(cmnd->buf_len, GFP_KERNEL);
84 TRACE_RET(chip, STATUS_NOMEM);
86 retval = ext_sd_execute_read_data(chip, chip->card2lun[SD_CARD],
87 cmd_idx, cmd12, standby, acmd,
88 rsp_code, arg, len, buf,
90 if (retval != TRANSPORT_GOOD) {
92 TRACE_RET(chip, STATUS_FAIL);
96 copy_to_user((void *)cmnd->buf, (void *)buf, cmnd->buf_len);
99 TRACE_RET(chip, STATUS_NOMEM);
107 buf = kmalloc(cmnd->buf_len, GFP_KERNEL);
109 TRACE_RET(chip, STATUS_NOMEM);
112 copy_from_user((void *)buf, (void *)cmnd->buf,
116 TRACE_RET(chip, STATUS_NOMEM);
120 ext_sd_execute_write_data(chip, chip->card2lun[SD_CARD],
121 cmd_idx, cmd12, standby, acmd,
122 rsp_code, arg, len, buf,
124 if (retval != TRANSPORT_GOOD) {
126 TRACE_RET(chip, STATUS_FAIL);
134 TRACE_RET(chip, STATUS_FAIL);
137 return STATUS_SUCCESS;
140 static int rts51x_sd_get_rsp(struct rts51x_chip *chip, struct sd_rsp *rsp)
142 struct sd_info *sd_card = &(chip->sd_card);
143 int count = 0, retval;
145 if (sd_card->pre_cmd_err) {
146 sd_card->pre_cmd_err = 0;
147 TRACE_RET(chip, STATUS_FAIL);
150 if (sd_card->last_rsp_type == SD_RSP_TYPE_R0)
151 TRACE_RET(chip, STATUS_FAIL);
152 else if (sd_card->last_rsp_type == SD_RSP_TYPE_R2)
153 count = (rsp->rsp_len < 17) ? rsp->rsp_len : 17;
155 count = (rsp->rsp_len < 6) ? rsp->rsp_len : 6;
157 retval = copy_to_user((void *)rsp->rsp, (void *)sd_card->rsp, count);
159 TRACE_RET(chip, STATUS_NOMEM);
161 RTS51X_DEBUGP("Response length: %d\n", count);
162 RTS51X_DEBUGP("Response: 0x%x 0x%x 0x%x 0x%x\n",
163 sd_card->rsp[0], sd_card->rsp[1], sd_card->rsp[2],
166 return STATUS_SUCCESS;
169 int rts51x_open(struct inode *inode, struct file *filp)
171 struct rts51x_chip *chip;
172 struct usb_interface *interface;
176 subminor = iminor(inode);
178 interface = usb_find_interface(&rts51x_driver, subminor);
180 RTS51X_DEBUGP("%s - error, can't find device for minor %d\n",
186 chip = (struct rts51x_chip *)usb_get_intfdata(interface);
188 RTS51X_DEBUGP("Can't find chip\n");
193 /* Increase our reference to the host */
194 scsi_host_get(rts51x_to_host(chip));
196 /* lock the device pointers */
197 mutex_lock(&(chip->usb->dev_mutex));
199 /* save our object in the file's private structure */
200 filp->private_data = chip;
202 /* unlock the device pointers */
203 mutex_unlock(&chip->usb->dev_mutex);
209 int rts51x_release(struct inode *inode, struct file *filp)
211 struct rts51x_chip *chip;
213 chip = (struct rts51x_chip *)filp->private_data;
217 /* Drop our reference to the host; the SCSI core will free it
218 * (and "chip" along with it) when the refcount becomes 0. */
219 scsi_host_put(rts51x_to_host(chip));
224 ssize_t rts51x_read(struct file *filp, char __user *buf, size_t count,
230 ssize_t rts51x_write(struct file *filp, const char __user *buf, size_t count,
236 long rts51x_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
238 struct rts51x_chip *chip;
239 struct sd_direct_cmnd cmnd;
243 chip = (struct rts51x_chip *)filp->private_data;
247 /* lock the device pointers */
248 mutex_lock(&(chip->usb->dev_mutex));
251 case RTS5139_IOC_SD_DIRECT:
253 copy_from_user((void *)&cmnd, (void *)arg,
254 sizeof(struct sd_direct_cmnd));
257 TRACE_GOTO(chip, exit);
259 retval = rts51x_sd_direct_cmnd(chip, &cmnd);
260 if (retval != STATUS_SUCCESS) {
262 TRACE_GOTO(chip, exit);
266 case RTS5139_IOC_SD_GET_RSP:
268 copy_from_user((void *)&rsp, (void *)arg,
269 sizeof(struct sd_rsp));
272 TRACE_GOTO(chip, exit);
274 retval = rts51x_sd_get_rsp(chip, &rsp);
275 if (retval != STATUS_SUCCESS) {
277 TRACE_GOTO(chip, exit);
286 /* unlock the device pointers */
287 mutex_unlock(&chip->usb->dev_mutex);