/*
 * 3c90xbc.S86  -  Routines for supporting 3C90xB/C cards
 *
 * Copyright (C) 2002-2007 Gero Kuhlmann   <gero@gkminix.han.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.
 *
 * $Id: 3c90xbc.S86,v 1.8 2007/01/08 22:02:20 gkminix Exp $
 *
 *====================================================================
 */
#include <common.i86>
#include <system/bios.i86>
#include <system/pci.i86>
#include "flash.i86"

.file __FILE__
.line __LINE__



/*
 *====================================================================
 *
 * Some definitions which are local to this module
 */
#define PCI_VENDOR	0x10B7		/* 3Com PCI vendor ID */
#define EEPROM_VENDOR	0x6D50		/* Manufacturer ID */


/*
 * 3C90xB/C on-chip registers
 */
#define STATUS_REG	0x000E		/* NIC status register */
#define CMD_REG		0x000E		/* NIC command register */
#define CMD_SELBANK	0x0800		/* Select register bank command */

#define CONFIG_BANK	0x0003		/* Bank for accessing internal config */
#define CONFIG_REG	0x0000		/* Internal configuration register */
#define CONFIG_ROMSIZE	0x000000C0	/* Rom size value */
#define CONFIG_ROMFLG	0x02000000	/* Rom disable flag */
#define ROMSIZE_64	0x00000000	/* 64kB ROM size */
#define ROMSIZE_128	0x00000040	/* 128kB ROM size */

#define ROM_BANK	0x0000		/* Bank for accessing ROM registers */
#define ROM_ADDR	0x0004		/* Addr for next access to Flash ROM */
#define ROM_DATA	0x0008		/* Data port for Flash ROM access */

#define EEPROM_BANK	0x0000		/* Bank for accessing EEPROM regs */
#define EEPROM_CMD	0x000A		/* EEPROM command register */
#define EEPROM_DATA	0x000C		/* EEPROM data register */

#define EEPROM_CMDMASK	0x00C0		/* EEPROM command mask */
#define EEPROM_ADRMASK	0x0F3F		/* EEPROM address mask */
#define EEPROM_READ	0x0080		/* EEPROM read command */
#define EEPROM_WRITE	0x0040		/* EEPROM write command */
#define EEPROM_ERASE	0x00C0		/* EEPROM erase command */
#define EEPROM_BUSY	0x8000		/* EEPROM busy bit */


/*
 * Values for 3C90xB/C PCI configuration registers
 */
#define PCI_IOADDRMASK	0xFFFFFFF8	/* Mask to select I/O base address */
#define PCI_IOENABMASK	0x00000001	/* Mask to select I/O register access */
#define PCI_DEFHEADER	0x00		/* Default PCI header type */


/*
 * 3C90xB/C serial EEPROM configuration data. Note that the B series NIC
 * only supports up to 64 EEPROM values, while the C series supports up
 * to 512 EEPROM values. The first couple of values are the same with all
 * NICs.
 */
#define EEPROM_ADDR0	0x0000		/* Offset to node address (word 0) */
#define EEPROM_ADDR1	0x0001		/* Offset to node address (word 1) */
#define EEPROM_ADDR2	0x0002		/* Offset to node address (word 2) */
#define EEPROM_DEVICEID	0x0003		/* Offset to PCI device ID */
#define EEPROM_MANDATE	0x0004		/* Offset to manufacturing date */
#define EEPROM_MANDIV	0x0005		/* Offset to manufacturing division */
#define EEPROM_MANPROD	0x0006		/* Offset to manufacturer prod. code */
#define EEPROM_MANID	0x0007		/* Offset to manufacturer ID */
#define EEPROM_PCIPARM	0x0008		/* Offset to PCI parameters */
#define EEPROM_ROMINFO	0x0009		/* Offset to ROM info */
#define EEPROM_MAX	10		/* max. number of EEPROM entries */


/*
 * Definitions needed for the Flash EPROM loader
 */
#define ROM_WINSIZE	8192		/* Size of 3C905B ROM window */
#define PCI_DEV_MASK	0xFFF0		/* Mask for PCI device ID */
#define PCI_DEV_3C905B	0x9050		/* PCI device ID for 3C905B */




.line __LINE__
/*
 *====================================================================
 *
 * Define some external routines
 */
	.text


/*
 * The 3C90xB/C NICs only support 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	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) or error code
 *         DX    -  Offset to Flash EPROM info structure
 *         Carry set if interface not found
 * Changed registers: EAX, EBX, ECX, EDX, EDI
 */
ifdetect:

	push	esi

/*
 * Try to find the NIC in the system
 */

	mov	word ptr [deterr],1
	mov	bx,offset nic_list
	mov	dx,PCI_VENDOR
	call	fndpci
	jc	8f
	shl	ax,1
	mov	si,ax
	mov	ax,name_list[si]	# save pointer to NIC name
	mov	istruct_id[istruct_3c90xbc],ax
	mov	[pcipfn],bx		# save card identification number

	mov	ax,nic_list[si]
	and	ax,PCI_DEV_MASK		# check if we have a 3C905B and
	cmp	ax,PCI_DEV_3C905B	# install a Flash EPROM loader
	jne	1f
	mov	word ptr istruct_loader[istruct_3c90xbc],offset ifload

/*
 * The chip has to report PCI header type 0, otherwise all PCI register
 * offsets are wrong.
 */

1:	mov	word ptr [deterr],2
	mov	ax,PCI_FUNC_READ_BYTE
	mov	di,PCI_REG_HEADER_TYPE
	int	INT_PCI			# call BIOS to get PCI header type
	jc	8f
	mov	word ptr [deterr],3
	cmp	cl,PCI_DEFHEADER	# check if default header type
	jne	8f

/*
 * 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	word ptr [deterr],4
	mov	ax,PCI_FUNC_READ_DWORD
	mov	bx,[pcipfn]
	mov	di,PCI_REG_ADDR_0
	int	INT_PCI			# call BIOS to get I/O base address
	jc	8f
	mov	word ptr [deterr],5
	or	ecx,ecx			# resource has to be assigned by BIOS
	jz	8f
	mov	word ptr [deterr],6
	test	ecx,PCI_IOENABMASK	# check if registers are I/O based
	jz	8f
	mov	word ptr [deterr],7
	and	ecx,PCI_IOADDRMASK
	test	ecx,0xFFFF0000		# I/O address has to be within 64kB
	jnz	8f
	mov	[ioaddr],cx		# save I/O address

/*
 * Read the size of the Flash EPROM from the internal configuration register.
 * We consider this size as a window size, e.g. the size which is addressable
 * by the CPU. The real size of the Flash EPROM can be larger.
 */

	call	save_bank		# save old register bank
	mov	al,CONFIG_BANK
	call	set_bank		# set bank for configuration register
	mov	dx,cx
.ifne CONFIG_REG
	add	dx,CONFIG_REG
.endif
	in	eax,dx			# read internal config register
	mov	word ptr [deterr],8
	test	eax,CONFIG_ROMFLG	# check if Flash EPROM enabled
	jnz	8f
	and	eax,CONFIG_ROMSIZE
	mov	ecx,65536
	cmp	eax,ROMSIZE_64		# determine size of Flash EPROM
	je	4f
	mov	word ptr [deterr],9
	shl	ecx,1
	cmp	eax,ROMSIZE_128
	jne	8f
4:	mov	[winsize],ecx		# save Flash EPROM window size

/*
 * Read the serial EEPROM to get configuration data, and check that we
 * indeed have a 3Com NIC.
 */

.ifne CONFIG_BANK - EEPROM_BANK
	mov	al,EEPROM_BANK
	call	set_bank		# set bank for EEPROM command register
.endif
	xor	si,si
	mov	di,offset eeprom
	mov	cx,EEPROM_MAX
5:	call	read_eeprom		# read value from serial EEPROM
	mov	[di],ax			# save value into temp storage
	add	di,2
	inc	si
	loop	5b
	mov	word ptr [deterr],10
	cmp	word ptr [eeprom + EEPROM_MANID * 2],EEPROM_VENDOR
	jne	8f

/*
 * We have set all internal variables so far, so we can try finding a supported
 * Flash EPROM chip.
 */

.ifne EEPROM_BANK - ROM_BANK
	mov	al,ROM_BANK		# set register bank to access ROM
	call	set_bank
.endif
	mov	word ptr [deterr],11
	mov	bx,offset istruct_3c90xbc
	call	amd_readid		# read ID from Flash EPROM
	or	si,si
	jz	7f
	mov	word ptr [deterr],12
	mov	ecx,fstruct_romsize[si]
	cmp	ecx,[winsize]		# check that the Flash EPROM size is
	jb	8f			# within the window size
	mov	[romsize],ecx		# save physical size of Flash EPROM
	mov	al,[oldbank]
	call	set_bank		# restore old register bank
	mov	ecx,[winsize]		# return without error
	xor	edi,edi
	xor	eax,eax
	mov	dx,si
	jmp	9f

/*
 * Return to caller. If we switched register banks before, restore the old
 * bank before returning.
 */

7:	mov	al,[oldbank]		# restore old register bank
	call	set_bank
8:	stc				# return with error
	mov	ax,[deterr]
9:	pop	esi
	ret



/*
 *====================================================================
 *
 * Read one byte from Flash EPROM. This routine assumes that the NIC chip
 * has been set to register window 0 already.
 * Input:  EDI  -  Offset into Flash EPROM
 * Output: AL   -  Byte value
 * Changed registers: AL
 */
ifread:

	push	dx
	xor	al,al
	cmp	edi,[winsize]		# check if valid offset
	jae	9f
	mov	dx,[ioaddr]
	add	dx,ROM_ADDR
	xchg	eax,edi
	out	dx,eax			# write offset into Flash EPROM
	xchg	eax,edi
	add	dx,ROM_DATA - ROM_ADDR
	in	al,dx			# read data value
9:	pop	dx
	ret



/*
 *====================================================================
 *
 * Write one byte into Flash EPROM. This routine assumes that the NIC chip
 * has been set to register window 0 already.
 * Input:  EDI  -  Offset into Flash EPROM
 *         AL   -  Byte value
 * Output: none
 * Changed registers: none
 */
ifwrite:

	push	dx
	cmp	edi,[winsize]		# check if valid offset
	jae	9f
	mov	dx,[ioaddr]
	add	dx,ROM_ADDR
	xchg	eax,edi
	out	dx,eax			# write offset into Flash EPROM
	xchg	eax,edi
	add	dx,ROM_DATA - ROM_ADDR
	out	dx,al			# write data value
9:	pop	dx
	ret



/*
 *====================================================================
 *
 * Initialize NIC for programming. This just sets the register bank to 0.
 * Input:  none
 * Output: none
 * Changed registers: AX
 */
ifinit:

	call	save_bank		# save old register bank number
	mov	al,ROM_BANK
	call	set_bank		# set new register bank
	clc
	ret



/*
 *====================================================================
 *
 * Terminate programming. This restores the register bank. Note that this
 * routine does not enable the Flash EPROM. If its not already enabled,
 * this task should be done by a NIC configuration program. It requires
 * manipulating the serial configuration EEPROM.
 * Input:  none
 * Output: none
 * Changed registers: AX
 */
ifclean:

	mov	al,[oldbank]
	call	set_bank		# set old register bank
	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_3c90xbc
	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_3c90xbc

1:	mov	al,fs:[si]
	call	amd_doprog		# program one byte into Flash EPROM
	jc	9f
	inc	si			# increment source pointer
	test	si,0x8000
	jz	2f			# avoid source pointer overflow
	mov	ax,fs
	add	ax,0x0800
	mov	fs,ax
	and	si,0x7FFF
2:	inc	edi			# increment offset into Flash EPROM
 data32	loop	1b			# continue with next byte
	clc

9:	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_3c90xbc
	call	gen_verify		# call generic routine
	pop	bx
	ret



/*
 *====================================================================
 *
 * Save current register bank number
 * Input:  none
 * Output: AL   -  Old register bank number
 * Changed registers: AX
 */
save_bank:

	push	dx
	mov	dx,[ioaddr]
	add	dx,STATUS_REG
	in	ax,dx
	shr	ax,13
	and	ax,0x0007
	mov	[oldbank],al
	pop	dx
	ret



/*
 *====================================================================
 *
 * Set new register bank
 * Input:  AL   -  Register bank number
 * Output: none
 * Changed registers: AX
 */
set_bank:

	push	dx
	mov	dx,[ioaddr]
	add	dx,CMD_REG
	xor	ah,ah
	add	ax,CMD_SELBANK
	out	dx,ax
	pop	dx
	ret



/*
 *====================================================================
 *
 * Read one word from NIC serial EEPROM. This routine assumes that the
 * EEPROM register bank has been activated already.
 * Input:  SI   -  Offset into serial EEPROM
 * Output: AX   -  Word read from serial EEPROM
 * Changed registers: AX
 */
read_eeprom:

	push	bx
	push	dx
	mov	dx,[ioaddr]
	add	dx,EEPROM_CMD
1:	in	ax,dx			# wait until the EEPROM interface
	test	ax,EEPROM_BUSY		# is no longer busy
	jnz	1b

	mov	ax,si
	and	ax,0x003F
	mov	bx,si			# compute address into serial EEPROM
	shl	bx,2
	and	bx,0x0F00
	or	ax,bx
	and	ax,EEPROM_ADRMASK
	or	ax,EEPROM_READ		# add read command
	out	dx,ax			# send read command
	jcxz	2f
2:	jcxz	3f			# wait a little bit

3:	in	ax,dx			# wait until the EEPROM interface
	test	ax,EEPROM_BUSY		# is no longer busy
	jnz	3b
	add	dx,EEPROM_DATA - EEPROM_CMD
	in	ax,dx			# read data value
	pop	dx
	pop	bx
	ret




/*
 *====================================================================
 *
 * Due to a design flaw in the 3C905B ASIC this chip can only map the first
 * 8kB of the Flash EPROM into the processor address space. In order to access
 * the whole bootrom it is necessary to read the Flash EPROM contents by using
 * register access to the ASIC. For this, the following code gets copied into
 * the first 8kB of the Flash EPROM together with the initial bootrom loader,
 * and the compressed remainder of the bootrom gets burned into the hidden
 * space following those first 8kB. Then when the bootrom starts up and tries
 * to decompress the main parts (kernel and UNDI) it will call a reading
 * routine, which is coded below, for every compressed byte to read. This
 * reading routine will then read each byte using register access to the
 * ASIC. Because the assembler uses different offsets than when this code
 * gets executed within the bootrom context, we have to make sure that it
 * is strictly position-independent.
 *
 * These routines assume that they get called by a near call, and the DS is
 * set to CS.
 *
 *====================================================================
 *
 * Initialize the bootrom loader. This routine gets only called by the
 * bootrom, and it has to find an 3C905B network card and setup all
 * required data values. It returns the absolute offset to the Flash EPROM
 * reading routine. This routine has to be at the very beginning of the
 * whole loader code.
 * Input:  BX    -  PCI PFA of network card
 *         DX    -  PnP CSN of network card
 *         CS:SI -  Pointer to DWORD which contains the size of the bootrom
 * Output: AX    -  Offset to Flash EPROM reading routine (0 means error)
 *         DI    -  Offset to first byte following loader code
 * Changed registers: EAX, EBX, ECX, EDX, SI, DI
 */
ldinit:	jmp	7f

	.word	0			# size of flash image loader

7:	push	bx
	call	1f
1:	pop	bx
	sub	bx,offset 1b		# compute offset difference
	pop	cx			# get PCI PFA from stack

/*
 * First check to see that we are running within RAM. For this we read
 * the compressed bootrom image size and write it into its assigned
 * variable. If it is not the same, we are running within a ROM, which
 * should never happen.
 */

	mov	eax,cs:[si]		# read size of compressed image
	mov	ldrdsize[bx],eax
	cmp	ldrdsize[bx],eax	# check if we could store the variable
	jne	8f
	add	dword ptr ldrdsize[bx],WINID_LEN
	mov	dword ptr ldrdaddr[bx],ROM_WINSIZE
	mov	word ptr ldpcipfa[bx],cx

/*
 * Now find a 3C905B in the system, and determine its I/O base address
 */
	push	bx
	mov	ax,PCI_FUNC_READ_WORD
	mov	bx,ldpcipfa[bx]
	mov	di,PCI_REG_VENDOR_ID
	int	INT_PCI			# call BIOS to get vendor ID
	pop	bx
	jc	8f
	cmp	cx,PCI_VENDOR		# check that vendor ID is correct
	jne	8f

	push	bx
	mov	ax,PCI_FUNC_READ_WORD
	mov	bx,ldpcipfa[bx]
	mov	di,PCI_REG_DEVICE_ID
	int	INT_PCI			# call BIOS to get vendor ID
	pop	bx
	jc	8f
	and	cx,PCI_DEV_MASK		# check for correct device ID
	cmp	cx,PCI_DEV_3C905B
	jne	8f

	push	bx
	mov	ax,PCI_FUNC_READ_DWORD
	mov	bx,ldpcipfa[bx]
	mov	di,PCI_REG_ADDR_0
	int	INT_PCI			# call BIOS to get I/O base address
	pop	bx
	jc	8f
	or	ecx,ecx			# resource has to be assigned by BIOS
	jz	8f
	test	ecx,PCI_IOENABMASK	# check if registers are I/O based
	jz	8f
	and	ecx,PCI_IOADDRMASK
	test	ecx,0xFFFF0000		# I/O address has to be within 64kB
	jnz	8f
	mov	ldioaddr[bx],cx		# save I/O address

/*
 * Now check that we can really access the Flash EPROM by reading the
 * magic ID at the beginning of the compressed data.
 */

	cld
	lea	di,ldsig[bx]
	mov	cx,WINID_LEN
2:	call	ldread			# get next byte from Flash EPROM
	jz	8f
	scasb				# check if its correct
	jne	8f
	loop	2b
	lea	ax,ldread[bx]		# return without error
	lea	di,ldend[bx + 0x000F]
	and	di,0xFFF0		# adjust to paragraph boundary
	jmp	9f

8:	xor	ax,ax			# return with error
9:	ret



/*
 *====================================================================
 *
 * Read one byte from the Flash EPROM.
 * Input:  none
 * Output: AL   -  Byte read from Flash EPROM
 *         Zero flag set if at end of compressed bootrom contents
 * Changed registers: AX
 */
ldread:	push	bx
	call	1f
1:	pop	bx
	sub	bx,offset 1b		# compute offset difference

/*
 * First check if we are at the end of the file
 */

	mov	ax,word ptr ldrdsize[bx + 0]
	or	ax,word ptr ldrdsize[bx + 2]
	jz	9f

/*
 * Now read the requested byte from the Flash EPROM by acessing the
 * Flash EPROM registers of the ASIC.
 */

	push	dx
	push	esi
	mov	dx,ldioaddr[bx]		# get I/O address
	mov	esi,ldrdaddr[bx]	# get current read address

	add	dx,CMD_REG
	mov	ax,CMD_SELBANK + ROM_BANK
	out	dx,ax			# set bank to access ROM registers

	add	dx,ROM_ADDR - CMD_REG
	xchg	eax,esi
	out	dx,eax			# write offset into Flash EPROM
	xchg	eax,esi
	add	dx,ROM_DATA - ROM_ADDR
	in	al,dx			# read data value

	dec	dword ptr ldrdsize[bx]	# decrement number of bytes
	inc	dword ptr ldrdaddr[bx]	# increment read address
	or	dx,dx			# clear zero flag
	pop	esi
	pop	dx
9:	pop	bx
	ret



/*
 *====================================================================
 *
 * Variables used by the loader code. It is not nice to have variables within
 * the code segment, but there is no way to avoid this with the Flash EPROM
 * loader.
 */


/*
 * Variable to hold the I/O address of the 3C905B. This variable will only
 * be used by the Flash EPROM loader. The I/O address might be different at
 * loader runtime and at the time when we run the Flash EPROM programmer (for
 * example the user might have reconfigured the network card in the meantime).
 */
ldioaddr:	.word	0


/*
 * Variable to hold the 3C905B PCI PFA number. This variable will also only
 * be used by the Flash EPROM loader. It might be different at loader runtime
 * and at the time when we run the Flash EPROM programmer.
 */
ldpcipfa:	.word	0


/*
 * Current read address offset
 */
ldrdaddr:	.long	0


/*
 * Size of image to read from Flash EPROM
 */
ldrdsize:	.long	0


/*
 * Signature at the beginning of the compressed ROM code
 */
ldsig:		.ascii	WINID_MAGIC


/*
 * The loader code ends here. All the code from label ldinit up to here
 * gets copied into the bootrom lateron.
 */
ldend:




/*
 *====================================================================
 *
 * String and constants definitions
 */
	_rodata


/*
 * List of NICs supported by this module
 */
pci_list:
	.word	PCI_VENDOR

nic_list:
	.word	0x9200
	.word	0x9805
	.word	0x9004
	.word	0x9005
	.word	0x9006
	.word	0x900A
	.word	0x9055
	.word	0x9056
	.word	0x9058
	.word	0x905A
	.word	0


/*
 * NIC names
 */
name_3c90x:
	.asciz	"3Com 3C90x"

name_3c905c:
	.asciz	"3Com 3C905C"

name_3c980c:
	.asciz	"3Com 3C980C"

name_3c900btpo:
	.asciz	"3Com 3C900B TPO"

name_3c900bcombo:
	.asciz	"3Com 3C900B Combo"

name_3c900btpc:
	.asciz	"3Com 3C900B TPC"

name_3c900bfl:
	.asciz	"3Com 3C900B FL"

name_3c905btx:
	.asciz	"3Com 3C905B TX"

name_3c905bt4:
	.asciz	"3Com 3C905B T4"

name_3c905bcombo:
	.asciz	"3Com 3C905B Combo"

name_3c905bfx:
	.asciz	"3Com 3C905B FX"


name_list:
	.word	name_3c905c
	.word	name_3c980c
	.word	name_3c900btpo
	.word	name_3c900bcombo
	.word	name_3c900btpc
	.word	name_3c900bfl
	.word	name_3c905btx
	.word	name_3c905bt4
	.word	name_3c905bcombo
	.word	name_3c905bfx




/*
 *====================================================================
 *
 * Data definitions
 */
	.data

	.global	istruct_3c90xbc


/*
 * Interface definition
 */
istruct_3c90xbc:
	.word	name_3c90x		# 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	0			# no further flags necessary


/*
 * Loader definition
 */
ifload:	.word	ldinit			# pointer to start of loader code
	.word	ldend			# pointer to end of loader code
	.long	ROM_WINSIZE		# ROM address space window size




/*
 *====================================================================
 *
 * Variable definitions
 */
	.bss

	.lcomm	deterr,2		# detection routine error code
	.lcomm	pcipfn,2		# PCI identification number for card
	.lcomm	ioaddr,2		# I/O address for register access
	.lcomm	romsize,4		# size of physical Flash ROM
	.lcomm	winsize,4		# size of Flash ROM window
	.lcomm	oldbank,1		# saved bank number
	.lcomm	eeprom,EEPROM_MAX * 2	# area to save EEPROM values




/*
 *====================================================================
 */
	.end

