📄 pcisets.c
字号:
/* * BIOS/Flashrom driver for Linux * * Copyright (C) 1998-2002 Stefan Reinauer <stepan@suse.de> * */#include <linux/config.h>#include <linux/pci.h>#include <linux/errno.h>#include <linux/types.h>#include <linux/vmalloc.h>#include <linux/ioport.h>#include <linux/fcntl.h>#include <linux/init.h>#include <asm/io.h>#include <asm/delay.h>#include <linux/delay.h>#include <asm/uaccess.h>#include "bios.h"#include "pcisets.h"#if defined(__i386__) || defined(__ia64__) || defined(__alpha__)static void intel4x0_activate(void), intel4x0_deactivate(void);static void intel8x0_activate(void), intel8x0_deactivate(void);static void amd7xx_activate(void), amd7xx_deactivate(void);static void umc_activate(void), umc_deactivate(void);static void sis_activate(void), sis_deactivate(void);static void cs5530_activate(void), cs5530_deactivate(void);static void reliance_activate(void), reliance_deactivate(void);static void default_activate(void), default_deactivate(void);const struct functions pci_functions[] = { /* Intel 4x0 chipsets */ { (int[]) { 0x8086122d, 0x80861235, 0x80861237, 0x80861250, 0x80867030, 0x80867100, 0x80867180, 0x808684c4, 0x80867190, 0x80867192, 0x808671A0, 0x808671A2, 0 }, (int[]) { 0x8086122e, 0x80861234, 0x80867000, 0x80867110, 0 }, intel4x0_activate, intel4x0_deactivate }, /* Intel 8x0 chipsets */ { (int[]) { 0x80861A30, 0x80862500, 0x80862531, 0x80863575, 0x80867120, 0x80867124, 0x808684e0, 0 }, (int[]) { 0x80862410, 0x80862420, 0x80862440, 0x8086244c, 0x8086248c, 0x80867600, 0 }, intel8x0_activate, intel8x0_deactivate }, /* Irongate 75x, AMD-76xMP(X), VIA (M)VP3, VT8231/3 */ { (int[]) { 0x10227006, 0x1022700c, 0x1022700e, 0x11060576, 0x11060585, 0x11060595, 0x11060597, 0x11068597, 0x11060598, 0x11060685, 0x11060501, 0x11060691, 0x11060693, 0x11060601, 0x11060605, 0x11060391, 0x11060305, 0x11063099, 0x11063091, 0x11063101, 0x11063102, 0x11063103, 0x11063112, 0x11063133, 0 }, (int[]) { 0x10227408, 0x10227410, 0x10227440, 0x11060686, 0x11060586, 0x11060596, 0x11068231, 0x11063074, 0 }, amd7xx_activate, amd7xx_deactivate }, /* UMC 486 */ { (int[]) { 0x10608881, 0x10600881, 0x1060e881, 0 }, (int[]) { 0x1060886a, 0x10600886, 0x1060e886, 0x10608886, 0 }, umc_activate, umc_deactivate }, /* UMC Pentium */ { (int[]) { 0x10608891, 0x1060e891, 0x10600891, 0 }, (int[]) { 0x1060886a, 0x10600886, 0x1060e886, 0x10608886, 0 }, default_activate, default_deactivate }, /* SiS */ { (int[]) { 0x10390496, 0x10395597, 0x10390530, 0 }, (int[]) { 0x10390008, 0x10390018, 0 }, sis_activate, sis_deactivate }, /* OPTi */ { (int[]) { 0x1045c557, 0 }, (int[]) { 0x1045c558, 0 }, default_activate, default_deactivate }, /* CS5530(A) */ { (int[]) { 0x10780001, 0 }, (int[]) { 0x10780100, 0 }, cs5530_activate, cs5530_deactivate }, /* Reliance/ServerWorks NB6xxx */ { (int[]) { 0x11660007, 0x11660008, 0x11660009, 0 }, (int[]) { 0x11660200, 0 }, reliance_activate, reliance_deactivate }, { (int[]) { 0x0 }, (int[]) { 0x0 }, default_activate, default_deactivate },};#endifint chipset=0;#if defined(__i386__) || defined(__ia64__) || defined(__alpha__)unsigned char pci_dummy[4];struct pci_dev *isabridge=NULL, *hostbridge=NULL;int chipset_init(void);#endifchar flash_readb(unsigned int offset);void flash_writeb(unsigned int offset, char data);/* * ****************************************** * * own pci/shadow handling; We can't use * the PCI bios here as it would sweep * itself out! * * ****************************************** */static int pci_read(struct pci_dev *dev, unsigned char where){ if (!dev) return 0; outl((0x80000000 | (dev->bus->number << 16) | (dev->devfn << 8) | (where & ~3)), 0xCF8); mb(); return inb(0xCFC + (where&3));}static void pci_write(struct pci_dev *dev, unsigned char where, unsigned char value){ if (!dev) return; outl((0x80000000 | (dev->bus->number << 16) | (dev->devfn << 8) | (where & ~3)), 0xCF8); mb(); outb(value, 0xCFC + (where&3));}/* ****************************************** * * PCI Chipset specific routines. * * ****************************************** *//* This function detects the isa bridge and host bridge and * selects the correct chipset class for the pci_functions * structure. */#if defined(__i386__) || defined(__ia64__) || defined(__alpha__)#define HOST(x) pci_functions[chipset].hostbridges[x]#define ISA(x) pci_functions[chipset].isabridges[x]int chipset_init(void){ unsigned int i=0; /* look for a host bridge. Ruffians hide this one. */ hostbridge = pci_find_class(PCI_CLASS_BRIDGE_HOST<<8,NULL); /* Look for an ISA bridge */ isabridge = pci_find_class(PCI_CLASS_BRIDGE_ISA<<8,NULL);#ifdef DEBUG if (hostbridge) printk (KERN_DEBUG "BIOS: host bridge is %x, %x, %x\n", hostbridge->vendor, hostbridge->device, hostbridge->devfn); if (isabridge) printk (KERN_DEBUG "BIOS: isa bridge is %x, %x, %x\n", isabridge->vendor, isabridge->device, isabridge->devfn);#endif#ifdef __i386__ /* We do need to have a host bridge that is in the list * as long as there are chipset drivers using hostbridge * access. */ if (!hostbridge) { printk(KERN_ERR "BIOS: No hostbridge found.\n"); return -ENOMEDIUM; } for (chipset=0; HOST(0); chipset++ ) { for (i=0; HOST(i) && HOST(i) != pci_id(hostbridge); i++) ; if (HOST(i)) break; } /* If we did not find an isa bridge, we look for a * device known to have the functionality we want. */ if (!HOST(i)) { printk(KERN_ERR "BIOS: hostbridge not supported.\n"); return -ENOMEDIUM; } if(!isabridge) { for (i=0; ISA(i) && (isabridge = (pci_find_device(ISA(i)>>16,ISA(i)&0xffff, NULL))) == NULL; i++) ; /* Without any supported device we can't find a flash chip */ if (!isabridge) { printk(KERN_ERR "BIOS: No isa bridge found.\n"); return -ENOMEDIUM; } }#ifdef DEBUG else { for (i=0; ISA(i) && ISA(i)!= pci_id(isabridge); i++) ; if (!ISA(i)) printk ( KERN_DEBUG "BIOS: Unknown isa bridge.\n"); }#endif#else if (!isabridge) { printk(KERN_ERR "BIOS: No isa bridge found.\n"); return -ENOMEDIUM; } for (chipset=0; ISA(0); chipset++ ) { for (i=0; ISA(i) && ISA(i) != pci_id(isabridge); i++) ; if (ISA(i)) break; } if (!ISA(i)) { printk(KERN_ERR "BIOS: isa bridge not supported.\n"); return -ENOMEDIUM; }#endif return 0;}#undef HOST#undef ISA/* Intel 430, 440, 450 PCI Chipsets */static void intel4x0_activate(void){ pci_dummy[0]=pci_read(isabridge, 0x4e); pci_dummy[1]=pci_read(isabridge, 0x4f); /* Write and 128k enable */ pci_dummy[2]=0x44; if (isabridge->device < 0x7000) { /* enable 512k */ pci_dummy[2]|=0x80; } else { /* enable 1M */ pci_write(isabridge, 0x4f, pci_dummy[1] | 0x02); } pci_write(isabridge, 0x4e, pci_dummy[0] | pci_dummy[2]); // printk(KERN_DEBUG "BIOS: isa bridge cfg is 0x%02x\n", pci_dummy[0]);}static void intel4x0_deactivate(void){ pci_write(isabridge, 0x4e, pci_dummy[0]); pci_write(isabridge, 0x4f, pci_dummy[1]);}/* preliminary support for Intel 830 mobile chipset. untested!! */static void intel8x0_activate(void){ pci_dummy[0]=pci_read(isabridge, 0x4e); pci_dummy[1]=pci_read(isabridge, 0xe3); pci_write(isabridge, 0x4e, pci_dummy[0] | 0x01); pci_write(isabridge, 0xe3, pci_dummy[1] | 0xC0); // We don't have to change FWH_DEC_EN1, as it decodes // all memory areas to the FWH per default. // We try it anyways. // FWH_DEC_EN1: isabridge, 0xe3, 8bit, default 0xff. // FWH_SEL1: isabridge, 0xe8, 32bit, default 0x00112233 (??) //printk(KERN_DEBUG "BIOS: BIOS_CNTL is 0x%02x\n", pci_dummy[0]); //printk(KERN_DEBUG "BIOS: FWH_DEC_EN1 is 0x%02x\n", pci_dummy[1]);}static void intel8x0_deactivate(void){ pci_write(isabridge, 0x4e, pci_dummy[0]); pci_write(isabridge, 0xe3, pci_dummy[1]);}/* AMD 760/756/751 & VIA (M)VP3 */static void amd7xx_activate(void){ pci_dummy[0]=pci_read(isabridge, 0x40); /* IO Control 1 */ pci_dummy[1]=pci_read(isabridge, 0x43); /* SEGEN */ pci_write(isabridge, 0x40, pci_dummy[0] | 0x01); pci_write(isabridge, 0x43, pci_dummy[1] | 0x80);}static void amd7xx_deactivate(void){ pci_write(isabridge, 0x43, pci_dummy[1]); pci_write(isabridge, 0x40, pci_dummy[0]);}/* SiS works with 530/5595 chipsets */static void sis_activate(void) { pci_dummy[0]=pci_read(hostbridge, 0x76); pci_dummy[1]=readb(0x51); /* disable shadow */ pci_write(hostbridge, 0x76, 0x00); /* disable cache */ writeb(pci_dummy[1] & 0x7f, 0x51); /* enable flash write enable */ pci_write(isabridge, 0x45, 0x44);}static void sis_deactivate(void) { /* disable flash write */ pci_write(isabridge, 0x45, 0x60); /* shadow restore to original */ pci_write(hostbridge, 0x76, pci_dummy[0]); /* restore cache to original status */ writeb(pci_dummy[1], 0x51);}/* UMC 486 Chipset 8881/886a */static void umc_activate(void){ pci_dummy[0]=pci_read(hostbridge, 0x54); pci_dummy[1]=pci_read(hostbridge, 0x55); pci_write(hostbridge, 0x54, 0x00); pci_write(hostbridge, 0x55, 0x40); pci_write(isabridge,0x47, pci_read(isabridge,0x47) & ~0x40);}static void umc_deactivate(void){ pci_write(isabridge, 0x47, pci_read(isabridge,0x47) | 0x40); pci_write(hostbridge, 0x54, pci_dummy[0]); pci_write(hostbridge, 0x55, pci_dummy[1]);}/* CS5530 functions */static void cs5530_activate(void){ /* Save modified registers for later reset */ pci_dummy[0]=pci_read(isabridge,0x52); pci_dummy[1]=pci_read(isabridge,0x5b); /* enable rom write access */ pci_write(isabridge, 0x52, pci_dummy[0]|0x06); /* enable rom positive decode */ // pci_write(isabridge,0x5b, pci_dummy[1]|0x20); // pci_write(isabridge,0x52, pci_read(isabridge,0x52)|0x01);}static void cs5530_deactivate(void){ pci_write(isabridge, 0x52, pci_dummy[0]); // pci_write(isabridge, 0x5b, pci_dummy[1]);}/* Reliance / ServerWorks */static void reliance_activate(void){ pci_dummy[0]=pci_read(isabridge,0x41); pci_dummy[1]=pci_read(isabridge,0x70); pci_dummy[2]=inb(0xc6f); /* Enable 512k */ pci_write(isabridge, 0x41, pci_dummy[0] | 0x02); /* Enable 4MB */ pci_write(isabridge, 0x70, pci_dummy[1] | 0x80); /* Enable flash write */ outb(pci_dummy[2] | 0x40, 0xc6f);} static void reliance_deactivate(void){ pci_write(isabridge, 0x41, pci_dummy[0]); pci_write(isabridge, 0x70, pci_dummy[1]); outb(pci_dummy[2], 0xc6f);}/* Default routines. Use these if nothing else works */static void default_activate(void){ printk(KERN_ERR "BIOS: Could not handle your PCI Chipset. Please report!\n");}static void default_deactivate(void){ /* not possible */}#endif /* (__i386__) || (__ia64__) */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -