home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Serving the Web
/
ServingTheWeb1995.disc1of1.iso
/
connect
/
tcpip
/
crynwr
/
pktd11a
/
eep15.inc
< prev
next >
Wrap
Text File
|
1993-06-01
|
16KB
|
579 lines
;************************************************************************;
;* *;
;* EEP15.INC *;
;* *;
;* EEPROM configuration routines for the ATI AT-1500 Adapters. *;
;* *;
;* Copyright (c) 1992, 1993, Allied Telesis, Inc. All Rights Reserved.*;
;* *;
;************************************************************************;
DATASEG SEGMENT
ifdef CODE386 ; 386 "flat" model (Novell 386 server driver)
POINTER_REGISTER equ ESI
else ; all other models
POINTER_REGISTER equ SI
endif
ifndef @Version
@Version equ 000
endif
; Bit definitions for the PCNetISA "Vendor Specific Word", which on the
; AT-1500 controls the on-board serial EEPROM (National Semiconductor NMC95C12).
DATA_IN equ 001h ; EEPROM serial data in (DI) - write/only
CLOCK equ 002h ; EEPROM serial clock (SK) - write/only
DATA_OUT equ 004h ; EEPROM serial data out - read/only
CHIP_SEL equ 008h ; EEPROM Chip Select - write/only
JUMPER_STATE equ 008h ; Alternate Address Jumper state - read/only
; EEPROM command codes.
READ equ 80h ; Read EEPROM memory at specified address
WEN equ 30h ; Write Enable
WRITE equ 40h ; Write EEPROM memory at specified address
WRALL equ 10h ; Write to all EEPROM locations
WDS equ 00h ; Write Disable
SB equ 01h ; "Start Bit" (command follows)
ADDR_MASK equ 3Fh ; EEPROM memory address mask
; EEPROM locations used for AT-1500 configuration data (all are word addresses):
BOARD_TYPE_LOC equ 0 ; ASCII product name: 12 bytes
BOARD_REV_LOC equ 6 ; board rev. level: low-order byte
BOARD_SUBTYPE_LOC equ 6 ; board subtype code: high-order byte
FLAG_WORD_LOC equ 32 ; Flag bits - see below
SCR_SAVE_ADDR equ 61 ; SCR (below) power-up value save loc.
SCR_ADDR equ 62 ; "Switch Configuration Register"
SRR_ADDR equ 63 ; "Switch Readback Register"
; Configuration values for the SCR and the SCR_SAVE (word locations 61 & 62):
IRQ_MASK equ 0003h ; bits 0-3 (switch 1): IRQ: see below
DMA_MASK equ 0030h ; bits 4-7 (switch 2): DMA: see below
IO_BASE_MASK equ 0300h ; bits 8-11 (switch 3): IO: see below
BOOT_EN_MASK equ 1000h ; bits 12-15 (switch 4): BOOT: see below
MAU_SEL_MASK equ 2000h ; bits 12-15 (switch 4): PORT: see below
; SCR Bits 0-3: IRQ configuration:
IRQ_CHOICE_A equ 0000h
IRQ_CHOICE_B equ 0001h
IRQ_CHOICE_C equ 0002h
IRQ_CHOICE_D equ 0003h
IRQ_3 equ IRQ_CHOICE_A
IRQ_4 equ IRQ_CHOICE_B
IRQ_5 equ IRQ_CHOICE_C
IRQ_9 equ IRQ_CHOICE_D
IRQ_10 equ IRQ_CHOICE_A ; AT-1500xx-20 only
IRQ_11 equ IRQ_CHOICE_B ; AT-1500xx-00/20 only
IRQ_14 equ IRQ_CHOICE_C ; AT-1500xx-20 only
IRQ_15 equ IRQ_CHOICE_D ; AT-1500xx-00/20 only
; SCR Bits 4-7: DMA configuration:
DMA_3 equ 0000h
DMA_5 equ 0010h
DMA_6 equ 0020h
DMA_7 equ 0030h
; SCR Bits 8-11: IO BASE configuration:
BASE_IO_300 equ 0000h
BASE_IO_320 equ 0100h
BASE_IO_340 equ 0200h
BASE_IO_360 equ 0300h
; SCR Bits 12-15: BOOT PROM and PORT SELECTION configuration:
BOOT_ENA equ 1000h ; bit 12 = 1: Enable boot PROM
BOOT_DIS equ 0000h ; bit 12 = 0: Disable boot PROM
UTP_PORT equ 2000h ; bit 13 = 1: Select UTP Port
OTHER_PORT equ 0000h ; bit 13 = 0: Select "Other" Port
; Flag Word (location 32):
AUTO_SENSE_BIT equ 0001h
; Board "Subtypes" (location 6):
SUBTYPE_00 equ 1
SUBTYPE_10 equ 2
SUBTYPE_20 equ 3
; PCNetISA I/O Ports:
ADDR_PROM_OFFSET equ 0 ; MAC (datalink) Address PROM
RDP_OFFSET equ 16 ; Register Data Port
RAP_OFFSET equ 18 ; Register Address Port
ISACR_OFFSET equ 22 ; ISA-Bus Control Register
VSW_OFFSET equ 24 ; Vendor Specific Word
ISACR2 equ 2 ; ISACR2 (out RAP register == ISACR2)
MC_UTP_OTHER equ 001h ; value to select UTP or "Other" port
MC_AUTO_SEL equ 002h ; value to select "Auto Select" function
; Possible AT-1500 IRQ choices (varies depending on board "subtype"):
IRQ_RANGE MACRO range_name, irq_a, irq_b, irq_c, irq_d
range_name equ (irq_a SHL 12) + (irq_b SHL 8) + (irq_c SHL 4) + irq_d
ENDM
IRQ_RANGE LOW_IRQ_RANGE, 3, 4, 5, 9
IRQ_RANGE HIGH_IRQ_RANGE, 10, 11, 14, 15
IRQ_RANGE MIXED_IRQ_RANGE, 3, 11, 5, 15
DATASEG ENDS
CODESEG SEGMENT
if @Version GE 600
ASSUME CS:CODESEG
endif
ifdef DATAGROUP
ASSUME DS:DATAGROUP
endif
ifdef STACKSEG
ASSUME SS:STACKSEG
endif
ASSUME ES:NOTHING
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
; times 8 = at least 800ns on an 80Mhz 386 (!!)
jmp short $+2
jmp short $+2
jmp short $+2
jmp short $+2
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
; times 4 = at least 400ns on an 80Mhz 386 (!!)
jmp short $+2
jmp short $+2
jmp short $+2
jmp short $+2
ENDM
DEBUG_DISPLAY MACRO display_char
push AX
push DX
mov AH, 02h
mov DL, '<'
int 21h
mov DL, display_char
int 21h
mov DL, '>'
int 21h
pop DX
pop AX
ENDM
;************************************************************************;
;* *;
;* VerifyBoard *;
;* Function: Read the configuration of the AT-1500 board. *;
;* Input: DI = base I/O address of the AT-1500 board. *;
;* Output: stc (carry set) if not an AT-1500 or config error; *;
;* clc (carry clear) if successful, and: *;
;* BH = configured DMA channel. *;
;* BL = configured IRQ. *;
;* CX = value to be output to the ISACR2 register. *;
;* Other registers used are preserved. *;
;* *;
;************************************************************************;
VerifyBoard proc near
push AX ; save caller's registers
push DX
; Verify that this really is an AT-1500 board.
mov DX, DI ; DX = address prom I/O address
in AX, DX ; read the first 2 bytes of MAC address
cmp AX, 0 ; it better be 0000
je VB_go_on
jmp scr_error
VB_go_on:
add DX, 2
in AX, DX ; read the next 2 bytes of MAC address
cmp AL, 0F4h ; the third byte better be F4
je VB_its_ours
jmp scr_error
VB_its_ours:
; Read the SCR to get the state of the configuration "switches".
mov BX, SCR_ADDR
call rd_oper ; read the Switch Configuration Register
mov DX, AX ; save SCR value for later
; Read this board's rev level and "subtype" codes.
mov BX, BOARD_REV_LOC ; read "board rev code" at EEPROM loc 6
call rd_oper ; AL=rev level code, AH=Subtype code
; Determine the configured IRQ and return this value in BL.
mov BX, HIGH_IRQ_RANGE ; (assume this is a Subtype 20 board)
cmp AH, SUBTYPE_20 ; is this a Subtype 20 board ?
je got_irq_range ; yes, uses High range of IRQ choices
mov BX, MIXED_IRQ_RANGE
cmp AH, SUBTYPE_00 ; is this a Subtype 00 board ?
je got_irq_range ; yes, uses Mixed range of IRQ choices
mov BX, LOW_IRQ_RANGE ; must be Subtype 10: uses Low IRQ range
got_irq_range:
mov AX, DX ; get the SCR value again
and AX, IRQ_MASK ; isolate IRQ configuration bits
mov CL, 12
cmp AX, IRQ_CHOICE_A ; switch based upon on of 4 IRQ choices
je got_irq
mov CL, 8
cmp AX, IRQ_CHOICE_B
je got_irq
mov CL, 4
cmp AX, IRQ_CHOICE_C
je got_irq
xor CL, CL
cmp AX, IRQ_CHOICE_D
je got_irq
jmp scr_error
got_irq:
shr BX, CL ; compute actual IRQ value
and BL, 0Fh ; and return in register BL
; Determine the configured DMA channel and return this value in BH.
mov AX, DX ; get the SCR value again
and AX, DMA_MASK ; isolate DMA channel configuration bits
mov BH, 3
cmp AX, DMA_3 ; is it DMA channel 3 ?
je got_dma ; yes
mov BH, 5
cmp AX, DMA_5 ; is it DMA channel 5 ?
je got_dma ; yes
mov BH, 6
cmp AX, DMA_6 ; is it DMA channel 6 ?
je got_dma ; yes
mov BH, 7
cmp AX, DMA_7 ; is it DMA channel 7 ?
je got_dma ; yes
jmp scr_error
got_dma:
; Determine the proper value to be used for ISACR2 and return it in CX.
mov CX, 0001h ; assume ISACR2 = XMAUSEL (ext. hdw)
test DX, UTP_PORT ; check SCR value: is "UTP" selected ?
jz got_mau ; no, "Other" port (BNC/FOIRL/AUI)
push bx
mov BX, FLAG_WORD_LOC ; not the "other" port, but ...
call rd_oper ; read the flag word from the EEPROM
pop bx
test DX, AUTO_SENSE_BIT ; is "Auto Select" configured ?
jz got_mau ; no, must be the UTP port
mov CX, 0002h ; yes, ISACR2 = ASEL (Auto Select)
got_mau:
clc ; set CF=0 == "success"
pop dx ; restore caller's registers
pop ax
ret ; return to caller
scr_error:
stc ; set CF=1 == "error"
pop dx ; restore caller's registers
pop ax
ret ; return to caller
VerifyBoard endp
;************************************************************************;
;* *;
;* read_adr_prom *;
;* Function: read the MAC (datalink) address of the board. *;
;* Input: DS:(E)SI = pointer to caller's mac address buffer. *;
;* DI = base I/O address of the AT-1500 board *;
;* Output: the board's MAC address is placed in the caller's bfr. *;
;* registers used are preserved *;
;* *;
;************************************************************************;
read_adr_prom proc near
if @Version GE 600
ASSUME POINTER_REGISTER : PTR BYTE
endif
push ax ; save caller's registers
push dx
mov DX, DI ; DX = address prom I/O address
in ax, dx
mov word ptr [POINTER_REGISTER], ax
add dx, 2
in ax, dx
mov word ptr [POINTER_REGISTER+2], ax
add dx, 2
in ax, dx
mov word ptr [POINTER_REGISTER+4], ax
pop dx ; restore caller's registers
pop ax
ret ; return to caller
read_adr_prom 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-1500 board *;
;* Output: AX = data read from EEPROM. *;
;* registers used are preserved *;
;* *;
;************************************************************************;
rd_oper proc near
push bx ; save caller's registers
push cx
push dx
mov cx, bx
call pulse_cs
call prep_load ; prepare the EEPROM for a new command
mov dx, SB
call wr_bit ; write a Start Bit
mov dl, READ
and cl, ADDR_MASK
or dl, cl
call wr_byte ; write a READ command code with the address
xor bx, bx ; bx = data read
mov cx, 16 ; reading 16 bits
rd_next_bit1:
shl bx, 1
call rd_bit ; read a bit
or bx, ax ; merge it with accumulated bits so far
loop rd_next_bit1
call pulse_cs ; pulse CHIP SELECT to terminate the command
mov ax, bx ; return EEPROM value in AX
pop dx ; restore caller's registers
pop cx
pop bx
ret ; return to caller
rd_oper endp
;************************************************************************;
;* *;
;* rd_bit *;
;* Function: Read 1 bit from the eeprom DO pin. *;
;* Input: AX = the least significant bit (bit 0) is the data bit *;
;* read. *;
;* DI = base I/O address of the AT-1500 board *;
;* Output: nothing *;
;* registers used are preserved *;
;* *;
;************************************************************************;
rd_bit proc near
push dx
xor ax, ax
mov al, CHIP_SEL
or al, CLOCK
mov dx, DI
add dx, VSW_OFFSET
out dx, al ; make CLOCK go high
in al, dx ; read D0
and al, DATA_OUT
DELAY_750 ; chip requires about 750ns hold time here
push ax
mov al, CHIP_SEL
out dx, al ; make CLOCK go low again
pop ax
shr ax, 1
shr ax, 1 ; return DO in LSB (bit 0) of AX
pop dx
ret
rd_bit endp
;************************************************************************;
;* *;
;* wr_byte *;
;* Function: Write a byte to the eeprom. *;
;* Input: DL = data byte to be written. *;
;* DI = base I/O address of the AT-1500 board. *;
;* Output: nothing *;
;* registers used are preserved *;
;* *;
;************************************************************************;
wr_byte proc near
push ax ; save caller's registers
push cx
mov al, dl
mov cx, 8
next_bit:
rol al, 1
mov dl, al
and dl, 01h ; DL bit 0 = bit to write
call wr_bit ; write one bit of the byte
loop next_bit ; loop to write all bits
pop cx ; restore caller's registers
pop ax
ret ; return to caller
wr_byte endp
;************************************************************************;
;* *;
;* wr_bit *;
;* Function: Write a bit to the EEPROM Data In pin. *;
;* Input: DL = the least significant bit (bit 0) is the data bit *;
;* to be written. *;
;* DI = base I/O address of the AT-1500 board. *;
;* Output: nothing *;
;* registers used are preserved *;
;* *;
;************************************************************************;
wr_bit proc near
push ax ; save caller's registers
push bx
push dx
mov bl, dl
mov al, CHIP_SEL
and bl, 01h
or al, bl
mov dx, DI
add dx, VSW_OFFSET
out dx, al ; write CS and DI out
or al, CLOCK
out dx, al ; present data bit with CLOCK high
DELAY_750 ; chip requires about 750ns hold time here
mov al, CHIP_SEL
out dx, al ; make the CLOCK go low again
pop dx ; restore registers
pop bx
pop ax
ret ; return to caller
wr_bit endp
;************************************************************************;
;* *;
;* prep_load *;
;* Function: Generate one clock cycle as required before sending *;
;* a new command code to the EEPROM. *;
;* Input: DI = base I/O address of the AT-1500 board *;
;* Output: nothing *;
;* registers used are preserved *;
;* *;
;************************************************************************;
prep_load proc near
push ax
push dx
mov dx, DI
add dx, VSW_OFFSET
mov al, CHIP_SEL + CLOCK
out dx, al ; turn on CHIP SELECT and CLOCK
DELAY_250 ; chip requires about 250ns hold time here
and al, NOT CLOCK ; wait for 1 clock cycle
out dx, al ; turn off CLOCK
pop dx
pop ax
ret ; return to caller
prep_load endp
;************************************************************************;
;* *;
;* pulse_cs *;
;* function: to make CS pin in the eeprom go low for a short time, *;
;* then go high again (required between commands). *;
;* input: DI = base I/O address of the AT-1500 board *;
;* output: nothing *;
;* registers used are preserved *;
;* *;
;************************************************************************;
pulse_cs proc near
pushf ; save interrupt state
cli ; disable interrupts
call cs_low ; drop CHIP_SEL for about 250ns
call cs_high ; raise CHIP_SEL again
popf ; re-enable interrupts (if they were enabled)
ret ; return to caller
pulse_cs endp
;************************************************************************;
;* *;
;* cs_low *;
;* Function: to make the Chip Select pin in the EEPROM go low. *;
;* Input: DI = base I/O address of the AT-1500 board *;
;* Output: nothing *;
;* registers used are preserved *;
;* *;
;************************************************************************;
cs_low proc near
push ax ; save caller's registers
push dx
mov dx, DI
add dx, VSW_OFFSET
xor ax, ax
out dx, al ; turn off CHIP SELECT
DELAY_250 ; chip requires about 250ns between instructions
pop dx ; restore caller's registers
pop ax
ret ; return to caller
cs_low endp
;************************************************************************;
;* *;
;* cs_high *;
;* Function: to make the Chip Select pin in the EEPROM go high. *;
;* Input: DI = base I/O address of the AT-1500 board *;
;* Output: nothing *;
;* registers used are preserved *;
;* *;
;************************************************************************;
cs_high proc near
push ax ; save caller's registers
push dx
mov dx, DI
add dx, VSW_OFFSET
mov al, CHIP_SEL
out dx, al ; turn on CHIP SELECT
pop dx ; restore caller's registers
pop ax
ret ; return to caller
cs_high endp
CODESEG ENDS