123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497 |
- ; Copyright (C) 1997 Markus Gutschke <gutschk@uni-muenster.de>
- ;
- ; 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.
-
- ; Prepend this image file to an arbitrary ROM image. The resulting binary
- ; can be loaded from any BOOT-Prom that supports the "nbi" file format.
- ; When started, the image will reprogram the flash EPROM on the FlashCard
- ; ISA card. The flash EPROM has to be an AMD 29F010, and the programming
- ; algorithm is the same as that suggested by AMD in the appropriate data
- ; sheets.
-
-
- #define SEGLOW 0xC800 /* lower range for EPROM segment */
- #define SEGHIGH 0xE800 /* upper range for EPROM segment */
- #define AMD_ID 0x2001 /* flash EPROM ID, only support AMD */
- #define ERASE1_CMD 0x80 /* first cmd for erasing full chip */
- #define ERASE2_CMD 0x10 /* second cmd for erasing full chip */
- #define READID_CMD 0x90 /* cmd to read chip ID */
- #define PROG_CMD 0xA0 /* cmd to program a byte */
- #define RESET_CMD 0xF0 /* cmd to reset chip state machine */
-
- ;----------------------------------------------------------------------------
-
-
- .text
- .org 0
-
- ; .globl _main
- _main: mov ax,#0x0FE0
- mov ds,ax
- mov ax,magic ; verify that we have been loaded by
- cmp ax,#0xE4E4 ; boot prom
- jnz lderr
- jmpi 0x200,0x0FE0 ; adjust code segment
- lderr: mov si,#loaderr
- cld
- lderrlp:seg cs
- lodsb ; loop over all characters of
- or al,al ; string
- jnz lderrnx
- xor ah,ah
- int 0x16 ; wait for keypress
- jmpi 0x0000,0xFFFF ; reboot!
- lderrnx:mov ah,#0x0E ; print it
- mov bl,#0x07
- xor bh,bh
- int 0x10
- jmp lderrlp
-
- loaderr:.ascii "The flash EPROM utility has to be loaded from a BOOT-Prom"
- .byte 0xa,0xd
- .ascii "that knows about the 'nbi' file format!"
- .byte 0xa,0xd
- .ascii "Reboot to proceed..."
- .byte 0
-
- .org 510
- .byte 0x55,0xAA
-
- !----------------------------------------------------------------------------
-
- start: mov ax,cs
- mov ds,ax
- mov ax,romdata ; verify that there is an Prom image
- cmp ax,#0xAA55 ; attached to the utility
- jnz resmag
- mov al,romdata+2
- or al,al ; non-zero size is required
- jnz magicok
- resmag: mov si,#badmagic ; print error message
- reset: call prnstr
- xor ah,ah
- int 0x16 ; wait for keypress
- jmpi 0x0000,0xFFFF ; reboot!
- magicok:mov di,#clrline1
- mov si,#welcome ; print welcome message
- inpnew: call prnstr
- inprest:xor bx,bx
- mov cl,#0xC ; expect 4 nibbles input data
- inploop:xor ah,ah
- int 0x16
- cmp al,#0x8 ; <Backspace>
- jnz inpnobs
- or bx,bx ; there has to be at least one input ch
- jz inperr
- mov si,#delchar ; wipe out char from screen
- call prnstr
- add cl,#4 ; compute bitmask for removing input
- mov ch,cl
- mov cl,#0xC
- sub cl,ch
- mov ax,#0xFFFF
- shr ax,cl
- not ax
- and bx,ax
- mov cl,ch
- inploop1:jmp inploop
- inpnobs:cmp al,#0x0D ; <Return>
- jnz inpnocr
- or bx,bx ; zero input -> autoprobing
- jz inpdone
- cmp cl,#-4 ; otherwise there have to be 4 nibbles
- jz inpdone
- inperr: mov al,#7 ; ring the console bell
- jmp inpecho
- inpnocr:cmp al,#0x15 ; <CTRL-U>
- jnz inpnokl
- mov si,di
- call prnstr ; clear entire input and restart
- jmp inprest
- inpnokl:cmp cl,#-4 ; cannot input more than 4 nibbles
- jz inperr
- cmp al,#0x30 ; '0'
- jb inperr
- ja inpdig
- or bx,bx ; leading '0' is not allowed
- jz inperr
- inpdig: cmp al,#0x39 ; '9'
- ja inpnodg
- mov ch,al
- sub al,#0x30
- inpnum: xor ah,ah ; compute new input value
- shl ax,cl
- add ax,bx
- test ax,#0x1FF ; test for 8kB boundary
- jnz inperr
- cmp ax,#SEGHIGH ; input has to be below E800
- jae inperr
- cmp ax,#SEGLOW ; and above/equal C800
- jae inpok
- cmp cl,#0xC ; if there is just one nibble, yet,
- jnz inperr ; then the lower limit ix C000
- cmp ax,#0xC000
- jb inperr
- inpok: mov bx,ax ; adjust bitmask
- sub cl,#4
- mov al,ch
- inpecho:call prnchr ; output new character
- jmp inploop1
- inpnodg:and al,#0xDF ; lower case -> upper case
- cmp al,#0x41 ; 'A'
- jb inperr
- cmp al,#0x46 ; 'F'
- ja inperr
- mov ch,al
- sub al,#0x37
- jmp inpnum
- inpdone:or bx,bx ; zero -> autoprobing
- jnz probe
- mov si,#automsg
- call prnstr
- mov cx,#0x10
- mov bx,#SEGHIGH ; scan from E800 to C800
- autoprb:sub bx,#0x0200 ; stepping down in 8kB increments
- mov di,bx
- call readid
- cmp ax,#AMD_ID
- jz prbfnd
- loop autoprb
- mov si,#failmsg
- nofnd: mov di,#clrline2
- jmp near inpnew ; failure -> ask user for new input
- probe: mov di,bx
- test bx,#0x07FF ; EPROM might have to be aligned to
- jz noalign ; 32kB boundary
- call readid
- cmp ax,#AMD_ID ; check for AMDs id
- jz prbfnd
- mov si,#alignmsg
- call prnstr
- and bx,#0xF800 ; enforce alignment of hardware addr
- noalign:call readid ; check for AMDs id
- cmp ax,#AMD_ID
- jz prbfnd
- mov si,#nofndmsg ; could not find any EPROM at speci-
- call prnstr ; fied location --- even tried
- mov si,#basemsg ; aligning to 32kB boundary
- jmp nofnd ; failure -> ask user for new input
- prbfnd: mov si,#fndmsg
- call prnstr ; we found a flash EPROM
- mov ax,bx
- call prnwrd
- mov si,#ersmsg
- call prnstr
- call erase ; erase old contents
- jnc ersdone
- mov si,#failresmsg ; failure -> reboot machine
- jmp near reset
- ersdone:mov si,#prg1msg ; tell user that we are about
- call prnstr ; to program the new data into
- mov ax,di ; the specified range
- call prnwrd
- mov si,#prg2msg
- call prnstr
- xor dh,dh
- mov dl,romdata+2
- shl dx,#1
- mov ah,dh
- mov cl,#4
- shl ah,cl
- xor al,al
- add ax,di
- call prnwrd
- mov al,#0x3A ; ':'
- call prnchr
- mov ah,dl
- xor al,al
- dec ax
- call prnwrd
- mov al,#0x20
- call prnchr
- mov dh,romdata+2 ; number of 512 byte blocks
- push ds
- mov ax,ds
- add ax,#romdata>>4 ; adjust segment descriptor, so that
- mov ds,ax ; we can handle images which are
- prgloop:mov cx,#0x200 ; larger than 64kB
- xor si,si
- xor bp,bp
- call program ; program 512 data bytes
- jc prgerr ; check error condition
- mov ax,ds
- add ax,#0x20 ; increment segment descriptors
- mov ds,ax
- add di,#0x20
- dec dh ; decrement counter
- jnz prgloop
- pop ds
- mov si,#donemsg ; success -> reboot
- prgdone:call prnstr
- mov si,#resetmsg
- jmp near reset
- prgerr: pop ds ; failure -> reboot
- mov si,#failresmsg
- jmp prgdone
-
-
- ;----------------------------------------------------------------------------
-
- ; READID -- read EPROM id number, base address is passed in BX
- ; ======
- ;
- ; changes: AX, DL, ES
-
- readid: mov dl,#RESET_CMD ; reset chip
- call sendop
- mov dl,#READID_CMD
- call sendop ; send READID command
- mov es,bx
- seg es
- mov ax,0x00 ; read manufacturer ID
- mov dl,#RESET_CMD
- jmp sendop ; reset chip
-
-
- ;----------------------------------------------------------------------------
-
- ; ERASE -- erase entire EPROM, base address is passed in BX
- ; =====
- ;
- ; changes: AL, CX, DL, ES, CF
-
- erase: mov dl,#ERASE1_CMD
- call sendop ; send ERASE1 command
- mov dl,#ERASE2_CMD
- call sendop ; send ERASE2 command
- xor bp,bp
- mov al,#0xFF
- push di
- mov di,bx
- call waitop ; wait until operation finished
- pop di
- jnc erfail
- mov dl,#RESET_CMD
- call sendop ; reset chip
- stc
- erfail: ret
-
-
- ;----------------------------------------------------------------------------
-
- ; PROGRAM -- write data block at DS:SI of length CX into EPROM at DI:BP
- ; =======
- ;
- ; changes: AX, CX, DL, BP, ES, CF
-
- program:mov dl,#PROG_CMD
- call sendop ; send programming command
- lodsb ; get next byte from buffer
- mov es,di
- seg es
- mov byte ptr [bp],al ; write next byte into flash EPROM
- call waitop ; wait until programming operation is
- jc progdn ; completed
- inc bp
- loop program ; continue with next byte
- clc ; return without error
- progdn: ret
-
-
- ;----------------------------------------------------------------------------
-
- ; SENDOP -- send command in DL to EPROM, base address is passed in BX
- ; ======
- ;
- ; changes: ES
-
- sendop: mov es,bx
- seg es
- mov byte ptr 0x5555,#0xAA ; write magic data bytes into
- jcxz so1 ; magic locations. This unlocks
- so1: jcxz so2 ; the flash EPROM. N.B. that the
- so2: seg es ; magic locations are mirrored
- mov byte ptr 0x2AAA,#0x55 ; every 32kB; the hardware address
- jcxz so3 ; might have to be adjusted to a
- so3: jcxz so4 ; 32kB boundary
- so4: seg es
- mov byte ptr 0x5555,dl
- ret
-
-
- ;----------------------------------------------------------------------------
-
- ; WAITOP -- wait for command to complete, address is passed in DI:BP
- ; ======
- ;
- ; for details on the programming algorithm, c.f. http://www.amd.com
- ;
- ; changes: AX, DL, ES, CF
-
- waitop: and al,#0x80 ; monitor bit 7
- mov es,di
- wait1: seg es ; read contents of EPROM cell that is
- mov ah,byte ptr [bp] ; being programmed
- mov dl,ah
- and ah,#0x80
- cmp al,ah ; bit 7 indicates sucess
- je waitok
- test dl,#0x20 ; bit 5 indicates timeout/error
- jz wait1 ; otherwise wait for cmd to complete
- seg es
- mov ah,byte ptr [bp] ; check error condition once again,
- and ah,#0x80 ; because bits 7 and 5 can change
- cmp al,ah ; simultaneously
- je waitok
- stc
- ret
- waitok: clc
- ret
-
- ;----------------------------------------------------------------------------
-
- ; PRNSTR -- prints a string in DS:SI onto the console
- ; ======
- ;
- ; changes: AL
-
- prnstr: push si
- cld
- prns1: lodsb ; loop over all characters of
- or al,al ; string
- jz prns2
- call prnchr ; print character
- jmp prns1
- prns2: pop si
- ret
-
-
- ;----------------------------------------------------------------------------
-
- ; PRNWRD, PRNBYT, PRNNIB, PRNCHR -- prints hexadezimal values, or ASCII chars
- ; ====== ====== ====== ======
- ;
- ; changes: AX
-
- prnwrd: push ax
- mov al,ah
- call prnbyt ; print the upper byte
- pop ax
- prnbyt: push ax
- shr al,1 ; prepare upper nibble
- shr al,1
- shr al,1
- shr al,1
- call prnnib ; print it
- pop ax
- prnnib: and al,#0x0F ; prepare lower nibble
- add al,#0x30
- cmp al,#0x39 ; convert it into hex
- jle prnchr
- add al,#7
- prnchr: push bx
- mov ah,#0x0E ; print it
- mov bl,#0x07
- xor bh,bh
- int 0x10
- pop bx
- ret
-
-
- ;----------------------------------------------------------------------------
-
- magic: .byte 0xE4,0xE4
-
- badmagic:.byte 0xa,0xd
- .ascii "There does not appear to be a ROM image attached to the"
- .ascii "flash EPROM utility;"
- .byte 0xa,0xd
- resetmsg:.ascii "Reboot to proceed..."
- .byte 0
-
- welcome:.byte 0xa,0xd
- .ascii "Flash EPROM programming utility V1.0"
- .byte 0xa,0xd
- .ascii "Copyright (c) 1997 by M. Gutschke <gutschk@uni-muenster.de>"
- .byte 0xa,0xd
- .ascii "==========================================================="
- .byte 0xa,0xd
- prompt: .byte 0xa,0xd
- .ascii "Enter base address for AMD29F010 flash EPROM on FlashCard or"
- .byte 0xa,0xd
- .ascii "press <RETURN> to start autoprobing; the base address has"
- .byte 0xa
- clrline1:.byte 0xd
- .ascii "to be in the range C800..E600: "
- .ascii " "
- .byte 0x8,0x8,0x8,0x8
- .byte 0
-
- delchar:.byte 0x8,0x20,0x8
- .byte 0
-
- automsg:.ascii "autoprobing... "
- .byte 0
-
- failmsg:.ascii "failed!"
- basemsg:.byte 0xa
- clrline2:.byte 0xd
- .ascii "Enter base address: "
- .ascii " "
- .byte 0x8,0x8,0x8,0x8
- .byte 0
-
- fndmsg: .byte 0xa,0xd
- .ascii "Found flash EPROM at: "
- .byte 0
-
- alignmsg:.byte 0xa,0xd
- .ascii "FlashCard requires the hardware address to be aligned to a"
- .byte 0xa,0xd
- .ascii "32kB boundary; automatically adjusting..."
- .byte 0
-
- nofndmsg:.byte 0xa,0xd
- .ascii "No AMD29F010 flash EPROM found"
- .byte 0
-
- ersmsg: .byte 0xa,0xd
- .ascii "Erasing old contents... "
- .byte 0
-
- prg1msg:.ascii "done"
- .byte 0xa,0xd
- .ascii "Programming from "
- .byte 0
-
- prg2msg:.ascii ":0000 to "
- .byte 0
-
- donemsg:.ascii "done!"
- .byte 0xa,0xd
- .byte 0
-
- failresmsg:
- .ascii "failed!"
- .byte 0xa,0xd
- .byte 0
-
-
- ;----------------------------------------------------------------------------
-
- .align 16
- .org *-1
- .byte 0x00
- romdata:
|