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

📄 hpt366.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 4 页
字号:
}static int hpt370_ide_dma_end (ide_drive_t *drive){	ide_hwif_t *hwif	= HWIF(drive);	u8 dma_stat		= hwif->INB(hwif->dma_status);	if (dma_stat & 0x01) {		/* wait a little */		udelay(20);		dma_stat = hwif->INB(hwif->dma_status);	}	if ((dma_stat & 0x01) != 0) 		/* fallthrough */		(void) HWIF(drive)->ide_dma_timeout(drive);	return __ide_dma_end(drive);}static void hpt370_lostirq_timeout (ide_drive_t *drive){	ide_hwif_t *hwif	= HWIF(drive);	u8 bfifo = 0, reginfo	= hwif->channel ? 0x56 : 0x52;	u8 dma_stat = 0, dma_cmd = 0;	pci_read_config_byte(HWIF(drive)->pci_dev, reginfo, &bfifo);	printk(KERN_DEBUG "%s: %d bytes in FIFO\n", drive->name, bfifo);	hpt370_clear_engine(drive);	/* get dma command mode */	dma_cmd = hwif->INB(hwif->dma_command);	/* stop dma */	hwif->OUTB(dma_cmd & ~0x1, hwif->dma_command);	dma_stat = hwif->INB(hwif->dma_status);	/* clear errors */	hwif->OUTB(dma_stat | 0x6, hwif->dma_status);}static int hpt370_ide_dma_timeout (ide_drive_t *drive){	hpt370_lostirq_timeout(drive);	hpt370_clear_engine(drive);	return __ide_dma_timeout(drive);}static int hpt370_ide_dma_lostirq (ide_drive_t *drive){	hpt370_lostirq_timeout(drive);	hpt370_clear_engine(drive);	return __ide_dma_lostirq(drive);}/* returns 1 if DMA IRQ issued, 0 otherwise */static int hpt374_ide_dma_test_irq(ide_drive_t *drive){	ide_hwif_t *hwif	= HWIF(drive);	u16 bfifo		= 0;	u8 reginfo		= hwif->channel ? 0x56 : 0x52;	u8 dma_stat;	pci_read_config_word(hwif->pci_dev, reginfo, &bfifo);	if (bfifo & 0x1FF) {//		printk("%s: %d bytes in FIFO\n", drive->name, bfifo);		return 0;	}	dma_stat = hwif->INB(hwif->dma_status);	/* return 1 if INTR asserted */	if ((dma_stat & 4) == 4)		return 1;	if (!drive->waiting_for_dma)		printk(KERN_WARNING "%s: (%s) called while not waiting\n",				drive->name, __FUNCTION__);	return 0;}static int hpt374_ide_dma_end (ide_drive_t *drive){	struct pci_dev *dev	= HWIF(drive)->pci_dev;	ide_hwif_t *hwif	= HWIF(drive);	u8 msc_stat = 0, mscreg	= hwif->channel ? 0x54 : 0x50;	u8 bwsr_stat = 0, bwsr_mask = hwif->channel ? 0x02 : 0x01;	pci_read_config_byte(dev, 0x6a, &bwsr_stat);	pci_read_config_byte(dev, mscreg, &msc_stat);	if ((bwsr_stat & bwsr_mask) == bwsr_mask)		pci_write_config_byte(dev, mscreg, msc_stat|0x30);	return __ide_dma_end(drive);}/** *	hpt372n_set_clock	-	perform clock switching dance *	@drive: Drive to switch *	@mode: Switching mode (0x21 for write, 0x23 otherwise) * *	Switch the DPLL clock on the HPT372N devices. This is a *	right mess. */ static void hpt372n_set_clock(ide_drive_t *drive, int mode){	ide_hwif_t *hwif	= HWIF(drive);		/* FIXME: should we check for DMA active and BUG() */	/* Tristate the bus */	outb(0x80, hwif->dma_base+0x73);	outb(0x80, hwif->dma_base+0x77);		/* Switch clock and reset channels */	outb(mode, hwif->dma_base+0x7B);	outb(0xC0, hwif->dma_base+0x79);		/* Reset state machines */	outb(0x37, hwif->dma_base+0x70);	outb(0x37, hwif->dma_base+0x74);		/* Complete reset */	outb(0x00, hwif->dma_base+0x79);		/* Reconnect channels to bus */	outb(0x00, hwif->dma_base+0x73);	outb(0x00, hwif->dma_base+0x77);}/** *	hpt372n_rw_disk		-	prepare for I/O *	@drive: drive for command *	@rq: block request structure * *	This is called when a disk I/O is issued to the 372N. *	We need it because of the clock switching. */static void hpt372n_rw_disk(ide_drive_t *drive, struct request *rq){	ide_hwif_t *hwif = drive->hwif;	int wantclock;	wantclock = rq_data_dir(rq) ? 0x23 : 0x21;	if (hwif->config_data != wantclock) {		hpt372n_set_clock(drive, wantclock);		hwif->config_data = wantclock;	}}/* * 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. */static void hpt3xx_reset (ide_drive_t *drive){}static int hpt3xx_tristate (ide_drive_t * drive, int state){	ide_hwif_t *hwif	= HWIF(drive);	struct pci_dev *dev	= hwif->pci_dev;	u8 reg59h = 0, reset	= (hwif->channel) ? 0x80 : 0x40;	u8 regXXh = 0, state_reg= (hwif->channel) ? 0x57 : 0x53;	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	= drive->hwif;	struct pci_dev *dev	= hwif->pci_dev;	u8 tristate = 0, resetmask = 0, bus_reg = 0;	u16 tri_reg;	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(dev, tristate, &tri_reg);	pci_read_config_byte(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(dev, 0x59, bus_reg);	pci_write_config_word(dev, tristate, tri_reg);	return 0;}static void __devinit hpt366_clocking(ide_hwif_t *hwif){	u32 reg1	= 0;	struct hpt_info *info = ide_get_hwifdata(hwif);	pci_read_config_dword(hwif->pci_dev, 0x40, &reg1);	/* detect bus speed by looking at control reg timing: */	switch((reg1 >> 8) & 7) {		case 5:			info->speed = forty_base_hpt366;			break;		case 9:			info->speed = twenty_five_base_hpt366;			break;		case 7:		default:			info->speed = thirty_three_base_hpt366;			break;	}}static void __devinit hpt37x_clocking(ide_hwif_t *hwif){	struct hpt_info *info = ide_get_hwifdata(hwif);	struct pci_dev *dev = hwif->pci_dev;	int adjust, i;	u16 freq;	u32 pll;	u8 reg5bh;		/*	 * default to pci clock. make sure MA15/16 are set to output	 * to prevent drives having problems with 40-pin cables. Needed	 * for some drives such as IBM-DTLA which will not enter ready	 * state on reset when PDIAG is a input.	 *	 * ToDo: should we set 0x21 when using PLL mode ?	 */	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	 *	 * Todo. For non x86 should probably check the dword is	 * set to 0xABCDExxx indicating the BIOS saved f_CNT	 */	pci_read_config_word(dev, 0x78, &freq);	freq &= 0x1FF;		/*	 * The 372N uses different PCI clock information and has	 * some other complications	 *	On PCI33 timing we must clock switch	 *	On PCI66 timing we must NOT use the PCI clock	 *	 * Currently we always set up the PLL for the 372N	 */	 	if(info->flags & IS_372N)	{		printk(KERN_INFO "hpt: HPT372N detected, using 372N timing.\n");		if(freq < 0x55)			pll = F_LOW_PCI_33;		else if(freq < 0x70)			pll = F_LOW_PCI_40;		else if(freq < 0x7F)			pll = F_LOW_PCI_50;		else			pll = F_LOW_PCI_66;					printk(KERN_INFO "FREQ: %d PLL: %d\n", freq, pll);					/* We always use the pll not the PCI clock on 372N */	}	else	{		if(freq < 0x9C)			pll = F_LOW_PCI_33;		else if(freq < 0xb0)			pll = F_LOW_PCI_40;		else if(freq <0xc8)			pll = F_LOW_PCI_50;		else			pll = F_LOW_PCI_66;			if (pll == F_LOW_PCI_33) {			if (info->revision >= 8)				info->speed = thirty_three_base_hpt374;			else if (info->revision >= 5)				info->speed = thirty_three_base_hpt372;			else if (info->revision >= 4)				info->speed = thirty_three_base_hpt370a;			else				info->speed = thirty_three_base_hpt370;			printk(KERN_DEBUG "HPT37X: using 33MHz PCI clock\n");		} else if (pll == F_LOW_PCI_40) {			/* Unsupported */		} else if (pll == F_LOW_PCI_50) {			if (info->revision >= 8)				info->speed = fifty_base_hpt370a;			else if (info->revision >= 5)				info->speed = fifty_base_hpt372;			else if (info->revision >= 4)				info->speed = fifty_base_hpt370a;			else				info->speed = fifty_base_hpt370a;			printk(KERN_DEBUG "HPT37X: using 50MHz PCI clock\n");		} else {			if (info->revision >= 8) {				printk(KERN_ERR "HPT37x: 66MHz timings are not supported.\n");			}			else if (info->revision >= 5)				info->speed = sixty_six_base_hpt372;			else if (info->revision >= 4)				info->speed = sixty_six_base_hpt370a;			else				info->speed = sixty_six_base_hpt370;			printk(KERN_DEBUG "HPT37X: 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.	 *	 * ToDo: Use 66MHz PLL when ATA133 devices are present on a	 * 372 device so we can get ATA133 support	 */	if (info->speed)		goto init_hpt37X_done;	info->flags |= PLL_MODE;		/*	 * FIXME: make this work correctly, esp with 372N as per	 * reference driver code.	 *	 * 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);				if (info->revision >= 8)					info->speed = fifty_base_hpt370a;				else if (info->revision >= 5)					info->speed = fifty_base_hpt372;				else if (info->revision >= 4)					info->speed = fifty_base_hpt370a;				else					info->speed = fifty_base_hpt370a;				printk("HPT37X: using 50MHz internal PLL\n");				goto init_hpt37X_done;			}		}pll_recal:		if (adjust & 1)			pll -= (adjust >> 1);		else			pll += (adjust >> 1);	} init_hpt37X_done:	if (!info->speed)		printk(KERN_ERR "HPT37X%s: unknown bus timing [%d %d].\n",			(info->flags & IS_372N)?"N":"", pll, freq);	/* reset state engine */

⌨️ 快捷键说明

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