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

📄 ide.c

📁 ep9315平台下硬盘驱动的源码
💻 C
📖 第 1 页 / 共 5 页
字号:
 */void ide_setup_ports (	hw_regs_t *hw,			ide_ioreg_t base, int *offsets,			ide_ioreg_t ctrl, ide_ioreg_t intr,			ide_ack_intr_t *ack_intr,/* *			ide_io_ops_t *iops, */			int irq){	int i;	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->dma = NO_DMA;	hw->ack_intr = ack_intr;/* *	hw->iops = iops; */}EXPORT_SYMBOL(ide_setup_ports);/* * Register an IDE interface, specifing exactly the registers etc * Set init=1 iff calling before probes have taken place. */int ide_register_hw (hw_regs_t *hw, 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->hw.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 && ((!hwif->present && !hwif->mate && !initializing) ||			    (!hwif->hw.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(index);	if (hwif->present)		return -1;	memcpy(&hwif->hw, hw, sizeof(*hw));	memcpy(hwif->io_ports, hwif->hw.io_ports, sizeof(hwif->hw.io_ports));	hwif->irq = hw->irq;	hwif->noprobe = 0;	hwif->chipset = hw->chipset;	if (!initializing) {		ide_probe_module(1);#ifdef CONFIG_PROC_FS		create_proc_ide_interfaces();#endif		ide_driver_module(1);	}	if (hwifp)		*hwifp = hwif;	return (initializing || hwif->present) ? index : -1;}EXPORT_SYMBOL(ide_register_hw);/* * Compatability function with existing drivers.  If you want * something different, use the function above. */int ide_register (int arg1, int arg2, int irq){	hw_regs_t hw;	ide_init_hwif_ports(&hw, (ide_ioreg_t) arg1, (ide_ioreg_t) arg2, NULL);	hw.irq = irq;	return ide_register_hw(&hw, NULL);}EXPORT_SYMBOL(ide_register);/* *	Locks for IDE setting functionality */DECLARE_MUTEX(ide_setting_sem);EXPORT_SYMBOL(ide_setting_sem);/** *	ide_add_setting	-	add an ide setting option *	@drive: drive to use *	@name: setting name *	@rw: true if the function is read write *	@read_ioctl: function to call on read *	@write_ioctl: function to call on write *	@data_type: type of data *	@min: range minimum *	@max: range maximum *	@mul_factor: multiplication scale *	@div_factor: divison scale *	@data: private data field *	@set: setting * *	Removes the setting named from the device if it is present. *	The function takes the settings_lock to protect against  *	parallel changes. This function must not be called from IRQ *	context. Returns 0 on success or -1 on failure. * *	BUGS: This code is seriously over-engineered. There is also *	magic about how the driver specific features are setup. If *	a driver is attached we assume the driver settings are auto *	remove. */ int ide_add_setting (ide_drive_t *drive, const char *name, int rw, int read_ioctl, int write_ioctl, int data_type, int min, int max, int mul_factor, int div_factor, void *data, ide_procset_t *set){	ide_settings_t **p = (ide_settings_t **) &drive->settings, *setting = NULL;	down(&ide_setting_sem);	while ((*p) && strcmp((*p)->name, name) < 0)		p = &((*p)->next);	if ((setting = kmalloc(sizeof(*setting), GFP_KERNEL)) == NULL)		goto abort;	memset(setting, 0, sizeof(*setting));	if ((setting->name = kmalloc(strlen(name) + 1, GFP_KERNEL)) == NULL)		goto abort;	strcpy(setting->name, name);	setting->rw = rw;	setting->read_ioctl = read_ioctl;	setting->write_ioctl = write_ioctl;	setting->data_type = data_type;	setting->min = min;	setting->max = max;	setting->mul_factor = mul_factor;	setting->div_factor = div_factor;	setting->data = data;	setting->set = set;		setting->next = *p;	if (drive->driver != &idedefault_driver)		setting->auto_remove = 1;	*p = setting;	up(&ide_setting_sem);	return 0;abort:	up(&ide_setting_sem);	if (setting)		kfree(setting);	return -1;}EXPORT_SYMBOL(ide_add_setting);/** *	__ide_remove_setting	-	remove an ide setting option *	@drive: drive to use *	@name: setting name * *	Removes the setting named from the device if it is present. *	The caller must hold the setting semaphore. */ static void __ide_remove_setting (ide_drive_t *drive, char *name){	ide_settings_t **p, *setting;	p = (ide_settings_t **) &drive->settings;	while ((*p) && strcmp((*p)->name, name))		p = &((*p)->next);	if ((setting = (*p)) == NULL)		return;	(*p) = setting->next;		kfree(setting->name);	kfree(setting);}/** *	ide_remove_setting	-	remove an ide setting option *	@drive: drive to use *	@name: setting name * *	Removes the setting named from the device if it is present. *	The function takes the settings_lock to protect against  *	parallel changes. This function must not be called from IRQ *	context. */ void ide_remove_setting (ide_drive_t *drive, char *name){	down(&ide_setting_sem);	__ide_remove_setting(drive, name);	up(&ide_setting_sem);}EXPORT_SYMBOL(ide_remove_setting);/** *	ide_find_setting_by_ioctl	-	find a drive specific ioctl *	@drive: drive to scan *	@cmd: ioctl command to handle * *	Scan's the device setting table for a matching entry and returns *	this or NULL if no entry is found. The caller must hold the *	setting semaphore */ static ide_settings_t *ide_find_setting_by_ioctl (ide_drive_t *drive, int cmd){	ide_settings_t *setting = drive->settings;	while (setting) {		if (setting->read_ioctl == cmd || setting->write_ioctl == cmd)			break;		setting = setting->next;	}		return setting;}/** *	ide_find_setting_by_name	-	find a drive specific setting *	@drive: drive to scan *	@name: setting name * *	Scan's the device setting table for a matching entry and returns *	this or NULL if no entry is found. The caller must hold the *	setting semaphore */ ide_settings_t *ide_find_setting_by_name (ide_drive_t *drive, char *name){	ide_settings_t *setting = drive->settings;	while (setting) {		if (strcmp(setting->name, name) == 0)			break;		setting = setting->next;	}	return setting;}/** *	auto_remove_settings	-	remove driver specific settings *	@drive: drive * *	Automatically remove all the driver specific settings for this *	drive. This function may sleep and must not be called from IRQ *	context. Caller must hold the setting lock. */ static void auto_remove_settings (ide_drive_t *drive){	ide_settings_t *setting;repeat:	setting = drive->settings;	while (setting) {		if (setting->auto_remove) {			__ide_remove_setting(drive, setting->name);			goto repeat;		}		setting = setting->next;	}}/** *	ide_read_setting	-	read an IDE setting *	@drive: drive to read from *	@setting: drive setting * *	Read a drive setting and return the value. The caller *	must hold the ide_setting_sem when making this call. * *	BUGS: the data return and error are the same return value *	so an error -EINVAL and true return of the same value cannot *	be told apart */ int ide_read_setting (ide_drive_t *drive, ide_settings_t *setting){	int		val = -EINVAL;	unsigned long	flags;	if ((setting->rw & SETTING_READ)) {		spin_lock_irqsave(&io_request_lock, flags);		switch(setting->data_type) {			case TYPE_BYTE:				val = *((u8 *) setting->data);				break;			case TYPE_SHORT:				val = *((u16 *) setting->data);				break;			case TYPE_INT:			case TYPE_INTA:				val = *((u32 *) setting->data);				break;		}		spin_unlock_irqrestore(&io_request_lock, flags);	}	return val;}int ide_spin_wait_hwgroup (ide_drive_t *drive){	ide_hwgroup_t *hwgroup = HWGROUP(drive);	unsigned long timeout = jiffies + (3 * HZ);	spin_lock_irq(&io_request_lock);	while (hwgroup->busy) {		unsigned long lflags;		spin_unlock_irq(&io_request_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(&io_request_lock);	}	return 0;}EXPORT_SYMBOL(ide_spin_wait_hwgroup);/** *	ide_write_setting	-	read an IDE setting *	@drive: drive to read from *	@setting: drive setting *	@val: value * *	Write a drive setting if it is possible. The caller *	must hold the ide_setting_sem when making this call. * *	BUGS: the data return and error are the same return value *	so an error -EINVAL and true return of the same value cannot *	be told apart * *	FIXME:  This should be changed to enqueue a special request *	to the driver to change settings, and then wait on a sema for completion. *	The current scheme of polling is kludgy, though safe enough. */int ide_write_setting (ide_drive_t *drive, ide_settings_t *setting, int val){	int i;	u32 *p;	if (!capable(CAP_SYS_ADMIN))		return -EACCES;	if (!(setting->rw & SETTING_WRITE))		return -EPERM;	if (val < setting->min || val > setting->max)		return -EINVAL;	if (setting->set)		return setting->set(drive, val);	if (ide_spin_wait_hwgroup(drive))		return -EBUSY;	switch (setting->data_type) {		case TYPE_BYTE:			*((u8 *) setting->data) = val;			break;		case TYPE_SHORT:			*((u16 *) setting->data) = val;			break;		case TYPE_INT:			*((u32 *) setting->data) = val;			break;		case TYPE_INTA:			p = (u32 *) setting->data;			for (i = 0; i < 1 << PARTN_BITS; i++, p++)				*p = val;			break;	}	spin_unlock_irq(&io_request_lock);	return 0;}EXPORT_SYMBOL(ide_write_setting);static int set_io_32bit(ide_drive_t *drive, int arg){	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 */	return 0;}static int set_using_dma (ide_drive_t *drive, int arg){	if (!DRIVER(drive)->supports_dma)		return -EPERM;	if (!(drive->id->capability & 1))		return -EPERM;	if (HWIF(drive)->ide_dma_check == NULL)		return -EPERM;	if (HWIF(drive)->ide_dma_check(drive) != 0)		return -EIO;	if (arg) {		if (HWIF(drive)->ide_dma_check(drive) != 0)			return -EIO;		if (HWIF(drive)->ide_dma_on(drive)) return -EIO;	} else {		if (HWIF(drive)->ide_dma_off(drive)) return -EIO;	}	return 0;}static int set_pio_mode (ide_drive_t *drive, int arg){	struct request rq;	if (!HWIF(drive)->tuneproc)		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_xfer_rate (ide_drive_t *drive, int arg){	int err = ide_wait_cmd(drive,			WIN_SETFEATURES, (u8) arg,			SETFEATURES_XFER, 0, NULL);

⌨️ 快捷键说明

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