summaryrefslogtreecommitdiffstats
path: root/contrib/flashimg/flashimg.asm
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/flashimg/flashimg.asm')
-rw-r--r--contrib/flashimg/flashimg.asm497
1 files changed, 497 insertions, 0 deletions
diff --git a/contrib/flashimg/flashimg.asm b/contrib/flashimg/flashimg.asm
new file mode 100644
index 00000000..7a37ed54
--- /dev/null
+++ b/contrib/flashimg/flashimg.asm
@@ -0,0 +1,497 @@
+; 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: