📄 sdcard.c
字号:
else if( (1000*1000*1000)<=size && size<(2000*1000*1000) )
temp = 32;
else if( (2000*1000*1000)<=size && size<(2100*1000*1000) )
temp = 64;
else if( (2100*1000*1000)<=size )
temp = 128;
else
temp = 32;
return(temp);
}
/*
* get geo.sectors routine.
* @param size: sdcard size;
*
* @return value:sectors
*
*/
static unsigned int get_sectors(unsigned long size)
{
unsigned int temp=0;
if( size<(14*1000*1000) )
temp = 16;
else if( (14*1000*1000)<=size && size<(500*1000*1000) )
temp = 32;
else if( (500*1000*1000)<=size )
temp = 63;
else
temp = 63;
return(temp);
}
/*
* blk device ioctl routine.
* @param inode: pointer of the node;
* @param file: pointer of the file;
* @param cmd: request command;
* @param arg: request command parameter.
*
* @return value:0-- success
*
*/
static int sd_ioctl (struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg)
{
unsigned long size;
struct hd_geometry geo;
switch(cmd)
{
case HDIO_GETGEO:
size = Device.size*(hardsect_size/KERNEL_SECTOR_SIZE);
geo.cylinders = (size & ~0x3f) >> 6;
geo.heads = get_heads(size);//8;
geo.sectors = get_sectors(size);//32;
geo.start = 0;
if (copy_to_user((void *) arg, &geo, sizeof(geo)))
return -EFAULT;
return 0;
}
return -ENOTTY; /* unknown command */
}
/*
* get SD card state routine.
* @param gd: pointer gendisk
*
* @return value: card state
*
*/
int sd_media_changed(struct gendisk *gd)
{
struct sd_device *dev = gd->private_data;
return dev->media_change;
}
/*
* SD card reset routine.
* @param gd: pointer gendisk
*
* @return value:0-- success
*
*/
int sd_revalidate(struct gendisk *gd)
{
struct sd_device *dev = gd->private_data;
if (dev->media_change) {
dev->media_change = 0;
}
return (0);
}
/*
* blk open routine.
* @param inode: pointer inode
* @param filp : pointer file
*
* @return value:0-- success
*
*/
static int sd_open(struct inode *inode, struct file *filp)
{
struct sd_device *dev = inode->i_bdev->bd_disk->private_data;
filp->private_data = dev;
spin_lock(&dev->lock);
if (! dev->users)
check_disk_change(inode->i_bdev);
dev->users++;
spin_unlock(&dev->lock);
return 0;
}
/*
* blk release routine.
* @param inode: pointer inode
* @param filp : pointer file
*
* @return value:0-- success
*
*/
static int sd_release(struct inode *inode, struct file *filp)
{
struct sd_device *dev = inode->i_bdev->bd_disk->private_data;
spin_lock(&dev->lock);
dev->users--;
spin_unlock(&dev->lock);
return 0;
}
/*
* sd_rq_thread routine.
*
* @param wait: pointer void
*
* @return value: 0-- success
*/
static int sd_rq_thread(void * prq)
{
struct request *req = NULL;
struct request_queue *rq = (struct request_queue *)prq;
unsigned int ret=0;
unsigned int flags;
DECLARE_WAITQUEUE(wait, current);
struct sched_param param = { .sched_priority = 50 };
sched_setscheduler(current, SCHED_RR, ¶m);
current->flags |= PF_MEMALLOC|PF_NOFREEZE;
daemonize("sd_host");
while(! thread_quit)
{
spin_lock_irqsave(rq->queue_lock, flags);
req = elv_next_request(rq);
spin_unlock_irqrestore(rq->queue_lock, flags);
if (!req)
{
add_wait_queue(&Device.wq, &wait);
set_current_state(TASK_INTERRUPTIBLE);
schedule();
remove_wait_queue(&Device.wq, &wait);
continue;
}
if (! blk_fs_request(req))
{
printk (" NONE CMD request\n");
end_request(req, 0);
continue;
}
if(Device.sd_error)
{
spin_lock_irqsave(rq->queue_lock, flags);
while((req = elv_next_request(rq))!=NULL)
{
spin_unlock_irqrestore(rq->queue_lock, flags);
ret = sd_xfer_request(&Device, req);
spin_lock_irqsave(rq->queue_lock, flags);
end_that_request_first(req, 0, ret);
add_disk_randomness(req->rq_disk);
blkdev_dequeue_request(req);
end_that_request_last(req);
}
spin_unlock_irqrestore(rq->queue_lock, flags);
msleep(10);
}
else
{
ret = sd_xfer_request(&Device, req);
spin_lock_irqsave(rq->queue_lock, flags);
if (! end_that_request_first(req, 1, ret) )
{
add_disk_randomness(req->rq_disk);
blkdev_dequeue_request(req);
end_that_request_last(req);
}
spin_unlock_irqrestore(rq->queue_lock, flags);
}
}
spin_lock_irqsave(rq->queue_lock, flags);
blk_stop_queue(Queue);
while((req = elv_next_request(rq))!=NULL)
{
end_request(req,0);
}
spin_unlock_irqrestore(rq->queue_lock, flags);
return 0;
}
static struct block_device_operations sd_ops = {
.owner = THIS_MODULE,
.open = sd_open,
.release = sd_release,
.media_changed = sd_media_changed,
.revalidate_disk= sd_revalidate,
.ioctl = sd_ioctl
};
void sd_power_detect(int x)
{
if(x)
{
Device.sd_online=1;
}
else
{
Device.sd_online=0;
}
queue_work(sd_workqueue, &sd_work);
}
/*
* blk device init routine.
*
* @return value: 0-- success -ENOMEM-- not asked space -ENXIO-- sd card init error
*
*/
static int __init sd_init(void)
{
unsigned int ret=0;
sd_workqueue = create_singlethread_workqueue(SD_WORKQUEUE_NAME);
sd_insert_hook(&sd_power_detect);
memset(&Device.size,0,sizeof(struct sd_device));
if(get_sd_state())
Device.sd_online=1;
else
Device.sd_online=0;
sdcard_repower();
ret=sdcard_init();
if(ret)
{
printk(" SD card init error !!%d\n",ret);
goto init_out;
}
sdcard_cid_read();
ret=sdcard_csd_read();
if(ret == 0)
{
printk(" SD card read error !!%d\n",ret);
goto init_out;
}
else
{
nsectors=ret/KERNEL_SECTOR_SIZE;
Device.size = nsectors*hardsect_size;
printk(" %lu bytes\n",Device.size);
}
Device.major_num = register_blkdev(0, "sd");
if (Device.major_num <= 0)
{
printk("sd: unable to get major number\n");
goto out_unregister;
}
spin_lock_init(&Device.lock);
init_waitqueue_head(&Device.wq);
init_waitqueue_head(&Device.dma_wq);
Queue = blk_init_queue(sd_request, &Device.lock);
if (Queue == NULL){
printk( "blk_init_queue failed!\n");
goto out_unregister;
}
blk_queue_hardsect_size(Queue, hardsect_size);
blk_queue_max_sectors(Queue, MAXNUM);
blk_queue_max_phys_segments(Queue, MAXNUM);
blk_queue_max_hw_segments(Queue, MAXNUM);
blk_queue_max_segment_size(Queue, MAXNUM*KERNEL_SECTOR_SIZE);
if ((ret=kernel_thread(sd_rq_thread, Queue, CLONE_KERNEL) )< 0)
{
printk("Create kernel thread failed!\n");
goto out_unregister;
}
else
{
/* printk(" kernel_thread id=%d\n",ret); */
}
devfs_mk_dir("sd");
Device.gd = alloc_disk(minors);
if (! Device.gd){
printk("allock_disk failed!\n");
goto out_unregister;
}
#ifdef CONFIG_SSP_DMA
hi_ssp_set_serialclock(0,10);
ret=sd_dmac_ssp_init(&Device.mapreadbufaddr,&Device.mapwritebufaddr);
if(ret)
{
printk("sd: sd_dmac_ssp_init error \n");
goto del_disk;
}
Device.readbuf =(char *)Device.mapreadbufaddr;
Device.writebuf=(char *)Device.mapwritebufaddr;
#else
hi_ssp_set_serialclock(0,6);
#endif
Device.gd->flags = GENHD_FL_REMOVABLE;
Device.gd->major = Device.major_num;
Device.gd->first_minor = 0;
Device.gd->minors = minors;
Device.gd->fops = &sd_ops;
Device.gd->private_data = &Device.size;
strcpy (Device.gd->disk_name, "sd0");
strcpy (Device.gd->devfs_name, "sd/0");
set_capacity(Device.gd, nsectors*(hardsect_size/KERNEL_SECTOR_SIZE));
Device.gd->queue = Queue;
add_disk(Device.gd);
return 0;
#ifdef CONFIG_SSP_DMA
del_disk:
put_disk(Device.gd);
#endif
out_unregister:
unregister_blkdev(Device.major_num, "sd");
init_out:
flush_workqueue(sd_workqueue);
destroy_workqueue(sd_workqueue);
sd_insert_hook(NULL);
return -ENXIO;
}
/*
* blk device exit routine.
*
*/
static void __exit sd_exit(void)
{
thread_quit = 1;
wake_up(&Device.wq);
msleep(100);
del_gendisk(Device.gd);
put_disk(Device.gd);
blk_cleanup_queue(Queue);
unregister_blkdev(Device.major_num, "sd");
sdcard_exit();
#ifdef CONFIG_SSP_DMA
sd_dmac_ssp_exit();
#endif
sd_insert_hook(NULL);
flush_workqueue(sd_workqueue);
destroy_workqueue(sd_workqueue);
}
/*
* workqueue routine.
*
*/
static void sd_do_work(void *p)
{
unsigned int ret=0;
Device.media_change=1;
if(Device.sd_online==1)
{
ret=sdcard_init();
sdcard_cid_read();
ret=sdcard_csd_read();
if(ret == 0)
{
printk(" SD card error !!\n");
}
else
{
nsectors=ret/KERNEL_SECTOR_SIZE;
Device.size = nsectors*hardsect_size;
printk(" %lu bytes\n",Device.size);
blk_start_queue(Queue);
}
Device.sd_error=0;
#ifdef CONFIG_SSP_DMA
hi_ssp_set_serialclock(0,10);
#else
hi_ssp_set_serialclock(0,6);
#endif
return;
}
else
{
}
}
module_init(sd_init);
module_exit(sd_exit);
#ifdef MODULE
#include <linux/compile.h>
#endif
MODULE_INFO(build, UTS_VERSION);
MODULE_LICENSE("GPL");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -