home *** CD-ROM | disk | FTP | other *** search
- 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
-