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

📄 ide-disk.c

📁 at91rm9200处理器ide接口驱动程序源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
		return (lba48bit) ? WIN_MULTREAD_EXT : WIN_MULTREAD;	else if (cmd == READ)		return (lba48bit) ? WIN_READ_EXT : WIN_READ;	else if ((cmd == WRITE) && (drive->using_dma))		return (lba48bit) ? WIN_WRITEDMA_EXT : WIN_WRITEDMA;	else if ((cmd == WRITE) && (drive->mult_count))		return (lba48bit) ? WIN_MULTWRITE_EXT : WIN_MULTWRITE;	else if (cmd == WRITE)		return (lba48bit) ? WIN_WRITE_EXT : WIN_WRITE;	else		return WIN_NOP;}static ide_startstop_t chs_rw_disk (ide_drive_t *drive, struct request *rq, unsigned long block){	struct hd_drive_task_hdr	taskfile;	struct hd_drive_hob_hdr		hobfile;	ide_task_t			args;	task_ioreg_t command	= get_command(drive, rq->cmd);	unsigned int track	= (block / drive->sect);	unsigned int sect	= (block % drive->sect) + 1;	unsigned int head	= (track % drive->head);	unsigned int cyl	= (track / drive->head);	memset(&taskfile, 0, sizeof(task_struct_t));	memset(&hobfile, 0, sizeof(hob_struct_t));	taskfile.sector_count	= (rq->nr_sectors==256)?0x00:rq->nr_sectors;	taskfile.sector_number	= sect;	taskfile.low_cylinder	= cyl;	taskfile.high_cylinder	= (cyl>>8);	taskfile.device_head	= head;	taskfile.device_head	|= drive->select.all;	taskfile.command	= command;#ifdef DEBUG	printk("%s: %sing: ", drive->name, (rq->cmd==READ) ? "read" : "writ");	if (lba)	printk("LBAsect=%lld, ", block);	else		printk("CHS=%d/%d/%d, ", cyl, head, sect);	printk("sectors=%ld, ", rq->nr_sectors);	printk("buffer=0x%08lx\n", (unsigned long) rq->buffer);#endif	memcpy(args.tfRegister, &taskfile, sizeof(struct hd_drive_task_hdr));	memcpy(args.hobRegister, &hobfile, sizeof(struct hd_drive_hob_hdr));	args.command_type	= ide_cmd_type_parser(&args);	args.prehandler		= ide_pre_handler_parser(&taskfile, &hobfile);	args.handler		= ide_handler_parser(&taskfile, &hobfile);	args.posthandler	= NULL;	args.rq			= (struct request *) rq;	args.block		= block;	rq->special		= NULL;	rq->special		= (ide_task_t *)&args;	return do_rw_taskfile(drive, &args);}static ide_startstop_t lba_28_rw_disk (ide_drive_t *drive, struct request *rq, unsigned long block){	struct hd_drive_task_hdr	taskfile;	struct hd_drive_hob_hdr		hobfile;	ide_task_t			args;	task_ioreg_t command	= get_command(drive, rq->cmd);	memset(&taskfile, 0, sizeof(task_struct_t));	memset(&hobfile, 0, sizeof(hob_struct_t));	taskfile.sector_count	= (rq->nr_sectors==256)?0x00:rq->nr_sectors;	taskfile.sector_number	= block;	taskfile.low_cylinder	= (block>>=8);	taskfile.high_cylinder	= (block>>=8);	taskfile.device_head	= ((block>>8)&0x0f);	taskfile.device_head	|= drive->select.all;	taskfile.command	= command;#ifdef DEBUG	printk("%s: %sing: ", drive->name, (rq->cmd==READ) ? "read" : "writ");	if (lba)	printk("LBAsect=%lld, ", block);	else		printk("CHS=%d/%d/%d, ", cyl, head, sect);	printk("sectors=%ld, ", rq->nr_sectors);	printk("buffer=0x%08lx\n", (unsigned long) rq->buffer);#endif	memcpy(args.tfRegister, &taskfile, sizeof(struct hd_drive_task_hdr));	memcpy(args.hobRegister, &hobfile, sizeof(struct hd_drive_hob_hdr));	args.command_type	= ide_cmd_type_parser(&args);	args.prehandler		= ide_pre_handler_parser(&taskfile, &hobfile);	args.handler		= ide_handler_parser(&taskfile, &hobfile);	args.posthandler	= NULL;	args.rq			= (struct request *) rq;	args.block		= block;	rq->special		= NULL;	rq->special		= (ide_task_t *)&args;	return do_rw_taskfile(drive, &args);}/* * 268435455  == 137439 MB or 28bit limit * 320173056  == 163929 MB or 48bit addressing * 1073741822 == 549756 MB or 48bit addressing fake drive */static ide_startstop_t lba_48_rw_disk (ide_drive_t *drive, struct request *rq, unsigned long long block){	struct hd_drive_task_hdr	taskfile;	struct hd_drive_hob_hdr		hobfile;	ide_task_t			args;	task_ioreg_t command	= get_command(drive, rq->cmd);	memset(&taskfile, 0, sizeof(task_struct_t));	memset(&hobfile, 0, sizeof(hob_struct_t));	taskfile.sector_count	= rq->nr_sectors;	hobfile.sector_count	= (rq->nr_sectors>>8);	if (rq->nr_sectors == 65536) {		taskfile.sector_count	= 0x00;		hobfile.sector_count	= 0x00;	}	taskfile.sector_number	= block;	/* low lba */	taskfile.low_cylinder	= (block>>=8);	/* mid lba */	taskfile.high_cylinder	= (block>>=8);	/* hi  lba */	hobfile.sector_number	= (block>>=8);	/* low lba */	hobfile.low_cylinder	= (block>>=8);	/* mid lba */	hobfile.high_cylinder	= (block>>=8);	/* hi  lba */	taskfile.device_head	= drive->select.all;	hobfile.device_head	= taskfile.device_head;	hobfile.control		= (drive->ctl|0x80);	taskfile.command	= command;#ifdef DEBUG	printk("%s: %sing: ", drive->name, (rq->cmd==READ) ? "read" : "writ");	if (lba)	printk("LBAsect=%lld, ", block);	else		printk("CHS=%d/%d/%d, ", cyl, head, sect);	printk("sectors=%ld, ", rq->nr_sectors);	printk("buffer=0x%08lx\n", (unsigned long) rq->buffer);#endif	memcpy(args.tfRegister, &taskfile, sizeof(struct hd_drive_task_hdr));	memcpy(args.hobRegister, &hobfile, sizeof(struct hd_drive_hob_hdr));	args.command_type	= ide_cmd_type_parser(&args);	args.prehandler		= ide_pre_handler_parser(&taskfile, &hobfile);	args.handler		= ide_handler_parser(&taskfile, &hobfile);	args.posthandler	= NULL;	args.rq			= (struct request *) rq;	args.block		= block;	rq->special		= NULL;	rq->special		= (ide_task_t *)&args;	return do_rw_taskfile(drive, &args);}#else /* !__TASKFILE__IO *//* * do_rw_disk() issues READ and WRITE commands to a disk, * using LBA if supported, or CHS otherwise, to address sectors. * It also takes care of issuing special DRIVE_CMDs. */static ide_startstop_t do_rw_disk (ide_drive_t *drive, struct request *rq, unsigned long block){	if (IDE_CONTROL_REG)		OUT_BYTE(drive->ctl,IDE_CONTROL_REG);#ifdef CONFIG_BLK_DEV_PDC4030	if (drive->select.b.lba || IS_PDC4030_DRIVE) {#else /* !CONFIG_BLK_DEV_PDC4030 */	if (drive->select.b.lba) {#endif /* CONFIG_BLK_DEV_PDC4030 */		if ((drive->id->cfs_enable_2 & 0x0400) && (drive->addressing)) {			task_ioreg_t tasklets[10];			tasklets[0] = 0;			tasklets[1] = 0;			tasklets[2] = rq->nr_sectors;			tasklets[3] = (rq->nr_sectors>>8);			if (rq->nr_sectors == 65536) {				tasklets[2] = 0x00;				tasklets[3] = 0x00;			}			tasklets[4] = (task_ioreg_t) block;			tasklets[5] = (task_ioreg_t) (block>>8);			tasklets[6] = (task_ioreg_t) (block>>16);			tasklets[7] = (task_ioreg_t) (block>>24);			tasklets[8] = (task_ioreg_t) 0;			tasklets[9] = (task_ioreg_t) 0;//			tasklets[8] = (task_ioreg_t) (block>>32);//			tasklets[9] = (task_ioreg_t) (block>>40);#ifdef DEBUG			printk("%s: %sing: LBAsect=%lu, sectors=%ld, buffer=0x%08lx, LBAsect=0x%012lx\n",				drive->name,				(rq->cmd==READ)?"read":"writ",				block,				rq->nr_sectors,				(unsigned long) rq->buffer,				block);			printk("%s: 0x%02x%02x 0x%02x%02x%02x%02x%02x%02x\n",				drive->name, tasklets[3], tasklets[2],				tasklets[9], tasklets[8], tasklets[7],				tasklets[6], tasklets[5], tasklets[4]);#endif			OUT_BYTE(tasklets[1], IDE_FEATURE_REG);			OUT_BYTE(tasklets[3], IDE_NSECTOR_REG);			OUT_BYTE(tasklets[7], IDE_SECTOR_REG);			OUT_BYTE(tasklets[8], IDE_LCYL_REG);			OUT_BYTE(tasklets[9], IDE_HCYL_REG);			OUT_BYTE(tasklets[0], IDE_FEATURE_REG);			OUT_BYTE(tasklets[2], IDE_NSECTOR_REG);			OUT_BYTE(tasklets[4], IDE_SECTOR_REG);			OUT_BYTE(tasklets[5], IDE_LCYL_REG);			OUT_BYTE(tasklets[6], IDE_HCYL_REG);			OUT_BYTE(0x00|drive->select.all,IDE_SELECT_REG);		} else {#ifdef DEBUG			printk("%s: %sing: LBAsect=%ld, sectors=%ld, buffer=0x%08lx\n",				drive->name, (rq->cmd==READ)?"read":"writ",				block, rq->nr_sectors, (unsigned long) rq->buffer);#endif			OUT_BYTE(0x00, IDE_FEATURE_REG);			OUT_BYTE((rq->nr_sectors==256)?0x00:rq->nr_sectors,IDE_NSECTOR_REG);			OUT_BYTE(block,IDE_SECTOR_REG);			OUT_BYTE(block>>=8,IDE_LCYL_REG);			OUT_BYTE(block>>=8,IDE_HCYL_REG);			OUT_BYTE(((block>>8)&0x0f)|drive->select.all,IDE_SELECT_REG);		}	} else {		unsigned int sect,head,cyl,track;		track = block / drive->sect;		sect  = block % drive->sect + 1;		OUT_BYTE(sect,IDE_SECTOR_REG);		head  = track % drive->head;		cyl   = track / drive->head;		OUT_BYTE(0x00, IDE_FEATURE_REG);		OUT_BYTE((rq->nr_sectors==256)?0x00:rq->nr_sectors,IDE_NSECTOR_REG);		OUT_BYTE(cyl,IDE_LCYL_REG);		OUT_BYTE(cyl>>8,IDE_HCYL_REG);		OUT_BYTE(head|drive->select.all,IDE_SELECT_REG);#ifdef DEBUG		printk("%s: %sing: CHS=%d/%d/%d, sectors=%ld, buffer=0x%08lx\n",			drive->name, (rq->cmd==READ)?"read":"writ", cyl,			head, sect, rq->nr_sectors, (unsigned long) rq->buffer);#endif	}#ifdef CONFIG_BLK_DEV_PDC4030	if (IS_PDC4030_DRIVE) {		extern ide_startstop_t do_pdc4030_io(ide_drive_t *, struct request *);		return do_pdc4030_io (drive, rq);	}#endif /* CONFIG_BLK_DEV_PDC4030 */	if (rq->cmd == READ) {#ifdef CONFIG_BLK_DEV_IDEDMA		if (drive->using_dma && !(HWIF(drive)->dmaproc(ide_dma_read, drive)))			return ide_started;#endif /* CONFIG_BLK_DEV_IDEDMA */		ide_set_handler(drive, &read_intr, WAIT_CMD, NULL);		if ((drive->id->cfs_enable_2 & 0x0400) && (drive->addressing)) {			OUT_BYTE(drive->mult_count ? WIN_MULTREAD_EXT : WIN_READ_EXT, IDE_COMMAND_REG);		} else {			OUT_BYTE(drive->mult_count ? WIN_MULTREAD : WIN_READ, IDE_COMMAND_REG);		}		return ide_started;	}	if (rq->cmd == WRITE) {		ide_startstop_t startstop;#ifdef CONFIG_BLK_DEV_IDEDMA		if (drive->using_dma && !(HWIF(drive)->dmaproc(ide_dma_write, drive)))			return ide_started;#endif /* CONFIG_BLK_DEV_IDEDMA */		if ((drive->id->cfs_enable_2 & 0x0400) && (drive->addressing)) {			OUT_BYTE(drive->mult_count ? WIN_MULTWRITE_EXT : WIN_WRITE_EXT, IDE_COMMAND_REG);		} else {			OUT_BYTE(drive->mult_count ? WIN_MULTWRITE : WIN_WRITE, IDE_COMMAND_REG);		}		if (ide_wait_stat(&startstop, drive, DATA_READY, drive->bad_wstat, WAIT_DRQ)) {			printk(KERN_ERR "%s: no DRQ after issuing %s\n", drive->name,				drive->mult_count ? "MULTWRITE" : "WRITE");			return startstop;		}		if (!drive->unmask)			__cli();	/* local CPU only */		if (drive->mult_count) {			ide_hwgroup_t *hwgroup = HWGROUP(drive);	/*	 * Ugh.. this part looks ugly because we MUST set up	 * the interrupt handler before outputting the first block	 * of data to be written.  If we hit an error (corrupted buffer list)	 * in ide_multwrite(), then we need to remove the handler/timer	 * before returning.  Fortunately, this NEVER happens (right?).	 *	 * Except when you get an error it seems...	 */			hwgroup->wrq = *rq; /* scratchpad */			ide_set_handler(drive, &multwrite_intr, WAIT_CMD, NULL);			if (ide_multwrite(drive, drive->mult_count)) {				unsigned long flags;				spin_lock_irqsave(&io_request_lock, flags);				hwgroup->handler = NULL;				del_timer(&hwgroup->timer);				spin_unlock_irqrestore(&io_request_lock, flags);				return ide_stopped;			}		} else {			ide_set_handler (drive, &write_intr, WAIT_CMD, NULL);			idedisk_output_data(drive, rq->buffer, SECTOR_WORDS);		}		return ide_started;	}	printk(KERN_ERR "%s: bad command: %d\n", drive->name, rq->cmd);	ide_end_request(0, HWGROUP(drive));	return ide_stopped;}#endif /* __TASKFILE__IO */static int idedisk_open (struct inode *inode, struct file *filp, ide_drive_t *drive){	MOD_INC_USE_COUNT;	if (drive->removable && drive->usage == 1) {		struct hd_drive_task_hdr taskfile;		struct hd_drive_hob_hdr hobfile;		memset(&taskfile, 0, sizeof(struct hd_drive_task_hdr));		memset(&hobfile, 0, sizeof(struct hd_drive_hob_hdr));		taskfile.command = WIN_DOORLOCK;		check_disk_change(inode->i_rdev);		/*		 * Ignore the return code from door_lock,		 * since the open() has already succeeded,		 * and the door_lock is irrelevant at this point.		 */		if (drive->doorlocking && ide_wait_taskfile(drive, &taskfile, &hobfile, NULL))			drive->doorlocking = 0;	}	return 0;}static int do_idedisk_flushcache(ide_drive_t *drive);static void idedisk_release (struct inode *inode, struct file *filp, ide_drive_t *drive){	if (drive->removable && !drive->usage) {		struct hd_drive_task_hdr taskfile;		struct hd_drive_hob_hdr hobfile;		memset(&taskfile, 0, sizeof(struct hd_drive_task_hdr));		memset(&hobfile, 0, sizeof(struct hd_drive_hob_hdr));		taskfile.command = WIN_DOORUNLOCK;		invalidate_bdev(inode->i_bdev, 0);		if (drive->doorlocking && ide_wait_taskfile(drive, &taskfile, &hobfile, NULL))			drive->doorlocking = 0;	}	if ((drive->id->cfs_enable_2 & 0x3000) && drive->wcache)		if (do_idedisk_flushcache(drive))			printk (KERN_INFO "%s: Write Cache FAILED Flushing!\n",				drive->name);	MOD_DEC_USE_COUNT;}static int idedisk_media_change (ide_drive_t *drive){	return drive->removable;	/* if removable, always assume it was changed */}static void idedisk_revalidate (ide_drive_t *drive){	grok_partitions(HWIF(drive)->gd, drive->select.b.unit,			1<<PARTN_BITS,			current_capacity(drive));}/* * Queries for true maximum capacity of the drive. * Returns maximum LBA address (> 0) of the drive, 0 if failed. */static unsigned long idedisk_read_native_max_address(ide_drive_t *drive){	ide_task_t args;	unsigned long addr = 0;	if (!(drive->id->command_set_1 & 0x0400) &&	    !(drive->id->cfs_enable_2 & 0x0100))

⌨️ 快捷键说明

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