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