📄 patch-2.4.19-mmc
字号:
+/******************************************************************/++static int __init mmc_media_init( void )+{+ int i, result;+ DEBUG(0,"\n");++ mmc_devfs_handle = devfs_mk_dir(NULL, DEVICE_NAME, NULL);+ if (!mmc_devfs_handle) return -EBUSY;++ result = devfs_register_blkdev(mmc_major, DEVICE_NAME, &mmc_bdops);+ if (result < 0) {+ printk(KERN_WARNING "Unable to get major %d for MMC media\n", mmc_major);+ return result;+ }++ if ( !mmc_major ) mmc_major = result;++ /* Set up global block arrays */+ read_ahead[mmc_major] = rahead;+ for(i=0 ; i < MMC_NDISK; i++)+ mmc_blk[i] = 512;+ hardsect_size[mmc_major] = mmc_blk;+ for(i=0; i < MMC_NDISK; i++)+ mmc_max[i] = maxsectors;+ max_sectors[mmc_major] = mmc_max;++ /* Start with zero-sized partitions : we'll fix this later */+ memset(mmc_sizes, 0, sizeof(int) * MMC_NDISK);+ blk_size[mmc_major] = mmc_sizes;++ /* Fix up the gendisk structure */+ mmc_gendisk.part = mmc_partitions;+ mmc_gendisk.sizes = mmc_sizes;+ mmc_gendisk.nr_real = 0;+ mmc_gendisk.de_arr = &mmc_devfs_handle;+ mmc_gendisk.flags = &mmc_gendisk_flags;+ mmc_gendisk.fops = &mmc_bdops;++ /* Add ourselves to the global list */+ mmc_gendisk.major = mmc_major;+ add_gendisk(&mmc_gendisk);+ + blk_init_queue(BLK_DEFAULT_QUEUE(mmc_major), DEVICE_REQUEST);+ return mmc_register_media_driver(&mmc_driver);+}++static void __exit mmc_media_cleanup( void )+{+ int i;+ DEBUG(0,"\n");++ flush_scheduled_tasks();+ unregister_blkdev(mmc_major, DEVICE_NAME);++ for ( i = 0 ; i < MMC_NDISK; i++ )+ fsync_dev(MKDEV(mmc_major,i));++ mmc_unregister_media_driver(&mmc_driver);++ blk_cleanup_queue(BLK_DEFAULT_QUEUE(mmc_major));++ blk_size[mmc_major] = NULL;+ hardsect_size[mmc_major] = NULL;+ max_sectors[mmc_major] = NULL;++ del_gendisk(&mmc_gendisk);++ devfs_unregister(mmc_devfs_handle);+}++struct mmc_media_module media_module = {+ init: mmc_media_init,+ cleanup: mmc_media_cleanup+};diff -ruwN -X dontdiff linux-2.4.19/drivers/mmc/mmc_media.h linux-2.4.19-mmc1/drivers/mmc/mmc_media.h--- linux-2.4.19/drivers/mmc/mmc_media.h Wed Dec 31 19:00:00 1969+++ linux-2.4.19-mmc1/drivers/mmc/mmc_media.h Fri Aug 9 16:07:33 2002@@ -0,0 +1,96 @@+/*+ * Header for MultiMediaCard (MMC)+ *+ * Copyright (c) 2002 Hewlett-Packard Company+ * + * Permission is hereby granted, free of charge, to any person obtaining a+ * copy of this software and associated documentation files (the+ * "Software"), to deal in the Software without restriction, including+ * without limitation the rights to use, copy, modify, merge, publish,+ * distribute, sublicense, and/or sell copies of the Software, and to+ * permit persons to whom the Software is furnished to do so, subject to+ * the following conditions:+ * + * The above copyright notice and this permission notice shall be included+ * in all copies or substantial portions of the Software.+ * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.+ *+ * Many thanks to Alessandro Rubini and Jonathan Corbet!+ *+ * Based strongly on code by:+ *+ * Author: Yong-iL Joh <tolkien@mizi.com>+ * Date : $Date: 2002/06/18 12:38:40 $ + *+ * Author: Andrew Christian+ * 15 May 2002+ */++#ifndef MMC_MMC_MEDIA_H+#define MMC_MMC_MEDIA_H++#include <linux/interrupt.h>+#include <linux/list.h>++#include <linux/mmc/mmc_protocol.h>++/* Set an upper bound for how many cards we'll support */+/* This is used only for static array initialization */+#define MMC_MAX_SLOTS 2++#define MMC_SLOT_FLAG_INSERT (1<<0)+#define MMC_SLOT_FLAG_EJECT (1<<1)++struct mmc_media_driver;++struct mmc_slot {+ int id; /* Card index */+ /* Card specific information */+ struct mmc_cid cid;+ struct mmc_csd csd;++ enum card_state state; /* empty, ident, ready, whatever */+ int flags; /* Ejected, inserted */++ /* Assigned media driver */+ struct mmc_media_driver *media_driver;+};++struct mmc_io_request {+ int id; /* Card index */+ int cmd; /* READ or WRITE */+ unsigned long sector; /* Start address */+ unsigned long nr_sectors; /* Length of read */+ unsigned long block_len; /* Size of sector (sanity check) */+ char *buffer; /* Data buffer */+};++/* Media driver (e.g., Flash card, I/O card...) */+struct mmc_media_driver {+ struct list_head node;+ char *name;+ void (*load)(struct mmc_slot *);+ void (*unload)(struct mmc_slot *);+ int (*probe)(struct mmc_slot *);+ void (*io_request_done)(struct mmc_io_request *, int result);+};++struct mmc_media_module {+ int (*init)(void);+ void (*cleanup)(void);+};++/* Calls made by the media driver */+extern int mmc_register_media_driver( struct mmc_media_driver * );+extern void mmc_unregister_media_driver( struct mmc_media_driver * );+extern void mmc_handle_io_request( struct mmc_io_request * );++#endif /* MMC_MMC_MEDIA_H */+diff -ruwN -X dontdiff linux-2.4.19/drivers/mmc/mmc_protocol.c linux-2.4.19-mmc1/drivers/mmc/mmc_protocol.c--- linux-2.4.19/drivers/mmc/mmc_protocol.c Wed Dec 31 19:00:00 1969+++ linux-2.4.19-mmc1/drivers/mmc/mmc_protocol.c Fri Aug 9 16:07:45 2002@@ -0,0 +1,440 @@+/*+ * MMC State machine functions+ *+ * Copyright (c) 2002 Hewlett-Packard Company+ * + * Permission is hereby granted, free of charge, to any person obtaining a+ * copy of this software and associated documentation files (the+ * "Software"), to deal in the Software without restriction, including+ * without limitation the rights to use, copy, modify, merge, publish,+ * distribute, sublicense, and/or sell copies of the Software, and to+ * permit persons to whom the Software is furnished to do so, subject to+ * the following conditions:+ * + * The above copyright notice and this permission notice shall be included+ * in all copies or substantial portions of the Software.+ * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.+ *+ * Many thanks to Alessandro Rubini and Jonathan Corbet!+ *+ * This part of the code is separated from mmc_core.o so we can+ * plug in different state machines (e.g., SPI, SD)+ *+ * This code assumes that you have exactly one card slot, no more.+ *+ * Author: Andrew Christian+ * 6 May 2002+ */++#include <linux/config.h>+#include <linux/module.h>++#include <linux/version.h>+#include <linux/proc_fs.h>++#include "mmc_core.h"++static void * mmc_cim_default_state( struct mmc_dev *dev, int first );++/******************************************************************+ *+ * Useful utility functions+ *+ ******************************************************************/++static int mmc_has_valid_request( struct mmc_dev *dev )+{+ struct mmc_io_request *request = dev->io_request;+ struct mmc_slot *slot;++ DEBUG(2," (%p)\n", request);++ if ( !request ) return 0;++ slot = dev->slot + request->id;++ if ( !slot->media_driver ) {+ DEBUG(0,": card doesn't have media driver\n");+ return 0;+ }++ return 1;+}++static void mmc_configure_card( struct mmc_dev *dev, int slot )+{+ u32 rate;+ DEBUG(2,": slot=%d\n", slot);++ /* Fix the clock rate */+ rate = mmc_tran_speed(dev->slot[slot].csd.tran_speed);+ if ( rate < MMC_CLOCK_SLOW )+ rate = MMC_CLOCK_SLOW;+ if ( rate > MMC_CLOCK_FAST )+ rate = MMC_CLOCK_FAST;++ dev->sdrive->set_clock(rate);+ + /* Match the drive media */+ mmc_match_media_driver(&dev->slot[slot]);+ run_sbin_mmc_hotplug(dev, slot, 1);+}++/* The blocks requested by the kernel may or may not+ match what we can do. Unfortunately, filesystems play+ fast and loose with block sizes, so we're stuck with this */++static void mmc_fix_request_block_size( struct mmc_dev *dev )+{+ struct mmc_io_request *t = dev->io_request;+ struct mmc_slot *slot = dev->slot + t->id;+ u16 block_len;++ DEBUG(1, ": io_request id=%d cmd=%d sector=%ld nr_sectors=%ld block_len=%ld buf=%p\n",+ t->id, t->cmd, t->sector, t->nr_sectors, t->block_len, t->buffer);++ switch( t->cmd ) {+ case READ:+ block_len = 1 << slot->csd.read_bl_len;+ break;+ case WRITE:+ block_len = 1 << slot->csd.write_bl_len;+ break;+ default:+ DEBUG(0,": unrecognized command %d\n", t->cmd);+ return;+ }++ if ( block_len < t->block_len ) {+ int scale = t->block_len / block_len;+ DEBUG(1,": scaling by %d from block_len=%d to %ld\n", + scale, block_len, t->block_len);+ t->block_len = block_len;+ t->sector *= scale;+ t->nr_sectors *= scale;+ }+}+++/******************************************************************+ * State machine routines to read and write data+ *+ * SET_BLOCKLEN only needs to be done once for each card.+ * SET_BLOCK_COUNT is only valid in MMC 3.1; most cards don't support this,+ * so we don't use it.+ * + * In the 2.x cards we have a choice between STREAMING mode and+ * SINGLE mode. There's an obvious performance possibility in + * using streaming mode, but at this time we're just using the SINGLE+ * mode.+ ******************************************************************/++static void * mmc_cim_read_write_block( struct mmc_dev *dev, int first )+{+ struct mmc_io_request *t = dev->io_request;+ struct mmc_response_r1 r1;+ struct mmc_slot *slot = dev->slot + t->id;+ int retval = 0;+ int i;++ DEBUG(2," first=%d\n",first);++ if ( first ) {+ mmc_fix_request_block_size( dev );++ switch ( slot->state ) {+ case CARD_STATE_STBY:+ mmc_simple_cmd(dev, MMC_SELECT_CARD, ID_TO_RCA(slot->id) << 16, RESPONSE_R1B );+ break;+ case CARD_STATE_TRAN:+ mmc_simple_cmd(dev, MMC_SET_BLOCKLEN, t->block_len, RESPONSE_R1 );+ break;+ default:+ DEBUG(0,": invalid card state %d\n", slot->state);+ goto read_block_error;+ break;+ }+ return NULL;+ }++ switch (dev->request.cmd) {+ case MMC_SELECT_CARD:+ if ( (retval = mmc_unpack_r1( &dev->request, &r1, slot->state )) )+ goto read_block_error;++ for ( i = 0 ; i < dev->num_slots ; i++ )+ dev->slot[i].state = ( i == t->id ? CARD_STATE_TRAN : CARD_STATE_STBY );++ mmc_simple_cmd(dev, MMC_SET_BLOCKLEN, t->block_len, RESPONSE_R1 );+ break;++ case MMC_SET_BLOCKLEN:+ if ( (retval = mmc_unpack_r1( &dev->request, &r1, slot->state )) )+ goto read_block_error;++ mmc_send_cmd(dev, (t->cmd == READ ? MMC_READ_SINGLE_BLOCK : MMC_WRITE_BLOCK), + t->sector * t->block_len, 1, t->block_len, RESPONSE_R1 );+ break;++ case MMC_READ_SINGLE_BLOCK:+ case MMC_WRITE_BLOCK:+ if ( (retval = mmc_unpack_r1( &dev->request, &r1, slot->state )) )+ goto read_block_error;++ t->nr_sectors--;+ t->sector++;+ t->buffer += t->block_len;++ if ( t->nr_sectors ) {+ mmc_send_cmd(dev, (t->cmd == READ ? MMC_READ_SINGLE_BLOCK : MMC_WRITE_BLOCK), + t->sector * t->block_len, 1, t->block_len, RESPONSE_R1 );+ }+ else {+ mmc_finish_io_request( dev, 1 );+ if ( mmc_has_valid_request(dev) )+ return mmc_cim_read_write_block;+ return mmc_cim_default_state;+ }+ break;++ default:+ goto read_block_error;+ break;+ }+ return NULL;++read_block_error:+ DEBUG(0,": failure during cmd %d, error %d (%s)\n", + dev->request.cmd, retval, mmc_result_to_string(retval));+ mmc_finish_io_request( dev, 0 ); // Failure+ return mmc_cim_default_state;+}++/* Update the card's status information in preparation to running a read/write cycle */++static void * mmc_cim_get_status( struct mmc_dev *dev, int first )+{+ struct mmc_slot *slot = dev->slot + dev->io_request->id;+ struct mmc_response_r1 r1;+ int retval = MMC_NO_ERROR;++ DEBUG(2," first=%d\n",first);++ if ( first ) {+ mmc_simple_cmd(dev, MMC_SEND_STATUS, ID_TO_RCA(slot->id) <<
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -