int ide_register_hw_with_fixup(hw_regs_t *hw, int initializing, ide_hwif_t **hwifp, void(*fixup)(ide_hwif_t *hwif)) { 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) continue; if ((!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(hwif, index); init_hwif_default(hwif, 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; hwif->gendev.parent = hw->dev; if (!initializing) { probe_hwif_init_with_fixup(hwif, fixup); ide_proc_register_port(hwif); } if (hwifp) *hwifp = hwif; return (initializing || hwif->present) ? index : -1; }
void ide_release(dev_link_t *link) { ide_info_t *info = link->priv; DEBUG(0, "ide_release(0x%p)\n", link); if (info->ndev) { /* FIXME: if this fails we need to queue the cleanup somehow -- need to investigate the required PCMCIA magic */ ide_unregister(info->hd); /* deal with brain dead IDE resource management */ request_region(link->io.BasePort1, link->io.NumPorts1, info->node.dev_name); if (link->io.NumPorts2) request_region(link->io.BasePort2, link->io.NumPorts2, info->node.dev_name); MOD_DEC_USE_COUNT; } info->ndev = 0; link->dev = NULL; CardServices(ReleaseConfiguration, link->handle); CardServices(ReleaseIO, link->handle, &link->io); CardServices(ReleaseIRQ, link->handle, &link->irq); link->state &= ~DEV_CONFIG; } /* ide_release */
static void ide_release(void *arg) { dev_link_t *link = arg; ide_info_t *info = link->priv; if (!(link->state & DEV_CONFIG)) return; DEBUG(0, "ide_do_release(0x%p)\n", link); if (info->ndev) { /* FIXME: if this fails we need to queue the cleanup somehow -- need to investigate the required PCMCIA magic */ ide_unregister(info->hd); MOD_DEC_USE_COUNT; } request_region(link->io.BasePort1, link->io.NumPorts1,"ide-cs"); if (link->io.NumPorts2) request_region(link->io.BasePort2, link->io.NumPorts2,"ide-cs"); info->ndev = 0; link->dev = NULL; CardServices(ReleaseConfiguration, link->handle); CardServices(ReleaseIO, link->handle, &link->io); CardServices(ReleaseIRQ, link->handle, &link->irq); link->state &= ~DEV_CONFIG; } /* ide_release */
static int idecs_register(unsigned long io, unsigned long ctl, unsigned long irq, struct pcmcia_device *handle) { ide_hwif_t *hwif; hw_regs_t hw; int i; u8 idx[4] = { 0xff, 0xff, 0xff, 0xff }; memset(&hw, 0, sizeof(hw)); ide_std_init_ports(&hw, io, ctl); hw.irq = irq; hw.chipset = ide_pci; hw.dev = &handle->dev; hwif = ide_deprecated_find_port(hw.io_ports[IDE_DATA_OFFSET]); if (hwif == NULL) return -1; i = hwif->index; if (hwif->present) ide_unregister(i, 0, 0); else if (!hwif->hold) ide_init_port_data(hwif, i); ide_init_port_hw(hwif, &hw); hwif->quirkproc = &ide_undecoded_slave; idx[0] = i; ide_device_add(idx, NULL); return hwif->present ? i : -1; }
static int __devexit plat_ide_remove(struct platform_device *pdev) { ide_hwif_t *hwif = pdev->dev.driver_data; ide_unregister(hwif); return 0; }
static void idepnp_remove(struct pnp_dev * dev) { ide_hwif_t *hwif = pnp_get_drvdata(dev); if (hwif) { ide_unregister(hwif->index); } else printk(KERN_ERR "idepnp: Unable to remove device, please report.\n"); }
static void delkin_cb_remove (struct pci_dev *dev) { ide_hwif_t *hwif = pci_get_drvdata(dev); if (hwif) ide_unregister(hwif->index); pci_disable_device(dev); }
static void idepnp_remove(struct pnp_dev *dev) { ide_hwif_t *hwif = pnp_get_drvdata(dev); ide_unregister(hwif); release_region(pnp_port_start(dev, 1), 1); release_region(pnp_port_start(dev, 0), 8); }
static void __devexit rapide_remove(struct expansion_card *ec) { ide_hwif_t *hwif = ecard_get_drvdata(ec); ecard_set_drvdata(ec, NULL); /* there must be a better way */ ide_unregister(hwif - ide_hwifs); ecard_release_resources(ec); }
static void delkin_cb_remove (struct pci_dev *dev) { ide_hwif_t *hwif = pci_get_drvdata(dev); ide_unregister(hwif); pci_release_regions(dev); pci_disable_device(dev); }
/* * This procedure runs as a kernel thread to poll the media bay * once each tick and register and unregister the IDE interface * with the IDE driver. It needs to be a thread because * ide_register can't be called from interrupt context. */ int media_bay_task(void *x) { volatile struct media_bay_info* bay; int i = 0; strcpy(current->comm, "media-bay"); for (;;) { bay = &media_bays[i]; poll_media_bay(i); if (bay->content_id != bay->previous_id) { bay->reset_timer = (bay->content_id != MB_NO) ? MB_RESET_COUNT: 0; bay->ready = 0; #ifdef CONFIG_BLK_DEV_IDE bay->cd_timer = 0; if (bay->content_id != MB_CD && bay->cd_index >= 0) { printk(KERN_DEBUG "Unregistering mb %d ide, index:%d\n", i, bay->cd_index); ide_unregister(bay->cd_index); bay->cd_index = -1; } #endif } else if (bay->reset_timer) { if (--bay->reset_timer == 0) { feature_clear(bay->dev_node, FEATURE_Mediabay_reset); bay->ready = 1; #ifdef CONFIG_BLK_DEV_IDE bay->cd_timer = 0; if (bay->content_id == MB_CD && bay->cd_base != 0) bay->cd_timer = MB_IDE_WAIT; #endif } #ifdef CONFIG_BLK_DEV_IDE } else if (bay->cd_timer && (--bay->cd_timer == 0 || MB_IDE_READY(i)) && bay->cd_index < 0) { bay->cd_timer = 0; printk(KERN_DEBUG "Registering IDE, base:0x%08lx, irq:%d\n", bay->cd_base, bay->cd_irq); printk("\n"); bay->cd_index = ide_register(bay->cd_base, 0, bay->cd_irq); if (bay->cd_index == -1) printk("\nCD-ROM badly inserted. Remove it and try again !\n"); else printk(KERN_DEBUG "media-bay %d is ide %d\n", i, bay->cd_index); #endif } bay->previous_id = bay->content_id; current->state = TASK_INTERRUPTIBLE; schedule_timeout(1); if (signal_pending(current)) return 0; i = (i+1)%media_bay_count; } }
void __exit cleanup_module (void) { int index; for (index = 0; index < MAX_HWIFS; ++index) ide_unregister(index); #ifdef CONFIG_BLK_DEV_IDEPNP pnpide_exit(); #endif proc_ide_destroy(); bus_unregister(&ide_bus_type); }
void ide_release(struct pcmcia_device *link) { ide_info_t *info = link->priv; DEBUG(0, "ide_release(0x%p)\n", link); if (info->ndev) { /* FIXME: if this fails we need to queue the cleanup somehow -- need to investigate the required PCMCIA magic */ ide_unregister(info->hd); } info->ndev = 0; pcmcia_disable_device(link); } /* ide_release */
void ide_release(u_long arg) { dev_link_t *link = (dev_link_t *)arg; ide_info_t *info = link->priv; DEBUG(0, "ide_release(0x%p)\n", link); if (info->ndev) { ide_unregister(info->hd); MOD_DEC_USE_COUNT; } info->ndev = 0; link->dev = NULL; CardServices(ReleaseConfiguration, link->handle); CardServices(ReleaseIO, link->handle, &link->io); CardServices(ReleaseIRQ, link->handle, &link->irq); link->state &= ~DEV_CONFIG; } /* ide_release */
void ide_release(dev_link_t *link) { ide_info_t *info = link->priv; DEBUG(0, "ide_release(0x%p)\n", link); if (info->ndev) { /* FIXME: if this fails we need to queue the cleanup somehow -- need to investigate the required PCMCIA magic */ ide_unregister(info->hd); } info->ndev = 0; link->dev = NULL; pcmcia_release_configuration(link->handle); pcmcia_release_io(link->handle, &link->io); pcmcia_release_irq(link->handle, &link->irq); link->state &= ~DEV_CONFIG; } /* ide_release */
static int __devinit palm_bk3710_probe(struct platform_device *pdev) { struct clk *clk; struct resource *mem, *irq; ide_hwif_t *hwif; unsigned long base, rate; int i; hw_regs_t hw; u8 idx[4] = { 0xff, 0xff, 0xff, 0xff }; clk = clk_get(&pdev->dev, "IDECLK"); if (IS_ERR(clk)) return -ENODEV; clk_enable(clk); rate = clk_get_rate(clk); ideclk_period = 1000000000UL / rate; /* Register the IDE interface with Linux ATA Interface */ memset(&hw, 0, sizeof(hw)); mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (mem == NULL) { printk(KERN_ERR "failed to get memory region resource\n"); return -ENODEV; } irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); if (irq == NULL) { printk(KERN_ERR "failed to get IRQ resource\n"); return -ENODEV; } if (request_mem_region(mem->start, mem->end - mem->start + 1, "palm_bk3710") == NULL) { printk(KERN_ERR "failed to request memory region\n"); return -EBUSY; } base = IO_ADDRESS(mem->start); /* Configure the Palm Chip controller */ palm_bk3710_chipinit((void __iomem *)base); for (i = 0; i < IDE_NR_PORTS - 2; i++) hw.io_ports[i] = base + IDE_PALM_ATA_PRI_REG_OFFSET + i; hw.io_ports[IDE_CONTROL_OFFSET] = base + IDE_PALM_ATA_PRI_CTL_OFFSET; hw.irq = irq->start; hw.chipset = ide_palm3710; hwif = ide_deprecated_find_port(hw.io_ports[IDE_DATA_OFFSET]); if (hwif == NULL) goto out; i = hwif->index; if (hwif->present) ide_unregister(i, 0, 1); else if (!hwif->hold) ide_init_port_data(hwif, i); ide_init_port_hw(hwif, &hw); hwif->fixup = NULL; hwif->tuneproc = &palm_bk3710_tune_drive; hwif->speedproc = &palm_bk3710_tune_chipset; hwif->mmio = 2; default_hwif_mmiops(hwif); if (rate >= 100000000) hwif->ultra_mask = 0x3f; /* UDMA Mode 5 */ else hwif->ultra_mask = 0x1f; /* UDMA Mode 4 */ hwif->mwdma_mask = 0x7; hwif->drives[0].autotune = 1; hwif->drives[1].autotune = 1; hwif->ide_dma_check = &palm_bk3710_config_drive_xfer_rate; hwif->udma_four = 1; if (!noautodma) hwif->autodma = 1; hwif->drives[0].autodma = hwif->drives[1].autodma = hwif->autodma; ide_setup_dma(hwif, base, 8); idx[0] = i; ide_device_add(idx); if (!hwif->present) goto out; return 0; out: printk(KERN_WARNING "Palm Chip BK3710 IDE Register Fail\n"); return -ENODEV; }
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; }