Annotation of qemu/roms/openbios/utils/devbios/programming.c, revision 1.1

1.1     ! root        1: /*
        !             2:  *                     OpenBIOS - free your system! 
        !             3:  *              ( firmware/flash device driver for Linux )
        !             4:  *                          
        !             5:  *  programming.c - flash device programming and probing algorithms.  
        !             6:  *  
        !             7:  *  This program is part of a free implementation of the IEEE 1275-1994 
        !             8:  *  Standard for Boot (Initialization Configuration) Firmware.
        !             9:  *
        !            10:  *  Copyright (C) 1998-2004  Stefan Reinauer, <[email protected]>
        !            11:  *
        !            12:  *  This program is free software; you can redistribute it and/or modify
        !            13:  *  it under the terms of the GNU General Public License as published by
        !            14:  *  the Free Software Foundation; version 2 of the License.
        !            15:  *
        !            16:  *  This program is distributed in the hope that it will be useful,
        !            17:  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
        !            18:  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
        !            19:  *  GNU General Public License for more details.
        !            20:  *
        !            21:  *  You should have received a copy of the GNU General Public License
        !            22:  *  along with this program; if not, write to the Free Software
        !            23:  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA
        !            24:  *
        !            25:  */
        !            26: 
        !            27: // <-- C++ style comments are for experimental comments only.
        !            28: // They will disappear as soon as I fixed all the stuff.
        !            29: 
        !            30: /* #define DEBUG_PROBING */
        !            31: 
        !            32: #include <linux/config.h>
        !            33: #include <linux/version.h>
        !            34: #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) && defined(MODVERSIONS)
        !            35: #include <linux/modversions.h>
        !            36: #endif
        !            37: 
        !            38: #include <linux/pci.h>
        !            39: #include <linux/errno.h>
        !            40: #include <linux/types.h>
        !            41: #include <linux/vmalloc.h>
        !            42: #include <linux/delay.h>
        !            43: #include <linux/spinlock.h>
        !            44: #include <asm/io.h>
        !            45: #include <asm/delay.h>
        !            46: #include <asm/uaccess.h>
        !            47: 
        !            48: #include "bios.h"
        !            49: #include "pcisets.h"
        !            50: #include "flashchips.h"
        !            51: #include "programming.h"
        !            52: 
        !            53: struct flashdevice flashdevices[BIOS_MAXDEV];
        !            54: int flashcount;
        !            55: 
        !            56: /*
        !            57:  * ******************************************
        !            58:  *
        !            59:  *     flashchip handling
        !            60:  *
        !            61:  * ****************************************** 
        !            62:  */
        !            63: 
        !            64: 
        !            65: void flash_command (unsigned char *addr, unsigned char command)
        !            66: #if 1
        !            67: {
        !            68:        flash_writeb(addr, 0x5555, 0xaa);
        !            69:        flash_writeb(addr, 0x2AAA, 0x55);
        !            70:        flash_writeb(addr, 0x5555, command);
        !            71: }
        !            72: void fwh_flash_command(unsigned char *addr, unsigned char command)
        !            73: #endif
        !            74: {
        !            75:        flash_writeb(addr, 0x75555, 0xaa);
        !            76:        flash_writeb(addr, 0x72aaa, 0x55);
        !            77:        flash_writeb(addr, 0x75555, command);
        !            78: }
        !            79: 
        !            80: #define CFLASH flashdevices[flashcount]
        !            81: int flash_probe_address(void *address)
        !            82: {
        !            83:        int flashnum=0, manufnum=0, sectors=0;
        !            84:        unsigned short flash_id, testflash;
        !            85:        unsigned long flags;
        !            86: #ifdef DEBUG_PROBING
        !            87:        printk( KERN_DEBUG "BIOS: Probing for flash chip @0x%08lx\n", (unsigned long) address);
        !            88: #endif
        !            89: 
        !            90: #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
        !            91:        save_flags(flags);
        !            92: #endif
        !            93:        spin_lock_irqsave(&bios_lock, flags);
        !            94: 
        !            95:        testflash= (flash_readb(address, 0))+(flash_readb(address, 1)<<8);
        !            96: 
        !            97:        /* 1st method: Intel, Atmel listen to this.. */
        !            98: 
        !            99:        flash_command(address, 0x90);
        !           100:        udelay(20);
        !           101: 
        !           102:        flash_id = (flash_readb(address, 0))+(flash_readb(address, 1)<<8);
        !           103: 
        !           104: #ifdef DEBUG_PROBING
        !           105:        printk (KERN_DEBUG "BIOS: testflash[%04x] flash_id[%04x]\n",
        !           106:                testflash, flash_id); 
        !           107: #endif
        !           108:        
        !           109:        /* 2nd method: Winbond (I think this is Jedec standard) */
        !           110: 
        !           111:        if (flash_id==testflash) {
        !           112: #ifdef DEBUG_PROBING
        !           113:                printk (KERN_DEBUG "BIOS: Trying 2nd ID method.\n"); 
        !           114: #endif
        !           115:                flash_command(address, 0xf0); /* Reset */
        !           116:                udelay(20);
        !           117: 
        !           118:                flash_command(address, 0x80);
        !           119:                flash_command(address, 0x60);
        !           120:                udelay(20);
        !           121: 
        !           122:                flash_id = (flash_readb(address, 0))+(flash_readb(address, 1)<<8);
        !           123: #ifdef DEBUG_PROBING
        !           124:        printk (KERN_DEBUG "BIOS: testflash[%04x] flash_id[%04x]\n",
        !           125:                testflash, flash_id); 
        !           126: #endif
        !           127:        }
        !           128: 
        !           129:        /* 3rd Method: Some Winbonds seem to want this */
        !           130: 
        !           131:        if (flash_id==testflash) {
        !           132: #ifdef DEBUG_PROBING
        !           133:                printk (KERN_DEBUG "BIOS: Trying 3rd ID method.\n"); 
        !           134: #endif
        !           135:                flash_command(address, 0xf0); /* Reset again */
        !           136:                udelay(20);
        !           137: 
        !           138:                flash_command(address, 0x80);
        !           139:                flash_command(address, 0x20);
        !           140:                udelay(20);
        !           141: 
        !           142:                flash_id = (flash_readb(address, 0))+(flash_readb(address, 1)<<8);
        !           143: #ifdef DEBUG_PROBING
        !           144:        printk (KERN_DEBUG "BIOS: testflash[%04x] flash_id[%04x]\n",
        !           145:                testflash, flash_id); 
        !           146: #endif
        !           147:        }
        !           148: 
        !           149:        if (flash_id==0x7f7f && flash_readb(address, 0x100)==0x1c) {
        !           150:                /* We have an Eon flashchip. They keep their
        !           151:                 * device id at 0x101 instead of 0x1
        !           152:                 */
        !           153:                printk(KERN_INFO "BIOS: Eon flash device detected\n");
        !           154:                flash_id=(flash_readb(address, 0x1))+(flash_readb(address, 0x101)<<8);
        !           155:        }
        !           156: 
        !           157:        flash_command(address, 0xf0);
        !           158:        udelay(20);
        !           159: 
        !           160:        spin_unlock_irqrestore(&bios_lock, flags);
        !           161: 
        !           162:        if (flash_id==testflash) return 0; /* Nothing found :-( */
        !           163: 
        !           164:        while (flashchips[flashnum].id!=0) {
        !           165:                if (flash_id==flashchips[flashnum].id) 
        !           166:                        break;
        !           167:                flashnum++;
        !           168:        }
        !           169: 
        !           170:        while (manufacturers[manufnum].id!=0) {
        !           171:                if ((flash_id&0xff)==manufacturers[manufnum].id) 
        !           172:                        break;
        !           173:                manufnum++;
        !           174:        }
        !           175:        
        !           176:        if (flashchips[flashnum].id) {
        !           177:                while (flashchips[flashnum].sectors[sectors]<flashchips[flashnum].size)
        !           178:                        sectors++;
        !           179:        }
        !           180: 
        !           181:        if (flashcount >= BIOS_MAXDEV) {
        !           182:                printk(KERN_DEBUG "BIOS: Too many flash devices found.\n");
        !           183:                return -1;
        !           184:        }
        !           185: 
        !           186:        CFLASH.flashnum = flashnum;
        !           187:        CFLASH.manufnum = manufnum;
        !           188:        CFLASH.id       = flash_id;
        !           189:        CFLASH.size     = (flashchips[flashnum].size<<10);
        !           190:        CFLASH.sectors  = sectors;
        !           191:        CFLASH.open_mode= 0;
        !           192:        CFLASH.open_cnt = 0;
        !           193: 
        !           194:        return 1;
        !           195: }
        !           196: 
        !           197: void flash_probe_area(unsigned long romaddr, unsigned long romsize, 
        !           198:                int map_always)
        !           199: {
        !           200:        unsigned long probeaddr;
        !           201:        unsigned char *mapped;
        !           202: 
        !           203:        mapped=ioremap(romaddr, romsize);
        !           204:        
        !           205:        devices[flashdevices[currflash].idx].activate();
        !           206:        
        !           207:        probeaddr=(unsigned long)mapped;
        !           208:        
        !           209:        while ( probeaddr < (unsigned long)mapped + romsize - 0x5555 ) {
        !           210:                if ( flash_probe_address ((void *)probeaddr) != 1) {
        !           211:                        probeaddr += 4*1024;
        !           212:                        continue;
        !           213:                }
        !           214:                
        !           215:                CFLASH.offset   = probeaddr-(unsigned long)mapped;
        !           216:                CFLASH.mapped   = (unsigned long)mapped;
        !           217:                CFLASH.physical = romaddr+CFLASH.offset;
        !           218:                
        !           219:                printk( KERN_INFO "BIOS: flash device with size "
        !           220:                                "%dk (ID 0x%04x) found.\n", 
        !           221:                                CFLASH.size >> 10, CFLASH.id);
        !           222:                
        !           223:                printk( KERN_INFO "BIOS:   physical address "
        !           224:                                "0x%08lx (va=0x%08lx+0x%lx).\n",
        !           225:                                CFLASH.physical, (unsigned long)CFLASH.mapped,
        !           226:                                CFLASH.offset);
        !           227: 
        !           228:                if (flashchips[CFLASH.flashnum].flags&f_fwh_compl) {
        !           229:                        unsigned long t_lk;
        !           230:                        unsigned int i=7;
        !           231:                        printk(KERN_INFO "BIOS:   FWH compliant "
        !           232:                                                        "chip detected.\n");
        !           233:                        for (t_lk=0xffb80002; t_lk<=0xffbf0002; t_lk+=0x10000) 
        !           234:                        {
        !           235:                                printk(KERN_INFO "Lock register %d "
        !           236:                                                 "(0x%08lx): 0x%x\n",
        !           237:                                                i, t_lk, (unsigned int)
        !           238:                                                (readb(phys_to_virt(t_lk))));
        !           239:                                i--;
        !           240:                        }
        !           241:                }
        !           242:                flashcount++;
        !           243:                currflash++;
        !           244: #ifdef MULTIPLE_FLASH
        !           245:                probeaddr += flashdevices[flashcount-1].size;
        !           246:                flashdevices[flashcount].mapped=flashdevices[flashcount-1].mapped;
        !           247:                flashdevices[flashcount].data=flashdevices[flashcount-1].data;
        !           248:                continue;
        !           249: #else
        !           250:                break;
        !           251: #endif
        !           252:        }
        !           253: 
        !           254:        /* We might want to always map the memory
        !           255:         * region in certain cases
        !           256:         */
        !           257: 
        !           258:        if (map_always) {
        !           259:                CFLASH.flashnum = 0;
        !           260:                CFLASH.manufnum = 0;
        !           261:                CFLASH.id       = 0;
        !           262:                CFLASH.size     = romsize;
        !           263:                CFLASH.sectors  = 0;
        !           264:                CFLASH.open_mode= 0;
        !           265:                CFLASH.open_cnt = 0;
        !           266:                CFLASH.offset   = 0;
        !           267:                CFLASH.mapped   = (unsigned long)mapped;
        !           268:                CFLASH.physical = romaddr;
        !           269:                printk( KERN_INFO "BIOS: rom device with size "
        !           270:                                "%dk registered.\n", CFLASH.size >> 10);
        !           271:                flashcount++; currflash++;
        !           272:                return;
        !           273:        }
        !           274:        
        !           275:        /* We found nothing in this area, so let's unmap it again */
        !           276:        
        !           277:        if (flashcount && flashdevices[flashcount-1].mapped != (unsigned long)mapped)
        !           278:                iounmap(mapped);
        !           279: 
        !           280:        devices[flashdevices[currflash].idx].deactivate();
        !           281: }
        !           282: 
        !           283: #undef CFLASH
        !           284: 
        !           285: void flash_program (unsigned char *addr)
        !           286: {
        !           287:        flash_command(addr, 0xa0);
        !           288: }
        !           289: 
        !           290: void flash_program_atmel (unsigned char *addr)
        !           291: {
        !           292:        flash_command(addr, 0x80);
        !           293:        flash_command(addr, 0x20);
        !           294: }
        !           295: 
        !           296: int flash_erase (unsigned char *addr, unsigned int flashnum) 
        !           297: {
        !           298:        flash_command(addr, 0x80);
        !           299:        flash_command(addr, 0x10);
        !           300:        udelay(80);
        !           301:        return flash_ready_toggle(addr, 0);
        !           302: }
        !           303: 
        !           304: int flash_erase_sectors (unsigned char *addr, unsigned int flashnum, unsigned int startsec, unsigned int endsec) 
        !           305: {
        !           306:        unsigned int sector;
        !           307:   
        !           308:        if (!(flashchips[flashnum].flags & f_slow_sector_erase)) {
        !           309:                flash_command(addr, 0x80);
        !           310: 
        !           311:                if (flashchips[flashnum].flags&f_fwh_compl) {
        !           312:                        flash_writeb(addr, 0x75555,0xaa);
        !           313:                        flash_writeb(addr, 0x72aaa,0x55);
        !           314:                } else {
        !           315:                        flash_writeb(addr, 0x5555,0xaa);
        !           316:                        flash_writeb(addr, 0x2aaa,0x55);
        !           317:                }
        !           318:     
        !           319:                for (sector=startsec; sector <= endsec; sector++) {
        !           320:                        flash_writeb (addr, flashchips[flashnum].sectors[sector]*1024, 0x30);
        !           321:                }
        !           322:     
        !           323:                udelay(150); // 80 max normally, wait 150usec to be sure
        !           324: #if 0
        !           325:                if (flashchips[flashnum].flags&f_fwh_compl)
        !           326: #endif
        !           327:                        return flash_ready_toggle(addr, flashchips[flashnum].sectors[sector-1]*1024);
        !           328: #if 0
        !           329:                else
        !           330:                        return flash_ready_poll(addr, flashchips[flashnum].sectors[sector-1]*1024, 0xff);
        !           331: #endif
        !           332:        }
        !           333:   
        !           334:        /* sectors must be sent the sector erase command for every sector */
        !           335:        for (sector=startsec; sector <= endsec; sector++) {
        !           336:                flash_command(addr, 0x80);
        !           337:                if (flashchips[flashnum].flags&f_fwh_compl) {
        !           338:                        flash_writeb(addr, 0x75555,0xaa);
        !           339:                        flash_writeb(addr, 0x72aaa,0x55);
        !           340:                } else {
        !           341:                        flash_writeb(addr, 0x5555,0xaa);
        !           342:                        flash_writeb(addr, 0x2aaa,0x55);
        !           343:                }
        !           344:     
        !           345:                flash_writeb(addr, flashchips[flashnum].sectors[sector]*1024, 0x30);
        !           346:                udelay(150);
        !           347: #if 0
        !           348:                if (flashchips[flashnum].flags&f_fwh_compl)
        !           349: #endif
        !           350:                        flash_ready_toggle(addr, flashchips[flashnum].sectors[sector] *1024);
        !           351: #if 0
        !           352:                else
        !           353:                        flash_ready_poll(addr, flashchips[flashnum].sectors[sector]*1024, 0xff);
        !           354: #endif
        !           355:        }
        !           356: 
        !           357:        return 0;
        !           358: 
        !           359: }
        !           360: 
        !           361: /* waiting for the end of programming/erasure by using the toggle method.
        !           362:  * As long as there is a programming procedure going on, bit 6 of the last
        !           363:  * written byte is toggling it's state with each consecutive read. 
        !           364:  * The toggling stops as soon as the procedure is completed.
        !           365:  * This function returns 0 if everything is ok, 1 if an error occured
        !           366:  * while programming was in progress.
        !           367:  */ 
        !           368: 
        !           369: int flash_ready_toggle (unsigned char *addr, unsigned int offset)
        !           370: {
        !           371:        unsigned long int timeout=0;
        !           372:        unsigned char oldflag, flag;
        !           373:        int loop=1;
        !           374: 
        !           375:        oldflag=flash_readb(addr, offset) & 0x40;
        !           376: 
        !           377:        while (loop && (timeout<0x7fffffff)) {
        !           378:                flag=flash_readb(addr, offset) & 0x40;
        !           379: 
        !           380:                if (flag == oldflag)
        !           381:                        loop=0;
        !           382:                
        !           383:                oldflag=flag;
        !           384:                timeout++;
        !           385:        }
        !           386: 
        !           387:        if (loop) {
        !           388:                printk(KERN_DEBUG "BIOS: operation timed out (Toggle)\n");
        !           389:                return 1;
        !           390:        }
        !           391:        
        !           392:        return 0;
        !           393: }
        !           394: 
        !           395: /* This functions is similar to the above one. While a programming
        !           396:  * procedure is going on, bit 7 of the last written data byte is
        !           397:  * inverted. When the procedure is completed, bit 7 contains the
        !           398:  * correct data value
        !           399:  */
        !           400: 
        !           401: int flash_ready_poll (unsigned char *addr, unsigned int offset, unsigned char data)
        !           402: {
        !           403:        unsigned long int timeout=0;
        !           404:        unsigned char flag;
        !           405: 
        !           406:        flag=flash_readb(addr, offset);
        !           407: 
        !           408:        while ( ( flag & 0x80) != ( data & 0x80)) {
        !           409:                if ( ( flag & 0x80 ) == ( data & 0x80 ) ) {
        !           410: #ifdef DBGTIMEOUT
        !           411:                        printk(KERN_DEBUG "BIOS: Timeout value (EOT Polling) %ld\n",timeout);
        !           412: #endif
        !           413:                        return 0;
        !           414:                }                       
        !           415:                flag=flash_readb(addr, offset);
        !           416:                if (timeout++>12800) {  // 10 times more than usual.
        !           417:                        printk(KERN_ERR "BIOS: EOT Polling timed out at 0x%08x."
        !           418:                                " Try again or increase max. timeout.\n",offset);
        !           419:                        return 1;
        !           420:                }
        !           421:                if ((flag & 0x80) == ( data & 0x80)) {
        !           422:                  flag=flash_readb(addr, offset);
        !           423:                }
        !           424:        }
        !           425: #ifdef DBGTIMEOUT
        !           426:        printk(KERN_DEBUG "BIOS: Timeout value (EOT Polling) %ld\n",timeout);
        !           427: #endif
        !           428: 
        !           429:        flag=flash_readb(addr, offset);
        !           430:        if ( ( flag & 0x80 ) == ( data & 0x80 ) ) return 0; else return 1;
        !           431: }
        !           432: 
        !           433: 
        !           434: 
        !           435: void iflash_program_byte (unsigned char *addr, unsigned int offset, unsigned char data)
        !           436: {
        !           437:        unsigned long int timeout=0;
        !           438:        unsigned char flag;
        !           439: 
        !           440:        flash_writeb (addr, offset, 0x40);
        !           441:        flash_writeb (addr, offset, data);
        !           442: 
        !           443:        flash_writeb (addr, offset, 0x70);      /* Read Status */
        !           444:        do {
        !           445:                flag=flash_readb (addr, offset);
        !           446:                if (timeout++>100) { // usually 2 or 3 :-)
        !           447:                        printk(KERN_ERR "BIOS: Intel programming timed out at"
        !           448:                                "0x%08x. Try again or increase max. timeout.\n",offset);
        !           449:                        return;
        !           450:                }
        !           451:        } while ((flag&0x80) != 0x80);
        !           452: 
        !           453: #ifdef DBGTIMEOUT
        !           454:        printk (KERN_DEBUG"BIOS: Timeout value (Intel byte program) %ld\n",timeout);
        !           455: #endif
        !           456: 
        !           457:        if (flag&0x18) {
        !           458:                flash_writeb (addr, offset, 0x50);      /* Reset Status Register */
        !           459:                printk (KERN_ERR "BIOS: Error occured, please repeat write operation. (intel)\n");
        !           460:        }
        !           461: 
        !           462:        flash_writeb (addr, offset, 0xff);
        !           463: }
        !           464: 
        !           465: 
        !           466: 
        !           467: int  iflash_erase_sectors (unsigned char *addr, unsigned int flashnum, unsigned int startsec, unsigned int endsec)
        !           468: {
        !           469:        unsigned long int timeout;
        !           470:        unsigned int sector, offset=0;
        !           471:        unsigned char flag;
        !           472: 
        !           473:        for (sector=startsec; sector<=endsec; sector++) {
        !           474:                offset=(flashchips[flashnum].sectors[sector]*1024);
        !           475:                flash_writeb (addr, offset, 0x20);
        !           476:                flash_writeb (addr, offset, 0xd0);
        !           477: 
        !           478:                flash_writeb (addr, offset, 0x70);      /* Read Status */
        !           479:                timeout=0;
        !           480:                do {
        !           481:                        flag=flash_readb (addr, offset);
        !           482:                        if (timeout++>1440000) { // usually 144000
        !           483:                                printk(KERN_ERR "BIOS: Intel sector erase timed out at 0x%08x. Try again or increase max. timeout.\n",offset);
        !           484:                                return 1;
        !           485:                        }
        !           486:                } while ((flag&0x80) != 0x80);
        !           487: 
        !           488: #ifdef DBGTIMEOUT
        !           489:                printk (KERN_DEBUG "BIOS: Timeout value (Intel sector erase) %ld\n",timeout);
        !           490: #endif
        !           491: 
        !           492:                if (flag&0x28) {
        !           493:                        flash_writeb (addr, offset, 0x50);
        !           494:                        flash_writeb (addr, offset, 0xff);
        !           495:                        return 1; /* Error! */
        !           496:                }
        !           497:        }
        !           498: 
        !           499:        flash_writeb (addr, offset, 0xff);
        !           500:        return 0;       
        !           501: }
        !           502: 
        !           503: 
        !           504: 
        !           505: unsigned char flash_readb(unsigned char *addr, unsigned int offset)
        !           506: {
        !           507: #if defined(__alpha__)
        !           508:        if (flashdevices[currflash].data==(void *)0xfff80000) {
        !           509:                if (offset<0x80000)
        !           510:                        outb(0x00,0x800);
        !           511:                else {
        !           512:                        outb(0x01, 0x800);
        !           513:                        offset-=0x80000;
        !           514:                }
        !           515:        }
        !           516: #endif 
        !           517:        return readb(addr+offset);
        !           518: }
        !           519: 
        !           520: 
        !           521: 
        !           522: void flash_writeb(unsigned char *addr, unsigned int offset, unsigned char data) 
        !           523: {
        !           524: #if defined(__alpha__)
        !           525:        if (flashdevices[currflash].data==(void *)0xfff80000) {
        !           526:                if (offset<0x80000)
        !           527:                        outb(0x00,0x800);
        !           528:                else {
        !           529:                        outb(0x01, 0x800);
        !           530:                        offset-=0x80000;
        !           531:                }
        !           532:        }
        !           533: #endif 
        !           534: /* 
        !           535:        printk(KERN_DEBUG "BIOS: writing 0x%02x to 0x%lx+0x%x\n",
        !           536:                                                        data,bios,offset);
        !           537:  */
        !           538:        writeb(data,addr+offset);
        !           539: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.