home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Serving the Web
/
ServingTheWeb1995.disc1of1.iso
/
connect
/
tcpip
/
crynwr
/
pktd11b
/
t7231.asm
< prev
next >
Wrap
Assembly Source File
|
1993-10-13
|
27KB
|
1,046 lines
t7231_version equ 2
ifndef DAN
DAN equ 4 ; 4 seems to work best.
endif
;
; Code that is common between T7231 implementations.
;
; Ported from Tim Krauskopf's micnet.asm, an assembly language
; driver for the MICOM-Interlan NI5210, by Russell Nelson. Any bugs
; are due to Russell Nelson.
; Updated to version 1.08 Feb. 17, 1989 by Russell Nelson.
; Updated to support 1500 byte MTU April 27, 1989 By Brad Clements.
; copied and modified to support t7231 LanPACER controller by AT&T
; June 1, 1991 by Mark Darby.
; Updated to correct problems with higher speed CPU systems
; by Mark Darby - NCR, October 12, 1993
; Copyright, 1988-90, Russell Nelson
; 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, version 1.
;
; 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.
;
; Structure elements specific to the AT&T T7231 chip
;
; System Configuration Pointer
scp_struc struc
scp_bus db ?,?,?, ?,?,? ; bus use flag (0=16 bit, 1=8 bit).
scp_ptr dd ? ; 24pointer to iscp
scp_struc ends
; Intermediate System Configuration Pointer
iscp_struc struc
iscp_busy db ?,? ; busy flag (zeroed after init).
iscp_offset dw ? ; 16pointer to iscp
iscp_base dd ? ; base for all 16 pointers, lo, hi
iscp_struc ends
; System Control Block
scb_struc struc
scb_stat dw ? ; status
scb_com dw ? ; command
scb_cbl dw ? ; 16pointer to command block list
scb_rfa dw ? ; 16pointer to receive frame list
scb_serrs dw 4 dup(?) ; 4 words of error counts
scb_struc ends
; (Received) Frame Descriptor
fd_struc struc
fd_status dw ? ; status word for frame
fd_eol dw ? ; end of FD list flag
fd_link dw ? ; 16pointer to next FD
fd_ptr dw ? ; 16pointer to list of RBD's
fd_dest db EADDR_LEN dup(?); 48 bits of destination
fd_source db EADDR_LEN dup(?); 48 bits of source
fd_cnt dw ? ; length field of frame.
fd_struc ends
; Receive Buffer Descriptor
rbd_struc struc
rbd_status dw ? ; status word in RBD
rbd_link dw ? ; 16pointer to next RBD
rbd_ptr dd ? ; 24pointer to actual buffer
rbd_size dw ? ; size of the buffer
rbd_struc ends
; Transmit Command Block
tcb_struc struc
tcb_status dw ? ; status word for xmit
tcb_com dw ? ; command to transmit
tcb_link dw ? ; 16pointer to next command
tcb_ptr dw ? ; 16pointer to xmit TBD
tcb_addr db EADDR_LEN dup(?); destination address
tcb_len dw ?
tcb_struc ends
; Transmit Buffer Descriptor
tbd_struc struc
tbd_status dw ? ; bit 15=EOF, 13-0=actual count
tbd_link dw ? ; 16pointer to next TBD
tbd_ptr dd ? ; 24pointer to buffer
tbd_struc ends
; all commands have at least the following:
cmd_struc struc
cmd_status dw ? ; status word
cmd_com dw ? ; command word.
cmd_struc ends
; MC-SETUP Command Block
mcb_struc struc
mcb_status dw ? ; status word for multicast
mcb_com dw ? ; command to setup multicast
mcb_link dw ? ; 16pointer to next command
mcb_cnt dw ? ; number of multicast addresses.
mcb_struc ends
;Memory allocation.
;SCPTR EQU 0fff6h ; hardwired address for SCP
;ISCPTR EQU 0ffeeh ; my address for ISCP, points to SCB
SCPTR EQU 03ff6h ; hardwired address for SCP
ISCPTR EQU 03feeh ; my address for ISCP, points to SCB
SCB EQU ISCPTR - 16 ; system control block base
CCBPTR EQU SCB - 18 ; offset of configure command block
TBDPTR EQU CCBPTR - 8 ; xmit BD offset
TCBPTR EQU TBDPTR - 16 ; xmit CB offset
TBUFPTR EQU TCBPTR - GIANT ; xmit buffer offset
;the receive buffers appear at lower addresses than TBUFPTR.
RBUFLEN EQU 200
RBUF_TOTAL equ (size fd_struc) + (size rbd_struc) + RBUFLEN
FDBASE equ TBUFPTR - RBUF_TOTAL
memory_begin dw ?
public rcv_modes
rcv_modes dw 7 ;number of receive modes in our table.
dw 0 ;There is no mode zero
dw 0
dw rcv_mode_2
dw rcv_mode_3
dw rcv_mode_4 ;haven't set up perfect filtering yet.
dw 0
dw rcv_mode_6
firstfd dw FDBASE ; start of FD queue
lastfd dw 0 ; end of the FD chain
lastbd dw 0 ; end of the BD chain
flag dw 0
;
; Configuration block for 82586, this comprises one config command
; Parameters taken from MICOM driver
;
CBCONF DW 0 ; status word
DW 8002H ; end of command list + configure command
DW 0ffffh ; link to next command (not used)
DW 080CH ; fifo=8, byte count=C
DW 2E00H ; important! Addr (AL) not inserted on the fly!
DW 6000H ; IFS = 60h
DW 0F200H ; retry=F, slot time=200h
CBCONF_FLAGS label byte
DW 0 ; flags, set to 1 for promiscuous
CBCONF_MINLEN label byte
DW 40H ; min frame length=40h
doca_wait:
;enter with ax = command to execute, es = base_addr.
;exit with nc if the command ran to completion.
;exit with cy if the command timed out. Eventually we'll also reset the chip.
mov es:[SCB].scb_com,ax ;set the command.
mov si,es:[SCB].scb_cbl ;
mov es:[si].cmd_status,0 ; status word of specific command
and ax,0700h
cmp ax,0100h ; is it an action command?
jne doca_wait_a ; no, any other
call doca
comment \
Quoting from the D-Step Errata Revision 2.0:
The value for the deadman timer should be greater than the longest
command execution time. The command which can take the longest time
to execute is the transmit command, assuming maximum retries. To
determine the maximum amount of time the transmit command may take,
one must use the following equation: 7143 ST + 14 f, where ST stands
for Slot Time and f = Maximum Frame Size + IFS + Preamble. For
Ethernet/IEEE 802.3 where ST = 512 bits, f = 12144 bits, Preamble =
64 bits, IFS 96 bits, and one bit = 0.1 usec, the deadman timeout
should be greater than 0.369 seconds.
\
mov ax,14 ;36.4 ticks / seconds * .369 seconds
call set_timeout
doca_wait_1:
test es:[si].cmd_status,8000h ; is command complete?
jnz doca_wait_2 ;yes.
call do_timeout ;did we time out yet?
jne doca_wait_1 ;not yet.
;reset the chip here, then Configure, IA-Setup, and MC-Setup.
stc ;timeout -- uh-oh.
ret
doca_wait_2:
clc
ret
doca_wait_a:
call doca
doca_wait_a_0:
cmp es:[SCB].scb_com,0 ; has the command been accepted?
jnz doca_wait_a_0 ; not yet.
clc
ret
include timeout.asm
include movemem.asm
public bad_command_intercept
bad_command_intercept:
;called with ah=command, unknown to the skeleton.
;exit with nc if okay, cy, dh=error if not.
mov dh,BAD_COMMAND
stc
ret
public as_send_pkt
; The Asynchronous Transmit Packet routine.
; Enter with es:di -> i/o control block, ds:si -> packet, cx = packet length,
; interrupts possibly enabled.
; Exit with nc if ok, or else cy if error, dh set to error number.
; es:di and interrupt enable flag preserved on exit.
as_send_pkt:
ret
public drop_pkt
; Drop a packet from the queue.
; Enter with es:di -> iocb.
drop_pkt:
assume ds:nothing
ret
public xmit
; Process a transmit interrupt with the least possible latency to achieve
; back-to-back packet transmissions.
; May only use ax and dx.
xmit:
assume ds:nothing
ret
public send_pkt
send_pkt:
;enter with es:di->upcall routine, (0:0) if no upcall is desired.
; (only if the high-performance bit is set in driver_function)
;enter with ds:si -> packet, cx = packet length.
;exit with nc if ok, or else cy if error, dh set to error number.
assume ds:nothing
mov es,base_addr ; base for board
cmp cx,GIANT ; Is this packet too large?
ja send_pkt_toobig
mov dx,cx ; save a copy, might be less than 60, ok
cmp dx,RUNT ; minimum length for Ether
jnb oklen
mov dx,RUNT ; make sure size at least RUNT
oklen:
mov di,TBUFPTR ; start of xmit buffer
;
; check for previous xmit
;
xwait:
mov bx,es:[SCB].scb_com ; has previous command been accepted?
or bx,bx
jnz xwait ; not there yet, wait for it
wait_for_transmit_to_complete:
test word ptr es:[TCBPTR],4000h
jnz wait_for_transmit_to_complete
;
; move the data using word moves.
;
call movemem
;
; put the correct size into the TBD
;
or dx,08000h ; end of frame bit flag
mov es:[TBDPTR].tbd_status,dx ; store it
; mov es:[TCBPTR].tcb_status,0 ; zero status wd
mov es:[TCBPTR].tcb_com,8004h ; xmit command in TCB
; mov es:[SCB].scb_com,0100h ; execute command
mov es:[SCB].scb_cbl,TCBPTR ; say where xmit command is
mov ax,100h
call doca_wait
clc
ret
send_pkt_toobig:
mov dh,NO_SPACE
stc
ret
rcv_mode_2:
and CBCONF_FLAGS,not 3
or CBCONF_FLAGS,2 ;disable broadcasts.
mov CBCONF_MINLEN,40h
jmp short reconfigure
rcv_mode_4:
rcv_mode_3:
and CBCONF_FLAGS,not 3 ;clear promiscuous mode.
mov CBCONF_MINLEN,40h
jmp short reconfigure
rcv_mode_6:
and CBCONF_FLAGS,not 3
or CBCONF_FLAGS,1 ;set promiscuous mode.
mov CBCONF_MINLEN,0 ;allow runts.
reconfigure:
mov es,base_addr ;get the base address for the board.
mov si,offset CBCONF ; configure command
mov di,CCBPTR ; where command will reside
mov cx,9
rep movsw ; copy to board
;
; issue the configure command
;
mov es:[SCB].scb_cbl,CCBPTR ; where conf command is
mov es:[SCB].scb_serrs[0],0 ; zero errs field
mov es:[SCB].scb_serrs[2],0 ; zero errs field
mov es:[SCB].scb_serrs[4],0 ; zero errs field
mov es:[SCB].scb_serrs[6],0 ; zero errs field
mov ax,100h ; do-command command
call doca_wait
ret
public set_multicast_list
set_multicast_list:
;enter with ds:si ->list of multicast addresses, ax = number of addresses,
; cx = number of bytes.
;return nc if we set all of them, or cy,dh=error if we didn't.
assume ds:code
mov es,base_addr
mov es:[SCB].scb_cbl,TBUFPTR ;use the transmit buffer.
mov es:[TBUFPTR].mcb_status,0 ;status word
mov es:[TBUFPTR].mcb_com,08003h ;command word for mc-setup + EL
mov es:[TBUFPTR].mcb_link,-1 ;no command link.
mov di,TBUFPTR + mcb_cnt
mov ax,cx ;store the count.
stosw
rep movsb
comment \ avoid deferred execution of a CU command during reception.
If a command is executed with a length of 18 to 20 bytes, and a frame
is received, the 82586 may deadlock with HOLD active. We avoid this
problem by suspending the receiver. \
mov ax,30h ;suspend frame receiving.
call doca_wait
mov ax,100h ; do-command command
call doca_wait
jnc set_multicast_2
mov ax,20h ;resume frame receiving.
call doca_wait
mov dh,NO_MULTICAST ;for some reason we can't do multi's.
stc
ret
set_multicast_2:
mov ax,20h ;resume frame receiving.
call doca_wait
clc
ret
public terminate
terminate:
assume ds:code
ret
public reset_interface
reset_interface:
;reset the interface.
;we don't do anything.
assume ds:nothing
retpoint:
ret
;called when we want to determine what to do with a received packet.
;enter with cx = packet length, es:di -> packet type, dl = packet class.
extrn recv_find: near
;called after we have copied the packet into the buffer.
;enter with ds:si ->the packet, cx = length of the packet.
extrn recv_copy: near
;call this routine to schedule a subroutine that gets run after the
;recv_isr. This is done by stuffing routine's address in place
;of the recv_isr iret's address. This routine should push the flags when it
;is entered, and should jump to recv_exiting_exit to leave.
;enter with ax = address of routine to run.
extrn schedule_exiting: near
;recv_exiting jumps here to exit, after pushing the flags.
extrn recv_exiting_exit: near
extrn count_in_err: near
extrn count_out_err: near
public recv
recv:
ifdef IO_INTCLR
loadport ;clear the interupt latch.
setport IO_INTCLR
out dx,al
endif
mov flag, 1
;called from the recv isr. All registers have been saved, and ds=cs.
;Upon exit, the interrupt will be acknowledged.
recv1:
mov ds,base_addr ; base for board
assume ds:nothing
mov ax,ds:[SCB].scb_stat ;get the status.
recv_isr_1:
cmp ds:[SCB].scb_com,0 ;has previous command been accepted?
jne recv_isr_1 ;no -- keep waiting.
and ax,0f000h ;isolate the ACK bits to make a
; command to ack the interrupt.
if DAN and 1
jz recv_isr_2
endif
mov ds:[SCB].scb_com,ax ;set the command.
call doca
recv_isr_2:
cmp ds:[SCB].scb_com,0 ; has the command been accepted?
jnz recv_isr_2 ; not yet.
; Get whatever packets are on the board
;
mov bx,firstfd ; get addr of first FD in list
mov ax,[bx].fd_status ; status word of frame
test ax,08000h ; frame written?
jnz okframe
jmp ru_start ; no, restore receiver if necessary
frame_bad:
call count_in_err
ptrupdate_j_1:
jmp ptrupdate
; we have a frame, read it in
;
okframe:
test ax,02000h ;check frame OK bit
jz frame_bad ;bad, fix it.
mov si,[bx].fd_ptr ;get pointer to buffer descriptor
xor cx,cx ;start with zero bytes.
countbuf: ;es:di is already set to receive packet
mov dx,si ;save a copy of current BD ptr
mov ax,[si].rbd_status ;get status and count word for BD
test ax,04000h ;is count field there?
jz ptrupdate_j_1 ;no - we give up here.
add cl,al ;add the count into cx.
adc ch,0
mov si,[si].rbd_link ;go to next BD in list
test ax,8000h ;is this the last frame?
je countbuf ;no - keep counting.
push bx
push cx
mov ax,cs ;we need ds = code.
mov ds,ax
assume ds:code
mov es,base_addr ;get a pointer to their type.
mov di,es:[bx].fd_ptr ;get pointer to buffer descriptor
mov di,es:[di].rbd_ptr.offs ;get offset of data
add di,EADDR_LEN+EADDR_LEN ;skip the ethernet addreses and
; point to the packet type.
mov dl, BLUEBOOK ;assume bluebook Ethernet.
mov ax, es:[di]
xchg ah, al
cmp ax, 1500
ja BlueBookPacket
inc di ;set di to 802.2 header
inc di
mov dl, IEEE8023
BlueBookPacket:
call recv_find ;look up our type.
pop cx
pop bx
mov ds,base_addr ;restore ds to the board.
assume ds:nothing
mov ax,es ;is this pointer null?
or ax,di
je ptrupdate ;yes - just free the frame.
push cx
push es ;remember where the buffer pointer is.
push di
if DAN and 2
push cx
endif
mov si,[bx].fd_ptr ;get pointer to buffer descriptor
copybuf:
mov dx,si ;save a copy of current BD ptr
xor ch,ch ;200 bytes is largest this can be
mov cl,byte ptr [si].rbd_status;get count word for BD
mov si,[si].rbd_ptr.offs ;get offset of data
if DAN and 2
pop ax
sub ax, cx
jc copydone
push ax
ENDIf
call movemem
mov si,dx ;get back current BD ptr
test [si].rbd_status,8000h ;check EOF bit
mov si,[si].rbd_link ;go to next BD in list
jz copybuf ;not done, keep copying it.
if DAN and 2
pop cx
copydone:
endif
pop si ;now give the frame to the client.
pop ds
pop cx
assume ds:nothing
call recv_copy
;
; we are done with the frame, do the list management
;
ptrupdate:
movseg ds,cs
assume ds:code
mov es,base_addr ; reload board segment
mov si,es:[bx].fd_ptr ; first BD in frame list
nextbd:
mov cx,es:[si].rbd_status ; count word for BD, EOF bit
test cx,08000h ; EOF bit, if set, save si in lastbd
jnz dolastbd
mov es:[si].rbd_status,0 ; clear status word, EOF bit
cmp si,lastbd ; see if we are wrapping
jz dolastbd ; yes, just undo it
mov si,es:[si].rbd_link ; follow link
jmp nextbd
dolastbd:
mov di,lastbd ; where end of BD list is now
mov lastbd,si ; store last known BD
mov es:[si].rbd_size,08000h+200; end of list here
mov es:[si].rbd_status,0 ; clear status word, EOF bit
; size field for not end of list
mov es:[di].rbd_size,200 ; remove old end-of-list
;
; update the FD list flags, new end-of-list
;
mov es:[bx].fd_eol,08000h ; store new EOL
mov es:[bx].fd_status,0 ; clear status word for frame
mov di,lastfd ; get old end-of-list
mov es:[di].fd_eol,0 ; zero old one
mov lastfd,bx ; update stored pointer
mov si,es:[bx].fd_link ; where next fd is
mov firstfd,si ; store that info for next time
if DAN and 4
jmp recv1
endif
ru_start:
; re-start receive unit
;
; check to see if the receiver went off because of no resources
; and restart receiver if necessary
;
movseg ds,cs
mov es,base_addr
mov ax,es:[SCB].scb_stat ; status word for SCB
and ax,070h ; receiver status
cmp al,020h ; receiver has no resources
jnz hasres
if DAN and 8
cmp flag, 1
jnz ru_start1
mov flag, 0
jmp recv1
endif
ru_start1:
call count_out_err
;
; setup lists for starting the RU on the chip
; we know that there isn't anything in the buffer that we want
;
mov bx,firstfd ; get first FD on free list (assume free)
mov es:[SCB].scb_rfa,bx ; put into SCB
mov si,lastbd ; pointer to a BD, end of chain
mov ax,es:[si].rbd_link ; pointer to next BD
mov es:[bx].fd_ptr,ax ; set to start of BDs
;
;
; Start the RU, doesn't need CB, only SCB parms.
; command, to start receiving again
;
mov ax,10h ; start RU
call doca_wait
hasres:
;I don't we need to wait here because we haven't done anything to wait for.
ret
public set_address
set_address:
assume ds:nothing
;enter with ds:si -> Ethernet address, CX = length of address.
;exit with nc if okay, or cy, dh=error if any errors.
cmp cx,EADDR_LEN ;ensure that their address is okay.
je set_address_4
mov dh,BAD_ADDRESS
stc
jmp short set_address_done
set_address_4:
; Next step, load our address into the board
; reuses the space that the configure command used, with different command
;
mov es,base_addr ; set to base address
mov es:[SCB].scb_cbl,CCBPTR ; say where conf command is
mov di,CCBPTR ; start of config command block
xor ax,ax
stosw ; zero status word for commmand
mov ax,8001h ; IA setup command + EL
stosw
xor ax,ax
dec ax
stosw ; set link value to -1 (unused)
rep movsb ; move their ethernet address in.
;
; start the IA setup command
;
mov ax,100h ; do-command command
call doca_wait
jnc set_address_okay
mov dh,-1 ; no error in the list applies.
jmp short set_address_done
set_address_okay:
mov cx,EADDR_LEN ;return their address length.
clc
set_address_done:
movseg ds,cs
assume ds:code
ret
public timer_isr
timer_isr:
;if the first instruction is an iret, then the timer is not hooked
iret
;any code after this will not be kept. Buffers used by the program, if any,
;are allocated from the memory between end_resident and end_free_mem.
public end_resident,end_free_mem
end_resident label byte
end_free_mem label byte
timeout_msg db "Timed out while initializing the board.",CR,LF,'$'
addr_bad_msg db "Memory address should be less than 65536.",CR,LF,'$'
security_msg label byte
db "Security is enabled. Do not attempt to change the ethernet address or",CR,LF
db "set promiscuous mode on this board. Unexpected results may occur.",CR,LF
db '$'
mem8_16 db 2 ; 1 for 16k, 2 for 8k
extrn set_recv_isr: near
extrn maskint: near
;enter with si -> argument string, di -> word to store.
;if there is no number, don't change the number.
extrn get_number: near
;enter with dx -> name of word, di -> dword to print.
extrn print_number: near
;enter with ax = number to print.
extrn decout: near
;-> the assigned Ethernet address of the card.
extrn rom_address: byte
timeout_error:
mov dx,offset timeout_msg
jmp short error
error:
mov ah,9
int 21h
stc
ret
;
; data for configuring and setting up the board
;
; chip always looks at SCP for config info which points to ISCP for the
; pointer to the CONTROL BLOCK which handles everything from there.
; Kind of indirect, but it works.
;
SCP DB 0 ; bus use flag (0=16 bit, 1=8 bit).
public etopen
etopen:
mov al,int_no
call maskint ;disable these interrupts.
cmp base_addr.offs,0 ;low word of segment can't be zero.
je etopen_1
cmp base_addr.segm,0 ;high word of segment must be zero.
je etopen_2
etopen_1:
mov dx,offset addr_bad_msg
stc
ret
etopen_2:
; Initialize the Ethernet board, set receive type.
;
mov es,base_addr
;
; Check for the ATTLAN signature in shared memory
;
mov di,3ff9h
cmp byte ptr es:[di],'A'
jnz no_sig
inc di
cmp byte ptr es:[di],'T'
jnz no_sig
inc di
cmp byte ptr es:[di],'T'
jnz no_sig
inc di
cmp byte ptr es:[di],'L'
jnz no_sig
inc di
cmp byte ptr es:[di],'A'
jnz no_sig
inc di
cmp byte ptr es:[di],'N'
jnz no_sig
mov di,io_addr
shr di,1
shr di,1
shr di,1
shr di,1
and di,001fh
mov es:[3fffh],di
no_sig:
;
; check for correct EPROM location
;
call check_board
jnc etopen_3
ret
etopen_3:
;
; Turn off interrupts, I don't want them
;
ifdef IOINTOF
loadport
setport IOINTOF
out dx,al
endif
;
; Disconnect from network
;
ifdef IODIS
loadport
setport IODIS
out dx,al
endif
;
; Initialize the Ethernet board.
;
mov di,00000h ;our initial base address.
mov si,ISCPTR-2 ;try the init down a little.
;
; Now discern the end of memory by repeatedly re-initializing the board
; until the BUSY flag in the ISCP gets reset.
;
re_discern:
mov es,base_addr ;remember where we think it starts.
call init_root ;did we find our memory size?
jc confbad ;no, keep trying.
inc si ;yes, see if we found the real one.
inc si
call init_root ;try initializing it in a different locn.
jnc confok ;it worked! we've found the root.
confbad:
sti
jmp timeout_error
confok:
mov memory_begin,di
call reconfigure
jc confbad
;
; We have to determine if security is enabled on the board. This is done by
; attempting to set the board into promiscuous mode (rcv_mode_6). We will
; then check to see if the "Command Abort" bit has been set. If it has, then
; security is enabled and we will notify the user.
;
call rcv_mode_6
jc confbad
test es:[CCBPTR].cmd_status,01000h
jz no_security
mov dx,offset security_msg
mov ah,9
int 21h
mov word ptr rcv_modes+14,0000h
no_security:
call rcv_mode_3
jc confbad
;
; Ask the board for the Ethernet address, and then use set_address to set it.
;
movseg es,ds
mov di,offset rom_address
mov cx,EADDR_LEN
call get_address
mov si,offset rom_address
mov cx,EADDR_LEN
call set_address
jnc store_address_2
sti
jmp timeout_error
store_address_2:
;
; IA sent, setup all of the other data structures on the board
; start with xmit command descriptors
;
mov di,TCBPTR
mov es:[di].tcb_status,0
mov es:[di].tcb_com,08004h
mov es:[di].tcb_link,-1
mov es:[di].tcb_ptr,TBDPTR
add di,(size tcb_struc)
mov es:[di].tbd_status,0
mov es:[di].tbd_link,0
mov es:[di].tbd_ptr.offs,TBUFPTR
mov es:[di].tbd_ptr.segm,0
; Note that we allocate fd's, rbd's, and buffers all at the same time. This
; doesn't mean that each pair of fd's and rbd's necessarily have anything to
; do with each other. We just allocate them together because we want to have
; the same number of each, and it's easier to compute that way.
mov di,TBUFPTR ;get the last buffer.
mov ax,di ;compute the amount of free memory.
sub ax,memory_begin
xor dx,dx
mov bx,RBUF_TOTAL ;each buffer takes this much.
div bx
mov cx,ax ;put the number of buffers into cx.
init_rbuff_0:
sub di,RBUF_TOTAL ;back the pointer down by a little.
;init the FD.
mov es:[di].fd_status,0
mov es:[di].fd_eol,0
mov es:[di].fd_ptr,-1
lea ax,[di]-RBUF_TOTAL ;get the address of the next buffer.
mov es:[di].fd_link,ax
;init the BD.
lea bx,[di + (size fd_struc)]
mov es:[bx].rbd_status,0
lea ax,[bx-RBUF_TOTAL] ;make a pointer to the next BD
mov es:[bx].rbd_link,ax
lea ax,[bx+(size rbd_struc)] ;make a pointer to the buffer.
mov es:[bx].rbd_ptr.offs,ax
mov es:[bx].rbd_ptr.segm,0
mov es:[bx].rbd_size,RBUFLEN ;length of the buffer.
loop init_rbuff_0
init_rbuff_1:
;patch the parameters of the last FD and BD so they link around to the head.
mov es:[di].fd_eol,8000h
mov es:[di].fd_link,FDBASE
mov lastfd,di
lea bx,[di + (size fd_struc)]
mov es:[bx].rbd_link,FDBASE + (size fd_struc)
mov es:[bx].rbd_size,RBUFLEN + 8000h
mov lastbd,bx
;now put the location of the first rbd into the first fd.
mov es:[FDBASE].fd_ptr,FDBASE + (size fd_struc)
call enable_network
;
; Start the RU, doesn't need CB, only SCB parms.
; command, to start receiving
;
mov es:[SCB].scb_rfa,FDBASE ; set to frame descriptors
mov ax,10h ; start RU
call doca_wait
;
; Now reset CX, FR, CNA, and RNR so that we don't get a spurious interrupt.
;
mov ax,es:[SCB].scb_stat ;get the status.
and ax,0f000h ;isolate the ACK bits.
mov es:[SCB].scb_com,ax ;make a command to
;acknowledge the interrupt.
call doca
;
; Now hook in our interrupt
;
call set_recv_isr
sti
mov al, int_no ; Get board's interrupt vector
add al, 8
cmp al, 8+8 ; Is it a slave 8259 interrupt?
jb set_int_num ; No.
add al, 70h - 8 - 8 ; Map it to the real interrupt.
set_int_num:
xor ah, ah ; Clear high byte
mov int_num, ax ; Set parameter_list int num.
clc
ret
init_root:
;enter with es:di -> beginning of our system memory window,
; si -> place to put ISC.
;exit with nc if it worked, cy if it didn't work.
mov al,SCP
mov es:[SCPTR].scp_bus,al
mov es:[SCPTR].scp_ptr.offs,si
mov es:[SCPTR].scp_ptr.segm,0
mov es:[si].iscp_busy,1 ;set busy bit.
mov es:[si].iscp_offset,SCB ;point to the SCB.
mov es:[si].iscp_base.offs,0 ;scb base.
mov es:[si].iscp_base.segm,0 ;scb base.
call reset_586 ; reset the 586, hardware-specific.
push ax
in al, 61h
in al, 61h
in al, 61h
pop ax
mov al,int_no
cmp al,2
jnz int_not2
mov al,9
int_not2:
loadport
setport IOINTR
out dx,al
mov al,08h
mov ah,media_sel
or ah,ah
jz only_aui
add al,04h
mov ah,li_enabl
or ah,ah
jz tp_noli
add al,02h
tp_noli:
only_aui:
loadport
setport IOMISC
out dx,al
; mov ax,1
; call set_timeout
;time_delay:
; call do_timeout
; jne time_delay
push ax
in al, 61h
in al, 61h
in al, 61h
pop ax
;
; Issue a CA to initialize the chip after reset
;
call doca
push ax
in al, 61h
in al, 61h
in al, 61h
pop ax
; mov ax,2 ;don't wait too long.
; call set_timeout
;init_root_2:
cmp es:[si].iscp_busy,0 ;did it clear the busy flag?
je init_root_1 ;yes.
; call do_timeout
; jne init_root_2
stc
ret
init_root_1:
clc
ret