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

📄 nandsys.c

📁 linux下的nandflash驱动程序,这是从国外网站上下载来的
💻 C
📖 第 1 页 / 共 2 页
字号:
        FlashInitRoutine,        do_nothing,        Flash1_ChipSelect,        FlashReadByte,        FlashWriteByte,        FlashBlockRead,        FlashBlockWrite,        FlashCoreLeds,        mk_delay    },    {        FlashInitRoutine,        do_nothing,        Flash2_ChipSelect,        FlashReadByte,        FlashWriteByte,        FlashBlockRead,        FlashBlockWrite,        FlashCoreLeds,        mk_delay    }};/* nand_flash_init: register the block device number and set up pointer tables */int __init nand_flash_init (void){    int i, flash_id;    printk ("Nand Flash disk driver for CompuLab 786Core\r\nInterrupt disabling: %s\r\n", flashdisableintr?"Enabled":"Disabled");    //  Validate that ATA DMA is not enabled    if(!ignore_ata_var){      if (PciReadRegisterDWord (0x48, 0, 31, 1) & 0x0F)      {        printk ("Error: DMA is enabled for ATA.\r\nPlease build your kernel.\r\n");        return -1;      }    }        for (flash_id = 0;  flash_id < MAX_FLASHN;  flash_id++)    {        if (format)            printk ("Formatting Nand flash %d . . .\n", flash_id);        flogic[flash_id] = cl_logic_create (&cl_nand_linux[flash_id], 128, format);        if (!flogic[flash_id])        {            cl_error_log ("Flash %d initialization failed.\n", flash_id);            if(!flash_id)                return -1;        }    }            memset (flash_struct, 0, sizeof (flash_struct));    if (devfs_register_blkdev (MAJOR_NR, DEVICE_NAME, &flash_fops))    {	printk("flash: Unable to get major number %d\n",MAJOR_NR);	return -1;    }    devfs_handle = devfs_mk_dir (NULL, flash_gendisk.major_name, NULL);    blk_init_queue (BLK_DEFAULT_QUEUE(MAJOR_NR), DEVICE_REQUEST);    read_ahead[MAJOR_NR] = 8;	/* 8 sector (4kB) read ahead */    /*  Insert this disk into linked list of disks  */    flash_gendisk.next = gendisk_head;    gendisk_head = &flash_gendisk;    /*	Sizes initialization  */    for (i = 0;  i < (MAX_FLASHN << 6);  i++)	flash_blocksizes[i] = 1024;	/*  Blocks' sizes must be 1 KB  */    blksize_size[MAJOR_NR] = flash_blocksizes;    for (flash_id = 0;  flash_id < MAX_FLASHN;  flash_id++)        if (flogic[flash_id])        {            cl_trace_log (("Registering flash disk %d\r\n", flash_id));            register_disk (&flash_gendisk, MKDEV(MAJOR_NR, (flash_id << 6)),		           (1 << 6), &flash_fops,		           cl_logic_get_param (flogic[flash_id], CL_FLASH_TOTAL_SIZE, 0) / 512);        }    /*  Starting flush timer: the cl_timer_proc will be executed on each timer interrupt  */    cl_trace_log (("Starting timer task\r\n", flash_id));    queue_task(&timerTask, &tq_timer);    return 0;}/* flash_open: open a device */static int flash_open (struct inode *inode, struct file *file){    int dev = DEVICE_NR(inode->i_rdev);    MOD_INC_USE_COUNT;        if ((dev >= 0) && (dev < MAX_FLASHN) && flogic[dev])    {        cl_trace_log (("Flash device %d opened.\n", dev));	return 0;       /*  The device is valid  */    }    cl_trace_log (("Opening flash device %d failed.\n", dev));        MOD_DEC_USE_COUNT;    return -ENXIO;}static int flash_check_media_change (kdev_t dev){    return 0;	    /*	Disk not changed  */}static void cl_timer_proc (void* unused){    static int cnt = 0;    if (!(cnt++ & 3) && !StopLaunchTimer)    {       /*  Timer is 18 times a second. We take only 1/4  */        /*  Flush all cached data if ~100ms has elapsed since last write  */        if (last_end_write_cmd && (jiffies - last_end_write_cmd > HZ / 10))	{	    queue_task (&flushTask, &tq_disk);	}    }    /*  Reschedule timer  */    /* If cleanup wants us to die */    if (StopLaunchTimer)         queue_task (&flushTask, &tq_disk);    else        queue_task (&timerTask, &tq_timer);  }/*  This function is called by scheduler and it doesn't run in interrupts  */static void cl_flush_proc (void* unused){    int flash_id;    cl_trace_log (("cl_flush_proc called\r\n"));    down (&flash_sem);    for (flash_id = 0;  flash_id < MAX_FLASHN;  flash_id++)        if (flogic[flash_id])            cl_logic_sync (flogic[flash_id]);    cl_trace_log (("Data synced\r\n"));    last_end_write_cmd = 0;    up (&flash_sem);    if (StopLaunchTimer) 	wake_up (&WaitQ);   /* Now cleanup_module can return */}/* do_flash_request: handle an incoming request */static void do_flash_request (request_queue_t * q){    u_int block, count;    int code, i;    sti();    while (code = 0, !QUEUE_EMPTY)    {	INIT_REQUEST;	/* do some checking on the request structure */		if ((CURRENT_DEV < MAX_FLASHN) && flogic[CURRENT_DEV])	{	    block = CURRENT->sector + flash_struct[MINOR(CURRENT->rq_dev)].start_sect;	    count = CURRENT->current_nr_sectors;	    /*            printk ("Flash %d %s, start_sect = %d, total = %d, nr_sectors = %d, part_start = %d\r\n",                          CURRENT_DEV, ((CURRENT->cmd == READ) ? "read" : "write"),                          (int)block, (int)count, (int)CURRENT->nr_sectors, (int)flash_struct[MINOR(CURRENT->rq_dev)].start_sect);*/	    /*	Catch semaphore to disable simultaneous flash access from different places  */	    down (&flash_sem);    	    switch (CURRENT->cmd)	    {		case READ:		    for (i = 0, code = 1;  i < count;  i++)		    {			if (!cl_logic_read_sector (flogic[CURRENT_DEV],                                       block + i,                                      (char*)CURRENT->buffer + i * 512))			{			    code = 0;    /*	failure  */			    break;			}		    }		    break;		case WRITE:		    for (i = 0, code = 1;  i < count;  i++)		    {			if (!cl_logic_write_sector (flogic[CURRENT_DEV],                                       block + i,                                      (char*)CURRENT->buffer + i * 512))			{			    code = 0;    /*	failure  */			    break;			}		    }	            last_end_write_cmd = jiffies;		    break;		default:		    printk("do_flash_request: unknown request\n");		    break;	    }	    /*	Release semaphore  */	    up (&flash_sem);	}	else cl_trace_log  (("'IF' in request failed.\n"));	end_request (code);	/* wrap up, 0 = fail, 1 = success */    }}/* flash_ioctl: handle device ioctl's */static int flash_ioctl (struct inode *inode, struct file *file, u_int cmd, u_long arg){    int dev;        cl_trace_log (("flash_ioctl called.\n"));    if ((!inode) || !(inode->i_rdev))	return -EINVAL;    dev = DEVICE_NR(inode->i_rdev);    /*  Bad flash index  */    if ((dev < 0) || (dev >= MAX_FLASHN) || !flogic[dev])	return -EINVAL;    switch (cmd)    {	case HDIO_GETGEO:	{	    struct hd_geometry *geometry = (struct hd_geometry*)arg;	    if (!geometry)		return -EINVAL;	    /*	Bad arguments to ioctl  */	    put_user(cl_logic_get_param (flogic[dev], CL_FLASH_CYLINDERS_NUM, 0), &geometry->cylinders);	    put_user(cl_logic_get_param (flogic[dev], CL_FLASH_HEADS_NUM, 0), &geometry->heads);	    put_user(cl_logic_get_param (flogic[dev], CL_FLASH_SECTS_NUM, 0), &geometry->sectors);	    put_user(0, &geometry->start);	    return 0;	}	case BLKGETSIZE:	    if (!arg)		return -EINVAL;	    return put_user (cl_logic_get_param (flogic[dev], CL_FLASH_TOTAL_SIZE, 0) / 512, (long *) arg);	case HDIO_SET_DMA:	    /*	We don't use DMA for flash. This has no meaning  */	    if (!capable (CAP_SYS_ADMIN))		return -EACCES;	    return 0;	case HDIO_GET_DMA:	    return put_user( 0, (long *) arg);	/*  No DMA  */	case HDIO_GET_MULTCOUNT:	/*  We don't have a limitation of number of sectors in op.  */	    return put_user (128, (long *) arg);	case BLKRRPART:	{	    int partition;	    int start = (DEVICE_NR(dev)) << flash_gendisk.minor_shift;            if (!capable(CAP_SYS_ADMIN)) 		return -EACCES;	    for (partition = flash_gendisk.max_p - 1;  partition >= 0; partition--)	    {		int minor = (start | partition);		kdev_t devp = MKDEV(MAJOR_NR, minor);		struct super_block* sb = get_super(devp);				sync_dev(devp);		if (sb)		    invalidate_inodes(sb);		invalidate_buffers(devp);		flash_gendisk.part[start + partition].start_sect = 0;		flash_gendisk.part[start + partition].nr_sects = 0;	    }	    grok_partitions(&flash_gendisk, dev, (1 << 6),			    cl_logic_get_param (flogic[dev], CL_FLASH_TOTAL_SIZE, 0) / 512);	    return 0;	}	case BLKFLSBUF:	case BLKROSET:	case BLKROGET:	case BLKRASET:	case BLKRAGET:	case BLKPG:	    return blk_ioctl(inode->i_rdev, cmd, arg);	            case CL_FLASH_IO_GET_PARAM:	{	    int err;	    long* prm = (long*)arg;            err = verify_area (VERIFY_READ, prm, sizeof(long) * 2);	    if(err) return err;            err = verify_area (VERIFY_WRITE, prm, sizeof (long));	    if(err) return err;            prm[0] = cl_logic_get_param (flogic[dev], prm[0], prm[1]);            return 0;	}        case CL_FLASH_IO_DIRECT_ACCESS:	{	    int err;	    long* prm = (long*)arg;            err = verify_area (VERIFY_READ, prm, sizeof(long) * 3);	    if(err) return err;            err = verify_area (VERIFY_WRITE, prm, CL_FLASH_SECTOR_SIZE);	    if(err) return err;            return cl_logic_direct_access (flogic[dev],                                           (cl_nand_direct_access_type)prm[0],                                           (unsigned short)prm[1],                                           (unsigned short)prm[2],                                           (unsigned char*)(prm + 3));	}	default:	    return -EINVAL;    }}static int flash_revalidate (kdev_t dev){    return 0;}/* flash_release: release the device */static int flash_release (struct inode *inode, struct file *file){    int dev = DEVICE_NR(inode->i_rdev);    int flash_id;    cl_trace_log (("flash_release called for device %d.\n", dev));    down (&flash_sem);    for (flash_id = 0;  flash_id < MAX_FLASHN;  flash_id++)        if (flogic[flash_id])            cl_logic_sync (flogic[flash_id]);    cl_trace_log (("Data synced after RELEASE command\r\n"));    last_end_write_cmd = 0;    up (&flash_sem);    if ((dev >= 0) && (dev < MAX_FLASHN) && flogic[dev])    {#ifdef MODULE	MOD_DEC_USE_COUNT;#endif /* MODULE */    }        return 0;}#ifdef MODULEstatic void flash_done (void){    struct gendisk ** gdp;    int flash_id;        blksize_size[MAJOR_NR] = NULL;    blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));    blk_size[MAJOR_NR] = NULL;    hardsect_size[MAJOR_NR] = NULL;    read_ahead[MAJOR_NR] = 0;    /*	Remove this disk from linked lisk  */    for (gdp = &gendisk_head; *gdp; gdp = &((*gdp)->next))	if (*gdp == &flash_gendisk)	    break;    if (*gdp)	*gdp = (*gdp)->next;    /*	Free memory allocated by flash module  */    for (flash_id = 0;  flash_id < MAX_FLASHN;  flash_id++)        if (flogic[flash_id])        {            cl_logic_free (flogic[flash_id]);            flogic[flash_id] = NULL;        }}int init_module(void){    int error;    error = nand_flash_init();    if (error)	return error;    return 0;}void cleanup_module(void){    int partition, dev, start;    /*	Stop launching timers  */    cl_trace_log (("Stopping launching timers.\n"));    StopLaunchTimer = 1;    sleep_on (&WaitQ);    cl_trace_log (("Done stopping launching timers.\n"));    devfs_unregister_blkdev (MAJOR_NR, DEVICE_NAME);    for (dev = 0;  dev < MAX_FLASHN;  dev++)    {        if (!flogic[dev])            continue;        start = (dev << flash_gendisk.minor_shift);         for (partition = flash_gendisk.max_p - 1; partition >= 0; partition--)        {	    int minor = (start | partition);	    kdev_t devp = MKDEV(MAJOR_NR, minor);	    start = dev << flash_gendisk.minor_shift; 	    sync_dev(devp);	    invalidate_buffers(devp);        }        devfs_unregister (devfs_handle);    }    flash_done();}#endif /* MODULE */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -