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

📄 pmac.c

📁 这个linux源代码是很全面的~基本完整了~使用c编译的~由于时间问题我没有亲自测试~但就算用来做参考资料也是非常好的
💻 C
📖 第 1 页 / 共 4 页
字号:
				continue;			}			pci_set_master(pdev);						if (pci_request_regions(pdev, "U2 IDE")) {				printk(KERN_ERR "ide-pmac: Cannot obtain PCI resources\n");				continue;			}			rbase = pci_resource_start(pdev, 0);			rlen = pci_resource_len(pdev, 0);			base = (unsigned long) ioremap(rbase, rlen);			regbase = base + 0x2000;			irq = pdev->irq;		}		/*		 * If this slot is taken (e.g. by ide-pci.c) try the next one.		 */		while (i < MAX_HWIFS		       && ide_hwifs[i].io_ports[IDE_DATA_OFFSET] != 0)			++i;		if (i >= MAX_HWIFS)			break;		pmif = &pmac_ide[i];		pmif->mapbase = base;		pmif->regbase = regbase;		pmif->irq = irq;		pmif->node = np;		pmif->cable_80 = 0;		if (device_is_compatible(np, "kauai-ata")) {			pmif->kind = controller_un_ata6;			pci_set_drvdata(pdev, pmif);		} 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;		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) {			char* cable = get_property(np, "cable-type", NULL);			if (cable && !strncmp(cable, "80-", 3))				pmif->cable_80 = 1;		}		/* Make sure we have sane timings */		sanitize_timings(pmif);		if (np->parent && np->parent->name		    && strcasecmp(np->parent->name, "media-bay") == 0) {#ifdef CONFIG_PMAC_PBOOK			media_bay_set_ide_infos(np->parent,regbase,irq,i);#endif /* CONFIG_PMAC_PBOOK */			in_bay = 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 { 			/* 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);			mdelay(10);			ppc_md.feature_call(PMAC_FTR_IDE_RESET, np, pmif->aapl_bus_id, 0);			big_delay = 1;		}		hwif = &ide_hwifs[i];		/* 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, base, 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] || in_bay;		hwif->udma_four = pmif->cable_80;		hwif->pci_dev = pdev;		hwif->drives[0].unmask = 1;		hwif->drives[1].unmask = 1;		hwif->tuneproc = pmac_ide_tuneproc;		if (pmif->kind == controller_un_ata6)			hwif->selectproc = pmac_ide_kauai_selectproc;		else			hwif->selectproc = pmac_ide_selectproc;		hwif->speedproc = pmac_ide_tune_chipset;		printk(KERN_INFO "ide%d: Found Apple %s controller, bus ID %d%s\n",			i, model_name[pmif->kind], pmif->aapl_bus_id,			in_bay ? " (mediabay)" : "");			#ifdef CONFIG_PMAC_PBOOK		if (in_bay && check_media_bay_by_base(regbase, MB_CD) == 0)			hwif->noprobe = 0;#endif /* CONFIG_PMAC_PBOOK */#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC		if (np->n_addrs >= 2 || pmif->kind == controller_un_ata6) {			/* has a DBDMA controller channel */			pmac_ide_setup_dma(np, i);		}		hwif->atapi_dma = 1;		switch(pmif->kind) {			case controller_un_ata6:				hwif->ultra_mask = pmif->cable_80 ? 0x3f : 0x07;				hwif->mwdma_mask = 0x07;				hwif->swdma_mask = 0x00;				break;			case controller_kl_ata4:				hwif->ultra_mask = pmif->cable_80 ? 0x1f : 0x07;				hwif->mwdma_mask = 0x07;				hwif->swdma_mask = 0x00;				break;			default:				hwif->ultra_mask = 0x00;				hwif->mwdma_mask = 0x07;				hwif->swdma_mask = 0x00;				break;		}	#endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */		++i;	}	pmac_ide_count = i;	if (pmac_ide_count == 0)		return;			if (big_delay)		mdelay(IDE_WAKEUP_DELAY_MS);#ifdef CONFIG_PMAC_PBOOK	pmu_register_sleep_notifier(&idepmac_sleep_notifier);#endif /* CONFIG_PMAC_PBOOK */}#ifdef CONFIG_BLK_DEV_IDEDMA_PMACstatic int __pmacpmac_ide_build_sglist(ide_hwif_t *hwif, struct request *rq, int data_dir){	pmac_ide_hwif_t *pmif = (pmac_ide_hwif_t *)hwif->hwif_data;	struct buffer_head *bh;	struct scatterlist *sg = pmif->sg_table;	unsigned long lastdataend = ~0UL;	int nents = 0;	if (hwif->sg_dma_active)		BUG();			pmif->sg_dma_direction = data_dir;	bh = rq->bh;	do {		int contig = 0;		if (bh->b_page) {			if (bh_phys(bh) == lastdataend)				contig = 1;		} else {			if ((unsigned long) bh->b_data == lastdataend)				contig = 1;		}		if (contig) {			sg[nents - 1].length += bh->b_size;			lastdataend += bh->b_size;			continue;		}		if (nents >= MAX_DCMDS)			return 0;		memset(&sg[nents], 0, sizeof(*sg));		if (bh->b_page) {			sg[nents].page = bh->b_page;			sg[nents].offset = bh_offset(bh);			lastdataend = bh_phys(bh) + bh->b_size;		} else {			if ((unsigned long) bh->b_data < PAGE_SIZE)				BUG();			sg[nents].address = bh->b_data;			lastdataend = (unsigned long) bh->b_data + bh->b_size;		}		sg[nents].length = bh->b_size;		nents++;	} while ((bh = bh->b_reqnext) != NULL);	if(nents == 0)		BUG();	return pci_map_sg(hwif->pci_dev, sg, nents, data_dir);}static int  __pmacpmac_ide_raw_build_sglist(ide_hwif_t *hwif, struct request *rq){	pmac_ide_hwif_t *pmif = (pmac_ide_hwif_t *)hwif->hwif_data;	struct scatterlist *sg = hwif->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].address = 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].address = 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, int ddir){	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;	/* 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);	while (readl(&dma->status) & RUN)		udelay(1);	/* Build sglist */	if (rq->cmd == IDE_DRIVE_TASKFILE)		pmif->sg_nents = i = pmac_ide_raw_build_sglist(hwif, rq);	else		pmif->sg_nents = i = pmac_ide_build_sglist(hwif, rq, ddir);	if (!i)		return 0;	/* Build DBDMA commands list */	sg = pmif->sg_table;	while (i && sg_dma_len(sg)) {		u32 cur_addr;		u32 cur_len;		cur_addr = sg_dma_address(sg);		cur_len = sg_dma_len(sg);		while (cur_len) {			unsigned int tc = (cur_len < 0xfe00)? cur_len: 0xfe00;			if (++count >= MAX_DCMDS) {				printk(KERN_WARNING "%s: DMA table too small\n",				       drive->name);				goto use_pio_instead;			}			st_le16(&table->command,				(ddir == PCI_DMA_TODEVICE) ? OUTPUT_MORE: INPUT_MORE);			st_le16(&table->req_count, tc);			st_le32(&table->phy_addr, cur_addr);			table->cmd_dep = 0;			table->xfer_status = 0;			table->res_count = 0;			cur_addr += tc;			cur_len -= tc;			++table;		}		sg++;		i--;	}	/* convert the last command to an input/output last command */	if (count) {		st_le16(&table[-1].command,			(ddir == PCI_DMA_TODEVICE) ? OUTPUT_LAST: INPUT_LAST);		/* add the stop command to the end of the list */		memset(table, 0, sizeof(struct dbdma_cmd));		st_le16(&table->command, DBDMA_STOP);		mb();		writel(pmif->dma_table_dma, &dma->cmdptr);		return 1;	}	printk(KERN_DEBUG "%s: empty DMA table?\n", drive->name); use_pio_instead:	pci_unmap_sg(hwif->pci_dev,		     pmif->sg_table,		     pmif->sg_nents,		     pmif->sg_dma_direction);	hwif->sg_dma_active = 0;	return 0; /* revert to PIO for this request */}/* Teardown mappings after DMA has completed.  */static void __pmacpmac_ide_destroy_dmatable (ide_drive_t *drive){	struct pci_dev *dev = HWIF(drive)->pci_dev;	pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)HWIF(drive)->hwif_data;	struct scatterlist *sg = pmif->sg_table;	int nents = pmif->sg_nents;	if (nents) {		pci_unmap_sg(dev, sg, nents, pmif->sg_dma_direction);		pmif->sg_nents = 0;		HWIF(drive)->sg_dma_active = 0;	}}/* Calculate MultiWord DMA timings */static int __pmacpmac_ide_mdma_enable(ide_drive_t *drive, u16 mode){	ide_hwif_t *hwif = HWIF(drive);	pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)hwif->hwif_data;	int drive_cycle_time;	struct hd_driveid *id = drive->id;	u32 *timings, *timings2;	u32 timing_local[2];	int ret;	/* which drive is it ? */	timings = &pmif->timings[drive->select.b.unit & 0x01];	timings2 = &pmif->timings[(drive->select.b.unit & 0x01) + 2];	/* Check if drive provide explicit cycle time */	if ((id->field_valid & 2) && (id->eide_dma_time))		drive_cycle_time = id->eide_dma_time;	else		drive_cycle_time = 0;	/* Copy timings to local image */	timing_local[0] = *timings;	timing_local[1] = *timings2;	/* Calculate controller timings */	ret = set_timings_mdma(	pmif->kind,				&timing_local[0],				&timing_local[1],				mode,				drive_cycle_time);	if (ret)		return 0;	/* Set feature on drive */    	printk(KERN_INFO "%s: Enabling MultiWord DMA %d\n", drive->name, mode & 0xf);	ret = pmac_ide_do_setfeature(drive, mode);	if (ret) {	    	printk(KERN_WARNING "%s: Failed !\n", drive->name);	    	return 0;	}	/* Apply timings to controller */	*timings = timing_local[0];	*timings2 = timing_local[1];		/* Set speed info in drive */	drive->current_speed = mode;		if (!drive->init_speed)		drive->init_speed = mode;	return 1;}/* Calculate Ultra DMA timings */static int __pmacpmac_ide_udma_enable(ide_drive_t *drive, u16 mode){	ide_hwif_t *hwif = HWIF(drive);	pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)hwif->hwif_data;	u32 *timings, *timings2;	u32 timing_local[2];	int ret;			/* which drive is it ? */	timings = &pmif->timings[drive->select.b.unit & 0x01];	timings2 = &pmif->timings[(drive->select.b.unit & 0x01) + 2];	/* Copy timings to local image */	timing_local[0] = *timings;	timing_local[1] = *timings2;		/* Calculate timings for interface */	if (pmif->kind == controller_un_ata6)		ret = set_timings_udma_ata6(	&timing_local[0],						&timing_local[1],						mode);	else		ret = set_timings_udma_ata4(&timing_local[0], mode);	if (ret)		return 0;			/* Set feature on drive */    	printk(KERN_INFO "%s: Enabling Ultra DMA %d\n", drive->name, mode & 0x0f);	ret = pmac_ide_do_setfeature(drive, mode);	if (ret) {		printk(KERN_WARNING "%s: Failed !\n", drive->name);		return 0;	}	/* Apply timings to controller */	*timings = timing_local[0];	*timings2 = timing_local[1];	/* Set speed info in drive */	drive->current_speed = mode;		if (!drive->init_speed)		drive->init_speed = mode;	return 1;}static __pmacint pmac_ide_dma_check(ide_drive_t *drive){	struct hd_driveid *id = drive->id;	ide_hwif_t *hwif = HWIF(drive);	pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)hwif->hwif_data;	int enable = 1;	int map;	drive->using_dma = 0;		if (pmif == NULL)		return 0;			if (drive->media == ide_floppy)		enable = 0;	if (((id->capability & 1) == 0) &&	    !HWIF(drive)->ide_dma_good_drive(drive))		enable = 0;	if (HWIF(drive)->ide_dma_bad_drive(drive))		enable = 0;	if (enable) {		short mode;				map = XFER_MWDMA;		if (pmif->kind == controller_kl_ata4 || pmif->kind == controller_un_ata6) {			map |= XFER_UDMA;			if (pmif->cable_80) {				map |= XFER_UDMA_66;				if (pmif->kind == controller_un_ata6)					map |= XFER_UDMA_100;			}		}		mode = ide_find_best_mode(drive, map);		if (mode & XFER_UDMA)			drive->using_dma = pmac_ide_udma_enable(drive, mode);		else if (mode & XFER_MWDMA)			drive->using_dma = pmac_ide_mdma_enable(drive, mode);		hwif->OUTB(0, IDE_CONTROL_REG);		/* Apply settings to controller */		pmac_ide_do_update_timings(drive);	}	return 0;}static int __pmacpmac_ide_dma_read (ide_drive_t *drive){	ide_hwif_t *hwif = HWIF(drive);	pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)hwif->hwif_data;	struct request *rq = HWGROUP(drive)->rq;//	ide_task_t *args = rq->special;	u8 unit = (drive->select.b.unit & 0x01);	u8 ata4;	u8 lba48 = (drive->addressing == 1) ? 1 : 0;	task_ioreg_t command = WIN_NOP;	if (pmif == NULL)		return 1;	ata4 = (pmif->kind == controller_kl_ata4);	if (!pmac_ide_build_dmatable(drive, rq, PCI_DMA_FROMDEVICE))		/* try PIO instead of DMA */		return 1;	/* Apple adds 60ns to wrDataSetup on reads */	if (ata4 && (pmif->timings[unit] & TR_66_UDMA_EN)) {		writel(pmif->timings[unit]+0x00800000UL,			(unsigned *)(IDE_DATA_REG+IDE_TIMING_CONFIG));		io_flush(readl((unsigned *)(IDE_DATA_REG + IDE_TIMING_CONFIG)));	}	drive->waiting_for_dma = 1;		if (drive->media != ide_disk)		return 0;	/* paranoia check */	if (HWGROUP(drive)->handler != NULL)	/* paranoia check */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -