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

📄 pcmciamtd.c

📁 老版本的mtd-snap
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * $Id: pcmciamtd.c,v 1.53 2005/07/06 18:41:27 gleixner Exp $ * * 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/version.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_PARM(debug, "i");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", __FUNCTION__ , ## 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"#define DRIVER_VERSION	"$Revision: 1.53 $"/* Size of the PCMCIA address space: 26 bits = 64 MB */#define MAX_PCMCIA_ADDR	0x4000000struct pcmciamtd_dev {	dev_link_t	link;		/* PCMCIA link */	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)];};static dev_info_t dev_info = "pcmciamtd";static dev_link_t *dev_list;/* 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_PARM(bankwidth, "i");MODULE_PARM_DESC(bankwidth, "Set bankwidth (1=8 bit, 2=16 bit, default=2)");MODULE_PARM(mem_speed, "i");MODULE_PARM_DESC(mem_speed, "Set memory access speed in ns");MODULE_PARM(force_size, "i");MODULE_PARM_DESC(force_size, "Force size of card in MiB (1-64)");MODULE_PARM(setvpp, "i");MODULE_PARM_DESC(setvpp, "Set Vpp (0=Never, 1=On writes, 2=Always on, default=0)");MODULE_PARM(vpp, "i");MODULE_PARM_DESC(vpp, "Vpp value in 1/10ths eg 33=3.3V 120=12V (Dangerous)");MODULE_PARM(mem_type, "i");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(!(dev->link.state & DEV_PRESENT)) {		DEBUG(1, "device removed state = 0x%4.4X", dev->link.state);		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;		if( (ret = pcmcia_map_mem_page(win, &mrq)) != CS_SUCCESS) {			cs_error(dev->link.handle, 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)  (!(*(u_int *)x->map_priv_1 & DEV_PRESENT))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;	dev_link_t *link = &dev->link;	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->handle, &mod);	if(ret != CS_SUCCESS) {		cs_error(link->handle, 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(dev_link_t *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_release_configuration(link->handle);	link->state &= ~DEV_CONFIG;}static void card_settings(struct pcmciamtd_dev *dev, dev_link_t *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->handle, &tuple);	while(rc == CS_SUCCESS) {		rc = pcmcia_get_tuple_data(link->handle, &tuple);		if(rc != CS_SUCCESS) {			cs_error(link->handle, GetTupleData, rc);			break;		}		rc = pcmcia_parse_tuple(link->handle, &tuple, &parse);		if(rc != CS_SUCCESS) {			cs_error(link->handle, 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++) {				DEBUG(2, "Region %d, type = %u", i, t->dev[i].type);				DEBUG(2, "Region %d, wp = %u", i, t->dev[i].wp);				DEBUG(2, "Region %d, speed = %u ns", i, t->dev[i].speed);				DEBUG(2, "Region %d, size = %u bytes", i, t->dev[i].size);			}			break;		}					case CISTPL_VERS_1: {			cistpl_vers_1_t *t = &parse.version_1;			int i;			if(t->ns) {				dev->mtd_name[0] = '\0';				for(i = 0; i < t->ns; i++) {					if(i)						strcat(dev->mtd_name, " ");					strcat(dev->mtd_name, t->str+t->ofs[i]);				}			}			DEBUG(2, "Found name: %s", dev->mtd_name);			break;		}					case CISTPL_JEDEC_C: {			cistpl_jedec_t *t = &parse.jedec;			int i;			for(i = 0; i < t->nid; i++) {				DEBUG(2, "JEDEC: 0x%02x 0x%02x", t->id[i].mfr, t->id[i].info);			}			break;		}					case CISTPL_DEVICE_GEO: {			cistpl_device_geo_t *t = &parse.device_geo;			int i;			dev->pcmcia_map.bankwidth = t->geo[0].buswidth;			for(i = 0; i < t->ngeo; i++) {				DEBUG(2, "region: %d bankwidth = %u", i, t->geo[i].buswidth);

⌨️ 快捷键说明

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