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

📄 sis5513.c

📁 at91rm9200处理器ide接口驱动程序源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * linux/drivers/ide/sis5513.c		Version 0.13	March 6, 2002 * * Copyright (C) 1999-2000	Andre Hedrick <andre@linux-ide.org> * Copyright (C) 2002		Lionel Bouton <Lionel.Bouton@inet6.fr>, Maintainer * May be copied or modified under the terms of the GNU General Public License * * * Thanks : * * SiS Taiwan		: for direct support and hardware. * Daniela Engert	: for initial ATA100 advices and numerous others. * John Fremlin, Manfred Spraul : *			  for checking code correctness, providing patches. * * * Original tests and design on the SiS620/5513 chipset. * ATA100 tests and design on the SiS735/5513 chipset. * ATA16/33 design from specs *//* * TODO: *	- Get ridden of SisHostChipInfo[] completness dependancy. *	- Get ATA-133 datasheets, implement ATA-133 init code. *	- Study drivers/ide/ide-timing.h. *	- Are there pre-ATA_16 SiS5513 chips ? -> tune init code for them *	  or remove ATA_00 define *	- More checks in the config registers (force values instead of *	  relying on the BIOS setting them correctly). *	- Further optimisations ? *	  . for example ATA66+ regs 0x48 & 0x4A */#include <linux/config.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 <asm/io.h>#include <asm/irq.h>#include "ide_modes.h"/* When DEBUG is defined it outputs initial PCI config register   values and changes made to them by the driver */   // #define DEBUG/* When BROKEN_LEVEL is defined it limits the DMA mode   at boot time to its value */// #define BROKEN_LEVEL XFER_SW_DMA_0#define DISPLAY_SIS_TIMINGS/* Miscellaneaous flags */#define SIS5513_LATENCY		0x01/* registers layout and init values are chipset family dependant *//* 1/ define families */#define ATA_00		0x00#define ATA_16		0x01#define ATA_33		0x02#define ATA_66		0x03#define ATA_100a	0x04 // SiS730 is ATA100 with ATA66 layout#define ATA_100		0x05#define ATA_133		0x06/* 2/ variable holding the controller chipset family value */static unsigned char chipset_family;/* * Debug code: following IDE config registers' changes */#ifdef DEBUG/* Copy of IDE Config registers 0x00 -> 0x57   Fewer might be used depending on the actual chipset */static unsigned char ide_regs_copy[0x58];static byte sis5513_max_config_register(void) {	switch(chipset_family) {		case ATA_00:		case ATA_16:	return 0x4f;		case ATA_33:	return 0x52;		case ATA_66:		case ATA_100a:		case ATA_100:		case ATA_133:		default:	return 0x57;	}}/* Read config registers, print differences from previous read */static void sis5513_load_verify_registers(struct pci_dev* dev, char* info) {	int i;	byte reg_val;	byte changed=0;	byte max = sis5513_max_config_register();	printk("SIS5513: %s, changed registers:\n", info);	for(i=0; i<=max; i++) {		pci_read_config_byte(dev, i, &reg_val);		if (reg_val != ide_regs_copy[i]) {			printk("%0#x: %0#x -> %0#x\n",			       i, ide_regs_copy[i], reg_val);			ide_regs_copy[i]=reg_val;			changed=1;		}	}	if (!changed) {		printk("none\n");	}}/* Load config registers, no printing */static void sis5513_load_registers(struct pci_dev* dev) {	int i;	byte max = sis5513_max_config_register();	for(i=0; i<=max; i++) {		pci_read_config_byte(dev, i, &(ide_regs_copy[i]));	}}/* Print a register */static void sis5513_print_register(int reg) {	printk(" %0#x:%0#x", reg, ide_regs_copy[reg]);}/* Print valuable registers */static void sis5513_print_registers(struct pci_dev* dev, char* marker) {	int i;	byte max = sis5513_max_config_register();	sis5513_load_registers(dev);	printk("SIS5513 %s\n", marker);	printk("SIS5513 dump:");	for(i=0x00; i<0x40; i++) {		if ((i % 0x10)==0) printk("\n             ");		sis5513_print_register(i);	}	for(; i<49; i++) {		sis5513_print_register(i);	}	printk("\n             ");	for(; i<=max; i++) {		sis5513_print_register(i);	}	printk("\n");}#endif/* * Devices supported */static const struct {	const char *name;	unsigned short host_id;	unsigned char chipset_family;	unsigned char flags;} SiSHostChipInfo[] = {//	{ "SiS750",	PCI_DEVICE_ID_SI_750,	ATA_100,	SIS5513_LATENCY },//	{ "SiS745",	PCI_DEVICE_ID_SI_745,	ATA_100,	SIS5513_LATENCY },	{ "SiS740",	PCI_DEVICE_ID_SI_740,	ATA_100,	SIS5513_LATENCY },	{ "SiS735",	PCI_DEVICE_ID_SI_735,	ATA_100,	SIS5513_LATENCY },	{ "SiS730",	PCI_DEVICE_ID_SI_730,	ATA_100a,	SIS5513_LATENCY },//	{ "SiS650",	PCI_DEVICE_ID_SI_650,	ATA_100,	SIS5513_LATENCY },//	{ "SiS645",	PCI_DEVICE_ID_SI_645,	ATA_100,	SIS5513_LATENCY },	{ "SiS635",	PCI_DEVICE_ID_SI_635,	ATA_100,	SIS5513_LATENCY },	{ "SiS640",	PCI_DEVICE_ID_SI_640,	ATA_66,		SIS5513_LATENCY },	{ "SiS630",	PCI_DEVICE_ID_SI_630,	ATA_66,		SIS5513_LATENCY },	{ "SiS620",	PCI_DEVICE_ID_SI_620,	ATA_66,		SIS5513_LATENCY },	{ "SiS540",	PCI_DEVICE_ID_SI_540,	ATA_66,		0},	{ "SiS530",	PCI_DEVICE_ID_SI_530,	ATA_66,		0},	{ "SiS5600",	PCI_DEVICE_ID_SI_5600,	ATA_33,		0},	{ "SiS5598",	PCI_DEVICE_ID_SI_5598,	ATA_33,		0},	{ "SiS5597",	PCI_DEVICE_ID_SI_5597,	ATA_33,		0},	{ "SiS5591",	PCI_DEVICE_ID_SI_5591,	ATA_33,		0},	{ "SiS5513",	PCI_DEVICE_ID_SI_5513,	ATA_16,		0},	{ "SiS5511",	PCI_DEVICE_ID_SI_5511,	ATA_16,		0},};/* Cycle time bits and values vary accross chip dma capabilities   These three arrays hold the register layout and the values to set.   Indexed by chipset_family and (dma_mode - XFER_UDMA_0) */static byte cycle_time_offset[] = {0,0,5,4,4,0,0};static byte cycle_time_range[] = {0,0,2,3,3,4,4};static byte cycle_time_value[][XFER_UDMA_5 - XFER_UDMA_0 + 1] = {	{0,0,0,0,0,0}, /* no udma */	{0,0,0,0,0,0}, /* no udma */	{3,2,1,0,0,0},	{7,5,3,2,1,0},	{7,5,3,2,1,0},	{11,7,5,4,2,1},	{0,0,0,0,0,0} /* not yet known, ask SiS */};static struct pci_dev *host_dev = NULL;/* * Printing configuration */#if defined(DISPLAY_SIS_TIMINGS) && defined(CONFIG_PROC_FS)#include <linux/stat.h>#include <linux/proc_fs.h>static int sis_get_info(char *, char **, off_t, int);extern int (*sis_display_info)(char *, char **, off_t, int); /* ide-proc.c */static struct pci_dev *bmide_dev;static char* cable_type[] = {	"80 pins",	"40 pins"};static char* recovery_time[] ={	"12 PCICLK", "1 PCICLK",	"2 PCICLK", "3 PCICLK",	"4 PCICLK", "5 PCICLCK",	"6 PCICLK", "7 PCICLCK",	"8 PCICLK", "9 PCICLCK",	"10 PCICLK", "11 PCICLK",	"13 PCICLK", "14 PCICLK",	"15 PCICLK", "15 PCICLK"};static char* active_time[] = {	"8 PCICLK", "1 PCICLCK",	"2 PCICLK", "3 PCICLK",	"4 PCICLK", "5 PCICLK",	"6 PCICLK", "12 PCICLK"};static char* cycle_time[] = {	"Reserved", "2 CLK",	"3 CLK", "4 CLK",	"5 CLK", "6 CLK",	"7 CLK", "8 CLK",	"9 CLK", "10 CLK",	"11 CLK", "12 CLK",	"Reserved", "Reserved",	"Reserved", "Reserved"};/* Generic add master or slave info function */static char* get_drives_info (char *buffer, byte pos){	byte reg00, reg01, reg10, reg11; /* timing registers */	char* p = buffer;/* Postwrite/Prefetch */	pci_read_config_byte(bmide_dev, 0x4b, &reg00);	p += sprintf(p, "Drive %d:        Postwrite %s \t \t Postwrite %s\n",		     pos, (reg00 & (0x10 << pos)) ? "Enabled" : "Disabled",		     (reg00 & (0x40 << pos)) ? "Enabled" : "Disabled");	p += sprintf(p, "                Prefetch  %s \t \t Prefetch  %s\n",		     (reg00 & (0x01 << pos)) ? "Enabled" : "Disabled",		     (reg00 & (0x04 << pos)) ? "Enabled" : "Disabled");	pci_read_config_byte(bmide_dev, 0x40+2*pos, &reg00);	pci_read_config_byte(bmide_dev, 0x41+2*pos, &reg01);	pci_read_config_byte(bmide_dev, 0x44+2*pos, &reg10);	pci_read_config_byte(bmide_dev, 0x45+2*pos, &reg11);/* UDMA */	if (chipset_family >= ATA_33) {		p += sprintf(p, "                UDMA %s \t \t \t UDMA %s\n",			     (reg01 & 0x80)  ? "Enabled" : "Disabled",			     (reg11 & 0x80) ? "Enabled" : "Disabled");		p += sprintf(p, "                UDMA Cycle Time    ");		switch(chipset_family) {			case ATA_33:	p += sprintf(p, cycle_time[(reg01 & 0x60) >> 5]); break;			case ATA_66:			case ATA_100a:	p += sprintf(p, cycle_time[(reg01 & 0x70) >> 4]); break;			case ATA_100:	p += sprintf(p, cycle_time[reg01 & 0x0F]); break;			case ATA_133:			default:	p += sprintf(p, "133+ ?"); break;		}		p += sprintf(p, " \t UDMA Cycle Time    ");		switch(chipset_family) {			case ATA_33:	p += sprintf(p, cycle_time[(reg11 & 0x60) >> 5]); break;			case ATA_66:			case ATA_100a:	p += sprintf(p, cycle_time[(reg11 & 0x70) >> 4]); break;			case ATA_100:	p += sprintf(p, cycle_time[reg11 & 0x0F]); break;			case ATA_133:			default:	p += sprintf(p, "133+ ?"); break;		}		p += sprintf(p, "\n");	}/* Data Active */	p += sprintf(p, "                Data Active Time   ");	switch(chipset_family) {		case ATA_00:		case ATA_16: /* confirmed */		case ATA_33:		case ATA_66:		case ATA_100a: p += sprintf(p, active_time[reg01 & 0x07]); break;		case ATA_100: p += sprintf(p, active_time[(reg00 & 0x70) >> 4]); break;		case ATA_133:		default: p += sprintf(p, "133+ ?"); break;	}	p += sprintf(p, " \t Data Active Time   ");	switch(chipset_family) {		case ATA_00:		case ATA_16:		case ATA_33:		case ATA_66:		case ATA_100a: p += sprintf(p, active_time[reg11 & 0x07]); break;		case ATA_100: p += sprintf(p, active_time[(reg10 & 0x70) >> 4]); break;		case ATA_133:		default: p += sprintf(p, "133+ ?"); break;	}	p += sprintf(p, "\n");/* Data Recovery */	/* warning: may need (reg&0x07) for pre ATA66 chips */	p += sprintf(p, "                Data Recovery Time %s \t Data Recovery Time %s\n",		     recovery_time[reg00 & 0x0f], recovery_time[reg10 & 0x0f]);	return p;}static char* get_masters_info(char* buffer){	return get_drives_info(buffer, 0);}static char* get_slaves_info(char* buffer){	return get_drives_info(buffer, 1);}/* Main get_info, called on /proc/ide/sis reads */static int sis_get_info (char *buffer, char **addr, off_t offset, int count){	char *p = buffer;	byte reg;	u16 reg2, reg3;	p += sprintf(p, "\nSiS 5513 ");	switch(chipset_family) {		case ATA_00: p += sprintf(p, "Unknown???"); break;		case ATA_16: p += sprintf(p, "DMA 16"); break;		case ATA_33: p += sprintf(p, "Ultra 33"); break;		case ATA_66: p += sprintf(p, "Ultra 66"); break;		case ATA_100a:		case ATA_100: p += sprintf(p, "Ultra 100"); break;		case ATA_133:		default: p+= sprintf(p, "Ultra 133+"); break;	}	p += sprintf(p, " chipset\n");	p += sprintf(p, "--------------- Primary Channel ---------------- Secondary Channel -------------\n");/* Status */	pci_read_config_byte(bmide_dev, 0x4a, &reg);	p += sprintf(p, "Channel Status: ");	if (chipset_family < ATA_66) {		p += sprintf(p, "%s \t \t \t \t %s\n",			     (reg & 0x04) ? "On" : "Off",			     (reg & 0x02) ? "On" : "Off");	} else {		p += sprintf(p, "%s \t \t \t \t %s \n",			     (reg & 0x02) ? "On" : "Off",			     (reg & 0x04) ? "On" : "Off");	}/* Operation Mode */	pci_read_config_byte(bmide_dev, 0x09, &reg);	p += sprintf(p, "Operation Mode: %s \t \t \t %s \n",		     (reg & 0x01) ? "Native" : "Compatible",		     (reg & 0x04) ? "Native" : "Compatible");/* 80-pin cable ? */	if (chipset_family > ATA_33) {		pci_read_config_byte(bmide_dev, 0x48, &reg);		p += sprintf(p, "Cable Type:     %s \t \t \t %s\n",			     (reg & 0x10) ? cable_type[1] : cable_type[0],			     (reg & 0x20) ? cable_type[1] : cable_type[0]);	}/* Prefetch Count */	pci_read_config_word(bmide_dev, 0x4c, &reg2);	pci_read_config_word(bmide_dev, 0x4e, &reg3);	p += sprintf(p, "Prefetch Count: %d \t \t \t \t %d\n",		     reg2, reg3);	p = get_masters_info(p);	p = get_slaves_info(p);	return p-buffer;}#endif /* defined(DISPLAY_SIS_TIMINGS) && defined(CONFIG_PROC_FS) */byte sis_proc = 0;extern char *ide_xfer_verbose (byte xfer_rate);/* * Configuration functions *//* Enables per-drive prefetch and postwrite */static void config_drive_art_rwp (ide_drive_t *drive){	ide_hwif_t *hwif	= HWIF(drive);	struct pci_dev *dev	= hwif->pci_dev;	byte reg4bh		= 0;	byte rw_prefetch	= (0x11 << drive->dn);#ifdef DEBUG	printk("SIS5513: config_drive_art_rwp, drive %d\n", drive->dn);	sis5513_load_verify_registers(dev, "config_drive_art_rwp start");#endif	if (drive->media != ide_disk)		return;	pci_read_config_byte(dev, 0x4b, &reg4bh);

⌨️ 快捷键说明

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