linux/drivers/mtd/maps/pcmciamtd.c
<<
>>
Prefs
   1/*
   2 * pcmciamtd.c - MTD driver for PCMCIA flash memory cards
   3 *
   4 * Author: Simon Evans <spse@secret.org.uk>
   5 *
   6 * Copyright (C) 2002 Simon Evans
   7 *
   8 * Licence: GPL
   9 *
  10 */
  11
  12#include <linux/module.h>
  13#include <linux/slab.h>
  14#include <linux/timer.h>
  15#include <linux/init.h>
  16#include <asm/io.h>
  17#include <asm/system.h>
  18
  19#include <pcmcia/cs.h>
  20#include <pcmcia/cistpl.h>
  21#include <pcmcia/ds.h>
  22
  23#include <linux/mtd/map.h>
  24#include <linux/mtd/mtd.h>
  25
  26#ifdef CONFIG_MTD_DEBUG
  27static int debug = CONFIG_MTD_DEBUG_VERBOSE;
  28module_param(debug, int, 0);
  29MODULE_PARM_DESC(debug, "Set Debug Level 0=quiet, 5=noisy");
  30#undef DEBUG
  31#define DEBUG(n, format, arg...) \
  32        if (n <= debug) {        \
  33                printk(KERN_DEBUG __FILE__ ":%s(): " format "\n", __func__ , ## arg); \
  34        }
  35
  36#else
  37#undef DEBUG
  38#define DEBUG(n, arg...)
  39static const int debug = 0;
  40#endif
  41
  42#define info(format, arg...) printk(KERN_INFO "pcmciamtd: " format "\n" , ## arg)
  43
  44#define DRIVER_DESC     "PCMCIA Flash memory card driver"
  45
  46/* Size of the PCMCIA address space: 26 bits = 64 MB */
  47#define MAX_PCMCIA_ADDR 0x4000000
  48
  49struct pcmciamtd_dev {
  50        struct pcmcia_device    *p_dev;
  51        caddr_t         win_base;       /* ioremapped address of PCMCIA window */
  52        unsigned int    win_size;       /* size of window */
  53        unsigned int    offset;         /* offset into card the window currently points at */
  54        struct map_info pcmcia_map;
  55        struct mtd_info *mtd_info;
  56        int             vpp;
  57        char            mtd_name[sizeof(struct cistpl_vers_1_t)];
  58};
  59
  60
  61/* Module parameters */
  62
  63/* 2 = do 16-bit transfers, 1 = do 8-bit transfers */
  64static int bankwidth = 2;
  65
  66/* Speed of memory accesses, in ns */
  67static int mem_speed;
  68
  69/* Force the size of an SRAM card */
  70static int force_size;
  71
  72/* Force Vpp */
  73static int vpp;
  74
  75/* Set Vpp */
  76static int setvpp;
  77
  78/* Force card to be treated as FLASH, ROM or RAM */
  79static int mem_type;
  80
  81MODULE_LICENSE("GPL");
  82MODULE_AUTHOR("Simon Evans <spse@secret.org.uk>");
  83MODULE_DESCRIPTION(DRIVER_DESC);
  84module_param(bankwidth, int, 0);
  85MODULE_PARM_DESC(bankwidth, "Set bankwidth (1=8 bit, 2=16 bit, default=2)");
  86module_param(mem_speed, int, 0);
  87MODULE_PARM_DESC(mem_speed, "Set memory access speed in ns");
  88module_param(force_size, int, 0);
  89MODULE_PARM_DESC(force_size, "Force size of card in MiB (1-64)");
  90module_param(setvpp, int, 0);
  91MODULE_PARM_DESC(setvpp, "Set Vpp (0=Never, 1=On writes, 2=Always on, default=0)");
  92module_param(vpp, int, 0);
  93MODULE_PARM_DESC(vpp, "Vpp value in 1/10ths eg 33=3.3V 120=12V (Dangerous)");
  94module_param(mem_type, int, 0);
  95MODULE_PARM_DESC(mem_type, "Set Memory type (0=Flash, 1=RAM, 2=ROM, default=0)");
  96
  97
  98/* read/write{8,16} copy_{from,to} routines with window remapping
  99 * to access whole card
 100 */
 101static caddr_t remap_window(struct map_info *map, unsigned long to)
 102{
 103        struct pcmciamtd_dev *dev = (struct pcmciamtd_dev *)map->map_priv_1;
 104        window_handle_t win = (window_handle_t)map->map_priv_2;
 105        unsigned int offset;
 106        int ret;
 107
 108        if (!pcmcia_dev_present(dev->p_dev)) {
 109                DEBUG(1, "device removed");
 110                return 0;
 111        }
 112
 113        offset = to & ~(dev->win_size-1);
 114        if (offset != dev->offset) {
 115                DEBUG(2, "Remapping window from 0x%8.8x to 0x%8.8x",
 116                      dev->offset, offset);
 117                ret = pcmcia_map_mem_page(dev->p_dev, win, offset);
 118                if (ret != 0)
 119                        return NULL;
 120                dev->offset = offset;
 121        }
 122        return dev->win_base + (to & (dev->win_size-1));
 123}
 124
 125
 126static map_word pcmcia_read8_remap(struct map_info *map, unsigned long ofs)
 127{
 128        caddr_t addr;
 129        map_word d = {{0}};
 130
 131        addr = remap_window(map, ofs);
 132        if(!addr)
 133                return d;
 134
 135        d.x[0] = readb(addr);
 136        DEBUG(3, "ofs = 0x%08lx (%p) data = 0x%02lx", ofs, addr, d.x[0]);
 137        return d;
 138}
 139
 140
 141static map_word pcmcia_read16_remap(struct map_info *map, unsigned long ofs)
 142{
 143        caddr_t addr;
 144        map_word d = {{0}};
 145
 146        addr = remap_window(map, ofs);
 147        if(!addr)
 148                return d;
 149
 150        d.x[0] = readw(addr);
 151        DEBUG(3, "ofs = 0x%08lx (%p) data = 0x%04lx", ofs, addr, d.x[0]);
 152        return d;
 153}
 154
 155
 156static void pcmcia_copy_from_remap(struct map_info *map, void *to, unsigned long from, ssize_t len)
 157{
 158        struct pcmciamtd_dev *dev = (struct pcmciamtd_dev *)map->map_priv_1;
 159        unsigned long win_size = dev->win_size;
 160
 161        DEBUG(3, "to = %p from = %lu len = %zd", to, from, len);
 162        while(len) {
 163                int toread = win_size - (from & (win_size-1));
 164                caddr_t addr;
 165
 166                if(toread > len)
 167                        toread = len;
 168
 169                addr = remap_window(map, from);
 170                if(!addr)
 171                        return;
 172
 173                DEBUG(4, "memcpy from %p to %p len = %d", addr, to, toread);
 174                memcpy_fromio(to, addr, toread);
 175                len -= toread;
 176                to += toread;
 177                from += toread;
 178        }
 179}
 180
 181
 182static void pcmcia_write8_remap(struct map_info *map, map_word d, unsigned long adr)
 183{
 184        caddr_t addr = remap_window(map, adr);
 185
 186        if(!addr)
 187                return;
 188
 189        DEBUG(3, "adr = 0x%08lx (%p)  data = 0x%02lx", adr, addr, d.x[0]);
 190        writeb(d.x[0], addr);
 191}
 192
 193
 194static void pcmcia_write16_remap(struct map_info *map, map_word d, unsigned long adr)
 195{
 196        caddr_t addr = remap_window(map, adr);
 197        if(!addr)
 198                return;
 199
 200        DEBUG(3, "adr = 0x%08lx (%p)  data = 0x%04lx", adr, addr, d.x[0]);
 201        writew(d.x[0], addr);
 202}
 203
 204
 205static void pcmcia_copy_to_remap(struct map_info *map, unsigned long to, const void *from, ssize_t len)
 206{
 207        struct pcmciamtd_dev *dev = (struct pcmciamtd_dev *)map->map_priv_1;
 208        unsigned long win_size = dev->win_size;
 209
 210        DEBUG(3, "to = %lu from = %p len = %zd", to, from, len);
 211        while(len) {
 212                int towrite = win_size - (to & (win_size-1));
 213                caddr_t addr;
 214
 215                if(towrite > len)
 216                        towrite = len;
 217
 218                addr = remap_window(map, to);
 219                if(!addr)
 220                        return;
 221
 222                DEBUG(4, "memcpy from %p to %p len = %d", from, addr, towrite);
 223                memcpy_toio(addr, from, towrite);
 224                len -= towrite;
 225                to += towrite;
 226                from += towrite;
 227        }
 228}
 229
 230
 231/* read/write{8,16} copy_{from,to} routines with direct access */
 232
 233#define DEV_REMOVED(x)  (!(pcmcia_dev_present(((struct pcmciamtd_dev *)map->map_priv_1)->p_dev)))
 234
 235static map_word pcmcia_read8(struct map_info *map, unsigned long ofs)
 236{
 237        caddr_t win_base = (caddr_t)map->map_priv_2;
 238        map_word d = {{0}};
 239
 240        if(DEV_REMOVED(map))
 241                return d;
 242
 243        d.x[0] = readb(win_base + ofs);
 244        DEBUG(3, "ofs = 0x%08lx (%p) data = 0x%02lx",
 245              ofs, win_base + ofs, d.x[0]);
 246        return d;
 247}
 248
 249
 250static map_word pcmcia_read16(struct map_info *map, unsigned long ofs)
 251{
 252        caddr_t win_base = (caddr_t)map->map_priv_2;
 253        map_word d = {{0}};
 254
 255        if(DEV_REMOVED(map))
 256                return d;
 257
 258        d.x[0] = readw(win_base + ofs);
 259        DEBUG(3, "ofs = 0x%08lx (%p) data = 0x%04lx",
 260              ofs, win_base + ofs, d.x[0]);
 261        return d;
 262}
 263
 264
 265static void pcmcia_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len)
 266{
 267        caddr_t win_base = (caddr_t)map->map_priv_2;
 268
 269        if(DEV_REMOVED(map))
 270                return;
 271
 272        DEBUG(3, "to = %p from = %lu len = %zd", to, from, len);
 273        memcpy_fromio(to, win_base + from, len);
 274}
 275
 276
 277static void pcmcia_write8(struct map_info *map, map_word d, unsigned long adr)
 278{
 279        caddr_t win_base = (caddr_t)map->map_priv_2;
 280
 281        if(DEV_REMOVED(map))
 282                return;
 283
 284        DEBUG(3, "adr = 0x%08lx (%p)  data = 0x%02lx",
 285              adr, win_base + adr, d.x[0]);
 286        writeb(d.x[0], win_base + adr);
 287}
 288
 289
 290static void pcmcia_write16(struct map_info *map, map_word d, unsigned long adr)
 291{
 292        caddr_t win_base = (caddr_t)map->map_priv_2;
 293
 294        if(DEV_REMOVED(map))
 295                return;
 296
 297        DEBUG(3, "adr = 0x%08lx (%p)  data = 0x%04lx",
 298              adr, win_base + adr, d.x[0]);
 299        writew(d.x[0], win_base + adr);
 300}
 301
 302
 303static void pcmcia_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len)
 304{
 305        caddr_t win_base = (caddr_t)map->map_priv_2;
 306
 307        if(DEV_REMOVED(map))
 308                return;
 309
 310        DEBUG(3, "to = %lu from = %p len = %zd", to, from, len);
 311        memcpy_toio(win_base + to, from, len);
 312}
 313
 314
 315static void pcmciamtd_set_vpp(struct map_info *map, int on)
 316{
 317        struct pcmciamtd_dev *dev = (struct pcmciamtd_dev *)map->map_priv_1;
 318        struct pcmcia_device *link = dev->p_dev;
 319        modconf_t mod;
 320        int ret;
 321
 322        mod.Attributes = CONF_VPP1_CHANGE_VALID | CONF_VPP2_CHANGE_VALID;
 323        mod.Vcc = 0;
 324        mod.Vpp1 = mod.Vpp2 = on ? dev->vpp : 0;
 325
 326        DEBUG(2, "dev = %p on = %d vpp = %d\n", dev, on, dev->vpp);
 327        ret = pcmcia_modify_configuration(link, &mod);
 328}
 329
 330
 331/* After a card is removed, pcmciamtd_release() will unregister the
 332 * device, and release the PCMCIA configuration.  If the device is
 333 * still open, this will be postponed until it is closed.
 334 */
 335
 336static void pcmciamtd_release(struct pcmcia_device *link)
 337{
 338        struct pcmciamtd_dev *dev = link->priv;
 339
 340        DEBUG(3, "link = 0x%p", link);
 341
 342        if (link->win) {
 343                if(dev->win_base) {
 344                        iounmap(dev->win_base);
 345                        dev->win_base = NULL;
 346                }
 347        }
 348        pcmcia_disable_device(link);
 349}
 350
 351
 352#ifdef CONFIG_MTD_DEBUG
 353static int pcmciamtd_cistpl_format(struct pcmcia_device *p_dev,
 354                                tuple_t *tuple,
 355                                void *priv_data)
 356{
 357        cisparse_t parse;
 358
 359        if (!pcmcia_parse_tuple(tuple, &parse)) {
 360                cistpl_format_t *t = &parse.format;
 361                (void)t; /* Shut up, gcc */
 362                DEBUG(2, "Format type: %u, Error Detection: %u, offset = %u, length =%u",
 363                        t->type, t->edc, t->offset, t->length);
 364        }
 365        return -ENOSPC;
 366}
 367
 368static int pcmciamtd_cistpl_jedec(struct pcmcia_device *p_dev,
 369                                tuple_t *tuple,
 370                                void *priv_data)
 371{
 372        cisparse_t parse;
 373        int i;
 374
 375        if (!pcmcia_parse_tuple(tuple, &parse)) {
 376                cistpl_jedec_t *t = &parse.jedec;
 377                for (i = 0; i < t->nid; i++)
 378                        DEBUG(2, "JEDEC: 0x%02x 0x%02x",
 379                              t->id[i].mfr, t->id[i].info);
 380        }
 381        return -ENOSPC;
 382}
 383#endif
 384
 385static int pcmciamtd_cistpl_device(struct pcmcia_device *p_dev,
 386                                tuple_t *tuple,
 387                                void *priv_data)
 388{
 389        struct pcmciamtd_dev *dev = priv_data;
 390        cisparse_t parse;
 391        cistpl_device_t *t = &parse.device;
 392        int i;
 393
 394        if (pcmcia_parse_tuple(tuple, &parse))
 395                return -EINVAL;
 396
 397        DEBUG(2, "Common memory:");
 398        dev->pcmcia_map.size = t->dev[0].size;
 399        /* from here on: DEBUG only */
 400        for (i = 0; i < t->ndev; i++) {
 401                DEBUG(2, "Region %d, type = %u", i, t->dev[i].type);
 402                DEBUG(2, "Region %d, wp = %u", i, t->dev[i].wp);
 403                DEBUG(2, "Region %d, speed = %u ns", i, t->dev[i].speed);
 404                DEBUG(2, "Region %d, size = %u bytes", i, t->dev[i].size);
 405        }
 406        return 0;
 407}
 408
 409static int pcmciamtd_cistpl_geo(struct pcmcia_device *p_dev,
 410                                tuple_t *tuple,
 411                                void *priv_data)
 412{
 413        struct pcmciamtd_dev *dev = priv_data;
 414        cisparse_t parse;
 415        cistpl_device_geo_t *t = &parse.device_geo;
 416        int i;
 417
 418        if (pcmcia_parse_tuple(tuple, &parse))
 419                return -EINVAL;
 420
 421        dev->pcmcia_map.bankwidth = t->geo[0].buswidth;
 422        /* from here on: DEBUG only */
 423        for (i = 0; i < t->ngeo; i++) {
 424                DEBUG(2, "region: %d bankwidth = %u", i, t->geo[i].buswidth);
 425                DEBUG(2, "region: %d erase_block = %u", i, t->geo[i].erase_block);
 426                DEBUG(2, "region: %d read_block = %u", i, t->geo[i].read_block);
 427                DEBUG(2, "region: %d write_block = %u", i, t->geo[i].write_block);
 428                DEBUG(2, "region: %d partition = %u", i, t->geo[i].partition);
 429                DEBUG(2, "region: %d interleave = %u", i, t->geo[i].interleave);
 430        }
 431        return 0;
 432}
 433
 434
 435static void card_settings(struct pcmciamtd_dev *dev, struct pcmcia_device *p_dev, int *new_name)
 436{
 437        int i;
 438
 439        if (p_dev->prod_id[0]) {
 440                dev->mtd_name[0] = '\0';
 441                for (i = 0; i < 4; i++) {
 442                        if (i)
 443                                strcat(dev->mtd_name, " ");
 444                        if (p_dev->prod_id[i])
 445                                strcat(dev->mtd_name, p_dev->prod_id[i]);
 446                }
 447                DEBUG(2, "Found name: %s", dev->mtd_name);
 448        }
 449
 450#ifdef CONFIG_MTD_DEBUG
 451        pcmcia_loop_tuple(p_dev, CISTPL_FORMAT, pcmciamtd_cistpl_format, NULL);
 452        pcmcia_loop_tuple(p_dev, CISTPL_JEDEC_C, pcmciamtd_cistpl_jedec, NULL);
 453#endif
 454        pcmcia_loop_tuple(p_dev, CISTPL_DEVICE, pcmciamtd_cistpl_device, dev);
 455        pcmcia_loop_tuple(p_dev, CISTPL_DEVICE_GEO, pcmciamtd_cistpl_geo, dev);
 456
 457        if(!dev->pcmcia_map.size)
 458                dev->pcmcia_map.size = MAX_PCMCIA_ADDR;
 459
 460        if(!dev->pcmcia_map.bankwidth)
 461                dev->pcmcia_map.bankwidth = 2;
 462
 463        if(force_size) {
 464                dev->pcmcia_map.size = force_size << 20;
 465                DEBUG(2, "size forced to %dM", force_size);
 466        }
 467
 468        if(bankwidth) {
 469                dev->pcmcia_map.bankwidth = bankwidth;
 470                DEBUG(2, "bankwidth forced to %d", bankwidth);
 471        }
 472
 473        dev->pcmcia_map.name = dev->mtd_name;
 474        if(!dev->mtd_name[0]) {
 475                strcpy(dev->mtd_name, "PCMCIA Memory card");
 476                *new_name = 1;
 477        }
 478
 479        DEBUG(1, "Device: Size: %lu Width:%d Name: %s",
 480              dev->pcmcia_map.size,
 481              dev->pcmcia_map.bankwidth << 3, dev->mtd_name);
 482}
 483
 484
 485/* pcmciamtd_config() is scheduled to run after a CARD_INSERTION event
 486 * is received, to configure the PCMCIA socket, and to make the
 487 * MTD device available to the system.
 488 */
 489
 490static int pcmciamtd_config(struct pcmcia_device *link)
 491{
 492        struct pcmciamtd_dev *dev = link->priv;
 493        struct mtd_info *mtd = NULL;
 494        win_req_t req;
 495        int ret;
 496        int i;
 497        static char *probes[] = { "jedec_probe", "cfi_probe" };
 498        int new_name = 0;
 499
 500        DEBUG(3, "link=0x%p", link);
 501
 502        card_settings(dev, link, &new_name);
 503
 504        dev->pcmcia_map.phys = NO_XIP;
 505        dev->pcmcia_map.copy_from = pcmcia_copy_from_remap;
 506        dev->pcmcia_map.copy_to = pcmcia_copy_to_remap;
 507        if (dev->pcmcia_map.bankwidth == 1) {
 508                dev->pcmcia_map.read = pcmcia_read8_remap;
 509                dev->pcmcia_map.write = pcmcia_write8_remap;
 510        } else {
 511                dev->pcmcia_map.read = pcmcia_read16_remap;
 512                dev->pcmcia_map.write = pcmcia_write16_remap;
 513        }
 514        if(setvpp == 1)
 515                dev->pcmcia_map.set_vpp = pcmciamtd_set_vpp;
 516
 517        /* Request a memory window for PCMCIA. Some architeures can map windows
 518         * upto the maximum that PCMCIA can support (64MiB) - this is ideal and
 519         * we aim for a window the size of the whole card - otherwise we try
 520         * smaller windows until we succeed
 521         */
 522
 523        req.Attributes =  WIN_MEMORY_TYPE_CM | WIN_ENABLE;
 524        req.Attributes |= (dev->pcmcia_map.bankwidth == 1) ? WIN_DATA_WIDTH_8 : WIN_DATA_WIDTH_16;
 525        req.Base = 0;
 526        req.AccessSpeed = mem_speed;
 527        link->win = (window_handle_t)link;
 528        req.Size = (force_size) ? force_size << 20 : MAX_PCMCIA_ADDR;
 529        dev->win_size = 0;
 530
 531        do {
 532                int ret;
 533                DEBUG(2, "requesting window with size = %dKiB memspeed = %d",
 534                      req.Size >> 10, req.AccessSpeed);
 535                ret = pcmcia_request_window(link, &req, &link->win);
 536                DEBUG(2, "ret = %d dev->win_size = %d", ret, dev->win_size);
 537                if(ret) {
 538                        req.Size >>= 1;
 539                } else {
 540                        DEBUG(2, "Got window of size %dKiB", req.Size >> 10);
 541                        dev->win_size = req.Size;
 542                        break;
 543                }
 544        } while(req.Size >= 0x1000);
 545
 546        DEBUG(2, "dev->win_size = %d", dev->win_size);
 547
 548        if(!dev->win_size) {
 549                dev_err(&dev->p_dev->dev, "Cannot allocate memory window\n");
 550                pcmciamtd_release(link);
 551                return -ENODEV;
 552        }
 553        DEBUG(1, "Allocated a window of %dKiB", dev->win_size >> 10);
 554
 555        /* Get write protect status */
 556        DEBUG(2, "window handle = 0x%8.8lx", (unsigned long)link->win);
 557        dev->win_base = ioremap(req.Base, req.Size);
 558        if(!dev->win_base) {
 559                dev_err(&dev->p_dev->dev, "ioremap(%lu, %u) failed\n",
 560                        req.Base, req.Size);
 561                pcmciamtd_release(link);
 562                return -ENODEV;
 563        }
 564        DEBUG(1, "mapped window dev = %p req.base = 0x%lx base = %p size = 0x%x",
 565              dev, req.Base, dev->win_base, req.Size);
 566
 567        dev->offset = 0;
 568        dev->pcmcia_map.map_priv_1 = (unsigned long)dev;
 569        dev->pcmcia_map.map_priv_2 = (unsigned long)link->win;
 570
 571        dev->vpp = (vpp) ? vpp : link->socket->socket.Vpp;
 572        link->conf.Attributes = 0;
 573        if(setvpp == 2) {
 574                link->conf.Vpp = dev->vpp;
 575        } else {
 576                link->conf.Vpp = 0;
 577        }
 578
 579        link->conf.IntType = INT_MEMORY;
 580        link->conf.ConfigIndex = 0;
 581        DEBUG(2, "Setting Configuration");
 582        ret = pcmcia_request_configuration(link, &link->conf);
 583        if (ret != 0) {
 584                if (dev->win_base) {
 585                        iounmap(dev->win_base);
 586                        dev->win_base = NULL;
 587                }
 588                return -ENODEV;
 589        }
 590
 591        if(mem_type == 1) {
 592                mtd = do_map_probe("map_ram", &dev->pcmcia_map);
 593        } else if(mem_type == 2) {
 594                mtd = do_map_probe("map_rom", &dev->pcmcia_map);
 595        } else {
 596                for(i = 0; i < ARRAY_SIZE(probes); i++) {
 597                        DEBUG(1, "Trying %s", probes[i]);
 598                        mtd = do_map_probe(probes[i], &dev->pcmcia_map);
 599                        if(mtd)
 600                                break;
 601
 602                        DEBUG(1, "FAILED: %s", probes[i]);
 603                }
 604        }
 605
 606        if(!mtd) {
 607                DEBUG(1, "Can not find an MTD");
 608                pcmciamtd_release(link);
 609                return -ENODEV;
 610        }
 611
 612        dev->mtd_info = mtd;
 613        mtd->owner = THIS_MODULE;
 614
 615        if(new_name) {
 616                int size = 0;
 617                char unit = ' ';
 618                /* Since we are using a default name, make it better by adding
 619                 * in the size
 620                 */
 621                if(mtd->size < 1048576) { /* <1MiB in size, show size in KiB */
 622                        size = mtd->size >> 10;
 623                        unit = 'K';
 624                } else {
 625                        size = mtd->size >> 20;
 626                        unit = 'M';
 627                }
 628                snprintf(dev->mtd_name, sizeof(dev->mtd_name), "%d%ciB %s", size, unit, "PCMCIA Memory card");
 629        }
 630
 631        /* If the memory found is fits completely into the mapped PCMCIA window,
 632           use the faster non-remapping read/write functions */
 633        if(mtd->size <= dev->win_size) {
 634                DEBUG(1, "Using non remapping memory functions");
 635                dev->pcmcia_map.map_priv_2 = (unsigned long)dev->win_base;
 636                if (dev->pcmcia_map.bankwidth == 1) {
 637                        dev->pcmcia_map.read = pcmcia_read8;
 638                        dev->pcmcia_map.write = pcmcia_write8;
 639                } else {
 640                        dev->pcmcia_map.read = pcmcia_read16;
 641                        dev->pcmcia_map.write = pcmcia_write16;
 642                }
 643                dev->pcmcia_map.copy_from = pcmcia_copy_from;
 644                dev->pcmcia_map.copy_to = pcmcia_copy_to;
 645        }
 646
 647        if(add_mtd_device(mtd)) {
 648                map_destroy(mtd);
 649                dev->mtd_info = NULL;
 650                dev_err(&dev->p_dev->dev,
 651                        "Could not register the MTD device\n");
 652                pcmciamtd_release(link);
 653                return -ENODEV;
 654        }
 655        dev_info(&dev->p_dev->dev, "mtd%d: %s\n", mtd->index, mtd->name);
 656        return 0;
 657
 658        dev_err(&dev->p_dev->dev, "CS Error, exiting\n");
 659        pcmciamtd_release(link);
 660        return -ENODEV;
 661}
 662
 663
 664static int pcmciamtd_suspend(struct pcmcia_device *dev)
 665{
 666        DEBUG(2, "EVENT_PM_RESUME");
 667
 668        /* get_lock(link); */
 669
 670        return 0;
 671}
 672
 673static int pcmciamtd_resume(struct pcmcia_device *dev)
 674{
 675        DEBUG(2, "EVENT_PM_SUSPEND");
 676
 677        /* free_lock(link); */
 678
 679        return 0;
 680}
 681
 682
 683/* This deletes a driver "instance".  The device is de-registered
 684 * with Card Services.  If it has been released, all local data
 685 * structures are freed.  Otherwise, the structures will be freed
 686 * when the device is released.
 687 */
 688
 689static void pcmciamtd_detach(struct pcmcia_device *link)
 690{
 691        struct pcmciamtd_dev *dev = link->priv;
 692
 693        DEBUG(3, "link=0x%p", link);
 694
 695        if(dev->mtd_info) {
 696                del_mtd_device(dev->mtd_info);
 697                dev_info(&dev->p_dev->dev, "mtd%d: Removing\n",
 698                         dev->mtd_info->index);
 699                map_destroy(dev->mtd_info);
 700        }
 701
 702        pcmciamtd_release(link);
 703}
 704
 705
 706/* pcmciamtd_attach() creates an "instance" of the driver, allocating
 707 * local data structures for one device.  The device is registered
 708 * with Card Services.
 709 */
 710
 711static int pcmciamtd_probe(struct pcmcia_device *link)
 712{
 713        struct pcmciamtd_dev *dev;
 714
 715        /* Create new memory card device */
 716        dev = kzalloc(sizeof(*dev), GFP_KERNEL);
 717        if (!dev) return -ENOMEM;
 718        DEBUG(1, "dev=0x%p", dev);
 719
 720        dev->p_dev = link;
 721        link->priv = dev;
 722
 723        link->conf.Attributes = 0;
 724        link->conf.IntType = INT_MEMORY;
 725
 726        return pcmciamtd_config(link);
 727}
 728
 729static struct pcmcia_device_id pcmciamtd_ids[] = {
 730        PCMCIA_DEVICE_FUNC_ID(1),
 731        PCMCIA_DEVICE_PROD_ID123("IO DATA", "PCS-2M", "2MB SRAM", 0x547e66dc, 0x1fed36cd, 0x36eadd21),
 732        PCMCIA_DEVICE_PROD_ID12("IBM", "2MB SRAM", 0xb569a6e5, 0x36eadd21),
 733        PCMCIA_DEVICE_PROD_ID12("IBM", "4MB FLASH", 0xb569a6e5, 0x8bc54d2a),
 734        PCMCIA_DEVICE_PROD_ID12("IBM", "8MB FLASH", 0xb569a6e5, 0x6df1be3e),
 735        PCMCIA_DEVICE_PROD_ID12("Intel", "S2E20SW", 0x816cc815, 0xd14c9dcf),
 736        PCMCIA_DEVICE_PROD_ID12("Intel", "S2E8 SW", 0x816cc815, 0xa2d7dedb),
 737        PCMCIA_DEVICE_PROD_ID12("intel", "SERIES2-02 ", 0x40ade711, 0x145cea5c),
 738        PCMCIA_DEVICE_PROD_ID12("intel", "SERIES2-04 ", 0x40ade711, 0x42064dda),
 739        PCMCIA_DEVICE_PROD_ID12("intel", "SERIES2-20 ", 0x40ade711, 0x25ee5cb0),
 740        PCMCIA_DEVICE_PROD_ID12("intel", "VALUE SERIES 100 ", 0x40ade711, 0xdf8506d8),
 741        PCMCIA_DEVICE_PROD_ID12("KINGMAX TECHNOLOGY INC.", "SRAM 256K Bytes", 0x54d0c69c, 0xad12c29c),
 742        PCMCIA_DEVICE_PROD_ID12("Maxtor", "MAXFL MobileMax Flash Memory Card", 0xb68968c8, 0x2dfb47b0),
 743        PCMCIA_DEVICE_PROD_ID123("M-Systems", "M-SYS Flash Memory Card", "(c) M-Systems", 0x7ed2ad87, 0x675dc3fb, 0x7aef3965),
 744        PCMCIA_DEVICE_PROD_ID12("PRETEC", "  2MB SRAM CARD", 0xebf91155, 0x805360ca),
 745        PCMCIA_DEVICE_PROD_ID12("SEIKO EPSON", "WWB101EN20", 0xf9876baf, 0xad0b207b),
 746        PCMCIA_DEVICE_PROD_ID12("SEIKO EPSON", "WWB513EN20", 0xf9876baf, 0xe8d884ad),
 747        PCMCIA_DEVICE_PROD_ID12("SMART Modular Technologies", " 4MB FLASH Card", 0x96fd8277, 0x737a5b05),
 748        PCMCIA_DEVICE_PROD_ID12("Starfish, Inc.", "REX-3000", 0x05ddca47, 0xe7d67bca),
 749        PCMCIA_DEVICE_PROD_ID12("Starfish, Inc.", "REX-4100", 0x05ddca47, 0x7bc32944),
 750        /* the following was commented out in pcmcia-cs-3.2.7 */
 751        /* PCMCIA_DEVICE_PROD_ID12("RATOC Systems,Inc.", "SmartMedia ADAPTER PC Card", 0xf4a2fefe, 0x5885b2ae), */
 752#ifdef CONFIG_MTD_PCMCIA_ANONYMOUS
 753        { .match_flags = PCMCIA_DEV_ID_MATCH_ANONYMOUS, },
 754#endif
 755        PCMCIA_DEVICE_NULL
 756};
 757MODULE_DEVICE_TABLE(pcmcia, pcmciamtd_ids);
 758
 759static struct pcmcia_driver pcmciamtd_driver = {
 760        .drv            = {
 761                .name   = "pcmciamtd"
 762        },
 763        .probe          = pcmciamtd_probe,
 764        .remove         = pcmciamtd_detach,
 765        .owner          = THIS_MODULE,
 766        .id_table       = pcmciamtd_ids,
 767        .suspend        = pcmciamtd_suspend,
 768        .resume         = pcmciamtd_resume,
 769};
 770
 771
 772static int __init init_pcmciamtd(void)
 773{
 774        info(DRIVER_DESC);
 775
 776        if(bankwidth && bankwidth != 1 && bankwidth != 2) {
 777                info("bad bankwidth (%d), using default", bankwidth);
 778                bankwidth = 2;
 779        }
 780        if(force_size && (force_size < 1 || force_size > 64)) {
 781                info("bad force_size (%d), using default", force_size);
 782                force_size = 0;
 783        }
 784        if(mem_type && mem_type != 1 && mem_type != 2) {
 785                info("bad mem_type (%d), using default", mem_type);
 786                mem_type = 0;
 787        }
 788        return pcmcia_register_driver(&pcmciamtd_driver);
 789}
 790
 791
 792static void __exit exit_pcmciamtd(void)
 793{
 794        DEBUG(1, DRIVER_DESC " unloading");
 795        pcmcia_unregister_driver(&pcmciamtd_driver);
 796}
 797
 798module_init(init_pcmciamtd);
 799module_exit(exit_pcmciamtd);
 800
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.