vmu-flash.c (19788B)
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 removable; 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->removable = 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 struct maple_device *mdev = to_maple_dev(dev); 776 struct maple_driver *mdrv = to_maple_driver(dev->driver); 777 778 mdev->can_unload = vmu_can_unload; 779 mdev->fileerr_handler = vmu_file_error; 780 mdev->driver = mdrv; 781 782 return vmu_connect(mdev); 783} 784 785static int remove_maple_vmu(struct device *dev) 786{ 787 struct maple_device *mdev = to_maple_dev(dev); 788 789 vmu_disconnect(mdev); 790 return 0; 791} 792 793static struct maple_driver vmu_flash_driver = { 794 .function = MAPLE_FUNC_MEMCARD, 795 .drv = { 796 .name = "Dreamcast_visual_memory", 797 .probe = probe_maple_vmu, 798 .remove = remove_maple_vmu, 799 }, 800}; 801 802static int __init vmu_flash_map_init(void) 803{ 804 return maple_driver_register(&vmu_flash_driver); 805} 806 807static void __exit vmu_flash_map_exit(void) 808{ 809 maple_driver_unregister(&vmu_flash_driver); 810} 811 812module_init(vmu_flash_map_init); 813module_exit(vmu_flash_map_exit); 814 815MODULE_LICENSE("GPL"); 816MODULE_AUTHOR("Adrian McMenamin"); 817MODULE_DESCRIPTION("Flash mapping for Sega Dreamcast visual memory");