Merge branch 'for_3.6/pm/sr-move' of git://git.kernel.org/pub/scm/linux/kernel/git...
[cascardo/linux.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 #include "rts51x.h"
40
41 #define RTS5139_IOC_MAGIC               0x39
42
43 #define RTS5139_IOC_SD_DIRECT           _IOWR(RTS5139_IOC_MAGIC, 0xA0, int)
44 #define RTS5139_IOC_SD_GET_RSP          _IOWR(RTS5139_IOC_MAGIC, 0xA1, int)
45
46 static int rts51x_sd_direct_cmnd(struct rts51x_chip *chip,
47                                  struct sd_direct_cmnd *cmnd)
48 {
49         int retval;
50         u8 dir, cmd12, standby, acmd, cmd_idx, rsp_code;
51         u8 *buf;
52         u32 arg, len;
53
54         dir = (cmnd->cmnd[0] >> 3) & 0x03;
55         cmd12 = (cmnd->cmnd[0] >> 2) & 0x01;
56         standby = (cmnd->cmnd[0] >> 1) & 0x01;
57         acmd = cmnd->cmnd[0] & 0x01;
58         cmd_idx = cmnd->cmnd[1];
59         arg = ((u32) (cmnd->cmnd[2]) << 24) | ((u32) (cmnd->cmnd[3]) << 16) |
60             ((u32) (cmnd->cmnd[4]) << 8) | cmnd->cmnd[5];
61         len =
62             ((u32) (cmnd->cmnd[6]) << 16) | ((u32) (cmnd->cmnd[7]) << 8) |
63             cmnd->cmnd[8];
64         rsp_code = cmnd->cmnd[9];
65
66         if (dir) {
67                 if (!cmnd->buf || (cmnd->buf_len < len))
68                         TRACE_RET(chip, STATUS_FAIL);
69         }
70
71         switch (dir) {
72         case 0:
73                 /* No data */
74                 retval = ext_sd_execute_no_data(chip, chip->card2lun[SD_CARD],
75                                                 cmd_idx, standby, acmd,
76                                                 rsp_code, arg);
77                 if (retval != TRANSPORT_GOOD)
78                         TRACE_RET(chip, STATUS_FAIL);
79                 break;
80
81         case 1:
82                 /* Read from card */
83                 buf = kmalloc(cmnd->buf_len, GFP_KERNEL);
84                 if (!buf)
85                         TRACE_RET(chip, STATUS_NOMEM);
86
87                 retval = ext_sd_execute_read_data(chip, chip->card2lun[SD_CARD],
88                                                   cmd_idx, cmd12, standby, acmd,
89                                                   rsp_code, arg, len, buf,
90                                                   cmnd->buf_len, 0);
91                 if (retval != TRANSPORT_GOOD) {
92                         kfree(buf);
93                         TRACE_RET(chip, STATUS_FAIL);
94                 }
95
96                 retval =
97                     copy_to_user((void *)cmnd->buf, (void *)buf, cmnd->buf_len);
98                 if (retval) {
99                         kfree(buf);
100                         TRACE_RET(chip, STATUS_NOMEM);
101                 }
102
103                 kfree(buf);
104                 break;
105
106         case 2:
107                 /* Write to card */
108                 buf = kmalloc(cmnd->buf_len, GFP_KERNEL);
109                 if (!buf)
110                         TRACE_RET(chip, STATUS_NOMEM);
111
112                 retval =
113                     copy_from_user((void *)buf, (void *)cmnd->buf,
114                                    cmnd->buf_len);
115                 if (retval) {
116                         kfree(buf);
117                         TRACE_RET(chip, STATUS_NOMEM);
118                 }
119
120                 retval =
121                     ext_sd_execute_write_data(chip, chip->card2lun[SD_CARD],
122                                               cmd_idx, cmd12, standby, acmd,
123                                               rsp_code, arg, len, buf,
124                                               cmnd->buf_len, 0);
125                 if (retval != TRANSPORT_GOOD) {
126                         kfree(buf);
127                         TRACE_RET(chip, STATUS_FAIL);
128                 }
129
130                 kfree(buf);
131
132                 break;
133
134         default:
135                 TRACE_RET(chip, STATUS_FAIL);
136         }
137
138         return STATUS_SUCCESS;
139 }
140
141 static int rts51x_sd_get_rsp(struct rts51x_chip *chip, struct sd_rsp *rsp)
142 {
143         struct sd_info *sd_card = &(chip->sd_card);
144         int count = 0, retval;
145
146         if (sd_card->pre_cmd_err) {
147                 sd_card->pre_cmd_err = 0;
148                 TRACE_RET(chip, STATUS_FAIL);
149         }
150
151         if (sd_card->last_rsp_type == SD_RSP_TYPE_R0)
152                 TRACE_RET(chip, STATUS_FAIL);
153         else if (sd_card->last_rsp_type == SD_RSP_TYPE_R2)
154                 count = (rsp->rsp_len < 17) ? rsp->rsp_len : 17;
155         else
156                 count = (rsp->rsp_len < 6) ? rsp->rsp_len : 6;
157
158         retval = copy_to_user((void *)rsp->rsp, (void *)sd_card->rsp, count);
159         if (retval)
160                 TRACE_RET(chip, STATUS_NOMEM);
161
162         RTS51X_DEBUGP("Response length: %d\n", count);
163         RTS51X_DEBUGP("Response: 0x%x 0x%x 0x%x 0x%x\n",
164                        sd_card->rsp[0], sd_card->rsp[1], sd_card->rsp[2],
165                        sd_card->rsp[3]);
166
167         return STATUS_SUCCESS;
168 }
169
170 int rts51x_open(struct inode *inode, struct file *filp)
171 {
172         struct rts51x_chip *chip;
173         struct usb_interface *interface;
174         int subminor;
175         int retval = 0;
176
177         subminor = iminor(inode);
178
179         interface = usb_find_interface(&rts51x_driver, subminor);
180         if (!interface) {
181                 RTS51X_DEBUGP("%s - error, can't find device for minor %d\n",
182                                __func__, subminor);
183                 retval = -ENODEV;
184                 goto exit;
185         }
186
187         chip = (struct rts51x_chip *)usb_get_intfdata(interface);
188         if (!chip) {
189                 RTS51X_DEBUGP("Can't find chip\n");
190                 retval = -ENODEV;
191                 goto exit;
192         }
193
194         /* Increase our reference to the host */
195         scsi_host_get(rts51x_to_host(chip));
196
197         /* lock the device pointers */
198         mutex_lock(&(chip->usb->dev_mutex));
199
200         /* save our object in the file's private structure */
201         filp->private_data = chip;
202
203         /* unlock the device pointers */
204         mutex_unlock(&chip->usb->dev_mutex);
205
206 exit:
207         return retval;
208 }
209
210 int rts51x_release(struct inode *inode, struct file *filp)
211 {
212         struct rts51x_chip *chip;
213
214         chip = (struct rts51x_chip *)filp->private_data;
215         if (chip == NULL)
216                 return -ENODEV;
217
218         /* Drop our reference to the host; the SCSI core will free it
219          * (and "chip" along with it) when the refcount becomes 0. */
220         scsi_host_put(rts51x_to_host(chip));
221
222         return 0;
223 }
224
225 ssize_t rts51x_read(struct file *filp, char __user *buf, size_t count,
226                     loff_t *f_pos)
227 {
228         return 0;
229 }
230
231 ssize_t rts51x_write(struct file *filp, const char __user *buf, size_t count,
232                      loff_t *f_pos)
233 {
234         return 0;
235 }
236
237 long rts51x_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
238 {
239         struct rts51x_chip *chip;
240         struct sd_direct_cmnd cmnd;
241         struct sd_rsp rsp;
242         int retval = 0;
243
244         chip = (struct rts51x_chip *)filp->private_data;
245         if (chip == NULL)
246                 return -ENODEV;
247
248         /* lock the device pointers */
249         mutex_lock(&(chip->usb->dev_mutex));
250
251         switch (cmd) {
252         case RTS5139_IOC_SD_DIRECT:
253                 retval =
254                     copy_from_user((void *)&cmnd, (void *)arg,
255                                    sizeof(struct sd_direct_cmnd));
256                 if (retval) {
257                         retval = -ENOMEM;
258                         TRACE_GOTO(chip, exit);
259                 }
260                 retval = rts51x_sd_direct_cmnd(chip, &cmnd);
261                 if (retval != STATUS_SUCCESS) {
262                         retval = -EIO;
263                         TRACE_GOTO(chip, exit);
264                 }
265                 break;
266
267         case RTS5139_IOC_SD_GET_RSP:
268                 retval =
269                     copy_from_user((void *)&rsp, (void *)arg,
270                                    sizeof(struct sd_rsp));
271                 if (retval) {
272                         retval = -ENOMEM;
273                         TRACE_GOTO(chip, exit);
274                 }
275                 retval = rts51x_sd_get_rsp(chip, &rsp);
276                 if (retval != STATUS_SUCCESS) {
277                         retval = -EIO;
278                         TRACE_GOTO(chip, exit);
279                 }
280                 break;
281
282         default:
283                 break;
284         }
285
286 exit:
287         /* unlock the device pointers */
288         mutex_unlock(&chip->usb->dev_mutex);
289
290         return retval;
291 }
292
293 #endif