|
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);
-
|