📄 sd_sys.c
字号:
spin_lock_irq(q->queue_lock); set_current_state(TASK_INTERRUPTIBLE); if (!blk_queue_plugged(q)) pSDI->req = req = elv_next_request(q); spin_unlock_irq(q->queue_lock); if (!req) { if (pSDI->flags & SD_QUEUE_EXIT) break; up(&pSDI->thread_sem); schedule(); down(&pSDI->thread_sem); continue; } set_current_state(TASK_RUNNING); SD_issue_rq(req); } while (1); remove_wait_queue(&pSDI->thread_wq, &wait); up(&pSDI->thread_sem); complete_and_exit(&pSDI->thread_complete, 0); return 0;}/* * Prepare a SD request. Essentially, this means passing the * preparation off to the media driver. The media driver will * create a mmc_io_request in req->special. */static int SD_prep_request(struct request_queue *q, struct request *req){ int ret = BLKPREP_KILL; if (req->flags & REQ_SPECIAL) { /* * Special commands already have the command * blocks already setup in req->special. */ BUG_ON(!req->special); ret = BLKPREP_OK; } else if (req->flags & (REQ_CMD | REQ_BLOCK_PC)) { /* * Block I/O requests need translating according * to the protocol. */ ret = BLKPREP_OK; } else { /* * Everything else is invalid. */ blk_dump_rq_flags(req, "SD bad request"); } if (ret == BLKPREP_OK) req->flags |= REQ_DONTPREP; return ret;}static void SD_request(request_queue_t *q){ if (!pSDI->req) wake_up(&pSDI->thread_wq);}//----------------------------------------static int use_sd=1;static int __init setup_sd(char *str){ if(str[0] == '0') use_sd=0; return 1;}__setup("sd=", setup_sd);static int use_sdplug=0;static int __init setup_sdplug(char *str){ if(str[0] == '1') use_sdplug=1; return 1;}__setup("sdplug=", setup_sdplug);#include <asm/io.h>#include <asm/sizes.h>extern unsigned long RCA;//2007-07-31: add soft irq to handle timer irqstatic void SD_tasklet_card(unsigned long param){ //1--inserted, 0--uninserted if (sdinsert == 1) { if (!SDI_SendCmd(pSDI, &CommandParameters[SEND_STATUS], RCA, 0, 0)) { sdinsert = 0; SD_remove(pSDI); printk("<1>SD Card removed\n"); } } else { if(SD_insert(pSDI)) { sdinsert = 1; printk("<1>SD Card inserted!\n"); } } mod_timer(&pSDI->timer, jiffies + HZ);}static void SD_check_status(unsigned long data){ tasklet_schedule(&pSDI->card_tasklet); }static int check_sd_status(void){ return sdinsert;}#define SDPLUG_IOC_MAGIC 'n'#define SDPLUG_IOCREQUEST _IOR(SDPLUG_IOC_MAGIC, 1, unsigned long )static int sdplug_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg){ switch (cmd) { case SDPLUG_IOCREQUEST : return check_sd_status(); } return 0;}static struct file_operations sdplug_fops = { ioctl:sdplug_ioctl,};//2007-07-31: add request thread to handle request.//TODO: timer handle to support hot-plugstatic int __init SD_init(void){ int ret; printk("SD_init\n"); if(use_sd == 0) return -ENODEV; if(register_chrdev(218, "sd-plug", &sdplug_fops) < 0){ printk("<1>sd-plug: unable to register major\n"); return -ENODEV; } if(register_blkdev(SD_MAJOR,"z228_sd")){//register the block device printk("cann't register the block device z228_sd\n"); return -EBUSY; } pSDI = kmalloc(sizeof(SD_controller),GFP_KERNEL);//malloc the SD_controller struct if(!pSDI){ printk("fail to malloc device!\n"); goto unregister_device; } if (!SDI_init(pSDI)){//call the SDI_Initface printk("fail to init the SDI!\n"); goto out_disk; } spin_lock_init(&pSDI->lock); spin_lock_init(&pSDI->cmd_lock); //blk_cleanup_queue should be called in release funciont! pSDI->queue = blk_init_queue(SD_request, (spinlock_t *) (&pSDI->lock)); if(pSDI->queue == NULL){ printk("cannot init queue z228_sd\n"); goto out_disk; } blk_queue_prep_rq(pSDI->queue, SD_prep_request); blk_queue_bounce_limit(pSDI->queue, BLK_BOUNCE_HIGH); blk_queue_max_sectors(pSDI->queue, 8); blk_queue_max_phys_segments(pSDI->queue, 16); blk_queue_max_hw_segments(pSDI->queue, 16); blk_queue_max_segment_size(pSDI->queue, 64<<9); blk_queue_hardsect_size(pSDI->queue, 1 << BYTES_PER_SECTOR_SH); pSDI->req = NULL; init_completion(&pSDI->thread_complete); init_waitqueue_head(&pSDI->thread_wq); init_MUTEX(&pSDI->thread_sem); ret = kernel_thread(SD_queue_thread, NULL, CLONE_KERNEL); if (ret < 0) { printk("create queue thread error\n"); goto out_disk; } wait_for_completion(&pSDI->thread_complete); init_completion(&pSDI->thread_complete); tasklet_init(&pSDI->card_tasklet, SD_tasklet_card, NULL); pSDI->gd = alloc_disk(1);//alloc a gendisk if(!pSDI->gd){ printk(KERN_NOTICE "alloc_disk failure\n"); return 1; } //initialize the gen disk pSDI->gd->major = SD_MAJOR; pSDI->gd->first_minor = 0; pSDI->gd->fops = &SD_ops; pSDI->gd->queue = pSDI->queue; pSDI->gd->private_data = NULL; strcpy(pSDI->gd->disk_name, "z228_sd"); //SD_controller *dev = inode->i_bdev->bd_disk->private_data; if(sd_request_dma() < 0){//reuest a dma channel printk("sd dma error!\n"); goto out_disk; } if(use_sdplug==0) { if(SD_insert(pSDI)) { sdinsert = 1; //add_disk(pSDI->gd); } else { void *r; u32 data; r = ioremap(0x2002c000, SZ_4K); if(r==NULL){ printk("sd gpio setup error3\n"); return -ENODEV; } data = readl(r+0x400); writel((data & 0xef), r+0x400); data = readl(r+0x410); writel((data & 0xef), r+0x400); iounmap(r); } }#if 0 init_timer(&pSDI->timer); pSDI->timer.data = NULL; pSDI->timer.function = SD_check_status; pSDI->timer.expires = jiffies + HZ; add_timer(&pSDI->timer);#endif printk("<1>Z228 SD init OK\n"); return 0;out_disk: if(pSDI){ pSDI->flags |= SD_QUEUE_EXIT; wake_up(&pSDI->thread_wq); wait_for_completion(&pSDI->thread_complete); if(pSDI->irq_request_sign) free_irq(14,NULL); if(pSDI->Registers) iounmap((void *)pSDI->Registers); if(pSDI->queue) blk_cleanup_queue(pSDI->queue); if(pSDI->gd) del_gendisk(pSDI->gd); kfree((void *)pSDI); } unregister_device: unregister_blkdev(SD_MAJOR,"z228_sd"); unregister_chrdev(218, "sd-plug"); return -ENODEV;}//--------------------------------------------------------static void __exit SD_cleanup(void){ if(pSDI){ SDI_close(pSDI); SDI_deInit(pSDI); pSDI->flags |= SD_QUEUE_EXIT; wake_up(&pSDI->thread_wq); wait_for_completion(&pSDI->thread_complete); if(pSDI->irq_request_sign) free_irq(14,NULL); if(pSDI->Registers) iounmap((void *)pSDI->Registers); if(pSDI->queue) blk_cleanup_queue(pSDI->queue); if(pSDI->gd) del_gendisk(pSDI->gd); kfree((void *)pSDI); } unregister_blkdev(SD_MAJOR,"z228_sd"); unregister_chrdev(218, "sd-plug");} module_init(SD_init);module_exit(SD_cleanup);MODULE_AUTHOR("Jade Tech");MODULE_LICENSE("Dual BSD/GPL");MODULE_DESCRIPTION("z228 SD card driver!");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -