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

📄 ide-disk.c

📁 Linux Kernel 2.6.9 for OMAP1710
💻 C
📖 第 1 页 / 共 4 页
字号:
#else /* CONFIG_IDE_TASKFILE_IO */static ide_startstop_t chs_rw_disk(ide_drive_t *, struct request *, unsigned long);static ide_startstop_t lba_28_rw_disk(ide_drive_t *, struct request *, unsigned long);static ide_startstop_t lba_48_rw_disk(ide_drive_t *, struct request *, unsigned long long);/* * __ide_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. */ide_startstop_t __ide_do_rw_disk (ide_drive_t *drive, struct request *rq, sector_t block){	/*	 * 268435455  == 137439 MB or 28bit limit	 *	 * need to add split taskfile operations based on 28bit threshold.	 */	if (drive->addressing == 1)		/* 48-bit LBA */		return lba_48_rw_disk(drive, rq, (unsigned long long) block);	if (drive->select.b.lba)		/* 28-bit LBA */		return lba_28_rw_disk(drive, rq, (unsigned long) block);	/* 28-bit CHS : DIE DIE DIE piece of legacy crap!!! */	return chs_rw_disk(drive, rq, (unsigned long) block);}EXPORT_SYMBOL_GPL(__ide_do_rw_disk);static u8 get_command(ide_drive_t *drive, struct request *rq, ide_task_t *task){	unsigned int lba48 = (drive->addressing == 1) ? 1 : 0;	unsigned int dma = drive->using_dma;	if (drive->hwif->no_lba48_dma && lba48 && dma) {		if (rq->sector + rq->nr_sectors > 1ULL << 28)			dma = 0;	}	if (rq_data_dir(rq) == READ) {		task->command_type = IDE_DRIVE_TASK_IN;		if (dma)			return lba48 ? WIN_READDMA_EXT : WIN_READDMA;		task->handler = &task_in_intr;		if (drive->mult_count) {			task->data_phase = TASKFILE_MULTI_IN;			return lba48 ? WIN_MULTREAD_EXT : WIN_MULTREAD;		}		task->data_phase = TASKFILE_IN;		return lba48 ? WIN_READ_EXT : WIN_READ;	} else {		task->command_type = IDE_DRIVE_TASK_RAW_WRITE;		if (dma)			return lba48 ? WIN_WRITEDMA_EXT : WIN_WRITEDMA;		task->prehandler = &pre_task_out_intr;		task->handler = &task_out_intr;		if (drive->mult_count) {			task->data_phase = TASKFILE_MULTI_OUT;			return lba48 ? WIN_MULTWRITE_EXT : WIN_MULTWRITE;		}		task->data_phase = TASKFILE_OUT;		return lba48 ? WIN_WRITE_EXT : WIN_WRITE;	}}static ide_startstop_t chs_rw_disk (ide_drive_t *drive, struct request *rq, unsigned long block){	ide_task_t		args;	int			sectors;	ata_nsector_t		nsectors;	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);	nsectors.all = (u16) rq->nr_sectors;	pr_debug("%s: CHS=%u/%u/%u\n", drive->name, cyl, head, sect);	memset(&args, 0, sizeof(ide_task_t));	sectors	= (rq->nr_sectors == 256) ? 0x00 : rq->nr_sectors;	args.tfRegister[IDE_NSECTOR_OFFSET]	= sectors;	args.tfRegister[IDE_SECTOR_OFFSET]	= sect;	args.tfRegister[IDE_LCYL_OFFSET]	= cyl;	args.tfRegister[IDE_HCYL_OFFSET]	= (cyl>>8);	args.tfRegister[IDE_SELECT_OFFSET]	= head;	args.tfRegister[IDE_SELECT_OFFSET]	|= drive->select.all;	args.tfRegister[IDE_COMMAND_OFFSET]	= get_command(drive, rq, &args);	args.rq					= (struct request *) rq;	rq->special				= (ide_task_t *)&args;	drive->hwif->data_phase = args.data_phase;	return do_rw_taskfile(drive, &args);}static ide_startstop_t lba_28_rw_disk (ide_drive_t *drive, struct request *rq, unsigned long block){	ide_task_t		args;	int			sectors;	ata_nsector_t		nsectors;	nsectors.all = (u16) rq->nr_sectors;	memset(&args, 0, sizeof(ide_task_t));	sectors = (rq->nr_sectors == 256) ? 0x00 : rq->nr_sectors;	args.tfRegister[IDE_NSECTOR_OFFSET]	= sectors;	args.tfRegister[IDE_SECTOR_OFFSET]	= block;	args.tfRegister[IDE_LCYL_OFFSET]	= (block>>=8);	args.tfRegister[IDE_HCYL_OFFSET]	= (block>>=8);	args.tfRegister[IDE_SELECT_OFFSET]	= ((block>>8)&0x0f);	args.tfRegister[IDE_SELECT_OFFSET]	|= drive->select.all;	args.tfRegister[IDE_COMMAND_OFFSET]	= get_command(drive, rq, &args);	args.rq					= (struct request *) rq;	rq->special				= (ide_task_t *)&args;	drive->hwif->data_phase = args.data_phase;	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){	ide_task_t		args;	int			sectors;	ata_nsector_t		nsectors;	nsectors.all = (u16) rq->nr_sectors;	memset(&args, 0, sizeof(ide_task_t));	sectors = (rq->nr_sectors == 65536) ? 0 : rq->nr_sectors;	args.tfRegister[IDE_NSECTOR_OFFSET]	= sectors;	args.hobRegister[IDE_NSECTOR_OFFSET]	= sectors >> 8;	args.tfRegister[IDE_SECTOR_OFFSET]	= block;	/* low lba */	args.tfRegister[IDE_LCYL_OFFSET]	= (block>>=8);	/* mid lba */	args.tfRegister[IDE_HCYL_OFFSET]	= (block>>=8);	/* hi  lba */	args.tfRegister[IDE_SELECT_OFFSET]	= drive->select.all;	args.tfRegister[IDE_COMMAND_OFFSET]	= get_command(drive, rq, &args);	args.hobRegister[IDE_SECTOR_OFFSET]	= (block>>=8);	/* low lba */	args.hobRegister[IDE_LCYL_OFFSET]	= (block>>=8);	/* mid lba */	args.hobRegister[IDE_HCYL_OFFSET]	= (block>>=8);	/* hi  lba */	args.hobRegister[IDE_SELECT_OFFSET]	= drive->select.all;	args.hobRegister[IDE_CONTROL_OFFSET_HOB]= (drive->ctl|0x80);	args.rq					= (struct request *) rq;	rq->special				= (ide_task_t *)&args;	drive->hwif->data_phase = args.data_phase;	return do_rw_taskfile(drive, &args);}#endif /* CONFIG_IDE_TASKFILE_IO */static ide_startstop_t ide_do_rw_disk (ide_drive_t *drive, struct request *rq, sector_t block){	ide_hwif_t *hwif = HWIF(drive);	BUG_ON(drive->blocked);	if (!blk_fs_request(rq)) {		blk_dump_rq_flags(rq, "ide_do_rw_disk - bad command");		ide_end_request(drive, 0, 0);		return ide_stopped;	}	pr_debug("%s: %sing: block=%llu, sectors=%lu, buffer=0x%08lx\n",		 drive->name, rq_data_dir(rq) == READ ? "read" : "writ",		 block, rq->nr_sectors, (unsigned long)rq->buffer);	if (hwif->rw_disk)		return hwif->rw_disk(drive, rq, block);	else		return __ide_do_rw_disk(drive, rq, block);}static u8 idedisk_dump_status (ide_drive_t *drive, const char *msg, u8 stat){	ide_hwif_t *hwif = HWIF(drive);	unsigned long flags;	u8 err = 0;	local_irq_set(flags);	printk("%s: %s: status=0x%02x", drive->name, msg, stat);	printk(" { ");	if (stat & BUSY_STAT)		printk("Busy ");	else {		if (stat & READY_STAT)	printk("DriveReady ");		if (stat & WRERR_STAT)	printk("DeviceFault ");		if (stat & SEEK_STAT)	printk("SeekComplete ");		if (stat & DRQ_STAT)	printk("DataRequest ");		if (stat & ECC_STAT)	printk("CorrectedError ");		if (stat & INDEX_STAT)	printk("Index ");		if (stat & ERR_STAT)	printk("Error ");	}	printk("}");	printk("\n");	if ((stat & (BUSY_STAT|ERR_STAT)) == ERR_STAT) {		err = hwif->INB(IDE_ERROR_REG);		printk("%s: %s: error=0x%02x", drive->name, msg, err);		printk(" { ");		if (err & ABRT_ERR)	printk("DriveStatusError ");		if (err & ICRC_ERR)			printk("Bad%s ", (err & ABRT_ERR) ? "CRC" : "Sector");		if (err & ECC_ERR)	printk("UncorrectableError ");		if (err & ID_ERR)	printk("SectorIdNotFound ");		if (err & TRK0_ERR)	printk("TrackZeroNotFound ");		if (err & MARK_ERR)	printk("AddrMarkNotFound ");		printk("}");		if ((err & (BBD_ERR | ABRT_ERR)) == BBD_ERR ||		    (err & (ECC_ERR|ID_ERR|MARK_ERR))) {			if (drive->addressing == 1) {				__u64 sectors = 0;				u32 low = 0, high = 0;				low = ide_read_24(drive);				hwif->OUTB(drive->ctl|0x80, IDE_CONTROL_REG);				high = ide_read_24(drive);				sectors = ((__u64)high << 24) | low;				printk(", LBAsect=%llu, high=%d, low=%d",				       (unsigned long long) sectors,				       high, low);			} else {				u8 cur = hwif->INB(IDE_SELECT_REG);				if (cur & 0x40) {	/* using LBA? */					printk(", LBAsect=%ld", (unsigned long)					 ((cur&0xf)<<24)					 |(hwif->INB(IDE_HCYL_REG)<<16)					 |(hwif->INB(IDE_LCYL_REG)<<8)					 | hwif->INB(IDE_SECTOR_REG));				} else {					printk(", CHS=%d/%d/%d",					 (hwif->INB(IDE_HCYL_REG)<<8) +					  hwif->INB(IDE_LCYL_REG),					  cur & 0xf,					  hwif->INB(IDE_SECTOR_REG));				}			}			if (HWGROUP(drive) && HWGROUP(drive)->rq)				printk(", sector=%llu",					(unsigned long long)HWGROUP(drive)->rq->sector);		}	}	printk("\n");	{		struct request *rq;		unsigned char opcode = 0;		int found = 0;		spin_lock(&ide_lock);		rq = HWGROUP(drive)->rq;		spin_unlock(&ide_lock);		if (!rq)			goto out;		if (rq->flags & (REQ_DRIVE_CMD | REQ_DRIVE_TASK)) {			char *args = rq->buffer;			if (args) {				opcode = args[0];				found = 1;			}		} else if (rq->flags & REQ_DRIVE_TASKFILE) {			ide_task_t *args = rq->special;			if (args) {				task_struct_t *tf = (task_struct_t *) args->tfRegister;				opcode = tf->command;				found = 1;			}		}		printk("ide: failed opcode was: ");		if (!found)			printk("unknown\n");		else			printk("0x%02x\n", opcode);	}out:	local_irq_restore(flags);	return err;}ide_startstop_t idedisk_error (ide_drive_t *drive, const char *msg, u8 stat){	ide_hwif_t *hwif;	struct request *rq;	u8 err;	err = idedisk_dump_status(drive, msg, stat);	if (drive == NULL || (rq = HWGROUP(drive)->rq) == NULL)		return ide_stopped;	hwif = HWIF(drive);	/* retry only "normal" I/O: */	if (rq->flags & (REQ_DRIVE_CMD | REQ_DRIVE_TASK | REQ_DRIVE_TASKFILE)) {		rq->errors = 1;		ide_end_drive_cmd(drive, stat, err);		return ide_stopped;	}#ifdef CONFIG_IDE_TASKFILE_IO	/* make rq completion pointers new submission pointers */	blk_rq_prep_restart(rq);#endif	if (stat & BUSY_STAT || ((stat & WRERR_STAT) && !drive->nowerr)) {		/* other bits are useless when BUSY */		rq->errors |= ERROR_RESET;	} else if (stat & ERR_STAT) {		/* err has different meaning on cdrom and tape */		if (err == ABRT_ERR) {			if (drive->select.b.lba &&			    /* some newer drives don't support WIN_SPECIFY */			    hwif->INB(IDE_COMMAND_REG) == WIN_SPECIFY)				return ide_stopped;		} else if ((err & BAD_CRC) == BAD_CRC) {			/* UDMA crc error, just retry the operation */			drive->crc_count++;		} else if (err & (BBD_ERR | ECC_ERR)) {			/* retries won't help these */			rq->errors = ERROR_MAX;		} else if (err & TRK0_ERR) {			/* help it find track zero */			rq->errors |= ERROR_RECAL;		}	}	if ((stat & DRQ_STAT) && rq_data_dir(rq) == READ)		try_to_flush_leftover_data(drive);	if (hwif->INB(IDE_STATUS_REG) & (BUSY_STAT|DRQ_STAT)) {		/* force an abort */		hwif->OUTB(WIN_IDLEIMMEDIATE,IDE_COMMAND_REG);	}	if (rq->errors >= ERROR_MAX || blk_noretry_request(rq))		DRIVER(drive)->end_request(drive, 0, 0);	else {		if ((rq->errors & ERROR_RESET) == ERROR_RESET) {			++rq->errors;			return ide_do_reset(drive);		}		if ((rq->errors & ERROR_RECAL) == ERROR_RECAL)			drive->special.b.recalibrate = 1;		++rq->errors;	}	return ide_stopped;}ide_startstop_t idedisk_abort(ide_drive_t *drive, const char *msg){	ide_hwif_t *hwif;	struct request *rq;	if (drive == NULL || (rq = HWGROUP(drive)->rq) == NULL)		return ide_stopped;	hwif = HWIF(drive);	if (rq->flags & (REQ_DRIVE_CMD | REQ_DRIVE_TASK | REQ_DRIVE_TASKFILE)) {		rq->errors = 1;		ide_end_drive_cmd(drive, BUSY_STAT, 0);		return ide_stopped;	}	DRIVER(drive)->end_request(drive, 0, 0);	return ide_stopped;}/* * 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;	/* Create IDE/ATA command request structure */	memset(&args, 0, sizeof(ide_task_t));	args.tfRegister[IDE_SELECT_OFFSET]	= 0x40;	args.tfRegister[IDE_COMMAND_OFFSET]	= WIN_READ_NATIVE_MAX;	args.command_type			= IDE_DRIVE_TASK_NO_DATA;	args.handler				= &task_no_data_intr;	/* submit command request */	ide_raw_taskfile(drive, &args, NULL);	/* if OK, compute maximum address value */	if ((args.tfRegister[IDE_STATUS_OFFSET] & 0x01) == 0) {		addr = ((args.tfRegister[IDE_SELECT_OFFSET] & 0x0f) << 24)		     | ((args.tfRegister[  IDE_HCYL_OFFSET]       ) << 16)		     | ((args.tfRegister[  IDE_LCYL_OFFSET]       ) <<  8)		     | ((args.tfRegister[IDE_SECTOR_OFFSET]       ));		addr++;	/* since the return value is (maxlba - 1), we add 1 */	}	return addr;}static unsigned long long idedisk_read_native_max_address_ext(ide_drive_t *drive){	ide_task_t args;	unsigned long long addr = 0;	/* Create IDE/ATA command request structure */	memset(&args, 0, sizeof(ide_task_t));	args.tfRegister[IDE_SELECT_OFFSET]	= 0x40;	args.tfRegister[IDE_COMMAND_OFFSET]	= WIN_READ_NATIVE_MAX_EXT;	args.command_type			= IDE_DRIVE_TASK_NO_DATA;	args.handler				= &task_no_data_intr;        /* submit command request */        ide_raw_taskfile(drive, &args, NULL);	/* if OK, compute maximum address value */	if ((args.tfRegister[IDE_STATUS_OFFSET] & 0x01) == 0) {		u32 high = (args.hobRegister[IDE_HCYL_OFFSET] << 16) |			   (args.hobRegister[IDE_LCYL_OFFSET] <<  8) |			    args.hobRegister[IDE_SECTOR_OFFSET];		u32 low  = ((args.tfRegister[IDE_HCYL_OFFSET])<<16) |			   ((args.tfRegister[IDE_LCYL_OFFSET])<<8) |			    (args.tfRegister[IDE_SECTOR_OFFSET]);		addr = ((__u64)high << 24) | low;		addr++;	/* since the return value is (maxlba - 1), we add 1 */	}	return addr;}/* * Sets maximum virtual LBA address of the drive. * Returns new maximum virtual LBA address (> 0) or 0 on failure. */static unsigned long idedisk_set_max_address(ide_drive_t *drive, unsigned long addr_req){	ide_task_t args;	unsigned long addr_set = 0;		addr_req--;	/* Create IDE/ATA command request structure */	memset(&args, 0, sizeof(ide_task_t));	args.tfRegister[IDE_SECTOR_OFFSET]	= ((addr_req >>  0) & 0xff);	args.tfRegister[IDE_LCYL_OFFSET]	= ((addr_req >>  8) & 0xff);	args.tfRegister[IDE_HCYL_OFFSET]	= ((addr_req >> 16) & 0xff);	args.tfRegister[IDE_SELECT_OFFSET]	= ((addr_req >> 24) & 0x0f) | 0x40;	args.tfRegister[IDE_COMMAND_OFFSET]	= WIN_SET_MAX;	args.command_type			= IDE_DRIVE_TASK_NO_DATA;	args.handler				= &task_no_data_intr;	/* submit command request */	ide_raw_taskfile(drive, &args, NULL);	/* if OK, read new maximum address value */	if ((args.tfRegister[IDE_STATUS_OFFSET] & 0x01) == 0) {		addr_set = ((args.tfRegister[IDE_SELECT_OFFSET] & 0x0f) << 24)			 | ((args.tfRegister[  IDE_HCYL_OFFSET]       ) << 16)			 | ((args.tfRegister[  IDE_LCYL_OFFSET]       ) <<  8)			 | ((args.tfRegister[IDE_SECTOR_OFFSET]       ));		addr_set++;	}	return addr_set;}static unsigned long long idedisk_set_max_address_ext(ide_drive_t *drive, unsigned long long addr_req){	ide_task_t args;	unsigned long long addr_set = 0;	addr_req--;	/* Create IDE/ATA command request structure */	memset(&args, 0, sizeof(ide_task_t));	args.tfRegister[IDE_SECTOR_OFFSET]	= ((addr_req >>  0) & 0xff);

⌨️ 快捷键说明

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