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

📄 hpt366.c

📁 一个2.4.21版本的嵌入式linux内核
💻 C
📖 第 1 页 / 共 3 页
字号:
 * */static int config_chipset_for_dma (ide_drive_t *drive){	u8 speed = ide_dma_speed(drive, hpt3xx_ratemask(drive));	if (!(speed))		return 0;	(void) hpt3xx_tune_chipset(drive, speed);	return ide_dma_enable(drive);}static int hpt3xx_quirkproc (ide_drive_t *drive){	return ((int) check_in_drive_lists(drive, quirk_drives));}static void hpt3xx_intrproc (ide_drive_t *drive){	ide_hwif_t *hwif = HWIF(drive);	if (drive->quirk_list)		return;	/* drives in the quirk_list may not like intr setups/cleanups */	hwif->OUTB(drive->ctl|2, IDE_CONTROL_REG);}static void hpt3xx_maskproc (ide_drive_t *drive, int mask){	struct pci_dev *dev = HWIF(drive)->pci_dev;	if (drive->quirk_list) {		if (hpt_minimum_revision(dev,3)) {			u8 reg5a = 0;			pci_read_config_byte(dev, 0x5a, &reg5a);			if (((reg5a & 0x10) >> 4) != mask)				pci_write_config_byte(dev, 0x5a, mask ? (reg5a | 0x10) : (reg5a & ~0x10));		} else {			if (mask) {				disable_irq(HWIF(drive)->irq);			} else {				enable_irq(HWIF(drive)->irq);			}		}	} else {		if (IDE_CONTROL_REG)			HWIF(drive)->OUTB(mask ? (drive->ctl | 2) :						 (drive->ctl & ~2),						 IDE_CONTROL_REG);	}}static int hpt366_config_drive_xfer_rate (ide_drive_t *drive){	ide_hwif_t *hwif	= HWIF(drive);	struct hd_driveid *id	= drive->id;	drive->init_speed = 0;	if ((id->capability & 1) && drive->autodma) {		/* Consult the list of known "bad" drives */		if (hwif->ide_dma_bad_drive(drive))			goto fast_ata_pio;		if (id->field_valid & 4) {			if (id->dma_ultra & hwif->ultra_mask) {				/* Force if Capable UltraDMA */				int dma = config_chipset_for_dma(drive);				if ((id->field_valid & 2) && !dma)					goto try_dma_modes;			}		} else if (id->field_valid & 2) {try_dma_modes:			if (id->dma_mword & hwif->mwdma_mask) {				/* Force if Capable regular DMA modes */				if (!config_chipset_for_dma(drive))					goto no_dma_set;			}		} else if (hwif->ide_dma_good_drive(drive) &&			   (id->eide_dma_time < 150)) {			/* Consult the list of known "good" drives */			if (!config_chipset_for_dma(drive))				goto no_dma_set;		} else {			goto fast_ata_pio;		}	} else if ((id->capability & 8) || (id->field_valid & 2)) {fast_ata_pio:no_dma_set:		hpt3xx_tune_drive(drive, 5);		return hwif->ide_dma_off_quietly(drive);	}	return hwif->ide_dma_on(drive);}/* * This is specific to the HPT366 UDMA bios chipset * by HighPoint|Triones Technologies, Inc. */static int hpt366_ide_dma_lostirq (ide_drive_t *drive){	struct pci_dev *dev	= HWIF(drive)->pci_dev;	u8 reg50h = 0, reg52h = 0, reg5ah = 0;	pci_read_config_byte(dev, 0x50, &reg50h);	pci_read_config_byte(dev, 0x52, &reg52h);	pci_read_config_byte(dev, 0x5a, &reg5ah);	printk("%s: (%s)  reg50h=0x%02x, reg52h=0x%02x, reg5ah=0x%02x\n",		drive->name, __FUNCTION__, reg50h, reg52h, reg5ah);	if (reg5ah & 0x10)		pci_write_config_byte(dev, 0x5a, reg5ah & ~0x10);#if 0	/* how about we flush and reset, mmmkay? */	pci_write_config_byte(dev, 0x51, 0x1F);	/* fall through to a reset */	case ide_dma_begin:	case ide_dma_end:	/* reset the chips state over and over.. */	pci_write_config_byte(dev, 0x51, 0x13);#endif	return __ide_dma_lostirq(drive);}static void hpt370_clear_engine (ide_drive_t *drive){	u8 regstate = HWIF(drive)->channel ? 0x54 : 0x50;	pci_write_config_byte(HWIF(drive)->pci_dev, regstate, 0x37);	udelay(10);}static int hpt370_ide_dma_begin (ide_drive_t *drive){#ifdef HPT_RESET_STATE_ENGINE	hpt370_clear_engine(drive);#endif	return __ide_dma_begin(drive);}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("%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);}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+0x79);}/** *	hpt372n_rw_disk		-	wrapper for I/O *	@drive: drive for command *	@rq: block request structure *	@block: block number * *	This is called when a disk I/O is issued to the 372N instead *	of the default functionality. We need it because of the clock *	switching * */ static ide_startstop_t hpt372n_rw_disk(ide_drive_t *drive, struct request *rq, unsigned long block){	int wantclock;		if(rq_data_dir(rq) == READ)		wantclock = 0x21;	else		wantclock = 0x23;			if(HWIF(drive)->config_data != wantclock)	{		hpt372n_set_clock(drive, wantclock);		HWIF(drive)->config_data = wantclock;	}	return __ide_do_rw_disk(drive, rq, block);}/* * 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){#if 0	unsigned long high_16	= pci_resource_start(HWIF(drive)->pci_dev, 4);	u8 reset	= (HWIF(drive)->channel) ? 0x80 : 0x40;	u8 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;	u8 reg59h = 0, reset	= (hwif->channel) ? 0x80 : 0x40;	u8 regXXh = 0, state_reg= (hwif->channel) ? 0x57 : 0x53;	if (!hwif)		return -EINVAL;//	hwif->bus_state = state;	pci_read_config_byte(dev, 0x59, &reg59h);	pci_read_config_byte(dev, state_reg, &regXXh);	switch(state)	{		case BUSSTATE_ON:			(void) ide_do_reset(drive);			pci_write_config_byte(dev, state_reg, regXXh|0x80);			pci_write_config_byte(dev, 0x59, reg59h|reset);			break;		case BUSSTATE_OFF:			pci_write_config_byte(dev, 0x59, reg59h & ~(reset));			pci_write_config_byte(dev, state_reg, regXXh & ~(0x80));			(void) ide_do_reset(drive);			break;		default:			return -EINVAL;	}	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);	struct pci_dev *dev	= hwif->pci_dev;	u8 tristate = 0, resetmask = 0, bus_reg = 0;	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(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;	default:		return -EINVAL;	}	pci_write_config_byte(dev, 0x59, bus_reg);	pci_write_config_word(dev, tristate, tri_reg);	return 0;}static int __init init_hpt37x(struct pci_dev *dev){	int adjust, i;	u16 freq;	u32 pll;	u8 reg5bh;	u8 reg5ah;	unsigned long dmabase = pci_resource_start(dev, 4);	u8 did, rid;		int is_372n = 0;#if 1	pci_read_config_byte(dev, 0x5a, &reg5ah);	/* interrupt force enable */	pci_write_config_byte(dev, 0x5a, (reg5ah & ~0x10));#endif	if(dmabase)	{		did = inb(dmabase + 0x22);		rid = inb(dmabase + 0x28);			if((did == 4 && rid == 6) || (did == 5 && rid > 1))			is_372n = 1;	}			/*	 * 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(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 (hpt_minimum_revision(dev,8))				pci_set_drvdata(dev, (void *) thirty_three_base_hpt374);			else if (hpt_minimum_revision(dev,5))				pci_set_drvdata(dev, (void *) thirty_three_base_hpt372);			else if (hpt_minimum_revision(dev,4))				pci_set_drvdata(dev, (void *) thirty_three_base_hpt370a);			else				pci_set_drvdata(dev, (void *) thirty_three_base_hpt370);			printk("HPT37X: using 33MHz PCI clock\n");		} else if (pll == F_LOW_PCI_40) {		} else if (pll == F_LOW_PCI_50) {

⌨️ 快捷键说明

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