linux/drivers/pcmcia/pcmcia_resource.c
<<
>>
Prefs
   1/*
   2 * PCMCIA 16-bit resource management functions
   3 *
   4 * The initial developer of the original code is David A. Hinds
   5 * <dahinds@users.sourceforge.net>.  Portions created by David A. Hinds
   6 * are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
   7 *
   8 * Copyright (C) 1999        David A. Hinds
   9 * Copyright (C) 2004-2005   Dominik Brodowski
  10 *
  11 * This program is free software; you can redistribute it and/or modify
  12 * it under the terms of the GNU General Public License version 2 as
  13 * published by the Free Software Foundation.
  14 *
  15 */
  16
  17#include <linux/module.h>
  18#include <linux/kernel.h>
  19#include <linux/interrupt.h>
  20#include <linux/delay.h>
  21#include <linux/pci.h>
  22#include <linux/device.h>
  23
  24#include <pcmcia/cs_types.h>
  25#include <pcmcia/ss.h>
  26#include <pcmcia/cs.h>
  27#include <pcmcia/cistpl.h>
  28#include <pcmcia/cisreg.h>
  29#include <pcmcia/ds.h>
  30
  31#include "cs_internal.h"
  32
  33
  34/* Access speed for IO windows */
  35static int io_speed = 0;
  36module_param(io_speed, int, 0444);
  37
  38
  39#ifdef CONFIG_PCMCIA_PROBE
  40#include <asm/irq.h>
  41/* mask of IRQs already reserved by other cards, we should avoid using them */
  42static u8 pcmcia_used_irq[NR_IRQS];
  43#endif
  44
  45
  46#ifdef CONFIG_PCMCIA_DEBUG
  47extern int ds_pc_debug;
  48
  49#define ds_dbg(skt, lvl, fmt, arg...) do {                      \
  50        if (ds_pc_debug >= lvl)                                 \
  51                dev_printk(KERN_DEBUG, &skt->dev,               \
  52                           "pcmcia_resource: " fmt,             \
  53                           ## arg);                             \
  54} while (0)
  55#else
  56#define ds_dbg(skt, lvl, fmt, arg...) do { } while (0)
  57#endif
  58
  59
  60
  61/** alloc_io_space
  62 *
  63 * Special stuff for managing IO windows, because they are scarce
  64 */
  65
  66static int alloc_io_space(struct pcmcia_socket *s, u_int attr,
  67                          unsigned int *base, unsigned int num, u_int lines)
  68{
  69        int i;
  70        unsigned int try, align;
  71
  72        align = (*base) ? (lines ? 1<<lines : 0) : 1;
  73        if (align && (align < num)) {
  74                if (*base) {
  75                        ds_dbg(s, 0, "odd IO request: num %#x align %#x\n",
  76                               num, align);
  77                        align = 0;
  78                } else
  79                        while (align && (align < num)) align <<= 1;
  80        }
  81        if (*base & ~(align-1)) {
  82                ds_dbg(s, 0, "odd IO request: base %#x align %#x\n",
  83                       *base, align);
  84                align = 0;
  85        }
  86        if ((s->features & SS_CAP_STATIC_MAP) && s->io_offset) {
  87                *base = s->io_offset | (*base & 0x0fff);
  88                return 0;
  89        }
  90        /* Check for an already-allocated window that must conflict with
  91         * what was asked for.  It is a hack because it does not catch all
  92         * potential conflicts, just the most obvious ones.
  93         */
  94        for (i = 0; i < MAX_IO_WIN; i++)
  95                if ((s->io[i].res) && *base &&
  96                    ((s->io[i].res->start & (align-1)) == *base))
  97                        return 1;
  98        for (i = 0; i < MAX_IO_WIN; i++) {
  99                if (!s->io[i].res) {
 100                        s->io[i].res = pcmcia_find_io_region(*base, num, align, s);
 101                        if (s->io[i].res) {
 102                                *base = s->io[i].res->start;
 103                                s->io[i].res->flags = (s->io[i].res->flags & ~IORESOURCE_BITS) | (attr & IORESOURCE_BITS);
 104                                s->io[i].InUse = num;
 105                                break;
 106                        } else
 107                                return 1;
 108                } else if ((s->io[i].res->flags & IORESOURCE_BITS) != (attr & IORESOURCE_BITS))
 109                        continue;
 110                /* Try to extend top of window */
 111                try = s->io[i].res->end + 1;
 112                if ((*base == 0) || (*base == try))
 113                        if (pcmcia_adjust_io_region(s->io[i].res, s->io[i].res->start,
 114                                                    s->io[i].res->end + num, s) == 0) {
 115                                *base = try;
 116                                s->io[i].InUse += num;
 117                                break;
 118                        }
 119                /* Try to extend bottom of window */
 120                try = s->io[i].res->start - num;
 121                if ((*base == 0) || (*base == try))
 122                        if (pcmcia_adjust_io_region(s->io[i].res, s->io[i].res->start - num,
 123                                                    s->io[i].res->end, s) == 0) {
 124                                *base = try;
 125                                s->io[i].InUse += num;
 126                                break;
 127                        }
 128        }
 129        return (i == MAX_IO_WIN);
 130} /* alloc_io_space */
 131
 132
 133static void release_io_space(struct pcmcia_socket *s, unsigned int base,
 134                             unsigned int num)
 135{
 136        int i;
 137
 138        for (i = 0; i < MAX_IO_WIN; i++) {
 139                if (!s->io[i].res)
 140                        continue;
 141                if ((s->io[i].res->start <= base) &&
 142                    (s->io[i].res->end >= base+num-1)) {
 143                        s->io[i].InUse -= num;
 144                        /* Free the window if no one else is using it */
 145                        if (s->io[i].InUse == 0) {
 146                                release_resource(s->io[i].res);
 147                                kfree(s->io[i].res);
 148                                s->io[i].res = NULL;
 149                        }
 150                }
 151        }
 152} /* release_io_space */
 153
 154
 155/** pccard_access_configuration_register
 156 *
 157 * Access_configuration_register() reads and writes configuration
 158 * registers in attribute memory.  Memory window 0 is reserved for
 159 * this and the tuple reading services.
 160 */
 161
 162int pcmcia_access_configuration_register(struct pcmcia_device *p_dev,
 163                                         conf_reg_t *reg)
 164{
 165        struct pcmcia_socket *s;
 166        config_t *c;
 167        int addr;
 168        u_char val;
 169
 170        if (!p_dev || !p_dev->function_config)
 171                return -EINVAL;
 172
 173        s = p_dev->socket;
 174        c = p_dev->function_config;
 175
 176        if (!(c->state & CONFIG_LOCKED))
 177                return -EACCES;
 178
 179        addr = (c->ConfigBase + reg->Offset) >> 1;
 180
 181        switch (reg->Action) {
 182        case CS_READ:
 183                pcmcia_read_cis_mem(s, 1, addr, 1, &val);
 184                reg->Value = val;
 185                break;
 186        case CS_WRITE:
 187                val = reg->Value;
 188                pcmcia_write_cis_mem(s, 1, addr, 1, &val);
 189                break;
 190        default:
 191                return -EINVAL;
 192                break;
 193        }
 194        return 0;
 195} /* pcmcia_access_configuration_register */
 196EXPORT_SYMBOL(pcmcia_access_configuration_register);
 197
 198
 199/** pcmcia_get_window
 200 */
 201int pcmcia_get_window(struct pcmcia_socket *s, window_handle_t *handle,
 202                      int idx, win_req_t *req)
 203{
 204        window_t *win;
 205        int w;
 206
 207        if (!s || !(s->state & SOCKET_PRESENT))
 208                return -ENODEV;
 209        for (w = idx; w < MAX_WIN; w++)
 210                if (s->state & SOCKET_WIN_REQ(w))
 211                        break;
 212        if (w == MAX_WIN)
 213                return -EINVAL;
 214        win = &s->win[w];
 215        req->Base = win->ctl.res->start;
 216        req->Size = win->ctl.res->end - win->ctl.res->start + 1;
 217        req->AccessSpeed = win->ctl.speed;
 218        req->Attributes = 0;
 219        if (win->ctl.flags & MAP_ATTRIB)
 220                req->Attributes |= WIN_MEMORY_TYPE_AM;
 221        if (win->ctl.flags & MAP_ACTIVE)
 222                req->Attributes |= WIN_ENABLE;
 223        if (win->ctl.flags & MAP_16BIT)
 224                req->Attributes |= WIN_DATA_WIDTH_16;
 225        if (win->ctl.flags & MAP_USE_WAIT)
 226                req->Attributes |= WIN_USE_WAIT;
 227        *handle = win;
 228        return 0;
 229} /* pcmcia_get_window */
 230EXPORT_SYMBOL(pcmcia_get_window);
 231
 232
 233/** pcmcia_get_mem_page
 234 *
 235 * Change the card address of an already open memory window.
 236 */
 237int pcmcia_get_mem_page(window_handle_t win, memreq_t *req)
 238{
 239        if ((win == NULL) || (win->magic != WINDOW_MAGIC))
 240                return -EINVAL;
 241        req->Page = 0;
 242        req->CardOffset = win->ctl.card_start;
 243        return 0;
 244} /* pcmcia_get_mem_page */
 245EXPORT_SYMBOL(pcmcia_get_mem_page);
 246
 247
 248int pcmcia_map_mem_page(window_handle_t win, memreq_t *req)
 249{
 250        struct pcmcia_socket *s;
 251        if ((win == NULL) || (win->magic != WINDOW_MAGIC))
 252                return -EINVAL;
 253        s = win->sock;
 254        if (req->Page != 0) {
 255                ds_dbg(s, 0, "failure: requested page is zero\n");
 256                return -EINVAL;
 257        }
 258        win->ctl.card_start = req->CardOffset;
 259        if (s->ops->set_mem_map(s, &win->ctl) != 0) {
 260                ds_dbg(s, 0, "failed to set_mem_map\n");
 261                return -EIO;
 262        }
 263        return 0;
 264} /* pcmcia_map_mem_page */
 265EXPORT_SYMBOL(pcmcia_map_mem_page);
 266
 267
 268/** pcmcia_modify_configuration
 269 *
 270 * Modify a locked socket configuration
 271 */
 272int pcmcia_modify_configuration(struct pcmcia_device *p_dev,
 273                                modconf_t *mod)
 274{
 275        struct pcmcia_socket *s;
 276        config_t *c;
 277
 278        s = p_dev->socket;
 279        c = p_dev->function_config;
 280
 281        if (!(s->state & SOCKET_PRESENT))
 282                return -ENODEV;
 283        if (!(c->state & CONFIG_LOCKED))
 284                return -EACCES;
 285
 286        if (mod->Attributes & CONF_IRQ_CHANGE_VALID) {
 287                if (mod->Attributes & CONF_ENABLE_IRQ) {
 288                        c->Attributes |= CONF_ENABLE_IRQ;
 289                        s->socket.io_irq = s->irq.AssignedIRQ;
 290                } else {
 291                        c->Attributes &= ~CONF_ENABLE_IRQ;
 292                        s->socket.io_irq = 0;
 293                }
 294                s->ops->set_socket(s, &s->socket);
 295        }
 296
 297        if (mod->Attributes & CONF_VCC_CHANGE_VALID) {
 298                ds_dbg(s, 0, "changing Vcc is not allowed at this time\n");
 299                return -EINVAL;
 300        }
 301
 302        /* We only allow changing Vpp1 and Vpp2 to the same value */
 303        if ((mod->Attributes & CONF_VPP1_CHANGE_VALID) &&
 304            (mod->Attributes & CONF_VPP2_CHANGE_VALID)) {
 305                if (mod->Vpp1 != mod->Vpp2) {
 306                        ds_dbg(s, 0, "Vpp1 and Vpp2 must be the same\n");
 307                        return -EINVAL;
 308                }
 309                s->socket.Vpp = mod->Vpp1;
 310                if (s->ops->set_socket(s, &s->socket)) {
 311                        dev_printk(KERN_WARNING, &s->dev,
 312                                   "Unable to set VPP\n");
 313                        return -EIO;
 314                }
 315        } else if ((mod->Attributes & CONF_VPP1_CHANGE_VALID) ||
 316                   (mod->Attributes & CONF_VPP2_CHANGE_VALID)) {
 317                ds_dbg(s, 0, "changing Vcc is not allowed at this time\n");
 318                return -EINVAL;
 319        }
 320
 321        if (mod->Attributes & CONF_IO_CHANGE_WIDTH) {
 322                pccard_io_map io_off = { 0, 0, 0, 0, 1 };
 323                pccard_io_map io_on;
 324                int i;
 325
 326                io_on.speed = io_speed;
 327                for (i = 0; i < MAX_IO_WIN; i++) {
 328                        if (!s->io[i].res)
 329                                continue;
 330                        io_off.map = i;
 331                        io_on.map = i;
 332
 333                        io_on.flags = MAP_ACTIVE | IO_DATA_PATH_WIDTH_8;
 334                        io_on.start = s->io[i].res->start;
 335                        io_on.stop = s->io[i].res->end;
 336
 337                        s->ops->set_io_map(s, &io_off);
 338                        mdelay(40);
 339                        s->ops->set_io_map(s, &io_on);
 340                }
 341        }
 342
 343        return 0;
 344} /* modify_configuration */
 345EXPORT_SYMBOL(pcmcia_modify_configuration);
 346
 347
 348int pcmcia_release_configuration(struct pcmcia_device *p_dev)
 349{
 350        pccard_io_map io = { 0, 0, 0, 0, 1 };
 351        struct pcmcia_socket *s = p_dev->socket;
 352        config_t *c = p_dev->function_config;
 353        int i;
 354
 355        if (p_dev->_locked) {
 356                p_dev->_locked = 0;
 357                if (--(s->lock_count) == 0) {
 358                        s->socket.flags = SS_OUTPUT_ENA;   /* Is this correct? */
 359                        s->socket.Vpp = 0;
 360                        s->socket.io_irq = 0;
 361                        s->ops->set_socket(s, &s->socket);
 362                }
 363        }
 364        if (c->state & CONFIG_LOCKED) {
 365                c->state &= ~CONFIG_LOCKED;
 366                if (c->state & CONFIG_IO_REQ)
 367                        for (i = 0; i < MAX_IO_WIN; i++) {
 368                                if (!s->io[i].res)
 369                                        continue;
 370                                s->io[i].Config--;
 371                                if (s->io[i].Config != 0)
 372                                        continue;
 373                                io.map = i;
 374                                s->ops->set_io_map(s, &io);
 375                        }
 376        }
 377
 378        return 0;
 379} /* pcmcia_release_configuration */
 380
 381
 382/** pcmcia_release_io
 383 *
 384 * Release_io() releases the I/O ranges allocated by a client.  This
 385 * may be invoked some time after a card ejection has already dumped
 386 * the actual socket configuration, so if the client is "stale", we
 387 * don't bother checking the port ranges against the current socket
 388 * values.
 389 */
 390static int pcmcia_release_io(struct pcmcia_device *p_dev, io_req_t *req)
 391{
 392        struct pcmcia_socket *s = p_dev->socket;
 393        config_t *c = p_dev->function_config;
 394
 395        if (!p_dev->_io )
 396                return -EINVAL;
 397
 398        p_dev->_io = 0;
 399
 400        if ((c->io.BasePort1 != req->BasePort1) ||
 401            (c->io.NumPorts1 != req->NumPorts1) ||
 402            (c->io.BasePort2 != req->BasePort2) ||
 403            (c->io.NumPorts2 != req->NumPorts2))
 404                return -EINVAL;
 405
 406        c->state &= ~CONFIG_IO_REQ;
 407
 408        release_io_space(s, req->BasePort1, req->NumPorts1);
 409        if (req->NumPorts2)
 410                release_io_space(s, req->BasePort2, req->NumPorts2);
 411
 412        return 0;
 413} /* pcmcia_release_io */
 414
 415
 416static int pcmcia_release_irq(struct pcmcia_device *p_dev, irq_req_t *req)
 417{
 418        struct pcmcia_socket *s = p_dev->socket;
 419        config_t *c= p_dev->function_config;
 420
 421        if (!p_dev->_irq)
 422                return -EINVAL;
 423        p_dev->_irq = 0;
 424
 425        if (c->state & CONFIG_LOCKED)
 426                return -EACCES;
 427        if (c->irq.Attributes != req->Attributes) {
 428                ds_dbg(s, 0, "IRQ attributes must match assigned ones\n");
 429                return -EINVAL;
 430        }
 431        if (s->irq.AssignedIRQ != req->AssignedIRQ) {
 432                ds_dbg(s, 0, "IRQ must match assigned one\n");
 433                return -EINVAL;
 434        }
 435        if (--s->irq.Config == 0) {
 436                c->state &= ~CONFIG_IRQ_REQ;
 437                s->irq.AssignedIRQ = 0;
 438        }
 439
 440        if (req->Attributes & IRQ_HANDLE_PRESENT) {
 441                free_irq(req->AssignedIRQ, req->Instance);
 442        }
 443
 444#ifdef CONFIG_PCMCIA_PROBE
 445        pcmcia_used_irq[req->AssignedIRQ]--;
 446#endif
 447
 448        return 0;
 449} /* pcmcia_release_irq */
 450
 451
 452int pcmcia_release_window(window_handle_t win)
 453{
 454        struct pcmcia_socket *s;
 455
 456        if ((win == NULL) || (win->magic != WINDOW_MAGIC))
 457                return -EINVAL;
 458        s = win->sock;
 459        if (!(win->handle->_win & CLIENT_WIN_REQ(win->index)))
 460                return -EINVAL;
 461
 462        /* Shut down memory window */
 463        win->ctl.flags &= ~MAP_ACTIVE;
 464        s->ops->set_mem_map(s, &win->ctl);
 465        s->state &= ~SOCKET_WIN_REQ(win->index);
 466
 467        /* Release system memory */
 468        if (win->ctl.res) {
 469                release_resource(win->ctl.res);
 470                kfree(win->ctl.res);
 471                win->ctl.res = NULL;
 472        }
 473        win->handle->_win &= ~CLIENT_WIN_REQ(win->index);
 474
 475        win->magic = 0;
 476
 477        return 0;
 478} /* pcmcia_release_window */
 479EXPORT_SYMBOL(pcmcia_release_window);
 480
 481
 482int pcmcia_request_configuration(struct pcmcia_device *p_dev,
 483                                 config_req_t *req)
 484{
 485        int i;
 486        u_int base;
 487        struct pcmcia_socket *s = p_dev->socket;
 488        config_t *c;
 489        pccard_io_map iomap;
 490
 491        if (!(s->state & SOCKET_PRESENT))
 492                return -ENODEV;
 493
 494        if (req->IntType & INT_CARDBUS) {
 495                ds_dbg(p_dev->socket, 0, "IntType may not be INT_CARDBUS\n");
 496                return -EINVAL;
 497        }
 498        c = p_dev->function_config;
 499        if (c->state & CONFIG_LOCKED)
 500                return -EACCES;
 501
 502        /* Do power control.  We don't allow changes in Vcc. */
 503        s->socket.Vpp = req->Vpp;
 504        if (s->ops->set_socket(s, &s->socket)) {
 505                dev_printk(KERN_WARNING, &s->dev,
 506                           "Unable to set socket state\n");
 507                return -EINVAL;
 508        }
 509
 510        /* Pick memory or I/O card, DMA mode, interrupt */
 511        c->IntType = req->IntType;
 512        c->Attributes = req->Attributes;
 513        if (req->IntType & INT_MEMORY_AND_IO)
 514                s->socket.flags |= SS_IOCARD;
 515        if (req->IntType & INT_ZOOMED_VIDEO)
 516                s->socket.flags |= SS_ZVCARD | SS_IOCARD;
 517        if (req->Attributes & CONF_ENABLE_DMA)
 518                s->socket.flags |= SS_DMA_MODE;
 519        if (req->Attributes & CONF_ENABLE_SPKR)
 520                s->socket.flags |= SS_SPKR_ENA;
 521        if (req->Attributes & CONF_ENABLE_IRQ)
 522                s->socket.io_irq = s->irq.AssignedIRQ;
 523        else
 524                s->socket.io_irq = 0;
 525        s->ops->set_socket(s, &s->socket);
 526        s->lock_count++;
 527
 528        /* Set up CIS configuration registers */
 529        base = c->ConfigBase = req->ConfigBase;
 530        c->CardValues = req->Present;
 531        if (req->Present & PRESENT_COPY) {
 532                c->Copy = req->Copy;
 533                pcmcia_write_cis_mem(s, 1, (base + CISREG_SCR)>>1, 1, &c->Copy);
 534        }
 535        if (req->Present & PRESENT_OPTION) {
 536                if (s->functions == 1) {
 537                        c->Option = req->ConfigIndex & COR_CONFIG_MASK;
 538                } else {
 539                        c->Option = req->ConfigIndex & COR_MFC_CONFIG_MASK;
 540                        c->Option |= COR_FUNC_ENA|COR_IREQ_ENA;
 541                        if (req->Present & PRESENT_IOBASE_0)
 542                                c->Option |= COR_ADDR_DECODE;
 543                }
 544                if (c->state & CONFIG_IRQ_REQ)
 545                        if (!(c->irq.Attributes & IRQ_FORCED_PULSE))
 546                                c->Option |= COR_LEVEL_REQ;
 547                pcmcia_write_cis_mem(s, 1, (base + CISREG_COR)>>1, 1, &c->Option);
 548                mdelay(40);
 549        }
 550        if (req->Present & PRESENT_STATUS) {
 551                c->Status = req->Status;
 552                pcmcia_write_cis_mem(s, 1, (base + CISREG_CCSR)>>1, 1, &c->Status);
 553        }
 554        if (req->Present & PRESENT_PIN_REPLACE) {
 555                c->Pin = req->Pin;
 556                pcmcia_write_cis_mem(s, 1, (base + CISREG_PRR)>>1, 1, &c->Pin);
 557        }
 558        if (req->Present & PRESENT_EXT_STATUS) {
 559                c->ExtStatus = req->ExtStatus;
 560                pcmcia_write_cis_mem(s, 1, (base + CISREG_ESR)>>1, 1, &c->ExtStatus);
 561        }
 562        if (req->Present & PRESENT_IOBASE_0) {
 563                u_char b = c->io.BasePort1 & 0xff;
 564                pcmcia_write_cis_mem(s, 1, (base + CISREG_IOBASE_0)>>1, 1, &b);
 565                b = (c->io.BasePort1 >> 8) & 0xff;
 566                pcmcia_write_cis_mem(s, 1, (base + CISREG_IOBASE_1)>>1, 1, &b);
 567        }
 568        if (req->Present & PRESENT_IOSIZE) {
 569                u_char b = c->io.NumPorts1 + c->io.NumPorts2 - 1;
 570                pcmcia_write_cis_mem(s, 1, (base + CISREG_IOSIZE)>>1, 1, &b);
 571        }
 572
 573        /* Configure I/O windows */
 574        if (c->state & CONFIG_IO_REQ) {
 575                iomap.speed = io_speed;
 576                for (i = 0; i < MAX_IO_WIN; i++)
 577                        if (s->io[i].res) {
 578                                iomap.map = i;
 579                                iomap.flags = MAP_ACTIVE;
 580                                switch (s->io[i].res->flags & IO_DATA_PATH_WIDTH) {
 581                                case IO_DATA_PATH_WIDTH_16:
 582                                        iomap.flags |= MAP_16BIT; break;
 583                                case IO_DATA_PATH_WIDTH_AUTO:
 584                                        iomap.flags |= MAP_AUTOSZ; break;
 585                                default:
 586                                        break;
 587                                }
 588                                iomap.start = s->io[i].res->start;
 589                                iomap.stop = s->io[i].res->end;
 590                                s->ops->set_io_map(s, &iomap);
 591                                s->io[i].Config++;
 592                        }
 593        }
 594
 595        c->state |= CONFIG_LOCKED;
 596        p_dev->_locked = 1;
 597        return 0;
 598} /* pcmcia_request_configuration */
 599EXPORT_SYMBOL(pcmcia_request_configuration);
 600
 601
 602/** pcmcia_request_io
 603 *
 604 * Request_io() reserves ranges of port addresses for a socket.
 605 * I have not implemented range sharing or alias addressing.
 606 */
 607int pcmcia_request_io(struct pcmcia_device *p_dev, io_req_t *req)
 608{
 609        struct pcmcia_socket *s = p_dev->socket;
 610        config_t *c;
 611
 612        if (!(s->state & SOCKET_PRESENT))
 613                return -ENODEV;
 614
 615        if (!req)
 616                return -EINVAL;
 617        c = p_dev->function_config;
 618        if (c->state & CONFIG_LOCKED)
 619                return -EACCES;
 620        if (c->state & CONFIG_IO_REQ) {
 621                ds_dbg(s, 0, "IO already configured\n");
 622                return -EBUSY;
 623        }
 624        if (req->Attributes1 & (IO_SHARED | IO_FORCE_ALIAS_ACCESS)) {
 625                ds_dbg(s, 0, "bad attribute setting for IO region 1\n");
 626                return -EINVAL;
 627        }
 628        if ((req->NumPorts2 > 0) &&
 629            (req->Attributes2 & (IO_SHARED | IO_FORCE_ALIAS_ACCESS))) {
 630                ds_dbg(s, 0, "bad attribute setting for IO region 2\n");
 631                return -EINVAL;
 632        }
 633
 634        ds_dbg(s, 1, "trying to allocate resource 1\n");
 635        if (alloc_io_space(s, req->Attributes1, &req->BasePort1,
 636                           req->NumPorts1, req->IOAddrLines)) {
 637                ds_dbg(s, 0, "allocation of resource 1 failed\n");
 638                return -EBUSY;
 639        }
 640
 641        if (req->NumPorts2) {
 642                ds_dbg(s, 1, "trying to allocate resource 2\n");
 643                if (alloc_io_space(s, req->Attributes2, &req->BasePort2,
 644                                   req->NumPorts2, req->IOAddrLines)) {
 645                        ds_dbg(s, 0, "allocation of resource 2 failed\n");
 646                        release_io_space(s, req->BasePort1, req->NumPorts1);
 647                        return -EBUSY;
 648                }
 649        }
 650
 651        c->io = *req;
 652        c->state |= CONFIG_IO_REQ;
 653        p_dev->_io = 1;
 654        return 0;
 655} /* pcmcia_request_io */
 656EXPORT_SYMBOL(pcmcia_request_io);
 657
 658
 659/** pcmcia_request_irq
 660 *
 661 * Request_irq() reserves an irq for this client.
 662 *
 663 * Also, since Linux only reserves irq's when they are actually
 664 * hooked, we don't guarantee that an irq will still be available
 665 * when the configuration is locked.  Now that I think about it,
 666 * there might be a way to fix this using a dummy handler.
 667 */
 668
 669#ifdef CONFIG_PCMCIA_PROBE
 670static irqreturn_t test_action(int cpl, void *dev_id)
 671{
 672        return IRQ_NONE;
 673}
 674#endif
 675
 676int pcmcia_request_irq(struct pcmcia_device *p_dev, irq_req_t *req)
 677{
 678        struct pcmcia_socket *s = p_dev->socket;
 679        config_t *c;
 680        int ret = -EINVAL, irq = 0;
 681        int type;
 682
 683        if (!(s->state & SOCKET_PRESENT))
 684                return -ENODEV;
 685        c = p_dev->function_config;
 686        if (c->state & CONFIG_LOCKED)
 687                return -EACCES;
 688        if (c->state & CONFIG_IRQ_REQ) {
 689                ds_dbg(s, 0, "IRQ already configured\n");
 690                return -EBUSY;
 691        }
 692
 693        /* Decide what type of interrupt we are registering */
 694        type = 0;
 695        if (s->functions > 1)           /* All of this ought to be handled higher up */
 696                type = IRQF_SHARED;
 697        else if (req->Attributes & IRQ_TYPE_DYNAMIC_SHARING)
 698                type = IRQF_SHARED;
 699        else printk(KERN_WARNING "pcmcia: Driver needs updating to support IRQ sharing.\n");
 700
 701#ifdef CONFIG_PCMCIA_PROBE
 702
 703#ifdef IRQ_NOAUTOEN
 704        /* if the underlying IRQ infrastructure allows for it, only allocate
 705         * the IRQ, but do not enable it
 706         */
 707        if (!(req->Attributes & IRQ_HANDLE_PRESENT))
 708                type |= IRQ_NOAUTOEN;
 709#endif /* IRQ_NOAUTOEN */
 710
 711        if (s->irq.AssignedIRQ != 0) {
 712                /* If the interrupt is already assigned, it must be the same */
 713                irq = s->irq.AssignedIRQ;
 714        } else {
 715                int try;
 716                u32 mask = s->irq_mask;
 717                void *data = &p_dev->dev.driver; /* something unique to this device */
 718
 719                for (try = 0; try < 64; try++) {
 720                        irq = try % 32;
 721
 722                        /* marked as available by driver, and not blocked by userspace? */
 723                        if (!((mask >> irq) & 1))
 724                                continue;
 725
 726                        /* avoid an IRQ which is already used by a PCMCIA card */
 727                        if ((try < 32) && pcmcia_used_irq[irq])
 728                                continue;
 729
 730                        /* register the correct driver, if possible, of check whether
 731                         * registering a dummy handle works, i.e. if the IRQ isn't
 732                         * marked as used by the kernel resource management core */
 733                        ret = request_irq(irq,
 734                                          (req->Attributes & IRQ_HANDLE_PRESENT) ? req->Handler : test_action,
 735                                          type,
 736                                          p_dev->devname,
 737                                          (req->Attributes & IRQ_HANDLE_PRESENT) ? req->Instance : data);
 738                        if (!ret) {
 739                                if (!(req->Attributes & IRQ_HANDLE_PRESENT))
 740                                        free_irq(irq, data);
 741                                break;
 742                        }
 743                }
 744        }
 745#endif
 746        /* only assign PCI irq if no IRQ already assigned */
 747        if (ret && !s->irq.AssignedIRQ) {
 748                if (!s->pci_irq)
 749                        return ret;
 750                type = IRQF_SHARED;
 751                irq = s->pci_irq;
 752        }
 753
 754        if (ret && (req->Attributes & IRQ_HANDLE_PRESENT)) {
 755                ret = request_irq(irq, req->Handler, type,
 756                                  p_dev->devname, req->Instance);
 757                if (ret)
 758                        return ret;
 759        }
 760
 761        /* Make sure the fact the request type was overridden is passed back */
 762        if (type == IRQF_SHARED && !(req->Attributes & IRQ_TYPE_DYNAMIC_SHARING)) {
 763                req->Attributes |= IRQ_TYPE_DYNAMIC_SHARING;
 764                dev_printk(KERN_WARNING, &p_dev->dev, "pcmcia: "
 765                        "request for exclusive IRQ could not be fulfilled.\n");
 766                dev_printk(KERN_WARNING, &p_dev->dev, "pcmcia: the driver "
 767                        "needs updating to supported shared IRQ lines.\n");
 768        }
 769        c->irq.Attributes = req->Attributes;
 770        s->irq.AssignedIRQ = req->AssignedIRQ = irq;
 771        s->irq.Config++;
 772
 773        c->state |= CONFIG_IRQ_REQ;
 774        p_dev->_irq = 1;
 775
 776#ifdef CONFIG_PCMCIA_PROBE
 777        pcmcia_used_irq[irq]++;
 778#endif
 779
 780        return 0;
 781} /* pcmcia_request_irq */
 782EXPORT_SYMBOL(pcmcia_request_irq);
 783
 784
 785/** pcmcia_request_window
 786 *
 787 * Request_window() establishes a mapping between card memory space
 788 * and system memory space.
 789 */
 790int pcmcia_request_window(struct pcmcia_device **p_dev, win_req_t *req, window_handle_t *wh)
 791{
 792        struct pcmcia_socket *s = (*p_dev)->socket;
 793        window_t *win;
 794        u_long align;
 795        int w;
 796
 797        if (!(s->state & SOCKET_PRESENT))
 798                return -ENODEV;
 799        if (req->Attributes & (WIN_PAGED | WIN_SHARED)) {
 800                ds_dbg(s, 0, "bad attribute setting for iomem region\n");
 801                return -EINVAL;
 802        }
 803
 804        /* Window size defaults to smallest available */
 805        if (req->Size == 0)
 806                req->Size = s->map_size;
 807        align = (((s->features & SS_CAP_MEM_ALIGN) ||
 808                  (req->Attributes & WIN_STRICT_ALIGN)) ?
 809                 req->Size : s->map_size);
 810        if (req->Size & (s->map_size-1)) {
 811                ds_dbg(s, 0, "invalid map size\n");
 812                return -EINVAL;
 813        }
 814        if ((req->Base && (s->features & SS_CAP_STATIC_MAP)) ||
 815            (req->Base & (align-1))) {
 816                ds_dbg(s, 0, "invalid base address\n");
 817                return -EINVAL;
 818        }
 819        if (req->Base)
 820                align = 0;
 821
 822        /* Allocate system memory window */
 823        for (w = 0; w < MAX_WIN; w++)
 824                if (!(s->state & SOCKET_WIN_REQ(w))) break;
 825        if (w == MAX_WIN) {
 826                ds_dbg(s, 0, "all windows are used already\n");
 827                return -EINVAL;
 828        }
 829
 830        win = &s->win[w];
 831        win->magic = WINDOW_MAGIC;
 832        win->index = w;
 833        win->handle = *p_dev;
 834        win->sock = s;
 835
 836        if (!(s->features & SS_CAP_STATIC_MAP)) {
 837                win->ctl.res = pcmcia_find_mem_region(req->Base, req->Size, align,
 838                                                      (req->Attributes & WIN_MAP_BELOW_1MB), s);
 839                if (!win->ctl.res) {
 840                        ds_dbg(s, 0, "allocating mem region failed\n");
 841                        return -EINVAL;
 842                }
 843        }
 844        (*p_dev)->_win |= CLIENT_WIN_REQ(w);
 845
 846        /* Configure the socket controller */
 847        win->ctl.map = w+1;
 848        win->ctl.flags = 0;
 849        win->ctl.speed = req->AccessSpeed;
 850        if (req->Attributes & WIN_MEMORY_TYPE)
 851                win->ctl.flags |= MAP_ATTRIB;
 852        if (req->Attributes & WIN_ENABLE)
 853                win->ctl.flags |= MAP_ACTIVE;
 854        if (req->Attributes & WIN_DATA_WIDTH_16)
 855                win->ctl.flags |= MAP_16BIT;
 856        if (req->Attributes & WIN_USE_WAIT)
 857                win->ctl.flags |= MAP_USE_WAIT;
 858        win->ctl.card_start = 0;
 859        if (s->ops->set_mem_map(s, &win->ctl) != 0) {
 860                ds_dbg(s, 0, "failed to set memory mapping\n");
 861                return -EIO;
 862        }
 863        s->state |= SOCKET_WIN_REQ(w);
 864
 865        /* Return window handle */
 866        if (s->features & SS_CAP_STATIC_MAP) {
 867                req->Base = win->ctl.static_start;
 868        } else {
 869                req->Base = win->ctl.res->start;
 870        }
 871        *wh = win;
 872
 873        return 0;
 874} /* pcmcia_request_window */
 875EXPORT_SYMBOL(pcmcia_request_window);
 876
 877void pcmcia_disable_device(struct pcmcia_device *p_dev) {
 878        pcmcia_release_configuration(p_dev);
 879        pcmcia_release_io(p_dev, &p_dev->io);
 880        pcmcia_release_irq(p_dev, &p_dev->irq);
 881        if (p_dev->win)
 882                pcmcia_release_window(p_dev->win);
 883}
 884EXPORT_SYMBOL(pcmcia_disable_device);
 885
 886
 887struct pcmcia_cfg_mem {
 888        tuple_t tuple;
 889        cisparse_t parse;
 890        u8 buf[256];
 891        cistpl_cftable_entry_t dflt;
 892};
 893
 894/**
 895 * pcmcia_loop_config() - loop over configuration options
 896 * @p_dev:      the struct pcmcia_device which we need to loop for.
 897 * @conf_check: function to call for each configuration option.
 898 *              It gets passed the struct pcmcia_device, the CIS data
 899 *              describing the configuration option, and private data
 900 *              being passed to pcmcia_loop_config()
 901 * @priv_data:  private data to be passed to the conf_check function.
 902 *
 903 * pcmcia_loop_config() loops over all configuration options, and calls
 904 * the driver-specific conf_check() for each one, checking whether
 905 * it is a valid one. Returns 0 on success or errorcode otherwise.
 906 */
 907int pcmcia_loop_config(struct pcmcia_device *p_dev,
 908                       int      (*conf_check)   (struct pcmcia_device *p_dev,
 909                                                 cistpl_cftable_entry_t *cfg,
 910                                                 cistpl_cftable_entry_t *dflt,
 911                                                 unsigned int vcc,
 912                                                 void *priv_data),
 913                       void *priv_data)
 914{
 915        struct pcmcia_cfg_mem *cfg_mem;
 916
 917        tuple_t *tuple;
 918        int ret;
 919        unsigned int vcc;
 920
 921        cfg_mem = kzalloc(sizeof(struct pcmcia_cfg_mem), GFP_KERNEL);
 922        if (cfg_mem == NULL)
 923                return -ENOMEM;
 924
 925        /* get the current Vcc setting */
 926        vcc = p_dev->socket->socket.Vcc;
 927
 928        tuple = &cfg_mem->tuple;
 929        tuple->TupleData = cfg_mem->buf;
 930        tuple->TupleDataMax = 255;
 931        tuple->TupleOffset = 0;
 932        tuple->DesiredTuple = CISTPL_CFTABLE_ENTRY;
 933        tuple->Attributes = 0;
 934
 935        ret = pcmcia_get_first_tuple(p_dev, tuple);
 936        while (!ret) {
 937                cistpl_cftable_entry_t *cfg = &cfg_mem->parse.cftable_entry;
 938
 939                if (pcmcia_get_tuple_data(p_dev, tuple))
 940                        goto next_entry;
 941
 942                if (pcmcia_parse_tuple(tuple, &cfg_mem->parse))
 943                        goto next_entry;
 944
 945                /* default values */
 946                p_dev->conf.ConfigIndex = cfg->index;
 947                if (cfg->flags & CISTPL_CFTABLE_DEFAULT)
 948                        cfg_mem->dflt = *cfg;
 949
 950                ret = conf_check(p_dev, cfg, &cfg_mem->dflt, vcc, priv_data);
 951                if (!ret)
 952                        break;
 953
 954next_entry:
 955                ret = pcmcia_get_next_tuple(p_dev, tuple);
 956        }
 957
 958        return ret;
 959}
 960EXPORT_SYMBOL(pcmcia_loop_config);
 961