# rtl8139.S86 - Routines for supporting RTL8139 cards # # 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: rtl8139.S86,v 1.1 2003/03/09 00:43:09 gkminix Exp $ # #==================================================================== # #include "common.i86" #include "flash.i86" .file "rtl8139.S86" .line 30 # #==================================================================== # # Some definitions which are local to this module # PCI_VENDOR .equ H'10EC # Realtek PCI vendor ID # RTL8139 PCI configuration registers PCI_IOBASE .equ H'0010 # I/O base address register PCI_IOADDRMASK .equ H'FFFFFFF0 # Mask to select I/O base address PCI_IOENABMASK .equ H'00000001 # Mask to select I/O register access PCI_ROMBASE .equ H'0030 # ROM base address register PCI_ROMADDRMASK .equ H'FFFFF800 # Mask to select ROM base address PCI_ROMENABMASK .equ H'00000001 # Mask to select ROM enable bit PCI_HEADERTYPE .equ H'000E # PCI header type PCI_DEFHEADER .equ H'00 # Default PCI header type # RTL8139 internal registers CONFIG0 .equ H'0051 # Configuration register 0 ROMSIZE_MASK .equ H'07 # Mask for Flash ROM size .line 61 # #==================================================================== # # Define some external routines # \(.text) # The RTL8139 NIC only supports Flash EPROMs which get programmed # using the AMD programming algorithm. .extern amd_readid # read Flash EPROM ID .extern amd_erase # erase area of Flash EPROM .extern amd_doprog # program a byte into Flash EPROM .extern fndpci # find PCI device .extern chkram # check if RAM at memory area .extern gen_verify # generic verification routine # #==================================================================== # # Detect Flash EPROM interface # Input: FS:SI - Pointer to bootrom image # Output: EDI - Start offset into Flash EPROM for bootrom image # ECX - Size of Flash EPROM available for bootrom image # EAX - Linear address of Flash EPROM (zero if N/A) # DX - Offset to Flash EPROM info structure # Carry set if interface not found # Changed registers: EAX, EBX, ECX, EDX, EDI # ifdetect: push esi push es # Try to find the NIC in the system mov bx,offset nic_list mov dx,PCI_VENDOR call fndpci jc detec8 shl ax,1 mov si,ax mov ax,name_list[si] # save pointer to NIC name mov [istruct_rtl8139 + ISTRUCT_ID],ax mov [pcipfn],bx # save card identification number # The chip has to report PCI header type 0, otherwise all PCI register # offsets are wrong. mov ax,0xB108 mov di,PCI_HEADERTYPE int 0x1A # call BIOS to get PCI header type jc detec8 cmp cl,PCI_DEFHEADER # check if default header type jne detec8 # Now read the I/O base address from the PCI configuration space. Note that # we can only access the chip using I/O, not using memory mapping, so we # check for this. mov ax,0xB10A mov bx,[pcipfn] mov di,PCI_IOBASE int 0x1A # call BIOS to get I/O base address jc detec8 or ecx,ecx # ressource has to be assigned by BIOS jz detec8 test ecx,PCI_IOENABMASK # check if registers are I/O based jz detec8 and ecx,PCI_IOADDRMASK test ecx,0xFFFF0000 # I/O address has to be within 64kB jnz detec8 mov [ioaddr],cx # save I/O address # Determine the addressing size of the installed Flash ROM mov dx,cx add dx,CONFIG0 in al,dx # read config register 0 and ax,ROMSIZE_MASK shl ax,2 mov si,ax mov eax,size_table[si] # determine boot rom size from table or eax,eax # check if valid Flash EPROM size jz detec8 mov [winsize],eax # save window size # Determine the address of the installed Flash ROM. Also, we have to check # that there really is no RAM (shadow or other) at the specified address. push si mov ax,0xB10A mov bx,[pcipfn] mov di,PCI_ROMBASE int 0x1A # call BIOS to get ROM base address pop si jc detec8 test ecx,PCI_ROMENABMASK jz detec8 # check if Flash EPROM enabled and ecx,mask_table[si] jz detec8 # check if valid address cmp ecx,0x000F0000 # check that the address is within the jae detec8 # first 1MB for real mode access mov [romaddr],ecx # save linear ROM address mov ebx,ecx mov ecx,[winsize] shr ebx,4 shr ecx,4 call chkram # check if RAM within ROM area jnc detec1 shl eax,4 and eax,0x000FFFF0 # if we found some RAM, compute the size sub eax,[romaddr] # of the non-RAM area, check if it is at cmp eax,AMD_MINSIZE # least sufficient to detect the Flash jb detec8 # EPROM, and then use that size as the mov [winsize],eax # window size # We have set all internal variables so far, so we can try finding a supported # Flash EPROM chip. detec1: mov bx,offset istruct_rtl8139 call amd_readid # read ID from Flash EPROM or si,si jz detec8 mov eax,[si + FSTRUCT_ROMSIZE] cmp eax,[winsize] # check if Flash EPROM size is jb detec8 # sufficient for our ROM window mov [romsize],eax xor edi,edi # return without error mov eax,[romaddr] mov ecx,[winsize] mov dx,si jmp detec9 # Return to caller. detec8: stc # return with error detec9: pop es pop esi ret # #==================================================================== # # Read one byte from Flash EPROM. # Input: EDI - Offset into Flash EPROM # Output: AL - Byte value # Changed registers: AL # ifread: push es push edi xor al,al cmp edi,[winsize] # check if offset is within limits jae read9 push eax add edi,[romaddr] mov eax,edi shr eax,4 # compute pointer to byte mov es,ax and di,0x000F pop eax mov al,es:[di] # get byte from Flash EPROM read9: pop edi pop es ret # #==================================================================== # # Write one byte into Flash EPROM. # Input: EDI - Offset into Flash EPROM # AL - Byte value # Output: none # Changed registers: none # ifwrite: push es push edi cmp edi,[winsize] # check if offset is within limits jae write9 push eax add edi,[romaddr] mov eax,edi shr eax,4 # compute pointer to byte mov es,ax and di,0x000F pop eax mov es:[di],al # put byte into Flash EPROM write9: pop edi pop es ret # #==================================================================== # # Initialize NIC for programming. # Input: none # Output: none # Changed registers: none # ifinit: # fall through # #==================================================================== # # Terminate programming. # Input: none # Output: none # Changed registers: none # ifclean: clc ret # #==================================================================== # # Turn programming voltage VPP on # Input: none # Output: none # Changed registers: none # ifvppon: # fall through # #==================================================================== # # Turn programming voltage VPP off # Input: none # Output: none # Changed registers: none # ifvppoff: stc ret # #==================================================================== # # Erase the Flash EPROM area occupied by the rom image. We simply call # the routine for the Flash EPROM chip. # Input: EDI - Offset to rom image block within EPROM # ECX - Number of bytes to erase # Output: carry flag set if error # Registers changed: EAX # iferase: push bx mov bx,offset istruct_rtl8139 call amd_erase # call chip erasure routine pop bx ret # #==================================================================== # # Program a memory area into the Flash EPROM. # Input: FS:SI - Pointer to memory area with source data # ECX - Number of bytes to program # EDI - Offset to rom image block within EPROM # Output: carry flag set if error # Registers changed: EAX # ifprog: push bx push ecx push edi push si push fs mov bx,offset istruct_rtl8139 prog1: mov al,fs:[si] call amd_doprog # program one byte into Flash EPROM jc prog9 inc si # increment source pointer test si,0x8000 jz prog2 # avoid source pointer overflow mov ax,fs add ax,0x0800 mov fs,ax and si,0x7FFF prog2: inc edi # increment offset into Flash EPROM data32 loop prog1 # continue with next byte clc prog9: pop fs pop si pop edi pop ecx pop bx ret # #==================================================================== # # Verify a memory area against the contents of the Flash EPROM. # Input: FS:SI - Pointer to memory area with source data # ECX - Number of bytes to verify # EDI - Offset to rom image block within EPROM # Output: carry flag set if error # Registers changed: EAX # ifverify: push bx mov bx,offset istruct_rtl8139 call gen_verify # call generic routine pop bx ret # #==================================================================== # # String and constants definitions # \(.data) .global istruct_rtl8139 # List of NICs supported by this module pci_list: .word PCI_VENDOR nic_list: .word 0x8139 .word 0x8138 .word 0 # NIC names name_8139: .asciz "Realtek RTL8139(C)" name_8138: .asciz "Realtek RTL8139B" name_list: .word name_8139 .word name_8138 # Interface definition istruct_rtl8139: .word 0 # pointer to interface name .word IDEVTYPE_PCI # interface device type .word pci_list # pointer to PCI ID list .word ifdetect # pointer to detection routine .word ifread # pointer to byte read routine .word ifwrite # pointer to byte write routine .word ifvppon # pointer to VPP-on routine .word ifvppoff # pointer to VPP-off routine .word ifinit # pointer to initialization routine .word ifclean # pointer to cleanup routine .word iferase # pointer to erase routine .word ifprog # pointer to programming routine .word ifverify # pointer to verify routine .word 0 # no loader necessary .word IFLAGS_NEEDMEM # interface needs direct memory access # Table to translate the value of config register 0 into the Flash ROM size size_table: .long 0 # no Flash EPROM installed .long 8192 # 8kB Flash EPROM .long 16384 # 16kB Flash EPROM .long 32768 # 32kB Flash EPROM .long 65536 # 64kB Flash EPROM .long 131072 # 128kB Flash EPROM .long 0 # invalid .long 0 # invalid # Table to translate the value of config register 0 into a mask for the # Flash ROM base address. Note that these masks have to make the base # address paragraph aligned. mask_table: .long 0 # no flash EPROM installed .long 0xFFFFE000 # 8kB Flash EPROM .long 0xFFFFC000 # 16kB Flash EPROM .long 0xFFFF8000 # 32kB Flash EPROM .long 0xFFFF0000 # 64kB Flash EPROM .long 0xFFFE0000 # 128kB Flash EPROM .long 0 # invalid .long 0 # invalid # #==================================================================== # # Variable definitions # \(.bss) .lcomm pcipfn,2 # PCI identification number for card .lcomm ioaddr,2 # I/O address for register access .lcomm romaddr,4 # base address of Flash ROM .lcomm romsize,4 # size of physical Flash ROM .lcomm winsize,4 # size of Flash ROM window # #==================================================================== # .end