📄 pcisets.c
字号:
/* * OpenBIOS - free your system! * ( firmware/flash device driver for Linux ) * * pcisets.c - support functions to map flash devices to kernel space * * This program is part of a free implementation of the IEEE 1275-1994 * Standard for Boot (Initialization Configuration) Firmware. * * Copyright (C) 1998-2004 Stefan Reinauer, <stepan@openbios.org> * * 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; version 2 of the License. * * 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., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA * */#include <linux/config.h>#include <linux/version.h>#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)#ifdef MODVERSIONS#include <linux/modversions.h>#endif#endif#include <linux/pci.h>#include <linux/types.h>#include <linux/ioport.h>#include <asm/io.h>#ifdef __alpha__#include <asm/hwrpb.h>#endif#include "bios.h"#include "flashchips.h"#include "pcisets.h"#include "programming.h"#ifdef CONFIG_PCI#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,10)#define pci_find_class pci_get_class#endif#define pci_id(dev) ((dev->vendor<<16) | (dev->device))struct pci_dev *hostbridge=NULL;static unsigned char pci_dummy[4];/* * ****************************************** * * 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));}/* * standard system firmware adress emitter */static int system_memarea(unsigned long *address, unsigned long *size, struct pci_dev *dev){#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) const struct pci_driver *drv; drv = pci_dev_driver(dev);#endif#ifndef __alpha__ *address=0xffe00000; *size=2048*1024;#else *address=0xfffffffffc000000; *size=512*1024;#endif printk(KERN_INFO "BIOS: Probing system firmware with " "%ldk rom area @0x%lx (%04x:%04x)\n", (*size>>10), *address, dev->vendor, dev->device );#ifdef CONFIG_PCI_NAMES#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) if (drv) printk(KERN_INFO "BIOS: System device is %s\n", drv->name);#else printk(KERN_INFO "BIOS: System device is %s\n", dev->name);#endif#endif return 0;}static int memarea_256k(unsigned long *address, unsigned long *size, struct pci_dev *dev){#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) const struct pci_driver *drv; drv = pci_dev_driver(dev);#endif *address=0xfffc0000; *size=256*1024; printk(KERN_INFO "BIOS: Probing system firmware with " "%ldk rom area @0x%lx (%04x:%04x)\n", (*size>>10), *address, dev->vendor, dev->device );#ifdef CONFIG_PCI_NAMES#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) if (drv) printk(KERN_INFO "BIOS: System device is %s\n", drv->name);#else printk(KERN_INFO "BIOS: System device is %s\n", dev->name);#endif#endif return 0;}/* * standard address emitter for normal pci devices */static int default_memarea(unsigned long *address, unsigned long *size, struct pci_dev *dev){#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) *address=dev->resource[PCI_ROM_RESOURCE].start; *size=dev->resource[PCI_ROM_RESOURCE].end - *address + 1;#else *address=0xdeadbeef; *size=0x00000000;#endif if (*address && (signed long)*address!=-1 ) { printk (KERN_DEBUG "BIOS: Probing PCI device %02x:%02x.%01x " "with %ldk rom area @ 0x%lx\n", dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn), (*size>>10), *address); return 1; } *address=0xdeadbeef; *size=0x00000000; return 0;}#ifdef __alpha__void probe_alphafw(void){ switch(hwrpb->sys_type) { case ST_DEC_EB164: /* Fall through */ break; case ST_DTI_RUFFIAN: /* case ST_DEC_TSUNAMI: // This crashes for whatever reason */ probe_pcibus(); return; default: printk(KERN_INFO "BIOS: unsupported alpha motherboard.\n"); return; } /* LX164 has system variation 0x2000 */ if (hwrpb->sys_variation == 0x2000) printk(KERN_INFO "BIOS: LX164 detected\n"); else printk(KERN_INFO "BIOS: EB164 board detected. Sys_var=0x%lx\n", hwrpb->sys_variation); flashdevices[flashcount].data=(void *)0xfff80000; flash_probe_area(0xfff80000, 512*1024, 0);}#endif#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0) #define pci_for_each_dev(dev) \ for(dev = pci_devices->next; dev != pci_devices; dev = dev->next)#endif#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,74)#define pci_for_each_dev(dev) \ while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)))#endif#define DEVICE(x) devices[g].pcidevs[x]void probe_pcibus(void){ struct pci_dev *dev=NULL; unsigned int g=0, d, map_always=0; unsigned long addr, size; /* Look whether we find something supported */ pci_for_each_dev(dev) { /* Search all device groups */ for (g=0; DEVICE(0); g++ ) { /* Search all devices in group */ for (d=0; DEVICE(d) && DEVICE(d) != pci_id(dev); d++); if(DEVICE(d) == pci_id(dev)) break; } flashdevices[flashcount].idx=g; flashdevices[flashcount].data=dev; map_always=devices[g].memarea(&addr, &size, dev);#ifdef DEBUG_PCI printk(KERN_INFO "BIOS: device=%x, cs=%d addr=%lx, size=%ld\n", pci_id(dev),g, addr,size);#endif if(!size) continue; flash_probe_area(addr, size, map_always); }}#undef DEVICE/* Intel 430, 440, 450 PCI Chipsets */#define CURRENT ((struct pci_dev *)flashdevices[currflash].data)static int gporeg_save;static void intel4x0_activate(void){#ifdef __ABIT_BE6II_v11__#define GPONUM 26#define GPOREG_OFFSET 0x34 register unsigned int gporeg; /* Read Bus 0, Dev 7, Func 3, Reg 40-44 (Power Managment Base Address) */ outl (0x80003B40, 0x0CF8); /* calc General Purpose Output Register I/O port address */ gporeg = (0xFFFFFFFE & inl (0x0CFC)) + GPOREG_OFFSET; /* Set GPO26 to 0 */ gporeg_save=inl(gporeg); printk(KERN_DEBUG "BIOS: GPOREG=0x%08x, mask=0x%x, new=0x%x\n",gporeg_save, (~(1<<GPONUM)), gporeg_save&(~(1<<GPONUM))); outl (gporeg_save&(~(1<<GPONUM)), gporeg);#undef GPOREG_OFFSET#endif pci_dummy[0]=pci_read(CURRENT, 0x4e); pci_dummy[1]=pci_read(CURRENT, 0x4f); /* Write and 128k enable */ pci_dummy[2]=0x44; //0xC4 if (CURRENT->device < 0x7000) { /* enable 512k */ pci_dummy[2]|=0x80; } else { /* enable 1M */ pci_write(CURRENT, 0x4f, pci_dummy[1] | 0x02); } pci_write(CURRENT, 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){#ifdef __ABIT_BE6II_v11__#define GPOREG_OFFSET 0x34 register unsigned long gporeg; /* Read Bus 0, Dev 7, Func 3, Reg 40-44 (Power Managment Base Address) */ outl (0x80003B40, 0x0CF8); /* calc General Purpose Output Register I/O port address */ gporeg = (0xFFFFFFFE & inl (0x0CFC)) + GPOREG_OFFSET; /* Reset GBO26 */ outl (gporeg_save, gporeg);#undef GPOREG_OFFSET#endif pci_write(CURRENT, 0x4e, pci_dummy[0]); pci_write(CURRENT, 0x4f, pci_dummy[1]);}/* preliminary support for Intel 830 mobile chipset. untested!! */static void intel8x0_activate(void){ pci_dummy[0]=pci_read(CURRENT, 0x4e); pci_dummy[1]=pci_read(CURRENT, 0xe3); pci_write(CURRENT, 0x4e, pci_dummy[0] | 0x01); pci_write(CURRENT, 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){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -