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

📄 ide-iops.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
{	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);/* * 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 error -- caller may then invoke ide_error(). * * 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. */static int __ide_wait_stat(ide_drive_t *drive, u8 good, u8 bad, unsigned long timeout, u8 *rstat){	ide_hwif_t *hwif = drive->hwif;	unsigned long flags;	int i;	u8 stat;	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);				*rstat = stat;				return -EBUSY;			}		}		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)) {			*rstat = stat;			return 0;		}	}	*rstat = stat;	return -EFAULT;}/* * In case of error returns error value after doing "*startstop = ide_error()". * The caller should return the updated value of "startstop" in this case, * "startstop" is unchanged when the function returns 0. */int ide_wait_stat(ide_startstop_t *startstop, ide_drive_t *drive, u8 good, u8 bad, unsigned long timeout){	int err;	u8 stat;	/* bail early if we've exceeded max_failures */	if (drive->max_failures && (drive->failures > drive->max_failures)) {		*startstop = ide_stopped;		return 1;	}	err = __ide_wait_stat(drive, good, bad, timeout, &stat);	if (err) {		char *s = (err == -EBUSY) ? "status timeout" : "status error";		*startstop = ide_error(drive, s, stat);	}	return err;}EXPORT_SYMBOL(ide_wait_stat);/** *	ide_in_drive_list	-	look for drive in black/white list *	@id: drive identifier *	@drive_table: list to inspect * *	Look for a drive in the blacklist and the whitelist tables *	Returns 1 if the drive is found in the table. */int ide_in_drive_list(struct hd_driveid *id, const struct drive_list_entry *drive_table){	for ( ; drive_table->id_model; drive_table++)		if ((!strcmp(drive_table->id_model, id->model)) &&		    (!drive_table->id_firmware ||		     strstr(id->fw_rev, drive_table->id_firmware)))			return 1;	return 0;}EXPORT_SYMBOL_GPL(ide_in_drive_list);/* * Early UDMA66 devices don't set bit14 to 1, only bit13 is valid. * We list them here and depend on the device side cable detection for them. * * Some optical devices with the buggy firmwares have the same problem. */static const struct drive_list_entry ivb_list[] = {	{ "QUANTUM FIREBALLlct10 05"	, "A03.0900"	},	{ "TSSTcorp CDDVDW SH-S202J"	, "SB00"	},	{ "TSSTcorp CDDVDW SH-S202J"	, "SB01"	},	{ "TSSTcorp CDDVDW SH-S202N"	, "SB00"	},	{ "TSSTcorp CDDVDW SH-S202N"	, "SB01"	},	{ NULL				, NULL		}};/* *  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){	ide_hwif_t *hwif = drive->hwif;	struct hd_driveid *id = drive->id;	int ivb = ide_in_drive_list(id, ivb_list);	if (hwif->cbl == ATA_CBL_PATA40_SHORT)		return 1;	if (ivb)		printk(KERN_DEBUG "%s: skipping word 93 validity check\n",				  drive->name);	if (ide_dev_is_sata(id) && !ivb)		return 1;	if (hwif->cbl != ATA_CBL_PATA80 && !ivb)		goto no_80w;	/*	 * FIXME:	 * - force bit13 (80c cable present) check also for !ivb devices	 *   (unless the slave device is pre-ATA3)	 */	if ((id->hw_config & 0x4000) || (ivb && (id->hw_config & 0x2000)))		return 1;no_80w:	if (drive->udma33_warned == 1)		return 0;	printk(KERN_WARNING "%s: %s side 80-wire cable detection failed, "			    "limiting max speed to UDMA33\n",			    drive->name,			    hwif->cbl == ATA_CBL_PATA80 ? "drive" : "host");	drive->udma33_warned = 1;	return 0;}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)) {		if (eighty_ninty_three(drive) == 0) {			printk(KERN_WARNING "%s: UDMA speeds >UDMA33 cannot "					    "be set\n", drive->name);			return 1;		}	}	return 0;}/* * 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;}#ifdef CONFIG_BLK_DEV_IDEDMAstatic 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;	}}#endif /* CONFIG_BLK_DEV_IDEDMA */int ide_driveid_update(ide_drive_t *drive){	ide_hwif_t *hwif = drive->hwif;	struct hd_driveid *id;	unsigned long timeout, flags;	/*	 * Re-read drive->id for possible DMA mode	 * change (copied from ide-probe.c)	 */	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);		if (drive->using_dma && ide_id_dma_bug(drive))			ide_dma_off(drive);	}	return 1;}int ide_config_drive_speed(ide_drive_t *drive, u8 speed){	ide_hwif_t *hwif = drive->hwif;	int error = 0;	u8 stat;//	while (HWGROUP(drive)->busy)//		msleep(50);#ifdef CONFIG_BLK_DEV_IDEDMA	if (hwif->ide_dma_on)	/* check if host supports DMA */		hwif->dma_host_off(drive);#endif	/* Skip setting PIO flow-control modes on pre-EIDE drives */	if ((speed & 0xf8) == XFER_PIO_0 && !(drive->id->capability & 0x08))		goto skip;	/*	 * 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);	hwif->OUTBSYNC(drive, WIN_SETFEATURES, IDE_COMMAND_REG);	if ((IDE_CONTROL_REG) && (drive->quirk_list == 2))		hwif->OUTB(drive->ctl, IDE_CONTROL_REG);	error = __ide_wait_stat(drive, drive->ready_stat,				BUSY_STAT|DRQ_STAT|ERR_STAT,				WAIT_CMD, &stat);	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;

⌨️ 快捷键说明

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