Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /* vmu-flash.c
0003  * Driver for SEGA Dreamcast Visual Memory Unit
0004  *
0005  * Copyright (c) Adrian McMenamin 2002 - 2009
0006  * Copyright (c) Paul Mundt 2001
0007  */
0008 #include <linux/init.h>
0009 #include <linux/slab.h>
0010 #include <linux/sched.h>
0011 #include <linux/delay.h>
0012 #include <linux/maple.h>
0013 #include <linux/mtd/mtd.h>
0014 #include <linux/mtd/map.h>
0015 
0016 struct vmu_cache {
0017     unsigned char *buffer;      /* Cache */
0018     unsigned int block;     /* Which block was cached */
0019     unsigned long jiffies_atc;  /* When was it cached? */
0020     int valid;
0021 };
0022 
0023 struct mdev_part {
0024     struct maple_device *mdev;
0025     int partition;
0026 };
0027 
0028 struct vmupart {
0029     u16 user_blocks;
0030     u16 root_block;
0031     u16 numblocks;
0032     char *name;
0033     struct vmu_cache *pcache;
0034 };
0035 
0036 struct memcard {
0037     u16 tempA;
0038     u16 tempB;
0039     u32 partitions;
0040     u32 blocklen;
0041     u32 writecnt;
0042     u32 readcnt;
0043     u32 removable;
0044     int partition;
0045     int read;
0046     unsigned char *blockread;
0047     struct vmupart *parts;
0048     struct mtd_info *mtd;
0049 };
0050 
0051 struct vmu_block {
0052     unsigned int num; /* block number */
0053     unsigned int ofs; /* block offset */
0054 };
0055 
0056 static struct vmu_block *ofs_to_block(unsigned long src_ofs,
0057     struct mtd_info *mtd, int partition)
0058 {
0059     struct vmu_block *vblock;
0060     struct maple_device *mdev;
0061     struct memcard *card;
0062     struct mdev_part *mpart;
0063     int num;
0064 
0065     mpart = mtd->priv;
0066     mdev = mpart->mdev;
0067     card = maple_get_drvdata(mdev);
0068 
0069     if (src_ofs >= card->parts[partition].numblocks * card->blocklen)
0070         goto failed;
0071 
0072     num = src_ofs / card->blocklen;
0073     if (num > card->parts[partition].numblocks)
0074         goto failed;
0075 
0076     vblock = kmalloc(sizeof(struct vmu_block), GFP_KERNEL);
0077     if (!vblock)
0078         goto failed;
0079 
0080     vblock->num = num;
0081     vblock->ofs = src_ofs % card->blocklen;
0082     return vblock;
0083 
0084 failed:
0085     return NULL;
0086 }
0087 
0088 /* Maple bus callback function for reads */
0089 static void vmu_blockread(struct mapleq *mq)
0090 {
0091     struct maple_device *mdev;
0092     struct memcard *card;
0093 
0094     mdev = mq->dev;
0095     card = maple_get_drvdata(mdev);
0096     /* copy the read in data */
0097 
0098     if (unlikely(!card->blockread))
0099         return;
0100 
0101     memcpy(card->blockread, mq->recvbuf->buf + 12,
0102         card->blocklen/card->readcnt);
0103 
0104 }
0105 
0106 /* Interface with maple bus to read blocks
0107  * caching the results so that other parts
0108  * of the driver can access block reads */
0109 static int maple_vmu_read_block(unsigned int num, unsigned char *buf,
0110     struct mtd_info *mtd)
0111 {
0112     struct memcard *card;
0113     struct mdev_part *mpart;
0114     struct maple_device *mdev;
0115     int partition, error = 0, x, wait;
0116     unsigned char *blockread = NULL;
0117     struct vmu_cache *pcache;
0118     __be32 sendbuf;
0119 
0120     mpart = mtd->priv;
0121     mdev = mpart->mdev;
0122     partition = mpart->partition;
0123     card = maple_get_drvdata(mdev);
0124     pcache = card->parts[partition].pcache;
0125     pcache->valid = 0;
0126 
0127     /* prepare the cache for this block */
0128     if (!pcache->buffer) {
0129         pcache->buffer = kmalloc(card->blocklen, GFP_KERNEL);
0130         if (!pcache->buffer) {
0131             dev_err(&mdev->dev, "VMU at (%d, %d) - read fails due"
0132                 " to lack of memory\n", mdev->port,
0133                 mdev->unit);
0134             error = -ENOMEM;
0135             goto outB;
0136         }
0137     }
0138 
0139     /*
0140     * Reads may be phased - again the hardware spec
0141     * supports this - though may not be any devices in
0142     * the wild that implement it, but we will here
0143     */
0144     for (x = 0; x < card->readcnt; x++) {
0145         sendbuf = cpu_to_be32(partition << 24 | x << 16 | num);
0146 
0147         if (atomic_read(&mdev->busy) == 1) {
0148             wait_event_interruptible_timeout(mdev->maple_wait,
0149                 atomic_read(&mdev->busy) == 0, HZ);
0150             if (atomic_read(&mdev->busy) == 1) {
0151                 dev_notice(&mdev->dev, "VMU at (%d, %d)"
0152                     " is busy\n", mdev->port, mdev->unit);
0153                 error = -EAGAIN;
0154                 goto outB;
0155             }
0156         }
0157 
0158         atomic_set(&mdev->busy, 1);
0159         blockread = kmalloc(card->blocklen/card->readcnt, GFP_KERNEL);
0160         if (!blockread) {
0161             error = -ENOMEM;
0162             atomic_set(&mdev->busy, 0);
0163             goto outB;
0164         }
0165         card->blockread = blockread;
0166 
0167         maple_getcond_callback(mdev, vmu_blockread, 0,
0168             MAPLE_FUNC_MEMCARD);
0169         error = maple_add_packet(mdev, MAPLE_FUNC_MEMCARD,
0170                 MAPLE_COMMAND_BREAD, 2, &sendbuf);
0171         /* Very long timeouts seem to be needed when box is stressed */
0172         wait = wait_event_interruptible_timeout(mdev->maple_wait,
0173             (atomic_read(&mdev->busy) == 0 ||
0174             atomic_read(&mdev->busy) == 2), HZ * 3);
0175         /*
0176         * MTD layer does not handle hotplugging well
0177         * so have to return errors when VMU is unplugged
0178         * in the middle of a read (busy == 2)
0179         */
0180         if (error || atomic_read(&mdev->busy) == 2) {
0181             if (atomic_read(&mdev->busy) == 2)
0182                 error = -ENXIO;
0183             atomic_set(&mdev->busy, 0);
0184             card->blockread = NULL;
0185             goto outA;
0186         }
0187         if (wait == 0 || wait == -ERESTARTSYS) {
0188             card->blockread = NULL;
0189             atomic_set(&mdev->busy, 0);
0190             error = -EIO;
0191             list_del_init(&(mdev->mq->list));
0192             kfree(mdev->mq->sendbuf);
0193             mdev->mq->sendbuf = NULL;
0194             if (wait == -ERESTARTSYS) {
0195                 dev_warn(&mdev->dev, "VMU read on (%d, %d)"
0196                     " interrupted on block 0x%X\n",
0197                     mdev->port, mdev->unit, num);
0198             } else
0199                 dev_notice(&mdev->dev, "VMU read on (%d, %d)"
0200                     " timed out on block 0x%X\n",
0201                     mdev->port, mdev->unit, num);
0202             goto outA;
0203         }
0204 
0205         memcpy(buf + (card->blocklen/card->readcnt) * x, blockread,
0206             card->blocklen/card->readcnt);
0207 
0208         memcpy(pcache->buffer + (card->blocklen/card->readcnt) * x,
0209             card->blockread, card->blocklen/card->readcnt);
0210         card->blockread = NULL;
0211         pcache->block = num;
0212         pcache->jiffies_atc = jiffies;
0213         pcache->valid = 1;
0214         kfree(blockread);
0215     }
0216 
0217     return error;
0218 
0219 outA:
0220     kfree(blockread);
0221 outB:
0222     return error;
0223 }
0224 
0225 /* communicate with maple bus for phased writing */
0226 static int maple_vmu_write_block(unsigned int num, const unsigned char *buf,
0227     struct mtd_info *mtd)
0228 {
0229     struct memcard *card;
0230     struct mdev_part *mpart;
0231     struct maple_device *mdev;
0232     int partition, error, locking, x, phaselen, wait;
0233     __be32 *sendbuf;
0234 
0235     mpart = mtd->priv;
0236     mdev = mpart->mdev;
0237     partition = mpart->partition;
0238     card = maple_get_drvdata(mdev);
0239 
0240     phaselen = card->blocklen/card->writecnt;
0241 
0242     sendbuf = kmalloc(phaselen + 4, GFP_KERNEL);
0243     if (!sendbuf) {
0244         error = -ENOMEM;
0245         goto fail_nosendbuf;
0246     }
0247     for (x = 0; x < card->writecnt; x++) {
0248         sendbuf[0] = cpu_to_be32(partition << 24 | x << 16 | num);
0249         memcpy(&sendbuf[1], buf + phaselen * x, phaselen);
0250         /* wait until the device is not busy doing something else
0251         * or 1 second - which ever is longer */
0252         if (atomic_read(&mdev->busy) == 1) {
0253             wait_event_interruptible_timeout(mdev->maple_wait,
0254                 atomic_read(&mdev->busy) == 0, HZ);
0255             if (atomic_read(&mdev->busy) == 1) {
0256                 error = -EBUSY;
0257                 dev_notice(&mdev->dev, "VMU write at (%d, %d)"
0258                     "failed - device is busy\n",
0259                     mdev->port, mdev->unit);
0260                 goto fail_nolock;
0261             }
0262         }
0263         atomic_set(&mdev->busy, 1);
0264 
0265         locking = maple_add_packet(mdev, MAPLE_FUNC_MEMCARD,
0266             MAPLE_COMMAND_BWRITE, phaselen / 4 + 2, sendbuf);
0267         wait = wait_event_interruptible_timeout(mdev->maple_wait,
0268             atomic_read(&mdev->busy) == 0, HZ/10);
0269         if (locking) {
0270             error = -EIO;
0271             atomic_set(&mdev->busy, 0);
0272             goto fail_nolock;
0273         }
0274         if (atomic_read(&mdev->busy) == 2) {
0275             atomic_set(&mdev->busy, 0);
0276         } else if (wait == 0 || wait == -ERESTARTSYS) {
0277             error = -EIO;
0278             dev_warn(&mdev->dev, "Write at (%d, %d) of block"
0279                 " 0x%X at phase %d failed: could not"
0280                 " communicate with VMU", mdev->port,
0281                 mdev->unit, num, x);
0282             atomic_set(&mdev->busy, 0);
0283             kfree(mdev->mq->sendbuf);
0284             mdev->mq->sendbuf = NULL;
0285             list_del_init(&(mdev->mq->list));
0286             goto fail_nolock;
0287         }
0288     }
0289     kfree(sendbuf);
0290 
0291     return card->blocklen;
0292 
0293 fail_nolock:
0294     kfree(sendbuf);
0295 fail_nosendbuf:
0296     dev_err(&mdev->dev, "VMU (%d, %d): write failed\n", mdev->port,
0297         mdev->unit);
0298     return error;
0299 }
0300 
0301 /* mtd function to simulate reading byte by byte */
0302 static unsigned char vmu_flash_read_char(unsigned long ofs, int *retval,
0303     struct mtd_info *mtd)
0304 {
0305     struct vmu_block *vblock;
0306     struct memcard *card;
0307     struct mdev_part *mpart;
0308     struct maple_device *mdev;
0309     unsigned char *buf, ret;
0310     int partition, error;
0311 
0312     mpart = mtd->priv;
0313     mdev = mpart->mdev;
0314     partition = mpart->partition;
0315     card = maple_get_drvdata(mdev);
0316     *retval =  0;
0317 
0318     buf = kmalloc(card->blocklen, GFP_KERNEL);
0319     if (!buf) {
0320         *retval = 1;
0321         ret = -ENOMEM;
0322         goto finish;
0323     }
0324 
0325     vblock = ofs_to_block(ofs, mtd, partition);
0326     if (!vblock) {
0327         *retval = 3;
0328         ret = -ENOMEM;
0329         goto out_buf;
0330     }
0331 
0332     error = maple_vmu_read_block(vblock->num, buf, mtd);
0333     if (error) {
0334         ret = error;
0335         *retval = 2;
0336         goto out_vblock;
0337     }
0338 
0339     ret = buf[vblock->ofs];
0340 
0341 out_vblock:
0342     kfree(vblock);
0343 out_buf:
0344     kfree(buf);
0345 finish:
0346     return ret;
0347 }
0348 
0349 /* mtd higher order function to read flash */
0350 static int vmu_flash_read(struct mtd_info *mtd, loff_t from, size_t len,
0351     size_t *retlen,  u_char *buf)
0352 {
0353     struct maple_device *mdev;
0354     struct memcard *card;
0355     struct mdev_part *mpart;
0356     struct vmu_cache *pcache;
0357     struct vmu_block *vblock;
0358     int index = 0, retval, partition, leftover, numblocks;
0359     unsigned char cx;
0360 
0361     mpart = mtd->priv;
0362     mdev = mpart->mdev;
0363     partition = mpart->partition;
0364     card = maple_get_drvdata(mdev);
0365 
0366     numblocks = card->parts[partition].numblocks;
0367     if (from + len > numblocks * card->blocklen)
0368         len = numblocks * card->blocklen - from;
0369     if (len == 0)
0370         return -EIO;
0371     /* Have we cached this bit already? */
0372     pcache = card->parts[partition].pcache;
0373     do {
0374         vblock =  ofs_to_block(from + index, mtd, partition);
0375         if (!vblock)
0376             return -ENOMEM;
0377         /* Have we cached this and is the cache valid and timely? */
0378         if (pcache->valid &&
0379             time_before(jiffies, pcache->jiffies_atc + HZ) &&
0380             (pcache->block == vblock->num)) {
0381             /* we have cached it, so do necessary copying */
0382             leftover = card->blocklen - vblock->ofs;
0383             if (vblock->ofs + len - index < card->blocklen) {
0384                 /* only a bit of this block to copy */
0385                 memcpy(buf + index,
0386                     pcache->buffer + vblock->ofs,
0387                     len - index);
0388                 index = len;
0389             } else {
0390                 /* otherwise copy remainder of whole block */
0391                 memcpy(buf + index, pcache->buffer +
0392                     vblock->ofs, leftover);
0393                 index += leftover;
0394             }
0395         } else {
0396             /*
0397             * Not cached so read one byte -
0398             * but cache the rest of the block
0399             */
0400             cx = vmu_flash_read_char(from + index, &retval, mtd);
0401             if (retval) {
0402                 *retlen = index;
0403                 kfree(vblock);
0404                 return cx;
0405             }
0406             memset(buf + index, cx, 1);
0407             index++;
0408         }
0409         kfree(vblock);
0410     } while (len > index);
0411     *retlen = index;
0412 
0413     return 0;
0414 }
0415 
0416 static int vmu_flash_write(struct mtd_info *mtd, loff_t to, size_t len,
0417     size_t *retlen, const u_char *buf)
0418 {
0419     struct maple_device *mdev;
0420     struct memcard *card;
0421     struct mdev_part *mpart;
0422     int index = 0, partition, error = 0, numblocks;
0423     struct vmu_cache *pcache;
0424     struct vmu_block *vblock;
0425     unsigned char *buffer;
0426 
0427     mpart = mtd->priv;
0428     mdev = mpart->mdev;
0429     partition = mpart->partition;
0430     card = maple_get_drvdata(mdev);
0431 
0432     numblocks = card->parts[partition].numblocks;
0433     if (to + len > numblocks * card->blocklen)
0434         len = numblocks * card->blocklen - to;
0435     if (len == 0) {
0436         error = -EIO;
0437         goto failed;
0438     }
0439 
0440     vblock = ofs_to_block(to, mtd, partition);
0441     if (!vblock) {
0442         error = -ENOMEM;
0443         goto failed;
0444     }
0445 
0446     buffer = kmalloc(card->blocklen, GFP_KERNEL);
0447     if (!buffer) {
0448         error = -ENOMEM;
0449         goto fail_buffer;
0450     }
0451 
0452     do {
0453         /* Read in the block we are to write to */
0454         error = maple_vmu_read_block(vblock->num, buffer, mtd);
0455         if (error)
0456             goto fail_io;
0457 
0458         do {
0459             buffer[vblock->ofs] = buf[index];
0460             vblock->ofs++;
0461             index++;
0462             if (index >= len)
0463                 break;
0464         } while (vblock->ofs < card->blocklen);
0465 
0466         /* write out new buffer */
0467         error = maple_vmu_write_block(vblock->num, buffer, mtd);
0468         /* invalidate the cache */
0469         pcache = card->parts[partition].pcache;
0470         pcache->valid = 0;
0471 
0472         if (error != card->blocklen)
0473             goto fail_io;
0474 
0475         vblock->num++;
0476         vblock->ofs = 0;
0477     } while (len > index);
0478 
0479     kfree(buffer);
0480     *retlen = index;
0481     kfree(vblock);
0482     return 0;
0483 
0484 fail_io:
0485     kfree(buffer);
0486 fail_buffer:
0487     kfree(vblock);
0488 failed:
0489     dev_err(&mdev->dev, "VMU write failing with error %d\n", error);
0490     return error;
0491 }
0492 
0493 static void vmu_flash_sync(struct mtd_info *mtd)
0494 {
0495     /* Do nothing here */
0496 }
0497 
0498 /* Maple bus callback function to recursively query hardware details */
0499 static void vmu_queryblocks(struct mapleq *mq)
0500 {
0501     struct maple_device *mdev;
0502     unsigned short *res;
0503     struct memcard *card;
0504     __be32 partnum;
0505     struct vmu_cache *pcache;
0506     struct mdev_part *mpart;
0507     struct mtd_info *mtd_cur;
0508     struct vmupart *part_cur;
0509     int error;
0510 
0511     mdev = mq->dev;
0512     card = maple_get_drvdata(mdev);
0513     res = (unsigned short *) (mq->recvbuf->buf);
0514     card->tempA = res[12];
0515     card->tempB = res[6];
0516 
0517     dev_info(&mdev->dev, "VMU device at partition %d has %d user "
0518         "blocks with a root block at %d\n", card->partition,
0519         card->tempA, card->tempB);
0520 
0521     part_cur = &card->parts[card->partition];
0522     part_cur->user_blocks = card->tempA;
0523     part_cur->root_block = card->tempB;
0524     part_cur->numblocks = card->tempB + 1;
0525     part_cur->name = kmalloc(12, GFP_KERNEL);
0526     if (!part_cur->name)
0527         goto fail_name;
0528 
0529     sprintf(part_cur->name, "vmu%d.%d.%d",
0530         mdev->port, mdev->unit, card->partition);
0531     mtd_cur = &card->mtd[card->partition];
0532     mtd_cur->name = part_cur->name;
0533     mtd_cur->type = 8;
0534     mtd_cur->flags = MTD_WRITEABLE|MTD_NO_ERASE;
0535     mtd_cur->size = part_cur->numblocks * card->blocklen;
0536     mtd_cur->erasesize = card->blocklen;
0537     mtd_cur->_write = vmu_flash_write;
0538     mtd_cur->_read = vmu_flash_read;
0539     mtd_cur->_sync = vmu_flash_sync;
0540     mtd_cur->writesize = card->blocklen;
0541 
0542     mpart = kmalloc(sizeof(struct mdev_part), GFP_KERNEL);
0543     if (!mpart)
0544         goto fail_mpart;
0545 
0546     mpart->mdev = mdev;
0547     mpart->partition = card->partition;
0548     mtd_cur->priv = mpart;
0549     mtd_cur->owner = THIS_MODULE;
0550 
0551     pcache = kzalloc(sizeof(struct vmu_cache), GFP_KERNEL);
0552     if (!pcache)
0553         goto fail_cache_create;
0554     part_cur->pcache = pcache;
0555 
0556     error = mtd_device_register(mtd_cur, NULL, 0);
0557     if (error)
0558         goto fail_mtd_register;
0559 
0560     maple_getcond_callback(mdev, NULL, 0,
0561         MAPLE_FUNC_MEMCARD);
0562 
0563     /*
0564     * Set up a recursive call to the (probably theoretical)
0565     * second or more partition
0566     */
0567     if (++card->partition < card->partitions) {
0568         partnum = cpu_to_be32(card->partition << 24);
0569         maple_getcond_callback(mdev, vmu_queryblocks, 0,
0570             MAPLE_FUNC_MEMCARD);
0571         maple_add_packet(mdev, MAPLE_FUNC_MEMCARD,
0572             MAPLE_COMMAND_GETMINFO, 2, &partnum);
0573     }
0574     return;
0575 
0576 fail_mtd_register:
0577     dev_err(&mdev->dev, "Could not register maple device at (%d, %d)"
0578         "error is 0x%X\n", mdev->port, mdev->unit, error);
0579     for (error = 0; error <= card->partition; error++) {
0580         kfree(((card->parts)[error]).pcache);
0581         ((card->parts)[error]).pcache = NULL;
0582     }
0583 fail_cache_create:
0584 fail_mpart:
0585     for (error = 0; error <= card->partition; error++) {
0586         kfree(((card->mtd)[error]).priv);
0587         ((card->mtd)[error]).priv = NULL;
0588     }
0589     maple_getcond_callback(mdev, NULL, 0,
0590         MAPLE_FUNC_MEMCARD);
0591     kfree(part_cur->name);
0592 fail_name:
0593     return;
0594 }
0595 
0596 /* Handles very basic info about the flash, queries for details */
0597 static int vmu_connect(struct maple_device *mdev)
0598 {
0599     unsigned long test_flash_data, basic_flash_data;
0600     int c, error;
0601     struct memcard *card;
0602     u32 partnum = 0;
0603 
0604     test_flash_data = be32_to_cpu(mdev->devinfo.function);
0605     /* Need to count how many bits are set - to find out which
0606      * function_data element has details of the memory card
0607      */
0608     c = hweight_long(test_flash_data);
0609 
0610     basic_flash_data = be32_to_cpu(mdev->devinfo.function_data[c - 1]);
0611 
0612     card = kmalloc(sizeof(struct memcard), GFP_KERNEL);
0613     if (!card) {
0614         error = -ENOMEM;
0615         goto fail_nomem;
0616     }
0617 
0618     card->partitions = (basic_flash_data >> 24 & 0xFF) + 1;
0619     card->blocklen = ((basic_flash_data >> 16 & 0xFF) + 1) << 5;
0620     card->writecnt = basic_flash_data >> 12 & 0xF;
0621     card->readcnt = basic_flash_data >> 8 & 0xF;
0622     card->removable = basic_flash_data >> 7 & 1;
0623 
0624     card->partition = 0;
0625 
0626     /*
0627     * Not sure there are actually any multi-partition devices in the
0628     * real world, but the hardware supports them, so, so will we
0629     */
0630     card->parts = kmalloc_array(card->partitions, sizeof(struct vmupart),
0631                     GFP_KERNEL);
0632     if (!card->parts) {
0633         error = -ENOMEM;
0634         goto fail_partitions;
0635     }
0636 
0637     card->mtd = kmalloc_array(card->partitions, sizeof(struct mtd_info),
0638                   GFP_KERNEL);
0639     if (!card->mtd) {
0640         error = -ENOMEM;
0641         goto fail_mtd_info;
0642     }
0643 
0644     maple_set_drvdata(mdev, card);
0645 
0646     /*
0647     * We want to trap meminfo not get cond
0648     * so set interval to zero, but rely on maple bus
0649     * driver to pass back the results of the meminfo
0650     */
0651     maple_getcond_callback(mdev, vmu_queryblocks, 0,
0652         MAPLE_FUNC_MEMCARD);
0653 
0654     /* Make sure we are clear to go */
0655     if (atomic_read(&mdev->busy) == 1) {
0656         wait_event_interruptible_timeout(mdev->maple_wait,
0657             atomic_read(&mdev->busy) == 0, HZ);
0658         if (atomic_read(&mdev->busy) == 1) {
0659             dev_notice(&mdev->dev, "VMU at (%d, %d) is busy\n",
0660                 mdev->port, mdev->unit);
0661             error = -EAGAIN;
0662             goto fail_device_busy;
0663         }
0664     }
0665 
0666     atomic_set(&mdev->busy, 1);
0667 
0668     /*
0669     * Set up the minfo call: vmu_queryblocks will handle
0670     * the information passed back
0671     */
0672     error = maple_add_packet(mdev, MAPLE_FUNC_MEMCARD,
0673         MAPLE_COMMAND_GETMINFO, 2, &partnum);
0674     if (error) {
0675         dev_err(&mdev->dev, "Could not lock VMU at (%d, %d)"
0676             " error is 0x%X\n", mdev->port, mdev->unit, error);
0677         goto fail_mtd_info;
0678     }
0679     return 0;
0680 
0681 fail_device_busy:
0682     kfree(card->mtd);
0683 fail_mtd_info:
0684     kfree(card->parts);
0685 fail_partitions:
0686     kfree(card);
0687 fail_nomem:
0688     return error;
0689 }
0690 
0691 static void vmu_disconnect(struct maple_device *mdev)
0692 {
0693     struct memcard *card;
0694     struct mdev_part *mpart;
0695     int x;
0696 
0697     mdev->callback = NULL;
0698     card = maple_get_drvdata(mdev);
0699     for (x = 0; x < card->partitions; x++) {
0700         mpart = ((card->mtd)[x]).priv;
0701         mpart->mdev = NULL;
0702         mtd_device_unregister(&((card->mtd)[x]));
0703         kfree(((card->parts)[x]).name);
0704     }
0705     kfree(card->parts);
0706     kfree(card->mtd);
0707     kfree(card);
0708 }
0709 
0710 /* Callback to handle eccentricities of both mtd subsystem
0711  * and general flakyness of Dreamcast VMUs
0712  */
0713 static int vmu_can_unload(struct maple_device *mdev)
0714 {
0715     struct memcard *card;
0716     int x;
0717     struct mtd_info *mtd;
0718 
0719     card = maple_get_drvdata(mdev);
0720     for (x = 0; x < card->partitions; x++) {
0721         mtd = &((card->mtd)[x]);
0722         if (mtd->usecount > 0)
0723             return 0;
0724     }
0725     return 1;
0726 }
0727 
0728 #define ERRSTR "VMU at (%d, %d) file error -"
0729 
0730 static void vmu_file_error(struct maple_device *mdev, void *recvbuf)
0731 {
0732     enum maple_file_errors error = ((int *)recvbuf)[1];
0733 
0734     switch (error) {
0735 
0736     case MAPLE_FILEERR_INVALID_PARTITION:
0737         dev_notice(&mdev->dev, ERRSTR " invalid partition number\n",
0738             mdev->port, mdev->unit);
0739         break;
0740 
0741     case MAPLE_FILEERR_PHASE_ERROR:
0742         dev_notice(&mdev->dev, ERRSTR " phase error\n",
0743             mdev->port, mdev->unit);
0744         break;
0745 
0746     case MAPLE_FILEERR_INVALID_BLOCK:
0747         dev_notice(&mdev->dev, ERRSTR " invalid block number\n",
0748             mdev->port, mdev->unit);
0749         break;
0750 
0751     case MAPLE_FILEERR_WRITE_ERROR:
0752         dev_notice(&mdev->dev, ERRSTR " write error\n",
0753             mdev->port, mdev->unit);
0754         break;
0755 
0756     case MAPLE_FILEERR_INVALID_WRITE_LENGTH:
0757         dev_notice(&mdev->dev, ERRSTR " invalid write length\n",
0758             mdev->port, mdev->unit);
0759         break;
0760 
0761     case MAPLE_FILEERR_BAD_CRC:
0762         dev_notice(&mdev->dev, ERRSTR " bad CRC\n",
0763             mdev->port, mdev->unit);
0764         break;
0765 
0766     default:
0767         dev_notice(&mdev->dev, ERRSTR " 0x%X\n",
0768             mdev->port, mdev->unit, error);
0769     }
0770 }
0771 
0772 
0773 static int probe_maple_vmu(struct device *dev)
0774 {
0775     struct maple_device *mdev = to_maple_dev(dev);
0776     struct maple_driver *mdrv = to_maple_driver(dev->driver);
0777 
0778     mdev->can_unload = vmu_can_unload;
0779     mdev->fileerr_handler = vmu_file_error;
0780     mdev->driver = mdrv;
0781 
0782     return vmu_connect(mdev);
0783 }
0784 
0785 static int remove_maple_vmu(struct device *dev)
0786 {
0787     struct maple_device *mdev = to_maple_dev(dev);
0788 
0789     vmu_disconnect(mdev);
0790     return 0;
0791 }
0792 
0793 static struct maple_driver vmu_flash_driver = {
0794     .function = MAPLE_FUNC_MEMCARD,
0795     .drv = {
0796         .name =     "Dreamcast_visual_memory",
0797         .probe =    probe_maple_vmu,
0798         .remove =   remove_maple_vmu,
0799     },
0800 };
0801 
0802 static int __init vmu_flash_map_init(void)
0803 {
0804     return maple_driver_register(&vmu_flash_driver);
0805 }
0806 
0807 static void __exit vmu_flash_map_exit(void)
0808 {
0809     maple_driver_unregister(&vmu_flash_driver);
0810 }
0811 
0812 module_init(vmu_flash_map_init);
0813 module_exit(vmu_flash_map_exit);
0814 
0815 MODULE_LICENSE("GPL");
0816 MODULE_AUTHOR("Adrian McMenamin");
0817 MODULE_DESCRIPTION("Flash mapping for Sega Dreamcast visual memory");