📄 mmc_core.c
字号:
{ check_disk_change (inode->i_rdev); }/* else { retval = -EBUSY; goto exit; }*/ dev->mode = file->f_pos; dev->open_count++; MOD_INC_USE_COUNT;exit : return retval;}static int mmc_blk_release (struct inode *inode, struct file *file){ int device_num = MINOR(inode->i_rdev) >> DEVICE_SHIFT; struct mmc_blk *dev; int retval = 0; dbg("enter %s", __FUNCTION__); if ((device_num < 0) || (device_num >= nb_dev)) { err("%s : DEV for minor %d don't exits", __FUNCTION__, device_num); return -ENODEV; } dev = (struct mmc_blk *) (mmc_blk_dev + device_num); if (dev->open_count <= 0) { err("%s - device not opened", __FUNCTION__); return -ENODEV; } /* decrement our usage count for the device */ --dev->open_count; MOD_DEC_USE_COUNT; return retval;}static int mmc_blk_ioctl (struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg){ int minor = MINOR(inode->i_rdev); int device_num = minor >> PAGE_SHIFT; long size; struct hd_geometry geo; if ((device_num < 0) || (device_num >= nb_dev)) { err("%s : DEV for minor %d don't exits", __FUNCTION__, device_num); return -ENODEV; } switch (cmd) { /* return device size in sector */ case BLKGETSIZE : dbg("%s - get size command", __FUNCTION__); if (!access_ok (VERIFY_WRITE, (void *) arg, sizeof (unsigned long))) return -EFAULT; //size = mmc_blk_gendisk.part[minor].nr_sects; size = mmc_blk_size[minor] * mmc_blk_blocksizes[minor] / mmc_blk_sectorsizes[minor]; dbg("(device %d - minor %d) size in sector = %ld", device_num, minor, size); if (copy_to_user ((unsigned long *) arg, &size, sizeof (unsigned long))) return (-EFAULT); return (0); /* read again partion table */ case BLKRRPART : return (mmc_blk_revalidate (inode->i_rdev)); /* return the device geometry */ case HDIO_GETGEO : dbg("%s - get the geom", __FUNCTION__); if (!access_ok (VERIFY_WRITE, (void *) arg, sizeof (unsigned long))) return -EFAULT; // size = mmc_blk_gendisk.part[device_num].nr_sects; size = mmc_blk_size[device_num] * mmc_blk_blocksizes[device_num] / mmc_blk_sectorsizes[device_num]; geo.cylinders = (size & ~0x3f) >> 6; geo.heads = 4; geo.sectors = 16; geo.start = 4; dbg("geom.cylinders = %d", geo.cylinders); dbg("(device %d - minor %d) size in sector = %ld", device_num, minor, size); if (copy_to_user ((struct hd_geometry *) arg, &geo, sizeof (struct hd_geometry))) return (-EFAULT); return (0); /* let the kernel handle for us the unkown command */ default : dbg("%s - let the kernel handle this ioctl :)", __FUNCTION__); return (blk_ioctl (inode->i_rdev, cmd, arg)); } return (-ENOTTY);}/* initialize the MMC and set device global variables (such as block size... etc) */static int init_mmc(int device_num, struct mmc_blk *dev){ int part, retval = 0; char *csd_tmp = NULL; char *cid_tmp = NULL; long mmc_size, c_size, c_size_mult, read_block_len, mult, block_len, block_nr; /* TODO : handle multiple devices */ if (device_num != 0) return (-ENODEV); retval = open_mmc (); if (retval < 0) { err("%s : unable to open mmc device", __FUNCTION__); /* attempt to let the qspi driver * in a proper state */ release_mmc (); return (retval); } dbg("%s - success to open the mmc device %d", __FUNCTION__, device_num); /* get the MMC CID register (Card Specific Data) */ cid_tmp = get_cid (); if (cid_tmp == NULL) { err("%s - unable to get CID register", __FUNCTION__); } else { memcpy (dev->cid, cid_tmp, CID_SIZE); kfree (cid_tmp); } /* get the MMC CSD register (Card Specific Data) */ csd_tmp = get_csd (); if (csd_tmp == NULL) { err("%s - unable to get CSD register : use default settings", __FUNCTION__); dev->size = DFLT_BLK_SIZE; } else { memcpy (dev->csd, csd_tmp, CSD_SIZE); c_size = ((long) (csd_tmp[6]&0x03)) << 10; c_size += ((long) (csd_tmp[7]&0xff) << 2) + ((long)(csd_tmp[8]&0xff)>>6); c_size_mult = (long) (((csd_tmp[9] & 0x03) << 1) + ((csd_tmp[10] & 0x80) >> 7)); read_block_len = (long) (csd_tmp[5] & 0x000f); block_len = (long) (1 << read_block_len); mult = (long) (1 << (c_size_mult + 2)); block_nr = (c_size + 1) * mult; mmc_size = block_len * block_nr; dev->size = (unsigned int) (mmc_size / DFLT_BLKSIZE_SIZE); kfree (csd_tmp); } dev->sector_size = DFLT_HARDSECT_SIZE; dev->block_size = DFLT_BLKSIZE_SIZE; mmc_blk_size[device_num << DEVICE_SHIFT] = dev->size; for (part = 0; part < (1 << DEVICE_SHIFT); part++) { mmc_blk_blocksizes[(device_num << DEVICE_SHIFT) + part] = dev->block_size; mmc_blk_sectorsizes[(device_num << DEVICE_SHIFT) + part] = dev->sector_size; } info("%s - mmc_size : %ld(KB) - block_len : %ld - block_nr : %ld", __FUNCTION__, dev->size, dev->block_size, dev->size); return (0);}static int __init mmc_blk_init(void){ int result, device_num, device_found = 0, retval = 0; if ((result = register_blkdev (mmc_blk_major, DEVICE_NAME, &mmc_blk_ops)) < 0) { dbg(" driver : unable to register chrdev"); return (-1); } if (mmc_blk_major == 0) mmc_blk_major = result; mmc_blk_gendisk.major = mmc_blk_major; /* allocate our device private structure */ if (!(mmc_blk_dev = (struct mmc_blk *) kmalloc (nb_dev * sizeof (struct mmc_blk), GFP_KERNEL))) { retval = -ENOMEM; err("%s - unable to allocate memory", __FUNCTION__); goto alloc_dev_error_exit; } memset (mmc_blk_dev, 0, sizeof (struct mmc_blk)); memset (mmc_blk_size, 0, sizeof (mmc_blk_size)); memset (mmc_blk_blocksizes, 0, sizeof (mmc_blk_blocksizes)); memset (mmc_blk_sectorsizes, 0, sizeof (mmc_blk_sectorsizes)); /* mmc initialization */ for (device_num = 0; device_num < nb_dev; device_num++) { if (init_mmc (device_num, &mmc_blk_dev[device_num]) == 0) { device_found++; } } if (!device_found) { retval = -ENODEV; err("%s - unable to found MMC device", __FUNCTION__); goto alloc_dev_error_exit; } blk_size[mmc_blk_major] = mmc_blk_gendisk.sizes = mmc_blk_size; blksize_size[mmc_blk_major] = mmc_blk_blocksizes; hardsect_size[mmc_blk_major] = mmc_blk_sectorsizes; read_ahead[mmc_blk_major] = DFLT_RAHEAD; /* allocate the partition array. */ mmc_blk_partitions = kmalloc ((nb_dev << DEVICE_SHIFT) * sizeof (struct hd_struct), GFP_KERNEL); if (!mmc_blk_partitions) goto alloc_partition_error_exit; memset(mmc_blk_partitions, 0, (nb_dev << DEVICE_SHIFT) * sizeof(struct hd_struct)); /* device settings (partition later) */ for (device_num = 0; device_num < nb_dev; device_num++) { mmc_blk_partitions[device_num << DEVICE_SHIFT].nr_sects = mmc_blk_size[device_num << DEVICE_SHIFT] * mmc_blk_blocksizes[device_num << DEVICE_SHIFT] / mmc_blk_sectorsizes[device_num << DEVICE_SHIFT]; } mmc_blk_gendisk.part = mmc_blk_partitions; mmc_blk_gendisk.nr_real = nb_dev; /* Put our gendisk structure on the list */// add_gendisk (&mmc_blk_gendisk); /* register the gentisk structure for older kernel */ mmc_blk_gendisk.next = gendisk_head; gendisk_head = &mmc_blk_gendisk; blk_queue_make_request (BLK_DEFAULT_QUEUE(mmc_blk_major), mmc_blk_make_request); info("(device %d) check partition", device_num); for (device_num = 0; device_num < nb_dev; device_num++) { register_disk (&mmc_blk_gendisk, MKDEV(mmc_blk_major, (device_num << DEVICE_SHIFT)), DEVICE_SHIFT, &mmc_blk_ops, mmc_blk_partitions[device_num << DEVICE_SHIFT].nr_sects); } info("%s - MMC is now ready to use", __FUNCTION__); return (0);alloc_partition_error_exit : kfree (mmc_blk_dev); alloc_dev_error_exit : unregister_blkdev (mmc_blk_major, DEVICE_NAME); return (retval);}void __exit mmc_blk_exit(void){ int device_num; struct gendisk **gdp; for (device_num = 0; device_num < nb_dev; device_num++) { fsync_dev (MKDEV(mmc_blk_major, device_num)); } kfree (mmc_blk_dev); kfree (mmc_blk_partitions); unregister_blkdev (mmc_blk_major, DEVICE_NAME); /* clean global array */ blk_size[mmc_blk_major] = NULL; blksize_size[mmc_blk_major] = NULL; hardsect_size[mmc_blk_major] = NULL; read_ahead[mmc_blk_major] = 0; /* Get our gendisk structure off the list */ //del_gendisk (&mmc_blk_gendisk); /* unregister the gentisk structure for older kernel */ for (gdp = &gendisk_head; *gdp; gdp = &((*gdp)->next)) { if (*gdp == &mmc_blk_gendisk) { *gdp = (*gdp)->next; break; } } if (release_mmc () < 0) err("unable to release MMC"); info("MMC support disabled"); return;}module_init (mmc_blk_init);module_exit (mmc_blk_exit);MODULE_AUTHOR(DRIVER_AUTHOR);MODULE_DESCRIPTION(DRIVER_DESC);MODULE_LICENSE("GPL");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -