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

📄 sdcard.c

📁 嵌入式linux系统下hi3510平台的osd开发源码
💻 C
📖 第 1 页 / 共 2 页
字号:
	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, &param);

	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 + -