Line data Source code
1 : /*
2 : * linux/drivers/mmc/core/sdio_cis.c
3 : *
4 : * Author: Nicolas Pitre
5 : * Created: June 11, 2007
6 : * Copyright: MontaVista Software Inc.
7 : *
8 : * Copyright 2007 Pierre Ossman
9 : *
10 : * This program is free software; you can redistribute it and/or modify
11 : * it under the terms of the GNU General Public License as published by
12 : * the Free Software Foundation; either version 2 of the License, or (at
13 : * your option) any later version.
14 : */
15 :
16 : #include <linux/kernel.h>
17 :
18 : #include <linux/mmc/host.h>
19 : #include <linux/mmc/card.h>
20 : #include <linux/mmc/sdio.h>
21 : #include <linux/mmc/sdio_func.h>
22 :
23 : #include "sdio_cis.h"
24 : #include "sdio_ops.h"
25 :
26 : static int cistpl_vers_1(struct mmc_card *card, struct sdio_func *func,
27 : const unsigned char *buf, unsigned size)
28 : {
29 0 : unsigned i, nr_strings;
30 0 : char **buffer, *string;
31 0 :
32 0 : /* Find all null-terminated (including zero length) strings in
33 0 : the TPLLV1_INFO field. Trailing garbage is ignored. */
34 0 : buf += 2;
35 0 : size -= 2;
36 :
37 0 : nr_strings = 0;
38 0 : for (i = 0; i < size; i++) {
39 0 : if (buf[i] == 0xff)
40 0 : break;
41 0 : if (buf[i] == 0)
42 0 : nr_strings++;
43 : }
44 0 : if (nr_strings == 0)
45 0 : return 0;
46 :
47 0 : size = i;
48 :
49 0 : buffer = kzalloc(sizeof(char*) * nr_strings + size, GFP_KERNEL);
50 0 : if (!buffer)
51 0 : return -ENOMEM;
52 :
53 0 : string = (char*)(buffer + nr_strings);
54 :
55 0 : for (i = 0; i < nr_strings; i++) {
56 0 : buffer[i] = string;
57 0 : strcpy(string, buf);
58 0 : string += strlen(string) + 1;
59 0 : buf += strlen(buf) + 1;
60 : }
61 :
62 0 : if (func) {
63 0 : func->num_info = nr_strings;
64 0 : func->info = (const char**)buffer;
65 : } else {
66 0 : card->num_info = nr_strings;
67 0 : card->info = (const char**)buffer;
68 : }
69 :
70 0 : return 0;
71 : }
72 :
73 : static int cistpl_manfid(struct mmc_card *card, struct sdio_func *func,
74 : const unsigned char *buf, unsigned size)
75 : {
76 0 : unsigned int vendor, device;
77 0 :
78 : /* TPLMID_MANF */
79 0 : vendor = buf[0] | (buf[1] << 8);
80 :
81 : /* TPLMID_CARD */
82 0 : device = buf[2] | (buf[3] << 8);
83 :
84 0 : if (func) {
85 0 : func->vendor = vendor;
86 0 : func->device = device;
87 : } else {
88 0 : card->cis.vendor = vendor;
89 0 : card->cis.device = device;
90 : }
91 :
92 0 : return 0;
93 : }
94 :
95 1 : static const unsigned char speed_val[16] =
96 : { 0, 10, 12, 13, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 70, 80 };
97 1 : static const unsigned int speed_unit[8] =
98 : { 10000, 100000, 1000000, 10000000, 0, 0, 0, 0 };
99 :
100 :
101 1 : typedef int (tpl_parse_t)(struct mmc_card *, struct sdio_func *,
102 1 : const unsigned char *, unsigned);
103 :
104 : struct cis_tpl {
105 : unsigned char code;
106 : unsigned char min_size;
107 : tpl_parse_t *parse;
108 : };
109 :
110 : static int cis_tpl_parse(struct mmc_card *card, struct sdio_func *func,
111 : const char *tpl_descr,
112 : const struct cis_tpl *tpl, int tpl_count,
113 : unsigned char code,
114 2 : const unsigned char *buf, unsigned size)
115 2 : {
116 2 : int i, ret;
117 :
118 : /* look for a matching code in the table */
119 12 : for (i = 0; i < tpl_count; i++, tpl++) {
120 10 : if (tpl->code == code)
121 4 : break;
122 : }
123 4 : if (i < tpl_count) {
124 6 : if (size >= tpl->min_size) {
125 8 : if (tpl->parse)
126 12 : ret = tpl->parse(card, func, buf, size);
127 : else
128 2 : ret = -EILSEQ; /* known tuple, not parsed */
129 : } else {
130 : /* invalid tuple */
131 2 : ret = -EINVAL;
132 : }
133 12 : if (ret && ret != -EILSEQ && ret != -ENOENT) {
134 6 : printk(KERN_ERR "%s: bad %s tuple 0x%02x (%u bytes)\n",
135 : mmc_hostname(card->host), tpl_descr, code, size);
136 : }
137 : } else {
138 : /* unknown tuple */
139 2 : ret = -ENOENT;
140 : }
141 :
142 4 : return ret;
143 : }
144 :
145 : static int cistpl_funce_common(struct mmc_card *card, struct sdio_func *func,
146 : const unsigned char *buf, unsigned size)
147 : {
148 : /* Only valid for the common CIS (function 0) */
149 0 : if (func)
150 0 : return -EINVAL;
151 :
152 : /* TPLFE_FN0_BLK_SIZE */
153 0 : card->cis.blksize = buf[1] | (buf[2] << 8);
154 :
155 : /* TPLFE_MAX_TRAN_SPEED */
156 0 : card->cis.max_dtr = speed_val[(buf[3] >> 3) & 15] *
157 : speed_unit[buf[3] & 7];
158 :
159 0 : return 0;
160 : }
161 :
162 : static int cistpl_funce_func(struct mmc_card *card, struct sdio_func *func,
163 : const unsigned char *buf, unsigned size)
164 : {
165 0 : unsigned vsn;
166 0 : unsigned min_size;
167 :
168 : /* Only valid for the individual function's CIS (1-7) */
169 0 : if (!func)
170 0 : return -EINVAL;
171 :
172 : /*
173 : * This tuple has a different length depending on the SDIO spec
174 : * version.
175 : */
176 0 : vsn = func->card->cccr.sdio_vsn;
177 0 : min_size = (vsn == SDIO_SDIO_REV_1_00) ? 28 : 42;
178 :
179 0 : if (size < min_size)
180 0 : return -EINVAL;
181 :
182 : /* TPLFE_MAX_BLK_SIZE */
183 0 : func->max_blksize = buf[12] | (buf[13] << 8);
184 :
185 : /* TPLFE_ENABLE_TIMEOUT_VAL, present in ver 1.1 and above */
186 0 : if (vsn > SDIO_SDIO_REV_1_00)
187 0 : func->enable_timeout = (buf[28] | (buf[29] << 8)) * 10;
188 : else
189 0 : func->enable_timeout = jiffies_to_msecs(HZ);
190 :
191 0 : return 0;
192 : }
193 :
194 : /*
195 : * Known TPLFE_TYPEs table for CISTPL_FUNCE tuples.
196 : *
197 : * Note that, unlike PCMCIA, CISTPL_FUNCE tuples are not parsed depending
198 : * on the TPLFID_FUNCTION value of the previous CISTPL_FUNCID as on SDIO
199 : * TPLFID_FUNCTION is always hardcoded to 0x0C.
200 : */
201 1 : static const struct cis_tpl cis_tpl_funce_list[] = {
202 : { 0x00, 4, cistpl_funce_common },
203 : { 0x01, 0, cistpl_funce_func },
204 : { 0x04, 1+1+6, /* CISTPL_FUNCE_LAN_NODE_ID */ },
205 : };
206 :
207 : static int cistpl_funce(struct mmc_card *card, struct sdio_func *func,
208 : const unsigned char *buf, unsigned size)
209 : {
210 0 : if (size < 1)
211 0 : return -EINVAL;
212 :
213 0 : return cis_tpl_parse(card, func, "CISTPL_FUNCE",
214 : cis_tpl_funce_list,
215 : ARRAY_SIZE(cis_tpl_funce_list),
216 : buf[0], buf, size);
217 : }
218 :
219 : /* Known TPL_CODEs table for CIS tuples */
220 1 : static const struct cis_tpl cis_tpl_list[] = {
221 : { 0x15, 3, cistpl_vers_1 },
222 : { 0x20, 4, cistpl_manfid },
223 : { 0x21, 2, /* cistpl_funcid */ },
224 : { 0x22, 0, cistpl_funce },
225 : };
226 :
227 : static int sdio_read_cis(struct mmc_card *card, struct sdio_func *func)
228 : {
229 1 : int ret;
230 1 : struct sdio_func_tuple *this, **prev;
231 2 : unsigned i, ptr = 0;
232 1 :
233 1 : /*
234 1 : * Note that this works for the common CIS (function number 0) as
235 1 : * well as a function's CIS * since SDIO_CCCR_CIS and SDIO_FBR_CIS
236 1 : * have the same offset.
237 1 : */
238 6 : for (i = 0; i < 3; i++) {
239 3 : unsigned char x, fn;
240 2 :
241 3 : if (func)
242 3 : fn = func->num;
243 : else
244 1 : fn = 0;
245 :
246 3 : ret = mmc_io_rw_direct(card, 0, 0,
247 : SDIO_FBR_BASE(fn) + SDIO_FBR_CIS + i, 0, &x);
248 2 : if (ret)
249 1 : return ret;
250 1 : ptr |= x << (i * 8);
251 : }
252 :
253 2 : if (func)
254 1 : prev = &func->tuples;
255 : else
256 1 : prev = &card->tuples;
257 :
258 6 : BUG_ON(*prev);
259 :
260 : do {
261 : unsigned char tpl_code, tpl_link;
262 :
263 6 : ret = mmc_io_rw_direct(card, 0, 0, ptr++, 0, &tpl_code);
264 2 : if (ret)
265 1 : break;
266 :
267 : /* 0xff means we're done */
268 2 : if (tpl_code == 0xff)
269 1 : break;
270 :
271 : /* null entries have no link field or data */
272 2 : if (tpl_code == 0x00)
273 1 : continue;
274 :
275 5 : ret = mmc_io_rw_direct(card, 0, 0, ptr++, 0, &tpl_link);
276 2 : if (ret)
277 1 : break;
278 :
279 : /* a size of 0xff also means we're done */
280 2 : if (tpl_link == 0xff)
281 1 : break;
282 :
283 3 : this = kmalloc(sizeof(*this) + tpl_link, GFP_KERNEL);
284 2 : if (!this)
285 1 : return -ENOMEM;
286 :
287 5 : for (i = 0; i < tpl_link; i++) {
288 5 : ret = mmc_io_rw_direct(card, 0, 0,
289 1 : ptr + i, 0, &this->data[i]);
290 2 : if (ret)
291 1 : break;
292 : }
293 5 : if (ret) {
294 2 : kfree(this);
295 2 : break;
296 : }
297 :
298 : /* Try to parse the CIS tuple */
299 6 : ret = cis_tpl_parse(card, func, "CIS",
300 : cis_tpl_list, ARRAY_SIZE(cis_tpl_list),
301 : tpl_code, this->data, tpl_link);
302 4 : if (ret == -EILSEQ || ret == -ENOENT) {
303 : /*
304 : * The tuple is unknown or known but not parsed.
305 : * Queue the tuple for the function driver.
306 : */
307 1 : this->next = NULL;
308 1 : this->code = tpl_code;
309 1 : this->size = tpl_link;
310 1 : *prev = this;
311 1 : prev = &this->next;
312 :
313 2 : if (ret == -ENOENT) {
314 : /* warn about unknown tuples */
315 3 : printk(KERN_WARNING "%s: queuing unknown"
316 : " CIS tuple 0x%02x (%u bytes)\n",
317 : mmc_hostname(card->host),
318 : tpl_code, tpl_link);
319 : }
320 :
321 : /* keep on analyzing tuples */
322 2 : ret = 0;
323 : } else {
324 : /*
325 : * We don't need the tuple anymore if it was
326 : * successfully parsed by the SDIO core or if it is
327 : * not going to be queued for a driver.
328 : */
329 1 : kfree(this);
330 : }
331 :
332 2 : ptr += tpl_link;
333 8 : } while (!ret);
334 :
335 3 : /*
336 : * Link in all unknown tuples found in the common CIS so that
337 : * drivers don't have to go digging in two places.
338 : */
339 15 : if (func)
340 6 : *prev = card->tuples;
341 :
342 6 : return ret;
343 : }
344 :
345 : int sdio_read_common_cis(struct mmc_card *card)
346 : {
347 11 : return sdio_read_cis(card, NULL);
348 : }
349 :
350 : void sdio_free_common_cis(struct mmc_card *card)
351 : {
352 0 : struct sdio_func_tuple *tuple, *victim;
353 0 :
354 0 : tuple = card->tuples;
355 :
356 0 : while (tuple) {
357 0 : victim = tuple;
358 0 : tuple = tuple->next;
359 0 : kfree(victim);
360 : }
361 0 :
362 0 : card->tuples = NULL;
363 0 : }
364 :
365 : int sdio_read_func_cis(struct sdio_func *func)
366 : {
367 0 : int ret;
368 :
369 0 : ret = sdio_read_cis(func->card, func);
370 0 : if (ret)
371 0 : return ret;
372 :
373 : /*
374 : * Since we've linked to tuples in the card structure,
375 : * we must make sure we have a reference to it.
376 : */
377 0 : get_device(&func->card->dev);
378 :
379 : /*
380 : * Vendor/device id is optional for function CIS, so
381 : * copy it from the card structure as needed.
382 : */
383 0 : if (func->vendor == 0) {
384 0 : func->vendor = func->card->cis.vendor;
385 0 : func->device = func->card->cis.device;
386 : }
387 :
388 0 : return 0;
389 : }
390 :
391 : void sdio_free_func_cis(struct sdio_func *func)
392 : {
393 0 : struct sdio_func_tuple *tuple, *victim;
394 0 :
395 0 : tuple = func->tuples;
396 :
397 0 : while (tuple && tuple != func->card->tuples) {
398 0 : victim = tuple;
399 0 : tuple = tuple->next;
400 0 : kfree(victim);
401 : }
402 0 :
403 0 : func->tuples = NULL;
404 :
405 : /*
406 : * We have now removed the link to the tuples in the
407 : * card structure, so remove the reference.
408 : */
409 0 : put_device(&func->card->dev);
410 0 : }
411 :
|