⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pcmciamtd.c

📁 基于linux-2.6.28的mtd驱动
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * pcmciamtd.c - MTD driver for PCMCIA flash memory cards * * Author: Simon Evans <spse@secret.org.uk> * * Copyright (C) 2002 Simon Evans * * Licence: GPL * */#include <linux/module.h>#include <linux/slab.h>#include <linux/timer.h>#include <linux/init.h>#include <asm/io.h>#include <asm/system.h>#include <pcmcia/cs_types.h>#include <pcmcia/cs.h>#include <pcmcia/cistpl.h>#include <pcmcia/ds.h>#include <linux/mtd/map.h>#include <linux/mtd/mtd.h>#ifdef CONFIG_MTD_DEBUGstatic int debug = CONFIG_MTD_DEBUG_VERBOSE;module_param(debug, int, 0);MODULE_PARM_DESC(debug, "Set Debug Level 0=quiet, 5=noisy");#undef DEBUG#define DEBUG(n, format, arg...) \	if (n <= debug) {	 \		printk(KERN_DEBUG __FILE__ ":%s(): " format "\n", __func__ , ## arg); \	}#else#undef DEBUG#define DEBUG(n, arg...)static const int debug = 0;#endif#define err(format, arg...) printk(KERN_ERR "pcmciamtd: " format "\n" , ## arg)#define info(format, arg...) printk(KERN_INFO "pcmciamtd: " format "\n" , ## arg)#define warn(format, arg...) printk(KERN_WARNING "pcmciamtd: " format "\n" , ## arg)#define DRIVER_DESC	"PCMCIA Flash memory card driver"/* Size of the PCMCIA address space: 26 bits = 64 MB */#define MAX_PCMCIA_ADDR	0x4000000struct pcmciamtd_dev {	struct pcmcia_device	*p_dev;	dev_node_t	node;		/* device node */	caddr_t		win_base;	/* ioremapped address of PCMCIA window */	unsigned int	win_size;	/* size of window */	unsigned int	offset;		/* offset into card the window currently points at */	struct map_info	pcmcia_map;	struct mtd_info	*mtd_info;	int		vpp;	char		mtd_name[sizeof(struct cistpl_vers_1_t)];};/* Module parameters *//* 2 = do 16-bit transfers, 1 = do 8-bit transfers */static int bankwidth = 2;/* Speed of memory accesses, in ns */static int mem_speed;/* Force the size of an SRAM card */static int force_size;/* Force Vpp */static int vpp;/* Set Vpp */static int setvpp;/* Force card to be treated as FLASH, ROM or RAM */static int mem_type;MODULE_LICENSE("GPL");MODULE_AUTHOR("Simon Evans <spse@secret.org.uk>");MODULE_DESCRIPTION(DRIVER_DESC);module_param(bankwidth, int, 0);MODULE_PARM_DESC(bankwidth, "Set bankwidth (1=8 bit, 2=16 bit, default=2)");module_param(mem_speed, int, 0);MODULE_PARM_DESC(mem_speed, "Set memory access speed in ns");module_param(force_size, int, 0);MODULE_PARM_DESC(force_size, "Force size of card in MiB (1-64)");module_param(setvpp, int, 0);MODULE_PARM_DESC(setvpp, "Set Vpp (0=Never, 1=On writes, 2=Always on, default=0)");module_param(vpp, int, 0);MODULE_PARM_DESC(vpp, "Vpp value in 1/10ths eg 33=3.3V 120=12V (Dangerous)");module_param(mem_type, int, 0);MODULE_PARM_DESC(mem_type, "Set Memory type (0=Flash, 1=RAM, 2=ROM, default=0)");/* read/write{8,16} copy_{from,to} routines with window remapping to access whole card */static caddr_t remap_window(struct map_info *map, unsigned long to){	struct pcmciamtd_dev *dev = (struct pcmciamtd_dev *)map->map_priv_1;	window_handle_t win = (window_handle_t)map->map_priv_2;	memreq_t mrq;	int ret;	if (!pcmcia_dev_present(dev->p_dev)) {		DEBUG(1, "device removed");		return 0;	}	mrq.CardOffset = to & ~(dev->win_size-1);	if(mrq.CardOffset != dev->offset) {		DEBUG(2, "Remapping window from 0x%8.8x to 0x%8.8x",		      dev->offset, mrq.CardOffset);		mrq.Page = 0;		ret = pcmcia_map_mem_page(win, &mrq);		if (ret != 0) {			cs_error(dev->p_dev, MapMemPage, ret);			return NULL;		}		dev->offset = mrq.CardOffset;	}	return dev->win_base + (to & (dev->win_size-1));}static map_word pcmcia_read8_remap(struct map_info *map, unsigned long ofs){	caddr_t addr;	map_word d = {{0}};	addr = remap_window(map, ofs);	if(!addr)		return d;	d.x[0] = readb(addr);	DEBUG(3, "ofs = 0x%08lx (%p) data = 0x%02x", ofs, addr, d.x[0]);	return d;}static map_word pcmcia_read16_remap(struct map_info *map, unsigned long ofs){	caddr_t addr;	map_word d = {{0}};	addr = remap_window(map, ofs);	if(!addr)		return d;	d.x[0] = readw(addr);	DEBUG(3, "ofs = 0x%08lx (%p) data = 0x%04x", ofs, addr, d.x[0]);	return d;}static void pcmcia_copy_from_remap(struct map_info *map, void *to, unsigned long from, ssize_t len){	struct pcmciamtd_dev *dev = (struct pcmciamtd_dev *)map->map_priv_1;	unsigned long win_size = dev->win_size;	DEBUG(3, "to = %p from = %lu len = %u", to, from, len);	while(len) {		int toread = win_size - (from & (win_size-1));		caddr_t addr;		if(toread > len)			toread = len;		addr = remap_window(map, from);		if(!addr)			return;		DEBUG(4, "memcpy from %p to %p len = %d", addr, to, toread);		memcpy_fromio(to, addr, toread);		len -= toread;		to += toread;		from += toread;	}}static void pcmcia_write8_remap(struct map_info *map, map_word d, unsigned long adr){	caddr_t addr = remap_window(map, adr);	if(!addr)		return;	DEBUG(3, "adr = 0x%08lx (%p)  data = 0x%02x", adr, addr, d.x[0]);	writeb(d.x[0], addr);}static void pcmcia_write16_remap(struct map_info *map, map_word d, unsigned long adr){	caddr_t addr = remap_window(map, adr);	if(!addr)		return;	DEBUG(3, "adr = 0x%08lx (%p)  data = 0x%04x", adr, addr, d.x[0]);	writew(d.x[0], addr);}static void pcmcia_copy_to_remap(struct map_info *map, unsigned long to, const void *from, ssize_t len){	struct pcmciamtd_dev *dev = (struct pcmciamtd_dev *)map->map_priv_1;	unsigned long win_size = dev->win_size;	DEBUG(3, "to = %lu from = %p len = %u", to, from, len);	while(len) {		int towrite = win_size - (to & (win_size-1));		caddr_t addr;		if(towrite > len)			towrite = len;		addr = remap_window(map, to);		if(!addr)			return;		DEBUG(4, "memcpy from %p to %p len = %d", from, addr, towrite);		memcpy_toio(addr, from, towrite);		len -= towrite;		to += towrite;		from += towrite;	}}/* read/write{8,16} copy_{from,to} routines with direct access */#define DEV_REMOVED(x)  (!(pcmcia_dev_present(((struct pcmciamtd_dev *)map->map_priv_1)->p_dev)))static map_word pcmcia_read8(struct map_info *map, unsigned long ofs){	caddr_t win_base = (caddr_t)map->map_priv_2;	map_word d = {{0}};	if(DEV_REMOVED(map))		return d;	d.x[0] = readb(win_base + ofs);	DEBUG(3, "ofs = 0x%08lx (%p) data = 0x%02x", ofs, win_base + ofs, d.x[0]);	return d;}static map_word pcmcia_read16(struct map_info *map, unsigned long ofs){	caddr_t win_base = (caddr_t)map->map_priv_2;	map_word d = {{0}};	if(DEV_REMOVED(map))		return d;	d.x[0] = readw(win_base + ofs);	DEBUG(3, "ofs = 0x%08lx (%p) data = 0x%04x", ofs, win_base + ofs, d.x[0]);	return d;}static void pcmcia_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len){	caddr_t win_base = (caddr_t)map->map_priv_2;	if(DEV_REMOVED(map))		return;	DEBUG(3, "to = %p from = %lu len = %u", to, from, len);	memcpy_fromio(to, win_base + from, len);}static void pcmcia_write8(struct map_info *map, u8 d, unsigned long adr){	caddr_t win_base = (caddr_t)map->map_priv_2;	if(DEV_REMOVED(map))		return;	DEBUG(3, "adr = 0x%08lx (%p)  data = 0x%02x", adr, win_base + adr, d);	writeb(d, win_base + adr);}static void pcmcia_write16(struct map_info *map, u16 d, unsigned long adr){	caddr_t win_base = (caddr_t)map->map_priv_2;	if(DEV_REMOVED(map))		return;	DEBUG(3, "adr = 0x%08lx (%p)  data = 0x%04x", adr, win_base + adr, d);	writew(d, win_base + adr);}static void pcmcia_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len){	caddr_t win_base = (caddr_t)map->map_priv_2;	if(DEV_REMOVED(map))		return;	DEBUG(3, "to = %lu from = %p len = %u", to, from, len);	memcpy_toio(win_base + to, from, len);}static void pcmciamtd_set_vpp(struct map_info *map, int on){	struct pcmciamtd_dev *dev = (struct pcmciamtd_dev *)map->map_priv_1;	struct pcmcia_device *link = dev->p_dev;	modconf_t mod;	int ret;	mod.Attributes = CONF_VPP1_CHANGE_VALID | CONF_VPP2_CHANGE_VALID;	mod.Vcc = 0;	mod.Vpp1 = mod.Vpp2 = on ? dev->vpp : 0;	DEBUG(2, "dev = %p on = %d vpp = %d\n", dev, on, dev->vpp);	ret = pcmcia_modify_configuration(link, &mod);	if (ret != 0)		cs_error(link, ModifyConfiguration, ret);}/* After a card is removed, pcmciamtd_release() will unregister the * device, and release the PCMCIA configuration.  If the device is * still open, this will be postponed until it is closed. */static void pcmciamtd_release(struct pcmcia_device *link){	struct pcmciamtd_dev *dev = link->priv;	DEBUG(3, "link = 0x%p", link);	if (link->win) {		if(dev->win_base) {			iounmap(dev->win_base);			dev->win_base = NULL;		}		pcmcia_release_window(link->win);	}	pcmcia_disable_device(link);}static void card_settings(struct pcmciamtd_dev *dev, struct pcmcia_device *link, int *new_name){	int rc;	tuple_t tuple;	cisparse_t parse;	u_char buf[64];	tuple.Attributes = 0;	tuple.TupleData = (cisdata_t *)buf;	tuple.TupleDataMax = sizeof(buf);	tuple.TupleOffset = 0;	tuple.DesiredTuple = RETURN_FIRST_TUPLE;	rc = pcmcia_get_first_tuple(link, &tuple);	while (rc == 0) {		rc = pcmcia_get_tuple_data(link, &tuple);		if (rc != 0) {			cs_error(link, GetTupleData, rc);			break;		}		rc = pcmcia_parse_tuple(&tuple, &parse);		if (rc != 0) {			cs_error(link, ParseTuple, rc);			break;		}		switch(tuple.TupleCode) {		case  CISTPL_FORMAT: {			cistpl_format_t *t = &parse.format;			(void)t; /* Shut up, gcc */			DEBUG(2, "Format type: %u, Error Detection: %u, offset = %u, length =%u",			      t->type, t->edc, t->offset, t->length);			break;		}		case CISTPL_DEVICE: {			cistpl_device_t *t = &parse.device;			int i;			DEBUG(2, "Common memory:");			dev->pcmcia_map.size = t->dev[0].size;			for(i = 0; i < t->ndev; i++) {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -