Linux-libre 3.6.3-gnu1
[librecmc/linux-libre.git] / drivers / staging / rts5139 / rts51x_fop.c
1 /* Driver for Realtek RTS51xx USB card reader
2  *
3  * Copyright(c) 2009 Realtek Semiconductor Corp. All rights reserved.
4  *
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
8  * later version.
9  *
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.
14  *
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/>.
17  *
18  * Author:
19  *   wwang (wei_wang@realsil.com.cn)
20  *   No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China
21  * Maintainer:
22  *   Edwin Rong (edwin_rong@realsil.com.cn)
23  *   No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China
24  */
25
26 #include "rts51x.h"
27
28 #ifdef SUPPORT_FILE_OP
29
30 #include <linux/types.h>
31 #include <linux/stat.h>
32 #include <linux/kref.h>
33 #include <linux/slab.h>
34
35 #include "rts51x_chip.h"
36 #include "rts51x_card.h"
37 #include "rts51x_fop.h"
38 #include "sd_cprm.h"
39
40 #define RTS5139_IOC_MAGIC               0x39
41
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)
44
45 static int rts51x_sd_direct_cmnd(struct rts51x_chip *chip,
46                                  struct sd_direct_cmnd *cmnd)
47 {
48         int retval;
49         u8 dir, cmd12, standby, acmd, cmd_idx, rsp_code;
50         u8 *buf;
51         u32 arg, len;
52
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];
60         len =
61             ((u32) (cmnd->cmnd[6]) << 16) | ((u32) (cmnd->cmnd[7]) << 8) |
62             cmnd->cmnd[8];
63         rsp_code = cmnd->cmnd[9];
64
65         if (dir) {
66                 if (!cmnd->buf || (cmnd->buf_len < len))
67                         TRACE_RET(chip, STATUS_FAIL);
68         }
69
70         switch (dir) {
71         case 0:
72                 /* No data */
73                 retval = ext_sd_execute_no_data(chip, chip->card2lun[SD_CARD],
74                                                 cmd_idx, standby, acmd,
75                                                 rsp_code, arg);
76                 if (retval != TRANSPORT_GOOD)
77                         TRACE_RET(chip, STATUS_FAIL);
78                 break;
79
80         case 1:
81                 /* Read from card */
82                 buf = kmalloc(cmnd->buf_len, GFP_KERNEL);
83                 if (!buf)
84                         TRACE_RET(chip, STATUS_NOMEM);
85
86                 retval = ext_sd_execute_read_data(chip, chip->card2lun[SD_CARD],
87                                                   cmd_idx, cmd12, standby, acmd,
88                                                   rsp_code, arg, len, buf,
89                                                   cmnd->buf_len, 0);
90                 if (retval != TRANSPORT_GOOD) {
91                         kfree(buf);
92                         TRACE_RET(chip, STATUS_FAIL);
93                 }
94
95                 retval =
96                     copy_to_user((void *)cmnd->buf, (void *)buf, cmnd->buf_len);
97                 if (retval) {
98                         kfree(buf);
99                         TRACE_RET(chip, STATUS_NOMEM);
100                 }
101
102                 kfree(buf);
103                 break;
104
105         case 2:
106                 /* Write to card */
107                 buf = kmalloc(cmnd->buf_len, GFP_KERNEL);
108                 if (!buf)
109                         TRACE_RET(chip, STATUS_NOMEM);
110
111                 retval =
112                     copy_from_user((void *)buf, (void *)cmnd->buf,
113                                    cmnd->buf_len);
114                 if (retval) {
115                         kfree(buf);
116                         TRACE_RET(chip, STATUS_NOMEM);
117                 }
118
119                 retval =
120                     ext_sd_execute_write_data(chip, chip->card2lun[SD_CARD],
121                                               cmd_idx, cmd12, standby, acmd,
122                                               rsp_code, arg, len, buf,
123                                               cmnd->buf_len, 0);
124                 if (retval != TRANSPORT_GOOD) {
125                         kfree(buf);
126                         TRACE_RET(chip, STATUS_FAIL);
127                 }
128
129                 kfree(buf);
130
131                 break;
132
133         default:
134                 TRACE_RET(chip, STATUS_FAIL);
135         }
136
137         return STATUS_SUCCESS;
138 }
139
140 static int rts51x_sd_get_rsp(struct rts51x_chip *chip, struct sd_rsp *rsp)
141 {
142         struct sd_info *sd_card = &(chip->sd_card);
143         int count = 0, retval;
144
145         if (sd_card->pre_cmd_err) {
146                 sd_card->pre_cmd_err = 0;
147                 TRACE_RET(chip, STATUS_FAIL);
148         }
149
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;
154         else
155                 count = (rsp->rsp_len < 6) ? rsp->rsp_len : 6;
156
157         retval = copy_to_user((void *)rsp->rsp, (void *)sd_card->rsp, count);
158         if (retval)
159                 TRACE_RET(chip, STATUS_NOMEM);
160
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],
164                        sd_card->rsp[3]);
165
166         return STATUS_SUCCESS;
167 }
168
169 int rts51x_open(struct inode *inode, struct file *filp)
170 {
171         struct rts51x_chip *chip;
172         struct usb_interface *interface;
173         int subminor;
174         int retval = 0;
175
176         subminor = iminor(inode);
177
178         interface = usb_find_interface(&rts51x_driver, subminor);
179         if (!interface) {
180                 RTS51X_DEBUGP("%s - error, can't find device for minor %d\n",
181                                __func__, subminor);
182                 retval = -ENODEV;
183                 goto exit;
184         }
185
186         chip = (struct rts51x_chip *)usb_get_intfdata(interface);
187         if (!chip) {
188                 RTS51X_DEBUGP("Can't find chip\n");
189                 retval = -ENODEV;
190                 goto exit;
191         }
192
193         /* Increase our reference to the host */
194         scsi_host_get(rts51x_to_host(chip));
195
196         /* lock the device pointers */
197         mutex_lock(&(chip->usb->dev_mutex));
198
199         /* save our object in the file's private structure */
200         filp->private_data = chip;
201
202         /* unlock the device pointers */
203         mutex_unlock(&chip->usb->dev_mutex);
204
205 exit:
206         return retval;
207 }
208
209 int rts51x_release(struct inode *inode, struct file *filp)
210 {
211         struct rts51x_chip *chip;
212
213         chip = (struct rts51x_chip *)filp->private_data;
214         if (chip == NULL)
215                 return -ENODEV;
216
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));
220
221         return 0;
222 }
223
224 ssize_t rts51x_read(struct file *filp, char __user *buf, size_t count,
225                     loff_t *f_pos)
226 {
227         return 0;
228 }
229
230 ssize_t rts51x_write(struct file *filp, const char __user *buf, size_t count,
231                      loff_t *f_pos)
232 {
233         return 0;
234 }
235
236 long rts51x_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
237 {
238         struct rts51x_chip *chip;
239         struct sd_direct_cmnd cmnd;
240         struct sd_rsp rsp;
241         int retval = 0;
242
243         chip = (struct rts51x_chip *)filp->private_data;
244         if (chip == NULL)
245                 return -ENODEV;
246
247         /* lock the device pointers */
248         mutex_lock(&(chip->usb->dev_mutex));
249
250         switch (cmd) {
251         case RTS5139_IOC_SD_DIRECT:
252                 retval =
253                     copy_from_user((void *)&cmnd, (void *)arg,
254                                    sizeof(struct sd_direct_cmnd));
255                 if (retval) {
256                         retval = -ENOMEM;
257                         TRACE_GOTO(chip, exit);
258                 }
259                 retval = rts51x_sd_direct_cmnd(chip, &cmnd);
260                 if (retval != STATUS_SUCCESS) {
261                         retval = -EIO;
262                         TRACE_GOTO(chip, exit);
263                 }
264                 break;
265
266         case RTS5139_IOC_SD_GET_RSP:
267                 retval =
268                     copy_from_user((void *)&rsp, (void *)arg,
269                                    sizeof(struct sd_rsp));
270                 if (retval) {
271                         retval = -ENOMEM;
272                         TRACE_GOTO(chip, exit);
273                 }
274                 retval = rts51x_sd_get_rsp(chip, &rsp);
275                 if (retval != STATUS_SUCCESS) {
276                         retval = -EIO;
277                         TRACE_GOTO(chip, exit);
278                 }
279                 break;
280
281         default:
282                 break;
283         }
284
285 exit:
286         /* unlock the device pointers */
287         mutex_unlock(&chip->usb->dev_mutex);
288
289         return retval;
290 }
291
292 #endif