home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Serving the Web
/
ServingTheWeb1995.disc1of1.iso
/
connect
/
tcpip
/
crynwr
/
pktd11a
/
eep17.inc
< prev
next >
Wrap
Text File
|
1993-04-14
|
19KB
|
696 lines
;************************************************************************;
;* *;
;* EEP17.INC *;
;* *;
;* EEPROM configuration routines for the ATI AT-1700 Adapters. *;
;* *;
;* Copyright (c) 1992, 1993, Allied Telesis, Inc. All Rights Reserved.*;
;* *;
;************************************************************************;
DATASEG SEGMENT
ifdef CODE386 ; 386 "flat" model
CONFIG_PTR equ ESI
else ; all other models
CONFIG_PTR equ SI
endif
ifndef @Version
@Version equ 000
endif
; EtherCoupler Register addresses (offsets from IOBASE):
DLCR7_OFFSET equ 7 ; Config (register select) register
DLCR8_OFFSET equ 8 ; Node ID register
EESKCS_OFFSET equ 16 ; EESKCS register - see below
EEDP_OFFSET equ 17 ; EEDP register - see below
IOBAI_OFFSET equ 18 ; IOBAI register
JLC_OFFSET equ 19 ; JumperLess Configuration register
IDROM_OFFSET equ 24 ; first byte of IDROM
; EtherCoupler's EESKCS EEPROM control register:
DATA_IN equ 80h ; serial data in (write)
CLOCK equ 40h ; serial clock (write)
DATA_OUT equ 04h ; serial data out (read)
CHIP_SEL equ 20h ; Chip Select
; EtherCoupler's EDDP EEPROM Data register:
SB equ 80h ; "Start Bit"
READ equ 80h ; Command Code: Read
EWEN equ 30h ; Command Code: Write Enable
WRITE equ 40h ; Command Code: Write
WRALL equ 10h ; Command Code: Write All
EWDS equ 00h ; Command Code: Write Disable
; EEPROM byte (word) locations:
CONFIG_ADDR equ 0/2 ; Configuration Byte - see below
ETHERNET_ADDR equ 8/2 ; Ethernet (MAC) address of this adapter
BMPR13_ADDR equ 24/2 ; value to be used in BMPR13 - see below
BRD_TYPE_ADDR equ 30/2 ; Board type code - see below
BRD_REV_ADDR equ 31/2 ; Board rev level code
; JLC register and Configuration Byte (EEPROM location 0) format:
IO_BASE_MASK equ 007h ; bits 0-2 = I/O Base code - see below
MEM_BASE_MASK equ 038h ; bits 3-5 = Boot PROM Base code - see below
IRQ_MASK equ 0C0h ; bits 6-7 = IRQ code - see below
; I/O Base code (JLC bits 0-2):
BASE_IO_260 equ 00h
BASE_IO_280 equ 01h
BASE_IO_2A0 equ 02h
BASE_IO_240 equ 03h
BASE_IO_340 equ 04h
BASE_IO_320 equ 05h
BASE_IO_380 equ 06h
BASE_IO_300 equ 07h
; Boot PROM Base code (JLC bits 3-5):
ROM_BASE_C400 equ 00h
ROM_BASE_C800 equ 08h
ROM_BASE_CC00 equ 10h
ROM_BASE_D000 equ 18h
ROM_BASE_D400 equ 20h
ROM_BASE_D800 equ 28h
ROM_BASE_DC00 equ 30h
ROM_BASE_DISABLED equ 38h
; IRQ code (JLC bits 6-7):
IRQ_3 equ 000h
IRQ_4 equ 040h
IRQ_5 equ 080h
IRQ_9 equ 0C0h
; BMPR13 Register bits (EEPROM location 24):
MAU_SEL_MASK equ 18h ; bits 3&4 = Port selection
UTP_PORT equ 08h ; UTP port
OTHER_PORT equ 18h ; "Other" (BNC/Fiber) port
AUTO_SELECT equ 00h ; "Auto Select"
TPTYPE_MASK equ 44h ; bits 2&6 = Twisted Pair Type selection
UTP_MEDIA_TYPE equ 40h ; 100ohm UTP or STP cabling
STP_MEDIA_TYPE equ 04h ; 150ohm STP cabling
; Board Type code (EEPROM location 30):
IS_A_1700T equ 0 ; AT-1700T Twisted-Pair only
IS_A_1700BT equ 1 ; AT-1700BT Twisted-Pair plus BNC
IS_A_1700FT equ 2 ; AT-1700FT Twisted-Pair plus FOIRL
DATASEG ENDS
CODESEG SEGMENT
DELAY_750 MACRO
; One CPU clock cycle = 25ns at 40Mhz CPU clock frequency
; jmp short = (min) 8 cycles on a 386 = 200ns per jump
; times 4 = at least 800ns on a 40Mhz 386
jmp short $+2
jmp short $+2
jmp short $+2
jmp short $+2
ENDM
DELAY_250 MACRO
; times 2 = at least 400ns on a 40Mhz 386
jmp short $+2
jmp short $+2
ENDM
;************************************************************************;
;* *;
;* VerifyBoard *;
;* Function: 1) reset the board *;
;* 2) read the IRQ and BMPR13 value from the EEPROM. *;
;* Input: DI = base I/O address of the AT-1700 board *;
;* Output: AH = IRQ from JLC register if success *;
;* AL = BMPR13 value register if success *;
;* AX = FFFFh if failure (not an AT-1700 or config error) *;
;* registers used are preserved *;
;* *;
;************************************************************************;
VerifyBoard proc near
push cx
push dx
xor ax, ax
mov dx, di ;reset the NIC
add dx, IDROM_OFFSET
out dx, al
call is_there_AT1700 ;read the register pattern
jnc get_irq
mov ax, 0ffffh ;it's not there
pop dx
pop cx
ret
get_irq:
mov dx, DI
add dx, JLC_OFFSET ;read JLC register
in al, dx
; AL now contains Base IO and IRQ
and al, IRQ_MASK
mov cl, 3
cmp al, IRQ_3
je get_bmpr
mov cl, 4
cmp al, IRQ_4
je get_bmpr
mov cl, 5
cmp al, IRQ_5
je get_bmpr
mov cl, 9
get_bmpr:
call read_BMPR_val ;al = BMPR13 register value
mov ah, cl
pop dx
pop cx
ret
VerifyBoard endp
;************************************************************************;
;* *;
;* GetIRQAndVerify *;
;* Function: Get the IRQ and read MAC addr from EEPROM to verify *;
;* the board *;
;* Input: DI = base I/O address of the AT-1700 board *;
;* DS:(E)SI => caller's buffer where to put MAC address. *;
;* Output: the board's MAC address is placed in the caller's bfr. *;
;* AX = IRQ from JLC register if success *;
;* AX = FFFFh if failure (not an AT-1700 or config error) *;
;* registers used are preserved *;
;* *;
;************************************************************************;
GetIRQAndVerify proc near
push cx ; save caller's registers
push dx
call Verify_JLC ; read & verify JLC (returns ah = JLC)
mov al, ah ; al = JLC value
xor cx, cx ; determine configured IRQ value
and al, IRQ_MASK
mov cl, 3
cmp al, IRQ_3
je VerifyMACAddr
mov cl, 4
cmp al, IRQ_4
je VerifyMACAddr
mov cl, 5
cmp al, IRQ_5
je VerifyMACAddr
mov cl, 9
VerifyMACAddr:
call read_mac_addr ; read the board's MAC address
cmp word ptr [CONFIG_PTR], 0 ; (validate it)
jne FailToVerify
cmp byte ptr [CONFIG_PTR+2], 0F4h
jne FailToVerify
mov ax, cx ; return IRQ value in ax
pop dx ; restore caller's registers
pop cx
ret ; return to caller
FailToVerify:
mov ax, 0ffffh
pop dx
pop cx
ret
GetIRQAndVerify endp
;************************************************************************;
;* *;
;* Verify_JLC *;
;* Function: Get the JLC and do a sanity check on it. *;
;* Input: DI = base I/O address of the AT-1700 board *;
;* Output: AH = JLC register value *;
;* ZF = TRUE (jz) on success *;
;* ZF = FALSE (jnz) on failure *;
;* registers used are preserved *;
;* *;
;************************************************************************;
Verify_JLC PROC NEAR
mov dx, DI
add dx, JLC_OFFSET
in al, dx ; read the JLC register
mov ah, al ; save it for caller in AH
and al, IO_BASE_MASK
cmp di, 0300h
jne next_io_1
cmp al, BASE_IO_300
je JLC_verified
jmp JLC_failure
next_io_1:
cmp di, 0320h
jne next_io_2
cmp al, BASE_IO_320
je JLC_verified
jmp JLC_failure
next_io_2:
cmp di, 0340h
jne next_io_3
cmp al, BASE_IO_340
je JLC_verified
jmp JLC_failure
next_io_3:
cmp di, 0380h
jne next_io_4
cmp al, BASE_IO_380
je JLC_verified
jmp JLC_failure
next_io_4:
cmp di, 0240h
jne next_io_5
cmp al, BASE_IO_240
je JLC_verified
jmp JLC_failure
next_io_5:
cmp di, 0260h
jne next_io_6
cmp al, BASE_IO_260
je JLC_verified
jmp JLC_failure
next_io_6:
cmp di, 0280h
jne next_io_7
cmp al, BASE_IO_280
je JLC_verified
jmp JLC_failure
next_io_7:
cmp di, 02A0h
jne JLC_failure
cmp al, BASE_IO_2A0
jne JLC_failure
JLC_verified:
JLC_failure:
ret ; return to caller
Verify_JLC endp
;************************************************************************;
;* *;
;* is_there_AT1700 *;
;* Function: determines if this is an AT-1700 at this location. *;
;* Input: DI = base I/O of the presumed AT-1700 adapter card. *;
;* Output: clc (carry clear) if AT1700 is found, else *;
;* stc (carry set) if not. *;
;* registers used are preserved *;
;* *;
;************************************************************************;
is_there_AT1700 PROC NEAR
push ax
push dx
; First do a pattern check - a just powered-up or reset AT-1700 board
; will have a known pattern to its I/O registers.
mov dx, DI
in al, dx ; check DLCR0
and al, NOT 40h ; remove NET BUSY bit
jz try_2 ; all other bits should be zero
jmp not_the_reset_pattern
try_2:
inc dx
in al, dx ; check DLCR1
or al, al
jz try_3
jmp not_the_reset_pattern
try_3:
inc dx
in al, dx ; check DLCR2
or al, al
jz try_4
jmp not_the_reset_pattern
try_4:
inc dx
in al, dx ; check DLCR3
or al, al
jz try_5
jmp not_the_reset_pattern
try_5:
inc dx
in al, dx ; check DLCR4
and al, 0Fh
cmp al, 06h
je try_6
jmp not_the_reset_pattern
try_6:
inc dx
in al, dx ; check DLCR5
cmp al, 041h
je try_7
jmp not_the_reset_pattern
try_7:
inc dx
in al, dx ; check DLCR6
cmp al, 0B6h
je try_8
jmp not_the_reset_pattern
try_8:
inc dx
in al, dx ; check DLCR7
cmp al, 0E0h
jne not_the_reset_pattern
; The pattern matches the AT-1700 reset pattern!
found_it:
clc
pop dx
pop ax
ret
not_the_reset_pattern:
; The board at this I/O address (if there indeed is a board here)
; does not match the AT-1700 reset pattern. Perhaps a driver has
; already been invoked which has changed some of the registers.
; So, we'll have to now follow Fujitsu's algorithm, which just checks
; a few registers to make sure a few reserved bits are actually zero.
; Since we don't think this approach is by itself very robust, we also
; add a check of DLCR6 and DLCR7 to make sure they make sense for this
; particular implementation (an AT-1700 always has 32k, for example).
mov DX, DI
inc DX
inc DX
in AL, DX ; read DLCR2
and AL, 71h ; isolate reserved bits
jnz not_there ; not zeros as expected
inc DX
inc DX
in AL, DX ; read DLCR4
and AL, 08h ; isolate reserved bit
jnz not_there ; not zero as expected
inc DX
in AL, DX ; read DLCR5
and AL, 80h ; isolate reserved bit
jnz not_there ; not zero as expected
inc DX
in AL, DX ; read DLCR6
and AL, 0F0h ; isolate AT-1700 meaningful bits
cmp AL, 050h ; known pattern for an AT-1700
jne not_there ; not an (initialized) AT-1700
inc DX
in AL, DX ; read DLCR7
and AL, 020h ; isolate AT-1700 meaningful bit
cmp AL, 020h ; known pattern for an AT-1700
jne not_there ; not an (initialized) AT-1700
; So far, it looks like this *might* be an (initialized) AT-1700.
; But we'll do two more checks to be sure:
; (1) the JLC (JumperLess Configuration) register better
; have an I/O base value corresponding to the I/O base
; that we're currently probing, and
; (2) the Node ID registers (DLCR8-10) better contain our magic
; cookie (0000F4). This assumes that since the other regs
; are not in a reset state then some driver must have done
; something, and any reasonable driver would also load the
; MAC address into the Node ID regs. This test also does
; something we do nowhere else while probing: it must write
; registers in order to read the Node ID. Although we don't
; like doing random writes, we assume that it must be fairly
; safe to do so since at this point we have passed all of the
; above tests.
call Verify_JLC ; do a sanity check on the JLC
push CX
pushf
cli ; disable interrupts in case driver up!
mov DX, DI
add DX, DLCR7_OFFSET-1
in AL, DX ; read DLCR6
mov CL, AL ; save DLCR6 value for later restore
or AL, 80h
out DX, AL ; enable the Node ID registers
inc DX
in AL, DX ; read DLCR7
mov CH, AL ; save DLCR7 value for later restore
and AL, 0F3h
out DX, AL ; switch to bank zero (DLCR0-DLCR15)
inc DX
in AL, DX ; read DLCR8 = Node ID [0]
cmp AL, 00h
jne not_a_1700 ; not 0000F4!!
inc DX
in AL, DX ; read DLCR9 = Node ID [1]
cmp AL, 00h
jne not_a_1700 ; not 0000F4!!
inc DX
in AL, DX ; read DLCR10 = Node ID [2]
cmp AL, 0F4h
jne not_a_1700 ; not 0000F4!!
mov DX, DI
add DX, DLCR7_OFFSET-1
mov AL, CL ; get saved DLCR6 value
out DX, AL ; restore DLCR6 for the driver
inc DX
mov AL, CH ; get saved DLCR7 value
out DX, AL ; restore DLCR7 for the driver
popf ; re-enable interrupts if appropriate
pop CX
jmp found_it ; this is apparently an AT-1700 !!!
not_a_1700:
popf ; re-enable interrupts if appropriate
pop CX
not_there:
stc
pop dx
pop ax
ret
is_there_AT1700 ENDP
;************************************************************************;
;* *;
;* read_mac_addr *;
;* Function: to read the mac address of the board. *;
;* Input: DS:(E)SI => caller's buffer where to place mac address. *;
;* DI = base I/O address of the AT-1700 board *;
;* Output: the board's MAC address is placed in the caller's bfr. *;
;* registers used are preserved *;
;* *;
;************************************************************************;
read_mac_addr proc near
push ax ; save caller's registers
push bx
mov bx, ETHERNET_ADDR ; start from EEPROM location 8
call rd_oper ; read a word of the MAC address
mov word ptr [CONFIG_PTR], ax
inc bx
call rd_oper
mov word ptr [CONFIG_PTR+2], ax
inc bx
call rd_oper
mov word ptr [CONFIG_PTR+4], ax
pop bx ; restore caller's registers
pop ax
ret ; return to caller
read_mac_addr endp
;************************************************************************;
;* *;
;* read_BMPR_val *;
;* Function: read the BMPR13 value to be used from EEPROM. *;
;* Input: DI = base I/O address of the AT-1700 board *;
;* Output: AX = BMPR13 value to be used by the driver. *;
;* registers used are preserved *;
;* *;
;************************************************************************;
read_BMPR_val proc near
push bx
mov bx, BMPR13_ADDR ; read location 24 for BMPR13
call rd_oper
pop bx
ret ; return to caller
read_BMPR_val endp
;************************************************************************;
;* *;
;* rd_oper *;
;* Function: do a complete word READ operation. *;
;* Input: BX = EEPROM address to be read. *;
;* DI = base I/O address of the AT-1700 board *;
;* Output: AX = EEPROM data from the specified location. *;
;* registers used are preserved *;
;* *;
;************************************************************************;
rd_oper proc near
push bx ; save caller's registers
push dx
or bl, READ
call wr_command ; output the address to be read
call rd_byte ; read the first (low-order) byte
mov dl, al ; temporarily save low-order byte
call rd_byte ; read the second (high-order) byte
mov dh, al ; assemble the complete word
mov ax, dx ; and return to caller in AX
pop dx ; restore caller's registers
pop bx
ret ; return to caller
rd_oper endp
;************************************************************************;
;* *;
;* rd_byte *;
;* Function: Read one byte from the EEPROM. *;
;* Input: DI = base I/O address of the AT-1700 board *;
;* Output: AL = byte read. *;
;* registers used are preserved *;
;* *;
;************************************************************************;
rd_byte proc near
push cx ; save caller's registers
push dx
mov dx, DI
add dx, EESKCS_OFFSET ; DX = EtherCoupler EESKSC register
mov cx, 8
r_bit:
mov al, CHIP_SEL
out dx, al ; turn on CHIP SELECT with CLOCK low
or al, CLOCK
out dx, al ; make CLOCK go high
inc dx ; DX = EtherCoupler EEDP register
in al, dx ; read EEDP
shl ax, 1 ; shift AH <<= 1; AL b7 -> AH b0;
dec dx ; DX = EESKSC register again
loop r_bit ; loop to read all 8 bits
mov al, ah ; return read byte (now in AH) in AL
pop dx ; restore caller's registers
pop cx
ret ; return to caller
rd_byte endp
;************************************************************************;
;* *;
;* wr_command *;
;* Function: Output a command and memory address to the EEPROM. *;
;* Input: BL = the command/address byte to be written. *;
;* DI = base I/O address of the AT-1700 board *;
;* Output: nothing *;
;* registers used are preserved *;
;* *;
;************************************************************************;
wr_command proc near
push ax ; save caller's registers
push dx
mov dx, DI
add dx, EESKCS_OFFSET ; DX = EtherCoupler EESKSC register
xor al, al
out dx, al ; turn off CHIP SELECT and CLOCK
inc dx ; DX = EtherCoupler EEDP register
out dx, al ; clear the Serial Data In line
dec dx ; DX = EESKSC register again
mov al, CHIP_SEL
out dx, al ; turn on CHIP SELECT with CLOCK low
inc dx ; DX = EEDP register again
mov al, SB
out dx, al ; write a start bit
dec dx ; DX = EESKSC register again
mov al, CHIP_SEL or CLOCK
out dx, al ; make CLOCK go high
call wr_byte ; write the caller's data byte
pop dx ; restore caller's registers
pop ax
ret ; return to caller
wr_command endp
;************************************************************************;
;* *;
;* wr_byte *;
;* Function: Write a byte to the eeprom. *;
;* Input: BL = data byte to be written *;
;* DI = base I/O address of the AT-1700 board *;
;* Output: nothing *;
;* registers used are preserved *;
;* *;
;************************************************************************;
wr_byte proc near
push ax ; save caller's registers
push cx
push dx
mov ax, bx ; save caller's byte temporarily
mov dx, DI
add dx, EEDP_OFFSET ; DX = EtherCoupler EEDP register
mov cx, 8
s_bit:
push ax ; save caller's byte on the stack
out dx, al ; output low-order bit of caller's byte
dec dx ; DX = EtherCoupler EESKSC register
mov al, CHIP_SEL
out dx, al ; turn on CHIP SELECT with CLOCK low
or al, CLOCK
out dx, al ; make CLOCK go high
inc dx ; DX = EEDP register again
pop ax ; restore caller's saved byte from stack
shl ax, 1 ; shift to next bit position
loop s_bit ; loop to output all 8 bits
pop dx ; restore caller's registers
pop cx
pop ax
ret ; return to caller
wr_byte endp
CODESEG ENDS