From: Adrian M. <zx8...@us...> - 2002-08-22 22:15:29
|
Update of /cvsroot/linuxdc/linux-sh-dc/drivers/mtd/maps In directory usw-pr-cvs1:/tmp/cvs-serv31168/drivers/mtd/maps Modified Files: vmu-flash.c Log Message: Updated and almost working VMU Flash driver Index: vmu-flash.c =================================================================== RCS file: /cvsroot/linuxdc/linux-sh-dc/drivers/mtd/maps/vmu-flash.c,v retrieving revision 1.1 retrieving revision 1.2 diff -u -d -r1.1 -r1.2 --- vmu-flash.c 28 Sep 2001 06:31:47 -0000 1.1 +++ vmu-flash.c 22 Aug 2002 22:15:22 -0000 1.2 @@ -2,6 +2,10 @@ * drivers/mtd/maps/vmu-flash.c * * (C)opyright 2001 Paul Mundt <le...@ch...> + + + + + + Messed about with and fragments copyright 2002, Adrian McMenamin <ad...@mc...> + + * * Flash mapping handler for the Sega Dreamcast VMU. * @@ -26,12 +30,111 @@ /* MTD Information */ static struct mtd_info *vmu_flash_mtd = NULL; +/* Persistent result */ +static struct mapleq *lastmq; +static struct maple_driver dc_flashmap_driver; +char *block_buffer = NULL; + +int waken_up = 1; + /* VMU Block */ typedef struct block_s { unsigned int num; /* Block Number */ unsigned int ofs; /* Block Offset */ } block_t; +/*************************************/ +/**********Read and write routines*************/ +int maple_vmu_read_block(unsigned int num, u_char * buf) +{ + + /* async maple call + assemble maple call + wait for return */ + + + /* Sanity check */ + if (!vmu_flash_mtd) { + printk(KERN_WARNING + "VMU FLASH: Attempting to read data without having set up mtd.\n"); + return -1; + } + + struct maple_driver_data *mdd = + (struct maple_driver_data *) (vmu_flash_mtd->priv); + struct mapleq *mqu = (struct mapleq *) &(mdd->mq); + mqu->command = 11; + mqu->length = 2; + + ((unsigned long *) (mqu->recvbuf))[0] = + cpu_to_be32(MAPLE_FUNC_MEMCARD); + + ((unsigned long *) (mqu->recvbuf))[1] = num; + mqu->sendbuf = mqu->recvbuf; + if (maple_add_packet(mqu) != 0) { + printk(KERN_WARNING "VMU FLASH: Could not add packet\n"); + return -1; + } + + lastmq = NULL; + wait_queue_head_t wq_mq; + init_waitqueue_head(&wq_mq); + do { + interruptible_sleep_on_timeout(&wq_mq, 1); + } while (lastmq == NULL); + + /* Now check if we've got a proper return */ + + if (block_buffer){ + memcpy(block_buffer, buf, 512); + kfree(block_buffer); + block_buffer = NULL; + return 0; + } + + printk(KERN_WARNING "VMU FLASH: Read has failed\n"); + + return -1; + +} + +int maple_vmu_write_block(unsigned int num, u_char * buf) +{ + + /* This function does not have to sleep */ + + /* Sanity check */ + if (!vmu_flash_mtd) { + printk(KERN_WARNING + "VMU FLASH: Attempting to write data without having set up mtd.\n"); + return -1; + } + + struct maple_driver_data *mdd = + (struct maple_driver_data *) (vmu_flash_mtd->priv); + struct mapleq *mqu = (struct mapleq *) &(mdd->mq); + mqu->command = 12; + mqu->length = 514; + + ((unsigned long *) (mqu->recvbuf))[0] = + cpu_to_be32(MAPLE_FUNC_MEMCARD); + + ((unsigned long *) (mqu->recvbuf))[1] = num; + memcpy((mqu->recvbuf) + 8, buf, 512); + + mqu->sendbuf = mqu->recvbuf; + if (maple_add_packet(mqu) != 0) { + printk(KERN_WARNING "VMU FLASH: Could not add packet\n"); + return -1; + } + + return 0; + +} + +/*************************************/ + + /** * __ofs_to_block - Offset to Block Conversion * @@ -56,27 +159,29 @@ /* Zero the block */ memset(block, 0, sizeof(struct block_s)); - + /* Make sure we don't overstep our boundaries */ if (src_ofs >= VMU_NUM_BLOCKS * VMU_BLOCK_SIZE) { - printk(KERN_WARNING "Source offset exceeds total offset\n"); + printk(KERN_WARNING + "Source offset exceeds total offset\n"); kfree(block); return NULL; } /* Find the block number */ - block->num = (unsigned int)(src_ofs / VMU_BLOCK_SIZE); + block->num = (unsigned int) (src_ofs / VMU_BLOCK_SIZE); /* Validate we've got a valid block */ if (block->num > VMU_NUM_BLOCKS) { - printk(KERN_WARNING "Block number exceeds number of blocks\n"); + printk(KERN_WARNING + "Block number exceeds number of blocks\n"); kfree(block); return NULL; } - + /* Calculate remaining offset in block */ - block->ofs = (unsigned int)(src_ofs % VMU_BLOCK_SIZE); - + block->ofs = (unsigned int) (src_ofs % VMU_BLOCK_SIZE); + return block; } @@ -90,33 +195,36 @@ * Reads a byte from a VMU at the specified offset. * */ -static __u8 vmu_flash_read8(struct map_info *map, unsigned long ofs) +static __u8 vmu_flash_read8(unsigned long ofs, long *retval) { block_t *block; - u_char *buf = NULL; - + *retval = 0; + u_char *buf = kmalloc(GFP_KERNEL, 512); /* Find the block */ block = __ofs_to_block(ofs); /* Validate it was found */ if (!block) { printk(KERN_WARNING "Got an invalid block\n"); - return 1; + *retval = 1; + return -1; } - /* Read the block */ - if (maple_vmu_read_block(vmu_flash_mdev, block->num, buf)) { + if (maple_vmu_read_block(block->num, buf) == -1) { printk(KERN_WARNING "Can't read block: %d\n", block->num); kfree(block); - return 1; + *retval = 2; + return -1; } - /* Handle the remaining offset */ - buf += block->ofs; - + u_char *buf2 = buf; + buf2 += block->ofs; + kfree(block); + __u8 ret = (__u8) *buf2; + kfree(buf); - return (__u8)(*buf); + return ret; } /** @@ -129,10 +237,10 @@ * Writes a byte to a VMU at the specified offset. * */ -static void vmu_flash_write8(struct map_info *map, __u8 d, unsigned long ofs) +static void vmu_flash_write8(__u8 d, unsigned long ofs) { block_t *block; - u_char *buf = NULL; + u_char *buf = kmalloc(GFP_KERNEL, 512); /* Find the block */ block = __ofs_to_block(ofs); @@ -144,31 +252,80 @@ } /* Read the block */ - if (maple_vmu_read_block(vmu_flash_mdev, block->num, buf)) { + if (maple_vmu_read_block(block->num, buf)) { printk(KERN_WARNING "Can't read block: %d\n", block->num); kfree(block); return; } /* Copy the byte to the block */ - (__u8)(*(buf + block->ofs)) = d; + (__u8) (*(buf + block->ofs)) = d; /* Write the block */ - if (maple_vmu_write_block(vmu_flash_mdev, block->num, buf)) { + if (maple_vmu_write_block(block->num, buf)) { printk(KERN_WARNING "Can't write block: %d\n", block->num); kfree(block); return; } kfree(block); + kfree(buf); } -static struct map_info vmu_flash_map = { - name: "VMU Flash", - size: VMU_NUM_BLOCKS * VMU_BLOCK_SIZE, - read8: vmu_flash_read8, - write8: vmu_flash_write8, -}; +/***********************************************/ +/* Read and Write routines */ + +int vmu_flash_read(struct mtd_info *mtd, loff_t from, size_t len, + size_t *retlen, u_char * buf) +{ + printk("Reading from %llx with length %llx\n", from, len); + if (len < 1) + return -1; + if (len > (128 * 1024)) len = 128 * 1024; + int start_here = (int)(from & 0xffffffff); + long retval = 0; + int index = 0; + do { + u8 cx = vmu_flash_read8(start_here + index, &retval ); + if (retval){ + *retlen = index; + return -1; + } + memset(buf + index, cx, 1); + index++; + } while (len > index); + *retlen = index; + return 0; + +} + + +int vmu_flash_write(struct mtd_info *mtd, loff_t to, size_t *retlen, size_t len, + const u_char * buf) +{ + if (len < 1) + return -1; + int index = 0; + do { + vmu_flash_write8(buf[index], to + index); + index++; + } while (len > index); + *retlen = index; + return 0; +} + +int vmu_flash_erase(struct mtd_info *mtd, struct erase_info *erase) +{ + int *z = (int *)kmalloc(GFP_KERNEL, 4); + vmu_flash_write(mtd, erase->addr, erase->len, z, "\0"); + kfree(z); + return 0; +} + +void vmu_flash_sync(struct mtd_info *mtd) +{ + /* Do nothing */ +} /** * vmu_flash_map_init - Initialization @@ -178,27 +335,18 @@ */ static int __init vmu_flash_map_init(void) { - printk(KERN_NOTICE "Regestering VMU flash mapping\n"); + printk(KERN_NOTICE "VMU flash driver available\n"); + maple_register_driver(&dc_flashmap_driver); /* FIXME: We need to do something with the vmu_flash_mdev */ - /* Look for the flash */ - vmu_flash_mtd = do_map_probe("cfi", &vmu_flash_map); - /* See if it's valid */ - if (!vmu_flash_mtd) { - printk(KERN_ERR "Failed to setup flash map\n"); - return -ENXIO; - } - - vmu_flash_mtd->module = THIS_MODULE; - - /* Register with MTD */ - add_mtd_device(vmu_flash_mtd); return 0; } + + /** * vmu_flash_map_exit - Cleanup * @@ -208,7 +356,7 @@ static void __exit vmu_flash_map_exit(void) { printk(KERN_NOTICE "Unregestering VMU flash mapping\n"); - + maple_unregister_driver(&dc_flashmap_driver); /* See if there's anything to unregister */ if (!vmu_flash_mtd) { printk(KERN_WARNING "Nothing to unregister\n"); @@ -220,6 +368,107 @@ map_destroy(vmu_flash_mtd); } +/***********Maple functions***************/ + + +static void dc_flashmap_callback(struct maple_driver_data *data) +{ + + + struct mapleq *mq = &data->mq; + if (mq->recvbuf[0] == 8) { + block_buffer = kmalloc(GFP_KERNEL, 512); + /* How big a transfer is it? */ + memcpy(mq->recvbuf + 12, block_buffer, + (__u8)(mq->recvbuf[3]) * 2 - 8); + + + lastmq = mq; + return; + } + lastmq = mq; +} + + + +static int dc_flashmap_connect(struct maple_driver_data *d) +{ + printk + ("Registering VMU Flash mapping and loading VMU Flash driver\n"); + /* Look for the flash */ + if (!vmu_flash_mtd) { + /* Populate a mtd_info */ + vmu_flash_mtd = kmalloc(GFP_KERNEL, 1000); + vmu_flash_mtd->name = "Dreamcast VMU Flash"; + + /* This is 'other' */ + vmu_flash_mtd->type = MTD_OTHER; + vmu_flash_mtd->flags = 0; + vmu_flash_mtd->size = 1024 * 128; /* 128k */ + vmu_flash_mtd->erasesize = 512; + + /* Mandatory functions */ + vmu_flash_mtd->write = vmu_flash_write; + vmu_flash_mtd->read = vmu_flash_read; + vmu_flash_mtd->erase = vmu_flash_erase; + vmu_flash_mtd->sync = vmu_flash_sync; + /* Use private data to point to d */ + vmu_flash_mtd->priv = d; + } + + + vmu_flash_mtd->module = THIS_MODULE; + + /* Register with MTD */ + add_mtd_device(vmu_flash_mtd); + /* Lock the device in */ + vmu_flash_mtd = get_mtd_device(vmu_flash_mtd, -1); + if (!vmu_flash_mtd) { + printk(KERN_ERR + "VMU Flash driver initialisation failed\n"); + return -1; + } + return 0; +} + +static void dc_flashmap_disconnect(struct maple_driver_data *d) +{ + printk(KERN_NOTICE "Unregistering VMU flash mapping\n"); + + /* See if there's anything to unregister */ + if (!vmu_flash_mtd) { + printk(KERN_WARNING "Nothing to unregister\n"); + return; + } + + + if (vmu_flash_mtd) { + /* Unregister from MTD */ + put_mtd_device(vmu_flash_mtd); + del_mtd_device(vmu_flash_mtd); + kfree(vmu_flash_mtd); + vmu_flash_mtd = NULL; + } + + +} + + +/***********Maple device*****************/ +static struct maple_driver dc_flashmap_driver = { + function:MAPLE_FUNC_MEMCARD, + name:"VMU Flash Memory", + connect:dc_flashmap_connect, + disconnect:dc_flashmap_disconnect, + reply:dc_flashmap_callback, + + +}; + + + + + + module_init(vmu_flash_map_init); module_exit(vmu_flash_map_exit); - |