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

📄 ide.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
	ide_hwif_t *hwif = HWIF(drive);	struct request rq;	struct request_pm_state rqpm;	ide_task_t args;	int ret;	/* Call ACPI _GTM only once */	if (!(drive->dn % 2))		ide_acpi_get_timing(hwif);	memset(&rq, 0, sizeof(rq));	memset(&rqpm, 0, sizeof(rqpm));	memset(&args, 0, sizeof(args));	rq.cmd_type = REQ_TYPE_PM_SUSPEND;	rq.special = &args;	rq.data = &rqpm;	rqpm.pm_step = ide_pm_state_start_suspend;	if (mesg.event == PM_EVENT_PRETHAW)		mesg.event = PM_EVENT_FREEZE;	rqpm.pm_state = mesg.event;	ret = ide_do_drive_cmd(drive, &rq, ide_wait);	/* only call ACPI _PS3 after both drivers are suspended */	if (!ret && (((drive->dn % 2) && hwif->drives[0].present		 && hwif->drives[1].present)		 || !hwif->drives[0].present		 || !hwif->drives[1].present))		ide_acpi_set_state(hwif, 0);	return ret;}static int generic_ide_resume(struct device *dev){	ide_drive_t *drive = dev->driver_data;	ide_hwif_t *hwif = HWIF(drive);	struct request rq;	struct request_pm_state rqpm;	ide_task_t args;	int err;	/* Call ACPI _STM only once */	if (!(drive->dn % 2)) {		ide_acpi_set_state(hwif, 1);		ide_acpi_push_timing(hwif);	}	ide_acpi_exec_tfs(drive);	memset(&rq, 0, sizeof(rq));	memset(&rqpm, 0, sizeof(rqpm));	memset(&args, 0, sizeof(args));	rq.cmd_type = REQ_TYPE_PM_RESUME;	rq.special = &args;	rq.data = &rqpm;	rqpm.pm_step = ide_pm_state_start_resume;	rqpm.pm_state = PM_EVENT_ON;	err = ide_do_drive_cmd(drive, &rq, ide_head_wait);	if (err == 0 && dev->driver) {		ide_driver_t *drv = to_ide_driver(dev->driver);		if (drv->resume)			drv->resume(drive);	}	return err;}int generic_ide_ioctl(ide_drive_t *drive, struct file *file, struct block_device *bdev,			unsigned int cmd, unsigned long arg){	unsigned long flags;	ide_driver_t *drv;	void __user *p = (void __user *)arg;	int err = 0, (*setfunc)(ide_drive_t *, int);	u8 *val;	switch (cmd) {	case HDIO_GET_32BIT:	    val = &drive->io_32bit;	 goto read_val;	case HDIO_GET_KEEPSETTINGS: val = &drive->keep_settings; goto read_val;	case HDIO_GET_UNMASKINTR:   val = &drive->unmask;	 goto read_val;	case HDIO_GET_DMA:	    val = &drive->using_dma;	 goto read_val;	case HDIO_SET_32BIT:	    setfunc = set_io_32bit;	 goto set_val;	case HDIO_SET_KEEPSETTINGS: setfunc = set_ksettings;	 goto set_val;	case HDIO_SET_PIO_MODE:	    setfunc = set_pio_mode;	 goto set_val;	case HDIO_SET_UNMASKINTR:   setfunc = set_unmaskirq;	 goto set_val;	case HDIO_SET_DMA:	    setfunc = set_using_dma;	 goto set_val;	}	switch (cmd) {		case HDIO_OBSOLETE_IDENTITY:		case HDIO_GET_IDENTITY:			if (bdev != bdev->bd_contains)				return -EINVAL;			if (drive->id_read == 0)				return -ENOMSG;			if (copy_to_user(p, 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 __user *) 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, cmd, arg);				default:					return -ENOMSG;			}#endif /* CONFIG_IDE_TASK_IOCTL */		case HDIO_DRIVE_CMD:			if (!capable(CAP_SYS_RAWIO))				return -EACCES;			return ide_cmd_ioctl(drive, cmd, arg);		case HDIO_DRIVE_TASK:			if (!capable(CAP_SYS_RAWIO))				return -EACCES;			return ide_task_ioctl(drive, cmd, arg);		case HDIO_SCAN_HWIF:		{			hw_regs_t hw;			int args[3];			if (!capable(CAP_SYS_RAWIO)) return -EACCES;			if (copy_from_user(args, p, 3 * sizeof(int)))				return -EFAULT;			memset(&hw, 0, sizeof(hw));			ide_init_hwif_ports(&hw, (unsigned long) args[0],					    (unsigned long) args[1], NULL);			hw.irq = args[2];			if (ide_register_hw(&hw, NULL, 0, NULL) == -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;			drv = *(ide_driver_t **)bdev->bd_disk->private_data;			if (drive->dsc_overlap && !drv->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(&ide_lock, flags);			if (HWGROUP(drive)->resetting) {				spin_unlock_irqrestore(&ide_lock, flags);				return -EBUSY;			}			ide_abort(drive, "drive reset");			BUG_ON(HWGROUP(drive)->handler);							/* Ensure nothing gets queued after we			   drop the lock. Reset will clear the busy */		   			HWGROUP(drive)->busy = 1;			spin_unlock_irqrestore(&ide_lock, flags);			(void) ide_do_reset(drive);			return 0;		}		case HDIO_GET_BUSSTATE:			if (!capable(CAP_SYS_ADMIN))				return -EACCES;			if (put_user(HWIF(drive)->bus_state, (long __user *)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 -EINVAL;	}read_val:	mutex_lock(&ide_setting_mtx);	spin_lock_irqsave(&ide_lock, flags);	err = *val;	spin_unlock_irqrestore(&ide_lock, flags);	mutex_unlock(&ide_setting_mtx);	return err >= 0 ? put_user(err, (long __user *)arg) : err;set_val:	if (bdev != bdev->bd_contains)		err = -EINVAL;	else {		if (!capable(CAP_SYS_ADMIN))			err = -EACCES;		else {			mutex_lock(&ide_setting_mtx);			err = setfunc(drive, arg);			mutex_unlock(&ide_setting_mtx);		}	}	return err;}EXPORT_SYMBOL(generic_ide_ioctl);/* * 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 */}#ifdef CONFIG_BLK_DEV_ALI14XXextern int probe_ali14xx;extern int ali14xx_init(void);#endif#ifdef CONFIG_BLK_DEV_UMC8672extern int probe_umc8672;extern int umc8672_init(void);#endif#ifdef CONFIG_BLK_DEV_DTC2278extern int probe_dtc2278;extern int dtc2278_init(void);#endif#ifdef CONFIG_BLK_DEV_HT6560Bextern int probe_ht6560b;extern int ht6560b_init(void);#endif#ifdef CONFIG_BLK_DEV_QD65XXextern int probe_qd65xx;extern int qd65xx_init(void);#endifstatic int __initdata is_chipset_set[MAX_HWIFS];/* * ide_setup() gets called VERY EARLY during initialization, * to handle kernel "command line" strings beginning with "hdx=" or "ide". * * Remember to update Documentation/ide.txt if you change something here. */static int __init ide_setup(char *s){	int i, vals[3];	ide_hwif_t *hwif;	ide_drive_t *drive;	unsigned int hw, unit;	const char max_drive = 'a' + ((MAX_HWIFS * MAX_DRIVES) - 1);	const char max_hwif  = '0' + (MAX_HWIFS - 1);		if (strncmp(s,"hd",2) == 0 && s[2] == '=')	/* hd= is for hd.c   */		return 0;				/* driver and not us */	if (strncmp(s,"ide",3) && strncmp(s,"idebus",6) && strncmp(s,"hd",2))		return 0;	printk(KERN_INFO "ide_setup: %s", s);	init_ide_data ();#ifdef CONFIG_BLK_DEV_IDEDOUBLER	if (!strcmp(s, "ide=doubler")) {		extern int ide_doubler;		printk(" : Enabled support for IDE doublers\n");		ide_doubler = 1;		return 1;	}#endif /* CONFIG_BLK_DEV_IDEDOUBLER */	if (!strcmp(s, "ide=nodma")) {		printk(" : Prevented DMA\n");		noautodma = 1;		goto obsolete_option;	}#ifdef CONFIG_IDEPCI_PCIBUS_ORDER	if (!strcmp(s, "ide=reverse")) {		ide_scan_direction = 1;		printk(" : Enabled support for IDE inverse scan order.\n");		return 1;	}#endif#ifdef CONFIG_BLK_DEV_IDEACPI	if (!strcmp(s, "ide=noacpi")) {		//printk(" : Disable IDE ACPI support.\n");		ide_noacpi = 1;		return 1;	}	if (!strcmp(s, "ide=acpigtf")) {		//printk(" : Enable IDE ACPI _GTF support.\n");		ide_noacpitfs = 0;		return 1;	}	if (!strcmp(s, "ide=acpionboot")) {		//printk(" : Call IDE ACPI methods on boot.\n");		ide_noacpionboot = 0;		return 1;	}#endif /* CONFIG_BLK_DEV_IDEACPI */	/*	 * Look for drive options:  "hdx="	 */	if (s[0] == 'h' && s[1] == 'd' && s[2] >= 'a' && s[2] <= max_drive) {		const char *hd_words[] = {			"none", "noprobe", "nowerr", "cdrom", "nodma",			"autotune", "noautotune", "minus8", "swapdata", "bswap",			"noflush", "remap", "remap63", "scsi", NULL };		unit = s[2] - 'a';		hw   = unit / MAX_DRIVES;		unit = unit % MAX_DRIVES;		hwif = &ide_hwifs[hw];		drive = &hwif->drives[unit];		if (strncmp(s + 4, "ide-", 4) == 0) {			strlcpy(drive->driver_req, s + 4, sizeof(drive->driver_req));			goto done;		}		switch (match_parm(&s[3], hd_words, vals, 3)) {			case -1: /* "none" */			case -2: /* "noprobe" */				drive->noprobe = 1;				goto done;			case -3: /* "nowerr" */				drive->bad_wstat = BAD_R_STAT;				hwif->noprobe = 0;				goto done;			case -4: /* "cdrom" */				drive->present = 1;				drive->media = ide_cdrom;				/* an ATAPI device ignores DRDY */				drive->ready_stat = 0;				hwif->noprobe = 0;				goto done;			case -5: /* nodma */				drive->nodma = 1;				goto done;			case -6: /* "autotune" */				drive->autotune = IDE_TUNE_AUTO;				goto obsolete_option;			case -7: /* "noautotune" */				drive->autotune = IDE_TUNE_NOAUTO;				goto obsolete_option;			case -9: /* "swapdata" */			case -10: /* "bswap" */				drive->bswap = 1;				goto done;			case -11: /* noflush */				drive->noflush = 1;				goto done;			case -12: /* "remap" */				drive->remap_0_to_1 = 1;				goto done;			case -13: /* "remap63" */				drive->sect0 = 63;				goto done;			case -14: /* "scsi" */				drive->scsi = 1;				goto done;			case 3: /* cyl,head,sect */				drive->media	= ide_disk;				drive->ready_stat = READY_STAT;				drive->cyl	= drive->bios_cyl  = vals[0];				drive->head	= drive->bios_head = vals[1];				drive->sect	= drive->bios_sect = vals[2];				drive->present	= 1;				drive->forced_geom = 1;				hwif->noprobe = 0;				goto done;			default:				goto bad_option;		}	}

⌨️ 快捷键说明

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