📄 ide.c
字号:
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 + -