ide-iops.c

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

C
1,291
字号
	id->csfo           = __le16_to_cpu(id->csfo);	for (i = 0; i < 26; i++)		id->words130_155[i] = __le16_to_cpu(id->words130_155[i]);	id->word156        = __le16_to_cpu(id->word156);	for (i = 0; i < 3; i++)		id->words157_159[i] = __le16_to_cpu(id->words157_159[i]);	id->cfa_power      = __le16_to_cpu(id->cfa_power);	for (i = 0; i < 14; i++)		id->words161_175[i] = __le16_to_cpu(id->words161_175[i]);	for (i = 0; i < 31; i++)		id->words176_205[i] = __le16_to_cpu(id->words176_205[i]);	for (i = 0; i < 48; i++)		id->words206_254[i] = __le16_to_cpu(id->words206_254[i]);	id->integrity_word  = __le16_to_cpu(id->integrity_word);# else#  error "Please fix <asm/byteorder.h>"# endif#endif}EXPORT_SYMBOL(ide_fix_driveid);void ide_fixstring (u8 *s, const int bytecount, const int byteswap){	u8 *p = s, *end = &s[bytecount & ~1]; /* bytecount must be even */	if (byteswap) {		/* convert from big-endian to host byte order */		for (p = end ; p != s;) {			unsigned short *pp = (unsigned short *) (p -= 2);			*pp = ntohs(*pp);		}	}	/* strip leading blanks */	while (s != end && *s == ' ')		++s;	/* compress internal blanks and strip trailing blanks */	while (s != end && *s) {		if (*s++ != ' ' || (s != end && *s && *s != ' '))			*p++ = *(s-1);	}	/* wipe out trailing garbage */	while (p != end)		*p++ = '\0';}EXPORT_SYMBOL(ide_fixstring);/* * Needed for PCI irq sharing */int drive_is_ready (ide_drive_t *drive){	ide_hwif_t *hwif	= HWIF(drive);	u8 stat			= 0;	if (drive->waiting_for_dma)		return hwif->ide_dma_test_irq(drive);#if 0	/* need to guarantee 400ns since last command was issued */	udelay(1);#endif#ifdef CONFIG_IDEPCI_SHARE_IRQ	/*	 * We do a passive status test under shared PCI interrupts on	 * cards that truly share the ATA side interrupt, but may also share	 * an interrupt with another pci card/device.  We make no assumptions	 * about possible isa-pnp and pci-pnp issues yet.	 */	if (IDE_CONTROL_REG)		stat = hwif->INB(IDE_ALTSTATUS_REG);	else#endif /* CONFIG_IDEPCI_SHARE_IRQ */		/* Note: this may clear a pending IRQ!! */		stat = hwif->INB(IDE_STATUS_REG);	if (stat & BUSY_STAT)		/* drive busy:  definitely not interrupting */		return 0;	/* drive ready: *might* be interrupting */	return 1;}EXPORT_SYMBOL(drive_is_ready);/* * Global for All, and taken from ide-pmac.c. Can be called * with spinlock held & IRQs disabled, so don't schedule ! */int wait_for_ready (ide_drive_t *drive, int timeout){	ide_hwif_t *hwif	= HWIF(drive);	u8 stat			= 0;	while(--timeout) {		stat = hwif->INB(IDE_STATUS_REG);		if (!(stat & BUSY_STAT)) {			if (drive->ready_stat == 0)				break;			else if ((stat & drive->ready_stat)||(stat & ERR_STAT))				break;		}		mdelay(1);	}	if ((stat & ERR_STAT) || timeout <= 0) {		if (stat & ERR_STAT) {			printk(KERN_ERR "%s: wait_for_ready, "				"error status: %x\n", drive->name, stat);		}		return 1;	}	return 0;}EXPORT_SYMBOL(wait_for_ready);/* * This routine busy-waits for the drive status to be not "busy". * It then checks the status for all of the "good" bits and none * of the "bad" bits, and if all is okay it returns 0.  All other * cases return 1 after invoking ide_error() -- caller should just return. * * This routine should get fixed to not hog the cpu during extra long waits.. * That could be done by busy-waiting for the first jiffy or two, and then * setting a timer to wake up at half second intervals thereafter, * until timeout is achieved, before timing out. */int ide_wait_stat (ide_startstop_t *startstop, ide_drive_t *drive, u8 good, u8 bad, unsigned long timeout){	ide_hwif_t *hwif = HWIF(drive);	u8 stat;	int i;	unsigned long flags; 	/* bail early if we've exceeded max_failures */	if (drive->max_failures && (drive->failures > drive->max_failures)) {		*startstop = ide_stopped;		return 1;	}	udelay(1);	/* spec allows drive 400ns to assert "BUSY" */	if ((stat = hwif->INB(IDE_STATUS_REG)) & BUSY_STAT) {		local_irq_set(flags);		timeout += jiffies;		while ((stat = hwif->INB(IDE_STATUS_REG)) & BUSY_STAT) {			if (time_after(jiffies, timeout)) {				/*				 * One last read after the timeout in case				 * heavy interrupt load made us not make any				 * progress during the timeout..				 */				stat = hwif->INB(IDE_STATUS_REG);				if (!(stat & BUSY_STAT))					break;				local_irq_restore(flags);				*startstop = DRIVER(drive)->error(drive, "status timeout", stat);				return 1;			}		}		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)), good, bad))			return 0;	}	*startstop = DRIVER(drive)->error(drive, "status error", stat);	return 1;}EXPORT_SYMBOL(ide_wait_stat);/* *  All hosts that use the 80c ribbon must use! *  The name is derived from upper byte of word 93 and the 80c ribbon. */u8 eighty_ninty_three (ide_drive_t *drive){#if 0	if (!HWIF(drive)->udma_four)		return 0;	if (drive->id->major_rev_num) {		int hssbd = 0;		int i;		/*		 * Determine highest Supported SPEC		 */		for (i=1; i<=15; i++)			if (drive->id->major_rev_num & (1<<i))				hssbd++;		switch (hssbd) {			case 7:			case 6:			case 5:		/* ATA-4 and older do not support above Ultra 33 */			default:				return 0;		}	}	return ((u8) (#ifndef CONFIG_IDEDMA_IVB		(drive->id->hw_config & 0x4000) &&#endif /* CONFIG_IDEDMA_IVB */		 (drive->id->hw_config & 0x6000)) ? 1 : 0);#else	return ((u8) ((HWIF(drive)->udma_four) &&#ifndef CONFIG_IDEDMA_IVB			(drive->id->hw_config & 0x4000) &&#endif /* CONFIG_IDEDMA_IVB */			(drive->id->hw_config & 0x6000)) ? 1 : 0);#endif}EXPORT_SYMBOL(eighty_ninty_three);int ide_ata66_check (ide_drive_t *drive, ide_task_t *args){	if ((args->tfRegister[IDE_COMMAND_OFFSET] == WIN_SETFEATURES) &&	    (args->tfRegister[IDE_SECTOR_OFFSET] > XFER_UDMA_2) &&	    (args->tfRegister[IDE_FEATURE_OFFSET] == SETFEATURES_XFER)) {#ifndef CONFIG_IDEDMA_IVB		if ((drive->id->hw_config & 0x6000) == 0) {#else /* !CONFIG_IDEDMA_IVB */		if (((drive->id->hw_config & 0x2000) == 0) ||		    ((drive->id->hw_config & 0x4000) == 0)) {#endif /* CONFIG_IDEDMA_IVB */			printk("%s: Speed warnings UDMA 3/4/5 is not "				"functional.\n", drive->name);			return 1;		}		if (!HWIF(drive)->udma_four) {			printk("%s: Speed warnings UDMA 3/4/5 is not "				"functional.\n",				HWIF(drive)->name);			return 1;		}	}	return 0;}EXPORT_SYMBOL(ide_ata66_check);/* * Backside of HDIO_DRIVE_CMD call of SETFEATURES_XFER. * 1 : Safe to update drive->id DMA registers. * 0 : OOPs not allowed. */int set_transfer (ide_drive_t *drive, ide_task_t *args){	if ((args->tfRegister[IDE_COMMAND_OFFSET] == WIN_SETFEATURES) &&	    (args->tfRegister[IDE_SECTOR_OFFSET] >= XFER_SW_DMA_0) &&	    (args->tfRegister[IDE_FEATURE_OFFSET] == SETFEATURES_XFER) &&	    (drive->id->dma_ultra ||	     drive->id->dma_mword ||	     drive->id->dma_1word))		return 1;	return 0;}EXPORT_SYMBOL(set_transfer);u8 ide_auto_reduce_xfer (ide_drive_t *drive){	if (!drive->crc_count)		return drive->current_speed;	drive->crc_count = 0;	switch(drive->current_speed) {		case XFER_UDMA_7:	return XFER_UDMA_6;		case XFER_UDMA_6:	return XFER_UDMA_5;		case XFER_UDMA_5:	return XFER_UDMA_4;		case XFER_UDMA_4:	return XFER_UDMA_3;		case XFER_UDMA_3:	return XFER_UDMA_2;		case XFER_UDMA_2:	return XFER_UDMA_1;		case XFER_UDMA_1:	return XFER_UDMA_0;			/*			 * OOPS we do not goto non Ultra DMA modes			 * without iCRC's available we force			 * the system to PIO and make the user			 * invoke the ATA-1 ATA-2 DMA modes.			 */		case XFER_UDMA_0:		default:		return XFER_PIO_4;	}}EXPORT_SYMBOL(ide_auto_reduce_xfer);/* * Update the  */int ide_driveid_update (ide_drive_t *drive){	ide_hwif_t *hwif	= HWIF(drive);	struct hd_driveid *id;#if 0	id = kmalloc(SECTOR_WORDS*4, GFP_ATOMIC);	if (!id)		return 0;	taskfile_lib_get_identify(drive, (char *)&id);	ide_fix_driveid(id);	if (id) {		drive->id->dma_ultra = id->dma_ultra;		drive->id->dma_mword = id->dma_mword;		drive->id->dma_1word = id->dma_1word;		/* anything more ? */		kfree(id);	}	return 1;#else	/*	 * Re-read drive->id for possible DMA mode	 * change (copied from ide-probe.c)	 */	unsigned long timeout, flags;	SELECT_MASK(drive, 1);	if (IDE_CONTROL_REG)		hwif->OUTB(drive->ctl,IDE_CONTROL_REG);	msleep(50);	hwif->OUTB(WIN_IDENTIFY, IDE_COMMAND_REG);	timeout = jiffies + WAIT_WORSTCASE;	do {		if (time_after(jiffies, timeout)) {			SELECT_MASK(drive, 0);			return 0;	/* drive timed-out */		}		msleep(50);	/* give drive a breather */	} while (hwif->INB(IDE_ALTSTATUS_REG) & BUSY_STAT);	msleep(50);	/* wait for IRQ and DRQ_STAT */	if (!OK_STAT(hwif->INB(IDE_STATUS_REG),DRQ_STAT,BAD_R_STAT)) {		SELECT_MASK(drive, 0);		printk("%s: CHECK for good STATUS\n", drive->name);		return 0;	}	local_irq_save(flags);	SELECT_MASK(drive, 0);	id = kmalloc(SECTOR_WORDS*4, GFP_ATOMIC);	if (!id) {		local_irq_restore(flags);		return 0;	}	ata_input_data(drive, id, SECTOR_WORDS);	(void) hwif->INB(IDE_STATUS_REG);	/* clear drive IRQ */	local_irq_enable();	local_irq_restore(flags);	ide_fix_driveid(id);	if (id) {		drive->id->dma_ultra = id->dma_ultra;		drive->id->dma_mword = id->dma_mword;		drive->id->dma_1word = id->dma_1word;		/* anything more ? */		kfree(id);	}	return 1;#endif}EXPORT_SYMBOL(ide_driveid_update);/* * Similar to ide_wait_stat(), except it never calls ide_error internally. * This is a kludge to handle the new ide_config_drive_speed() function, * and should not otherwise be used anywhere.  Eventually, the tuneproc's * should be updated to return ide_startstop_t, in which case we can get * rid of this abomination again.  :)   -ml * * It is gone.......... * * const char *msg == consider adding for verbose errors. */int ide_config_drive_speed (ide_drive_t *drive, u8 speed){	ide_hwif_t *hwif	= HWIF(drive);	int	i, error	= 1;	u8 stat;//	while (HWGROUP(drive)->busy)//		msleep(50);#ifdef CONFIG_BLK_DEV_IDEDMA	if (hwif->ide_dma_check)	 /* check if host supports DMA */		hwif->ide_dma_host_off(drive);#endif	/*	 * Don't use ide_wait_cmd here - it will	 * attempt to set_geometry and recalibrate,	 * but for some reason these don't work at	 * this point (lost interrupt).	 */        /*         * Select the drive, and issue the SETFEATURES command         */	disable_irq_nosync(hwif->irq);		/*	 *	FIXME: we race against the running IRQ here if	 *	this is called from non IRQ context. If we use	 *	disable_irq() we hang on the error path. Work	 *	is needed.	 */	 	udelay(1);	SELECT_DRIVE(drive);	SELECT_MASK(drive, 0);	udelay(1);	if (IDE_CONTROL_REG)		hwif->OUTB(drive->ctl | 2, IDE_CONTROL_REG);	hwif->OUTB(speed, IDE_NSECTOR_REG);	hwif->OUTB(SETFEATURES_XFER, IDE_FEATURE_REG);

⌨️ 快捷键说明

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