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

📄 memory_cs.c

📁 pcmcia source code
💻 C
📖 第 1 页 / 共 3 页
字号:
    win_req_t req;    int nd, i, last_ret, last_fn, attr, ret, nr[2];    DEBUG(0, "memory_config(0x%p)\n", link);    /* Configure card */    link->state |= DEV_CONFIG;    for (nd = 0; nd < MAX_DEV; nd++)	if (dev_table[nd] == link) break;        /* Allocate a small memory window for direct access */    req.Attributes = WIN_WIDTH(word_width);    req.Base = req.Size = 0;    req.AccessSpeed = mem_speed;    link->win = (window_handle_t)link->handle;    CS_CHECK(RequestWindow, &link->win, &req);    /* Get write protect status */    CS_CHECK(GetStatus, link->handle, &status);        dev->direct.Base = ioremap(req.Base, req.Size);    dev->direct.Size = req.Size;    dev->direct.cardsize = 0;    for (attr = 0; attr < 2; attr++) {	nr[attr] = 0;	minor = dev->minor + attr*MAX_PART;	region.Attributes = (attr) ? REGION_TYPE_AM : REGION_TYPE_CM;	ret = CardServices(GetFirstRegion, link->handle, &region);	while (ret == CS_SUCCESS) {	    minor->region = region;	    minor++; nr[attr]++;	    ret = CardServices(GetNextRegion, link->handle, &region);	}    }        sprintf(dev->node.dev_name, "mem%d", nd);    dev->node.major = major_dev;    dev->node.minor = MINOR_NR(nd, 0, 0, 0);    link->dev = &dev->node;#ifdef CISTPL_FORMAT_MEM    /* This is a hack, not a complete solution */    {	cisinfo_t info;	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 = CISTPL_FORMAT;	if ((CardServices(ValidateCIS, &info) == CS_SUCCESS) &&	    (info.Chains > 0) &&	    (CardServices(GetFirstTuple, link->handle, &tuple)	     == CS_SUCCESS)) {	    CS_CHECK(GetTupleData, link->handle, &tuple);	    CS_CHECK(ParseTuple, link->handle, &tuple, &parse);	    dev->direct.offset = dev->minor[0].offset =		parse.format.offset;	}    }#endif    printk(KERN_INFO "memory_cs: mem%d:", nd);    if ((nr[0] == 0) && (nr[1] == 0)) {	cisinfo_t cisinfo;	if ((CardServices(ValidateCIS, link->handle, &cisinfo)	     == CS_SUCCESS) && (cisinfo.Chains == 0)) {	    dev->direct.cardsize =		force_size ? force_size : get_size(link,&dev->direct);	    printk(" anonymous: ");	    if (dev->direct.cardsize == 0) {		dev->direct.cardsize = HIGH_ADDR;		printk("unknown size");	    } else {		print_size(dev->direct.cardsize);	    }	} else {	    printk(" no regions found.");	}    } else {	for (attr = 0; attr < 2; attr++) {	    minor = dev->minor + attr*MAX_PART;	    if (attr && nr[0] && nr[1])		printk(",");	    if (nr[attr])		printk(" %s", attr ? "attribute" : "common");	    for (i = 0; i < nr[attr]; i++) {		printk(" ");		print_size(minor[i].region.RegionSize);	    }	}    }    printk("\n");    link->state &= ~DEV_CONFIG_PENDING;    return;cs_failed:    cs_error(link->handle, last_fn, last_ret);    memory_release((u_long)link);    link->state &= ~DEV_CONFIG_PENDING;} /* memory_config *//*======================================================================    After a card is removed, memory_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 memory_release(u_long arg){    dev_link_t *link = (dev_link_t *)arg;    int nd;    DEBUG(0, "memory_release(0x%p)\n", link);    for (nd = 0; nd < MAX_DEV; nd++)	if (dev_table[nd] == link) break;    if (link->open) {	DEBUG(0, "memory_cs: release postponed, 'mem%d'"	      " still open\n", nd);	link->state |= DEV_STALE_CONFIG;	return;    }    link->dev = NULL;    if (link->win) {	memory_dev_t *dev = link->priv;	iounmap(dev->direct.Base);	CardServices(ReleaseWindow, link->win);    }    link->state &= ~DEV_CONFIG;        if (link->state & DEV_STALE_LINK)	memory_detach(link);    } /* memory_release *//*======================================================================    The card status event handler.  Mostly, this schedules other    stuff to run after an event is received.  A CARD_REMOVAL event    also sets some flags to discourage the driver from trying    to talk to the card any more.    ======================================================================*/static int memory_event(event_t event, int priority,		       event_callback_args_t *args){    dev_link_t *link = args->client_data;    memory_dev_t *dev = link->priv;    eraseq_entry_t *erase;    DEBUG(1, "memory_event(0x%06x)\n", event);        switch (event) {    case CS_EVENT_CARD_REMOVAL:	link->state &= ~DEV_PRESENT;	if (link->state & DEV_CONFIG)	    mod_timer(&link->release, jiffies + HZ/20);	break;    case CS_EVENT_CARD_INSERTION:	link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;	memory_config(link);	break;    case CS_EVENT_ERASE_COMPLETE:	erase = (eraseq_entry_t *)(args->info);	wake_up((wait_queue_head_t *)&erase->Optional);	wake_up_interruptible(&dev->erase_pending);	break;    case CS_EVENT_PM_SUSPEND:	link->state |= DEV_SUSPEND;	/* Fall through... */    case CS_EVENT_RESET_PHYSICAL:	/* get_lock(link); */	break;    case CS_EVENT_PM_RESUME:	link->state &= ~DEV_SUSPEND;	/* Fall through... */    case CS_EVENT_CARD_RESET:	/* free_lock(link); */	break;    }    return 0;} /* memory_event *//*======================================================================    This gets a memory handle for the region corresponding to the    minor device number.    ======================================================================*/static int memory_open(struct inode *inode, struct file *file){    int minor = MINOR(inode->i_rdev);    dev_link_t *link;    memory_dev_t *dev;    minor_dev_t *minor_dev;    open_mem_t open;    int ret;        DEBUG(0, "memory_open(%d)\n", minor);    link = dev_table[DEVICE_NR(minor)];    if (!DEV_OK(link))	return -ENODEV;        dev = (memory_dev_t *)link->priv;    if (IS_DIRECT(minor) || (dev->direct.cardsize > 0)) {	if ((file->f_mode & 2) && (dev->direct.flags & MEM_WRPROT))	    return -EROFS;	dev->direct.open++;	file->private_data = NULL;    } else {	minor_dev = &dev->minor[REGION_NR(minor)];	if (minor_dev->region.RegionSize == 0)	    return -ENODEV;	if (minor_dev->handle == NULL) {	    minor_dev->handle = (memory_handle_t)link->handle;	    open.Attributes = minor_dev->region.Attributes;	    open.Offset = minor_dev->region.CardOffset;	    ret = CardServices(OpenMemory, &minor_dev->handle, &open);	    if (ret != CS_SUCCESS)		return -ENOMEM;	}	minor_dev->open++;	file->private_data = minor_dev;    }        link->open++;    MOD_INC_USE_COUNT;    return 0;} /* memory_open *//*====================================================================*/static FS_RELEASE_T memory_close(struct inode *inode,				 struct file *file){    dev_link_t *link;    int minor = MINOR(inode->i_rdev);    memory_dev_t *dev;    minor_dev_t *minor_dev;        DEBUG(0, "memory_close(%d)\n", minor);    link = dev_table[DEVICE_NR(minor)];    dev = (memory_dev_t *)link->priv;    if (IS_DIRECT(minor) || (dev->direct.cardsize > 0)) {	dev->direct.open--;    } else {	minor_dev = &dev->minor[REGION_NR(minor)];	minor_dev->open--;	if (minor_dev->open == 0) {	    CardServices(CloseMemory, minor_dev->handle);	    minor_dev->handle = NULL;	}    }    link->open--;    MOD_DEC_USE_COUNT;    return (FS_RELEASE_T)0;} /* memory_close */static FS_RELEASE_T memory_blk_close(struct inode *inode,				     struct file *file){    fsync_dev(inode->i_rdev);    INVALIDATE_INODES(inode->i_rdev);    invalidate_buffers(inode->i_rdev);    return memory_close(inode, file);}/*======================================================================    Read for character-mode device    ======================================================================*/static ssize_t direct_read FOPS(struct inode *inode,				struct file *file, char *buf,				size_t count, loff_t *ppos){    int minor = MINOR(F_INODE(file)->i_rdev);    dev_link_t *link;    memory_dev_t *dev;    direct_dev_t *direct;    size_t size, pos, read, from, nb;    int ret;    modwin_t mod;    memreq_t mem;    DEBUG(2, "direct_read(%d, 0x%lx, %ld)\n", minor,	  (u_long)FPOS, (u_long)count);    link = dev_table[DEVICE_NR(minor)];        if (!DEV_OK(link))	return -ENODEV;    dev = (memory_dev_t *)link->priv;    direct = &dev->direct;        /* Boundary checks */    pos = FPOS;    size = (IS_DIRECT(minor)) ? HIGH_ADDR : direct->cardsize;    if (pos >= size)	return 0;    if (count > size - pos)	count = size - pos;    mod.Attributes = WIN_ENABLE | WIN_TYPE(REGION_AM(minor));    mod.Attributes |= WIN_WIDTH(word_width);    mod.AccessSpeed = mem_speed;    ret = CardServices(ModifyWindow, link->win, &mod);    if (ret != CS_SUCCESS) {	cs_error(link->handle, ModifyWindow, ret);	return -EIO;    }        mem.CardOffset = pos & ~(direct->Size-1);    mem.Page = 0;    from = pos & (direct->Size-1);    for (read = 0; count > 0; count -= nb, read += nb) {	ret = CardServices(MapMemPage, link->win, &mem);	if (ret != CS_SUCCESS) {	    cs_error(link->handle, MapMemPage, ret);	    return -EIO;	}	nb = (from+count > direct->Size) ? direct->Size-from : count;	copy_pc_to_user(buf, direct->Base+from, nb);	buf += nb;        from = 0;	mem.CardOffset += direct->Size;    }    FPOS += read;    return read;} /* direct_read */static ssize_t memory_read FOPS(struct inode *inode,				struct file *file, char *buf,				size_t count, loff_t *ppos){    minor_dev_t *minor;    mem_op_t req;    int ret;    minor = file->private_data;    if (minor == NULL)	return direct_read FOPS(inode, file, buf, count, ppos);        DEBUG(2, "memory_read(0x%p, 0x%lx, %ld)\n", minor->handle,	  (u_long)FPOS, (u_long)count);        req.Attributes = MEM_OP_BUFFER_USER;    req.Offset = FPOS;    req.Count = count;    ret = CardServices(ReadMemory, minor->handle, &req, buf);    if (ret == CS_SUCCESS) {	FPOS += count;	return count;    } else if (ret == CS_BAD_OFFSET)	return 0;    else	return -EIO;} /* memory_read *//*======================================================================    Erase a memory region.  This is used by the write routine for    suitably aligned and sized blocks.  It is also used for the    MEMERASE ioctl().    ======================================================================*/static int memory_erase(int minor, u_long f_pos, size_t count){    dev_link_t *link = dev_table[DEVICE_NR(minor)];    memory_dev_t *dev = link->priv;    minor_dev_t *minor_dev = &dev->minor[REGION_NR(minor)];    int i, ret;    DEBUG(2, "memory_erase(%d, 0x%lx, %ld)\n", minor,	  f_pos, (u_long)count);

⌨️ 快捷键说明

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