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

📄 ide.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
#ifndef CONFIG_BLK_DEV_IDECS	hwif->irq			= tmp_hwif->irq;#endif	hwif->dma_base			= tmp_hwif->dma_base;	hwif->dma_master		= tmp_hwif->dma_master;	hwif->dma_command		= tmp_hwif->dma_command;	hwif->dma_vendor1		= tmp_hwif->dma_vendor1;	hwif->dma_status		= tmp_hwif->dma_status;	hwif->dma_vendor3		= tmp_hwif->dma_vendor3;	hwif->dma_prdtable		= tmp_hwif->dma_prdtable;	hwif->config_data		= tmp_hwif->config_data;	hwif->select_data		= tmp_hwif->select_data;	hwif->extra_base		= tmp_hwif->extra_base;	hwif->extra_ports		= tmp_hwif->extra_ports;	hwif->hwif_data			= tmp_hwif->hwif_data;}/** *	ide_unregister		-	free an IDE interface *	@index: index of interface (will change soon to a pointer) * *	Perform the final unregister of an IDE interface. At the moment *	we don't refcount interfaces so this will also get split up. * *	Locking: *	The caller must not hold the IDE locks *	The drive present/vanishing is not yet properly locked *	Take care with the callbacks. These have been split to avoid *	deadlocking the IDE layer. The shutdown callback is called *	before we take the lock and free resources. It is up to the *	caller to be sure there is no pending I/O here, and that *	the interface will not be reopened (present/vanishing locking *	isn't yet done BTW). After we commit to the final kill we *	call the cleanup callback with the ide locks held. * *	Unregister restores the hwif structures to the default state. *	This is raving bonkers. */void ide_unregister(unsigned int index){	ide_drive_t *drive;	ide_hwif_t *hwif, *g;	static ide_hwif_t tmp_hwif; /* protected by ide_cfg_mtx */	ide_hwgroup_t *hwgroup;	int irq_count = 0, unit;	BUG_ON(index >= MAX_HWIFS);	BUG_ON(in_interrupt());	BUG_ON(irqs_disabled());	mutex_lock(&ide_cfg_mtx);	spin_lock_irq(&ide_lock);	hwif = &ide_hwifs[index];	if (!hwif->present)		goto abort;	for (unit = 0; unit < MAX_DRIVES; ++unit) {		drive = &hwif->drives[unit];		if (!drive->present)			continue;		spin_unlock_irq(&ide_lock);		device_unregister(&drive->gendev);		wait_for_completion(&drive->gendev_rel_comp);		spin_lock_irq(&ide_lock);	}	hwif->present = 0;	spin_unlock_irq(&ide_lock);	ide_proc_unregister_port(hwif);	hwgroup = hwif->hwgroup;	/*	 * free the irq if we were the only hwif using it	 */	g = hwgroup->hwif;	do {		if (g->irq == hwif->irq)			++irq_count;		g = g->next;	} while (g != hwgroup->hwif);	if (irq_count == 1)		free_irq(hwif->irq, hwgroup);	spin_lock_irq(&ide_lock);	/*	 * Note that we only release the standard ports,	 * and do not even try to handle any extra ports	 * allocated for weird IDE interface chipsets.	 */	ide_hwif_release_regions(hwif);	/*	 * Remove us from the hwgroup, and free	 * the hwgroup if we were the only member	 */	if (hwif->next == hwif) {		BUG_ON(hwgroup->hwif != hwif);		kfree(hwgroup);	} else {		/* There is another interface in hwgroup.		 * Unlink us, and set hwgroup->drive and ->hwif to		 * something sane.		 */		g = hwgroup->hwif;		while (g->next != hwif)			g = g->next;		g->next = hwif->next;		if (hwgroup->hwif == hwif) {			/* Chose a random hwif for hwgroup->hwif.			 * It's guaranteed that there are no drives			 * left in the hwgroup.			 */			BUG_ON(hwgroup->drive != NULL);			hwgroup->hwif = g;		}		BUG_ON(hwgroup->hwif == hwif);	}	/* More messed up locking ... */	spin_unlock_irq(&ide_lock);	device_unregister(&hwif->gendev);	wait_for_completion(&hwif->gendev_rel_comp);	/*	 * Remove us from the kernel's knowledge	 */	blk_unregister_region(MKDEV(hwif->major, 0), MAX_DRIVES<<PARTN_BITS);	kfree(hwif->sg_table);	unregister_blkdev(hwif->major, hwif->name);	spin_lock_irq(&ide_lock);	if (hwif->dma_base) {		(void) ide_release_dma(hwif);		hwif->dma_base = 0;		hwif->dma_master = 0;		hwif->dma_command = 0;		hwif->dma_vendor1 = 0;		hwif->dma_status = 0;		hwif->dma_vendor3 = 0;		hwif->dma_prdtable = 0;		hwif->extra_base  = 0;		hwif->extra_ports = 0;	}	/* copy original settings */	tmp_hwif = *hwif;	/* restore hwif data to pristine status */	init_hwif_data(hwif, index);	init_hwif_default(hwif, index);	ide_hwif_restore(hwif, &tmp_hwif);abort:	spin_unlock_irq(&ide_lock);	mutex_unlock(&ide_cfg_mtx);}EXPORT_SYMBOL(ide_unregister);/** *	ide_setup_ports 	-	set up IDE interface ports *	@hw: register descriptions *	@base: base register *	@offsets: table of register offsets *	@ctrl: control register *	@ack_irq: IRQ ack *	@irq: interrupt lie * *	Setup hw_regs_t structure described by parameters.  You *	may set up the hw structure yourself OR use this routine to *	do it for you. This is basically a helper * */ void ide_setup_ports (	hw_regs_t *hw,			unsigned long base, int *offsets,			unsigned long ctrl, unsigned long intr,			ide_ack_intr_t *ack_intr,/* *			ide_io_ops_t *iops, */			int irq){	int i;	memset(hw, 0, sizeof(hw_regs_t));	for (i = 0; i < IDE_NR_PORTS; i++) {		if (offsets[i] == -1) {			switch(i) {				case IDE_CONTROL_OFFSET:					hw->io_ports[i] = ctrl;					break;#if defined(CONFIG_AMIGA) || defined(CONFIG_MAC)				case IDE_IRQ_OFFSET:					hw->io_ports[i] = intr;					break;#endif /* (CONFIG_AMIGA) || (CONFIG_MAC) */				default:					hw->io_ports[i] = 0;					break;			}		} else {			hw->io_ports[i] = base + offsets[i];		}	}	hw->irq = irq;	hw->ack_intr = ack_intr;/* *	hw->iops = iops; */}/** *	ide_register_hw		-	register IDE interface *	@hw: hardware registers *	@fixup: fixup function *	@initializing: set while initializing built-in drivers *	@hwifp: pointer to returned hwif * *	Register an IDE interface, specifying exactly the registers etc. *	Set init=1 iff calling before probes have taken place. * *	Returns -1 on error. */int ide_register_hw(hw_regs_t *hw, void (*fixup)(ide_hwif_t *),		    int initializing, ide_hwif_t **hwifp){	int index, retry = 1;	ide_hwif_t *hwif;	do {		for (index = 0; index < MAX_HWIFS; ++index) {			hwif = &ide_hwifs[index];			if (hwif->io_ports[IDE_DATA_OFFSET] == hw->io_ports[IDE_DATA_OFFSET])				goto found;		}		for (index = 0; index < MAX_HWIFS; ++index) {			hwif = &ide_hwifs[index];			if (hwif->hold)				continue;			if ((!hwif->present && !hwif->mate && !initializing) ||			    (!hwif->io_ports[IDE_DATA_OFFSET] && initializing))				goto found;		}		for (index = 0; index < MAX_HWIFS; index++)			ide_unregister(index);	} while (retry--);	return -1;found:	if (hwif->present)		ide_unregister(index);	else if (!hwif->hold) {		init_hwif_data(hwif, index);		init_hwif_default(hwif, index);	}	if (hwif->present)		return -1;	memcpy(hwif->io_ports, hw->io_ports, sizeof(hwif->io_ports));	hwif->irq = hw->irq;	hwif->noprobe = 0;	hwif->fixup = fixup;	hwif->chipset = hw->chipset;	hwif->gendev.parent = hw->dev;	hwif->ack_intr = hw->ack_intr;	if (initializing == 0) {		u8 idx[4] = { index, 0xff, 0xff, 0xff };		ide_device_add(idx);	}	if (hwifp)		*hwifp = hwif;	return (initializing || hwif->present) ? index : -1;}EXPORT_SYMBOL(ide_register_hw);/* *	Locks for IDE setting functionality */DEFINE_MUTEX(ide_setting_mtx);EXPORT_SYMBOL_GPL(ide_setting_mtx);/** *	ide_spin_wait_hwgroup	-	wait for group *	@drive: drive in the group * *	Wait for an IDE device group to go non busy and then return *	holding the ide_lock which guards the hwgroup->busy status *	and right to use it. */int ide_spin_wait_hwgroup (ide_drive_t *drive){	ide_hwgroup_t *hwgroup = HWGROUP(drive);	unsigned long timeout = jiffies + (3 * HZ);	spin_lock_irq(&ide_lock);	while (hwgroup->busy) {		unsigned long lflags;		spin_unlock_irq(&ide_lock);		local_irq_set(lflags);		if (time_after(jiffies, timeout)) {			local_irq_restore(lflags);			printk(KERN_ERR "%s: channel busy\n", drive->name);			return -EBUSY;		}		local_irq_restore(lflags);		spin_lock_irq(&ide_lock);	}	return 0;}EXPORT_SYMBOL(ide_spin_wait_hwgroup);int set_io_32bit(ide_drive_t *drive, int arg){	if (drive->no_io_32bit)		return -EPERM;	if (arg < 0 || arg > 1 + (SUPPORT_VLB_SYNC << 1))		return -EINVAL;	if (ide_spin_wait_hwgroup(drive))		return -EBUSY;	drive->io_32bit = arg;#ifdef CONFIG_BLK_DEV_DTC2278	if (HWIF(drive)->chipset == ide_dtc2278)		HWIF(drive)->drives[!drive->select.b.unit].io_32bit = arg;#endif /* CONFIG_BLK_DEV_DTC2278 */	spin_unlock_irq(&ide_lock);	return 0;}static int set_ksettings(ide_drive_t *drive, int arg){	if (arg < 0 || arg > 1)		return -EINVAL;	if (ide_spin_wait_hwgroup(drive))		return -EBUSY;	drive->keep_settings = arg;	spin_unlock_irq(&ide_lock);	return 0;}int set_using_dma(ide_drive_t *drive, int arg){#ifdef CONFIG_BLK_DEV_IDEDMA	ide_hwif_t *hwif = drive->hwif;	int err = -EPERM;	if (arg < 0 || arg > 1)		return -EINVAL;	if (!drive->id || !(drive->id->capability & 1))		goto out;	if (hwif->ide_dma_on == NULL)		goto out;	err = -EBUSY;	if (ide_spin_wait_hwgroup(drive))		goto out;	/*	 * set ->busy flag, unlock and let it ride	 */	hwif->hwgroup->busy = 1;	spin_unlock_irq(&ide_lock);	err = 0;	if (arg) {		hwif->dma_off_quietly(drive);		if (ide_set_dma(drive) || hwif->ide_dma_on(drive))			err = -EIO;	} else		ide_dma_off(drive);	/*	 * lock, clear ->busy flag and unlock before leaving	 */	spin_lock_irq(&ide_lock);	hwif->hwgroup->busy = 0;	spin_unlock_irq(&ide_lock);out:	return err;#else	if (arg < 0 || arg > 1)		return -EINVAL;	return -EPERM;#endif}int set_pio_mode(ide_drive_t *drive, int arg){	struct request rq;	if (arg < 0 || arg > 255)		return -EINVAL;	if (drive->hwif->set_pio_mode == NULL)		return -ENOSYS;	if (drive->special.b.set_tune)		return -EBUSY;	ide_init_drive_cmd(&rq);	drive->tune_req = (u8) arg;	drive->special.b.set_tune = 1;	(void) ide_do_drive_cmd(drive, &rq, ide_wait);	return 0;}static int set_unmaskirq(ide_drive_t *drive, int arg){	if (drive->no_unmask)		return -EPERM;	if (arg < 0 || arg > 1)		return -EINVAL;	if (ide_spin_wait_hwgroup(drive))		return -EBUSY;	drive->unmask = arg;	spin_unlock_irq(&ide_lock);	return 0;}/** *	system_bus_clock	-	clock guess * *	External version of the bus clock guess used by very old IDE drivers *	for things like VLB timings. Should not be used. */int system_bus_clock (void){	return((int) ((!system_bus_speed) ? ide_system_bus_speed() : system_bus_speed ));}EXPORT_SYMBOL(system_bus_clock);static int generic_ide_suspend(struct device *dev, pm_message_t mesg){	ide_drive_t *drive = dev->driver_data;

⌨️ 快捷键说明

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