📄 pmac.c
字号:
del_timer(&pmu_blink_timer); pmu_blink_ledstate = 0; spin_unlock_irqrestore(&pmu_blink_lock, flags); }#endif /* CONFIG_BLK_DEV_IDE_PMAC_BLINK */ /* The media bay will handle itself just fine */ if (pmif->mediabay) return 0; /* Disable the bus */ 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); msleep(jiffies_to_msecs(IDE_WAKEUP_DELAY)); } /* Sanitize drive timings */ sanitize_timings(pmif); 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, i; pmif->cable_80 = 0; pmif->broken_dma = pmif->broken_dma_warn = 0; 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) { char* cable = get_property(np, "cable-type", NULL); if (cable && !strncmp(cable, "80-", 3)) pmif->cable_80 = 1; } 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_PBOOK media_bay_set_ide_infos(np->parent, pmif->regbase, pmif->irq, hwif->index);#endif /* CONFIG_PMAC_PBOOK */ 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) 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_PBOOK if (pmif->mediabay && check_media_bay_by_base(pmif->regbase, MB_CD) == 0) hwif->noprobe = 0;#endif /* CONFIG_PMAC_PBOOK */#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); /* The code IDE code will have set hwif->present if we have devices attached, * if we don't, the discard the interface except if we are on a media bay slot */ if (!hwif->present && !pmif->mediabay) { printk(KERN_INFO "ide%d: Bus empty, interface released.\n", hwif->index); default_hwif_iops(hwif); for (i = IDE_DATA_OFFSET; i <= IDE_CONTROL_OFFSET; ++i) hwif->io_ports[i] = 0; hwif->chipset = ide_unknown; hwif->noprobe = 1; return -ENODEV; } return 0;}/* * Attach to a macio probed interface */static int __devinitpmac_ide_macio_attach(struct macio_dev *mdev, const struct of_match *match){ unsigned long base, 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 (mdev->ofdev.node->n_addrs == 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 = (unsigned long)ioremap(macio_resource_start(mdev, 0), 0x400); regbase = 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;#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 = (volatile struct dbdma_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((void *)base); if (pmif->dma_regs) iounmap((void *)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, u32 state){ ide_hwif_t *hwif = (ide_hwif_t *)dev_get_drvdata(&mdev->ofdev.dev); int rc = 0; if (state != mdev->ofdev.dev.power_state && state >= 2) { rc = pmac_ide_do_suspend(hwif); if (rc == 0) mdev->ofdev.dev.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_state != 0) { rc = pmac_ide_do_resume(hwif); if (rc == 0) mdev->ofdev.dev.power_state = 0; } 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; unsigned long 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 = (unsigned long) ioremap(rbase, rlen); pmif->regbase = base + 0x2000;#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC pmif->dma_regs = (volatile struct dbdma_regs*)(base + 0x1000);#endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */ /* We use the OF node irq mapping */ if (np->n_intrs == 0) pmif->irq = pdev->irq; else pmif->irq = np->intrs[0].line; 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((void *)base); memset(pmif, 0, sizeof(*pmif)); pci_release_regions(pdev); } return rc;}static intpmac_ide_pci_suspend(struct pci_dev *pdev, u32 state){ ide_hwif_t *hwif = (ide_hwif_t *)pci_get_drvdata(pdev); int rc = 0; if (state != pdev->dev.power_state && state >= 2) { rc = pmac_ide_do_suspend(hwif); if (rc == 0) pdev->dev.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_state != 0) { rc = pmac_ide_do_resume(hwif); if (rc == 0) pdev->dev.power_state = 0; } return rc;}static struct of_match pmac_ide_macio_match[] = { { .name = "IDE", .type = OF_ANY_MATCH, .compatible = OF_ANY_MATCH }, { .name = "ATA", .type = OF_ANY_MATCH, .compatible = OF_ANY_MATCH }, { .name = OF_ANY_MATCH, .type = "ide", .compatible = OF_ANY_MATCH }, { .name = OF_ANY_MATCH, .type = "ata", .compatible = OF_ANY_MATCH }, {},};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, .resume = pmac_ide_macio_resume,};static struct pci_device_id pmac_ide_pci_match[] = { { PCI_VENDOR_ID_APPLE, PCI_DEVIEC_ID_APPLE_UNI_N_ATA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, { PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_IPID_ATA100, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, { PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_K2_ATA100, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},};static struct pci_driver pmac_ide_pci_driver = { .name = "ide-pmac", .id_table = pmac_ide_pci_match, .probe = pmac_ide_pci_attach, .suspend = pmac_ide_pci_suspend, .resume = pmac_ide_pci_resume,};void __initpmac_ide_probe(void){ if (_machine != _MACH_Pmac) return;#ifdef CONFIG_BLK_DEV_IDE_PMAC_ATA100FIRST pci_register_driver(&pmac_ide_pci_driver); macio_register_driver(&pmac_ide_macio_driver);#else macio_register_driver(&pmac_ide_macio_driver); pci_register_driver(&pmac_ide_pci_driver);#endif }#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC/* * This is very close to the generic ide-dma version of the function except * that we don't use the fields in the hwif but our own copies for sg_table * and friends. We build & map the sglist for a given request */static int __pmacpmac_ide_build_sglist(ide_drive_t *drive, struct request *rq){ ide_hwif_t *hwif = HWIF(drive); pmac_ide_hwif_t *pmif = (pmac_ide_hwif_t *)hwif->hwif_data; struct scatterlist *sg = pmif->sg_table; int nents; if (hwif->sg_dma_active) BUG(); nents = blk_rq_map_sg(drive->queue, rq, sg); if (rq_data_dir(rq) == READ) pmif->sg_dma_direction = PCI_DMA_FROMDEVICE; else pmif->sg_dma_direction = PCI_DMA_TODEVICE; return pci_map_sg(hwif->pci_dev, sg, nents, pmif->sg_dma_direction);}/* * Same as above but for a "raw" taskfile request */static int __pmacpmac_ide_raw_build_sglist(ide_drive_t *drive, struct request *rq){ ide_hwif_t *hwif = HWIF(drive); pmac_ide_hwif_t *pmif = (pmac_ide_hwif_t *)hwif->hwif_data; struct scatterlist *sg = pmif->sg_table; int nents = 0; ide_task_t *args = rq->special; unsigned char *virt_addr = rq->buffer; int sector_count = rq->nr_sectors; if (args->command_type == IDE_DRIVE_TASK_RAW_WRITE) pmif->sg_dma_direction = PCI_DMA_TODEVICE; else pmif->sg_dma_direction = PCI_DMA_FROMDEVICE; if (sector_count > 128) { memset(&sg[nents], 0, sizeof(*sg)); sg[nents].page = virt_to_page(virt_addr); sg[nents].offset = offset_in_page(virt_addr); sg[nents].length = 128 * SECTOR_SIZE; nents++; virt_addr = virt_addr + (128 * SECTOR_SIZE); sector_count -= 128; } memset(&sg[nents], 0, sizeof(*sg)); sg[nents].page = virt_to_page(virt_addr); sg[nents].offset = offset_in_page(virt_addr); sg[nents].length = sector_count * SECTOR_SIZE; nents++; return pci_map_sg(hwif->pci_dev, sg, nents, pmif->sg_dma_direction);}/* * pmac_ide_build_dmatable builds the DBDMA command list * for a transfer and sets the DBDMA channel to point to it. */static int __pmacpmac_ide_build_dmatable(ide_drive_t *drive, struct request *rq){ struct dbdma_cmd *table; int i, count = 0; ide_hwif_t *hwif = HWIF(drive); pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)hwif->hwif_data; volatile struct dbdma_regs *dma = pmif->dma_regs; struct scatterlist *sg; int wr = (rq_data_dir(rq) == WRITE); /* DMA table is already aligned */ table = (struct dbdma_cmd *) pmif->dma_table_cpu; /* Make sure DMA controller is stopped (necessary ?) */ writel((RUN|PAUSE|FLUSH|WAKE|DEAD) << 16, &dma->control);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -