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        if (*prev)
 266                return -EINVAL;
 267
 268        do {
 269                unsigned char tpl_code, tpl_link;
 270
 271                ret = mmc_io_rw_direct(card, 0, 0, ptr++, 0, &tpl_code);
 272                if (ret)
 273                        break;
 274
 275                /* 0xff means we're done */
 276                if (tpl_code == 0xff)
 277                        break;
 278
 279                /* null entries have no link field or data */
 280                if (tpl_code == 0x00)
 281                        continue;
 282
 283                ret = mmc_io_rw_direct(card, 0, 0, ptr++, 0, &tpl_link);
 284                if (ret)
 285                        break;
 286
 287                /* a size of 0xff also means we're done */
 288                if (tpl_link == 0xff)
 289                        break;
 290
 291                this = kmalloc(sizeof(*this) + tpl_link, GFP_KERNEL);
 292                if (!this)
 293                        return -ENOMEM;
 294
 295                for (i = 0; i < tpl_link; i++) {
 296                        ret = mmc_io_rw_direct(card, 0, 0,
 297                                               ptr + i, 0, &this->data[i]);
 298                        if (ret)
 299                                break;
 300                }
 301                if (ret) {
 302                        kfree(this);
 303                        break;
 304                }
 305
 306                /* Try to parse the CIS tuple */
 307                ret = cis_tpl_parse(card, func, "CIS",
 308                                    cis_tpl_list, ARRAY_SIZE(cis_tpl_list),
 309                                    tpl_code, this->data, tpl_link);
 310                if (ret == -EILSEQ || ret == -ENOENT) {
 311                        /*
 312                         * The tuple is unknown or known but not parsed.
 313                         * Queue the tuple for the function driver.
 314                         */
 315                        this->next = NULL;
 316                        this->code = tpl_code;
 317                        this->size = tpl_link;
 318                        *prev = this;
 319                        prev = &this->next;
 320
 321                        if (ret == -ENOENT) {
 322                                /* warn about unknown tuples */
 323                                pr_warn_ratelimited("%s: queuing unknown"
 324                                       " CIS tuple 0x%02x (%u bytes)\n",
 325                                       mmc_hostname(card->host),
 326                                       tpl_code, tpl_link);
 327                        }
 328
 329                        /* keep on analyzing tuples */
 330                        ret = 0;
 331                } else {
 332                        /*
 333                         * We don't need the tuple anymore if it was
 334                         * successfully parsed by the SDIO core or if it is
 335                         * not going to be queued for a driver.
 336                         */
 337                        kfree(this);
 338                }
 339
 340                ptr += tpl_link;
 341        } while (!ret);
 342
 343        /*
 344         * Link in all unknown tuples found in the common CIS so that
 345         * drivers don't have to go digging in two places.
 346         */
 347        if (func)
 348                *prev = card->tuples;
 349
 350        return ret;
 351}
 352
 353int sdio_read_common_cis(struct mmc_card *card)
 354{
 355        return sdio_read_cis(card, NULL);
 356}
 357
 358void sdio_free_common_cis(struct mmc_card *card)
 359{
 360        struct sdio_func_tuple *tuple, *victim;
 361
 362        tuple = card->tuples;
 363
 364        while (tuple) {
 365                victim = tuple;
 366                tuple = tuple->next;
 367                kfree(victim);
 368        }
 369
 370        card->tuples = NULL;
 371}
 372
 373int sdio_read_func_cis(struct sdio_func *func)
 374{
 375        int ret;
 376
 377        ret = sdio_read_cis(func->card, func);
 378        if (ret)
 379                return ret;
 380
 381        /*
 382         * Since we've linked to tuples in the card structure,
 383         * we must make sure we have a reference to it.
 384         */
 385        get_device(&func->card->dev);
 386
 387        /*
 388         * Vendor/device id is optional for function CIS, so
 389         * copy it from the card structure as needed.
 390         */
 391        if (func->vendor == 0) {
 392                func->vendor = func->card->cis.vendor;
 393                func->device = func->card->cis.device;
 394        }
 395
 396        return 0;
 397}
 398
 399void sdio_free_func_cis(struct sdio_func *func)
 400{
 401        struct sdio_func_tuple *tuple, *victim;
 402
 403        tuple = func->tuples;
 404
 405        while (tuple && tuple != func->card->tuples) {
 406                victim = tuple;
 407                tuple = tuple->next;
 408                kfree(victim);
 409        }
 410
 411        func->tuples = NULL;
 412
 413        /*
 414         * We have now removed the link to the tuples in the
 415         * card structure, so remove the reference.
 416         */
 417        put_device(&func->card->dev);
 418}
 419
 420