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

📄 flashprg.c

📁 Ibmstb02500 miniboot 源码
💻 C
字号:
/* openbios/miscLib/flashprg.c, redbios, redbios_iii_1.0 6/14/99 14:33:55 *//*-----------------------------------------------------------------------------+||       This source code has been made available to you by IBM on an AS-IS|       basis.  Anyone receiving this source is licensed under IBM|       copyrights to use it in any way he or she deems fit, including|       copying it, modifying it, compiling it, and redistributing it either|       with or without modifications.  No license under IBM patents or|       patent applications is to be implied by the copyright license.||       Any user of this software should understand that IBM cannot provide|       technical support for this software and will not be responsible for|       any consequences resulting from the use of this software.||       Any person who transfers this source code or any derivative work|       must include the IBM copyright notice, this paragraph, and the|       preceding two paragraphs in the transferred software.||       COPYRIGHT   I B M   CORPORATION 1995|       LICENSED MATERIAL  -  PROGRAM PROPERTY OF I B M+-----------------------------------------------------------------------------*//*-----------------------------------------------------------------------------+||  File Name:   flash_prog.c||  Function:    Programs flash memory, must run out of DRAM.||  Author:      Maciej P. Tyrlik.||  Change Activity-||  Date        Description of Change                                       BY|  ---------   ---------------------                                       ---|  14-Jun-94   Created                                                     MPT|  15-Jun-94   Finished                                                    MPT|  30-Sep-94   Changed to use ROM ID (removed PASS_TWO_128 & PASS_TWO_512) KDW|  05-Oct-94   Added more comments                                         KDW|  08-Nov-94   Removed PASS_ONE                                            MPT|  24-Apr-95   Include s1Lib.h for function prototypes                     JWB|  23-Jan-97   Ported to DDI board                                         KDW|  27-Jun-97   Updated to support multiple sector erease and programming   pag|  25-Feb-98   ported to redwood board                                     pag|  04-Jun-98   fixed comments, added no_erase_mode flag.                   pag|  15-Jan-99   Ported to Redwood III (removed dram refresh)                pag|  10-Jun-99   Replaced intemp and outtemp with macros                     pag|  14-Jun-99   copy code to RAM in order to simplify make file.            pag|  03-Mar-00   Rewrite using Sector Map Table                              jfh|  03-Mar-00   Rewrite for 16 Meg Flash devices AMD 29LV160BB              jfh|  25-Apr-00   Move FLASH_CODE_ADDRESS to eval.h (easier to see Mem Map)   jfh|  07-Jan-02   Rewrite to enable random write accross all range            YYD|              by read before write|  24-Jun-02   Added interrupt lock and cache flush for flash_prog         YYD+-----------------------------------------------------------------------------*/#include <stddef.h>#include <ppcLib.h>#include <s1Lib.h>#include <string.h>#include <s1ldLib.h>#include <eval.h>#include "flash.h"//#define DEBUG#undef  DEBUG/* function pointers for copied code that does the actual work */static unsigned long (*get_flash_type_ptr)(void);static int (*write_flash_ptr)(unsigned short *, unsigned short, unsigned short);static int (*flash_prog_ptr)(unsigned long start, int offset, char *addr, size_t len, int no_erase_mode);static int (*flash_printf)(const char *format, ...);/* prototypes for copied code that does the actual work */static unsigned long zget_flash_type(void);static int zwrite_flash(unsigned short *, unsigned short, unsigned short);static int zflash_prog(unsigned long start, int offset, char *addr, size_t len, int no_erase_mode);void init_flash_code(void){   int len = zflash_code_size();   int i;   unsigned long *sptr, *dptr;#ifdef DEBUG   s1printf("Copying Flash code to RAM... \n");#endif   /* copy the flash code to RAM one word at a time to support OCM */   sptr = (unsigned long *) zget_flash_type;   dptr = (unsigned long *) BIOS_FLASH_CODE_ADDR;#ifdef DEBUG   s1printf("   Source      %x\n", sptr);   s1printf("   Destination %x\n", dptr);#endif   /*  copy the code to FLASH code to the address where it will run */   for (i = 0; i < len/4; ++i)   {       *dptr++ = *sptr++;   }#ifdef DEBUG   s1printf("Copying completed\n");#endif   /* update the function pointers to the newly copied locations. */   get_flash_type_ptr = (unsigned long (*)(void)) BIOS_FLASH_CODE_ADDR;   write_flash_ptr = (int (*)(unsigned short *, unsigned short, unsigned short))                  (BIOS_FLASH_CODE_ADDR + (int) zwrite_flash - (int) zget_flash_type);   flash_prog_ptr = (int (*)(unsigned long, int, char *, size_t, int))                  (BIOS_FLASH_CODE_ADDR + (int) zflash_prog - (int) zget_flash_type);                     flash_printf = s1printf;#ifdef DEBUG   s1printf("Get Flash Type   %x\n", get_flash_type_ptr);   s1printf("Write Flash      %x\n", write_flash_ptr);   s1printf("Program Flash    %x\n", flash_prog_ptr);#endif}unsigned long get_flash_type(){   return get_flash_type_ptr();}int flash_prog(unsigned long start, int offset, char *addr, size_t len, int no_erase_mode){   // YYD, added interrupt lock and cache invalidate    int rtn;   unsigned long        msr;   msr=ppcAndMsr(~(ppcMsrEE|ppcMsrCI));   rtn = flash_prog_ptr(start, offset, addr, len, no_erase_mode);   invalidated_invlidatei((unsigned char *)(start + offset), len);   (void)ppcMtmsr(msr);   return rtn;}/* This function will allow for determining the manufacturing information  *//* associated with the ROM being used.  Code sequences were taken from the *//* AMD Flash Memory Products 1992/1993 Data Book/Handbook.                 */unsigned long zget_flash_type(){   unsigned int            fl_base;   unsigned short          mfg_code, dev_code;   volatile unsigned short *flashp;   /*--------------------------------------------------------------------------+   | Read Autoselect bytes to determnine FLASH type.   +--------------------------------------------------------------------------*/   for (fl_base = FLASH_START; fl_base < (unsigned)FLASH_START + FLASH_TOTAL_SIZE; fl_base = fl_base + FLASH_DEV_SIZE)   {      flashp = (unsigned short *)fl_base;      flashp[0x000] = 0xF0;      flashp[0x555] = 0xAA;      flashp[0x2AA] = 0x55;      flashp[0x555] = 0x90;      mfg_code = flashp[0];      dev_code = flashp[1];      /*---------------------------------------------------------------------+      | Reset the FLASH (enable read access)      +----------------------------------------------------------------------*/      flashp[0x000] = 0xF0;      #ifdef DEBUG      flash_printf("mfg_code = %8.8X  dev_code = %8.8X\n",mfg_code, dev_code);#endif      if ((mfg_code != MFG_STRING) ||          (dev_code != DEV_STRING)) {         flash_printf("Device not recognized\n");         flash_printf("mfg_code = %8.8X  dev_code = %8.8X\n",mfg_code, dev_code);         return -1;  // YYD       }   }   return(dev_code);}/* writes one word to the flash at specified address */int zwrite_flash(unsigned short *addr, unsigned short data, unsigned short mask){   volatile unsigned short *flashp;   unsigned short temp;   int i;   if (mask == 0xffff)   {      temp = data;   }   else   {      flashp = addr;      temp = (flashp[0x000] & ~mask) | (data & mask);   }   /* Set-up sequence for writing data. */   flashp = (unsigned short *) ((unsigned long ) addr & 0x7fff0000);   flashp[0x555] = 0xAA;   flashp[0x2AA] = 0x55;   flashp[0x555] = 0xA0;   flashp = addr;   flashp[0x000] = temp;   while (1) { /* poll until the write is complete */      for (i = 0; i < 500    ; i++);      if ((flashp[0x000] & 0x80) == (temp & 0x80)) {         break;      }      if ((flashp[0x000] & 0x20) != 0) {         if ((flashp[0x000] & 0x80) == (temp & 0x80)) {            break;         } else {#ifdef DEBUG            flash_printf("Failed to write flash address 0x%08x\n",  addr);#endif            return -1;         }      }   }   return 0;}// YYD, this one has been rewrite to enable random write by read before writeint zflash_prog(unsigned long start,    int offset, char *addr, size_t len, int no_erase_mode){   int                  sector;   unsigned long        nvptr, nvend, bufptr;   /* Determine the size of the flash being used. */   if (get_flash_type_ptr() != DEV_STRING) // YYD   {#ifdef DEBUG      flash_printf("Unsupported FLASH device\n");#endif      return -1;   }   /*--------------------------------------------------------------------------+   | Write requested information.   +--------------------------------------------------------------------------*/   /* Set nvstart to the address where writing will begin. */      nvptr = (start + offset) & FLASH_ADDR_MASK;   nvend = nvptr + len;   bufptr = 0;      if(nvptr < FLASH_START || nvptr >= (unsigned)FLASH_START + FLASH_TOTAL_SIZE || nvend >= (unsigned)FLASH_START + FLASH_TOTAL_SIZE)   {#ifdef DEBUG   	flash_printf("Flash address out of range\n");#endif   	return -1;   }#ifdef DEBUG   flash_printf("FLASH: Flashing address 0x%08x 0x%08x\n", nvptr, nvend);#endif   /*--------------------------------------------------------------------------+   | Locate the first modified sector   +--------------------------------------------------------------------------*/   for (sector = 0; sector < NUM_SECTORS; sector++)   {       if (nvptr >= flash_map[sector].start_addr && nvptr < flash_map[sector+1].start_addr)       {           break;       }   }   if(sector >= NUM_SECTORS)  //YYD, failed to located the sector address   {#ifdef DEBUG   	flash_printf("FLASH: Flash address out of range\n");#endif   	return -1; // should not happen since we have checked the address   }   while(nvptr < nvend)   {   	int sect_len = flash_map[sector+1].start_addr - flash_map[sector].start_addr;   	unsigned short *flash_buffer = (unsigned short *)BIOS_FLASH_BUFFER_ADDR;   	unsigned short *sect_addr = (unsigned short *)flash_map[sector].start_addr;   	int k;           	if(sect_len > BIOS_FLASH_BUFFER_SIZE)   	{#ifdef DEBUG	    flash_printf("FLASH: device secter too large, please change BIOS_FLASH_BUFFER_SIZE\n");#endif   	    return -1;   	}        if (nvptr < flash_map[sector].start_addr || nvptr >= flash_map[sector+1].start_addr)        {            return -1; // some dirty mistake happened       	}       	   	// read the sector first   	for(k=0; k<sect_len/2; k++)   	{   	    flash_buffer[k] = sect_addr[k];   	}#ifdef DEBUG        flash_printf("FLASH: copied sector %d (%d) bytes\n", sector, sect_len);#endif   	// copy the changed content then   	for(k=nvptr-(unsigned int)sect_addr; k<sect_len && nvptr<nvend; nvptr++, bufptr++, k++)   	{   	    *((unsigned char *)flash_buffer + k) = addr[bufptr];   	}#ifdef DEBUG        flash_printf("FLASH: copied buffer 0x%08x (%d) bytes\n", nvptr-k, k);#endif   	   	// erase the sector now        {	        /*--------------------------------------------------------------------------+	        | Start the erase sector in each sector that needs to be erased.	        +--------------------------------------------------------------------------*/	        volatile unsigned short *flashp = sect_addr;	        flashp[0x555] = 0xAA;	        flashp[0x2AA] = 0x55;	        flashp[0x555] = 0x80;	        flashp[0x555] = 0xAA;	        flashp[0x2AA] = 0x55;	        flashp[0x000] = 0x30;			        /*--------------------------------------------------------------------------+	        | Poll for completion of the erase sector in each sector that we're erasing.	        +--------------------------------------------------------------------------*/	        while (1) { /* poll until the erase is complete */	           if ((flashp[0] & 0x80)!=0) {	               break;	           }	           if ((flashp[0] & 0x20)!=0) {	               if ((flashp[0] & 0x80)!=0) {	                   break;	               } else {#ifdef DEBUG			   flash_printf("FLASH: erase sector %d failed\n", sector);#endif	                   return -1;  // flash erase failed !!!	               }	           }	        }   	        }   	// at last, write the updated sector   	for(k=0; k<sect_len/2; k++)   	{           if (write_flash_ptr(sect_addr+k, flash_buffer[k], 0xffff))           {#ifdef DEBUG	      flash_printf("FLASH: write 0x%08x failed\n", sect_addr+k);#endif              return(-1);           }   	}   	   	// then move to next sector   	sector ++;   	if(sector >= NUM_SECTORS && nvptr < nvend)   	{#ifdef DEBUG	        flash_printf("FLASH: sector number out of range\n");#endif   		return -1;  // we should never be here   	}   }   return(0);}int zflash_code_size(void){   return (int) zflash_code_size - (int) zget_flash_type;}

⌨️ 快捷键说明

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