home *** CD-ROM | disk | FTP | other *** search
- version equ 2
- ;History:1145,1
-
- .286
-
- ; Copyright, 1988-1992, Russell Nelson, Crynwr Software
-
- ; 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.
-
- ;-------------------------------------------------------------------------
- ; vA 4/3/93 Hacks for multiple ISA board support added, IJW @ Leeds Univ.
- ; vB 10/3/93 Added checks for legal packet size in rx, ijw.
- ;-------------------------------------------------------------------------
-
- include defs.asm
-
- code segment word public
- assume cs:code, ds:code
-
- ;----------------------------------------------------------------------------;
- ; ;
- ; This source file is the property of 3Com Corporation and may not be ;
- ; copied or distributed in any isomorphic form without an appropriate ;
- ; prior licensing arrangement with 3Com Corporation. ;
- ; ;
- ; Copyright (c) 1988 3Com Corporation ;
- ; ;
- ;------ Equates -------------------------------------------------------------;
- ;
- ; Command code masks
- ;
- CMD_CMDMASK equ 0F800h ; command bits
- CMD_ARGMASK equ 007FFh ; argument bits
- ;
- ; Command codes, word form
- ;
- CMD_GLOBALRESET equ 00000b shl 11 ; global reset
- CMD_SELECTWINDOW equ 00001B shl 11 ; select register window
- CMD_STARTINTXCVR equ 00010b shl 11 ; start internal transciver
- CMD_RXDISABLE equ 00011b shl 11 ; rx disable
- CMD_RXENABLE equ 00100b shl 11 ; rx enable
- CMD_RXRESET equ 00101b shl 11 ; rx reset
- CMD_RXDISCARD equ 01000b shl 11 ; rx discard top packet
- CMD_TXENABLE equ 01001b shl 11 ; tx enable
- CMD_TXDISABLE equ 01010b shl 11 ; tx disable
- CMD_TXRESET equ 01011b shl 11 ; tx reset
- CMD_REQUESTINT equ 01100b shl 11 ; request interrupt
- CMD_ACKNOWLEDGE equ 01101b shl 11 ; acknowledge interrupt
- CMD_SETINTMASK equ 01110b shl 11 ; set interrupt mask
- CMD_SETRZMASK equ 01111b shl 11 ; set read zero mask
- CMD_SETRXFILTER equ 10000b shl 11 ; set rx filter
- CMD_SETRXEARLY equ 10001b shl 11 ; set rx early threshold
- CMD_SETTXAVAILABLE equ 10010b shl 11 ; set tx available threshold
- CMD_SETTXSTART equ 10011b shl 11 ; set tx start threshold
- CMD_STATSENABLE equ 10101b shl 11 ; statistics enable
- CMD_STATSDISABLE equ 10110b shl 11 ; statistics disable
- CMD_STOPINTXCVR equ 10111b shl 11 ; start internal transciver
- ;
- ; Command codes, hibyte form (commands without operands only)
- ;
- CMDH_STARTINTXCVR equ CMD_STARTINTXCVR shr 8
- CMDH_RXDISABLE equ CMD_RXDISABLE shr 8
- CMDH_RXENABLE equ CMD_RXENABLE shr 8
- CMDH_RXDISCARD equ CMD_RXDISCARD shr 8
- CMDH_TXENABLE equ CMD_TXENABLE shr 8
- CMDH_TXDISABLE equ CMD_TXDISABLE shr 8
- CMDH_REQUESTINT equ CMD_REQUESTINT shr 8
- CMDH_STATSENABLE equ CMD_STATSENABLE shr 8
- CMDH_STATSDISABLE equ CMD_STATSDISABLE shr 8
- CMDH_STOPINTXCVR equ CMD_STOPINTXCVR shr 8
- ;
- ; Status register bits (INT for interrupt sources, ST for the rest)
- ;
- INT_LATCH equ 00001h ; interrupt latch
- INT_ADAPTERFAIL equ 00002h ; adapter failure
- INT_TXCOMPLETE equ 00004h ; tx complete
- INT_TXAVAILABLE equ 00008h ; tx available
- INT_RXCOMPLETE equ 00010h ; rx complete
- INT_RXEARLY equ 00020h ; rx early
- INT_REQUESTED equ 00040h ; interrupt requested
- INT_UPDATESTATS equ 00080h ; update statistics
- ST_FAILED equ 00800h ; command failed
- ST_BUSY equ 01000h ; command busy
- ST_WINDOW equ 0E000h ; window bits (13-15)
-
- STH_FAILED equ ST_FAILED shr 8
- STH_BUSY equ ST_BUSY shr 8
- STH_WINDOW equ ST_WINDOW shr 8
-
- ;
- ; RxStatus register bits
- ;
- RXS_INCOMPLETE equ 8000h ; not completely received
- RXS_ERROR equ 4000h ; error in packet
- RXS_LENGTH equ 07FFh ; bytes in RxFIFO
- RXS_ERRTYPE equ 3800h ; Rx error type, bit 13-11
- RXS_OVERRUN equ 0000h ; overrun error
- RXS_OVERSIZE equ 0800h ; oversize packet error
- RXS_DRIBBLE equ 1000h ; dribble bit (not an error)
- RXS_RUNT equ 1800h ; runt packet error
- RXS_CRC equ 2800h ; CRC error
- RXS_FRAMING equ 2000h ; framing error
-
- RXSH_INCOMPLETE equ RXS_INCOMPLETE shr 8
- RXSH_ERROR equ RXS_ERROR shr 8
- RXSH_ERRTYPE equ RXS_ERRTYPE shr 8
- RXSH_OVERRUN equ RXS_OVERRUN shr 8
- RXSH_DRIBBLE equ RXS_DRIBBLE shr 8
- RXSH_CRC equ RXS_CRC shr 8
- RXSH_RUNT equ RXS_RUNT shr 8
- RXSH_OVERSIZE equ RXS_OVERSIZE shr 8
- RXSH_FRAMING equ RXS_FRAMING shr 8
- ;
- ; TxStatus register bits
- ;
- TXS_COMPLETE equ 80h ; tx completed
- TXS_INTREQUESTED equ 40h ; interrupt on successfull tx
- TXS_ERRTYPE equ 38h ; error bits
- TXS_JABBERERROR equ 20h ; jabber error
- TXS_UNDERRUN equ 10h ; tx underrun error
- TXS_MAXCOLLISIONS equ 08h ; max collisions error
- TXS_STATUSOVERFLOW equ 04h ; TX status stack is full
- ;
- ; Window Numbers
- ;
- WNO_SETUP equ 0 ; setup/configuration
- WNO_OPERATING equ 1 ; operating set
- WNO_STATIONADDRESS equ 2 ; station address setup/read
- WNO_FIFO equ 3 ; FIFO management
- WNO_DIAGNOSTICS equ 4 ; diagnostics
- WNO_READABLE equ 5 ; registers set by commands
- WNO_STATISTICS equ 6 ; statistics
- ;
- ; Port offsets, Window 1 (WNO_OPERATING)
- ;
- PORT_CmdStatus equ 0Eh ; command/status
- PORT_TxFree equ 0Ch ; free transmit bytes
- PORT_TxStatus equ 0Bh ; transmit status (byte)
- PORT_Timer equ 0Ah ; latency timer (byte)
- PORT_RxStatus equ 08h ; receive status
- PORT_RxFIFO equ 00h ; RxFIFO read
- PORT_TxFIFO equ 00h ; TxFIFO write
- ;
- ; Port offsets, Window 0 (WNO_SETUP)
- ;
- PORT_EEData equ 0Ch ; EEProm data register
- PORT_EECmd equ 0Ah ; EEProm command register
- PORT_CfgResource equ 08h ; resource configuration
- PORT_CfgAddress equ 06h ; address configuration
- PORT_CfgControl equ 04h ; configuration control
- PORT_ProductID equ 02h ; product id (EISA)
- PORT_Manufacturer equ 00h ; Manufacturer code (EISA)
- ;
- ; Port offsets, Window 2 (WNO_STATIONADDRESS)
- ;
- PORT_SA0_1 equ 00h ; station address bytes 0,1
- PORT_SA2_3 equ 02h ; station address bytes 2,3
- PORT_SA4_5 equ 04h ; station address bytes 4,5
- ;
- ; Port offsets, Window 3 (WNO_FIFO)
- ;
- PORT_ALT_TxFree equ 0Ch ; free transmit bytes (dup)
- PORT_RxFree equ 0Ah ; free receive bytes
- ;
- ; Port offsets, Window 4 (WNO_DIAGNOSTICS)
- ;
- PORT_MediaStatus equ 0Ah ; media type/status
- PORT_SlingshotStatus equ 08h ; Slingshot status
- PORT_NetDiagnostic equ 06h ; net diagnostic
- PORT_FIFODiagnostic equ 04h ; FIFO diagnostic
- PORT_HostDiagnostic equ 02h ; host diagnostic
- PORT_TxDiagnostic equ 00h ; tx diagnostic
- ;
- ; Port offsets, Window 5 (WNO_READABLE)
- ;
- PORT_RZMask equ 0Ch ; read zero mask
- PORT_IntMask equ 0Ah ; interrupt mask
- PORT_RxFilter equ 08h ; receive filter
- PORT_RxEarly equ 06h ; rx early threshold
- PORT_TxAvailable equ 02h ; tx available threshold
- PORT_TxStart equ 00h ; tx start threshold
- ;
- ; Port offsets, Window 6 (WNO_STATISTICS)
- ;
- PORT_TXBYTES equ 0Ch ; tx bytes ok
- PORT_RXBYTES equ 0Ah ; rx bytes ok
- PORT_TXDEFER equ 08h ; tx frames deferred (byte)
- PORT_RXFRAMES equ 07h ; rx frames ok (byte)
- PORT_TXFRAMES equ 06h ; tx frames ok (byte)
- PORT_RXDISCARDED equ 05h ; rx frames discarded (byte)
- PORT_TXLATE equ 04h ; tx frames late coll. (byte)
- PORT_TXSINGLE equ 03h ; tx frames one coll. (byte)
- PORT_TXMULTIPLE equ 02h ; tx frames mult. coll. (byte)
- PORT_TXNOCD equ 01h ; tx frames no CDheartbt (byte)
- PORT_TXCARRIERLOST equ 00h ; tx frames carrier lost (byte)
- ;
- ; Various command arguments
- ;
- INT_ALLDISABLED equ 00000000000b ; all interrupts disabled
- INT_ALLENABLED equ 00011111110b ; all interrupts enabled
-
- FILTER_INDIVIDUAL equ 0001b ; individual address
- FILTER_MULTICAST equ 0010b ; multicast/group addresses
- FILTER_BROADCAST equ 0100b ; broadcast address
- FILTER_PROMISCUOUS equ 1000b ; promiscuous mode
-
- RXEARLY_DISABLED equ 2032 ; RxEarly to disable
-
- TXAVAIL_DISABLED equ 2040 ; TxAvailable to disable
- TXAVAIL_MIN equ 4
-
- TXSTART_DISABLED equ 2040 ; TxStart to disable
- TXSTART_MIN equ 0
- TXSTART_MAX equ TXSTART_DISABLED
-
- RXLENGTH_MAX equ 1792 ; maximum rxlength
- ;
- ; Transmit Preamble
- ;
- PREAMBLESIZE equ 4 ; transmit preamble size
- TXP_INTONSUCCESS equ 8000h ; interrupt on successful tx
- ;
- ; Bits in various diagnostics registers
- ;
- MEDIA_TP equ 8000h ; TP transciever
- MEDIA_BNC equ 4000h ; Thinnet transciever
- MEDIA_INTENDEC equ 2000h ; internal encoder/decoder
- MEDIA_SQE equ 1000h ; SQE present
- MEDIA_LBEAT equ 0800h ; link beat ok (TP)
- MEDIA_POLARITY equ 0400h ; polarity (TP)
- MEDIA_JABBER equ 0200h ; jabber (TP)
- MEDIA_UNSQUELCH equ 0100h ; unsquelch (TP)
- MEDIA_LBEATENABLE equ 0080h ; link beat enable (TP)
- MEDIA_JABBERENABLE equ 0040h ; jabber enable (TP)
- MEDIA_CRS equ 0020h ; carrier sense
- MEDIA_COLLISION equ 0010h ; collision
- MEDIA_SQEENABLE equ 0008h ; enable SQE statistics
-
- NETD_EXTLOOPBACK equ 8000h ; TP external loopback
- NETD_ENDECLOOPBACK equ 4000h ; ENDEC loopback
- NETD_CORELOOPBACK equ 2000h ; ethernet core loopback
- NETD_FIFOLOOPBACK equ 1000h ; FIFO loopback
- NETD_TXENABLED equ 0800h ; tx enabled
- NETD_RXENABLED equ 0400h ; rx enabled
- NETD_TXTRANSMITTING equ 0200h ; tx transmitting
- NETD_TXRESETREQD equ 0100h ; tx reset required
-
- FIFOD_RXRECEIVING equ 8000h ; rx receiveing
- FIFOD_RXUNDERRUN equ 2000h ; rx underrun
- FIFOD_RXSTATUSOVER equ 1000h ; rx status overrun
- FIFOD_RXOVERRUN equ 0800h ; rx overrun
- FIFOD_TXOVERRUN equ 0400h ; tx overrun
- FIFOD_BISTRESULTS equ 00FFh ; BIST results (mask)
-
- SLING_TXUNDERRUN equ 2000h ; Slingshot TxUnderrun bit
- ;
- ; board identification codes, byte swapped in Rev 0
- ;
- EISA_MANUFACTURER_ID equ 06D50h ; EISA manufacturer code
- ISA_PRODUCT_ID equ 09050h ; Product ID for ISA board
- PRODUCT_ID_MASK equ 0F0FFh ; Mask off revision nibble
- ;
- ; EEProm access
- ;
- EE_BUSY equ 8000h ; EEProm busy bit in EECmd
- EE_TCOM_NODE_ADDR_WORD0 equ 00h
- EE_TCOM_NODE_ADDR_WORD1 equ 01h
- EE_TCOM_NODE_ADDR_WORD2 equ 02h
- EE_VULCAN_PROD_ID equ 03h
- EE_MANUFACTURING_DATA equ 04h
- EE_SERIAL_NUMBER_WORD0 equ 05h
- EE_SERIAL_NUMBER_WORD1 equ 06h
- EE_MANUFACTURER_CODE equ 07h
- EE_ADDR_CONFIGURATION equ 08h
- EE_RESOURCE_CONFIGURATION equ 09h
- EE_OEM_NODE_ADDR_WORD0 equ 0Ah
- EE_OEM_NODE_ADDR_WORD1 equ 0Bh
- EE_OEM_NODE_ADDR_WORD2 equ 0Ch
- EE_SOFTWARE_CONFIG_INFO equ 0Dh
- EE_CWORD equ 0Eh
- ;
- ; contention logic
- ;
- READ_EEPROM equ 080h
- ID_GLOBAL_RESET equ 0C0h
- SET_TAG_REGISTER equ 0D0h
- TEST_TAG_REGISTER equ 0D8h
- ACTIVATE_AND_SET_IO equ 0E0h
- ACTIVATE_VULCAN equ 0FFh
- ;
- ; Resource Configuration Register bits
- ;
- RCONFIG_IRQ equ 0F000h
- ;
- ; Address Configuration Register bits
- ;
- ACONFIG_XCVR equ 0C000h
- ACONFIG_IOBASE equ 0001Fh
-
- IOBASE_EISA equ 0001Fh
-
- TP_XCVR equ 00000h
- BNC_XCVR equ 0C000h
- AUI_XCVR equ 04000h
-
- MIN_IO_BASE_ADDR equ 200h
- MAX_IO_BASE_ADDR equ 3F0h
- REGISTER_SET_SIZE equ 10h
- ;
- ; Software Configuration Register bits
- ;
- SW_OPTIMIZE equ 0030h
- SW_MAXCLI equ 3F00h
- SW_LINKBEAT equ 4000h
- ;
- ; Possibilities for SW_OPTIMIZE
- ;
- OPTIMIZE_DOS_CLIENT equ 0010h
- OPTIMIZE_WINDOWS_CLIENT equ 0020h
- OPTIMIZE_SERVER equ 0030h
- ;
- ; Configuration Control Register bits
- ;
- ENABLE_ADAPTER equ 01h
-
- setwin macro win
- setport PORT_CmdStatus
- mov ax,CMD_SELECTWINDOW+win
- out dx,ax
- endm
-
- extrn is_eisa: byte ;=0 if ISA, =1 if EISA
- extrn is_186: byte ;=0 if 808[68], =1 if 80[1234]86.
- extrn is_386: byte ;=0 if 80[12]8[68], =1 if 80[34]86.
-
- public int_no, io_addr
- int_no db 0,0,0,0 ;must be four bytes long for get_number.
- io_addr dw 0,0 ;must be four bytes long for get_number.
-
- public driver_class, driver_type, driver_name, driver_function, parameter_list
- driver_class db BLUEBOOK,IEEE8023,0 ;null terminated list of classes.
- driver_type db 94 ;assigned by FTP Software, <jbvb@ftp.com>
- driver_name db '3c509',0 ;name of the driver.
- driver_function db 2
- parameter_list label byte
- db 1 ;major rev of packet driver specification
- db 9 ;minor rev of packet driver specification
- db 14 ;length of parameter list
- db EADDR_LEN ;length of MAC-layer address
- dw GIANT ;MTU, including MAC headers
- dw MAX_MULTICAST * EADDR_LEN ;buffer size of multicast addrs
- dw 0 ;(# of back-to-back MTU rcvs) - 1
- dw 0 ;(# of successive xmits) - 1
- int_num dw 0 ;Interrupt # to hook for post-EOI
- ;processing, 0 == none,
-
- public rcv_modes
- rcv_modes dw 7 ;number of receive modes in our table.
- dw 0 ;There is no mode zero
- dw rcv_mode_1
- dw rcv_mode_2
- dw rcv_mode_3
- dw 0 ;haven't set up perfect filtering yet.
- dw rcv_mode_5
- dw rcv_mode_6
-
- include timeout.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.
- ;if we're a high-performance driver, es:di -> upcall.
- ;exit with nc if ok, or else cy if error, dh set to error number.
- assume ds:nothing
- cmp cx,GIANT ; Is this packet too large?
- ja send_pkt_toobig
-
- loadport
- setport PORT_TxStatus ;get the previous transmit status.
- in al,dx
- setport PORT_CmdStatus
- test al,TXS_UNDERRUN or TXS_JABBERERROR ;do we need to reset transmitter?
- je send_pkt_0
- push ax
- mov ax,CMD_TXRESET
- out dx,ax
- pop ax
- send_pkt_0:
-
- test al,TXS_ERRTYPE ;any errors?
- je send_pkt_3 ;no.
- call count_out_err ;yes, count it.
- mov ax,CMD_TXENABLE ;yes, re-enable the transmitter.
- out dx,ax
- send_pkt_3:
-
- mov bx,cx ;round BX up to dword boundary.
- add bx,3
- and bx,not 3
-
- setport PORT_TxFree ;wait for enough bytes in transmit buffer.
- mov ax,18
- call set_timeout
- send_pkt_1:
- in ax,dx
- cmp ax,bx
- jae send_pkt_2
- call do_timeout
- jne send_pkt_1
- mov dh,CANT_SEND ;timed out, can't send.
- stc
- ret
- send_pkt_toobig:
- mov dh,NO_SPACE
- stc
- ret
- send_pkt_2:
-
- setport PORT_TxFIFO
- mov ax,cx ;output the count
- out dx,ax ; (no interrupt requested)
- out dx,ax ;output the second reserved word.
- mov cx,bx ;output the rest of the packet.
-
- cmp is_386,0 ;can we output dwords?
- jne send_pkt_7 ;yes.
- shr cx,1 ;output 16 bits at a time.
- rep outsw
- jmp short send_pkt_6
- send_pkt_7:
- .386
- shr cx,2 ;already rounded up.
- rep outsd ;output 32 bits at a time.
- .286
- send_pkt_6:
-
- clc
- ret
-
-
- public set_address
- set_address:
- ;enter with ds:si -> Ethernet address, CX = length of address.
- ;exit with nc if okay, or cy, dh=error if any errors.
- assume ds:nothing
- 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:
-
- loadport
- setwin WNO_STATIONADDRESS
- setport PORT_SA0_1
- set_address_1:
- lodsb
- out dx,al
- inc dx
- loop set_address_1
- set_address_okay:
- mov cx,EADDR_LEN ;return their address length.
- clc
- set_address_done:
- push cs
- pop ds
- assume ds:code
- loadport
- setwin WNO_OPERATING
- ret
-
-
- ;skip past the following two bytes while destroying BX.
- skip2 macro
- db 0bbh ;opcode of "mov bx,0000"
- endm
-
- rcv_mode_1:
- mov al,0 ;receive nothing
- skip2
- rcv_mode_2:
- mov al,1 ;receive individual address
- skip2
- rcv_mode_3:
- mov al,5 ;receive individual address+broadcast
- skip2
- rcv_mode_5:
- mov al,3 ;receive individual address+group addr(multicast)
- skip2
- rcv_mode_6:
- mov al,8 ;receive all packets.
- mov ah,CMD_SETRXFILTER shr 8 ;set receive filter
- loadport
- setport PORT_CmdStatus
- out dx,ax
- 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.
- mov dh,NO_MULTICAST
- stc
- ret
-
-
- public terminate
- terminate:
- loadport
- setport PORT_CmdStatus
- mov ax,CMD_GLOBALRESET
- out dx,ax
- ret
-
-
- public reset_interface
- reset_interface:
- ;reset the interface.
- assume ds:code
- ret
-
-
- ;decide if we know this packet's type.
- ;enter with es:di -> packet type, dl = packet class.
- ;exit with nc if we know it, cy if not.
- extrn recv_locate: near
-
- ;do the first upcall, get a pointer to the packet.
- ;enter with cx = packet length.
- ;exit with cx = packet length, es:di -> buffer for the packet.
- extrn recv_found: near
-
- ;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
-
- ether_buff db EADDR_LEN dup(?)
- db EADDR_LEN dup(?)
- ether_type db 8 dup(?)
- ETHER_BUFF_LEN equ $ - ether_buff
- .erre (ETHER_BUFF_LEN and 3) eq 0 ;must be an even # of dwords.
-
- early_bytes dw 0 ;the early byte gets the worm.
-
- read_header:
- ;enter with dx -> PORT_RxFIFO
- ;exit with es:di -> packet type.
-
- mov ax,ds
- mov es,ax
- mov di,offset ether_buff
- mov cx,ETHER_BUFF_LEN/4
- repinsd:
- shl cx,1 ;*** this gets changed into "rep insd"
- rep insw ;*** "nop" on a 386 or 486.
-
- mov di,offset ether_type
-
- mov dl, BLUEBOOK ;assume bluebook Ethernet.
- mov ax, es:[di]
- xchg ah, al
- cmp ax, 1500
- ja read_header_1
- inc di ;set di to 802.2 header
- inc di
- mov dl, IEEE8023
- read_header_1:
- ret
-
-
- public recv
- recv:
- ;called from the recv isr. All registers have been saved, ds=cs,
- ;our interrupt has been acknowledged, and our interrupts have been
- ;masked at the interrupt controller.
- assume ds:code
- recv_another:
- loadport
- setport PORT_CmdStatus
- in ax,dx ;did we get a packet?
- or ax,CMD_ACKNOWLEDGE
- out dx,ax
- setport PORT_RxStatus
- test al,INT_RXCOMPLETE
- jne recv_complete
- test al,INT_RXEARLY ;are we getting it early?
- jne recv_early
- jmp recv_exit ;no.
- recv_early:
- in ax,dx ;get the amount we can read.
- and ax,RXS_LENGTH
- cmp ax,ETHER_BUFF_LEN ;do we have enough to read early?
- jb recv_early_1 ;no, give up.
-
- mov early_bytes,ETHER_BUFF_LEN
-
- setport PORT_RxFIFO
- call read_header
- call recv_locate ;see if this is a type we want.
- jnc recv_early_1 ;it is, just exit.
- jmp recv_discard ;it isn't.
-
- recv_early_1:
- jmp recv_exit
-
- ;yes, this is dead code. It's only in here to ensure that the setport macro
- ;has the right value.
- setport PORT_RxStatus
- recv_complete:
- in ax,dx ;get the size.
- test ax,RXS_ERROR ;any errors?
- je recv_complete_2 ;no, it's fine.
-
- and ax,RXS_ERRTYPE ;get just the error type bits.
- cmp ax,RXS_DRIBBLE ;dribble is just a warning.
- jne recv_complete_1
-
- recv_err:
- call count_in_err
- jmp recv_discard
-
- recv_complete_1:
- in ax,dx ;get the size again.
- recv_complete_2:
- ;Put it on the receive queue
- and ax,RXS_LENGTH
- mov cx,ax
-
- cmp early_bytes,0 ;did we read the header in already?
- jne recv_complete_3 ;yes, we've already got it.
-
- cmp cx,RUNT ;check legal packet size
- jb recv_err
- cmp cx,GIANT
- ja recv_err
-
- push cx
- setport PORT_RxFIFO
- call read_header
- pop cx
-
- push cx
- call recv_find
- pop cx
- jmp short recv_complete_4
-
- recv_complete_3:
- add cx,early_bytes ;add in the early bytes we got.
-
- cmp cx,RUNT ;check legal packet size
- jb recv_err
- cmp cx,GIANT
- ja recv_err
-
- push cx
- call recv_found ;do the first upcall.
- pop cx
-
- recv_complete_4:
- mov ax,es ;is this pointer null?
- or ax,di
- je recv_discard ;yes - just free the frame.
-
- push es ;remember where the buffer pointer is.
- push di
-
- mov bx,cx ;save the count.
- mov cx,ETHER_BUFF_LEN/2 ;move the data over.
- mov si,offset ether_buff
- rep movsw
-
- loadport ;restore the I/O port.
- setport PORT_RxFIFO
- mov cx,bx ;restore the count.
- sub cx,ETHER_BUFF_LEN ;but leave off what we've already copied.
-
- cmp is_386,0
- jne io_input_386
- io_input_286:
- push cx
- shr cx,1
- rep insw
- pop cx
- jnc io_input_286_1 ;go if the count was even.
- insb ;get that last byte.
- in al,dx ;and get the pad byte.
- test cx,2 ;even number of words?
- jne io_input_done ;no.
- in ax,dx ;yes, get the pad word.
- jmp short io_input_done
- io_input_286_1:
- test cx,2 ;odd number of words?
- je io_input_done ;no.
- in ax,dx ;yes, get the pad word.
- jmp short io_input_done
-
- io_input_386:
- .386
- push eax
- push cx ;first, get all the full words.
- shr cx,2
- rep insd
- pop cx
- test cx,3 ;even number of dwords?
- je io_input_386_one_byte ;yes.
- in eax,dx ;no, get the partial word.
- test cx,2 ;a full word to be stored?
- je io_input_386_one_word
- stosw ;yes, store it,
- shr eax,16 ;and move over by a word.
- io_input_386_one_word:
-
- test cx,1 ;a full byte to be stored?
- je io_input_386_one_byte
- stosb ;yes, store it.
- io_input_386_one_byte:
- pop eax
- .286
-
- io_input_done:
-
- mov cx,bx ;restore the count.
- pop si
- pop ds
- assume ds:nothing
- call recv_copy ;tell them that we copied it.
-
- mov ax,cs ;restore our ds.
- mov ds,ax
- assume ds:code
-
- recv_discard:
- loadport
- setport PORT_CmdStatus
- mov ax,CMD_RXDISCARD
- out dx,ax
-
- recv_discard_1:
- in ax,dx ;wait for the command to finish.
- test ax,ST_BUSY
- jne recv_discard_1
-
- mov early_bytes,0
-
- jmp recv_another
- recv_exit:
- 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
-
-
- public usage_msg
- usage_msg db "usage: 3c509 [options] <packet_int_no> "
- db "[id_port]|[io_port]|[board_num]",CR,LF,'$'
- public copyright_msg
- copyright_msg db "Packet driver for a 3c509, version ",'0'+(majver / 10),'0'+(majver mod 10),".",'0'+version,CR,LF
- db "Portions Copyright 1992, Crynwr Software",CR,LF,'$'
- needs_186_msg db "Needs a 186 or higher-numbered processor",CR,LF,'$'
- no_isa_msg db CR,LF
- db "No 3c509 found. Use a different id_port value. Default is 0x110.",CR,LF,'$'
- reading_msg db "Reading EEPROM.",'$'
-
- multiple_msg db "Multiple 3C509s found, specify i/o port",CR,LF,'$'
- wrong_port_msg db "No 3C509 board found at specified i/o port",CR,LF,'$'
- eisa_in_isa_msg db "EISA configured board in ISA slot",CR,LF,'$'
-
- int_no_name db "Interrupt number ",'$'
- io_addr_name db "I/O port ",'$'
- aui_xcvr_msg db "Using AUI transceiver",CR,LF,'$'
- bnc_xcvr_msg db "Using BNC (10Base2) transceiver",CR,LF,'$'
- tp_xcvr_msg db "Using Twisted Pair (10BaseT) transceiver",CR,LF,'$'
- id_port_name db "ID port ",'$'
-
- ;called when you're ready to receive interrupts.
- extrn set_recv_isr: near
-
- ;enter with si -> argument string, di -> dword to store.
- ;if there is no number, don't change the number.
- extrn get_number: near
-
- ;enter with dx -> argument string, di -> dword to print.
- extrn print_number: near
-
- ;-> the unique Ethernet address of the card. Filled in by the etopen routine.
- extrn rom_address: byte
-
- ;-> current address. Normally the same as rom_address, unless changed
- ;by the set_address() call.
- extrn my_address: byte
-
- address_configuration dw ?
- resource_configuration dw ?
-
- is_10base2 db 0
- is_10baseT db 0
-
- id_port dw 110h,0
- scratch dw 0,0 ;for multi-board support
- board_number db 0
-
- ;print the character in al.
- extrn chrout: near
-
- ;print a crlf
- extrn crlf: near
-
- ;parse_args is called with si -> first parameter (CR if none).
- public parse_args
- parse_args:
- ;exit with nc if all went well, cy otherwise.
- mov di,offset scratch
- call get_number ;also returns number in bx:cx
- jc pa_ok
- cmp cx,15 ;board or slot?
- ja pa_id
- mov board_number,cl
- jmp parse_args
- pa_id:
- cmp cx,200h ;id-port (100-1f0) or io-port (200-3e0) ?
- jae pa_io
- cmp cx,100h
- jb pa_bad
- and cx,1F0h
- mov id_port,cx
- jmp parse_args
- pa_io:
- cmp cx,3E0h
- ja pa_bad ; bad value
- and cx,3F0h
- mov io_addr,cx
- jmp parse_args ; get another arg
- pa_ok:
- clc
- ret
- pa_bad:
- stc
- ret
-
-
- public etopen
- etopen:
- ;initialize the driver. Fill in rom_address with the assigned address of
- ;the board. Exit with nc if all went well, or cy, dx -> $ terminated error msg.
- ;if all is okay,
- cmp is_186,0 ;this version requires a 186 or better.
- jne etopen_1
- mov dx,offset needs_186_msg
- stc
- ret
- etopen_1:
-
- cmp is_386,0 ;can we do a real insd?
- je etopen_2
- ;overlay the repinsd routine with a real "rep insd;nop"
- mov word ptr repinsd+0,066h+0f3h*256
- mov word ptr repinsd+2,06dh+090h*256
- etopen_2:
-
- cmp is_eisa,0
- jne etopen_eisa
- jmp etopen_isa
- etopen_eisa:
- mov cx,0fh
- eisa_search:
- mov dx,cx ;move it into the first nibble.
- shl dx,12
- or dx,0c80h
- in ax,dx ;look for the manufacturer's ID
- cmp ax,EISA_MANUFACTURER_ID
- jne eisa_search_1
- inc dx
- inc dx
- in ax,dx ;look for the product ID
- and ax,PRODUCT_ID_MASK
- cmp ax,ISA_PRODUCT_ID
- je eisa_found
- eisa_search_1:
- loop eisa_search
- jmp etopen_isa ;;; if it's not EISA-configured, try ISA.
-
- eisa_found:
- and dx,0f000h
- mov io_addr,dx
-
- loadport
- setwin WNO_SETUP
-
- setport PORT_CfgAddress
- in ax,dx
- mov address_configuration,ax
-
- setport PORT_CfgResource
- in ax,dx
- mov resource_configuration,ax
-
- setport PORT_EECmd
- mov si,offset read_ee_eisa
- call read_eaddr
-
- jmp have_configuration
-
- ;---------------------------------------------------------------------------
- ; etopen_ISA for multiple 3c509 boards, added 3/93, IJW.
- ;
- etopen_isa:
- and id_port,01F0h
- mov dx,id_port
- xor bl,bl
-
- isa_1:
- cli
- call write_id_pat
- or bl,bl ; first board?
- jnz isa_2
- mov al,SET_TAG_REGISTER
- out dx,al
- isa_2:
- mov al,EE_MANUFACTURER_CODE
- call read_ee_isa
- cmp ax,EISA_MANUFACTURER_ID ; board here ?
- jne isa_3 ; no
-
- mov al,EE_OEM_NODE_ADDR_WORD0 ; must read the address..
- call read_ee_isa ; else it don't work ?!
- mov al,EE_OEM_NODE_ADDR_WORD1 ; address[1]
- call read_ee_isa ; address[2]
- mov al,EE_OEM_NODE_ADDR_WORD2
- call read_ee_isa ; address[3]
-
- inc bl ;count up a board.
- mov al,bl
- or al,SET_TAG_REGISTER
- out dx,al
- xor al,al
- out dx,al ; reset
- sti
- jmp isa_1 ; see if any more boards
-
- isa_3:
- xor al,al
- out dx,al ; reset
- sti
- or bl,bl ; found any boards ?
- jnz isa_4
-
- not_found_isa:
- mov dx,offset no_isa_msg
- stc
- ret
- isa_multiple:
- mov dx,offset multiple_msg
- stc
- ret
-
- isa_4:
- xor bl,bl
- isa_5:
- cli
- call write_id_pat
- inc bl
- mov al,bl
- add al,TEST_TAG_REGISTER
- out dx,al ; select the board
- mov al,SET_TAG_REGISTER
- out dx,al
- mov al,EE_MANUFACTURER_CODE
- call read_ee_isa
- cmp ax,EISA_MANUFACTURER_ID ; board here ?
- jne isa_8
-
- cmp io_addr,0 ; did user give an io_address ?
- je isa_6 ; no
- mov al,EE_ADDR_CONFIGURATION
- call read_ee_isa
- and ax,1Fh ; make real io-address
- shl ax,4
- add ax,MIN_IO_BASE_ADDR
- cmp ax,io_addr ; this board ?
- jne isa_7 ; no
-
- isa_6:
- cmp board_number,0
- jne isa_multiple
- mov board_number,bl
-
- isa_7:
- mov al,bl
- add al,set_tag_register ; D0
- out dx,al
- xor al,al ; reset
- out dx,al
- sti
- jmp isa_5 ; find the next board
-
- isa_8:
- sti
- cmp board_number,0 ; found the board?
- jne isa_9 ; yes
- mov dx,offset wrong_port_msg
- stc
- ret
-
- isa_9:
- cli
- call write_id_pat
- mov al,TEST_TAG_REGISTER
- add al,board_number
- out dx,al
- mov al,SET_TAG_REGISTER
- out dx,al
- mov al,EE_ADDR_CONFIGURATION
- call read_ee_isa
- mov address_configuration,ax
- cmp io_addr,0 ; know the base address?
- jne isa_10 ; yes
- and ax,1Fh
- shl ax,4
- add ax,min_io_base_addr ; make realworld io addr
- mov io_addr,ax
-
- isa_10:
- mov al,EE_RESOURCE_CONFIGURATION
- call read_ee_isa
- mov resource_configuration,ax
-
- mov si,offset read_ee_isa
- call read_eaddr
-
- mov al,SET_TAG_REGISTER
- or al,board_number
- out dx,al
- sti
-
- cmp io_addr,3F0h
- jne isa_start
- mov dx,offset eisa_in_isa_msg
- stc
- ret
-
- isa_start:
- mov al,ACTIVATE_VULCAN
- out dx,al
-
- have_configuration:
- mov ax,address_configuration
- and ax,BNC_XCVR or TP_XCVR or AUI_XCVR ;include all the bits.
- cmp ax,BNC_XCVR ;does it match BNC?
- jne not_10base2
- inc is_10base2
- not_10base2:
- cmp ax,TP_XCVR ;does it match TP?
- jne not_10baseT
- inc is_10baseT
- not_10baseT:
-
- mov bx,resource_configuration
- mov cl,12 ;move it over where we need it.
- shr bx,cl
- mov int_no,bl
-
- loadport
- setwin WNO_DIAGNOSTICS
- setport PORT_MediaStatus
- in ax,dx
- or ax,MEDIA_LBEATENABLE or MEDIA_JABBERENABLE
- out dx,ax
-
- setwin WNO_SETUP ;select Window 0
-
- mov ax,CMD_TXENABLE ;Enable the transmitter
- out dx,ax
-
- mov ax,CMD_RXENABLE ;Enable the receiver
- out dx,ax
-
- ;Enable RX Complete interrupts
- mov ax,CMD_SETINTMASK + INT_RXCOMPLETE + INT_RXEARLY
- out dx,ax
-
- mov ax,CMD_SETRZMASK + 0feh ;Enable all the status bits.
- out dx,ax
-
- mov ax,CMD_SETTXSTART + 0 ;start transmitting after this many bytes.
- out dx,ax
-
- mov ax,CMD_SETRXEARLY + 0 ;receive after this many bytes.
- out dx,ax
-
- cmp is_10base2,0 ;coax?
- je not_10base2_1 ;no.
- mov ax,CMD_STARTINTXCVR ;start internal transciever
- out dx,ax
- call delay_27_5ms
- not_10base2_1:
-
- setport PORT_CfgControl ;position to the CCR
- mov al,ENABLE_ADAPTER ;Enable the adapter.
- out dx,al
-
- call rcv_mode_3
-
- mov si,offset rom_address ;set our address.
- mov cx,EADDR_LEN
- call set_address_4
- ;sets the window to WNO_OPERATING.
-
- call set_recv_isr
-
- 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
- ;if we got an error,
- stc
- ret
-
-
- write_id_pat:
- ;write the 3c509 ID pattern to the ID port.
- ;enter with dx=id_port
- xor al,al
- out dx,al ;select the ID port.
- out dx,al ;reset hardware pattern generator
- mov cx,0ffh
- mov al,0ffh
- write_id_pat_1:
- out dx,al ;keep writing matching values...
- shl al,1
- jnc write_id_pat_2
- xor al,0cfh
- write_id_pat_2:
- loop write_id_pat_1
- ret
-
- read_eaddr:
- ;enter with dx = eeprom register, si -> routine to read eeprom.
- push cs
- pop es
- mov di,offset rom_address
-
- mov al,EE_TCOM_NODE_ADDR_WORD0 ;read the Ethernet address.
- call si
- xchg ah,al
- stosw
- mov al,EE_TCOM_NODE_ADDR_WORD1
- call si
- xchg ah,al
- stosw
- mov al,EE_TCOM_NODE_ADDR_WORD2
- call si
- xchg ah,al
- stosw
- ret
-
-
- read_ee_eisa:
- ;enter with al = EEPROM address to read, dx = PORT_EECmd
- ;exit with ax = data.
- or al,READ_EEPROM
- out dx,al
- read_ee_eisa_1:
- in ax,dx
- test ax,EE_BUSY
- jnz read_ee_eisa_1
- add dx,PORT_EEData - PORT_EECmd ;move to data register.
- in ax,dx
- add dx,PORT_EECmd - PORT_EEData ;move back to command register.
- ret
-
-
- read_ee_isa:
- ;enter with al = EEPROM address to read, dx = address of ID port.
- ;exit with ax = data, cx = 0.
- push bx
- or al,READ_EEPROM
- out dx,al
- ;wait 400 us here.
- call delay_27_5ms
- mov cx,16
- read_ee_isa_1:
- in al,dx
- shr al,1 ;put it into the carry.
- rcl bx,1 ;shift it into bx.
- loop read_ee_isa_1
- mov ax,bx
- pop bx
- ret
-
-
- delay_27_5ms:
- ;delay one timeout period, which is 27.5 ms.
- mov ax,1
- delay:
- ;delay AX timeout periods, each of which is 27.5 ms.
- call set_timeout
- delay_1:
- call do_timeout
- jnz delay_1
- ret
-
-
- public print_parameters
- print_parameters:
- ;echo our command-line parameters
- mov di,offset int_no
- mov dx,offset int_no_name
- call print_number
- mov di,offset io_addr
- mov dx,offset io_addr_name
- call print_number
- mov dx,offset aui_xcvr_msg
- cmp is_10base2,0 ;coax?
- je print_parameters_1
- mov dx,offset bnc_xcvr_msg
- print_parameters_1:
- cmp is_10baseT,0 ;tp?
- je print_parameters_2
- mov dx,offset tp_xcvr_msg
- print_parameters_2:
- mov ah,9
- int 21h
- mov di,offset id_port
- mov dx,offset id_port_name
- call print_number
- ret
-
- code ends
-
- end
-