⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pmac.c

📁 优龙2410linux2.6.8内核源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
			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 + -