📄 pmac.c
字号:
unsigned int value, value2 = 0; switch(pmif->kind) { case controller_sh_ata6: value = 0x0a820c97; value2 = 0x00033031; break; case controller_un_ata6: case controller_k2_ata6: value = 0x08618a92; value2 = 0x00002921; break; case controller_kl_ata4: value = 0x0008438c; break; case controller_kl_ata3: value = 0x00084526; break; case controller_heathrow: case controller_ohare: default: value = 0x00074526; break; } pmif->timings[0] = pmif->timings[1] = value; pmif->timings[2] = pmif->timings[3] = value2;}unsigned longpmac_ide_get_base(int index){ return pmac_ide[index].regbase;}intpmac_ide_check_base(unsigned long base){ int ix; for (ix = 0; ix < MAX_HWIFS; ++ix) if (base == pmac_ide[ix].regbase) return ix; return -1;}intpmac_ide_get_irq(unsigned long base){ int ix; for (ix = 0; ix < MAX_HWIFS; ++ix) if (base == pmac_ide[ix].regbase) return pmac_ide[ix].irq; return 0;}static int ide_majors[] = { 3, 22, 33, 34, 56, 57 };dev_t __initpmac_find_ide_boot(char *bootdevice, int n){ int i; /* * Look through the list of IDE interfaces for this one. */ for (i = 0; i < pmac_ide_count; ++i) { char *name; if (!pmac_ide[i].node || !pmac_ide[i].node->full_name) continue; name = pmac_ide[i].node->full_name; if (memcmp(name, bootdevice, n) == 0 && name[n] == 0) { /* XXX should cope with the 2nd drive as well... */ return MKDEV(ide_majors[i], 0); } } return 0;}/* Suspend call back, should be called after the child devices * have actually been suspended */static intpmac_ide_do_suspend(ide_hwif_t *hwif){ pmac_ide_hwif_t *pmif = (pmac_ide_hwif_t *)hwif->hwif_data; /* We clear the timings */ pmif->timings[0] = 0; pmif->timings[1] = 0; #ifdef CONFIG_BLK_DEV_IDE_PMAC_BLINK /* Note: This code will be called for every hwif, thus we'll * try several time to stop the LED blinker timer, but that * should be harmless */ if (pmu_ide_blink_enabled) { unsigned long flags; /* Make sure we don't hit the PMU blink */ spin_lock_irqsave(&pmu_blink_lock, flags); if (pmu_blink_ledstate) del_timer(&pmu_blink_timer); pmu_blink_ledstate = 0; spin_unlock_irqrestore(&pmu_blink_lock, flags); }#endif /* CONFIG_BLK_DEV_IDE_PMAC_BLINK */ disable_irq(pmif->irq); /* The media bay will handle itself just fine */ if (pmif->mediabay) return 0; /* Kauai has bus control FCRs directly here */ if (pmif->kauai_fcr) { u32 fcr = readl(pmif->kauai_fcr); fcr &= ~(KAUAI_FCR_UATA_RESET_N | KAUAI_FCR_UATA_ENABLE); writel(fcr, pmif->kauai_fcr); } /* Disable the bus on older machines and the cell on kauai */ ppc_md.feature_call(PMAC_FTR_IDE_ENABLE, pmif->node, pmif->aapl_bus_id, 0); return 0;}/* Resume call back, should be called before the child devices * are resumed */static intpmac_ide_do_resume(ide_hwif_t *hwif){ pmac_ide_hwif_t *pmif = (pmac_ide_hwif_t *)hwif->hwif_data; /* Hard reset & re-enable controller (do we really need to reset ? -BenH) */ if (!pmif->mediabay) { ppc_md.feature_call(PMAC_FTR_IDE_RESET, pmif->node, pmif->aapl_bus_id, 1); ppc_md.feature_call(PMAC_FTR_IDE_ENABLE, pmif->node, pmif->aapl_bus_id, 1); msleep(10); ppc_md.feature_call(PMAC_FTR_IDE_RESET, pmif->node, pmif->aapl_bus_id, 0); /* Kauai has it different */ if (pmif->kauai_fcr) { u32 fcr = readl(pmif->kauai_fcr); fcr |= KAUAI_FCR_UATA_RESET_N | KAUAI_FCR_UATA_ENABLE; writel(fcr, pmif->kauai_fcr); } msleep(jiffies_to_msecs(IDE_WAKEUP_DELAY)); } /* Sanitize drive timings */ sanitize_timings(pmif); enable_irq(pmif->irq); return 0;}/* * Setup, register & probe an IDE channel driven by this driver, this is * called by one of the 2 probe functions (macio or PCI). Note that a channel * that ends up beeing free of any device is not kept around by this driver * (it is kept in 2.4). This introduce an interface numbering change on some * rare machines unfortunately, but it's better this way. */static intpmac_ide_setup_device(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif){ struct device_node *np = pmif->node; int *bidp; pmif->cable_80 = 0; pmif->broken_dma = pmif->broken_dma_warn = 0; if (device_is_compatible(np, "shasta-ata")) pmif->kind = controller_sh_ata6; else if (device_is_compatible(np, "kauai-ata")) pmif->kind = controller_un_ata6; else if (device_is_compatible(np, "K2-UATA")) pmif->kind = controller_k2_ata6; else if (device_is_compatible(np, "keylargo-ata")) { if (strcmp(np->name, "ata-4") == 0) pmif->kind = controller_kl_ata4; else pmif->kind = controller_kl_ata3; } else if (device_is_compatible(np, "heathrow-ata")) pmif->kind = controller_heathrow; else { pmif->kind = controller_ohare; pmif->broken_dma = 1; } bidp = (int *)get_property(np, "AAPL,bus-id", NULL); pmif->aapl_bus_id = bidp ? *bidp : 0; /* Get cable type from device-tree */ if (pmif->kind == controller_kl_ata4 || pmif->kind == controller_un_ata6 || pmif->kind == controller_k2_ata6 || pmif->kind == controller_sh_ata6) { char* cable = get_property(np, "cable-type", NULL); if (cable && !strncmp(cable, "80-", 3)) pmif->cable_80 = 1; } /* G5's seem to have incorrect cable type in device-tree. Let's assume * they have a 80 conductor cable, this seem to be always the case unless * the user mucked around */ if (device_is_compatible(np, "K2-UATA") || device_is_compatible(np, "shasta-ata")) pmif->cable_80 = 1; /* On Kauai-type controllers, we make sure the FCR is correct */ if (pmif->kauai_fcr) writel(KAUAI_FCR_UATA_MAGIC | KAUAI_FCR_UATA_RESET_N | KAUAI_FCR_UATA_ENABLE, pmif->kauai_fcr); pmif->mediabay = 0; /* Make sure we have sane timings */ sanitize_timings(pmif);#ifndef CONFIG_PPC64 /* XXX FIXME: Media bay stuff need re-organizing */ if (np->parent && np->parent->name && strcasecmp(np->parent->name, "media-bay") == 0) {#ifdef CONFIG_PMAC_MEDIABAY media_bay_set_ide_infos(np->parent, pmif->regbase, pmif->irq, hwif->index);#endif /* CONFIG_PMAC_MEDIABAY */ pmif->mediabay = 1; if (!bidp) pmif->aapl_bus_id = 1; } else if (pmif->kind == controller_ohare) { /* The code below is having trouble on some ohare machines * (timing related ?). Until I can put my hand on one of these * units, I keep the old way */ ppc_md.feature_call(PMAC_FTR_IDE_ENABLE, np, 0, 1); } else#endif { /* This is necessary to enable IDE when net-booting */ ppc_md.feature_call(PMAC_FTR_IDE_RESET, np, pmif->aapl_bus_id, 1); ppc_md.feature_call(PMAC_FTR_IDE_ENABLE, np, pmif->aapl_bus_id, 1); msleep(10); ppc_md.feature_call(PMAC_FTR_IDE_RESET, np, pmif->aapl_bus_id, 0); msleep(jiffies_to_msecs(IDE_WAKEUP_DELAY)); } /* Setup MMIO ops */ default_hwif_mmiops(hwif); hwif->OUTBSYNC = pmac_outbsync; /* Tell common code _not_ to mess with resources */ hwif->mmio = 2; hwif->hwif_data = pmif; pmac_ide_init_hwif_ports(&hwif->hw, pmif->regbase, 0, &hwif->irq); memcpy(hwif->io_ports, hwif->hw.io_ports, sizeof(hwif->io_ports)); hwif->chipset = ide_pmac; hwif->noprobe = !hwif->io_ports[IDE_DATA_OFFSET] || pmif->mediabay; hwif->hold = pmif->mediabay; hwif->udma_four = pmif->cable_80; hwif->drives[0].unmask = 1; hwif->drives[1].unmask = 1; hwif->tuneproc = pmac_ide_tuneproc; if (pmif->kind == controller_un_ata6 || pmif->kind == controller_k2_ata6 || pmif->kind == controller_sh_ata6) hwif->selectproc = pmac_ide_kauai_selectproc; else hwif->selectproc = pmac_ide_selectproc; hwif->speedproc = pmac_ide_tune_chipset;#ifdef CONFIG_BLK_DEV_IDE_PMAC_BLINK pmu_ide_blink_enabled = pmu_hd_blink_init(); if (pmu_ide_blink_enabled) hwif->led_act = pmu_hd_kick_blink;#endif printk(KERN_INFO "ide%d: Found Apple %s controller, bus ID %d%s, irq %d\n", hwif->index, model_name[pmif->kind], pmif->aapl_bus_id, pmif->mediabay ? " (mediabay)" : "", hwif->irq); #ifdef CONFIG_PMAC_MEDIABAY if (pmif->mediabay && check_media_bay_by_base(pmif->regbase, MB_CD) == 0) hwif->noprobe = 0;#endif /* CONFIG_PMAC_MEDIABAY */ hwif->sg_max_nents = MAX_DCMDS;#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC /* has a DBDMA controller channel */ if (pmif->dma_regs) pmac_ide_setup_dma(pmif, hwif);#endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */ /* We probe the hwif now */ probe_hwif_init(hwif); return 0;}/* * Attach to a macio probed interface */static int __devinitpmac_ide_macio_attach(struct macio_dev *mdev, const struct of_device_id *match){ void __iomem *base; unsigned long regbase; int irq; ide_hwif_t *hwif; pmac_ide_hwif_t *pmif; int i, rc; i = 0; while (i < MAX_HWIFS && (ide_hwifs[i].io_ports[IDE_DATA_OFFSET] != 0 || pmac_ide[i].node != NULL)) ++i; if (i >= MAX_HWIFS) { printk(KERN_ERR "ide-pmac: MacIO interface attach with no slot\n"); printk(KERN_ERR " %s\n", mdev->ofdev.node->full_name); return -ENODEV; } pmif = &pmac_ide[i]; hwif = &ide_hwifs[i]; if (macio_resource_count(mdev) == 0) { printk(KERN_WARNING "ide%d: no address for %s\n", i, mdev->ofdev.node->full_name); return -ENXIO; } /* Request memory resource for IO ports */ if (macio_request_resource(mdev, 0, "ide-pmac (ports)")) { printk(KERN_ERR "ide%d: can't request mmio resource !\n", i); return -EBUSY; } /* XXX This is bogus. Should be fixed in the registry by checking * the kind of host interrupt controller, a bit like gatwick * fixes in irq.c. That works well enough for the single case * where that happens though... */ if (macio_irq_count(mdev) == 0) { printk(KERN_WARNING "ide%d: no intrs for device %s, using 13\n", i, mdev->ofdev.node->full_name); irq = 13; } else irq = macio_irq(mdev, 0); base = ioremap(macio_resource_start(mdev, 0), 0x400); regbase = (unsigned long) base; hwif->pci_dev = mdev->bus->pdev; hwif->gendev.parent = &mdev->ofdev.dev; pmif->mdev = mdev; pmif->node = mdev->ofdev.node; pmif->regbase = regbase; pmif->irq = irq; pmif->kauai_fcr = NULL;#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC if (macio_resource_count(mdev) >= 2) { if (macio_request_resource(mdev, 1, "ide-pmac (dma)")) printk(KERN_WARNING "ide%d: can't request DMA resource !\n", i); else pmif->dma_regs = ioremap(macio_resource_start(mdev, 1), 0x1000); } else pmif->dma_regs = NULL;#endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */ dev_set_drvdata(&mdev->ofdev.dev, hwif); rc = pmac_ide_setup_device(pmif, hwif); if (rc != 0) { /* The inteface is released to the common IDE layer */ dev_set_drvdata(&mdev->ofdev.dev, NULL); iounmap(base); if (pmif->dma_regs) iounmap(pmif->dma_regs); memset(pmif, 0, sizeof(*pmif)); macio_release_resource(mdev, 0); if (pmif->dma_regs) macio_release_resource(mdev, 1); } return rc;}static intpmac_ide_macio_suspend(struct macio_dev *mdev, pm_message_t state){ ide_hwif_t *hwif = (ide_hwif_t *)dev_get_drvdata(&mdev->ofdev.dev); int rc = 0; if (state.event != mdev->ofdev.dev.power.power_state.event && state.event >= PM_EVENT_SUSPEND) { rc = pmac_ide_do_suspend(hwif); if (rc == 0) mdev->ofdev.dev.power.power_state = state; } return rc;}static intpmac_ide_macio_resume(struct macio_dev *mdev){ ide_hwif_t *hwif = (ide_hwif_t *)dev_get_drvdata(&mdev->ofdev.dev); int rc = 0; if (mdev->ofdev.dev.power.power_state.event != PM_EVENT_ON) { rc = pmac_ide_do_resume(hwif); if (rc == 0) mdev->ofdev.dev.power.power_state = PMSG_ON; } return rc;}/* * Attach to a PCI probed interface */static int __devinitpmac_ide_pci_attach(struct pci_dev *pdev, const struct pci_device_id *id){ ide_hwif_t *hwif; struct device_node *np; pmac_ide_hwif_t *pmif; void __iomem *base; unsigned long rbase, rlen; int i, rc; np = pci_device_to_OF_node(pdev); if (np == NULL) { printk(KERN_ERR "ide-pmac: cannot find MacIO node for Kauai ATA interface\n"); return -ENODEV; } i = 0; while (i < MAX_HWIFS && (ide_hwifs[i].io_ports[IDE_DATA_OFFSET] != 0 || pmac_ide[i].node != NULL)) ++i; if (i >= MAX_HWIFS) { printk(KERN_ERR "ide-pmac: PCI interface attach with no slot\n"); printk(KERN_ERR " %s\n", np->full_name); return -ENODEV; } pmif = &pmac_ide[i]; hwif = &ide_hwifs[i]; if (pci_enable_device(pdev)) { printk(KERN_WARNING "ide%i: Can't enable PCI device for %s\n", i, np->full_name); return -ENXIO; } pci_set_master(pdev); if (pci_request_regions(pdev, "Kauai ATA")) { printk(KERN_ERR "ide%d: Cannot obtain PCI resources for %s\n", i, np->full_name); return -ENXIO; } hwif->pci_dev = pdev; hwif->gendev.parent = &pdev->dev; pmif->mdev = NULL; pmif->node = np; rbase = pci_resource_start(pdev, 0); rlen = pci_resource_len(pdev, 0); base = ioremap(rbase, rlen); pmif->regbase = (unsigned long) base + 0x2000;#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC pmif->dma_regs = base + 0x1000;#endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */ pmif->kauai_fcr = base; pmif->irq = pdev->irq; pci_set_drvdata(pdev, hwif); rc = pmac_ide_setup_device(pmif, hwif); if (rc != 0) { /* The inteface is released to the common IDE layer */ pci_set_drvdata(pdev, NULL); iounmap(base); memset(pmif, 0, sizeof(*pmif)); pci_release_regions(pdev); } return rc;}static intpmac_ide_pci_suspend(struct pci_dev *pdev, pm_message_t state){ ide_hwif_t *hwif = (ide_hwif_t *)pci_get_drvdata(pdev); int rc = 0; if (state.event != pdev->dev.power.power_state.event && state.event >= 2) { rc = pmac_ide_do_suspend(hwif); if (rc == 0) pdev->dev.power.power_state = state; } return rc;}static intpmac_ide_pci_resume(struct pci_dev *pdev){ ide_hwif_t *hwif = (ide_hwif_t *)pci_get_drvdata(pdev); int rc = 0; if (pdev->dev.power.power_state.event != PM_EVENT_ON) { rc = pmac_ide_do_resume(hwif); if (rc == 0) pdev->dev.power.power_state = PMSG_ON; } return rc;}static struct of_device_id pmac_ide_macio_match[] = { { .name = "IDE", }, { .name = "ATA", }, { .type = "ide", }, { .type = "ata", }, {},};static struct macio_driver pmac_ide_macio_driver = { .name = "ide-pmac", .match_table = pmac_ide_macio_match, .probe = pmac_ide_macio_attach, .suspend = pmac_ide_macio_suspend,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -