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

📄 via82cxxx.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * $Id: via82cxxx.c,v 2.1e 2000/10/03 10:01:00 vojtech Exp $ * *  Copyright (c) 2000 Vojtech Pavlik * *  Based on the work of: *	Michel Aubry *	Jeff Garzik *	Andre Hedrick * *  Sponsored by SuSE *//* * VIA vt82c586 IDE driver for Linux. Supports * *   vt82c586, vt82c586a, vt82c586b, vt82c596a, vt82c596b, vt82c686a, vt8231 * * southbridges, which can be found in * *  VIA Apollo VP, VPX, VPX/97, VP2, VP2/97, VP3, MVP3, MVP4 *  VIA Apollo Pro, Pro Plus, Pro 133, Pro 133A, ProMedia 601, ProSavage 605 *  VIA Apollo KX133, KT133 *  AMD-640, AMD-750 IronGate * * chipsets. Supports PIO 0-5, MWDMA 0-2, SWDMA 0-2 and * UDMA 0-5 (includes UDMA33, 66 and 100) modes. UDMA100 isn't possible * on any of the supported chipsets yet. * * UDMA66 and higher modes are autodetected only in case the BIOS has enabled them. * To force UDMA66, use 'ide0=ata66' or 'ide1=ata66' on the kernel command line. *//* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Should you need to contact me, the author, you can do so either by * e-mail - mail your message to <vojtech@suse.cz>, or by paper mail: * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic */#include <linux/config.h>#include <linux/types.h>#include <linux/kernel.h>#include <linux/timer.h>#include <linux/mm.h>#include <linux/ioport.h>#include <linux/interrupt.h>#include <linux/blkdev.h>#include <linux/hdreg.h>#include <linux/pci.h>#include <linux/init.h>#include <linux/delay.h>#include <linux/ide.h>#include <asm/io.h>#include "ide_modes.h"#define VIA_BM_BASE		0x20#define VIA_IDE_ENABLE		0x40#define VIA_IDE_CONFIG		0x41#define VIA_FIFO_CONFIG		0x43#define VIA_MISC_1		0x44#define VIA_MISC_2		0x45#define VIA_MISC_3		0x46#define VIA_DRIVE_TIMING	0x48#define VIA_ADDRESS_SETUP	0x4c#define VIA_UDMA_TIMING		0x50#define VIA_PRI_SECTOR_SIZE	0x60#define VIA_SEC_SECTOR_SIZE	0x68/* * VIA SouthBridge chips. */static const struct {	char *name;	unsigned short id;	unsigned char speed;} via_isa_bridges[] = {	{ "vt8231",	PCI_DEVICE_ID_VIA_8231,     XFER_UDMA_4 },	{ "vt82c686a",	PCI_DEVICE_ID_VIA_82C686,   XFER_UDMA_4 },	{ "vt82c596b",	PCI_DEVICE_ID_VIA_82C596,   XFER_UDMA_4 },	{ "vt82c596a",	PCI_DEVICE_ID_VIA_82C596,   XFER_UDMA_2 },	{ "vt82c586b",	PCI_DEVICE_ID_VIA_82C586_0, XFER_UDMA_2 },	{ "vt82c586a",	PCI_DEVICE_ID_VIA_82C586_0, XFER_UDMA_2 },	{ "vt82c586",	PCI_DEVICE_ID_VIA_82C586_0, XFER_MW_DMA_2 },	{ "Unknown SouthBridge",	0,	    XFER_UDMA_2 },};static unsigned char via_config;static unsigned char via_enabled;static unsigned int via_ata66;/* * PIO 0-5, MWDMA 0-2 and UDMA 0-5 timings (in nanoseconds). * These were taken from ATA/ATAPI-6 standard, rev 0a, except * for PIO 5, which is a nonstandard extension. * * Dilemma: 8-bit (register) PIO accesses need more relaxed timing. * Hopefully the chipset is taking care of that. If it doesn't * do so, define VIA_USE_8_BIT_TIMING to see if it helps. */#ifndef XFER_PIO_5#define XFER_PIO_5		0x0d#endifstatic const struct {	int mode;	char *name;	short setup;	/* t1 */	short active;	/* t2  or tD */	short recover;	/* t2i or tK */	short cycle;	/* t0 */	short udma;	/* t2CYCTYP/2 */} via_timing[] = {	{ XFER_UDMA_5,    "UDMA5", 25,  70,  25, 120,  20 },	{ XFER_UDMA_4,    "UDMA4", 25,  70,  25, 120,  30 },	{ XFER_UDMA_3,    "UDMA3", 25,  70,  25, 120,  45 },	{ XFER_UDMA_2,    "UDMA2", 25,  70,  25, 120,  60 },	{ XFER_UDMA_1,    "UDMA1", 25,  70,  25, 120,  80 },	{ XFER_UDMA_0,    "UDMA0", 25,  70,  25, 120, 120 },	{ XFER_MW_DMA_2,  "MDMA2", 25,  70,  25, 120,   0 },	{ XFER_MW_DMA_1,  "MDMA1", 45,  80,  50, 150,   0 },	{ XFER_MW_DMA_0,  "MDMA0", 60, 215, 215, 480,   0 },	{ XFER_SW_DMA_2,  "SDMA2", 60, 120, 120, 240,   0 },	{ XFER_SW_DMA_1,  "SDMA1", 90, 240, 240, 480,   0 },	{ XFER_SW_DMA_0,  "SDMA0",120, 480, 480, 960,   0 },	{ XFER_PIO_5,     "PIO5",  20,  50,  30, 100,   0 },	{ XFER_PIO_4,     "PIO4",  25,  70,  25, 120,   0 },	{ XFER_PIO_3,     "PIO3",  30,  80,  70, 180,   0 },#ifdef VIA_USE_8_BIT_TIMING	{ XFER_PIO_2,     "PIO2",  30, 290,  60, 330,   0 },	{ XFER_PIO_1,     "PIO1",  50, 290, 100, 383,   0 },	{ XFER_PIO_0,     "PIO0",  70, 290, 300, 600,   0 },#else	{ XFER_PIO_2,     "PIO2",  30, 100,  90, 240,   0 },	{ XFER_PIO_1,     "PIO1",  50, 125, 100, 383,   0 },	{ XFER_PIO_0,     "PIO0",  70, 165, 150, 600,   0 },#endif	{ XFER_PIO_SLOW,  "SLOW", 120, 290, 240, 960,   0 },	{ 0 }};/* * VIA /proc entry. */#ifdef CONFIG_PROC_FS#include <linux/stat.h>#include <linux/proc_fs.h>int via_proc = 0;static struct pci_dev *bmide_dev, *isa_dev;extern int (*via_display_info)(char *, char **, off_t, int); /* ide-proc.c */static char *via_fifo[] = { " 1 ", "3/4", "1/2", "1/4" };static char *via_control3[] = { "No limit", "64", "128", "192" };#define via_print(format, arg...) p += sprintf(p, format "\n" , ## arg)#define via_print_drive(name, format, arg...)\	p += sprintf(p, name); for (i = 0; i < 4; i++) p += sprintf(p, format, ## arg); p += sprintf(p, "\n");static int via_get_info(char *buffer, char **addr, off_t offset, int count){	short pci_clock, speed[4], cycle[4], setup[4], active[4], recover[4], umul[4], uen[4], udma[4];	struct pci_dev *dev = bmide_dev;	unsigned int v, u, i, base;	unsigned short c, size0, size1;	unsigned char t, c0, c1;	char *p = buffer;	via_print("----------VIA BusMastering IDE Configuration----------------");	via_print("Driver Version:                     2.1e");	pci_read_config_byte(isa_dev, PCI_REVISION_ID, &t);	via_print("South Bridge:                       VIA %s rev %#x", via_isa_bridges[via_config].name, t);	pci_read_config_word(dev, PCI_COMMAND, &c);	via_print("Command register:                   %#x", c);	pci_read_config_byte(dev, PCI_LATENCY_TIMER, &t);	via_print("Latency timer:                      %d", t);	pci_clock = system_bus_clock();	via_print("PCI clock:                          %dMHz", pci_clock);	pci_read_config_byte(dev, VIA_MISC_1, &t);	via_print("Master Read  Cycle IRDY:            %dws", (t & 64) >>6 );	via_print("Master Write Cycle IRDY:            %dws", (t & 32) >> 5 );	via_print("FIFO Output Data 1/2 Clock Advance: %s", (t & 16) ? "on" : "off" );	via_print("BM IDE Status Register Read Retry:  %s", (t & 8) ? "on" : "off" );	pci_read_config_byte(dev, VIA_MISC_3, &t);	via_print("Max DRDY Pulse Width:               %s%s", via_control3[(t & 0x03)], (t & 0x03) ? "PCI clocks" : "");	via_print("-----------------------Primary IDE-------Secondary IDE------");	via_print("Read DMA FIFO flush:   %10s%20s", (t & 0x80) ? "on" : "off", (t & 0x40) ? "on" : "off" );	via_print("End Sect. FIFO flush:  %10s%20s", (t & 0x20) ? "on" : "off", (t & 0x10) ? "on" : "off" );	pci_read_config_byte(dev, VIA_IDE_CONFIG, &t);	via_print("Prefetch Buffer:       %10s%20s", (t & 0x80) ? "on" : "off", (t & 0x20) ? "on" : "off" );	via_print("Post Write Buffer:     %10s%20s", (t & 0x40) ? "on" : "off", (t & 0x10) ? "on" : "off" );	pci_read_config_byte(dev, VIA_FIFO_CONFIG, &t);	via_print("FIFO size:             %10d%20d", 16 - (((t >> 5) & 1) + ((t >> 6) & 1)) * 8,							  (((t >> 5) & 1) + ((t >> 6) & 1)) * 8);	via_print("Threshold Prim.:       %10s%20s", via_fifo[(t >> 2) & 3], via_fifo[t & 3]);	pci_read_config_word(dev, VIA_PRI_SECTOR_SIZE, &size0);	pci_read_config_word(dev, VIA_SEC_SECTOR_SIZE, &size1);	via_print("Bytes Per Sector:      %10d%20d", size0 & 0xfff, size1 & 0xfff);	pci_read_config_dword(dev, VIA_BM_BASE, &base);	base = (base & 0xfff0) ;	c0 = inb((unsigned short)base + 0x02);	c1 = inb((unsigned short)base + 0x0a);	via_print("Both channels togth:   %10s%20s", (c0 & 0x80) ? "no" : "yes", (c1 & 0x80) ? "no" : "yes" );	via_print("-------------------drive0----drive1----drive2----drive3-----");	via_print("BMDMA enabled: %10s%10s%10s%10s", (c0 & 0x20) ? "yes" : "no", (c0 & 0x40) ? "yes" : "no",						     (c1 & 0x20) ? "yes" : "no", (c1 & 0x40) ? "yes" : "no" );	pci_read_config_byte(dev, VIA_ADDRESS_SETUP, &t);	pci_read_config_dword(dev, VIA_DRIVE_TIMING, &v);	pci_read_config_dword(dev, VIA_UDMA_TIMING, &u);	for (i = 0; i < 4; i++) {		setup[i]   = ((t >>  ((3 - i) << 1)     ) & 0x3) + 1;		active[i]  = ((v >> (((3 - i) << 3) + 4)) & 0xf) + 1;		recover[i] = ((v >>  ((3 - i) << 3)     ) & 0xf) + 1;		udma[i]    = ((u >>  ((3 - i) << 3)     ) & 0x7) + 2;		umul[i]    = ((u >> (((3 - i) & 2) << 3)) & 0x8) ? 2 : 1;		uen[i]     = ((u >> ((3 - i) << 3)) & 0x20) ? 1 : 0;		speed[i] = uen[i] ? 20 * pci_clock * umul[i] / udma[i] :				    20 * pci_clock / (active[i] + recover[i]);		cycle[i] = uen[i] ? 1000 / (pci_clock * umul[i]) * udma[i] :				    1000 / pci_clock * (active[i] + recover[i]);	}	via_print_drive("Transfer Mode: ", "%10s", uen[i] ? "UDMA" : "DMA/PIO");	via_print_drive("Address Setup: ", "%8dns", (1000 / pci_clock) * setup[i]);	via_print_drive("Active Pulse:  ", "%8dns", (1000 / pci_clock) * active[i]);	via_print_drive("Recovery Time: ", "%8dns", (1000 / pci_clock) * recover[i]);	via_print_drive("Cycle Time:    ", "%8dns", cycle[i]);	via_print_drive("Transfer Rate: ", "%4d.%dMB/s", speed[i] / 10, speed[i] % 10);	return p - buffer;	/* hoping it is less than 4K... */}#endif#define FIT(v,min,max) ((v)>(max)?(max):((v)<(min)?(min):(v)))#define ENOUGH(v,un) (((v)-1)/(un)+1)#ifdef DEBUG#define via_write_config_byte(dev,number,value) do {\		printk(KERN_DEBUG "VP_IDE: Setting register %#x to %#x\n", number, value);\		pci_write_config_byte(dev,number,value); } while (0)#else#define via_write_config_byte	pci_write_config_byte#endifstatic int via_set_speed(ide_drive_t *drive, byte speed){	struct pci_dev *dev = HWIF(drive)->pci_dev;	int i, T, err = 0;	unsigned char t, setup, active, recover, cycle;	if (drive->dn > 3) return -1;	T = 1000 / system_bus_clock();	if (speed > via_isa_bridges[via_config].speed)		speed = via_isa_bridges[via_config].speed;	for (i = 0; via_timing[i].mode && via_timing[i].mode != speed; i++);#ifdef DEBUG	printk(KERN_DEBUG "VP_IDE: Setting drive %d to %s\n", drive->dn, via_timing[i].name);#endif	setup   = ENOUGH(via_timing[i].setup,   T);	active  = ENOUGH(via_timing[i].active,  T);	recover = ENOUGH(via_timing[i].recover, T);	cycle   = ENOUGH(via_timing[i].cycle,   T);

⌨️ 快捷键说明

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