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

📄 memory_cs.c

📁 pcmcia source code
💻 C
📖 第 1 页 / 共 3 页
字号:
        /* Find a free erase slot, or wait for one to become available */    for (;;) {	for (i = 0; i < MAX_ERASE; i++)	    if (!ERASE_IN_PROGRESS(dev->eraseq[i].State)) break;	if (i < MAX_ERASE) break;	DEBUG(2, "waiting for erase slot...\n");	interruptible_sleep_on(&dev->erase_pending);	if (signal_pending(current))	    return -ERESTARTSYS;    }    /* Queue a new request */    init_waitqueue_head((wait_queue_head_t *)&dev->eraseq[i].Optional);    dev->eraseq[i].State = ERASE_QUEUED;    dev->eraseq[i].Handle = minor_dev->handle;    dev->eraseq[i].Offset = f_pos;    dev->eraseq[i].Size = count;    ret = CardServices(CheckEraseQueue, dev->eraseq_handle);    if (ret != CS_SUCCESS) {	cs_error(link->handle, CheckEraseQueue, ret);	return -EIO;    }    /* Wait for request to complete */    if (ERASE_IN_PROGRESS(dev->eraseq[i].State))	sleep_on((wait_queue_head_t *)&dev->eraseq[i].Optional);    if (dev->eraseq[i].State != ERASE_PASSED)	return -EIO;    return 0;}/*======================================================================    Write for character-mode device    ======================================================================*/static ssize_t direct_write FOPS(struct inode *inode,				 struct file *file, const 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, wrote, to, nb;    int ret;    modwin_t mod;    memreq_t mem;        DEBUG(2, "direct_write(%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;        /* Check for write protect */    if (direct->flags & MEM_WRPROT)	return -EROFS;    /* Boundary checks */    size = (IS_DIRECT(minor)) ? HIGH_ADDR : direct->cardsize;    pos = FPOS;    if (pos >= size)        return -ENOSPC;    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;    to = pos & (direct->Size-1);    for (wrote = 0; count > 0; count -= nb, wrote += nb) {	ret = CardServices(MapMemPage, link->win, &mem);	if (ret != CS_SUCCESS) {	    cs_error(link->handle, MapMemPage, ret);	    return -EIO;	}	nb = (to+count > direct->Size) ? direct->Size-to : count;	copy_user_to_pc(direct->Base+to, buf, nb);	buf += nb;        to = 0;	mem.CardOffset += direct->Size;    }    FPOS += wrote;    return wrote;} /* direct_write */static ssize_t memory_write FOPS(struct inode *inode,				 struct file *file, const 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_write FOPS(inode, file, buf, count, ppos);        DEBUG(2, "memory_write(0x%p, 0x%lx, %ld)\n", minor->handle,	  (u_long)FPOS, (u_long)count);    if ((minor->region.BlockSize > 1) &&	((FPOS & (minor->region.BlockSize-1)) == 0) &&	((count & (minor->region.BlockSize-1)) == 0)) {	ret = memory_erase(MINOR(F_INODE(file)->i_rdev), FPOS, count);	if (ret != 0)	    return ret;    }        req.Attributes = 0;    req.Offset = FPOS;    req.Count = count;    ret = CardServices(WriteMemory, minor->handle, &req, buf);    if (ret == CS_SUCCESS) {	FPOS += count;	return count;    } else	return -EIO;} /* memory_write *//*======================================================================    IOCTL calls for getting device parameters.======================================================================*/static int memory_ioctl(struct inode *inode, struct file *file,			u_int cmd, u_long arg){    int minor = MINOR(inode->i_rdev);    dev_link_t *link;    memory_dev_t *dev;    minor_dev_t *minor_dev;    erase_info_t erase;    u_int size;    int ret = 0;    link = dev_table[DEVICE_NR(minor)];        if (!DEV_OK(link))	return -ENODEV;    dev = (memory_dev_t *)link->priv;    minor_dev = &dev->minor[REGION_NR(minor)];    size = (cmd & IOCSIZE_MASK) >> IOCSIZE_SHIFT;    if (cmd & IOC_IN) {	ret = verify_area(VERIFY_READ, (char *)arg, size);	if (ret) return ret;    }    if (cmd & IOC_OUT) {	ret = verify_area(VERIFY_WRITE, (char *)arg, size);	if (ret) return ret;    }    switch (cmd) {    case BLKGETSIZE:	if (IS_DIRECT(minor))	    size = dev->direct.cardsize - dev->direct.offset;	else	    size = minor_dev->region.RegionSize - minor_dev->offset;	put_user(size/SECTOR_SIZE, (long *)arg);	break;    case MEMGETINFO:	if (!IS_DIRECT(minor)) {	    copy_to_user((region_info_t *)arg, &minor_dev->region,			 sizeof(struct region_info_t));	} else ret = -EINVAL;	break;    case MEMERASE:	if (!IS_DIRECT(minor)) {	    copy_from_user(&erase, (erase_info_t *)arg,			   sizeof(struct erase_info_t));	    ret = memory_erase(minor, erase.Offset, erase.Size);	} else ret = -EINVAL;	break;#if (LINUX_VERSION_CODE < VERSION(2,3,3))    case BLKFLSBUF:	if (!capable(CAP_SYS_ADMIN)) return -EACCES;	if (!(inode->i_rdev)) return -EINVAL;	fsync_dev(inode->i_rdev);	invalidate_buffers(inode->i_rdev);	break;#else    case BLKROSET:    case BLKROGET:    case BLKFLSBUF:	ret = blk_ioctl(inode->i_rdev, cmd, arg);	break;#endif    default:	ret = -EINVAL;    }        return ret;} /* memory_ioctl *//*======================================================================    Handler for block device requests    ======================================================================*/static void do_direct_request(dev_link_t *link){    memory_dev_t *dev = link->priv;    int addr, len, from, nb, ret;    char *buf;    direct_dev_t *direct;    modwin_t mod;    memreq_t mem;    direct = &dev->direct;        addr = CURRENT->sector * SECTOR_SIZE + direct->offset;    len = CURRENT->current_nr_sectors * SECTOR_SIZE;    if ((addr + len) > direct->cardsize) {	end_request(0);	return;    }        mod.Attributes = WIN_ENABLE | WIN_MEMORY_TYPE_CM;    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);	end_request(0);	return;    }    buf = CURRENT->buffer;    mem.Page = 0;    mem.CardOffset = addr & ~(direct->Size-1);    from = addr & (direct->Size-1);    ret = 0;        if ((CURRENT->cmd == READ) || (CURRENT->cmd == WRITE))	for ( ; len > 0; len -= nb, buf += nb, from = 0) {	    ret = CardServices(MapMemPage, link->win, &mem);	    if (ret != CS_SUCCESS) break;	    nb = (from+len > direct->Size) ? direct->Size-from : len;	    if (CURRENT->cmd == READ)		copy_from_pc(buf, &direct->Base[from], nb);	    else		copy_to_pc(&direct->Base[from], buf, nb);	    mem.CardOffset += direct->Size;	}    else panic("pcmem_cs: unknown block command!\n");        if (ret == CS_SUCCESS)	end_request(1);    else {	cs_error(link->handle, MapMemPage, ret);	end_request(0);    }} /* do_direct_request */static void do_memory_request(request_arg_t){    int ret, minor;    char *buf;    mem_op_t req;    dev_link_t *link;    memory_dev_t *dev;    minor_dev_t *minor_dev;        sti();    do {	INIT_REQUEST;	minor = MINOR(CURRENT->rq_dev);	link = dev_table[DEVICE_NR(minor)];	dev = (memory_dev_t *)link->priv;	if (IS_DIRECT(minor) || (dev->direct.cardsize > 0)) {	    do_direct_request(link);	    continue;	}		minor_dev = &dev->minor[REGION_NR(minor)];	req.Attributes = MEM_OP_BUFFER_KERNEL;	req.Offset = CURRENT->sector * SECTOR_SIZE + minor_dev->offset;	req.Count = CURRENT->current_nr_sectors * SECTOR_SIZE;	buf = CURRENT->buffer;	ret = CS_SUCCESS;		if (CURRENT->cmd == READ) {	    ret = CardServices(ReadMemory, minor_dev->handle,			       &req, buf);	    if (ret != CS_SUCCESS)		cs_error(link->handle, ReadMemory, ret);	} else if (CURRENT->cmd == WRITE) {	    ret = CardServices(WriteMemory, minor_dev->handle,			       &req, buf);	    if (ret != CS_SUCCESS)		cs_error(link->handle, WriteMemory, ret);	} else	    panic("memory_cs: unknown block command!\n");		if (ret == CS_SUCCESS)	    end_request(1);	else	    end_request(0);    } while (1);} /* do_memory_request *//*====================================================================*/static int __init init_memory_cs(void){    servinfo_t serv;    int i;        DEBUG(0, "%s\n", version);        CardServices(GetCardServicesInfo, &serv);    if (serv.Revision != CS_RELEASE_CODE) {	printk(KERN_NOTICE "memory_cs: Card Services release "	       "does not match!\n");	return -EINVAL;    }        register_pccard_driver(&dev_info, &memory_attach, &memory_detach);    for (i = MAX_CHRDEV-1; i > 0; i--) {	if (register_chrdev(i, "memory", &memory_chr_fops) == 0) {	    if (register_blkdev(i, "memory", &memory_blk_fops) == 0)		break;	    else		unregister_chrdev(i, "memory");	}    }    if (i == 0) {	printk(KERN_NOTICE "memory_cs: unable to grab a device #\n");	return -ENODEV;    }    major_dev = i;    blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), &do_memory_request);    for (i = 0; i < MINOR_NR(MAX_DEV, 0, 0, 0); i++)	memory_blocksizes[i] = 1024;    blksize_size[major_dev] = memory_blocksizes;        return 0;}static void __exit exit_memory_cs(void){    int i;    dev_link_t *link;    DEBUG(0, "memory_cs: unloading\n");    unregister_pccard_driver(&dev_info);    if (major_dev != 0) {	unregister_chrdev(major_dev, "memory");	unregister_blkdev(major_dev, "memory");	blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));	blksize_size[major_dev] = NULL;    }    for (i = 0; i < MAX_DEV; i++) {	link = dev_table[i];	if (link) {	    if (link->state & DEV_CONFIG)		memory_release((u_long)link);	    memory_detach(link);	}    }}module_init(init_memory_cs);module_exit(exit_memory_cs);

⌨️ 快捷键说明

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