# misc.S86 - Misc. routines for flash EPROM programmer # # Copyright (C) 2002-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: misc.S86,v 1.1 2003/03/09 00:43:09 gkminix Exp $ # #==================================================================== # #include "common.i86" #include "flash.i86" .file "misc.S86" .line 30 # #==================================================================== # # Some definitions which are local to this module # # # I/O ports used for the sound generator # SPKTMR .equ H'42 # 8253 port to set the sound frequency KBCTL .equ H'61 # PPI port for the keyboard controller # Base clock in MHz times 100 of 8253 timer STD_CLOCK_LOW .equ 42480 STD_CLOCK_HIGH .equ 1820 .line 50 # #==================================================================== # # Define some external routines # \(.text) .extern set_ticks .extern chk_timeout .global fndpci .global fndpnp .global chkram .global gen_verify .global play # #==================================================================== # # Find a PCI interface # Input: FS:SI - Pointer to bootrom image # BX - Offset to list of device IDs # DX - Allowed vendor ID # Output: AX - Index into device table # BX - PCI PFN # Carry set if interface not found # Changed registers: EAX, EBX, ECX, EDX # fndpci: push edi push esi push bx push dx push bp mov bp,sp # use BP to access caller values # First check if we have a PCI BIOS at all test byte ptr [pciini],0xFF jnz fndpc1 # check if checked already mov ax,0xB101 xor edi,edi int 0x1A # call BIOS installation check jc fndpc8 or ah,ah # check if PCI BIOS installed jnz fndpc8 cmp edx,0x20494350 jne fndpc8 inc byte ptr [pciini] # Now determine the PCI vendor and device ID's from bootrom image and then # try to find the device ID in the caller-provided list of allowed device IDs. fndpc1: cld mov di,[bp + 0x0006] mov si,fs:[di + ROMPCIHDR] # get pointer to PCI header or si,si jz fndpc8 add si,di mov dx,fs:[si + PCIVENDORID] mov cx,fs:[si + PCIDEVICEID] cmp dx,[bp + 0x0002] # check if vendor ID allowed jne fndpc8 mov si,[bp + 0x0004] fndpc2: lodsw # get next device ID or ax,ax jz fndpc8 # error if not found cmp ax,cx jne fndpc2 # continue with next device ID sub si,[bp + 0x0004] # compute index into table shr si,1 dec si mov [bp + 0x0004],si # save it for function return # Finally check if the device is installed at all by calling the BIOS. mov ax,0xB102 xor si,si # we better save them int 0x1A # call BIOS to find first device jc fndpc8 or ah,ah # check if NIC is installed jz fndpc9 fndpc8: stc fndpc9: pop bp pop dx pop ax pop esi pop edi ret # #==================================================================== # # Find a PnP signature in the bootrom # Input: FS:SI - Pointer to bootrom image # BX - Offset to list of device IDs # Output: BX - Device index # EDX - PnP vendor and device ID # Carry set if signature not found # Changed registers: AX, BX, CX, EDX # fndpnp: push si push di mov di,fs:[si + ROMPNPHDR] # get pointer to PnP header within or di,di # bootrom jz fndpn8 add di,si # FS:DI points to PnP header mov si,bx # DS:SI points to list of PnP IDs cld xor bx,bx # BX becomes device index fndpn1: xor edx,edx # EDX becomes the binary device ID lodsb or al,al jz fndpn8 sub al,0x40 # convert first character shl al,2 or dl,al lodsb sub al,0x40 # convert second character mov ah,al shr al,3 or dl,al shl ah,5 or dh,ah lodsb sub al,0x40 # convert third character or dh,al mov cx,4 fndpn3: shl edx,4 lodsb # get next hex char of PnP ID sub al,0x30 cmp al,0x10 # convert it into binary jb fndpn4 sub al,0x07 fndpn4: and al,0x0F or dl,al # put it into EDX and continue with loop fndpn3 # next character xchg dl,dh rol edx,16 # convert EDX into memory format cmp edx,fs:[di + PNPDEVID] # check if its the required device ID je fndpn9 inc bx # no, continue with next ID string jmp fndpn1 fndpn8: stc fndpn9: pop di pop si ret # #==================================================================== # # Check that there is no RAM at a given paragraph address range. # Input: BX - Segment to check # CX - Number of segments to check # Output: AX - Last checked segment # carry flag set if RAM found # Registers changed: AX # chkram: push es push bx mov ax,bx add bx,cx # BX points to the end of the scan area ckram1: mov es,ax cli mov al,es:[0] mov ah,al not al # read first byte of paragraph, invert mov es:[0],al # all bits, write it back and the read xchg es:[0],ah # it again sti cmp al,ah # check if it was possible to write the je ckram8 # modified value, we have RAM mov ax,es inc ax cmp ax,bx # continue with next paragraph jb ckram1 dec ax jmp ckram9 ckram8: stc # return with error mov ax,es ckram9: pop bx pop es ret # #==================================================================== # # Verify a memory area against the contents of the Flash EPROM. This # is a generic routine which uses the read routine of the interface module. # If an interface requires a special routine for verification, this generic # one cant be used. # Input: FS:SI - Pointer to memory area with source data # ECX - Number of bytes to verify # EDI - Offset to rom image block within EPROM # BX - Pointer to interface definition structure # Output: carry flag set if error # Registers changed: EAX # gen_verify: push ecx push edi push si push fs vrfy1: call [bx + ISTRUCT_READ] # read next byte from Flash EPROM cmp al,fs:[si] # check if its the same as in the stc # source image jnz vrfy9 inc si # increment source pointer test si,0x8000 jz vrfy2 # avoid source pointer overflow mov ax,fs add ax,0x0800 mov fs,ax and si,0x7FFF vrfy2: inc edi # increment offset into Flash EPROM data32 loop vrfy1 # continue with next byte clc # return without error vrfy9: pop fs pop si pop edi pop ecx ret # #==================================================================== # # Turn speaker on # Input: none # Output: none # Registers changed: AL # spkr_on: in al,KBCTL or al,0x03 # turn speaker output on out KBCTL,al ret # #==================================================================== # # Turn speaker off # Input: none # Output: none # Registers changed: AL # spkr_off: in al,KBCTL and al,0xFC # turn speaker output off out KBCTL,al ret # #==================================================================== # # Set speaker frequency # Input: BX - speaker frequency in HZ # Output: none # Registers changed: AX, BX, DX # spkr_freq: or bx,bx jz spkrf1 mov dx,STD_CLOCK_HIGH mov ax,STD_CLOCK_LOW # compute number of timer ticks for div bx # given frequency mov bx,ax spkrf1: mov al,0xB6 out SPKTMR + 1,al # write new count into timer chip mov al,bl out SPKTMR,al mov al,bh out SPKTMR,al ret # #==================================================================== # # Play a sound # Input: BX - speaker frequency in HZ # CX - duration of sound in timer ticks # Output: none # Registers changed: AX, BX, DX # sound: or bx,bx jnz sound1 call spkr_off # turn speaker off if frequency jmp sound2 # is zero sound1: call spkr_freq # set frequency call spkr_on # turn speaker on sound2: mov ax,cx xor dx,dx call set_ticks sound3: call chk_timeout # wait until time elapsed jnc sound3 call spkr_off # turn speaker off ret # #==================================================================== # # Play a sequence of sounds # Input: SI - offset to list of sounds # Output: none # Registers changed: AX # play: cld push bx push dx play1: lodsw or ax,ax jz play9 mov cx,ax # read all tick/frequency pairs lodsw # and play them in sequence mov bx,ax call sound jmp play1 play9: pop dx pop bx ret # #==================================================================== # # Variable definitions # \(.bss) .lcomm pciini,1 # flag if PCI interface initialized # #==================================================================== # .end