# intelchips.S86 - Low level routines for Intel like flash EPROM chip access # # Copyright (C) 2003 Gero Kuhlmann # # 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; either version 2 of the License, or # any later version. # # 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., 675 Mass Ave, Cambridge, MA 02139, USA. # # $Id: intelchips.S86,v 1.1 2003/03/09 00:43:09 gkminix Exp $ # #==================================================================== # #include "common.i86" #include "flash.i86" .file "intelchips.S86" .line 30 # #==================================================================== # # Internal additions to the flash EPROM chip definition structure # We only support single-block flash EPROMs, no boot-sector or # multi-sector chips. # FSTRUCT_ID .equ FSTRUCT_INT + H'0000 # offset to chip ID FSTRUCT_ISIZE .equ FSTRUCT_INT + H'0002 # total size of structure # #==================================================================== # # Definitions used for programming Intel Flash EPROM chips # READID_CMD .equ H'90 # command to read chip ID ERASE1_CMD .equ H'20 # command to setup erasure ERASE2_CMD .equ H'A0 # command to verify erasure PROG1_CMD .equ H'40 # command to setup programming PROG2_CMD .equ H'C0 # command to verify programming RESET_CMD .equ H'FF # command to reset chip VPPTIME .equ 1000 # wait 1 millisecond to let Vpp settle ERASETIME .equ 10000 # wait 10 milliseconds during erase PROGTIME .equ 10 # wait 10 microseconds during program VERIFYTIME .equ 6 # wait 6 microseconds during verify PROGRETRY .equ 25 # retry programming 25 times ERASERETRY .equ 1000 # retry erasing 1000 times .line 65 # #==================================================================== # # Public routines defined in this module # \(.text) .global intel_readid .global intel_erase .global intel_doprog .global intel_setup .global intel_cleanup .extern wait_usec # #==================================================================== # # Read manufacturer ID from Flash-EPROM # Input: BX - Pointer to interface definition structure # Output: SI - Pointer to Flash EPROM info structure, zero if no # Flash EPROM found # Changed registers: AX, SI # intel_readid: push edx push edi # Read the manufacturer and device ID from the chip, if there is a # chip. It is the responsibility of the caller to ensure that this # routine does not write into RAM. call intel_setup # turn Vpp on jc rdid8 xor edi,edi # set address for manufacturer ID mov al,READID_CMD call [bx + ISTRUCT_WRITE] # send read-ID command call [bx + ISTRUCT_READ] # read manufacturer ID mov dl,al inc edi # set address for device ID mov al,READID_CMD call [bx + ISTRUCT_WRITE] # send read-ID command again call [bx + ISTRUCT_READ] # read device ID mov dh,al call intel_cleanup # finally turn Vpp off # Now find the chip in the list of supported Flash EPROMS. rdid2: mov si,offset cstruct_list rdid3: mov ax,[si + FSTRUCT_INTID] or ax,ax # check if end of list jz rdid8 cmp dx,[si + FSTRUCT_ID] # find chip ID in chip list je rdid5 add si,FSTRUCT_ISIZE jmp rdid3 rdid5: mov [curchip],si # save pointer to current chip jmp rdid9 # definition structure rdid8: xor si,si rdid9: pop edi pop edx ret # #==================================================================== # # Setup Flash EPROM access. This just sets the programming voltage. # Input: BX - Pointer to interface definition structure # Output: Carry flag set if error # Changed registers: AX # intel_setup: call [bx + ISTRUCT_VPPON] # turn Vpp on jc setup9 mov ax,VPPTIME # wait until Vpp settles call wait_usec mov byte ptr [iniflg],0x01 clc setup9: ret # #==================================================================== # # Cleanup Flash EPROM access. This just turns the programming voltage off. # Input: BX - Pointer to interface definition structure # Output: Carry flag set if error # Changed registers: AX # intel_cleanup: push edi xor edi,edi xor al,al call [bx + ISTRUCT_WRITE] # write read command pop edi mov ax,VERIFYTIME call wait_usec # wait until returned to data mode call [bx + ISTRUCT_VPPOFF] # turn Vpp off jc clean9 mov ax,VPPTIME # wait until Vpp settles call wait_usec mov byte ptr [iniflg],0x00 clc clean9: ret # #==================================================================== # # Erase the memory area occupied by the rom image. This is a really # awkward matter, because we first have to program all bytes to 00 # before we can erase the chip. And after erasing, we have to check # that really all bytes are FF. This whole process can take minutes! # Input: BX - Pointer to interface definition structure # EDI - Offset to rom image block within EPROM # ECX - Number of bytes to erase # Output: carry flag set if error # Registers changed: EAX # intel_erase: push edx push ecx push edi push si mov si,[curchip] mov eax,edi add eax,ecx cmp eax,[si + FSTRUCT_ROMSIZE] jae erase8 # check if EPROM size exceeded test byte ptr [iniflg],0xFF # check if programming enabled jz erase8 mov [imgstart],edi # save values for later reference mov [imgend],eax mov [imglen],ecx # First we have to make sure that all bytes in the Flash EPROM do have # a value of zero. xor edi,edi erase1: call [bx + ISTRUCT_READ] or al,al # check if byte is zero jz erase2 xor al,al call progbyte # program byte to zero xor al,al call [bx + ISTRUCT_WRITE] # return to data mode erase2: inc edi cmp edi,[si + FSTRUCT_ROMSIZE] jb erase1 # check if all bytes processed # Now we can erase the chip. xor edi,edi xor cx,cx erase3: mov al,ERASE1_CMD call [bx + ISTRUCT_WRITE] # write erase command mov al,ERASE1_CMD call [bx + ISTRUCT_WRITE] # write erase command again mov ax,ERASETIME call wait_usec # wait for erasure erase4: mov al,ERASE2_CMD call [bx + ISTRUCT_WRITE] # write erase-verify command mov ax,VERIFYTIME call wait_usec # wait for verify call [bx + ISTRUCT_READ] # read erased byte cmp al,0xFF # check if really erased je erase5 loop erase3 # retry erasure mov al,RESET_CMD call [bx + ISTRUCT_WRITE] # in case of error abort erasure mov ax,VERIFYTIME call wait_usec # wait until reset completed jmp erase8 erase5: inc edi # continue with next byte cmp edi,[si + FSTRUCT_ROMSIZE] jb erase4 clc # erase completed jmp erase9 erase8: stc erase9: pop si pop edi pop ecx pop edx ret # #==================================================================== # # Program one byte into Flash EPROM chip # Input: BX - Pointer to interface definition structure # AL - Byte value to program # EDI - Offset into Flash EPROM # Output: carry flag set if error # Registers changed: EAX # intel_doprog: cmp edi,[imgstart] jb iprog8 # check if address is within limits cmp edi,[imgend] jae iprog8 call progbyte # program byte into Flash EPROM jmp iprog9 iprog8: stc iprog9: ret # #==================================================================== # # Program one byte into Flash EPROM chip. This is an internal routine, # which avoids checking the image boundaries. # Input: BX - Pointer to interface definition structure # AL - Byte value to program # EDI - Offset into Flash EPROM # Output: carry flag set if error # Registers changed: EAX # progbyte: push cx push dx push edi test byte ptr [iniflg],0xFF # check if programming enabled jz prog8 mov cx,PROGRETRY prog1: push ax mov al,PROG1_CMD call [bx + ISTRUCT_WRITE] # send setup-program command pop ax call [bx + ISTRUCT_WRITE] # write data push ax mov ax,PROGTIME call wait_usec # wait 10 microseconds mov al,PROG2_CMD call [bx + ISTRUCT_WRITE] # write program-verify command mov ax,VERIFYTIME call wait_usec # wait 6 microseconds call [bx + ISTRUCT_READ] # read data mov dl,al pop ax cmp al,dl # check if data is what we programmed je prog9 loop prog1 # retry programming prog8: stc prog9: pop edi pop dx pop cx ret # #==================================================================== # # String and constants definitions # \(.data) # Names of Flash EPROM chips which can be used by this program name50: .asciz "I28F512" name51: .asciz "I28F010" name52: .asciz "I28F020" name60: .asciz "AM28F512" name61: .asciz "AM28F010" name70: .asciz "CAT28F512" name71: .asciz "CAT28F010" name72: .asciz "CAT28F020" # List of Flash EPROM definition structures cstruct_list: # Intel chips .word CHIP_I28F512 # internal chip ID number .word name50 # offset to chip name .long 65536 # total size in bytes .byte 0x89, 0xB8 # chip ID code .word CHIP_I28F010 .word name51 .long 131072 .byte 0x89, 0xB4 .word CHIP_I28F020 .word name52 .long 262144 .byte 0x89, 0xBD # AMD chips .word CHIP_AM28F512 .word name60 .long 65536 .byte 0x01, 0x25 .word CHIP_AM28F010 .word name61 .long 131072 .byte 0x01, 0xA7 # Catalyst chips .word CHIP_CAT28F512 .word name70 .long 65536 .byte 0x31, 0xB8 .word CHIP_CAT28F010 .word name71 .long 131072 .byte 0x31, 0xB4 .word CHIP_CAT28F020 .word name72 .long 262144 .byte 0x31, 0xBD .word 0 # end of list # #==================================================================== # # Variable definitions # \(.bss) .lcomm curchip,2 # pointer to current chip structure .lcomm imgstart,4 # start offset of rom image .lcomm imgend,4 # end offset of rom image .lcomm imglen,4 # length of rom image .lcomm iniflg,1 # flag if initialized # #==================================================================== # .end