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

📄 memory_cs.c

📁 pcmcia source code
💻 C
📖 第 1 页 / 共 3 页
字号:
/*======================================================================    A general driver for accessing PCMCIA card memory via Bulk    Memory Services.    This driver provides the equivalent of /dev/mem for a PCMCIA    card's attribute and common memory.  It includes character    and block device support.    memory_cs.c 1.87 2002/06/29 06:27:37    The contents of this file are subject to the Mozilla Public    License Version 1.1 (the "License"); you may not use this file    except in compliance with the License. You may obtain a copy of    the License at http://www.mozilla.org/MPL/    Software distributed under the License is distributed on an "AS    IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or    implied. See the License for the specific language governing    rights and limitations under the License.    The initial developer of the original code is David A. Hinds    <dahinds@users.sourceforge.net>.  Portions created by David A. Hinds    are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.    Alternatively, the contents of this file may be used under the    terms of the GNU General Public License version 2 (the "GPL"), in    which case the provisions of the GPL are applicable instead of the    above.  If you wish to allow the use of your version of this file    only under the terms of the GPL and not to allow others to use    your version of this file under the MPL, indicate your decision    by deleting the provisions above and replace them with the notice    and other provisions required by the GPL.  If you do not delete    the provisions above, a recipient may use your version of this    file under either the MPL or the GPL.    ======================================================================*/#include <linux/module.h>#include <linux/init.h>#include <linux/kernel.h>#include <linux/sched.h>#include <linux/slab.h>#include <linux/string.h>#include <linux/timer.h>#include <linux/major.h>#include <linux/fs.h>#include <linux/ioctl.h>#include <linux/blkpg.h>#include <asm/io.h>#include <asm/system.h>#include <stdarg.h>#include <pcmcia/version.h>#include <pcmcia/cs_types.h>#include <pcmcia/cs.h>#include <pcmcia/bulkmem.h>#include <pcmcia/cistpl.h>#include <pcmcia/ds.h>#include <pcmcia/memory.h>#include <pcmcia/mem_op.h>/* Major device #'s for memory device */static int major_dev = 0;/* Funky stuff for setting up a block device */#define MAJOR_NR		major_dev#define DEVICE_NAME		"memory"#define DEVICE_REQUEST		do_memory_request#define DEVICE_ON(device)#define DEVICE_OFF(device)#define DEVICE_NR(minor)	((minor)>>4)#define IS_DIRECT(minor)	(((minor)&8)>>3)#define REGION_AM(minor)	(((minor)&4)>>2)#define REGION_NR(minor)	((minor)&7)#define MINOR_NR(dev,dir,attr,rgn) \(((dev)<<4)+((dir)<<3)+((attr)<<2)+(rgn))#include <linux/blk.h>/*====================================================================*//* Module parameters */MODULE_AUTHOR("David Hinds <dahinds@users.sourceforge.net>");MODULE_DESCRIPTION("PCMCIA memory card driver");MODULE_LICENSE("Dual MPL/GPL");#define INT_MODULE_PARM(n, v) static int n = v; MODULE_PARM(n, "i")INT_MODULE_PARM(word_width, 1);		/* 1 = 16-bit, 0 = 8-bit */INT_MODULE_PARM(mem_speed, 0);		/* access speed, in ns */INT_MODULE_PARM(force_size, 0);		/* force SRAM card size? */#ifdef PCMCIA_DEBUGINT_MODULE_PARM(pc_debug, PCMCIA_DEBUG);#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)static char *version ="memory_cs.c 1.87 2002/06/29 06:27:37 (David Hinds)";#else#define DEBUG(n, args...)#endif/*====================================================================*//* Maximum number of separate memory devices we'll allow */#define MAX_DEV		4/* Maximum number of partitions per memory space */#define MAX_PART	4/* Maximum number of outstanding erase requests per socket */#define MAX_ERASE	8/* Sector size -- shouldn't need to change */#define SECTOR_SIZE	512/* Size of the PCMCIA address space: 26 bits = 64 MB */#define HIGH_ADDR	0x4000000static void memory_config(dev_link_t *link);static void memory_release(u_long arg);static int memory_event(event_t event, int priority,			event_callback_args_t *args);static dev_link_t *memory_attach(void);static void memory_detach(dev_link_t *);/* Each memory region corresponds to a minor device */typedef struct minor_dev_t {		/* For normal regions */    region_info_t	region;    memory_handle_t	handle;    int			open;    u_int		offset;} minor_dev_t;typedef struct direct_dev_t {		/* For direct access */    int			flags;    int			open;    caddr_t		Base;    u_int		Size;    u_int		cardsize;    u_int		offset;} direct_dev_t;typedef struct memory_dev_t {    dev_link_t		link;    dev_node_t		node;    eraseq_handle_t	eraseq_handle;    eraseq_entry_t	eraseq[MAX_ERASE];    wait_queue_head_t	erase_pending;    direct_dev_t	direct;    minor_dev_t		minor[2*MAX_PART];} memory_dev_t;#define MEM_WRPROT	1static dev_info_t dev_info = "memory_cs";static dev_link_t *dev_table[MAX_DEV] = { NULL, /* ... */ };static int memory_blocksizes[MINOR_NR(MAX_DEV, 0, 0, 0)] ={ 0, /* ... */ };    /*====================================================================*/static int memory_ioctl(struct inode *inode, struct file *file,			u_int cmd, u_long arg);static ssize_t memory_read FOPS(struct inode *inode,				struct file *file, char *buf,				size_t count, loff_t *ppos);static ssize_t memory_write FOPS(struct inode *inode,				 struct file *file, const char *buf,				 size_t count, loff_t *ppos);static int memory_open(struct inode *inode, struct file *file);static FS_RELEASE_T memory_close(struct inode *inode,				 struct file *file);static FS_RELEASE_T memory_blk_close(struct inode *inode,				     struct file *file);static struct file_operations memory_chr_fops = {    open:	memory_open,    release:	memory_close,    read:	memory_read,    write:	memory_write,    ioctl:	memory_ioctl,};static struct block_device_operations memory_blk_fops = {    open:	memory_open,    release:	memory_blk_close,    ioctl:	memory_ioctl,#ifdef block_device_operations    read:	block_read,    write:	block_write,    fsync:	block_fsync#endif};/*====================================================================*/static void cs_error(client_handle_t handle, int func, int ret){    error_info_t err = { func, ret };    CardServices(ReportError, handle, &err);}/*======================================================================    memory_attach() creates an "instance" of the driver, allocating    local data structures for one device.  The device is registered    with Card Services.======================================================================*/static dev_link_t *memory_attach(void){    memory_dev_t *dev;    dev_link_t *link;    client_reg_t client_reg;    eraseq_hdr_t eraseq_hdr;    int i, ret;        DEBUG(0, "memory_attach()\n");    for (i = 0; i < MAX_DEV; i++)	if (dev_table[i] == NULL) break;    if (i == MAX_DEV) {	printk(KERN_NOTICE "memory_cs: no devices available\n");	return NULL;    }        /* Create new memory card device */    dev = kmalloc(sizeof(*dev), GFP_KERNEL);    if (!dev) return NULL;    memset(dev, 0, sizeof(*dev));    link = &dev->link; link->priv = dev;    link->release.function = &memory_release;    link->release.data = (u_long)link;    dev_table[i] = link;    init_waitqueue_head(&dev->erase_pending);    /* Register with Card Services */    client_reg.dev_info = &dev_info;    client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE;    client_reg.EventMask =	CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |	CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |	CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME;    client_reg.event_handler = &memory_event;    client_reg.Version = 0x0210;    client_reg.event_callback_args.client_data = link;    ret = CardServices(RegisterClient, &link->handle, &client_reg);    if (ret != 0) {	cs_error(link->handle, RegisterClient, ret);	memory_detach(link);	return NULL;    }    for (i = 0; i < MAX_ERASE; i++)	dev->eraseq[i].State = ERASE_IDLE;    eraseq_hdr.QueueEntryCnt = MAX_ERASE;    eraseq_hdr.QueueEntryArray = dev->eraseq;    dev->eraseq_handle = (void *)link->handle;    ret = CardServices(RegisterEraseQueue, &dev->eraseq_handle, &eraseq_hdr);    if (ret != 0) {	cs_error(link->handle, RegisterEraseQueue, ret);	dev->eraseq_handle = NULL;	memory_detach(link);	return NULL;    }        return link;} /* memory_attach *//*======================================================================    This deletes a driver "instance".  The device is de-registered    with Card Services.  If it has been released, all local data    structures are freed.  Otherwise, the structures will be freed    when the device is released.======================================================================*/static void memory_detach(dev_link_t *link){    memory_dev_t *dev = link->priv;    int nd;    DEBUG(0, "memory_detach(0x%p)\n", link);        /* Verify device address */    for (nd = 0; nd < MAX_DEV; nd++)	if (dev_table[nd] == link) break;    if (nd == MAX_DEV)	return;    del_timer(&link->release);    if (link->state & DEV_CONFIG) {	memory_release((u_long)link);	if (link->state & DEV_STALE_CONFIG) {	    link->state |= DEV_STALE_LINK;	    return;	}    }    if (dev->eraseq_handle)	CardServices(DeregisterEraseQueue, dev->eraseq_handle);    if (link->handle)	CardServices(DeregisterClient, link->handle);        /* Unlink device structure, free bits */    dev_table[nd] = NULL;    kfree(dev);    } /* memory_detach *//*======================================================================    Figure out the size of a simple SRAM card    ======================================================================*/#define WIN_TYPE(a)  ((a) ? WIN_MEMORY_TYPE_AM : WIN_MEMORY_TYPE_CM)#define WIN_WIDTH(w) ((w) ? WIN_DATA_WIDTH_16 : WIN_DATA_WIDTH_8)static u_int get_size(dev_link_t *link, direct_dev_t *direct){    modwin_t mod;    memreq_t mem;    u_char b0, b1;    int s, ret;    mod.Attributes = WIN_ENABLE | WIN_MEMORY_TYPE_CM;    mod.AccessSpeed = mem_speed;    ret = CardServices(ModifyWindow, link->win, &mod);    if (ret != CS_SUCCESS)	cs_error(link->handle, ModifyWindow, ret);    /* Look for wrap-around or dead end */    mem.Page = mem.CardOffset = 0;    CardServices(MapMemPage, link->win, &mem);    b0 = readb(direct->Base);    for (s = 12; s < 26; s++) {	mem.CardOffset = 1<<s;	CardServices(MapMemPage, link->win, &mem);	b1 = readb(direct->Base);	writeb(~b1, direct->Base);	mem.CardOffset = 0;	CardServices(MapMemPage, link->win, &mem);	if (readb(direct->Base) != b0) {	    writeb(b0, direct->Base);	    break;	}	mem.CardOffset = 1<<s;	CardServices(MapMemPage, link->win, &mem);	if (readb(direct->Base) != (0xff & ~b1)) break;	writeb(b1, direct->Base);    }    return (s > 15) ? (1<<s) : 0;} /* get_size */static void print_size(u_int sz){    if (sz & 0x03ff)	printk("%d bytes", sz);    else if (sz & 0x0fffff)	printk("%d kb", sz >> 10);    else	printk("%d mb", sz >> 20);}/*======================================================================    memory_config() is scheduled to run after a CARD_INSERTION event    is received, to configure the PCMCIA socket, and to make the    ethernet device available to the system.    ======================================================================*/#define CS_CHECK(fn, args...) \while ((last_ret=CardServices(last_fn=(fn), args))!=0) goto cs_failedstatic void memory_config(dev_link_t *link){    memory_dev_t *dev = link->priv;    minor_dev_t *minor;    region_info_t region;    cs_status_t status;

⌨️ 快捷键说明

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