static int idecs_register(unsigned long io, unsigned long ctl, unsigned long irq) { hw_regs_t hw; ide_init_hwif_ports(&hw, io, ctl, NULL); hw.irq = irq; hw.chipset = ide_pci; return ide_register_hw(&hw, NULL); }
int idecs_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; hw.chipset = ide_pci; /* this enables IRQ sharing w/ PCI irqs */ return ide_register_hw(&hw, NULL); }
static int idecs_register(unsigned long io, unsigned long ctl, unsigned long irq) { hw_regs_t hw; memset(&hw, 0, sizeof(hw)); ide_init_hwif_ports(&hw, io, ctl, NULL); hw.irq = irq; hw.chipset = ide_pci; return ide_register_hw_with_fixup(&hw, NULL, ide_undecoded_slave); }
static int idecs_register(unsigned long io, unsigned long ctl, unsigned long irq, struct pcmcia_device *handle) { hw_regs_t hw; memset(&hw, 0, sizeof(hw)); ide_init_hwif_ports(&hw, io, ctl, NULL); hw.irq = irq; hw.chipset = ide_pci; hw.dev = &handle->dev; return ide_register_hw_with_fixup(&hw, 0, NULL, ide_undecoded_slave); }
static int __devinit delkin_cb_probe (struct pci_dev *dev, const struct pci_device_id *id) { unsigned long base; hw_regs_t hw; ide_hwif_t *hwif = NULL; ide_drive_t *drive; int i, rc; rc = pci_enable_device(dev); if (rc) { printk(KERN_ERR "delkin_cb: pci_enable_device failed (%d)\n", rc); return rc; } rc = pci_request_regions(dev, "delkin_cb"); if (rc) { printk(KERN_ERR "delkin_cb: pci_request_regions failed (%d)\n", rc); pci_disable_device(dev); return rc; } base = pci_resource_start(dev, 0); outb(0x02, base + 0x1e); /* set nIEN to block interrupts */ inb(base + 0x17); /* read status to clear interrupts */ for (i = 0; i < sizeof(setup); ++i) { if (setup[i]) outb(setup[i], base + i); } pci_release_regions(dev); /* IDE layer handles regions itself */ memset(&hw, 0, sizeof(hw)); ide_init_hwif_ports(&hw, (ide_ioreg_t)(base + 0x10), (ide_ioreg_t)(base + 0x1e), NULL); hw.irq = dev->irq; hw.chipset = ide_pci; /* this enables IRQ sharing */ rc = ide_register_hw(&hw, &hwif); if (rc < 0) /* ide_register_hw likes to be invoked twice (buggy) */ rc = ide_register_hw(&hw, &hwif); if (rc < 0) { printk(KERN_ERR "delkin_cb: ide_register_hw failed (%d)\n", rc); pci_disable_device(dev); return -ENODEV; } MOD_INC_USE_COUNT; pci_set_drvdata(dev, hwif); hwif->pci_dev = dev; drive = &hwif->drives[0]; if (drive->present) { drive->id->csfo = 0; /* workaround for idedisk_open bug */ drive->io_32bit = 1; drive->unmask = 1; } return 0; }
static void init_hwif_default(ide_hwif_t *hwif, unsigned int index) { hw_regs_t hw; memset(&hw, 0, sizeof(hw_regs_t)); ide_init_hwif_ports(&hw, ide_default_io_base(index), 0, &hwif->irq); memcpy(&hwif->hw, &hw, sizeof(hw)); memcpy(hwif->io_ports, hw.io_ports, sizeof(hw.io_ports)); hwif->noprobe = !hwif->io_ports[IDE_DATA_OFFSET]; #ifdef CONFIG_BLK_DEV_HD if (hwif->io_ports[IDE_DATA_OFFSET] == HD_DATA) hwif->noprobe = 1; /* may be overridden by ide_setup() */ #endif }
/* init_pdc4030: Test for presence of a Promise caching controller card. Returns: 0 if no Promise card present at this io_base 1 if Promise card found */ int init_pdc4030 (void) { ide_startstop_t startstop; ide_hwif_t *hwif = hwif_required; ide_drive_t *drive; ide_hwif_t *second_hwif; struct dc_ident ident; int i; if (!hwif) return 0; drive = &hwif->drives[0]; second_hwif = &ide_hwifs[hwif->index+1]; if(hwif->chipset == ide_pdc4030) /* we've already been found ! */ return 1; if(IN_BYTE(IDE_NSECTOR_REG) == 0xFF || IN_BYTE(IDE_SECTOR_REG) == 0xFF) { return 0; } OUT_BYTE(0x08,IDE_CONTROL_REG); if(pdc4030_cmd(drive,PROMISE_GET_CONFIG)) { return 0; } if(ide_wait_stat(&startstop,drive,DATA_READY,BAD_W_STAT,WAIT_DRQ)) { printk("%s: Failed Promise read config!\n",hwif->name); return 0; } ide_input_data(drive,&ident,SECTOR_WORDS); if(ident.id[1] != 'P' || ident.id[0] != 'T') { return 0; } printk("%s: Promise caching controller, ",hwif->name); switch(ident.type) { case 0x43: printk("DC4030VL-2, "); break; case 0x41: printk("DC4030VL-1, "); break; case 0x40: printk("DC4030VL, "); break; default: printk("unknown - type 0x%02x - please report!\n" ,ident.type); return 0; } printk("%dKB cache, ",(int)ident.cache_mem); switch(ident.irq) { case 0x00: hwif->irq = 14; break; case 0x01: hwif->irq = 12; break; default: hwif->irq = 15; break; } printk("on IRQ %d\n",hwif->irq); hwif->chipset = second_hwif->chipset = ide_pdc4030; hwif->mate = second_hwif; second_hwif->mate = hwif; second_hwif->channel = 1; hwif->selectproc = second_hwif->selectproc = &promise_selectproc; /* Shift the remaining interfaces down by one */ for (i=MAX_HWIFS-1 ; i > hwif->index+1 ; i--) { ide_hwif_t *h = &ide_hwifs[i]; printk("Shifting i/f %d values to i/f %d\n",i-1,i); ide_init_hwif_ports(h->io_ports, (h-1)->io_ports[IDE_DATA_OFFSET], NULL); h->io_ports[IDE_CONTROL_OFFSET] = (h-1)->io_ports[IDE_CONTROL_OFFSET]; h->noprobe = (h-1)->noprobe; } ide_init_hwif_ports(second_hwif->io_ports, hwif->io_ports[IDE_DATA_OFFSET], NULL); second_hwif->io_ports[IDE_CONTROL_OFFSET] = hwif->io_ports[IDE_CONTROL_OFFSET]; second_hwif->irq = hwif->irq; for (i=0; i<2 ; i++) { hwif->drives[i].io_32bit = 3; second_hwif->drives[i].io_32bit = 3; if(!ident.current_tm[i+2].cyl) second_hwif->drives[i].noprobe=1; } return 1; }
/* * 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; return 1; } #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", "minus5", "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 -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; } } if (s[0] != 'i' || s[1] != 'd' || s[2] != 'e') goto bad_option; /* * Look for bus speed option: "idebus=" */ if (s[3] == 'b' && s[4] == 'u' && s[5] == 's') { if (match_parm(&s[6], NULL, vals, 1) != 1) goto bad_option; if (vals[0] >= 20 && vals[0] <= 66) { idebus_parameter = vals[0]; } else printk(" -- BAD BUS SPEED! Expected value from 20 to 66"); goto done; } /* * Look for interface options: "idex=" */ if (s[3] >= '0' && s[3] <= max_hwif) { /* * Be VERY CAREFUL changing this: note hardcoded indexes below * (-8, -9, -10) are reserved to ease the hardcoding. */ static const char *ide_words[] = { "noprobe", "serialize", "minus3", "minus4", "reset", "dma", "ata66", "minus8", "minus9", "minus10", "four", "qd65xx", "ht6560b", "cmd640_vlb", "dtc2278", "umc8672", "ali14xx", NULL }; hw = s[3] - '0'; hwif = &ide_hwifs[hw]; i = match_parm(&s[4], ide_words, vals, 3); /* * Cryptic check to ensure chipset not already set for hwif. * Note: we can't depend on hwif->chipset here. */ if ((i >= -18 && i <= -11) || (i > 0 && i <= 3)) { /* chipset already specified */ if (is_chipset_set[hw]) goto bad_option; if (i > -18 && i <= -11) { /* these drivers are for "ide0=" only */ if (hw != 0) goto bad_hwif; /* chipset already specified for 2nd port */ if (is_chipset_set[hw+1]) goto bad_option; } is_chipset_set[hw] = 1; printk("\n"); } switch (i) { #ifdef CONFIG_BLK_DEV_ALI14XX case -17: /* "ali14xx" */ probe_ali14xx = 1; goto done; #endif #ifdef CONFIG_BLK_DEV_UMC8672 case -16: /* "umc8672" */ probe_umc8672 = 1; goto done; #endif #ifdef CONFIG_BLK_DEV_DTC2278 case -15: /* "dtc2278" */ probe_dtc2278 = 1; goto done; #endif #ifdef CONFIG_BLK_DEV_CMD640 case -14: /* "cmd640_vlb" */ { extern int cmd640_vlb; /* flag for cmd640.c */ cmd640_vlb = 1; goto done; } #endif #ifdef CONFIG_BLK_DEV_HT6560B case -13: /* "ht6560b" */ probe_ht6560b = 1; goto done; #endif #ifdef CONFIG_BLK_DEV_QD65XX case -12: /* "qd65xx" */ probe_qd65xx = 1; goto done; #endif #ifdef CONFIG_BLK_DEV_4DRIVES case -11: /* "four" drives on one set of ports */ { ide_hwif_t *mate = &ide_hwifs[hw^1]; mate->drives[0].select.all ^= 0x20; mate->drives[1].select.all ^= 0x20; hwif->chipset = mate->chipset = ide_4drives; mate->irq = hwif->irq; memcpy(mate->io_ports, hwif->io_ports, sizeof(hwif->io_ports)); hwif->mate = mate; mate->mate = hwif; hwif->serialized = mate->serialized = 1; goto obsolete_option; } #endif /* CONFIG_BLK_DEV_4DRIVES */ case -10: /* minus10 */ case -9: /* minus9 */ case -8: /* minus8 */ case -4: case -3: goto bad_option; case -7: /* ata66 */ #ifdef CONFIG_BLK_DEV_IDEPCI hwif->udma_four = 1; goto obsolete_option; #else goto bad_hwif; #endif case -6: /* dma */ hwif->autodma = 1; goto obsolete_option; case -5: /* "reset" */ hwif->reset = 1; goto obsolete_option; case -2: /* "serialize" */ hwif->mate = &ide_hwifs[hw^1]; hwif->mate->mate = hwif; hwif->serialized = hwif->mate->serialized = 1; goto obsolete_option; case -1: /* "noprobe" */ hwif->noprobe = 1; goto done; case 1: /* base */ vals[1] = vals[0] + 0x206; /* default ctl */ case 2: /* base,ctl */ vals[2] = 0; /* default irq = probe for it */ case 3: /* base,ctl,irq */ hwif->hw.irq = vals[2]; ide_init_hwif_ports(&hwif->hw, (unsigned long) vals[0], (unsigned long) vals[1], &hwif->irq); memcpy(hwif->io_ports, hwif->hw.io_ports, sizeof(hwif->io_ports)); hwif->irq = vals[2]; hwif->noprobe = 0; hwif->chipset = ide_forced; goto obsolete_option; case 0: goto bad_option; default: printk(" -- SUPPORT NOT CONFIGURED IN THIS KERNEL\n"); return 1; } } bad_option: printk(" -- BAD OPTION\n"); return 1; obsolete_option: printk(" -- OBSOLETE OPTION, WILL BE REMOVED SOON!\n"); return 1; bad_hwif: printk("-- NOT SUPPORTED ON ide%d", hw); done: printk("\n"); return 1; }
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, 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 CDROMEJECT: case CDROMCLOSETRAY: return scsi_cmd_ioctl(file, bdev->bd_disk, cmd, p); 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: down(&ide_setting_sem); spin_lock_irqsave(&ide_lock, flags); err = *val; spin_unlock_irqrestore(&ide_lock, flags); up(&ide_setting_sem); 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 { down(&ide_setting_sem); err = setfunc(drive, arg); up(&ide_setting_sem); } } return err; }