linux/drivers/pcmcia/pcmcia_cis.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * PCMCIA high-level CIS access functions
   4 *
   5 * The initial developer of the original code is David A. Hinds
   6 * <dahinds@users.sourceforge.net>.  Portions created by David A. Hinds
   7 * are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
   8 *
   9 * Copyright (C) 1999        David A. Hinds
  10 * Copyright (C) 2004-2010   Dominik Brodowski
  11 */
  12
  13#include <linux/slab.h>
  14#include <linux/module.h>
  15#include <linux/kernel.h>
  16#include <linux/netdevice.h>
  17
  18#include <pcmcia/cisreg.h>
  19#include <pcmcia/cistpl.h>
  20#include <pcmcia/ss.h>
  21#include <pcmcia/ds.h>
  22#include "cs_internal.h"
  23
  24
  25/**
  26 * pccard_read_tuple() - internal CIS tuple access
  27 * @s:          the struct pcmcia_socket where the card is inserted
  28 * @function:   the device function we loop for
  29 * @code:       which CIS code shall we look for?
  30 * @parse:      buffer where the tuple shall be parsed (or NULL, if no parse)
  31 *
  32 * pccard_read_tuple() reads out one tuple and attempts to parse it
  33 */
  34int pccard_read_tuple(struct pcmcia_socket *s, unsigned int function,
  35                cisdata_t code, void *parse)
  36{
  37        tuple_t tuple;
  38        cisdata_t *buf;
  39        int ret;
  40
  41        buf = kmalloc(256, GFP_KERNEL);
  42        if (buf == NULL) {
  43                dev_warn(&s->dev, "no memory to read tuple\n");
  44                return -ENOMEM;
  45        }
  46        tuple.DesiredTuple = code;
  47        tuple.Attributes = 0;
  48        if (function == BIND_FN_ALL)
  49                tuple.Attributes = TUPLE_RETURN_COMMON;
  50        ret = pccard_get_first_tuple(s, function, &tuple);
  51        if (ret != 0)
  52                goto done;
  53        tuple.TupleData = buf;
  54        tuple.TupleOffset = 0;
  55        tuple.TupleDataMax = 255;
  56        ret = pccard_get_tuple_data(s, &tuple);
  57        if (ret != 0)
  58                goto done;
  59        ret = pcmcia_parse_tuple(&tuple, parse);
  60done:
  61        kfree(buf);
  62        return ret;
  63}
  64
  65
  66/**
  67 * pccard_loop_tuple() - loop over tuples in the CIS
  68 * @s:          the struct pcmcia_socket where the card is inserted
  69 * @function:   the device function we loop for
  70 * @code:       which CIS code shall we look for?
  71 * @parse:      buffer where the tuple shall be parsed (or NULL, if no parse)
  72 * @priv_data:  private data to be passed to the loop_tuple function.
  73 * @loop_tuple: function to call for each CIS entry of type @function. IT
  74 *              gets passed the raw tuple, the paresed tuple (if @parse is
  75 *              set) and @priv_data.
  76 *
  77 * pccard_loop_tuple() loops over all CIS entries of type @function, and
  78 * calls the @loop_tuple function for each entry. If the call to @loop_tuple
  79 * returns 0, the loop exits. Returns 0 on success or errorcode otherwise.
  80 */
  81static int pccard_loop_tuple(struct pcmcia_socket *s, unsigned int function,
  82                             cisdata_t code, cisparse_t *parse, void *priv_data,
  83                             int (*loop_tuple) (tuple_t *tuple,
  84                                         cisparse_t *parse,
  85                                         void *priv_data))
  86{
  87        tuple_t tuple;
  88        cisdata_t *buf;
  89        int ret;
  90
  91        buf = kzalloc(256, GFP_KERNEL);
  92        if (buf == NULL) {
  93                dev_warn(&s->dev, "no memory to read tuple\n");
  94                return -ENOMEM;
  95        }
  96
  97        tuple.TupleData = buf;
  98        tuple.TupleDataMax = 255;
  99        tuple.TupleOffset = 0;
 100        tuple.DesiredTuple = code;
 101        tuple.Attributes = 0;
 102
 103        ret = pccard_get_first_tuple(s, function, &tuple);
 104        while (!ret) {
 105                if (pccard_get_tuple_data(s, &tuple))
 106                        goto next_entry;
 107
 108                if (parse)
 109                        if (pcmcia_parse_tuple(&tuple, parse))
 110                                goto next_entry;
 111
 112                ret = loop_tuple(&tuple, parse, priv_data);
 113                if (!ret)
 114                        break;
 115
 116next_entry:
 117                ret = pccard_get_next_tuple(s, function, &tuple);
 118        }
 119
 120        kfree(buf);
 121        return ret;
 122}
 123
 124
 125/*
 126 * pcmcia_io_cfg_data_width() - convert cfgtable to data path width parameter
 127 */
 128static int pcmcia_io_cfg_data_width(unsigned int flags)
 129{
 130        if (!(flags & CISTPL_IO_8BIT))
 131                return IO_DATA_PATH_WIDTH_16;
 132        if (!(flags & CISTPL_IO_16BIT))
 133                return IO_DATA_PATH_WIDTH_8;
 134        return IO_DATA_PATH_WIDTH_AUTO;
 135}
 136
 137
 138struct pcmcia_cfg_mem {
 139        struct pcmcia_device *p_dev;
 140        int (*conf_check) (struct pcmcia_device *p_dev, void *priv_data);
 141        void *priv_data;
 142        cisparse_t parse;
 143        cistpl_cftable_entry_t dflt;
 144};
 145
 146/*
 147 * pcmcia_do_loop_config() - internal helper for pcmcia_loop_config()
 148 *
 149 * pcmcia_do_loop_config() is the internal callback for the call from
 150 * pcmcia_loop_config() to pccard_loop_tuple(). Data is transferred
 151 * by a struct pcmcia_cfg_mem.
 152 */
 153static int pcmcia_do_loop_config(tuple_t *tuple, cisparse_t *parse, void *priv)
 154{
 155        struct pcmcia_cfg_mem *cfg_mem = priv;
 156        struct pcmcia_device *p_dev = cfg_mem->p_dev;
 157        cistpl_cftable_entry_t *cfg = &parse->cftable_entry;
 158        cistpl_cftable_entry_t *dflt = &cfg_mem->dflt;
 159        unsigned int flags = p_dev->config_flags;
 160        unsigned int vcc = p_dev->socket->socket.Vcc;
 161
 162        dev_dbg(&p_dev->dev, "testing configuration %x, autoconf %x\n",
 163                cfg->index, flags);
 164
 165        /* default values */
 166        cfg_mem->p_dev->config_index = cfg->index;
 167        if (cfg->flags & CISTPL_CFTABLE_DEFAULT)
 168                cfg_mem->dflt = *cfg;
 169
 170        /* check for matching Vcc? */
 171        if (flags & CONF_AUTO_CHECK_VCC) {
 172                if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) {
 173                        if (vcc != cfg->vcc.param[CISTPL_POWER_VNOM] / 10000)
 174                                return -ENODEV;
 175                } else if (dflt->vcc.present & (1 << CISTPL_POWER_VNOM)) {
 176                        if (vcc != dflt->vcc.param[CISTPL_POWER_VNOM] / 10000)
 177                                return -ENODEV;
 178                }
 179        }
 180
 181        /* set Vpp? */
 182        if (flags & CONF_AUTO_SET_VPP) {
 183                if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM))
 184                        p_dev->vpp = cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
 185                else if (dflt->vpp1.present & (1 << CISTPL_POWER_VNOM))
 186                        p_dev->vpp =
 187                                dflt->vpp1.param[CISTPL_POWER_VNOM] / 10000;
 188        }
 189
 190        /* enable audio? */
 191        if ((flags & CONF_AUTO_AUDIO) && (cfg->flags & CISTPL_CFTABLE_AUDIO))
 192                p_dev->config_flags |= CONF_ENABLE_SPKR;
 193
 194
 195        /* IO window settings? */
 196        if (flags & CONF_AUTO_SET_IO) {
 197                cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
 198                int i = 0;
 199
 200                p_dev->resource[0]->start = p_dev->resource[0]->end = 0;
 201                p_dev->resource[1]->start = p_dev->resource[1]->end = 0;
 202                if (io->nwin == 0)
 203                        return -ENODEV;
 204
 205                p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
 206                p_dev->resource[0]->flags |=
 207                                        pcmcia_io_cfg_data_width(io->flags);
 208                if (io->nwin > 1) {
 209                        /* For multifunction cards, by convention, we
 210                         * configure the network function with window 0,
 211                         * and serial with window 1 */
 212                        i = (io->win[1].len > io->win[0].len);
 213                        p_dev->resource[1]->flags = p_dev->resource[0]->flags;
 214                        p_dev->resource[1]->start = io->win[1-i].base;
 215                        p_dev->resource[1]->end = io->win[1-i].len;
 216                }
 217                p_dev->resource[0]->start = io->win[i].base;
 218                p_dev->resource[0]->end = io->win[i].len;
 219                p_dev->io_lines = io->flags & CISTPL_IO_LINES_MASK;
 220        }
 221
 222        /* MEM window settings? */
 223        if (flags & CONF_AUTO_SET_IOMEM) {
 224                /* so far, we only set one memory window */
 225                cistpl_mem_t *mem = (cfg->mem.nwin) ? &cfg->mem : &dflt->mem;
 226
 227                p_dev->resource[2]->start = p_dev->resource[2]->end = 0;
 228                if (mem->nwin == 0)
 229                        return -ENODEV;
 230
 231                p_dev->resource[2]->start = mem->win[0].host_addr;
 232                p_dev->resource[2]->end = mem->win[0].len;
 233                if (p_dev->resource[2]->end < 0x1000)
 234                        p_dev->resource[2]->end = 0x1000;
 235                p_dev->card_addr = mem->win[0].card_addr;
 236        }
 237
 238        dev_dbg(&p_dev->dev,
 239                "checking configuration %x: %pr %pr %pr (%d lines)\n",
 240                p_dev->config_index, p_dev->resource[0], p_dev->resource[1],
 241                p_dev->resource[2], p_dev->io_lines);
 242
 243        return cfg_mem->conf_check(p_dev, cfg_mem->priv_data);
 244}
 245
 246/**
 247 * pcmcia_loop_config() - loop over configuration options
 248 * @p_dev:      the struct pcmcia_device which we need to loop for.
 249 * @conf_check: function to call for each configuration option.
 250 *              It gets passed the struct pcmcia_device and private data
 251 *              being passed to pcmcia_loop_config()
 252 * @priv_data:  private data to be passed to the conf_check function.
 253 *
 254 * pcmcia_loop_config() loops over all configuration options, and calls
 255 * the driver-specific conf_check() for each one, checking whether
 256 * it is a valid one. Returns 0 on success or errorcode otherwise.
 257 */
 258int pcmcia_loop_config(struct pcmcia_device *p_dev,
 259                       int      (*conf_check)   (struct pcmcia_device *p_dev,
 260                                                 void *priv_data),
 261                       void *priv_data)
 262{
 263        struct pcmcia_cfg_mem *cfg_mem;
 264        int ret;
 265
 266        cfg_mem = kzalloc(sizeof(struct pcmcia_cfg_mem), GFP_KERNEL);
 267        if (cfg_mem == NULL)
 268                return -ENOMEM;
 269
 270        cfg_mem->p_dev = p_dev;
 271        cfg_mem->conf_check = conf_check;
 272        cfg_mem->priv_data = priv_data;
 273
 274        ret = pccard_loop_tuple(p_dev->socket, p_dev->func,
 275                                CISTPL_CFTABLE_ENTRY, &cfg_mem->parse,
 276                                cfg_mem, pcmcia_do_loop_config);
 277
 278        kfree(cfg_mem);
 279        return ret;
 280}
 281EXPORT_SYMBOL(pcmcia_loop_config);
 282
 283
 284struct pcmcia_loop_mem {
 285        struct pcmcia_device *p_dev;
 286        void *priv_data;
 287        int (*loop_tuple) (struct pcmcia_device *p_dev,
 288                           tuple_t *tuple,
 289                           void *priv_data);
 290};
 291
 292/*
 293 * pcmcia_do_loop_tuple() - internal helper for pcmcia_loop_config()
 294 *
 295 * pcmcia_do_loop_tuple() is the internal callback for the call from
 296 * pcmcia_loop_tuple() to pccard_loop_tuple(). Data is transferred
 297 * by a struct pcmcia_cfg_mem.
 298 */
 299static int pcmcia_do_loop_tuple(tuple_t *tuple, cisparse_t *parse, void *priv)
 300{
 301        struct pcmcia_loop_mem *loop = priv;
 302
 303        return loop->loop_tuple(loop->p_dev, tuple, loop->priv_data);
 304};
 305
 306/**
 307 * pcmcia_loop_tuple() - loop over tuples in the CIS
 308 * @p_dev:      the struct pcmcia_device which we need to loop for.
 309 * @code:       which CIS code shall we look for?
 310 * @priv_data:  private data to be passed to the loop_tuple function.
 311 * @loop_tuple: function to call for each CIS entry of type @function. IT
 312 *              gets passed the raw tuple and @priv_data.
 313 *
 314 * pcmcia_loop_tuple() loops over all CIS entries of type @function, and
 315 * calls the @loop_tuple function for each entry. If the call to @loop_tuple
 316 * returns 0, the loop exits. Returns 0 on success or errorcode otherwise.
 317 */
 318int pcmcia_loop_tuple(struct pcmcia_device *p_dev, cisdata_t code,
 319                      int (*loop_tuple) (struct pcmcia_device *p_dev,
 320                                         tuple_t *tuple,
 321                                         void *priv_data),
 322                      void *priv_data)
 323{
 324        struct pcmcia_loop_mem loop = {
 325                .p_dev = p_dev,
 326                .loop_tuple = loop_tuple,
 327                .priv_data = priv_data};
 328
 329        return pccard_loop_tuple(p_dev->socket, p_dev->func, code, NULL,
 330                                 &loop, pcmcia_do_loop_tuple);
 331}
 332EXPORT_SYMBOL(pcmcia_loop_tuple);
 333
 334
 335struct pcmcia_loop_get {
 336        size_t len;
 337        cisdata_t **buf;
 338};
 339
 340/*
 341 * pcmcia_do_get_tuple() - internal helper for pcmcia_get_tuple()
 342 *
 343 * pcmcia_do_get_tuple() is the internal callback for the call from
 344 * pcmcia_get_tuple() to pcmcia_loop_tuple(). As we're only interested in
 345 * the first tuple, return 0 unconditionally. Create a memory buffer large
 346 * enough to hold the content of the tuple, and fill it with the tuple data.
 347 * The caller is responsible to free the buffer.
 348 */
 349static int pcmcia_do_get_tuple(struct pcmcia_device *p_dev, tuple_t *tuple,
 350                               void *priv)
 351{
 352        struct pcmcia_loop_get *get = priv;
 353
 354        *get->buf = kzalloc(tuple->TupleDataLen, GFP_KERNEL);
 355        if (*get->buf) {
 356                get->len = tuple->TupleDataLen;
 357                memcpy(*get->buf, tuple->TupleData, tuple->TupleDataLen);
 358        } else
 359                dev_dbg(&p_dev->dev, "do_get_tuple: out of memory\n");
 360        return 0;
 361}
 362
 363/**
 364 * pcmcia_get_tuple() - get first tuple from CIS
 365 * @p_dev:      the struct pcmcia_device which we need to loop for.
 366 * @code:       which CIS code shall we look for?
 367 * @buf:        pointer to store the buffer to.
 368 *
 369 * pcmcia_get_tuple() gets the content of the first CIS entry of type @code.
 370 * It returns the buffer length (or zero). The caller is responsible to free
 371 * the buffer passed in @buf.
 372 */
 373size_t pcmcia_get_tuple(struct pcmcia_device *p_dev, cisdata_t code,
 374                        unsigned char **buf)
 375{
 376        struct pcmcia_loop_get get = {
 377                .len = 0,
 378                .buf = buf,
 379        };
 380
 381        *get.buf = NULL;
 382        pcmcia_loop_tuple(p_dev, code, pcmcia_do_get_tuple, &get);
 383
 384        return get.len;
 385}
 386EXPORT_SYMBOL(pcmcia_get_tuple);
 387
 388
 389/*
 390 * pcmcia_do_get_mac() - internal helper for pcmcia_get_mac_from_cis()
 391 *
 392 * pcmcia_do_get_mac() is the internal callback for the call from
 393 * pcmcia_get_mac_from_cis() to pcmcia_loop_tuple(). We check whether the
 394 * tuple contains a proper LAN_NODE_ID of length 6, and copy the data
 395 * to struct net_device->dev_addr[i].
 396 */
 397static int pcmcia_do_get_mac(struct pcmcia_device *p_dev, tuple_t *tuple,
 398                             void *priv)
 399{
 400        struct net_device *dev = priv;
 401        int i;
 402
 403        if (tuple->TupleData[0] != CISTPL_FUNCE_LAN_NODE_ID)
 404                return -EINVAL;
 405        if (tuple->TupleDataLen < ETH_ALEN + 2) {
 406                dev_warn(&p_dev->dev, "Invalid CIS tuple length for "
 407                        "LAN_NODE_ID\n");
 408                return -EINVAL;
 409        }
 410
 411        if (tuple->TupleData[1] != ETH_ALEN) {
 412                dev_warn(&p_dev->dev, "Invalid header for LAN_NODE_ID\n");
 413                return -EINVAL;
 414        }
 415        for (i = 0; i < 6; i++)
 416                dev->dev_addr[i] = tuple->TupleData[i+2];
 417        return 0;
 418}
 419
 420/**
 421 * pcmcia_get_mac_from_cis() - read out MAC address from CISTPL_FUNCE
 422 * @p_dev:      the struct pcmcia_device for which we want the address.
 423 * @dev:        a properly prepared struct net_device to store the info to.
 424 *
 425 * pcmcia_get_mac_from_cis() reads out the hardware MAC address from
 426 * CISTPL_FUNCE and stores it into struct net_device *dev->dev_addr which
 427 * must be set up properly by the driver (see examples!).
 428 */
 429int pcmcia_get_mac_from_cis(struct pcmcia_device *p_dev, struct net_device *dev)
 430{
 431        return pcmcia_loop_tuple(p_dev, CISTPL_FUNCE, pcmcia_do_get_mac, dev);
 432}
 433EXPORT_SYMBOL(pcmcia_get_mac_from_cis);
 434
 435