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