📄 sd_sys.c
字号:
/**************************************************************************** File: sd_sys.c - Export stream interface to OS* * The content of this file or document is CONFIDENTIAL and PROPRIETARY* to Jade Technologies Co., Ltd. It is subject to the terms of a* License Agreement between Licensee and Jade Technologies Co., Ltd.* restricting among other things, the use, reproduction, distribution* and transfer. Each of the embodiments, including this information * and any derivative work shall retain this copyright notice.* * Copyright (c) 2005 Jade Technologies Co., Ltd. * All rights reserved.****************************************************************************/#include <linux/syscalls.h>#include <linux/module.h>#include <linux/blkdev.h>#include "sd.h"#define SD_SYS_DEBUG 0#define SD_MAJOR 220#define SD_MINOR 0//------------------------------------------------------------------------------// Global Variables in SD_SYS.C//------------------------------------------------------------------------------//DISK_INFO DiskInfo = {0}; // store information of card//LPWSTR ActivePath = NULL; // get strings in registerstatic SD_controller *pSDI = NULL; // structure of card's instancestatic int g_ExcCnt = 0; // count times open/close error ocurredstatic int g_CardStatus = 0; // indicate the card's statestatic int nsectors = 8;int sdinsert=0;int irqcount=0;int irqcount1=0;static int SD_open(struct inode *inode,struct file *filp);static int SD_release(struct inode *inode,struct file *filp);static int SD_ioctl(struct inode *inode,struct file *filp,unsigned int cmd,unsigned long arg);static struct block_device_operations SD_ops = { .owner = THIS_MODULE, .open = SD_open, .release= SD_release, .ioctl = SD_ioctl};//----------------------------------------------//reset the interface and register SD cmd irq//----------------------------------------------static BOOLSDI_init(SD_controller * pSDI){ unsigned long errorcode = 0; pSDI->irq_request_sign = 1;//indicate no irq is requested if(!SDI_InitInterface(pSDI,&errorcode)) return 0; g_CardStatus = STATE_INITING;#if SD_TEST g_CardStatus = STATE_TEST;#endif return 1;}//-------------------------------------------------static BOOLSD_insert1(SD_controller * pSDI){ unsigned long errorcode = 0; if (SDI_StartUpCard(pSDI, &errorcode)){ set_capacity(pSDI->gd, (pSDI->CardCSD.CardSize)/BYTES_PER_SECTOR );//set the disk size if (g_CardStatus != STATE_TEST) g_CardStatus = STATE_OPENED; g_ExcCnt = 0; add_disk(pSDI->gd); return 1; }else{ printk("<1>sdi_open:%lu\n", errorcode); if (g_CardStatus != STATE_TEST) g_CardStatus = STATE_CLOSED; if ((g_ExcCnt++) > 8) g_CardStatus = STATE_DEAD; return 0; }}static BOOLSD_insert(SD_controller * pSDI){ int retry=3; do { if(SD_insert1(pSDI)) return 1; retry--; if(retry==0) break; } while(1); return 0;} //------------------------------------------------------------------------------static BOOLSD_remove(SD_controller * pSDI){ BOOL bClose = FALSE; unsigned long errorcode = 0; if (SDI_ResetInterface(pSDI, &errorcode)){ bClose = TRUE; if (g_CardStatus != STATE_TEST) g_CardStatus = STATE_CLOSED; g_ExcCnt = 0; }else{ if (g_CardStatus != STATE_TEST) g_CardStatus = STATE_OPENED; if ((g_ExcCnt++) > 8) g_CardStatus = STATE_DEAD; } return bClose;} // SDI_Close//------------------------------------------------------------------------------static BOOLSDI_deinit(SD_controller *pSDI){ BOOL bDeinit = FALSE; unsigned long errorcode = 0; if (SDI_DeinitInterface(pSDI, &errorcode)){ bDeinit = TRUE; g_CardStatus = STATE_DEINITING; }else{ g_CardStatus = STATE_DEAD; } msleep(100); /*{ volatile int a, b; for(a=0; a<100; a++); for(b=0; b<10000; b++); }*/ return bDeinit;} // SDI_Deinit#if SD_SYS_DEBUGstatic char sector_r[512];static char sector_w[512];static void SD_Demo(void){ int i; unsigned long errorcode; memset((void *)sector_r, 0, 512); memset((void *)sector_w, 0xff, 512); for (i=0; i<16; i++) sector_w[i] = i; { printk("original w sector: \n"); for (i=0; i<16; i++) { printk("%02X ", sector_w[i]); } printk("\n"); } for (i=0; i<5; i++) SDI_BlockWrite(pSDI, 5 + i, 1, sector_w, &errorcode); for (i=0; i<5; i++) SDI_BlockRead(pSDI, 5 + i, 1, sector_r, &errorcode);}#endif//-------------------------------------------------------static int SD_open(struct inode *inode,struct file *filp){#if SD_SYS_DEBUG SD_Demo();#endif return 0;} //--------------------------------------------------------static int SD_release(struct inode *inode,struct file *filp){ return 0;}//--------------------------------------------------------static int SD_ioctl(struct inode *inode,struct file *filp,unsigned int cmd,unsigned long arg){ switch (cmd) { case HDIO_GETGEO: { struct hd_geometry g; struct hd_geometry __user *geom= (void __user *)arg; /* g.heads = ((pSDI->CardCSD.CardSize)/BYTES_PER_SECTOR) >> 24; g.sectors = (pSDI->CardCSD.CardSize)/BYTES_PER_SECTOR ; g.cylinders = ((pSDI->CardCSD.CardSize)/BYTES_PER_SECTOR) >> 8 ; */ g.heads=4; g.sectors=60; g.cylinders = pSDI->CardCSD.CardSize / (g.heads * g.sectors * BYTES_PER_SECTOR) ; //g.heads = 4; //g.sectors = 16; //g.cylinders = pSDI->CardCSD.CardSize / (g.heads * g.sectors * BYTES_PER_SECTOR) ; g.start = 0; return copy_to_user(geom, &g, sizeof(g)) ? -EFAULT : 0; } default: printk("SD_ioctl:%x, unsupport\n", cmd); return -EINVAL; } return 0;}//--------------------------------------------------------#define SD_QUEUE_EXIT (1 << 0)//2007-07-31: modify r/w request handle. use one thread to replace// old request function.static BOOL SD_issue_rq(struct request *req){ BOOL i = TRUE; unsigned long errorcode = 0; unsigned long start, len; int ret = 0; do { start = req->sector; len = req->nr_sectors; if(len >= 32) len = 31; req->hard_cur_sectors = len; //spin_lock(&pSDI->cmd_lock); if (rq_data_dir(req) == READ) { //printk("cmd type: %c\n", 'R'); i = SDI_BlockRead(pSDI, start, len , req->buffer, &errorcode); } else if (rq_data_dir(req) == WRITE) { //printk("cmd type: %c\n", 'W'); i = SDI_BlockWrite(pSDI, start, len , req->buffer, &errorcode); } else { printk("cmd type: %c\n", 'X'); i = TRUE; } //spin_unlock(&pSDI->cmd_lock); if (i == FALSE) break; /* * A block was successfully transferred. */ spin_lock_irq(&pSDI->lock); ret = end_that_request_chunk(req, 1, len << 9); if (!ret) { /* * The whole request completed successfully. */ add_disk_randomness(req->rq_disk); blkdev_dequeue_request(req); end_that_request_last(req); } spin_unlock_irq(&pSDI->lock); } while (ret); if (i == FALSE) { printk("%s errorcode:%lu\n", (rq_data_dir(req) == READ)?"read":"write", errorcode); /* * This is a little draconian, but until we get proper * error handling sorted out here, its the best we can * do - especially as some hosts have no idea how much * data was transferred before the error occurred. */ spin_lock_irq(&pSDI->lock); do { ret = end_that_request_chunk(req, 0, req->current_nr_sectors << 9); } while (ret); add_disk_randomness(req->rq_disk); blkdev_dequeue_request(req); end_that_request_last(req); spin_unlock_irq(&pSDI->lock); } return i;}static int SD_queue_thread(void *d){ struct request_queue *q = pSDI->queue; DECLARE_WAITQUEUE(wait, current); /* * Set iothread to ensure that we aren't put to sleep by * the process freezing. We handle suspension ourselves. */ current->flags |= PF_MEMALLOC|PF_NOFREEZE; daemonize("mmcqd"); complete(&pSDI->thread_complete); down(&pSDI->thread_sem); add_wait_queue(&pSDI->thread_wq, &wait); do { struct request *req = NULL;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -