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

📄 ide.c

📁 ep9315平台下硬盘驱动的源码
💻 C
📖 第 1 页 / 共 5 页
字号:
	if (!err && arg) {		ide_set_xfer_rate(drive, (u8) arg);		ide_driveid_update(drive);	}	return err;}int ide_atapi_to_scsi (ide_drive_t *drive, int arg){	if (drive->media == ide_disk) {		drive->scsi = 0;		return 0;	}	if (DRIVER(drive)->cleanup(drive)) {		drive->scsi = 0;		return 0;	}	drive->scsi = (u8) arg;	ide_attach_drive(drive);	return 0;}void ide_add_generic_settings (ide_drive_t *drive){/* *			drive	setting name		read/write access				read ioctl		write ioctl		data type	min	max				mul_factor	div_factor	data pointer			set function */	ide_add_setting(drive,	"io_32bit",		drive->no_io_32bit ? SETTING_READ : SETTING_RW,	HDIO_GET_32BIT,		HDIO_SET_32BIT,		TYPE_BYTE,	0,	1 + (SUPPORT_VLB_SYNC << 1),	1,		1,		&drive->io_32bit,		set_io_32bit);	ide_add_setting(drive,	"keepsettings",		SETTING_RW,					HDIO_GET_KEEPSETTINGS,	HDIO_SET_KEEPSETTINGS,	TYPE_BYTE,	0,	1,				1,		1,		&drive->keep_settings,		NULL);	ide_add_setting(drive,	"nice1",		SETTING_RW,					-1,			-1,			TYPE_BYTE,	0,	1,				1,		1,		&drive->nice1,			NULL);	ide_add_setting(drive,	"pio_mode",		SETTING_WRITE,					-1,			HDIO_SET_PIO_MODE,	TYPE_BYTE,	0,	255,				1,		1,		NULL,				set_pio_mode);	ide_add_setting(drive,	"slow",			SETTING_RW,					-1,			-1,			TYPE_BYTE,	0,	1,				1,		1,		&drive->slow,			NULL);	ide_add_setting(drive,	"unmaskirq",		drive->no_unmask ? SETTING_READ : SETTING_RW,	HDIO_GET_UNMASKINTR,	HDIO_SET_UNMASKINTR,	TYPE_BYTE,	0,	1,				1,		1,		&drive->unmask,			NULL);	ide_add_setting(drive,	"using_dma",		SETTING_RW,					HDIO_GET_DMA,		HDIO_SET_DMA,		TYPE_BYTE,	0,	1,				1,		1,		&drive->using_dma,		set_using_dma);	ide_add_setting(drive,	"init_speed",		SETTING_RW,					-1,			-1,			TYPE_BYTE,	0,	70,				1,		1,		&drive->init_speed,		NULL);	ide_add_setting(drive,	"current_speed",	SETTING_RW,					-1,			-1,			TYPE_BYTE,	0,	70,				1,		1,		&drive->current_speed,		set_xfer_rate);	ide_add_setting(drive,	"number",		SETTING_RW,					-1,			-1,			TYPE_BYTE,	0,	3,				1,		1,		&drive->dn,			NULL);#if 0	/* Experimental, but this needs the setting/register locking rewritten to be used */		if (drive->media != ide_disk)		ide_add_setting(drive,	"ide-scsi",		SETTING_RW,					-1,		HDIO_SET_IDE_SCSI,		TYPE_BYTE,	0,	1,				1,		1,		&drive->scsi,			ide_atapi_to_scsi);#endif		}/* * Delay for *at least* 50ms.  As we don't know how much time is left * until the next tick occurs, we wait an extra tick to be safe. * This is used only during the probing/polling for drives at boot time. * * However, its usefullness may be needed in other places, thus we export it now. * The future may change this to a millisecond setable delay. */void ide_delay_50ms (void){#ifndef CONFIG_BLK_DEV_IDECS	mdelay(50);#else	__set_current_state(TASK_UNINTERRUPTIBLE);	schedule_timeout(1+HZ/20);#endif /* CONFIG_BLK_DEV_IDECS */}EXPORT_SYMBOL(ide_delay_50ms);int system_bus_clock (void){	return((int) ((!system_bus_speed) ? ide_system_bus_speed() : system_bus_speed ));}EXPORT_SYMBOL(system_bus_clock);int ide_replace_subdriver (ide_drive_t *drive, const char *driver){	if (!drive->present || drive->busy || drive->usage || drive->dead)		goto abort;	if (DRIVER(drive)->cleanup(drive))		goto abort;	strncpy(drive->driver_req, driver, 9);	ide_driver_module(0);	drive->driver_req[0] = 0;	ide_driver_module(0);	if (!strcmp(DRIVER(drive)->name, driver))		return 0;abort:	return 1;}EXPORT_SYMBOL(ide_replace_subdriver);int ide_attach_drive (ide_drive_t *drive){	/* Someone unplugged the device on us */	if(drive->dead)		return 1;		#ifdef CONFIG_BLK_DEV_IDESCSI	if (drive->scsi) {		extern int idescsi_attach(ide_drive_t *drive);		if (idescsi_attach(drive))			return 0;	}#endif /* CONFIG_BLK_DEV_IDESCSI */	switch (drive->media) {#ifdef CONFIG_BLK_DEV_IDECD		case ide_cdrom:		{			extern int ide_cdrom_attach(ide_drive_t *drive);			if (ide_cdrom_attach(drive))				return 1;			break;		}#endif /* CONFIG_BLK_DEV_IDECD */#ifdef CONFIG_BLK_DEV_IDEDISK		case ide_disk:		{			extern int idedisk_attach(ide_drive_t *drive);			if (idedisk_attach(drive))				return 1;			break;		}#endif /* CONFIG_BLK_DEV_IDEDISK */#ifdef CONFIG_BLK_DEV_IDEFLOPPY		case ide_floppy:		{			extern int idefloppy_attach(ide_drive_t *drive);			if (idefloppy_attach(drive))				return 1;			break;		}#endif /* CONFIG_BLK_DEV_IDEFLOPPY */#ifdef CONFIG_BLK_DEV_IDETAPE		case ide_tape:		{			extern int idetape_attach(ide_drive_t *drive);			if (idetape_attach(drive))				return 1;			break;		}#endif /* CONFIG_BLK_DEV_IDETAPE */		default:		{			extern int idedefault_attach(ide_drive_t *drive);			if(idedefault_attach(drive))				printk(KERN_CRIT "ide: failed to attach default driver.\n");			return 1;		}	}	return 0;}EXPORT_SYMBOL(ide_attach_drive);static int ide_ioctl (struct inode *inode, struct file *file,			unsigned int cmd, unsigned long arg){	int err = 0, major, minor;	ide_drive_t *drive;	struct request rq;	kdev_t dev;	ide_settings_t *setting;	if (!inode || !(dev = inode->i_rdev))		return -EINVAL;	major = MAJOR(dev); minor = MINOR(dev);	if ((drive = get_info_ptr(inode->i_rdev)) == NULL)		return -ENODEV;	down(&ide_setting_sem);	if ((setting = ide_find_setting_by_ioctl(drive, cmd)) != NULL) {		if (cmd == setting->read_ioctl) {			err = ide_read_setting(drive, setting);			up(&ide_setting_sem);			return err >= 0 ? put_user(err, (long *) arg) : err;		} else {			if ((MINOR(inode->i_rdev) & PARTN_MASK))				err = -EINVAL;			else 				err = ide_write_setting(drive, setting, arg);			up(&ide_setting_sem);			return err;		}	}	up(&ide_setting_sem);	ide_init_drive_cmd (&rq);	switch (cmd) {		case HDIO_GETGEO:		{			struct hd_geometry *loc = (struct hd_geometry *) arg;			u16 bios_cyl = drive->bios_cyl; /* truncate */			if (!loc || (drive->media != ide_disk && drive->media != ide_floppy)) return -EINVAL;			if (put_user(drive->bios_head, (u8 *) &loc->heads)) return -EFAULT;			if (put_user(drive->bios_sect, (u8 *) &loc->sectors)) return -EFAULT;			if (put_user(bios_cyl, (u16 *) &loc->cylinders)) return -EFAULT;			if (put_user((unsigned)drive->part[MINOR(inode->i_rdev)&PARTN_MASK].start_sect,				(unsigned long *) &loc->start)) return -EFAULT;			return 0;		}		case HDIO_GETGEO_BIG:		{			struct hd_big_geometry *loc = (struct hd_big_geometry *) arg;			if (!loc || (drive->media != ide_disk && drive->media != ide_floppy)) return -EINVAL;			if (put_user(drive->bios_head, (u8 *) &loc->heads)) return -EFAULT;			if (put_user(drive->bios_sect, (u8 *) &loc->sectors)) return -EFAULT;			if (put_user(drive->bios_cyl, (unsigned int *) &loc->cylinders)) return -EFAULT;			if (put_user((unsigned)drive->part[MINOR(inode->i_rdev)&PARTN_MASK].start_sect,				(unsigned long *) &loc->start)) return -EFAULT;			return 0;		}		case HDIO_GETGEO_BIG_RAW:		{			struct hd_big_geometry *loc = (struct hd_big_geometry *) arg;			if (!loc || (drive->media != ide_disk && drive->media != ide_floppy)) return -EINVAL;			if (put_user(drive->head, (u8 *) &loc->heads)) return -EFAULT;			if (put_user(drive->sect, (u8 *) &loc->sectors)) return -EFAULT;			if (put_user(drive->cyl, (unsigned int *) &loc->cylinders)) return -EFAULT;			if (put_user((unsigned)drive->part[MINOR(inode->i_rdev)&PARTN_MASK].start_sect,				(unsigned long *) &loc->start)) return -EFAULT;			return 0;		}	 	case BLKGETSIZE:   /* Return device size */			return put_user(drive->part[MINOR(inode->i_rdev)&PARTN_MASK].nr_sects, (unsigned long *) arg);	 	case BLKGETSIZE64:			return put_user((u64)drive->part[MINOR(inode->i_rdev)&PARTN_MASK].nr_sects << 9, (u64 *) arg);		case BLKRRPART: /* Re-read partition tables */			if (!capable(CAP_SYS_ADMIN)) return -EACCES;			return ide_revalidate_disk(inode->i_rdev);		case HDIO_OBSOLETE_IDENTITY:		case HDIO_GET_IDENTITY:			if (MINOR(inode->i_rdev) & PARTN_MASK)				return -EINVAL;			if (drive->id_read == 0)				return -ENOMSG;			if (copy_to_user((char *)arg, (char *)drive->id, (cmd == HDIO_GET_IDENTITY) ? sizeof(*drive->id) : 142))				return -EFAULT;			return 0;		case HDIO_GET_NICE:			return put_user(drive->dsc_overlap	<<	IDE_NICE_DSC_OVERLAP	|					drive->atapi_overlap	<<	IDE_NICE_ATAPI_OVERLAP	|					drive->nice0		<< 	IDE_NICE_0		|					drive->nice1		<<	IDE_NICE_1		|					drive->nice2		<<	IDE_NICE_2,					(long *) arg);#ifdef CONFIG_IDE_TASK_IOCTL		case HDIO_DRIVE_TASKFILE:		        if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO))				return -EACCES;			switch(drive->media) {				case ide_disk:					return ide_taskfile_ioctl(drive, inode, file, cmd, arg);#ifdef CONFIG_PKT_TASK_IOCTL				case ide_cdrom:				case ide_tape:				case ide_floppy:					return pkt_taskfile_ioctl(drive, inode, file, cmd, arg);#endif /* CONFIG_PKT_TASK_IOCTL */				default:					return -ENOMSG;			}#endif /* CONFIG_IDE_TASK_IOCTL */		case HDIO_DRIVE_CMD:			if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO))				return -EACCES;			return ide_cmd_ioctl(drive, inode, file, cmd, arg);		case HDIO_DRIVE_TASK:			if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO))				return -EACCES;			return ide_task_ioctl(drive, inode, file, cmd, arg);		case HDIO_SCAN_HWIF:		{			int args[3];			if (!capable(CAP_SYS_RAWIO)) return -EACCES;			if (copy_from_user(args, (void *)arg, 3 * sizeof(int)))				return -EFAULT;			if (ide_register(args[0], args[1], args[2]) == -1)				return -EIO;			return 0;		}	        case HDIO_UNREGISTER_HWIF:			if (!capable(CAP_SYS_RAWIO)) return -EACCES;			/* (arg > MAX_HWIFS) checked in function */			ide_unregister(arg);			return 0;		case HDIO_SET_NICE:			if (!capable(CAP_SYS_ADMIN)) return -EACCES;			if (arg != (arg & ((1 << IDE_NICE_DSC_OVERLAP) | (1 << IDE_NICE_1))))				return -EPERM;			drive->dsc_overlap = (arg >> IDE_NICE_DSC_OVERLAP) & 1;			if (drive->dsc_overlap && !DRIVER(drive)->supports_dsc_overlap) {				drive->dsc_overlap = 0;				return -EPERM;			}			drive->nice1 = (arg >> IDE_NICE_1) & 1;			return 0;		case HDIO_DRIVE_RESET:		{			unsigned long flags;			if (!capable(CAP_SYS_ADMIN)) return -EACCES;						/*			 *	Abort the current command on the			 *	group if there is one, taking			 *	care not to allow anything else			 *	to be queued and to die on the			 *	spot if we miss one somehow			 */			spin_lock_irqsave(&io_request_lock, flags);						DRIVER(drive)->abort(drive, "drive reset");			if(HWGROUP(drive)->handler)				BUG();							/* Ensure nothing gets queued after we			   drop the lock. Reset will clear the busy */			   			HWGROUP(drive)->busy = 1;			spin_unlock_irqrestore(&io_request_lock, flags);			(void) ide_do_reset(drive);			if (drive->suspend_reset) {/* *				APM WAKE UP todo !! *				int nogoodpower = 1; *				while(nogoodpower) { *					check_power1() or check_power2() *					nogoodpower = 0; *				}  *				HWIF(drive)->multiproc(drive); */				return ide_revalidate_disk(inode->i_rdev);			}			return 0;		}		case BLKROSET:		case BLKROGET:		case BLKFLSBUF:		case BLKSSZGET:		case BLKPG:		case BLKELVGET:		case BLKELVSET:		case BLKBSZGET:		case BLKBSZSET:			return blk_ioctl(inode->i_rdev, cmd, arg);		case HDIO_GET_BUSSTATE:			if (!capable(CAP_SYS_ADMIN))				return -EACCES;			if (put_user(HWIF(drive)->bus_state, (long *)arg))				return -EFAULT;			return 0;		case HDIO_SET_BUSSTATE:			if (!capable(CAP_SYS_ADMIN))				return -EACCES;			if (HWIF(drive)->busproc)				return HWIF(drive)->busproc(drive, (int)arg);			return -EOPNOTSUPP;		default:			return DRIVER(drive)->ioctl(drive, inode, file, cmd, arg);			return -EPERM;	}}static int ide_check_media_change (kdev_t i_rdev){	ide_drive_t *drive;	if ((drive = get_info_ptr(i_rdev)) == NULL)		return -ENODEV;	return DRIVER(drive)->media_change(drive);}/* * stridx() returns the offset of c within s, * or -1 if c is '\0' or not found within s. */static int __init stridx (const char *s, char c){	char *i = strchr(s, c);	return (i && c) ? i - s : -1;}/* * match_parm() does parsing for ide_setup(): * * 1. the first char of s must be '='. * 2. if the remainder matches one of the supplied keywords, *     the index (1 based) of the keyword is negated and returned. * 3. if the remainder is a series of no more than max_vals numbers *     separated by commas, the numbers are saved in vals[] and a *     count of how many were saved is returned.  Base10 is assumed, *     and base16 is allowed when prefixed with "0x". * 4. otherwise, zero is returned. */static int __init match_parm (char *s, const char *keywords[], int vals[], int max_vals){	static const char *decimal = "0123456789";	static const char *hex = "0123456789abcdef";	int i, n;	if (*s++ == '=') {		/*		 * Try matching against the supplied keywords,		 * and return -(index+1) if we match one		 */		if (keywords != NULL) {			for (i = 0; *keywords != NULL; ++i) {				if (!strcmp(s, *keywords++))					return -(i+1);			}		}		/*		 * Look for a series of no more than "max_vals"		 * numeric values separated by commas, in base10,		 * or base16 when prefixed with "0x".		 * Return a count of how many were found.		 */		for (n = 0; (i = stridx(decimal, *s)) >= 0;) {			vals[n] = i;			while ((i = stridx(decimal, *++s)) >= 0)				vals[n] = (vals[n] * 10) + i;			if (*s == 'x' && !vals[n]) {				while ((i = stridx(hex, *++s)) >= 0)					vals[n] = (vals[n] * 0x10) + i;			}			if (++n == max_vals)				break;			if (*s == ',' || *s == ';')				++s;		}		if (!*s)			return n;	}	return 0;	/* zero = nothing matched */}/* * ide_setup() gets called VERY EARLY during initialization, * to handle kernel "command line" strings beginning with "hdx=" * or "ide".  Here is the complete set currently supported: * * "hdx="  is recognized for all "x" from "a" to "h", such as "hdc". * "idex=" is recognized for all "x" from "0" to "3", such as "ide1". * * "hdx=noprobe"	: drive may be present, but do not probe for it * "hdx=none"		: drive is NOT present, ignore cmos and do not probe * "hdx=nowerr"		: ignore the WRERR_STAT bit on this drive * "hdx=cdrom"		: drive is present, and is a cdrom drive * "hdx=cyl,head,sect"	: disk drive is present, with specified geometry

⌨️ 快捷键说明

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