ide-iops.c

来自「Linux Kernel 2.6.9 for OMAP1710」· C语言 代码 · 共 1,291 行 · 第 1/3 页

C
1,291
字号
	hwif->OUTB(WIN_SETFEATURES, IDE_COMMAND_REG);	if ((IDE_CONTROL_REG) && (drive->quirk_list == 2))		hwif->OUTB(drive->ctl, IDE_CONTROL_REG);	udelay(1);	/*	 * Wait for drive to become non-BUSY	 */	if ((stat = hwif->INB(IDE_STATUS_REG)) & BUSY_STAT) {		unsigned long flags, timeout;		local_irq_set(flags);		timeout = jiffies + WAIT_CMD;		while ((stat = hwif->INB(IDE_STATUS_REG)) & BUSY_STAT) {			if (time_after(jiffies, timeout))				break;		}		local_irq_restore(flags);	}	/*	 * Allow status to settle, then read it again.	 * A few rare drives vastly violate the 400ns spec here,	 * so we'll wait up to 10usec for a "good" status	 * rather than expensively fail things immediately.	 * This fix courtesy of Matthew Faupel & Niccolo Rigacci.	 */	for (i = 0; i < 10; i++) {		udelay(1);		if (OK_STAT((stat = hwif->INB(IDE_STATUS_REG)), DRIVE_READY, BUSY_STAT|DRQ_STAT|ERR_STAT)) {			error = 0;			break;		}	}	SELECT_MASK(drive, 0);	enable_irq(hwif->irq);	if (error) {		(void) ide_dump_status(drive, "set_drive_speed_status", stat);		return error;	}	drive->id->dma_ultra &= ~0xFF00;	drive->id->dma_mword &= ~0x0F00;	drive->id->dma_1word &= ~0x0F00;#ifdef CONFIG_BLK_DEV_IDEDMA	if (speed >= XFER_SW_DMA_0)		hwif->ide_dma_host_on(drive);	else if (hwif->ide_dma_check)	/* check if host supports DMA */		hwif->ide_dma_off_quietly(drive);#endif	switch(speed) {		case XFER_UDMA_7:   drive->id->dma_ultra |= 0x8080; break;		case XFER_UDMA_6:   drive->id->dma_ultra |= 0x4040; break;		case XFER_UDMA_5:   drive->id->dma_ultra |= 0x2020; break;		case XFER_UDMA_4:   drive->id->dma_ultra |= 0x1010; break;		case XFER_UDMA_3:   drive->id->dma_ultra |= 0x0808; break;		case XFER_UDMA_2:   drive->id->dma_ultra |= 0x0404; break;		case XFER_UDMA_1:   drive->id->dma_ultra |= 0x0202; break;		case XFER_UDMA_0:   drive->id->dma_ultra |= 0x0101; break;		case XFER_MW_DMA_2: drive->id->dma_mword |= 0x0404; break;		case XFER_MW_DMA_1: drive->id->dma_mword |= 0x0202; break;		case XFER_MW_DMA_0: drive->id->dma_mword |= 0x0101; break;		case XFER_SW_DMA_2: drive->id->dma_1word |= 0x0404; break;		case XFER_SW_DMA_1: drive->id->dma_1word |= 0x0202; break;		case XFER_SW_DMA_0: drive->id->dma_1word |= 0x0101; break;		default: break;	}	if (!drive->init_speed)		drive->init_speed = speed;	drive->current_speed = speed;	return error;}EXPORT_SYMBOL(ide_config_drive_speed);/* * This should get invoked any time we exit the driver to * wait for an interrupt response from a drive.  handler() points * at the appropriate code to handle the next interrupt, and a * timer is started to prevent us from waiting forever in case * something goes wrong (see the ide_timer_expiry() handler later on). * * See also ide_execute_command */void __ide_set_handler (ide_drive_t *drive, ide_handler_t *handler,		      unsigned int timeout, ide_expiry_t *expiry){	ide_hwgroup_t *hwgroup = HWGROUP(drive);	if (hwgroup->handler != NULL) {		printk(KERN_CRIT "%s: ide_set_handler: handler not null; "			"old=%p, new=%p\n",			drive->name, hwgroup->handler, handler);	}	hwgroup->handler	= handler;	hwgroup->expiry		= expiry;	hwgroup->timer.expires	= jiffies + timeout;	add_timer(&hwgroup->timer);}EXPORT_SYMBOL(__ide_set_handler);void ide_set_handler (ide_drive_t *drive, ide_handler_t *handler,		      unsigned int timeout, ide_expiry_t *expiry){	unsigned long flags;	spin_lock_irqsave(&ide_lock, flags);	__ide_set_handler(drive, handler, timeout, expiry);	spin_unlock_irqrestore(&ide_lock, flags);}EXPORT_SYMBOL(ide_set_handler); /** *	ide_execute_command	-	execute an IDE command *	@drive: IDE drive to issue the command against *	@command: command byte to write *	@handler: handler for next phase *	@timeout: timeout for command *	@expiry:  handler to run on timeout * *	Helper function to issue an IDE command. This handles the *	atomicity requirements, command timing and ensures that the  *	handler and IRQ setup do not race. All IDE command kick off *	should go via this function or do equivalent locking. */ void ide_execute_command(ide_drive_t *drive, task_ioreg_t cmd, ide_handler_t *handler, unsigned timeout, ide_expiry_t *expiry){	unsigned long flags;	ide_hwgroup_t *hwgroup = HWGROUP(drive);	ide_hwif_t *hwif = HWIF(drive);		spin_lock_irqsave(&ide_lock, flags);		if(hwgroup->handler)		BUG();	hwgroup->handler	= handler;	hwgroup->expiry		= expiry;	hwgroup->timer.expires	= jiffies + timeout;	add_timer(&hwgroup->timer);	hwif->OUTBSYNC(drive, cmd, IDE_COMMAND_REG);	/* Drive takes 400nS to respond, we must avoid the IRQ being	   serviced before that. 	   	   FIXME: we could skip this delay with care on non shared	   devices 	*/	ndelay(400);	spin_unlock_irqrestore(&ide_lock, flags);}EXPORT_SYMBOL(ide_execute_command);/* needed below */static ide_startstop_t do_reset1 (ide_drive_t *, int);/* * atapi_reset_pollfunc() gets invoked to poll the interface for completion every 50ms * during an atapi drive reset operation. If the drive has not yet responded, * and we have not yet hit our maximum waiting time, then the timer is restarted * for another 50ms. */static ide_startstop_t atapi_reset_pollfunc (ide_drive_t *drive){	ide_hwgroup_t *hwgroup	= HWGROUP(drive);	ide_hwif_t *hwif	= HWIF(drive);	u8 stat;	SELECT_DRIVE(drive);	udelay (10);	if (OK_STAT(stat = hwif->INB(IDE_STATUS_REG), 0, BUSY_STAT)) {		printk("%s: ATAPI reset complete\n", drive->name);	} else {		if (time_before(jiffies, hwgroup->poll_timeout)) {			if (HWGROUP(drive)->handler != NULL)				BUG();			ide_set_handler(drive, &atapi_reset_pollfunc, HZ/20, NULL);			/* continue polling */			return ide_started;		}		/* end of polling */		hwgroup->poll_timeout = 0;		printk("%s: ATAPI reset timed-out, status=0x%02x\n",				drive->name, stat);		/* do it the old fashioned way */		return do_reset1(drive, 1);	}	/* done polling */	hwgroup->poll_timeout = 0;	return ide_stopped;}/* * reset_pollfunc() gets invoked to poll the interface for completion every 50ms * during an ide reset operation. If the drives have not yet responded, * and we have not yet hit our maximum waiting time, then the timer is restarted * for another 50ms. */static ide_startstop_t reset_pollfunc (ide_drive_t *drive){	ide_hwgroup_t *hwgroup	= HWGROUP(drive);	ide_hwif_t *hwif	= HWIF(drive);	u8 tmp;	if (hwif->reset_poll != NULL) {		if (hwif->reset_poll(drive)) {			printk(KERN_ERR "%s: host reset_poll failure for %s.\n",				hwif->name, drive->name);			return ide_stopped;		}	}	if (!OK_STAT(tmp = hwif->INB(IDE_STATUS_REG), 0, BUSY_STAT)) {		if (time_before(jiffies, hwgroup->poll_timeout)) {			if (HWGROUP(drive)->handler != NULL)				BUG();			ide_set_handler(drive, &reset_pollfunc, HZ/20, NULL);			/* continue polling */			return ide_started;		}		printk("%s: reset timed-out, status=0x%02x\n", hwif->name, tmp);		drive->failures++;	} else  {		printk("%s: reset: ", hwif->name);		if ((tmp = hwif->INB(IDE_ERROR_REG)) == 1) {			printk("success\n");			drive->failures = 0;		} else {			drive->failures++;			printk("master: ");			switch (tmp & 0x7f) {				case 1: printk("passed");					break;				case 2: printk("formatter device error");					break;				case 3: printk("sector buffer error");					break;				case 4: printk("ECC circuitry error");					break;				case 5: printk("controlling MPU error");					break;				default:printk("error (0x%02x?)", tmp);			}			if (tmp & 0x80)				printk("; slave: failed");			printk("\n");		}	}	hwgroup->poll_timeout = 0;	/* done polling */	return ide_stopped;}static void check_dma_crc(ide_drive_t *drive){#ifdef CONFIG_BLK_DEV_IDEDMA	if (drive->crc_count) {		(void) HWIF(drive)->ide_dma_off_quietly(drive);		ide_set_xfer_rate(drive, ide_auto_reduce_xfer(drive));		if (drive->current_speed >= XFER_SW_DMA_0)			(void) HWIF(drive)->ide_dma_on(drive);	} else		(void)__ide_dma_off(drive);#endif}void pre_reset (ide_drive_t *drive){	DRIVER(drive)->pre_reset(drive);	if (!drive->keep_settings) {		if (drive->using_dma) {			check_dma_crc(drive);		} else {			drive->unmask = 0;			drive->io_32bit = 0;		}		return;	}	if (drive->using_dma)		check_dma_crc(drive);	if (HWIF(drive)->pre_reset != NULL)		HWIF(drive)->pre_reset(drive);}/* * do_reset1() attempts to recover a confused drive by resetting it. * Unfortunately, resetting a disk drive actually resets all devices on * the same interface, so it can really be thought of as resetting the * interface rather than resetting the drive. * * ATAPI devices have their own reset mechanism which allows them to be * individually reset without clobbering other devices on the same interface. * * Unfortunately, the IDE interface does not generate an interrupt to let * us know when the reset operation has finished, so we must poll for this. * Equally poor, though, is the fact that this may a very long time to complete, * (up to 30 seconds worstcase).  So, instead of busy-waiting here for it, * we set a timer to poll at 50ms intervals. */static ide_startstop_t do_reset1 (ide_drive_t *drive, int do_not_try_atapi){	unsigned int unit;	unsigned long flags;	ide_hwif_t *hwif;	ide_hwgroup_t *hwgroup;		spin_lock_irqsave(&ide_lock, flags);	hwif = HWIF(drive);	hwgroup = HWGROUP(drive);	/* We must not reset with running handlers */	if(hwgroup->handler != NULL)		BUG();	/* For an ATAPI device, first try an ATAPI SRST. */	if (drive->media != ide_disk && !do_not_try_atapi) {		pre_reset(drive);		SELECT_DRIVE(drive);		udelay (20);		hwif->OUTB(WIN_SRST, IDE_COMMAND_REG);		hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE;		__ide_set_handler(drive, &atapi_reset_pollfunc, HZ/20, NULL);		spin_unlock_irqrestore(&ide_lock, flags);		return ide_started;	}	/*	 * First, reset any device state data we were maintaining	 * for any of the drives on this interface.	 */	for (unit = 0; unit < MAX_DRIVES; ++unit)		pre_reset(&hwif->drives[unit]);#if OK_TO_RESET_CONTROLLER	if (!IDE_CONTROL_REG) {		spin_unlock_irqrestore(&ide_lock, flags);		return ide_stopped;	}	/*	 * Note that we also set nIEN while resetting the device,	 * to mask unwanted interrupts from the interface during the reset.	 * However, due to the design of PC hardware, this will cause an	 * immediate interrupt due to the edge transition it produces.	 * This single interrupt gives us a "fast poll" for drives that	 * recover from reset very quickly, saving us the first 50ms wait time.	 */	/* set SRST and nIEN */	hwif->OUTBSYNC(drive, drive->ctl|6,IDE_CONTROL_REG);	/* more than enough time */	udelay(10);	if (drive->quirk_list == 2) {		/* clear SRST and nIEN */		hwif->OUTBSYNC(drive, drive->ctl, IDE_CONTROL_REG);	} else {		/* clear SRST, leave nIEN */		hwif->OUTBSYNC(drive, drive->ctl|2, IDE_CONTROL_REG);	}	/* more than enough time */	udelay(10);	hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE;	__ide_set_handler(drive, &reset_pollfunc, HZ/20, NULL);	/*	 * Some weird controller like resetting themselves to a strange	 * state when the disks are reset this way. At least, the Winbond	 * 553 documentation says that	 */	if (hwif->resetproc != NULL) {		hwif->resetproc(drive);	}	#endif	/* OK_TO_RESET_CONTROLLER */	spin_unlock_irqrestore(&ide_lock, flags);	return ide_started;}/* * ide_do_reset() is the entry point to the drive/interface reset code. */ide_startstop_t ide_do_reset (ide_drive_t *drive){	return do_reset1(drive, 0);}EXPORT_SYMBOL(ide_do_reset);/* * ide_wait_not_busy() waits for the currently selected device on the hwif * to report a non-busy status, see comments in probe_hwif(). */int ide_wait_not_busy(ide_hwif_t *hwif, unsigned long timeout){	u8 stat = 0;	while(timeout--) {		/*		 * Turn this into a schedule() sleep once I'm sure		 * about locking issues (2.5 work ?).		 */		mdelay(1);		stat = hwif->INB(hwif->io_ports[IDE_STATUS_OFFSET]);		if ((stat & BUSY_STAT) == 0)			return 0;		/*		 * Assume a value of 0xff means nothing is connected to		 * the interface and it doesn't implement the pull-down		 * resistor on D7.		 */		if (stat == 0xff)			return -ENODEV;	}	return -EBUSY;}EXPORT_SYMBOL_GPL(ide_wait_not_busy);

⌨️ 快捷键说明

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