diff options
Diffstat (limited to 'qemu/roms/openbios/utils/devbios/programming.c')
-rw-r--r-- | qemu/roms/openbios/utils/devbios/programming.c | 539 |
1 files changed, 0 insertions, 539 deletions
diff --git a/qemu/roms/openbios/utils/devbios/programming.c b/qemu/roms/openbios/utils/devbios/programming.c deleted file mode 100644 index e1b35a34b..000000000 --- a/qemu/roms/openbios/utils/devbios/programming.c +++ /dev/null @@ -1,539 +0,0 @@ -/* - * OpenBIOS - free your system! - * ( firmware/flash device driver for Linux ) - * - * programming.c - flash device programming and probing algorithms. - * - * 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 - * - */ - -// <-- C++ style comments are for experimental comments only. -// They will disappear as soon as I fixed all the stuff. - -/* #define DEBUG_PROBING */ - -#include <linux/config.h> -#include <linux/version.h> -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) && defined(MODVERSIONS) -#include <linux/modversions.h> -#endif - -#include <linux/pci.h> -#include <linux/errno.h> -#include <linux/types.h> -#include <linux/vmalloc.h> -#include <linux/delay.h> -#include <linux/spinlock.h> -#include <asm/io.h> -#include <asm/delay.h> -#include <asm/uaccess.h> - -#include "bios.h" -#include "pcisets.h" -#include "flashchips.h" -#include "programming.h" - -struct flashdevice flashdevices[BIOS_MAXDEV]; -int flashcount; - -/* - * ****************************************** - * - * flashchip handling - * - * ****************************************** - */ - - -void flash_command (unsigned char *addr, unsigned char command) -#if 1 -{ - flash_writeb(addr, 0x5555, 0xaa); - flash_writeb(addr, 0x2AAA, 0x55); - flash_writeb(addr, 0x5555, command); -} -void fwh_flash_command(unsigned char *addr, unsigned char command) -#endif -{ - flash_writeb(addr, 0x75555, 0xaa); - flash_writeb(addr, 0x72aaa, 0x55); - flash_writeb(addr, 0x75555, command); -} - -#define CFLASH flashdevices[flashcount] -int flash_probe_address(void *address) -{ - int flashnum=0, manufnum=0, sectors=0; - unsigned short flash_id, testflash; - unsigned long flags; -#ifdef DEBUG_PROBING - printk( KERN_DEBUG "BIOS: Probing for flash chip @0x%08lx\n", (unsigned long) address); -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) - save_flags(flags); -#endif - spin_lock_irqsave(&bios_lock, flags); - - testflash= (flash_readb(address, 0))+(flash_readb(address, 1)<<8); - - /* 1st method: Intel, Atmel listen to this.. */ - - flash_command(address, 0x90); - udelay(20); - - flash_id = (flash_readb(address, 0))+(flash_readb(address, 1)<<8); - -#ifdef DEBUG_PROBING - printk (KERN_DEBUG "BIOS: testflash[%04x] flash_id[%04x]\n", - testflash, flash_id); -#endif - - /* 2nd method: Winbond (I think this is Jedec standard) */ - - if (flash_id==testflash) { -#ifdef DEBUG_PROBING - printk (KERN_DEBUG "BIOS: Trying 2nd ID method.\n"); -#endif - flash_command(address, 0xf0); /* Reset */ - udelay(20); - - flash_command(address, 0x80); - flash_command(address, 0x60); - udelay(20); - - flash_id = (flash_readb(address, 0))+(flash_readb(address, 1)<<8); -#ifdef DEBUG_PROBING - printk (KERN_DEBUG "BIOS: testflash[%04x] flash_id[%04x]\n", - testflash, flash_id); -#endif - } - - /* 3rd Method: Some Winbonds seem to want this */ - - if (flash_id==testflash) { -#ifdef DEBUG_PROBING - printk (KERN_DEBUG "BIOS: Trying 3rd ID method.\n"); -#endif - flash_command(address, 0xf0); /* Reset again */ - udelay(20); - - flash_command(address, 0x80); - flash_command(address, 0x20); - udelay(20); - - flash_id = (flash_readb(address, 0))+(flash_readb(address, 1)<<8); -#ifdef DEBUG_PROBING - printk (KERN_DEBUG "BIOS: testflash[%04x] flash_id[%04x]\n", - testflash, flash_id); -#endif - } - - if (flash_id==0x7f7f && flash_readb(address, 0x100)==0x1c) { - /* We have an Eon flashchip. They keep their - * device id at 0x101 instead of 0x1 - */ - printk(KERN_INFO "BIOS: Eon flash device detected\n"); - flash_id=(flash_readb(address, 0x1))+(flash_readb(address, 0x101)<<8); - } - - flash_command(address, 0xf0); - udelay(20); - - spin_unlock_irqrestore(&bios_lock, flags); - - if (flash_id==testflash) return 0; /* Nothing found :-( */ - - while (flashchips[flashnum].id!=0) { - if (flash_id==flashchips[flashnum].id) - break; - flashnum++; - } - - while (manufacturers[manufnum].id!=0) { - if ((flash_id&0xff)==manufacturers[manufnum].id) - break; - manufnum++; - } - - if (flashchips[flashnum].id) { - while (flashchips[flashnum].sectors[sectors]<flashchips[flashnum].size) - sectors++; - } - - if (flashcount >= BIOS_MAXDEV) { - printk(KERN_DEBUG "BIOS: Too many flash devices found.\n"); - return -1; - } - - CFLASH.flashnum = flashnum; - CFLASH.manufnum = manufnum; - CFLASH.id = flash_id; - CFLASH.size = (flashchips[flashnum].size<<10); - CFLASH.sectors = sectors; - CFLASH.open_mode= 0; - CFLASH.open_cnt = 0; - - return 1; -} - -void flash_probe_area(unsigned long romaddr, unsigned long romsize, - int map_always) -{ - unsigned long probeaddr; - unsigned char *mapped; - - mapped=ioremap(romaddr, romsize); - - devices[flashdevices[currflash].idx].activate(); - - probeaddr=(unsigned long)mapped; - - while ( probeaddr < (unsigned long)mapped + romsize - 0x5555 ) { - if ( flash_probe_address ((void *)probeaddr) != 1) { - probeaddr += 4*1024; - continue; - } - - CFLASH.offset = probeaddr-(unsigned long)mapped; - CFLASH.mapped = (unsigned long)mapped; - CFLASH.physical = romaddr+CFLASH.offset; - - printk( KERN_INFO "BIOS: flash device with size " - "%dk (ID 0x%04x) found.\n", - CFLASH.size >> 10, CFLASH.id); - - printk( KERN_INFO "BIOS: physical address " - "0x%08lx (va=0x%08lx+0x%lx).\n", - CFLASH.physical, (unsigned long)CFLASH.mapped, - CFLASH.offset); - - if (flashchips[CFLASH.flashnum].flags&f_fwh_compl) { - unsigned long t_lk; - unsigned int i=7; - printk(KERN_INFO "BIOS: FWH compliant " - "chip detected.\n"); - for (t_lk=0xffb80002; t_lk<=0xffbf0002; t_lk+=0x10000) - { - printk(KERN_INFO "Lock register %d " - "(0x%08lx): 0x%x\n", - i, t_lk, (unsigned int) - (readb(phys_to_virt(t_lk)))); - i--; - } - } - flashcount++; - currflash++; -#ifdef MULTIPLE_FLASH - probeaddr += flashdevices[flashcount-1].size; - flashdevices[flashcount].mapped=flashdevices[flashcount-1].mapped; - flashdevices[flashcount].data=flashdevices[flashcount-1].data; - continue; -#else - break; -#endif - } - - /* We might want to always map the memory - * region in certain cases - */ - - if (map_always) { - CFLASH.flashnum = 0; - CFLASH.manufnum = 0; - CFLASH.id = 0; - CFLASH.size = romsize; - CFLASH.sectors = 0; - CFLASH.open_mode= 0; - CFLASH.open_cnt = 0; - CFLASH.offset = 0; - CFLASH.mapped = (unsigned long)mapped; - CFLASH.physical = romaddr; - printk( KERN_INFO "BIOS: rom device with size " - "%dk registered.\n", CFLASH.size >> 10); - flashcount++; currflash++; - return; - } - - /* We found nothing in this area, so let's unmap it again */ - - if (flashcount && flashdevices[flashcount-1].mapped != (unsigned long)mapped) - iounmap(mapped); - - devices[flashdevices[currflash].idx].deactivate(); -} - -#undef CFLASH - -void flash_program (unsigned char *addr) -{ - flash_command(addr, 0xa0); -} - -void flash_program_atmel (unsigned char *addr) -{ - flash_command(addr, 0x80); - flash_command(addr, 0x20); -} - -int flash_erase (unsigned char *addr, unsigned int flashnum) -{ - flash_command(addr, 0x80); - flash_command(addr, 0x10); - udelay(80); - return flash_ready_toggle(addr, 0); -} - -int flash_erase_sectors (unsigned char *addr, unsigned int flashnum, unsigned int startsec, unsigned int endsec) -{ - unsigned int sector; - - if (!(flashchips[flashnum].flags & f_slow_sector_erase)) { - flash_command(addr, 0x80); - - if (flashchips[flashnum].flags&f_fwh_compl) { - flash_writeb(addr, 0x75555,0xaa); - flash_writeb(addr, 0x72aaa,0x55); - } else { - flash_writeb(addr, 0x5555,0xaa); - flash_writeb(addr, 0x2aaa,0x55); - } - - for (sector=startsec; sector <= endsec; sector++) { - flash_writeb (addr, flashchips[flashnum].sectors[sector]*1024, 0x30); - } - - udelay(150); // 80 max normally, wait 150usec to be sure -#if 0 - if (flashchips[flashnum].flags&f_fwh_compl) -#endif - return flash_ready_toggle(addr, flashchips[flashnum].sectors[sector-1]*1024); -#if 0 - else - return flash_ready_poll(addr, flashchips[flashnum].sectors[sector-1]*1024, 0xff); -#endif - } - - /* sectors must be sent the sector erase command for every sector */ - for (sector=startsec; sector <= endsec; sector++) { - flash_command(addr, 0x80); - if (flashchips[flashnum].flags&f_fwh_compl) { - flash_writeb(addr, 0x75555,0xaa); - flash_writeb(addr, 0x72aaa,0x55); - } else { - flash_writeb(addr, 0x5555,0xaa); - flash_writeb(addr, 0x2aaa,0x55); - } - - flash_writeb(addr, flashchips[flashnum].sectors[sector]*1024, 0x30); - udelay(150); -#if 0 - if (flashchips[flashnum].flags&f_fwh_compl) -#endif - flash_ready_toggle(addr, flashchips[flashnum].sectors[sector] *1024); -#if 0 - else - flash_ready_poll(addr, flashchips[flashnum].sectors[sector]*1024, 0xff); -#endif - } - - return 0; - -} - -/* waiting for the end of programming/erasure by using the toggle method. - * As long as there is a programming procedure going on, bit 6 of the last - * written byte is toggling it's state with each consecutive read. - * The toggling stops as soon as the procedure is completed. - * This function returns 0 if everything is ok, 1 if an error occured - * while programming was in progress. - */ - -int flash_ready_toggle (unsigned char *addr, unsigned int offset) -{ - unsigned long int timeout=0; - unsigned char oldflag, flag; - int loop=1; - - oldflag=flash_readb(addr, offset) & 0x40; - - while (loop && (timeout<0x7fffffff)) { - flag=flash_readb(addr, offset) & 0x40; - - if (flag == oldflag) - loop=0; - - oldflag=flag; - timeout++; - } - - if (loop) { - printk(KERN_DEBUG "BIOS: operation timed out (Toggle)\n"); - return 1; - } - - return 0; -} - -/* This functions is similar to the above one. While a programming - * procedure is going on, bit 7 of the last written data byte is - * inverted. When the procedure is completed, bit 7 contains the - * correct data value - */ - -int flash_ready_poll (unsigned char *addr, unsigned int offset, unsigned char data) -{ - unsigned long int timeout=0; - unsigned char flag; - - flag=flash_readb(addr, offset); - - while ( ( flag & 0x80) != ( data & 0x80)) { - if ( ( flag & 0x80 ) == ( data & 0x80 ) ) { -#ifdef DBGTIMEOUT - printk(KERN_DEBUG "BIOS: Timeout value (EOT Polling) %ld\n",timeout); -#endif - return 0; - } - flag=flash_readb(addr, offset); - if (timeout++>12800) { // 10 times more than usual. - printk(KERN_ERR "BIOS: EOT Polling timed out at 0x%08x." - " Try again or increase max. timeout.\n",offset); - return 1; - } - if ((flag & 0x80) == ( data & 0x80)) { - flag=flash_readb(addr, offset); - } - } -#ifdef DBGTIMEOUT - printk(KERN_DEBUG "BIOS: Timeout value (EOT Polling) %ld\n",timeout); -#endif - - flag=flash_readb(addr, offset); - if ( ( flag & 0x80 ) == ( data & 0x80 ) ) return 0; else return 1; -} - - - -void iflash_program_byte (unsigned char *addr, unsigned int offset, unsigned char data) -{ - unsigned long int timeout=0; - unsigned char flag; - - flash_writeb (addr, offset, 0x40); - flash_writeb (addr, offset, data); - - flash_writeb (addr, offset, 0x70); /* Read Status */ - do { - flag=flash_readb (addr, offset); - if (timeout++>100) { // usually 2 or 3 :-) - printk(KERN_ERR "BIOS: Intel programming timed out at" - "0x%08x. Try again or increase max. timeout.\n",offset); - return; - } - } while ((flag&0x80) != 0x80); - -#ifdef DBGTIMEOUT - printk (KERN_DEBUG"BIOS: Timeout value (Intel byte program) %ld\n",timeout); -#endif - - if (flag&0x18) { - flash_writeb (addr, offset, 0x50); /* Reset Status Register */ - printk (KERN_ERR "BIOS: Error occured, please repeat write operation. (intel)\n"); - } - - flash_writeb (addr, offset, 0xff); -} - - - -int iflash_erase_sectors (unsigned char *addr, unsigned int flashnum, unsigned int startsec, unsigned int endsec) -{ - unsigned long int timeout; - unsigned int sector, offset=0; - unsigned char flag; - - for (sector=startsec; sector<=endsec; sector++) { - offset=(flashchips[flashnum].sectors[sector]*1024); - flash_writeb (addr, offset, 0x20); - flash_writeb (addr, offset, 0xd0); - - flash_writeb (addr, offset, 0x70); /* Read Status */ - timeout=0; - do { - flag=flash_readb (addr, offset); - if (timeout++>1440000) { // usually 144000 - printk(KERN_ERR "BIOS: Intel sector erase timed out at 0x%08x. Try again or increase max. timeout.\n",offset); - return 1; - } - } while ((flag&0x80) != 0x80); - -#ifdef DBGTIMEOUT - printk (KERN_DEBUG "BIOS: Timeout value (Intel sector erase) %ld\n",timeout); -#endif - - if (flag&0x28) { - flash_writeb (addr, offset, 0x50); - flash_writeb (addr, offset, 0xff); - return 1; /* Error! */ - } - } - - flash_writeb (addr, offset, 0xff); - return 0; -} - - - -unsigned char flash_readb(unsigned char *addr, unsigned int offset) -{ -#if defined(__alpha__) - if (flashdevices[currflash].data==(void *)0xfff80000) { - if (offset<0x80000) - outb(0x00,0x800); - else { - outb(0x01, 0x800); - offset-=0x80000; - } - } -#endif - return readb(addr+offset); -} - - - -void flash_writeb(unsigned char *addr, unsigned int offset, unsigned char data) -{ -#if defined(__alpha__) - if (flashdevices[currflash].data==(void *)0xfff80000) { - if (offset<0x80000) - outb(0x00,0x800); - else { - outb(0x01, 0x800); - offset-=0x80000; - } - } -#endif -/* - printk(KERN_DEBUG "BIOS: writing 0x%02x to 0x%lx+0x%x\n", - data,bios,offset); - */ - writeb(data,addr+offset); -} |