Category : Network Files
Archive   : PKTD11A.ZIP
Filename : EEP17.INC

 
Output of file : EEP17.INC contained in archive : PKTD11A.ZIP
;************************************************************************;
;* *;
;* 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



  3 Responses to “Category : Network Files
Archive   : PKTD11A.ZIP
Filename : EEP17.INC

  1. Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!

  2. This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.

  3. But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/