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

📄 hpt366.c

📁 at91rm9200处理器ide接口驱动程序源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
#if 0		case ide_dma_begin:		case ide_dma_end:			/* reset the chips state over and over.. */			pci_write_config_byte(HWIF(drive)->pci_dev, 0x51, 0x13);#endif			break;		case ide_dma_timeout:		default:			break;	}	return ide_dmaproc(func, drive);	/* use standard DMA stuff */}int hpt370_dmaproc (ide_dma_action_t func, ide_drive_t *drive){	ide_hwif_t *hwif = HWIF(drive);	unsigned long dma_base = hwif->dma_base;	byte regstate = hwif->channel ? 0x54 : 0x50;	byte reginfo = hwif->channel ? 0x56 : 0x52;	byte dma_stat;	switch (func) {		case ide_dma_check:			return config_drive_xfer_rate(drive);		case ide_dma_test_irq:	/* returns 1 if dma irq issued, 0 otherwise */			dma_stat = inb(dma_base+2);			return (dma_stat & 4) == 4;	/* return 1 if INTR asserted */		case ide_dma_end:			dma_stat = inb(dma_base + 2);			if (dma_stat & 0x01) {				udelay(20); /* wait a little */				dma_stat = inb(dma_base + 2);			}			if ((dma_stat & 0x01) == 0) 				break;			func = ide_dma_timeout;			/* fallthrough */		case ide_dma_timeout:		case ide_dma_lostirq:			pci_read_config_byte(hwif->pci_dev, reginfo, 					     &dma_stat); 			printk("%s: %d bytes in FIFO\n", drive->name, 			       dma_stat);			pci_write_config_byte(hwif->pci_dev, regstate, 0x37);			udelay(10);			dma_stat = inb(dma_base);			outb(dma_stat & ~0x1, dma_base); /* stop dma */			dma_stat = inb(dma_base + 2); 			outb(dma_stat | 0x6, dma_base+2); /* clear errors */			/* fallthrough */#ifdef HPT_RESET_STATE_ENGINE	        case ide_dma_begin:#endif			pci_write_config_byte(hwif->pci_dev, regstate, 0x37);			udelay(10);			break;		default:			break;	}	return ide_dmaproc(func, drive);	/* use standard DMA stuff */}#endif /* CONFIG_BLK_DEV_IDEDMA *//* * Since SUN Cobalt is attempting to do this operation, I should disclose * this has been a long time ago Thu Jul 27 16:40:57 2000 was the patch date * HOTSWAP ATA Infrastructure. */void hpt3xx_reset (ide_drive_t *drive){#if 0	unsigned long high_16	= pci_resource_start(HWIF(drive)->pci_dev, 4);	byte reset		= (HWIF(drive)->channel) ? 0x80 : 0x40;	byte reg59h		= 0;	pci_read_config_byte(HWIF(drive)->pci_dev, 0x59, &reg59h);	pci_write_config_byte(HWIF(drive)->pci_dev, 0x59, reg59h|reset);	pci_write_config_byte(HWIF(drive)->pci_dev, 0x59, reg59h);#endif}static int hpt3xx_tristate (ide_drive_t * drive, int state){	ide_hwif_t *hwif	= HWIF(drive);	struct pci_dev *dev	= hwif->pci_dev;	byte reset		= (hwif->channel) ? 0x80 : 0x40;	byte state_reg		= (hwif->channel) ? 0x57 : 0x53;	byte reg59h		= 0;	byte regXXh		= 0;	if (!hwif)		return -EINVAL;//	hwif->bus_state = state;	pci_read_config_byte(dev, 0x59, &reg59h);	pci_read_config_byte(dev, state_reg, &regXXh);	if (state) {		(void) ide_do_reset(drive);		pci_write_config_byte(dev, state_reg, regXXh|0x80);		pci_write_config_byte(dev, 0x59, reg59h|reset);	} else {		pci_write_config_byte(dev, 0x59, reg59h & ~(reset));		pci_write_config_byte(dev, state_reg, regXXh & ~(0x80));		(void) ide_do_reset(drive);	}	return 0;}/*  * set/get power state for a drive. * turning the power off does the following things: *   1) soft-reset the drive *   2) tri-states the ide bus * * when we turn things back on, we need to re-initialize things. */#define TRISTATE_BIT  0x8000static int hpt370_busproc(ide_drive_t * drive, int state){	ide_hwif_t *hwif = HWIF(drive);	byte tristate, resetmask, bus_reg;	u16 tri_reg;	if (!hwif)		return -EINVAL;	hwif->bus_state = state;	if (hwif->channel) { 		/* secondary channel */		tristate = 0x56;		resetmask = 0x80; 	} else { 		/* primary channel */		tristate = 0x52;		resetmask = 0x40;	}	/* grab status */	pci_read_config_word(hwif->pci_dev, tristate, &tri_reg);	pci_read_config_byte(hwif->pci_dev, 0x59, &bus_reg);	/* set the state. we don't set it if we don't need to do so.	 * make sure that the drive knows that it has failed if it's off */	switch (state) {	case BUSSTATE_ON:		hwif->drives[0].failures = 0;		hwif->drives[1].failures = 0;		if ((bus_reg & resetmask) == 0)			return 0;		tri_reg &= ~TRISTATE_BIT;		bus_reg &= ~resetmask;		break;	case BUSSTATE_OFF:		hwif->drives[0].failures = hwif->drives[0].max_failures + 1;		hwif->drives[1].failures = hwif->drives[1].max_failures + 1;		if ((tri_reg & TRISTATE_BIT) == 0 && (bus_reg & resetmask))			return 0;		tri_reg &= ~TRISTATE_BIT;		bus_reg |= resetmask;		break;	case BUSSTATE_TRISTATE:		hwif->drives[0].failures = hwif->drives[0].max_failures + 1;		hwif->drives[1].failures = hwif->drives[1].max_failures + 1;		if ((tri_reg & TRISTATE_BIT) && (bus_reg & resetmask))			return 0;		tri_reg |= TRISTATE_BIT;		bus_reg |= resetmask;		break;	}	pci_write_config_byte(hwif->pci_dev, 0x59, bus_reg);	pci_write_config_word(hwif->pci_dev, tristate, tri_reg);	return 0;}static void __init init_hpt370(struct pci_dev *dev){	int adjust, i;	u16 freq;	u32 pll;	byte reg5bh;	/*	 * default to pci clock. make sure MA15/16 are set to output	 * to prevent drives having problems with 40-pin cables.	 */	pci_write_config_byte(dev, 0x5b, 0x23);	/*	 * set up the PLL. we need to adjust it so that it's stable. 	 * freq = Tpll * 192 / Tpci	 */	pci_read_config_word(dev, 0x78, &freq);	freq &= 0x1FF;	if (freq < 0x9c) {		pll = F_LOW_PCI_33;		dev->sysdata = (void *) thirty_three_base_hpt370;		printk("HPT370: using 33MHz PCI clock\n");	} else if (freq < 0xb0) {		pll = F_LOW_PCI_40;	} else if (freq < 0xc8) {		pll = F_LOW_PCI_50;		dev->sysdata = (void *) fifty_base_hpt370;		printk("HPT370: using 50MHz PCI clock\n");	} else {		pll = F_LOW_PCI_66;		dev->sysdata = (void *) sixty_six_base_hpt370;		printk("HPT370: using 66MHz PCI clock\n");	}		/*	 * only try the pll if we don't have a table for the clock	 * speed that we're running at. NOTE: the internal PLL will	 * result in slow reads when using a 33MHz PCI clock. we also	 * don't like to use the PLL because it will cause glitches	 * on PRST/SRST when the HPT state engine gets reset.	 */	if (dev->sysdata) 		goto init_hpt370_done;		/*	 * adjust PLL based upon PCI clock, enable it, and wait for	 * stabilization.	 */	adjust = 0;	freq = (pll < F_LOW_PCI_50) ? 2 : 4;	while (adjust++ < 6) {		pci_write_config_dword(dev, 0x5c, (freq + pll) << 16 |				       pll | 0x100);		/* wait for clock stabilization */		for (i = 0; i < 0x50000; i++) {			pci_read_config_byte(dev, 0x5b, &reg5bh);			if (reg5bh & 0x80) {				/* spin looking for the clock to destabilize */				for (i = 0; i < 0x1000; ++i) {					pci_read_config_byte(dev, 0x5b, 							     &reg5bh);					if ((reg5bh & 0x80) == 0)						goto pll_recal;				}				pci_read_config_dword(dev, 0x5c, &pll);				pci_write_config_dword(dev, 0x5c, 						       pll & ~0x100);				pci_write_config_byte(dev, 0x5b, 0x21);				dev->sysdata = (void *) fifty_base_hpt370;				printk("HPT370: using 50MHz internal PLL\n");				goto init_hpt370_done;			}		}pll_recal:		if (adjust & 1)			pll -= (adjust >> 1);		else			pll += (adjust >> 1);	} init_hpt370_done:	/* reset state engine */	pci_write_config_byte(dev, 0x50, 0x37); 	pci_write_config_byte(dev, 0x54, 0x37); 	udelay(100);}unsigned int __init pci_init_hpt366 (struct pci_dev *dev, const char *name){	byte test = 0;	if (dev->resource[PCI_ROM_RESOURCE].start)		pci_write_config_byte(dev, PCI_ROM_ADDRESS, dev->resource[PCI_ROM_RESOURCE].start | PCI_ROM_ADDRESS_ENABLE);	pci_read_config_byte(dev, PCI_CACHE_LINE_SIZE, &test);	if (test != (L1_CACHE_BYTES / 4))		pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, (L1_CACHE_BYTES / 4));	pci_read_config_byte(dev, PCI_LATENCY_TIMER, &test);	if (test != 0x78)		pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x78);	pci_read_config_byte(dev, PCI_MIN_GNT, &test);	if (test != 0x08)		pci_write_config_byte(dev, PCI_MIN_GNT, 0x08);	pci_read_config_byte(dev, PCI_MAX_LAT, &test);	if (test != 0x08)		pci_write_config_byte(dev, PCI_MAX_LAT, 0x08);	if (pci_rev_check_hpt3xx(dev)) {		init_hpt370(dev);		hpt_devs[n_hpt_devs++] = dev;	} else {		hpt_devs[n_hpt_devs++] = dev;	}	#if defined(DISPLAY_HPT366_TIMINGS) && defined(CONFIG_PROC_FS)	if (!hpt366_proc) {		hpt366_proc = 1;		hpt366_display_info = &hpt366_get_info;	}#endif /* DISPLAY_HPT366_TIMINGS && CONFIG_PROC_FS */	return dev->irq;}unsigned int __init ata66_hpt366 (ide_hwif_t *hwif){	byte ata66	= 0;	byte regmask	= (hwif->channel) ? 0x01 : 0x02;	pci_read_config_byte(hwif->pci_dev, 0x5a, &ata66);#ifdef DEBUG	printk("HPT366: reg5ah=0x%02x ATA-%s Cable Port%d\n",		ata66, (ata66 & regmask) ? "33" : "66",		PCI_FUNC(hwif->pci_dev->devfn));#endif /* DEBUG */	return ((ata66 & regmask) ? 0 : 1);}void __init ide_init_hpt366 (ide_hwif_t *hwif){	int hpt_rev;	hwif->tuneproc	= &hpt3xx_tune_drive;	hwif->speedproc	= &hpt3xx_tune_chipset;	hwif->quirkproc	= &hpt3xx_quirkproc;	hwif->intrproc	= &hpt3xx_intrproc;	hwif->maskproc	= &hpt3xx_maskproc;#ifdef HPT_SERIALIZE_IO	/* serialize access to this device */	if (hwif->mate)		hwif->serialized = hwif->mate->serialized = 1;#endif	hpt_rev = pci_rev_check_hpt3xx(hwif->pci_dev);	if (hpt_rev) {		/* set up ioctl for power status. note: power affects both		 * drives on each channel */		hwif->busproc   = &hpt370_busproc;	}	if (pci_rev2_check_hpt3xx(hwif->pci_dev)) {		/* do nothing now but will split device types */		hwif->resetproc = &hpt3xx_reset;/* * don't do until we can parse out the cobalt box argh ... *		hwif->busproc   = &hpt3xx_tristate; */	}#ifdef CONFIG_BLK_DEV_IDEDMA	if (hwif->dma_base) {		if (hpt_rev) {			byte reg5ah = 0;			pci_read_config_byte(hwif->pci_dev, 0x5a, &reg5ah);			if (reg5ah & 0x10)	/* interrupt force enable */				pci_write_config_byte(hwif->pci_dev, 0x5a, reg5ah & ~0x10);			hwif->dmaproc = &hpt370_dmaproc;		} else {			hwif->dmaproc = &hpt366_dmaproc;		}		if (!noautodma)			hwif->autodma = 1;		else			hwif->autodma = 0;	} else {		hwif->autodma = 0;		hwif->drives[0].autotune = 1;		hwif->drives[1].autotune = 1;	}#else /* !CONFIG_BLK_DEV_IDEDMA */	hwif->drives[0].autotune = 1;	hwif->drives[1].autotune = 1;	hwif->autodma = 0;#endif /* CONFIG_BLK_DEV_IDEDMA */}void __init ide_dmacapable_hpt366 (ide_hwif_t *hwif, unsigned long dmabase){	byte masterdma = 0, slavedma = 0;	byte dma_new = 0, dma_old = inb(dmabase+2);	byte primary	= hwif->channel ? 0x4b : 0x43;	byte secondary	= hwif->channel ? 0x4f : 0x47;	unsigned long flags;	__save_flags(flags);	/* local CPU only */	__cli();		/* local CPU only */	dma_new = dma_old;	pci_read_config_byte(hwif->pci_dev, primary, &masterdma);	pci_read_config_byte(hwif->pci_dev, secondary, &slavedma);	if (masterdma & 0x30)	dma_new |= 0x20;	if (slavedma & 0x30)	dma_new |= 0x40;	if (dma_new != dma_old) outb(dma_new, dmabase+2);	__restore_flags(flags);	/* local CPU only */	ide_setup_dma(hwif, dmabase, 8);}

⌨️ 快捷键说明

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