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

📄 sc1200.c

📁 ep9315平台下硬盘驱动的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * linux/drivers/ide/pci/sc1200.c		Version 0.91	28-Jan-2003 * * Copyright (C) 2000-2002		Mark Lord <mlord@pobox.com> * May be copied or modified under the terms of the GNU General Public License * * Development of this chipset driver was funded * by the nice folks at National Semiconductor. * * Documentation: *	Available from National Semiconductor */#include <linux/config.h>#include <linux/module.h>#include <linux/types.h>#include <linux/kernel.h>#include <linux/delay.h>#include <linux/timer.h>#include <linux/mm.h>#include <linux/ioport.h>#include <linux/blkdev.h>#include <linux/hdreg.h>#include <linux/interrupt.h>#include <linux/pci.h>#include <linux/init.h>#include <linux/ide.h>#include <linux/pm.h>#include <asm/io.h>#include <asm/irq.h>#include "ide_modes.h"#include "sc1200.h"#define DISPLAY_SC1200_TIMINGS#if defined(DISPLAY_SC1200_TIMINGS) && defined(CONFIG_PROC_FS)#include <linux/stat.h>#include <linux/proc_fs.h>static int sc1200_get_info(char *, char **, off_t, int);extern int (*sc1200_display_info)(char *, char **, off_t, int); /* ide-proc.c */extern char *ide_media_verbose(ide_drive_t *);static u8 sc1200_proc = 0;#define SC1200_REV_A	0x00#define SC1200_REV_B1	0x01#define SC1200_REV_B3	0x02#define SC1200_REV_C1	0x03#define SC1200_REV_D1	0x04#define PCI_CLK_33	0x00#define PCI_CLK_48	0x01#define PCI_CLK_66	0x02#define PCI_CLK_33A	0x03static unsigned short sc1200_get_pci_clock (void){	unsigned char chip_id, silicon_revision;	unsigned int pci_clock;	/*	 * Check the silicon revision, as not all versions of the chip	 * have the register with the fast PCI bus timings.	 */	chip_id = inb (0x903c);	silicon_revision = inb (0x903d);	// Read the fast pci clock frequency	if (chip_id == 0x04 && silicon_revision < SC1200_REV_B1) {		pci_clock = PCI_CLK_33;	} else {		// check clock generator configuration (cfcc)		// the clock is in bits 8 and 9 of this word		pci_clock = inw (0x901e);		pci_clock >>= 8;		pci_clock &= 0x03;		if (pci_clock == PCI_CLK_33A)			pci_clock = PCI_CLK_33;	}	return pci_clock;}static struct pci_dev *bmide_dev;static int sc1200_get_info (char *buffer, char **addr, off_t offset, int count){	char *p = buffer;	unsigned long bibma = pci_resource_start(bmide_dev, 4);	int len;	u8  c0 = 0, c1 = 0;	/*	 * at that point bibma+0x2 et bibma+0xa are byte registers	 * to investigate:	 */	c0 = inb_p(bibma + 0x02);	c1 = inb_p(bibma + 0x0a);	p += sprintf(p, "\n                               National SCx200 Chipset.\n");	p += sprintf(p, "--------------- Primary Channel ---------------- Secondary Channel -------------\n");	p += sprintf(p, "                %sabled                         %sabled\n",			(c0&0x80) ? "dis" : " en",			(c1&0x80) ? "dis" : " en");	p += sprintf(p, "--------------- drive0 --------- drive1 -------- drive0 ---------- drive1 ------\n");	p += sprintf(p, "DMA enabled:    %s              %s             %s               %s\n",			(c0&0x20) ? "yes" : "no ", (c0&0x40) ? "yes" : "no ",			(c1&0x20) ? "yes" : "no ", (c1&0x40) ? "yes" : "no " );	p += sprintf(p, "UDMA\n");	p += sprintf(p, "DMA\n");	p += sprintf(p, "PIO\n");	len = (p - buffer) - offset;	*addr = buffer + offset;		return len > count ? count : len;}#endif /* DISPLAY_SC1200_TIMINGS && CONFIG_PROC_FS */extern char *ide_xfer_verbose (byte xfer_rate);/* * Set a new transfer mode at the drive */int sc1200_set_xfer_mode (ide_drive_t *drive, byte mode){	printk("%s: sc1200_set_xfer_mode(%s)\n", drive->name, ide_xfer_verbose(mode));	return ide_config_drive_speed(drive, mode);}/* * Here are the standard PIO mode 0-4 timings for each "format". * Format-0 uses fast data reg timings, with slower command reg timings. * Format-1 uses fast timings for all registers, but won't work with all drives. */static const unsigned int sc1200_pio_timings[4][5] =	{{0x00009172, 0x00012171, 0x00020080, 0x00032010, 0x00040010},	// format0  33Mhz	 {0xd1329172, 0x71212171, 0x30200080, 0x20102010, 0x00100010},	// format1, 33Mhz	 {0xfaa3f4f3, 0xc23232b2, 0x513101c1, 0x31213121, 0x10211021},	// format1, 48Mhz	 {0xfff4fff4, 0xf35353d3, 0x814102f1, 0x42314231, 0x11311131}};	// format1, 66Mhz/* * After chip reset, the PIO timings are set to 0x00009172, which is not valid. *///#define SC1200_BAD_PIO(timings) (((timings)&~0x80000000)==0x00009172)static int sc1200_autoselect_dma_mode (ide_drive_t *drive){	int			udma_ok = 1, mode = 0;	ide_hwif_t		*hwif = HWIF(drive);	int			unit = drive->select.b.unit;	ide_drive_t		*mate = &hwif->drives[unit^1];	struct hd_driveid	*id = drive->id;	/*	 * The SC1200 specifies that two drives sharing a cable cannot	 * mix UDMA/MDMA.  It has to be one or the other, for the pair,	 * though different timings can still be chosen for each drive.	 * We could set the appropriate timing bits on the fly,	 * but that might be a bit confusing.  So, for now we statically	 * handle this requirement by looking at our mate drive to see	 * what it is capable of, before choosing a mode for our own drive.	 */	if (mate->present) {		struct hd_driveid *mateid = mate->id;		if ((mateid->capability & 1) && !hwif->ide_dma_bad_drive(mate)) {			if ((mateid->field_valid & 4) && (mateid->dma_ultra & 7))				udma_ok = 1;			else if ((mateid->field_valid & 2) && (mateid->dma_mword & 7))				udma_ok = 0;			else				udma_ok = 1;		}	}	/*	 * Now see what the current drive is capable of,	 * selecting UDMA only if the mate said it was ok.	 */	if ((id->capability & 1) && hwif->autodma && !hwif->ide_dma_bad_drive(drive)) {		if (udma_ok && (id->field_valid & 4) && (id->dma_ultra & 7)) {			if      (id->dma_ultra & 4)				mode = XFER_UDMA_2;			else if (id->dma_ultra & 2)				mode = XFER_UDMA_1;			else if (id->dma_ultra & 1)				mode = XFER_UDMA_0;		}		if (!mode && (id->field_valid & 2) && (id->dma_mword & 7)) {			if      (id->dma_mword & 4)				mode = XFER_MW_DMA_2;			else if (id->dma_mword & 2)				mode = XFER_MW_DMA_1;			else if (id->dma_mword & 1)				mode = XFER_MW_DMA_0;		}	}	return mode;}/* * sc1200_config_dma2() handles selection/setting of DMA/UDMA modes * for both the chipset and drive. */static int sc1200_config_dma2 (ide_drive_t *drive, int mode){	ide_hwif_t		*hwif = HWIF(drive);	int			unit = drive->select.b.unit;	unsigned int		reg, timings;	unsigned short		pci_clock;	unsigned int		basereg = hwif->channel ? 0x50 : 0x40;	/*	 * Default to DMA-off in case we run into trouble here.	 */	hwif->ide_dma_off_quietly(drive);			/* turn off DMA while we fiddle */	outb(inb(hwif->dma_base+2)&~(unit?0x40:0x20), hwif->dma_base+2); /* clear DMA_capable bit */	/*	 * Tell the drive to switch to the new mode; abort on failure.	 */	if (!mode || sc1200_set_xfer_mode(drive, mode)) {		printk("SC1200: set xfer mode failure\n");		return 1;	/* failure */	}	pci_clock = sc1200_get_pci_clock();	/*	 * Now tune the chipset to match the drive:	 *	 * Note that each DMA mode has several timings associated with it.	 * The correct timing depends on the fast PCI clock freq.	 */	timings = 0;	switch (mode) {		case XFER_UDMA_0:			switch (pci_clock) {				case PCI_CLK_33:	timings = 0x00921250;	break;				case PCI_CLK_48:	timings = 0x00932470;	break;				case PCI_CLK_66:	timings = 0x009436a1;	break;			}			break;		case XFER_UDMA_1:			switch (pci_clock) {				case PCI_CLK_33:	timings = 0x00911140;	break;				case PCI_CLK_48:	timings = 0x00922260;	break;				case PCI_CLK_66:	timings = 0x00933481;	break;			}			break;		case XFER_UDMA_2:			switch (pci_clock) {				case PCI_CLK_33:	timings = 0x00911030;	break;				case PCI_CLK_48:	timings = 0x00922140;	break;				case PCI_CLK_66:	timings = 0x00923261;	break;			}			break;		case XFER_MW_DMA_0:			switch (pci_clock) {				case PCI_CLK_33:	timings = 0x00077771;	break;				case PCI_CLK_48:	timings = 0x000bbbb2;	break;				case PCI_CLK_66:	timings = 0x000ffff3;	break;			}			break;		case XFER_MW_DMA_1:			switch (pci_clock) {				case PCI_CLK_33:	timings = 0x00012121;	break;				case PCI_CLK_48:	timings = 0x00024241;	break;				case PCI_CLK_66:	timings = 0x00035352;	break;			}			break;		case XFER_MW_DMA_2:			switch (pci_clock) {				case PCI_CLK_33:	timings = 0x00002020;	break;				case PCI_CLK_48:	timings = 0x00013131;	break;				case PCI_CLK_66:	timings = 0x00015151;	break;			}			break;	}	if (timings == 0) {		printk("%s: sc1200_config_dma: huh? mode=%02x clk=%x \n", drive->name, mode, pci_clock);		return 1;	/* failure */	}	if (unit == 0) {			/* are we configuring drive0? */		pci_read_config_dword(hwif->pci_dev, basereg+4, &reg);		timings |= reg & 0x80000000;	/* preserve PIO format bit */		pci_write_config_dword(hwif->pci_dev, basereg+4, timings);	} else {		pci_write_config_dword(hwif->pci_dev, basereg+12, timings);	}	outb(inb(hwif->dma_base+2)|(unit?0x40:0x20), hwif->dma_base+2);	/* set DMA_capable bit */	/*	 * Finally, turn DMA on in software, and exit.	 */	return hwif->ide_dma_on(drive);	/* success */

⌨️ 快捷键说明

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