1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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
45static 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
73 retval = ext_rts51x_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
82 buf = kzalloc(cmnd->buf_len, GFP_KERNEL);
83 if (!buf)
84 TRACE_RET(chip, STATUS_NOMEM);
85
86 retval = ext_rts51x_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
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_rts51x_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
140static 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
169int 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
194 scsi_host_get(rts51x_to_host(chip));
195
196
197 mutex_lock(&(chip->usb->dev_mutex));
198
199
200 filp->private_data = chip;
201
202
203 mutex_unlock(&chip->usb->dev_mutex);
204
205exit:
206 return retval;
207}
208
209int 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
218
219 scsi_host_put(rts51x_to_host(chip));
220
221 return 0;
222}
223
224ssize_t rts51x_read(struct file *filp, char __user *buf, size_t count,
225 loff_t *f_pos)
226{
227 return 0;
228}
229
230ssize_t rts51x_write(struct file *filp, const char __user *buf, size_t count,
231 loff_t *f_pos)
232{
233 return 0;
234}
235
236long 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
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
285exit:
286
287 mutex_unlock(&chip->usb->dev_mutex);
288
289 return retval;
290}
291
292#endif
293