linux/drivers/mtd/maps/vmu-flash.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/* vmu-flash.c
   3 * Driver for SEGA Dreamcast Visual Memory Unit
   4 *
   5 * Copyright (c) Adrian McMenamin 2002 - 2009
   6 * Copyright (c) Paul Mundt 2001
   7 */
   8#include <linux/init.h>
   9#include <linux/slab.h>
  10#include <linux/sched.h>
  11#include <linux/delay.h>
  12#include <linux/maple.h>
  13#include <linux/mtd/mtd.h>
  14#include <linux/mtd/map.h>
  15
  16struct vmu_cache {
  17        unsigned char *buffer;          /* Cache */
  18        unsigned int block;             /* Which block was cached */
  19        unsigned long jiffies_atc;      /* When was it cached? */
  20        int valid;
  21};
  22
  23struct mdev_part {
  24        struct maple_device *mdev;
  25        int partition;
  26};
  27
  28struct vmupart {
  29        u16 user_blocks;
  30        u16 root_block;
  31        u16 numblocks;
  32        char *name;
  33        struct vmu_cache *pcache;
  34};
  35
  36struct memcard {
  37        u16 tempA;
  38        u16 tempB;
  39        u32 partitions;
  40        u32 blocklen;
  41        u32 writecnt;
  42        u32 readcnt;
  43        u32 removeable;
  44        int partition;
  45        int read;
  46        unsigned char *blockread;
  47        struct vmupart *parts;
  48        struct mtd_info *mtd;
  49};
  50
  51struct vmu_block {
  52        unsigned int num; /* block number */
  53        unsigned int ofs; /* block offset */
  54};
  55
  56static struct vmu_block *ofs_to_block(unsigned long src_ofs,
  57        struct mtd_info *mtd, int partition)
  58{
  59        struct vmu_block *vblock;
  60        struct maple_device *mdev;
  61        struct memcard *card;
  62        struct mdev_part *mpart;
  63        int num;
  64
  65        mpart = mtd->priv;
  66        mdev = mpart->mdev;
  67        card = maple_get_drvdata(mdev);
  68
  69        if (src_ofs >= card->parts[partition].numblocks * card->blocklen)
  70                goto failed;
  71
  72        num = src_ofs / card->blocklen;
  73        if (num > card->parts[partition].numblocks)
  74                goto failed;
  75
  76        vblock = kmalloc(sizeof(struct vmu_block), GFP_KERNEL);
  77        if (!vblock)
  78                goto failed;
  79
  80        vblock->num = num;
  81        vblock->ofs = src_ofs % card->blocklen;
  82        return vblock;
  83
  84failed:
  85        return NULL;
  86}
  87
  88/* Maple bus callback function for reads */
  89static void vmu_blockread(struct mapleq *mq)
  90{
  91        struct maple_device *mdev;
  92        struct memcard *card;
  93
  94        mdev = mq->dev;
  95        card = maple_get_drvdata(mdev);
  96        /* copy the read in data */
  97
  98        if (unlikely(!card->blockread))
  99                return;
 100
 101        memcpy(card->blockread, mq->recvbuf->buf + 12,
 102                card->blocklen/card->readcnt);
 103
 104}
 105
 106/* Interface with maple bus to read blocks
 107 * caching the results so that other parts
 108 * of the driver can access block reads */
 109static int maple_vmu_read_block(unsigned int num, unsigned char *buf,
 110        struct mtd_info *mtd)
 111{
 112        struct memcard *card;
 113        struct mdev_part *mpart;
 114        struct maple_device *mdev;
 115        int partition, error = 0, x, wait;
 116        unsigned char *blockread = NULL;
 117        struct vmu_cache *pcache;
 118        __be32 sendbuf;
 119
 120        mpart = mtd->priv;
 121        mdev = mpart->mdev;
 122        partition = mpart->partition;
 123        card = maple_get_drvdata(mdev);
 124        pcache = card->parts[partition].pcache;
 125        pcache->valid = 0;
 126
 127        /* prepare the cache for this block */
 128        if (!pcache->buffer) {
 129                pcache->buffer = kmalloc(card->blocklen, GFP_KERNEL);
 130                if (!pcache->buffer) {
 131                        dev_err(&mdev->dev, "VMU at (%d, %d) - read fails due"
 132                                " to lack of memory\n", mdev->port,
 133                                mdev->unit);
 134                        error = -ENOMEM;
 135                        goto outB;
 136                }
 137        }
 138
 139        /*
 140        * Reads may be phased - again the hardware spec
 141        * supports this - though may not be any devices in
 142        * the wild that implement it, but we will here
 143        */
 144        for (x = 0; x < card->readcnt; x++) {
 145                sendbuf = cpu_to_be32(partition << 24 | x << 16 | num);
 146
 147                if (atomic_read(&mdev->busy) == 1) {
 148                        wait_event_interruptible_timeout(mdev->maple_wait,
 149                                atomic_read(&mdev->busy) == 0, HZ);
 150                        if (atomic_read(&mdev->busy) == 1) {
 151                                dev_notice(&mdev->dev, "VMU at (%d, %d)"
 152                                        " is busy\n", mdev->port, mdev->unit);
 153                                error = -EAGAIN;
 154                                goto outB;
 155                        }
 156                }
 157
 158                atomic_set(&mdev->busy, 1);
 159                blockread = kmalloc(card->blocklen/card->readcnt, GFP_KERNEL);
 160                if (!blockread) {
 161                        error = -ENOMEM;
 162                        atomic_set(&mdev->busy, 0);
 163                        goto outB;
 164                }
 165                card->blockread = blockread;
 166
 167                maple_getcond_callback(mdev, vmu_blockread, 0,
 168                        MAPLE_FUNC_MEMCARD);
 169                error = maple_add_packet(mdev, MAPLE_FUNC_MEMCARD,
 170                                MAPLE_COMMAND_BREAD, 2, &sendbuf);
 171                /* Very long timeouts seem to be needed when box is stressed */
 172                wait = wait_event_interruptible_timeout(mdev->maple_wait,
 173                        (atomic_read(&mdev->busy) == 0 ||
 174                        atomic_read(&mdev->busy) == 2), HZ * 3);
 175                /*
 176                * MTD layer does not handle hotplugging well
 177                * so have to return errors when VMU is unplugged
 178                * in the middle of a read (busy == 2)
 179                */
 180                if (error || atomic_read(&mdev->busy) == 2) {
 181                        if (atomic_read(&mdev->busy) == 2)
 182                                error = -ENXIO;
 183                        atomic_set(&mdev->busy, 0);
 184                        card->blockread = NULL;
 185                        goto outA;
 186                }
 187                if (wait == 0 || wait == -ERESTARTSYS) {
 188                        card->blockread = NULL;
 189                        atomic_set(&mdev->busy, 0);
 190                        error = -EIO;
 191                        list_del_init(&(mdev->mq->list));
 192                        kfree(mdev->mq->sendbuf);
 193                        mdev->mq->sendbuf = NULL;
 194                        if (wait == -ERESTARTSYS) {
 195                                dev_warn(&mdev->dev, "VMU read on (%d, %d)"
 196                                        " interrupted on block 0x%X\n",
 197                                        mdev->port, mdev->unit, num);
 198                        } else
 199                                dev_notice(&mdev->dev, "VMU read on (%d, %d)"
 200                                        " timed out on block 0x%X\n",
 201                                        mdev->port, mdev->unit, num);
 202                        goto outA;
 203                }
 204
 205                memcpy(buf + (card->blocklen/card->readcnt) * x, blockread,
 206                        card->blocklen/card->readcnt);
 207
 208                memcpy(pcache->buffer + (card->blocklen/card->readcnt) * x,
 209                        card->blockread, card->blocklen/card->readcnt);
 210                card->blockread = NULL;
 211                pcache->block = num;
 212                pcache->jiffies_atc = jiffies;
 213                pcache->valid = 1;
 214                kfree(blockread);
 215        }
 216
 217        return error;
 218
 219outA:
 220        kfree(blockread);
 221outB:
 222        return error;
 223}
 224
 225/* communicate with maple bus for phased writing */
 226static int maple_vmu_write_block(unsigned int num, const unsigned char *buf,
 227        struct mtd_info *mtd)
 228{
 229        struct memcard *card;
 230        struct mdev_part *mpart;
 231        struct maple_device *mdev;
 232        int partition, error, locking, x, phaselen, wait;
 233        __be32 *sendbuf;
 234
 235        mpart = mtd->priv;
 236        mdev = mpart->mdev;
 237        partition = mpart->partition;
 238        card = maple_get_drvdata(mdev);
 239
 240        phaselen = card->blocklen/card->writecnt;
 241
 242        sendbuf = kmalloc(phaselen + 4, GFP_KERNEL);
 243        if (!sendbuf) {
 244                error = -ENOMEM;
 245                goto fail_nosendbuf;
 246        }
 247        for (x = 0; x < card->writecnt; x++) {
 248                sendbuf[0] = cpu_to_be32(partition << 24 | x << 16 | num);
 249                memcpy(&sendbuf[1], buf + phaselen * x, phaselen);
 250                /* wait until the device is not busy doing something else
 251                * or 1 second - which ever is longer */
 252                if (atomic_read(&mdev->busy) == 1) {
 253                        wait_event_interruptible_timeout(mdev->maple_wait,
 254                                atomic_read(&mdev->busy) == 0, HZ);
 255                        if (atomic_read(&mdev->busy) == 1) {
 256                                error = -EBUSY;
 257                                dev_notice(&mdev->dev, "VMU write at (%d, %d)"
 258                                        "failed - device is busy\n",
 259                                        mdev->port, mdev->unit);
 260                                goto fail_nolock;
 261                        }
 262                }
 263                atomic_set(&mdev->busy, 1);
 264
 265                locking = maple_add_packet(mdev, MAPLE_FUNC_MEMCARD,
 266                        MAPLE_COMMAND_BWRITE, phaselen / 4 + 2, sendbuf);
 267                wait = wait_event_interruptible_timeout(mdev->maple_wait,
 268                        atomic_read(&mdev->busy) == 0, HZ/10);
 269                if (locking) {
 270                        error = -EIO;
 271                        atomic_set(&mdev->busy, 0);
 272                        goto fail_nolock;
 273                }
 274                if (atomic_read(&mdev->busy) == 2) {
 275                        atomic_set(&mdev->busy, 0);
 276                } else if (wait == 0 || wait == -ERESTARTSYS) {
 277                        error = -EIO;
 278                        dev_warn(&mdev->dev, "Write at (%d, %d) of block"
 279                                " 0x%X at phase %d failed: could not"
 280                                " communicate with VMU", mdev->port,
 281                                mdev->unit, num, x);
 282                        atomic_set(&mdev->busy, 0);
 283                        kfree(mdev->mq->sendbuf);
 284                        mdev->mq->sendbuf = NULL;
 285                        list_del_init(&(mdev->mq->list));
 286                        goto fail_nolock;
 287                }
 288        }
 289        kfree(sendbuf);
 290
 291        return card->blocklen;
 292
 293fail_nolock:
 294        kfree(sendbuf);
 295fail_nosendbuf:
 296        dev_err(&mdev->dev, "VMU (%d, %d): write failed\n", mdev->port,
 297                mdev->unit);
 298        return error;
 299}
 300
 301/* mtd function to simulate reading byte by byte */
 302static unsigned char vmu_flash_read_char(unsigned long ofs, int *retval,
 303        struct mtd_info *mtd)
 304{
 305        struct vmu_block *vblock;
 306        struct memcard *card;
 307        struct mdev_part *mpart;
 308        struct maple_device *mdev;
 309        unsigned char *buf, ret;
 310        int partition, error;
 311
 312        mpart = mtd->priv;
 313        mdev = mpart->mdev;
 314        partition = mpart->partition;
 315        card = maple_get_drvdata(mdev);
 316        *retval =  0;
 317
 318        buf = kmalloc(card->blocklen, GFP_KERNEL);
 319        if (!buf) {
 320                *retval = 1;
 321                ret = -ENOMEM;
 322                goto finish;
 323        }
 324
 325        vblock = ofs_to_block(ofs, mtd, partition);
 326        if (!vblock) {
 327                *retval = 3;
 328                ret = -ENOMEM;
 329                goto out_buf;
 330        }
 331
 332        error = maple_vmu_read_block(vblock->num, buf, mtd);
 333        if (error) {
 334                ret = error;
 335                *retval = 2;
 336                goto out_vblock;
 337        }
 338
 339        ret = buf[vblock->ofs];
 340
 341out_vblock:
 342        kfree(vblock);
 343out_buf:
 344        kfree(buf);
 345finish:
 346        return ret;
 347}
 348
 349/* mtd higher order function to read flash */
 350static int vmu_flash_read(struct mtd_info *mtd, loff_t from, size_t len,
 351        size_t *retlen,  u_char *buf)
 352{
 353        struct maple_device *mdev;
 354        struct memcard *card;
 355        struct mdev_part *mpart;
 356        struct vmu_cache *pcache;
 357        struct vmu_block *vblock;
 358        int index = 0, retval, partition, leftover, numblocks;
 359        unsigned char cx;
 360
 361        mpart = mtd->priv;
 362        mdev = mpart->mdev;
 363        partition = mpart->partition;
 364        card = maple_get_drvdata(mdev);
 365
 366        numblocks = card->parts[partition].numblocks;
 367        if (from + len > numblocks * card->blocklen)
 368                len = numblocks * card->blocklen - from;
 369        if (len == 0)
 370                return -EIO;
 371        /* Have we cached this bit already? */
 372        pcache = card->parts[partition].pcache;
 373        do {
 374                vblock =  ofs_to_block(from + index, mtd, partition);
 375                if (!vblock)
 376                        return -ENOMEM;
 377                /* Have we cached this and is the cache valid and timely? */
 378                if (pcache->valid &&
 379                        time_before(jiffies, pcache->jiffies_atc + HZ) &&
 380                        (pcache->block == vblock->num)) {
 381                        /* we have cached it, so do necessary copying */
 382                        leftover = card->blocklen - vblock->ofs;
 383                        if (vblock->ofs + len - index < card->blocklen) {
 384                                /* only a bit of this block to copy */
 385                                memcpy(buf + index,
 386                                        pcache->buffer + vblock->ofs,
 387                                        len - index);
 388                                index = len;
 389                        } else {
 390                                /* otherwise copy remainder of whole block */
 391                                memcpy(buf + index, pcache->buffer +
 392                                        vblock->ofs, leftover);
 393                                index += leftover;
 394                        }
 395                } else {
 396                        /*
 397                        * Not cached so read one byte -
 398                        * but cache the rest of the block
 399                        */
 400                        cx = vmu_flash_read_char(from + index, &retval, mtd);
 401                        if (retval) {
 402                                *retlen = index;
 403                                kfree(vblock);
 404                                return cx;
 405                        }
 406                        memset(buf + index, cx, 1);
 407                        index++;
 408                }
 409                kfree(vblock);
 410        } while (len > index);
 411        *retlen = index;
 412
 413        return 0;
 414}
 415
 416static int vmu_flash_write(struct mtd_info *mtd, loff_t to, size_t len,
 417        size_t *retlen, const u_char *buf)
 418{
 419        struct maple_device *mdev;
 420        struct memcard *card;
 421        struct mdev_part *mpart;
 422        int index = 0, partition, error = 0, numblocks;
 423        struct vmu_cache *pcache;
 424        struct vmu_block *vblock;
 425        unsigned char *buffer;
 426
 427        mpart = mtd->priv;
 428        mdev = mpart->mdev;
 429        partition = mpart->partition;
 430        card = maple_get_drvdata(mdev);
 431
 432        numblocks = card->parts[partition].numblocks;
 433        if (to + len > numblocks * card->blocklen)
 434                len = numblocks * card->blocklen - to;
 435        if (len == 0) {
 436                error = -EIO;
 437                goto failed;
 438        }
 439
 440        vblock = ofs_to_block(to, mtd, partition);
 441        if (!vblock) {
 442                error = -ENOMEM;
 443                goto failed;
 444        }
 445
 446        buffer = kmalloc(card->blocklen, GFP_KERNEL);
 447        if (!buffer) {
 448                error = -ENOMEM;
 449                goto fail_buffer;
 450        }
 451
 452        do {
 453                /* Read in the block we are to write to */
 454                error = maple_vmu_read_block(vblock->num, buffer, mtd);
 455                if (error)
 456                        goto fail_io;
 457
 458                do {
 459                        buffer[vblock->ofs] = buf[index];
 460                        vblock->ofs++;
 461                        index++;
 462                        if (index >= len)
 463                                break;
 464                } while (vblock->ofs < card->blocklen);
 465
 466                /* write out new buffer */
 467                error = maple_vmu_write_block(vblock->num, buffer, mtd);
 468                /* invalidate the cache */
 469                pcache = card->parts[partition].pcache;
 470                pcache->valid = 0;
 471
 472                if (error != card->blocklen)
 473                        goto fail_io;
 474
 475                vblock->num++;
 476                vblock->ofs = 0;
 477        } while (len > index);
 478
 479        kfree(buffer);
 480        *retlen = index;
 481        kfree(vblock);
 482        return 0;
 483
 484fail_io:
 485        kfree(buffer);
 486fail_buffer:
 487        kfree(vblock);
 488failed:
 489        dev_err(&mdev->dev, "VMU write failing with error %d\n", error);
 490        return error;
 491}
 492
 493static void vmu_flash_sync(struct mtd_info *mtd)
 494{
 495        /* Do nothing here */
 496}
 497
 498/* Maple bus callback function to recursively query hardware details */
 499static void vmu_queryblocks(struct mapleq *mq)
 500{
 501        struct maple_device *mdev;
 502        unsigned short *res;
 503        struct memcard *card;
 504        __be32 partnum;
 505        struct vmu_cache *pcache;
 506        struct mdev_part *mpart;
 507        struct mtd_info *mtd_cur;
 508        struct vmupart *part_cur;
 509        int error;
 510
 511        mdev = mq->dev;
 512        card = maple_get_drvdata(mdev);
 513        res = (unsigned short *) (mq->recvbuf->buf);
 514        card->tempA = res[12];
 515        card->tempB = res[6];
 516
 517        dev_info(&mdev->dev, "VMU device at partition %d has %d user "
 518                "blocks with a root block at %d\n", card->partition,
 519                card->tempA, card->tempB);
 520
 521        part_cur = &card->parts[card->partition];
 522        part_cur->user_blocks = card->tempA;
 523        part_cur->root_block = card->tempB;
 524        part_cur->numblocks = card->tempB + 1;
 525        part_cur->name = kmalloc(12, GFP_KERNEL);
 526        if (!part_cur->name)
 527                goto fail_name;
 528
 529        sprintf(part_cur->name, "vmu%d.%d.%d",
 530                mdev->port, mdev->unit, card->partition);
 531        mtd_cur = &card->mtd[card->partition];
 532        mtd_cur->name = part_cur->name;
 533        mtd_cur->type = 8;
 534        mtd_cur->flags = MTD_WRITEABLE|MTD_NO_ERASE;
 535        mtd_cur->size = part_cur->numblocks * card->blocklen;
 536        mtd_cur->erasesize = card->blocklen;
 537        mtd_cur->_write = vmu_flash_write;
 538        mtd_cur->_read = vmu_flash_read;
 539        mtd_cur->_sync = vmu_flash_sync;
 540        mtd_cur->writesize = card->blocklen;
 541
 542        mpart = kmalloc(sizeof(struct mdev_part), GFP_KERNEL);
 543        if (!mpart)
 544                goto fail_mpart;
 545
 546        mpart->mdev = mdev;
 547        mpart->partition = card->partition;
 548        mtd_cur->priv = mpart;
 549        mtd_cur->owner = THIS_MODULE;
 550
 551        pcache = kzalloc(sizeof(struct vmu_cache), GFP_KERNEL);
 552        if (!pcache)
 553                goto fail_cache_create;
 554        part_cur->pcache = pcache;
 555
 556        error = mtd_device_register(mtd_cur, NULL, 0);
 557        if (error)
 558                goto fail_mtd_register;
 559
 560        maple_getcond_callback(mdev, NULL, 0,
 561                MAPLE_FUNC_MEMCARD);
 562
 563        /*
 564        * Set up a recursive call to the (probably theoretical)
 565        * second or more partition
 566        */
 567        if (++card->partition < card->partitions) {
 568                partnum = cpu_to_be32(card->partition << 24);
 569                maple_getcond_callback(mdev, vmu_queryblocks, 0,
 570                        MAPLE_FUNC_MEMCARD);
 571                maple_add_packet(mdev, MAPLE_FUNC_MEMCARD,
 572                        MAPLE_COMMAND_GETMINFO, 2, &partnum);
 573        }
 574        return;
 575
 576fail_mtd_register:
 577        dev_err(&mdev->dev, "Could not register maple device at (%d, %d)"
 578                "error is 0x%X\n", mdev->port, mdev->unit, error);
 579        for (error = 0; error <= card->partition; error++) {
 580                kfree(((card->parts)[error]).pcache);
 581                ((card->parts)[error]).pcache = NULL;
 582        }
 583fail_cache_create:
 584fail_mpart:
 585        for (error = 0; error <= card->partition; error++) {
 586                kfree(((card->mtd)[error]).priv);
 587                ((card->mtd)[error]).priv = NULL;
 588        }
 589        maple_getcond_callback(mdev, NULL, 0,
 590                MAPLE_FUNC_MEMCARD);
 591        kfree(part_cur->name);
 592fail_name:
 593        return;
 594}
 595
 596/* Handles very basic info about the flash, queries for details */
 597static int vmu_connect(struct maple_device *mdev)
 598{
 599        unsigned long test_flash_data, basic_flash_data;
 600        int c, error;
 601        struct memcard *card;
 602        u32 partnum = 0;
 603
 604        test_flash_data = be32_to_cpu(mdev->devinfo.function);
 605        /* Need to count how many bits are set - to find out which
 606         * function_data element has details of the memory card
 607         */
 608        c = hweight_long(test_flash_data);
 609
 610        basic_flash_data = be32_to_cpu(mdev->devinfo.function_data[c - 1]);
 611
 612        card = kmalloc(sizeof(struct memcard), GFP_KERNEL);
 613        if (!card) {
 614                error = -ENOMEM;
 615                goto fail_nomem;
 616        }
 617
 618        card->partitions = (basic_flash_data >> 24 & 0xFF) + 1;
 619        card->blocklen = ((basic_flash_data >> 16 & 0xFF) + 1) << 5;
 620        card->writecnt = basic_flash_data >> 12 & 0xF;
 621        card->readcnt = basic_flash_data >> 8 & 0xF;
 622        card->removeable = basic_flash_data >> 7 & 1;
 623
 624        card->partition = 0;
 625
 626        /*
 627        * Not sure there are actually any multi-partition devices in the
 628        * real world, but the hardware supports them, so, so will we
 629        */
 630        card->parts = kmalloc_array(card->partitions, sizeof(struct vmupart),
 631                                    GFP_KERNEL);
 632        if (!card->parts) {
 633                error = -ENOMEM;
 634                goto fail_partitions;
 635        }
 636
 637        card->mtd = kmalloc_array(card->partitions, sizeof(struct mtd_info),
 638                                  GFP_KERNEL);
 639        if (!card->mtd) {
 640                error = -ENOMEM;
 641                goto fail_mtd_info;
 642        }
 643
 644        maple_set_drvdata(mdev, card);
 645
 646        /*
 647        * We want to trap meminfo not get cond
 648        * so set interval to zero, but rely on maple bus
 649        * driver to pass back the results of the meminfo
 650        */
 651        maple_getcond_callback(mdev, vmu_queryblocks, 0,
 652                MAPLE_FUNC_MEMCARD);
 653
 654        /* Make sure we are clear to go */
 655        if (atomic_read(&mdev->busy) == 1) {
 656                wait_event_interruptible_timeout(mdev->maple_wait,
 657                        atomic_read(&mdev->busy) == 0, HZ);
 658                if (atomic_read(&mdev->busy) == 1) {
 659                        dev_notice(&mdev->dev, "VMU at (%d, %d) is busy\n",
 660                                mdev->port, mdev->unit);
 661                        error = -EAGAIN;
 662                        goto fail_device_busy;
 663                }
 664        }
 665
 666        atomic_set(&mdev->busy, 1);
 667
 668        /*
 669        * Set up the minfo call: vmu_queryblocks will handle
 670        * the information passed back
 671        */
 672        error = maple_add_packet(mdev, MAPLE_FUNC_MEMCARD,
 673                MAPLE_COMMAND_GETMINFO, 2, &partnum);
 674        if (error) {
 675                dev_err(&mdev->dev, "Could not lock VMU at (%d, %d)"
 676                        " error is 0x%X\n", mdev->port, mdev->unit, error);
 677                goto fail_mtd_info;
 678        }
 679        return 0;
 680
 681fail_device_busy:
 682        kfree(card->mtd);
 683fail_mtd_info:
 684        kfree(card->parts);
 685fail_partitions:
 686        kfree(card);
 687fail_nomem:
 688        return error;
 689}
 690
 691static void vmu_disconnect(struct maple_device *mdev)
 692{
 693        struct memcard *card;
 694        struct mdev_part *mpart;
 695        int x;
 696
 697        mdev->callback = NULL;
 698        card = maple_get_drvdata(mdev);
 699        for (x = 0; x < card->partitions; x++) {
 700                mpart = ((card->mtd)[x]).priv;
 701                mpart->mdev = NULL;
 702                mtd_device_unregister(&((card->mtd)[x]));
 703                kfree(((card->parts)[x]).name);
 704        }
 705        kfree(card->parts);
 706        kfree(card->mtd);
 707        kfree(card);
 708}
 709
 710/* Callback to handle eccentricities of both mtd subsystem
 711 * and general flakyness of Dreamcast VMUs
 712 */
 713static int vmu_can_unload(struct maple_device *mdev)
 714{
 715        struct memcard *card;
 716        int x;
 717        struct mtd_info *mtd;
 718
 719        card = maple_get_drvdata(mdev);
 720        for (x = 0; x < card->partitions; x++) {
 721                mtd = &((card->mtd)[x]);
 722                if (mtd->usecount > 0)
 723                        return 0;
 724        }
 725        return 1;
 726}
 727
 728#define ERRSTR "VMU at (%d, %d) file error -"
 729
 730static void vmu_file_error(struct maple_device *mdev, void *recvbuf)
 731{
 732        enum maple_file_errors error = ((int *)recvbuf)[1];
 733
 734        switch (error) {
 735
 736        case MAPLE_FILEERR_INVALID_PARTITION:
 737                dev_notice(&mdev->dev, ERRSTR " invalid partition number\n",
 738                        mdev->port, mdev->unit);
 739                break;
 740
 741        case MAPLE_FILEERR_PHASE_ERROR:
 742                dev_notice(&mdev->dev, ERRSTR " phase error\n",
 743                        mdev->port, mdev->unit);
 744                break;
 745
 746        case MAPLE_FILEERR_INVALID_BLOCK:
 747                dev_notice(&mdev->dev, ERRSTR " invalid block number\n",
 748                        mdev->port, mdev->unit);
 749                break;
 750
 751        case MAPLE_FILEERR_WRITE_ERROR:
 752                dev_notice(&mdev->dev, ERRSTR " write error\n",
 753                        mdev->port, mdev->unit);
 754                break;
 755
 756        case MAPLE_FILEERR_INVALID_WRITE_LENGTH:
 757                dev_notice(&mdev->dev, ERRSTR " invalid write length\n",
 758                        mdev->port, mdev->unit);
 759                break;
 760
 761        case MAPLE_FILEERR_BAD_CRC:
 762                dev_notice(&mdev->dev, ERRSTR " bad CRC\n",
 763                        mdev->port, mdev->unit);
 764                break;
 765
 766        default:
 767                dev_notice(&mdev->dev, ERRSTR " 0x%X\n",
 768                        mdev->port, mdev->unit, error);
 769        }
 770}
 771
 772
 773static int probe_maple_vmu(struct device *dev)
 774{
 775        int error;
 776        struct maple_device *mdev = to_maple_dev(dev);
 777        struct maple_driver *mdrv = to_maple_driver(dev->driver);
 778
 779        mdev->can_unload = vmu_can_unload;
 780        mdev->fileerr_handler = vmu_file_error;
 781        mdev->driver = mdrv;
 782
 783        error = vmu_connect(mdev);
 784        if (error)
 785                return error;
 786
 787        return 0;
 788}
 789
 790static int remove_maple_vmu(struct device *dev)
 791{
 792        struct maple_device *mdev = to_maple_dev(dev);
 793
 794        vmu_disconnect(mdev);
 795        return 0;
 796}
 797
 798static struct maple_driver vmu_flash_driver = {
 799        .function =     MAPLE_FUNC_MEMCARD,
 800        .drv = {
 801                .name =         "Dreamcast_visual_memory",
 802                .probe =        probe_maple_vmu,
 803                .remove =       remove_maple_vmu,
 804        },
 805};
 806
 807static int __init vmu_flash_map_init(void)
 808{
 809        return maple_driver_register(&vmu_flash_driver);
 810}
 811
 812static void __exit vmu_flash_map_exit(void)
 813{
 814        maple_driver_unregister(&vmu_flash_driver);
 815}
 816
 817module_init(vmu_flash_map_init);
 818module_exit(vmu_flash_map_exit);
 819
 820MODULE_LICENSE("GPL");
 821MODULE_AUTHOR("Adrian McMenamin");
 822MODULE_DESCRIPTION("Flash mapping for Sega Dreamcast visual memory");
 823