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; }
static int __devinit sgiioc4_ide_setup_pci_device(struct pci_dev *dev, ide_pci_device_t * d) { unsigned long cmd_base, dma_base, irqport; unsigned long bar0, cmd_phys_base, ctl; void __iomem *virt_base; ide_hwif_t *hwif; int h; /* * Find an empty HWIF; if none available, return -ENOMEM. */ for (h = 0; h < MAX_HWIFS; ++h) { hwif = &ide_hwifs[h]; if (hwif->chipset == ide_unknown) break; } if (h == MAX_HWIFS) { printk(KERN_ERR "%s: too many IDE interfaces, no room in table\n", d->name); return -ENOMEM; } /* Get the CmdBlk and CtrlBlk Base Registers */ bar0 = pci_resource_start(dev, 0); virt_base = ioremap(bar0, pci_resource_len(dev, 0)); if (virt_base == NULL) { printk(KERN_ERR "%s: Unable to remap BAR 0 address: 0x%lx\n", d->name, bar0); return -ENOMEM; } cmd_base = (unsigned long) virt_base + IOC4_CMD_OFFSET; ctl = (unsigned long) virt_base + IOC4_CTRL_OFFSET; irqport = (unsigned long) virt_base + IOC4_INTR_OFFSET; dma_base = pci_resource_start(dev, 0) + IOC4_DMA_OFFSET; cmd_phys_base = bar0 + IOC4_CMD_OFFSET; if (!request_mem_region(cmd_phys_base, IOC4_CMD_CTL_BLK_SIZE, hwif->name)) { printk(KERN_ERR "%s : %s -- ERROR, Addresses " "0x%p to 0x%p ALREADY in use\n", __FUNCTION__, hwif->name, (void *) cmd_phys_base, (void *) cmd_phys_base + IOC4_CMD_CTL_BLK_SIZE); return -ENOMEM; } if (hwif->io_ports[IDE_DATA_OFFSET] != cmd_base) { /* Initialize the IO registers */ sgiioc4_init_hwif_ports(&hwif->hw, cmd_base, ctl, irqport); memcpy(hwif->io_ports, hwif->hw.io_ports, sizeof (hwif->io_ports)); hwif->noprobe = !hwif->io_ports[IDE_DATA_OFFSET]; } hwif->irq = dev->irq; hwif->chipset = ide_pci; hwif->pci_dev = dev; hwif->channel = 0; /* Single Channel chip */ hwif->cds = (struct ide_pci_device_s *) d; hwif->gendev.parent = &dev->dev;/* setup proper ancestral information */ /* The IOC4 uses MMIO rather than Port IO. */ default_hwif_mmiops(hwif); /* Initializing chipset IRQ Registers */ writel(0x03, (void __iomem *)(irqport + IOC4_INTR_SET * 4)); ide_init_sgiioc4(hwif); if (dma_base) ide_dma_sgiioc4(hwif, dma_base); else printk(KERN_INFO "%s: %s Bus-Master DMA disabled\n", hwif->name, d->name); if (probe_hwif_init(hwif)) return -EIO; /* Create /proc/ide entries */ ide_proc_register_port(hwif); return 0; }