home *** CD-ROM | disk | FTP | other *** search
- ; Packet driver for Novell's NE/2
- ; Written by:
- ; Eric Henderson
- ; Brigham Young University
- ;
- ; Based on the "generic" packet driver by Russell Nelson with help
- ; from the western digital pd by Russell Nelson.
- ; 80[123]86 processor support lifted from 3com driver by permission
- ; from Russell Nelson
- ;
- ; Portions (C) Copyright 1990 BYU
-
- version equ 5
-
- .286
- include defs.asm
-
- code segment byte public
- assume cs:code, ds:code
-
- ;*****************************************************************************
- ;
- ; NE/2 controller board offsets
- ; IO port definition (BASE in io_addr)
- ;*****************************************************************************
- ADDROM EQU 10h ; LAN Address ROM
- RACK EQU 10h ; NE2 Port Window
- NERESET EQU 20h ; Issue a read for reset
-
- ; 8390 LAN Controller (page0) register offset for read and write
- CMDR EQU 00h ; command register for read & write
- CLDA0 EQU 01h ; current local dma addr 0 for read
- PSTART EQU 01h ; page start register for write
- CLDA1 EQU 02h ; current local dma addr 1 for read
- PSTOP EQU 02h ; page stop register for write
- BNRY EQU 03h ; boundary reg for rd and wr
- TSR EQU 04h ; tx status reg for rd
- TPSR EQU 04h ; tx start page start reg for wr
- NCR EQU 05h ; number of collision reg for rd
- TBCR0 EQU 05h ; tx byte count 0 reg for wr
- FIFO EQU 06h ; FIFO for rd
- TBCR1 EQU 06h ; tx byte count 1 reg for wr
- ISR EQU 07h ; interrupt status reg for rd and wr
- CRDA0 EQU 08h ; current remote dma address 0 for rd
- RSAR0 EQU 08h ; remote start address reg 0 for wr
- CRDA1 EQU 09h ; current remote dma address 1 for rd
- RSAR1 EQU 09h ; remote start address reg 1 for wr
- RBCR0 EQU 0Ah ; remote byte count reg 0 for wr
- RBCR1 EQU 0Bh ; remote byte count reg 1 for wr
- RSR EQU 0Ch ; rx status reg for rd
- RCRWD EQU 0Ch ; rx configuration reg for wr
- CNTR0 EQU 0Dh ; tally cnt 0 for frm alg err for rd
- TCR EQU 0Dh ; tx configuration reg for wr
- CNTR1 EQU 0Eh ; tally cnt 1 for crc err for rd
- DCR EQU 0Eh ; data configuration reg for wr
- CNTR2 EQU 0Fh ; tally cnt 2 for missed pkt for rd
- IMR EQU 0Fh ; interrupt mask reg for wr
- ; 8390 LAN Controller (page1) register offset for read and write
- PAR0 EQU 01h ; physical addr reg 0 for rd and wr
- PAR1 EQU 02h ; physical addr reg 1 for rd and wr
- PAR2 EQU 03h ; physical addr reg 2 for rd and wr
- PAR3 EQU 04h ; physical addr reg 3 for rd and wr
- PAR4 EQU 05h ; physical addr reg 4 for rd and wr
- PAR5 EQU 06h ; physical addr reg 5 for rd and wr
- CURR EQU 07h ; current page reg for rd and wr
- MAR0 EQU 08h ; multicast addr reg 0 fro rd and WR
- MAR1 EQU 09h ; multicast addr reg 1 fro rd and WR
- MAR2 EQU 0Ah ; multicast addr reg 2 fro rd and WR
- MAR3 EQU 0Bh ; multicast addr reg 3 fro rd and WR
- MAR4 EQU 0Ch ; multicast addr reg 4 fro rd and WR
- MAR5 EQU 0Dh ; multicast addr reg 5 fro rd and WR
- MAR6 EQU 0Eh ; multicast addr reg 6 fro rd and WR
- MAR7 EQU 0Fh ; multicast addr reg 7 fro rd and WR
-
- ;***********************************************************************
- ;
- ; 8003 control register operations
- ;***********************************************************************
-
- MSK_RESET EQU 80h ; reset LAN controller
- MSK_ENASH EQU 40h ; enable PC access to shared mem
- MSK_DECOD EQU 3Fh ; ???? memory decode bits, corresponding
- ; to SA 18-13. SA 19 assumed to be 1
- ;***********************************************************************
- ;
- ; 8390 CMDR MASK
- ;***********************************************************************
-
- MSK_STP EQU 01h ; software reset, take 8390 off line
- MSK_STA EQU 02h ; activate the 8390 NIC
- MSK_TXP EQU 26h ; initial txing of a frm (With DMA)
- MSK_RD2 EQU 20h ; abort remote DMA
- MSK_PG0 EQU 00h ; select register page 0
- MSK_PG1 EQU 40h ; select register page 1
- MSK_PG2 EQU 80h ; select register page 2
- MSK_DMA_RD EQU 0ah ; start DMA read
- MSK_DMA_WR EQU 12h ; start DMA write
-
- ;***********************************************************************
- ;
- ; 8390 ISR & IMR MASK
- ;***********************************************************************
-
- MSK_PRX EQU 01h ; rx with no error
- MSK_PTX EQU 02h ; tx with no error
- MSK_RXE EQU 04h ; rx with error
- MSK_TXE EQU 08h ; tx with error
- MSK_OVW EQU 10h ; overwrite warning
- MSK_CNT EQU 20h ; MSB of one of the tally counters is set
- MSK_RDC EQU 40h ; remote dma completed
- MSK_RST EQU 80h ; reset state indicator
- MaskByte equ 0
- UnmaskByte equ 1fh
- InterruptMask equ 0fh
-
- ;***********************************************************************
- ;
- ; 8390 DCR MASK
- ;***********************************************************************
-
- MSK_WTS EQU 01h ; word transfer mode selection
- MSK_BOS EQU 02h ; byte order selection
- MSK_LAS EQU 04h ; long addr selection
- MSK_BMS EQU 08h ; burst mode selection
- MSK_ARM EQU 10h ; atuoinitialize remote
- MSK_FT00 EQU 00h ; burst lrngth selection
- MSK_FT01 EQU 20h ; burst lrngth selection
- MSK_FT10 EQU 40h ; burst lrngth selection
- MSK_FT11 EQU 60h ; burst lrngth selection
-
- ;***********************************************************************
- ;
- ; 8390 RCR MASK
- ;***********************************************************************
-
- MSK_SEP EQU 01h ; save error pkts
- MSK_AR EQU 02h ; accept runt pkt
- MSK_AB EQU 04h ; accept broadcast
- MSK_AM EQU 08h ; accept multicast
- MSK_PRO EQU 10h ; promiscuous physical
- ; accept all pkt with physical adr
- MSK_MON EQU 20h ; monitor mode
-
- ;***********************************************************************
- ;
- ; 8390 TCR MASK
- ;***********************************************************************
-
- MSK_CRC EQU 01h ; inhibit CRC, do not append crc
- MSK_LB01 EQU 06h ; encoded loopback control
- MSK_ATD EQU 08h ; auto tx disable
- MSK_OFST EQU 10h ; collision offset enable
-
- ;***********************************************************************
- ;
- ; 8390 RSR MASK
- ;***********************************************************************
-
- SMK_PRX EQU 01h ; rx without error
- SMK_CRC EQU 02h ; CRC error
- SMK_FAE EQU 04h ; frame alignment error
- SMK_FO EQU 08h ; FIFO overrun
- SMK_MPA EQU 10h ; missed pkt
- SMK_PHY EQU 20h ; physical/multicase address
- SMK_DIS EQU 40h ; receiver disable. set in monitor mode
- SMK_DEF EQU 80h ; deferring
-
- ;***********************************************************************
- ;
- ; 8390 TSR MASK
- ;***********************************************************************
-
- SMK_PTX EQU 01h ; tx without error
- SMK_DFR EQU 02h ; non deferred tx
- SMK_COL EQU 04h ; tx collided
- SMK_ABT EQU 08h ; tx aboort because of excessive collisions
- SMK_CRS EQU 10h ; carrier sense lost
- SMK_FU EQU 20h ; FIFO underrun
- SMK_CDH EQU 40h ; collision detect heartbeat
- SMK_OWC EQU 80h ; out of window collision
-
- ;***********************************************************************
- ;
- ; on board memory constant definition
- ;***********************************************************************
- ; for rcv buff ring of onboard mem
- START_PG EQU 46h ; start at page 46
- STOP_PG EQU 80h ; end at page 80
- ; for tx buff of shr mem
- TB_SIZE EQU 1 ; number of tb buff in shr mem
- TB_PGNO EQU 6 ; number of pages in one tb buff
-
- EIGHTBITSLOT db 0 ;8-bit machine flag
- Path dw ?
- RxPath dw ?
-
- public int_no, io_addr
- int_no db 3,0,0,0 ;must be four bytes long for get_number.
- io_addr dw 1000h,0 ; I/O address for card (jumpers)
- m_channel dw 0 ; micro channel flag
-
- rd_NE MACRO port
- mov DX, CS:io_addr
- add DX, port ; DX contains address of port
- in AL, DX ; AL contains data read from port
- ENDM
-
- wr_NE MACRO port
- mov DX, CS:io_addr
- add DX, port ; DX contains address of port
- out DX, AL ; AL contains data to be written to port
- ENDM
-
- ReceiveHeaderStructure struc
- RReceiveStatus db ?
- RNextBuffer db ?
- RByteCount dw ?
-
- RDestinationAddress db 6 dup(?)
- RSourceAddress db 6 dup(?)
- RPacketLength dw ?
- RChecksum dw ?
- RRPacketLength dw ?
- RTranControl db ?
- RHPacketType db ?
- RDestinationNet db 4 dup(?)
- RDestinationNode db 6 dup(?)
- RDestinationSocket dw ?
- ReceiveHeaderStructure ends
-
- ReceiveHeader ReceiveHeaderStructure <>
-
- Current equ InterruptStatus
- CurrentDMA0 equ RemoteStartAddress0
- CurrentDMA1 equ RemoteStartAddress1
- ForRSTBit equ 80h
-
- NIC struc
- Command db ?
- PageStart db ?
- PageStop db ?
- Boundry db ?
- TransmitStatus db ?
- TransmitByteCount0 db ?
- TransmitByteCount1 db ?
- InterruptStatus db ?
- RemoteStartAddress0 db ?
- RemoteStartAddress1 db ?
- RemoteByteCount0 db ?
- RemoteByteCount1 db ?
- ReceiveConfiguration db ?
- TransmitConfiguration db ?
- DataConfiguration db ?
- IntMask db ?
- DataPort db ?
- db 15 dup (?)
- Reset db ?
- NIC ends
-
- BLUEBOOK equ 1
- IEEE8023 equ 11
- public driver_class, driver_type, driver_name, driver_function, parameter_list
- driver_class db BLUEBOOK, IEEE8023, 0 ;from the packet spec
- driver_type dw 0ffffh ;Wild card matches any type
- driver_name db 'NE/2',0 ;name of the driver.
- driver_function db 2
- parameter_list label byte
- db 1 ;major rev of packet driver
- db 9 ;minor rev of packet driver
- 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
- dw 0 ;Interrupt # to hook for post-EOI
- ;processing, 0 == none,
-
- mcast_list_bits db 0,0,0,0,0,0,0,0 ;Bit mask from last set_multicast_list
- mcast_all_flag db 0 ;Non-zero if hware should have all
-
- public rcv_modes
- rcv_modes dw 7 ;number of receive modes in our table.
- dw 0 ;there is no mode 1.
- dw rcv_mode_1
- dw rcv_mode_2
- dw rcv_mode_3
- dw rcv_mode_4
- dw rcv_mode_5
- dw rcv_mode_6
- rxcr_bits db MSK_AB ; Default to ours plus multicast
-
-
- 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 ds:si -> packet, cx = packet length.
- ;exit with nc if ok, or else cy if error, dh set to error number.
- assume ds:nothing
- ; get txblk length
- inc cx
- and cl, 0feh
- cmp CX, RUNT
- jnb length_ok
- mov cx, RUNT
- length_ok:
- cmp cx, GIANT
- jbe length1_ok
- mov dh, NO_SPACE
- stc
- jmp count_out_err
- length1_ok:
- ;new stuff
- mov AX, CX
- wr_NE TBCR0 ; Transmit byte count
- mov al, ah
- wr_NE TBCR1
- mov al, 0
- wr_NE RSAR0
- mov al, 40h
- wr_NE RSAR1
- mov ax, cx
- wr_NE RBCR0 ; Remote byte count
- mov al, ah
- wr_NE RBCR1
-
- ; Clear out DMA complete interrupt
- mov al, MSK_PG0
- wr_NE CMDR
- mov al, 40h
- wr_NE ISR
-
- mov al, MSK_DMA_WR
- wr_NE CMDR
-
- mov DX, CS:io_addr
- add DX, RACK ; DX has address NE/2 Port window
-
- shr cx, 1
- rep outsw
-
- xor cx, cx ; Prevent infinite loop
- WaitForDMAComplete:
- rd_NE ISR
- test al, 40h
- jnz DMAComplete
- loop WaitForDMAComplete
-
- DMAComplete:
- mov al, MSK_TXP
- wr_NE CMDR
- clc
- exit_now:
- 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.
- ;This proc will set the first CX bytes of the ethernet address, leaving
- ; the rest unchanged.
- assume ds:nothing
-
- cmp cx, 6
- jbe set1
- mov dh, BAD_ADDRESS
- stc
- ret
- set1:
- mov al, 61h
- wr_NE CMDR
- mov DX, CS:io_addr
- add DX, PAR0 ; DX has address 8390 Phys Address Reg
- AddressToChip1:
- lodsb
- out dx, al
- inc dx
- in al,61h ;wait a little while...
- loop AddressToChip1
- pop di
- pop es
-
- mov al, 21h
- wr_NE CMDR
- clc
- ret
-
- ; Routines to set address filtering modes in the DS8390
- ; This was lifted from R. Clements' WD PD
- rcv_mode_1: ; Turn off receiver
- mov al, MSK_MON ; Set to monitor for counts but accept none
- jmp short rcv_mode_set
- rcv_mode_2: ; Receive only packets to this interface
- mov al, 0 ; Set for only our packets
- jmp short rcv_mode_set
- rcv_mode_3: ; Mode 2 plus broadcast packets (This is the default)
- mov al, MSK_AB ; Set four ours plus broadcasts
- jmp short rcv_mode_set
- rcv_mode_4: ; Mode 3 plus selected multicast packets
- mov al, MSK_AB+MSK_AM ; Ours, bcst, and filtered multicasts
- mov mcast_all_flag,0
- jmp short rcv_mode_set
- rcv_mode_5: ; Mode 3 plus ALL multicast packets
- mov al, MSK_AB+MSK_AM; Ours, bcst, and filtered multicasts
- mov mcast_all_flag,1
- jmp short rcv_mode_set
- rcv_mode_6: ; Receive all packets (Promiscuous physical plus all multi)
- mov al, MSK_AB+MSK_AM+MSK_PRO
- mov mcast_all_flag,1
- rcv_mode_set:
- push ax ; Hold mode until masks are right
- call set_8390_multi ; Set the multicast mask bits in chip
- pop ax
- WR_NE RCRWD
- mov rxcr_bits,al ; Save a copy of what we set it to
- 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
-
- ; Set the multicast filter mask bits in case promiscuous rcv wanted
- ; This was lifted from R. Clements' WD PD
- set_8390_multi:
-
- mov al,MSK_RD2+MSK_PG1
- WR_NE CMDR
- mov cx,8 ; Eight bytes of multicast filter
- mov si,offset mcast_list_bits ; Where bits are, if not all ones
- push cs
- pop ds
- cli ; Protect from irq changing page bits
-
- mov DX, CS:io_addr
- add DX, MAR0
- mov al,mcast_all_flag ; Want all ones or just selected bits?
- or al,al
- jz set_mcast_2 ; z = just selected ones
- mov al,0ffh ; Ones for filter
- set_mcast_all:
- out dx, al
- inc dl ; Step to next one
- jmp $+2 ; limit chip access rate
- loop set_mcast_all
- jmp short set_mcast_x
-
- set_mcast_2:
- lodsb ; Get a byte of mask bits
- out dx,al ; Write a mask byte
- inc dl ; Step to next I/O register
- jmp $+2 ; limit chip access rate
- loop set_mcast_2
- set_mcast_x:
- mov al, MSK_RD2+MSK_PG0
- WR_NE CMDR
- sti ; OK for interrupts now
- ret
-
-
- public terminate
- terminate:
- ret
-
-
- public reset_interface
- reset_interface:
- ;reset the interface.
- assume ds:code
- mov al, MSK_STP + MSK_RD2
- wr_NE CMDR
- mov al, 0ffh ; Clear all pending interrupts
- wr_NE ISR
- xor al, al ; Turn off all enables
- wr_NE IMR
- wr_NE NERESET ; Hard reset NE/2
- wr_NE NERESET
- wr_NE NERESET
- wr_NE NERESET
- wr_NE NERESET
- wr_NE NERESET
- wr_NE NERESET
- wr_NE NERESET
-
- rd_NE NERESET
-
- mov al, 21h
- wr_NE CMDR
- 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.
- ;It returns with es:di = 0 if don't want this type or if no buffer available.
- 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:
- ;called from the recv isr. All registers have been saved, and ds=cs.
- ;Actually, not just receive, but all interrupts come here.
- ;Upon exit, the interrupt will be acknowledged.
- assume ds:code
-
- ; read irq status register
- mov al, MaskByte
- wr_NE IMR
- sti
- rd_isr:
- rd_NE ISR ; read isr into AL
- and AL, 3Fh ; check bit0-bit5, if all 1's no irq
- cmp AL, 0 ; if any irq
- jne tst_ovw ; some irq
- cli
- mov al, UnmaskByte
- wr_NE IMR
- ret ; no more irq, exit
-
- ; process OVW (OVW = 1)
- ; may report error here
- tst_ovw:
- test AL, MSK_OVW ; if OVW irq
- jnz prcs_ov ; OVW (OVW = 1)
- jmp test_rx ; no OVW (OVW = 0)
-
- ; **************************************************************
- ; follow the DP8390 datasheet addendum to handle the buff ring overflow
- prcs_ov:
- ; 1. issue a STOP mode command
- mov AL, MSK_STP + MSK_RD2
- wr_NE CMDR
- ; 6. remove one packet from the ring
- rd_NE BNRY ; BNRY in AL
- add AL, 1 ; start page of frm in AL
- cmp AL, STOP_PG ; check boundary
- jne get1
- mov AL, START_PG
- ; ring not empty
- get1:
- mov BH, AL ; BX has the rx_frm pointer
- mov al, SIZE ReceiveHeader
- wr_NE RBCR0
- xor al, al
- wr_NE RBCR1
- wr_NE RSAR0
- mov al, bh
- wr_NE RSAR1
- mov al, MSK_DMA_RD
- wr_NE CMDR
-
- mov DX, CS:io_addr
- add DX, RACK ; DX has address NE/2 Port window
- mov di, OFFSET ReceiveHeader
- mov ax, cs
- mov es, ax
- mov cx, SIZE ReceiveHeader
- shr cx, 1
- Receive1:
- rep insw
-
- SkipReceive1:
- mov bx, offset ReceiveHeader
- mov AL, CS:[BX] ; AL has the status byte
- test AL, SMK_PRX ; if rx good
- jz fd_bnr ; rx error, drop frm by forward bnry
-
- ; good frm, call _rcv_frm
- call _rcv_frm
-
- fd_bnr: ;drop frm by forward BNRY
- mov al, cs:ReceiveHeader.RNextBuffer ; al = next pointer
- sub AL, 1 ; new BNRY in AL
- cmp AL, START_PG ; check boundary
- jae wrbnr ; unsigned arithmetic
- mov AL, STOP_PG - 1 ;
- ; dec AL ;
- wrbnr:
- wr_NE BNRY
- ; 2. clear the remote byte count registers (RBCR0,RBCR1)
- xor AL, AL
- wr_NE RBCR0
- wr_NE RBCR1
- ; 3. poll the ISR for the RST bit
- plisr:
- mov cx, 0ffffh
- rd_NE ISR
- test AL, MSK_RST
- jnz plisr_ok
- loop plisr ; keep polling until the RST bit set
- ; 4. place the NIC in loopback mode (mode 1 or 2) by writing 02 or 04 to TCR
- plisr_ok:
- mov AL, 02h ; put it in mode 2 (internal loopback)
- wr_NE TCR
- ; 5. issue start mode command
- mov AL, MSK_STA + MSK_RD2
- wr_NE CMDR
- ; 7. out from loopback mode by writing 00 to TCR
- xor AL, AL
- wr_NE TCR ; normal operation configuration
- ; clear OVW in ISR
- mov AL, MSK_OVW
- wr_NE ISR ; clear OVW
- call count_in_err ; increment overflow counter
- jmp rd_isr ; back to the top
-
-
- ; end of the modification
- ; *****************************************************
- ;
- ;process PRX and RXE
- ;
- test_rx:
- test AL, MSK_RXE
- jnz prcs_rxe ; RXE = 1
- test AL, MSK_PRX
- jnz prcs_rx ; PRX = 1
- jmp test_tx
-
- prcs_rxe:
- call count_in_err
- mov al, MSK_RXE
- wr_NE ISR
- jmp rd_isr
- prcs_rx:
- mov AL, MSK_PG1 + MSK_RD2 ; read CURR reg
- wr_NE CMDR
- rd_NE CURR
- mov BL, AL ; CURR in BL
- mov AL, MSK_PG0 + MSK_RD2 ; read BNRY reg
- wr_NE CMDR
- rd_NE BNRY ; BNRY in AL
- add AL, 1 ; start page of frm in AL
- cmp AL, STOP_PG ; check boundary
- jne go_cmp
- mov AL, START_PG ;
- go_cmp:
- cmp AL, BL
- jne Ring_Not_Empty
- jmp rd_isr ; buff ring empty
-
- Ring_Not_Empty:
- wr_NE RSAR1
- xor al, al
- wr_NE RBCR1
- wr_NE RSAR0
- mov al, SIZE ReceiveHeader
- wr_NE RBCR0
- mov al, MSK_DMA_RD
- wr_NE CMDR
-
- mov DX, CS:io_addr
- add DX, RACK ; DX has address NE/2 Port window
- mov di, OFFSET ReceiveHeader
- mov ax, cs
- mov es, ax
- mov cx, SIZE ReceiveHeader
- shr cx, 1
-
- Receive2:
- rep insw
-
- SkipReceive2:
- mov bx, offset ReceiveHeader
- mov AL, CS:[BX] ; AL has the status byte
- test AL, SMK_PRX ; if rx good
- jz fd_bnry ; rx error, drop frm by forward bnry
-
- ; good frm, call _rcv_frm
- call _rcv_frm
-
- fd_bnry: ; drop frm by forward BNRY
- mov al, CS:ReceiveHeader.RNextBuffer ; al = next pointer
- sub AL, 1 ; new BNRY in AL
- cmp AL, START_PG ; check boundary
- jae wrbnry ; unsigned arithmetic
- mov AL, STOP_PG - 1 ;
-
- wrbnry:
- wr_NE BNRY
- mov al, MSK_PRX
- wr_NE ISR
- jmp prcs_rx
-
- ;process PTX and TXE
- test_tx:
- test AL, MSK_PTX
- jnz prc_ptx ; PTX = 1
- test AL, MSK_TXE
- jnz prc_txe ; TXE = 1
- jmp test_cnt
-
-
- ; process tx good, update txok, lostcrs, collsn
- prc_ptx: ; tx good
- rd_NE TSR
- test AL, SMK_CRS ; is crs set in TSR
- jz nocrs ; no
- nocrs:
- rd_NE NCR ; read number of collision in AL
- mov AL, MSK_PTX
- wr_NE ISR ; clear PTX
- jmp rd_isr
-
- ; process tx error, update .txbad .underrun
- prc_txe: ; tx bad
- call count_out_err
- rd_NE TSR
- test AL, SMK_FU ; it fu set in TSR
- jz nofu ; no
- nofu:
- mov AL, MSK_TXE
- wr_NE ISR ; clear PTX
- jmp rd_isr
-
- ; process counter overflow, update .algerr .crcerr .???(missed pkt)
- test_cnt:
- test AL, MSK_CNT
- jnz prc_cnt ; yes, process cnt
- jmp rd_isr ; no CNT irq, back to the top
- ; process CNT
- prc_cnt:
- mov AL, MSK_CNT
- wr_NE ISR ; clear CNT
- jmp rd_isr ; back to the top
-
- ; End of RECV
-
- _rcv_frm:
-
- ; read byte count
- mov cx, cs:ReceiveHeader.RByteCount ; Extract size of frame
- cmp CX, 5dch
- jna rxlen_ok
- jmp rcv_ret
- rxlen_ok:
- sub CX, 4 ; 4 control bytes
- mov AX, cs
- mov ES, AX
- mov di, offset cs:ReceiveHeader.RPacketLength
- mov dl, BLUEBOOK ;default
- mov ax, es:[di]
- xchg ah, al
- cmp ax, 1500
- ja BlueBookPacket
- mov di, offset cs:ReceiveHeader.RChecksum
- mov dl, IEEE8023
- BlueBookPacket:
-
- push cx ; Save frame size
- push es
-
- mov ax, cs ; Set ds = code
- mov ds, ax
- assume ds:code
- call recv_find ; See if type and size are wanted
- ; CX = packet length
- ; ES:DI = packet type
- ; ES:DI = packet type
-
- pop ds ; RX page pointer in ds now
- assume ds:nothing
- pop cx
-
- cld ; Copies below are forward
- mov ax, es ; Did recv_find give us a null pointer?
- or ax, di ; ..
- je no_buff ; If null, don't copy the data
- has_buf:
-
- ;Tell DMA to copy the whole packet for us
- mov ax, 4
- wr_NE RSAR0 ; Don't copy 4 8390 control bytes
- mov ax, cx ; CX has byte count
- wr_NE RBCR0 ; LSB first
- mov al, ah
- wr_NE RBCR1 ; Now MSB
-
- mov al, MSK_DMA_RD ; Issue DMA read command
- wr_NE CMDR
-
- ; copy from NE/2 on board memory using the window RACK
- ; use IN and stosb to do the copy, IN -> AX -> ES:DI (CX has byte count)
-
- copynow:
- push cx ; We will want the count and pointer
- push es ; to hand to client after copying,
- push di ; so save them at this point
-
- mov DX, CS:io_addr
- add DX, RACK ; DX has address NE/2 Port window (?)
-
- mov si, cx
- shr cx, 1
- rep insw
- test si, 1
- jz call_rc
- in ax, dx
- stosb
- call_rc:
- pop si ; Recover pointer to destination
- pop ds ; Tell client it's his source
- pop cx ; And it's this long
- assume ds:nothing
- call recv_copy ; Give it to him
- jmp short rcv_ret
-
- ; no system buff availble to hold rx frm
- no_buff:
- rcv_ret:
- 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 after initialization. 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: NE2 [options] <packet_int_no>",CR,LF,'$'
-
- public copyright_msg
- copyright_msg db "Packet driver for NE/2 version "
- db '0'+(majver / 10),'0'+(majver mod 10),".",'0'+version,CR,LF
- db "Portions Copyright 1990, Eric Henderson, BYU",CR,LF,'$'
- int_no_name db "Interrupt number ",'$'
- io_addr_name db "I/O port ",'$'
- no_board_msg:
- db "NE/2 apparently not present at this IO address.",CR,LF,'$'
- HardwareFailure:
- db "The NE/2 is not responding.",CR,LF,'$'
-
- extrn set_recv_isr: near
-
-
- ;enter with si -> argument string, di -> word to store.
- ;if there is no number, don't change the number.
- ; extrn decout: near
- ; extrn hexout: near
-
- ;-> the assigned Ethernet address of the card.
- extrn rom_address: byte
-
- public parse_args
- print_args:
- mov dx,offset int_no_name
- mov ah,9
- int 21h
- mov di,offset int_no
- mov ax,[di] ;print the number in hex.
- mov dx,[di+2]
- ; call hexout
- mov dl,' '
- mov ah, 2
- int 21h
- mov dl,'('
- mov ah, 2
- int 21h
- mov ax,[di] ;print the number in decimal.
- mov dx,[di+2]
- ; call decout
- mov dl,')'
- mov ah, 2
- int 21h
- mov dl,CR
- mov ah, 2
- int 21h
- mov dl,LF
- mov ah, 2
- int 21h
- mov dx,offset io_addr_name
- mov ah,9
- int 21h
- mov di,offset io_addr
- mov ax,[di] ;print the number in hex.
- mov dx,[di+2]
- ; call hexout
- mov dl,' '
- mov ah, 2
- int 21h
- mov dl,'('
- mov ah, 2
- int 21h
- mov ax,[di] ;print the number in decimal.
- mov dx,[di+2]
- ; call decout
- mov dl,')'
- mov ah, 2
- int 21h
- mov dl,CR
- mov ah, 2
- int 21h
- mov dl,LF
- mov ah, 2
- int 21h
- parse_args:
- ret
-
- extrn etopen_diagn: byte
-
- BoardNotResponding:
- mov dx, offset HardwareFailure
- mov etopen_diagn, 35
- jmp short error_wrt
- bad_cksum:
- no_memory:
- mov dx,offset no_board_msg
- mov etopen_diagn,37
- error_wrt:
- stc
- ret
-
- SlotSelectRegister equ 96h
- POS0 equ 100h
- POS1 equ 101h
- POS2 equ 102h
- NE2ID equ 7154h
-
- IRQConfiguration label byte ;possible IRQ settings
- db 3
- db 4
- db 5
- db 9
-
- IOConfiguration label word ;possible I/O Base addresses
- dw 1000h
- dw 2020h
- dw 8020h
- dw 0A0A0h
- dw 0B0B0h
- dw 0C0C0h
- dw 0C3D0h
-
- public etopen
- etopen:
- ;if all is okay,
- cli ;Find the NE/2 NIC
- mov cl, 7 ; channel position (8=1st slot
- ; F=8th slot)
- NextSlot:
- inc cl
- cmp cl,10h ;check 8 I/O slots
- jne NoHardwareFailure
- jmp BoardNotResponding
- NoHardwareFailure:
- mov al, cl
- out SlotSelectRegister, al ;select card slot
- mov dx, POS1
- in al, dx ;check for NE2 ID
- mov ah, al
- mov dx, POS0
- in al, dx
- cmp ax, NE2ID
- jne NextSlot
-
- mov dx, POS2 ;read configuration port
- in al, dx
-
- test al, 01 ;test to see if card enable
- jz NextSlot ; bit is set
-
- mov bl, al
- and bx, 000Eh ;mask all but I/O base addr.
-
- jz NextSlot ;check next slot if no option
- ; setting in POS 2
- dec bx
- dec bx
- mov dx, IOConfiguration[bx] ; IO address
- mov io_addr, dx ;save the base I/O address
-
- test al, 10h ;if boot prom enabled then
-
- SetIRQ:
- shr al, 5 ;load the hardware config.
- and ax, 3 ; table with the IRQ line
- mov bx, ax ; value and string
- mov dl, IRQConfiguration[bx]
- mov int_no, dl ;save interrupt level
- ; call print_args
-
- call set_recv_isr ; Put ourselves in interrupt chain
-
- ; reset NE/2 board
- cli
- wr_NE NERESET
- wr_NE NERESET
- wr_NE NERESET
- wr_NE NERESET
- wr_NE NERESET
- wr_NE NERESET
- wr_NE NERESET
- wr_NE NERESET
-
- rd_NE NERESET
-
- mov al, 21h
- wr_NE CMDR
-
- ; Test to see if we're OK
- rd_NE CMDR
- cmp al, 21h
- je WeBeOK
- jmp BoardNotResponding
-
- WeBeOK:
- mov al, 49h ;Word mode
- wr_NE DCR
- mov al, 0
- wr_NE RBCR0
- wr_NE RBCR1
- mov al, 4
- wr_NE RCRWD
- mov al, 02
- wr_NE TCR
- mov al, START_PG
- wr_NE PSTART
- wr_NE BNRY
- mov al, STOP_PG
- wr_NE PSTOP
-
- mov al, 0ffh
- wr_NE ISR
- mov al, 01fh
- wr_NE IMR
-
- mov al, 61h
- wr_NE CMDR
- mov al, START_PG + 1
- wr_NE CURR
- mov al, 21h
- wr_NE CMDR
-
-
-
- mov DX, CS:io_addr
- add DX, RACK ; DX has address NE/2 Port window
-
- mov bx, -1 ;setup for Nic's memory test
-
- mov bp, CS:io_addr
- call RAMTest ;16 bit memory test
-
- jz memory_OK ;if error, report it
- jmp no_memory
-
- memory_OK:
- ; set up rom_address from addr ROM.
- mov al, 12 ;read 6 bytes from PROM (word mode=12)
- wr_NE RBCR0
- mov al, 0
- wr_NE RBCR1
- wr_NE RSAR0
- wr_NE RSAR1
- mov al, MSK_DMA_RD
- wr_NE CMDR
-
- mov DX, CS:io_addr
- add DX, RACK ; DX has address NE/2 Port window (?)
- mov di, OFFSET rom_address
- mov ax, cs
- mov es, ax
- mov cx, 6
- GetEnetAddress:
- in al, dx
- stosb
- loop GetEnetAddress
-
- ModeCheckDone:
- mov ax, cs
- mov ds, ax
- mov si, OFFSET rom_address
- mov cx, 6
- call set_address
-
- mov al, 21h
- wr_NE CMDR
-
- SetTXPage:
- mov al,0C0h ;C000h is used as TX
- wr_NE TPSR ;page because of
- ;spurious writes to
- ;Ram during transmits
- ;when collisions occur
- mov al, 22h
- jmp $+2
- wr_NE CMDR
-
- mov al, 0
- wr_NE TCR
-
- mov al,0 ;deselect all I/O channels
- out SlotSelectRegister,al
-
- sti
- clc
- ret
-
- ;**********************************************************************
- ;
- ; RAM Test
- ;
- ; assumes:
- ; BX has the test value
- ; BP points to IOBase
- ; NIC (8390) has been set to ignore activity on wire
- ; (loopback mode) and is set to page 0
- ;
- ; returns:
- ; Z flag set if no error
- ; BP preserved.
- ; NIC set to page 0
- ;
- ;**********************************************************************
-
- RAMTest proc near
-
- lea dx, [bp].RemoteStartAddress0 ;point at start of RAM
- xor al, al
- out dx, al
- inc dx
- mov al, 40h
- out dx, al
-
- inc dx ;set byte count=16k
- xor al, al ; (both 8k RAM chips)
- out dx, al
- inc dx
- mov al, 40h
- out dx, al
-
- lea dx, [bp].Command ;write in all RAM locations
- mov al, MSK_DMA_WR ; what we send
- out dx, al
-
- lea dx, [bp].DataPort ;point at Nic's data port
-
- mov cx, 2000h ;set count to 8k words
-
- mov ax, bx ;read in test value
-
- WriteLoop:
- inc ax ;adjust test pattern
- out dx, ax ;send it out to Nic
- loop WriteLoop
-
- ;now read back and compare
- ; test pattern from NIC
-
- lea dx, [bp].RemoteStartAddress0 ;point at start of RAM
- xor al, al
- out dx, al
- inc dx
- mov al, 40h
- out dx, al
-
- inc dx ;set byte count = 16k
- xor al, al
- out dx, al
- inc dx
- mov al, 40h
- out dx, al
-
- lea dx, [bp].Command ;tell NIC to send back test
- mov al, MSK_DMA_RD ; pattern
- out dx, al
-
- lea dx, [bp].DataPort ;point at Nic's data port
-
- mov cx, 2000h ;setup loop
-
- ReadLoop:
- in ax, dx ;read in test pattern and
- inc bx ; compare with original
- cmp bx, ax
-
- loopz ReadLoop
-
- ret ;zero flag set if memory error
-
- RAMTest endp
-
- public print_parameters
- print_parameters:
- ;echo our command-line parameters
- ret
-
-
- code ends
-
- end
-