home *** CD-ROM | disk | FTP | other *** search
- PAGE ,132
- .286c
- version equ 1
-
- include defs.asm ;SEE ENCLOSED COPYRIGHT MESSAGE
-
- ;/* PC/FTP Packet Driver source, conforming to version 1.09 of the spec
- ;* Portions (C) Copyright 1990 D-Link, Inc.
- ;*
- ;* Permission is granted to any individual or institution to use, copy,
- ;* modify, or redistribute this software and its documentation provided
- ;* this notice and the copyright notices are retained. This software may
- ;* not be distributed for profit, either in original form or in derivative
- ;* works. D-Link, inc. makes no representations about the suitability
- ;* of this software for any purpose. D-LINK GIVES NO WARRANTY,
- ;* EITHER EXPRESS OR IMPLIED, FOR THE PROGRAM AND/OR DOCUMENTATION
- ;* PROVIDED, INCLUDING, WITHOUT LIMITATION, WARRANTY OF MERCHANTABILITY
- ;* AND WARRANTY OF FITNESS FOR A PARTICULAR PURPOSE.
- ;*/
-
- BIT0 EQU 01H
- BIT1 EQU 02H
- BIT2 EQU 04H
- BIT3 EQU 08H
- BIT4 EQU 10H
- BIT5 EQU 20H
- BIT6 EQU 40H
- BIT7 EQU 80H
-
- code segment byte public
- assume cs:code, ds:code
-
- ; DE-600's I/O port Table
- DAT equ 0
- STAT equ 1
- CMD equ 2
-
- ; DE-600's DATA port Command
- WRITE equ 0004h ;write memory
- READ equ 0104h ;read memory
- STATUS equ 0204h ;read status register
- COMMAND equ 0304h ;write command register
- NUL_CMD equ 0ch ;null command
- RX_LEN equ 0504h ;read Rx packet length
- TX_ADR equ 0604h ;write Tx address
- RW_ADR equ 0704h ;write memory address
-
- ;< COMMAND bits 7-0 >
- RXEN equ 08h ; bit 3
- TXEN equ 04h ; bit 2
- LOOPBACK equ 0Ch ; RXEN=1, TXEN=1
- RX_NONE equ 00h ; M1=0, M0=0 (bit 1,0)
- RX_ALL equ 01h ; M1=0, M0=1
- RX_BP equ 02h ; M1=1, M0=0
- RX_MBP equ 03h ; M1=1, M0=1
- RESET equ 80h ; set bit 7 high
- STOP_RESET equ 00h ; set bit 7 low
- ; bit 6 -- IRQ inverse
- ; bit 5,4 -- Rx Page Number ( RA12=1, RA11=0 or 1 )
-
- ;< TX_ADR bit 7, bit 4 >
- ; bit 7 -- Tx Page Number ( TA11=0 or 1 )
- ; bit 4 -- Tx Page Number ( TA12=0 )
- PAGE0 equ 00h
- PAGE1 equ 08h
- PAGE2 equ 10h
- PAGE3 equ 18h
-
- ;< RW_ADR bit 7, bit 5,4 >
- ; bit 7 -- RW Page Number ( H11 =? )
- ; bit 4 -- RW Page Number ( H12 =? )
- ; bit 5 -- Address Maping ( HA13=0 => Memory, HA13=1 => Node Number )
- HA13 equ 020h
-
- ; DE-600's CMD port Command
- SLT_NIC equ 004h ;select Network Interface Card
- SLT_PRN equ 01Ch ;select Printer
- NML_PRN equ 0ECh ;normal Printer situation
- IRQEN equ 010h ;enable IRQ line
-
- ; DE-600's STAT port bits 7-4
- RXBUSY equ 80h
- GOOD equ 40h
- RESET_FLAG equ 20h
- T16 equ 10h
- TXBUSY equ 08h
-
- BFRSIZ equ 2048 ;number of bytes in a buffer
- PRNTABADD equ 408h ;DOS printer table address
- RX_MIN_LEN equ 18 ;= EADDR_LEN + EADDR_LEN + TYPE_LEN + CRC
-
- write_sub_delay macro reg
- mov al,reg ;output the low nibble.
- shl al,cl ;cl must be four.
- or al,ch
- xor al,08h ;raise the write line.
- out dx,al
- call delay
-
- xor al,08h ;lower the write line
- out dx,al
- call delay
-
- mov al,reg ;output the high nibble.
- and al,not 0fh ;get us some zero bits.
- or al,ch
- out dx,al ;(write line is low).
- call delay
-
- xor al,08h ;raise the write line.
- out dx,al
- endm
-
- write_sub_fast macro reg
- mov al,reg ;output the low nibble.
- shl al,cl ;cl must be four.
- or al,ch
- out dx,al
-
- mov al,reg ;output the high nibble.
- and al,not 0fh ;get us some zero bits.
- or al,ch
- xor al,08h ;raise the write line.
- out dx,al ;(write line is low).
- endm
-
- write_sub_slow macro reg
- mov al,reg ;output the low nibble.
- shl al,cl ;cl must be four.
- or al,ch
- out dx,al
- call delay
-
- mov al,reg ;output the high nibble.
- and al,not 0fh ;get us some zero bits.
- or al,ch
- xor al,08h ;raise the write line.
- out dx,al ;(write line is low).
- endm
-
- read_sub_fast macro reg
- setport DAT
- mov al,ch
- out dx,al
- pause
-
- setport STAT
- in al,dx
- mov reg,al
- setport DAT
- mov al,ch
- xor al,08h
- out dx,al
- pause
-
- setport STAT
- in al,dx
- shr reg,cl
- and al,0f0h
- or reg,al
- endm
-
-
- read_sub_slow macro reg
- setport DAT
- mov al,ch
- out dx,al
- call delay
-
- setport STAT
- in al,dx
- mov reg,al
- setport DAT
- mov al,ch
- xor al,08h
- out dx,al
- call delay
-
- setport STAT
- in al,dx
- shr reg,cl
- and al,0f0h
- or reg,al
- endm
-
-
- read_sub_delay macro reg, first
- setport DAT
- mov al,ch
- if first
- xor al,08h
- endif
- out dx,al
- call delay
-
- if first
- xor al,08h
- out dx,al
- call delay
- endif
-
- setport STAT
- in al,dx
- mov reg,al
- setport DAT
- mov al,ch
- xor al,08h
- out dx,al
- call delay
-
- setport STAT
- in al,dx
- shr reg,cl
- and al,0f0h
- or reg,al
- endm
-
-
- pause macro
- jmp $+2
- endm
-
- public int_no
- int_no db 7,0,0,0 ; IRQ interrupt number
- io_addr dw 03bch,0 ; I/O address for card (jumpers)
-
- public driver_class, driver_type, driver_name, driver_function, parameter_list
- driver_class db BLUEBOOK, IEEE8023, 0 ;from the packet spec
- driver_type db 31 ;from the packet spec
- driver_name db 'DE600',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
- 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 0
- dw rcv_mode_3
- dw 0
- dw rcv_mode_5
- dw rcv_mode_6
-
- CurTxPage db 08h ;the BL value when OUT DATA,TX_ADR
- CurRxPage db 20h ;the BL value when OUT DATA,COMMAND
- TxStartAdd dw ?
- RxStartAdd dw ?
- InitRxTxReg dw ?
- RxPktLen dw ?
- TxPktLen dw ?
- Mode_RxPg db ?
- Mode db RX_BP
- IRQinverse db 0 ; = 40h for XT printer adapter
- NICstatus db 0
- In_ISR db 0
- In_Tx db 0
- printer dw 408h
- PS2 db 0
-
- our_type dw ?,?
-
-
- 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
- cmp cx,GIANT ; Is this packet too large?
- ja send_pkt_toobig
-
- ;select DE-600
- mov al,SLT_NIC
- ;*** CMD sub ***
- loadport
- setport CMD
- out dx,al
- ;*** End CMD sub ***
- mov In_Tx,1
- call delay
-
- cmp cx,RUNT ; minimum length for Ether
- jae LengthOK
- mov cx,RUNT ; make sure size at least RUNT
- LengthOK:
- inc cx
- and cx,not 1
-
- mov di,cx
- ;change Tx page to another free buffer
- xor CurTxPage,08h
-
- mov bx,offset send_pkt_pointer
- jmp cs:[bx]
-
- send_pkt_toobig:
- mov dh,NO_SPACE
- stc
- ret
-
- send_pkt_pointer dw offset send_pkt0
-
- send_pkt0:
- ;set Tx Pointer for moving packet
- mov ax,BFRSIZ
- sub ax,cx ;AX = the pointer to TX
- or ah,CurTxPage
- mov TxStartAdd,ax ;save Current Tx Packet Start Address
- mov bx,ax ;write memory address
- mov cx,RW_ADR
- setport DAT
- write_sub_fast bl
- write_sub_fast bh
- cld
- mov cx,WRITE ;write packet into memory
- mov ah,ch
- xor ah,08h
- write_mem:
- lodsb
- mov bl,al
- shl al,cl
- or al,ch
- out dx,al
-
- mov al,bl
- and al,0f0h
- or al,ah
- dec di
- out dx,al
- jnz write_mem
-
- mov cx,4000h
- setport STAT
- wait_Tx_idle:
- in al,dx
- test al,TXBUSY ; Is the previous Tx successful ?
- jz command_to_Tx ; Yes, TXBUSY is low. Then could Tx next packet.
- loop wait_Tx_idle
-
- command_to_Tx:
- ;set Tx Pointer at beginning of packet
- mov bx,TxStartAdd
- mov cx,TX_ADR
- loadport
- setport DAT
- write_sub_fast bl
- write_sub_fast bh
-
- ;Enable interrupt and start Tx
- mov bl,Mode_RxPg
- mov cx,COMMAND
- write_sub_fast bl
- or bl,TXEN
- write_sub_fast bl
-
- Exit_Send_Packet:
- mov In_Tx,0
-
- cmp In_ISR,0
- jne using_NIC_now
- mov al,SLT_PRN
- loadport
- setport CMD
- out dx,al
-
- cmp PS2,0
- jnz using_NIC_now
- setport STAT
- in al,dx
- and al,40h
- xor al,IRQinverse
- jz using_NIC_now
- call trigger_int
- using_NIC_now:
- clc
- ret
-
-
- send_pkt1:
- ;set Tx Pointer for moving packet
- mov ax,BFRSIZ
- sub ax,cx ;AX = the pointer to TX
- or ah,CurTxPage
- mov TxStartAdd,ax ;save Current Tx Packet Start Address
- mov bx,ax ;write memory address
- mov cx,RW_ADR
- loadport
- setport DAT
- write_sub_slow bl
- call delay
- write_sub_slow bh
-
- cld
- mov cx,WRITE ;write packet into memory
- mov ah,ch
- xor ah,08h
- write_mem1:
- lodsb
- mov bl,al
- shl al,cl
- or al,ch
- out dx,al
- call delay
-
- mov al,bl
- and al,0f0h
- or al,ah
- dec di
- out dx,al
- call delay
- jnz write_mem1
-
- mov cx,4000h
- setport STAT
- wait_Tx_idle1:
- in al,dx
- test al,TXBUSY ; Is the previous Tx successful ?
- jz command_to_Tx1 ; Yes, TXBUSY is low. Then could Tx next packet.
- loop wait_Tx_idle1
-
- command_to_Tx1:
- ;set Tx Pointer at beginning of packet
- mov bx,TxStartAdd
- mov cx,TX_ADR
- loadport
- setport DAT
- write_sub_slow bl
- call delay
- write_sub_slow bh
- call delay
-
- ;Enable interrupt and start Tx
- mov bl,Mode_RxPg
- mov cx,COMMAND
- write_sub_slow bl
- call delay
- or bl,TXEN
- write_sub_slow bl
- jmp Exit_Send_Packet
-
-
- send_pkt2:
- ;set Tx Pointer for moving packet
- mov ax,BFRSIZ
- sub ax,cx ;AX = the pointer to TX
- or ah,CurTxPage
- mov TxStartAdd,ax ;save Current Tx Packet Start Address
- mov bx,ax ;write memory address
- mov cx,RW_ADR
- loadport
- setport DAT
- write_sub_delay bl
- call delay
- write_sub_delay bh
- cld
- mov cx,WRITE ;write packet into memory
- write_mem2:
- lodsb
- mov bl,al ;except for this line,
- shl al,cl ; it's write_sub_delay
- or al,ch
- xor al,08h
- out dx,al
- call delay
-
- xor al,08h
- out dx,al
- call delay
-
- mov al,bl
- and al,0f0h
- or al,ch
- out dx,al
- call delay
-
- xor al,08h
- out dx,al
- call delay
- dec di
- jnz write_mem2
-
- mov cx,4000h
- setport STAT
- wait_Tx_idle2:
- in al,dx
- test al,TXBUSY ; Is the previous Tx successful ?
- jz command_to_Tx2 ; Yes, TXBUSY is low. Then could Tx next packet.
- loop wait_Tx_idle2
-
- command_to_Tx2:
- ;set Tx Pointer at beginning of packet
- mov bx,TxStartAdd
- mov cx,TX_ADR
- loadport
- setport DAT
- write_sub_delay bl
- call delay
- write_sub_delay bh
- call delay
-
- ;Enable interrupt and start Tx
- mov bl,Mode_RxPg
- mov cx,COMMAND
- write_sub_delay bl
- call delay
- or bl,TXEN
- write_sub_delay bl
- jmp Exit_Send_Packet
-
-
- trigger_int:
- mov al,SLT_NIC
- call CMD_sub
-
- mov bl,Mode_RxPg
- xor bl,BIT6
- mov cx,COMMAND
- call Write_sub
-
- mov al,SLT_PRN
- call CMD_sub
-
- call delay
- call delay
-
- mov al,SLT_NIC
- call CMD_sub
-
- mov bl,Mode_RxPg
- mov cx,COMMAND
- call Write_sub
- ret
-
-
- rcv_mode_1:
- mov cl,RX_NONE
- jmp short set_RXCR
- rcv_mode_3:
- mov cl,RX_BP
- jmp short set_RxCR
- rcv_mode_5:
- mov cl,RX_MBP
- jmp short set_RxCR
- rcv_mode_6:
- mov cl,RX_ALL
- set_RxCR:
- mov Mode,cl
- mov bl,cl
- or bl,CurRxPage ; Add original Rx Page
- mov Mode_RxPg,bl ; Save Rx Mode & Rx Page
- ;select DE-600
- loadport
- setport CMD
- in al,dx
- pause
- test al,BIT4
- jz in_IC_mode
- ;not active, we have to put a wrapper around it.
- mov al,int_no
- call maskint
-
- mov al,SLT_NIC ;turn on the NIC.
- call CMD_sub
- call in_IC_mode ;now we're in the right mode.
- mov al,SLT_PRN ;turn on the PRN.
- call CMD_sub
-
- mov al,int_no
- call unmaskint
- ret
-
- in_IC_mode:
- mov cx,COMMAND ; Set new Rx Mode
- call Write_sub
- ret
-
-
- extrn maskint : near
- extrn unmaskint : near
-
- public set_address
- set_address:
- ;Set Ethernet address on controller
- ;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 ;make sure that we have enough room.
- je can_set_address
- mov dh,BAD_ADDRESS
- stc
- jmp set_address_none
-
- ;select DE-600
- can_set_address:
- loadport
- setport CMD
- in al,dx
- push ax
- test al,BIT4
- jz IC_mode
-
- mov al,int_no
- call maskint
- mov al,SLT_NIC
- call CMD_sub
- IC_mode:
- mov cx,RW_ADR
- xor bl,bl
- call Write_sub
- or bl,HA13
- call Write_sub
-
- cld
- mov bp,cs
- mov es,bp
-
- mov di,EADDR_LEN
- mov cx,WRITE
- set_our_address:
- lodsb
- mov bl,al
- call Write_sub
- dec di
- jnz set_our_address
-
- pop ax
- test al,BIT4
- jz IC_mode1
-
- mov al,SLT_PRN
- call CMD_sub
- mov al,int_no
- call unmaskint
- IC_mode1:
- clc
- set_address_none:
- push cs
- pop ds
- assume ds:code
- 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:
- ret
-
-
- public reset_interface
- reset_interface:
- mov al,int_no
- call maskint
- ;select DE-600
-
- mov al,SLT_NIC
- call CMD_sub
-
- ; Pulse IE_RESET
- mov bl,RESET
- mov cx,COMMAND
- call Write_sub
- mov bl,STOP_RESET
- call Write_sub
-
- ; Initialize Rx buffer pointer, and start receive
- mov bl,Mode_RxPg
- mov cx,COMMAND
- call Write_sub
- or bl,RXEN
- call Write_sub
-
- ; Enable Printer Adapter IRQ line
- mov al,SLT_PRN
- call CMD_sub
-
- mov al,int_no
- call unmaskint
- ret
-
-
- assume ds:nothing
- Write_sub:
- loadport
- setport DAT
- write_sub_delay bl
- ret
-
- Read_sub:
- loadport
- setport DAT
- mov al,ch
- xor al,08h
- out dx,al
- call delay
-
- xor al,08h
- out dx,al
- call delay
-
- setport STAT
- in al,dx
- mov bl,al
- test ch,BIT1
- jz not_READ_STATUS
- dec dx
- mov al,NUL_CMD
- xor al,08h
- out dx,al
- call delay
-
- xor al,08h
- out dx,al
- jmp short End_read
- not_READ_STATUS:
- setport DAT
- mov al,ch
- xor al,08h
- out dx,al
- call delay
-
- setport STAT
- in al,dx
- shr bl,cl
- and al,0f0h
- or bl,al
- End_read:
- ret
-
- CMD_sub:
- loadport
- setport CMD
- out dx,al
- ret
-
- delay:
- nop ; pointer 0
- nop ; 1
- nop ; 2
- nop ; 3
- nop ; 4
- nop ; 5
- nop ; 6
- nop ; 7
- nop ; 8
- nop ; 9
- 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
-
- extrn count_in_err: near
- extrn count_out_err: near
-
- recv_pointer dw offset recv0
-
- public recv
- recv:
- ;called from the recv isr. All registers have been saved, and ds=cs.
- ;Upon exit, the interrupt will be acknowledged.
- assume ds:code
- ;select DE-600
- mov al,SLT_NIC
- ;*** CMD sub ***
- loadport
- setport CMD
- out dx,al
- ;*** End CMD sub ***
- ;set watch dog
- mov In_ISR,1
- call delay
-
- ;Check the interrupt source, Rx or Tx ?
- mov cx,STATUS ; Read NIC Status Register
- ;*** Read sub ***
- setport DAT
- mov al,ch
- out dx,al
- pause
- setport STAT
- in al,dx
- ;*** End Read sub ***
-
- jmp recv_pointer
-
- recv0:
- mov NICstatus,al ; save NIC status
- setport DAT
- test al,GOOD ; Is Rx generating interrupt ?
- mov al,NUL_CMD
- out dx,al
- jnz Rx_Good_Pkt ; Yes, take care of this situation.
- mov al,NICstatus
- test al,RXBUSY
- jz Enable_Rx
- jmp CheckTx
-
- Enable_Rx:
- ;change Rx page & enable NIC to Rx
- mov bl,Mode_RxPg
- mov cx,COMMAND
- setport DAT
- write_sub_fast bl
- or bl,RXEN
- write_sub_fast bl
- jmp CheckTx
-
- Rx_Good_Pkt:
- ;Put it on the receive queue
- mov cx,RX_LEN ; read Rx Packet Length
- loadport
- read_sub_fast bl
- read_sub_fast bh
-
- sub bx,4 ;subtrate 4 CRC Byte Count
- mov RxPktLen,bx ;save Rx Packet Length
-
- ;change Rx page & enable NIC to Rx
- xor Mode_RxPg,10h
- mov bl,Mode_RxPg
- mov cx,COMMAND
- setport DAT
- write_sub_fast bl
- or bl,RXEN
- write_sub_fast bl
- xor bx,bx
- mov bh,CurRxPage ;BL = Current Rx Page
- xor CurRxPage,10h ;change to next page for Rx
- shr bx,1 ;shift BX to real memory address
- mov RxStartAdd,bx ;save just Rx Packet Start Address
-
- add bx,EADDR_LEN+EADDR_LEN ;seek to the TYPE word
- mov cx,RW_ADR
- write_sub_fast bl
- write_sub_fast bh
- pause
- mov cx,READ ;read the TYPE word
- read_sub_fast bl
- read_sub_fast bh
-
- mov our_type,bx ;save the TYPE word
-
- mov cx,READ ;read the TYPE word
- read_sub_fast bl
- read_sub_fast bh
-
- mov our_type[2],bx ;save the TYPE word
-
- mov ax,ds
- mov es,ax
- mov di,offset our_type
- mov cx,RxPktLen
-
- 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 ;request a Rx buffer to store Rx data
-
- mov ax,es ;is this pointer null?
- or ax,di
- jnz find_buffer
- jmp short CheckTx ;yes - just free the frame.
- find_buffer:
- push es
- push di ;remember where the buffer pointer is.
- assume ds:nothing
- mov bx,RxStartAdd
- mov cx,RW_ADR
- loadport
- setport DAT
- write_sub_fast bl
- write_sub_fast bh
-
- cld
- mov bp,RxPktLen ;CX = the byte count of Rx Packet
- setport STAT
- mov cx,READ
- mov ah,ch
- xor ah,08h
- read_mem:
- setport DAT
- mov al,ch ;output our read request.
- out dx,al
- pause
-
- setport STAT
- in al,dx ;input four bits into bl.
- mov bl,al
- setport DAT ;now output the inverse read request.
- mov al,ah
- out dx,al
- pause
-
- setport STAT
- in al,dx ;input the high four bits.
- shr bl,cl
- and al,0f0h
- or al,bl ;combine the two nibbles.
- stosb
- dec bp
- jnz read_mem
-
- RxCopy_CheckTx:
- pop si
- pop ds
- mov cx,RxPktLen
-
- call recv_copy ;tell them that we copied it.
-
- mov ax,cs ;restore our ds.
- mov ds,ax
- assume ds:code
-
- CheckTx:
- test NICstatus,T16 ; Is pending a Tx Packet ?
- jz return ; No, then return.
- ; Yes, send this packet.
- ;set Tx Pointer at beginning of packet
- mov bx,TxStartAdd
- mov cx,TX_ADR
- call Write_sub
- xchg bh,bl
- call Write_sub
-
- ;Enable interrupt and start Tx
- mov bl,Mode_RxPg
- mov cx,COMMAND
- call Write_sub
- or bl,TXEN
- call Write_sub
- return:
- mov al,SLT_PRN
- ;*** CMD sub ***
- loadport
- setport CMD
- out dx,al
- ;*** End CMD sub ***
-
- cmp PS2,0
- jnz Rx_another_pkt
- setport STAT
- in al,dx
- and al,40h
- xor al,IRQinverse
- jz Rx_another_pkt
- call trigger_int
- Rx_another_pkt:
- mov In_ISR,0
- ret
-
-
- recv1:
- assume ds:code
- mov NICstatus,al ; save NIC status
- loadport
- setport DAT
- test al,GOOD ; Is Rx generating interrupt ?
- mov al,NUL_CMD
- out dx,al
- jnz Rx_Good_Pkt1 ; Yes, take care of this situation.
- mov al,NICstatus
- test al,RXBUSY
- jz Enable_Rx1
- jmp CheckTx ; No, go to check Tx.
-
- Enable_Rx1:
- ;change Rx page & enable NIC to Rx
- mov bl,Mode_RxPg
- mov cx,COMMAND
- setport DAT
- write_sub_slow bl
- call delay
- or bl,RXEN
- write_sub_slow bl
- jmp CheckTx
-
- Rx_Good_Pkt1:
- ;Put it on the receive queue
- mov cx,RX_LEN ; read Rx Packet Length
- loadport
- read_sub_slow bl
- read_sub_slow bh
-
- sub bx,4 ;subtrate 4 CRC Byte Count
- mov RxPktLen,bx ;save Rx Packet Length
-
- ;change Rx page & enable NIC to Rx
- xor Mode_RxPg,10h
- mov bl,Mode_RxPg
- mov cx,COMMAND
- setport DAT
- write_sub_slow bl
- call delay
- or bl,RXEN
- write_sub_slow bl
- call delay
- xor bx,bx
- mov bh,CurRxPage ;BL = Current Rx Page
- xor CurRxPage,10h ;change to next page for Rx
- shr bx,1 ;shift BX to real memory address
- mov RxStartAdd,bx ;save just Rx Packet Start Address
-
- add bx,EADDR_LEN+EADDR_LEN ;seek to the TYPE word
- mov cx,RW_ADR
- write_sub_slow bl
- call delay
- write_sub_slow bh
- call delay
- mov cx,READ ;read the TYPE word
-
- read_sub_slow bl
- read_sub_slow bh
-
- mov our_type,bx ;save the TYPE word
-
- mov ax,ds
- mov es,ax
- mov di,offset our_type
- mov cx,RxPktLen
-
- call recv_find ;request a Rx buffer to store Rx data
-
- mov ax,es ;is this pointer null?
- or ax,di
- jnz find_buffer1
- jmp CheckTx ;yes - just free the frame.
- find_buffer1:
- push es
- push di ;remember where the buffer pointer is.
- assume ds:nothing
- mov bx,RxStartAdd
- mov cx,RW_ADR
- loadport
- setport DAT
- write_sub_slow bl
- call delay
- write_sub_slow bh
- call delay
-
- cld
- mov bp,RxPktLen ;CX = the byte count of Rx Packet
- setport STAT
- mov cx,READ
- mov ah,ch
- xor ah,08h
- read_mem1:
- dec dx
- mov al,ch
- out dx,al
- call delay
-
- inc dx
- in al,dx
- mov bl,al
- dec dx
- mov al,ah
- out dx,al
- call delay
-
- inc dx
- in al,dx
- shr bl,cl
- and al,0f0h
- or al,bl
- stosb
- dec bp
- jnz read_mem1
- jmp RxCopy_CheckTx
-
-
- recv2:
- assume ds:code
- mov NICstatus,al ; save NIC status
- loadport
- setport DAT
- test al,GOOD ; Is Rx generating interrupt ?
- mov al,NUL_CMD
- out dx,al
- jnz Rx_Good_Pkt2 ; Yes, take care of this situation.
- mov al,NICstatus
- test al,RXBUSY
- jz Enable_Rx2
- jmp CheckTx ; No, go to check Tx.
-
- Enable_Rx2:
- ;change Rx page & enable NIC to Rx
- mov bl,Mode_RxPg
- mov cx,COMMAND
- setport DAT
- write_sub_delay bl
- call delay
- or bl,RXEN
- if 0
- write_sub_delay bl
- else
- mov al,bl
- shl al,cl
- or al,ch
- xor al,08h
- out dx,al
- call delay
-
- xor al,08h
- out dx,al
- call delay
-
- mov al,bl
- and al,0f0h
- or al,ch
- xor al,08h
- out dx,al
- endif
- jmp CheckTx
-
- Rx_Good_Pkt2:
- ;Put it on the receive queue
- mov cx,RX_LEN ; read Rx Packet Length
- loadport
-
- read_sub_delay bl, 1
- read_sub_delay bh, 0
-
- sub bx,4 ;subtrate 4 CRC Byte Count
- mov RxPktLen,bx ;save Rx Packet Length
-
- ;change Rx page & enable NIC to Rx
- xor Mode_RxPg,10h
- mov bl,Mode_RxPg
- mov cx,COMMAND
- setport DAT
- write_sub_delay bl
- call delay
- or bl,RXEN
- write_sub_delay bl
- call delay
-
- xor bx,bx
- mov bh,CurRxPage ;BL = Current Rx Page
- xor CurRxPage,10h ;change to next page for Rx
- shr bx,1 ;shift BX to real memory address
- mov RxStartAdd,bx ;save just Rx Packet Start Address
-
- add bx,EADDR_LEN+EADDR_LEN ;seek to the TYPE word
- mov cx,RW_ADR
- write_sub_delay bl
- call delay
- write_sub_delay bh
- call delay
-
- mov cx,READ ;read the TYPE word
-
- read_sub_delay bl, 1
- read_sub_delay bh, 0
- mov our_type,bx ;save the TYPE word
-
- mov ax,ds
- mov es,ax
- mov di,offset our_type
- mov cx,RxPktLen
-
- call recv_find ;request a Rx buffer to store Rx data
-
- mov ax,es ;is this pointer null?
- or ax,di
- jnz find_buffer2
- jmp CheckTx ;yes - just free the frame.
- find_buffer2:
- push es
- push di ;remember where the buffer pointer is.
- assume ds:nothing
- mov bx,RxStartAdd
- mov cx,RW_ADR
- loadport
- setport DAT
- write_sub_delay bl
- call delay
- write_sub_delay bh
- call delay
-
- cld
- mov bp,RxPktLen ;CX = the byte count of Rx Packet
- setport STAT
- mov cx,READ
- mov ah,ch
- xor ah,08h
- read_mem2:
- dec dx
- mov al,ch
- out dx,al
- call delay
-
- inc dx
- in al,dx
- mov bl,al
- dec dx
- mov al,ah
- out dx,al
- call delay
-
- inc dx
- in al,dx
- shr bl,cl
- and al,0f0h
- or al,bl
- stosb
- dec bp
- jnz read_mem2
- jmp RxCopy_CheckTx
-
-
- public end_resident,end_free_mem
- end_resident label byte
- end_free_mem label byte
- 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.
-
- public usage_msg
- usage_msg db "usage: DE600 [options] <packet_int_no>",CR,LF,'$'
-
- public copyright_msg
- copyright_msg db "Packet driver for the D-Link DE-600, "
- db "version ",'0'+(majver / 10),'0'+(majver mod 10),".",'0'+version,CR,LF,'$'
- db "Portions Copyright 1988, Robert C. Clements, K1BC"
- db CR,LF,'$'
-
- CableErr db "Bad cable connection.",07,CR,LF,'$'
- mem_error_msg db "Adapter memory buffer failure, or bad printer "
- db "port connection.",07,CR,LF,'$'
- irq_error_msg db "IRQ unavailable, please check other hardware in "
- db "computer.",07,CR,LF,'$'
- no_NIC_err db "Adapter not found, or AC adapter power is off.",07,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 get_number: near
-
- ;enter with dx -> name of word, di -> dword to print.
- extrn print_number: near
-
- ;-> the assigned Ethernet address of the card.
- extrn rom_address: byte
-
- assume ds:code
- public parse_args
- parse_args:
- ret
-
-
- public print_parameters
- print_parameters:
- ret
-
- cable_err:
- mov dx,offset CableErr
- stc
- ret
- IRQ_error:
- mov dx,offset irq_error_msg
- stc
- ret
- no_our_NIC:
- mov dx,offset no_NIC_err
- stc
- ret
-
- public etopen
- etopen:
- ; Initialize the Ethernet board.
- call check_PS2
-
- xor ax,ax
- mov es,ax
- mov si,PRNTABADD-2 ; point to printer table at low memory
- next_prn_port:
- add si,2
- mov bx,es:[si] ; get LPTx's I/O Base
- or bx,bx ; Does LPTx really exist ?
- jz Chk_out_of_range
- mov io_addr,bx ; save the I/O Base number
- mov printer,si ; memorize it's LPTx now
- call Check_DE600 ; Yes, BX = I/O Base, then check.
- jnc IO_good ; If carry flag is clear, so go to
- mov al,NML_PRN
- call CMD_sub
- Chk_out_of_range:
- cmp si,PRNTABADD+6 ; We still miss our card from LPT1 to
- jb next_prn_port
- jmp short no_our_NIC ; We still miss our card from LPT1 to
- ; LPT4. We give it up.
- IO_good:
- ; Copy our Ethernet address from PROM into DE600.
- push ds
- pop es
- mov di,offset rom_address
- mov cx,RW_ADR
- xor bl,bl
- call Write_sub
- or bl,HA13
- call Write_sub
-
- cld
- mov bp,EADDR_LEN
- mov cx,READ
- get_our_address:
- call Read_sub
- mov al,bl
- stosb
- dec bp
- jnz get_our_address
-
- mov si,offset rom_address ;make sure it's got the right magic
- cmp word ptr es:[si],0de00h ; number.
- jne no_our_NIC
- cmp byte ptr es:[si+2],15h
- jne no_our_NIC
-
- mov word ptr es:[si],8000h ;now modify it to the address assigned
- mov byte ptr es:[si+2],0c8h ; by Xerox.
- and byte ptr es:[si+3],0fh
- or byte ptr es:[si+3],070h
-
- mov cx,EADDR_LEN
- call set_address
-
- ; Check DE600's IRQ enviroment
- call Check_IRQ
- cmp bx,1
- je cable_OK
- jmp cable_err
-
- cable_OK:
- mov bx,offset delay
- mov byte ptr [bx],0c3h ; ret
-
- ; test 8 KBytes memory
- ;********** write mode 1 *************
- mov cx,700h
- mov al,PAGE3
- call Write_LoopBack_Data
- xor bx,bx
- mov si,bx
- write_next_page:
- call Tx_Data
- push bx
- mov cx,RW_ADR
- loadport
- setport DAT
- write_sub_fast bl
- write_sub_fast bh
-
- mov bx,si
- mov bp,800h
- mov cx,WRITE
- mov ah,ch
- xor ah,08h
- wr_this_page:
- mov al,bl
- shl al,cl
- or al,ch
- out dx,al
- mov al,bl
- and al,0f0h
- or al,ah
- out dx,al
- inc bl
- dec bp
- jnz wr_this_page
- inc si
- pop bx
- add bx,800h
- cmp bx,1800h
- ja read_memory
- jmp short write_next_page
-
- ;************ read mode 1 ************
- read_memory:
- loadport
- setport DAT
- xor bx,bx
- mov si,bx
- read_next_page:
- push bx
- mov cx,RW_ADR
- write_sub_fast bl
- write_sub_fast bh
-
- mov bx,si
- mov bp,800h
- mov cx,READ
- mov ah,ch
- xor ah,08h
- rd_this_page:
- mov al,ch
- out dx,al
- pause
- inc dx
- in al,dx
- mov bh,al
- dec dx
- mov al,ah
- out dx,al
- pause
- inc dx
- in al,dx
- shr bh,cl
- and al,0f0h
- or bh,al
- cmp bh,bl
- jne memory_test
- dec dx
- inc bl
- dec bp
- jnz rd_this_page
- inc si
- pop bx
- add bx,800h
- cmp bx,1800h
- ja mem_is_OK
- push si
- push bx
- mov cx,700h
- mov al,PAGE0
- call Write_LoopBack_Data
- call Tx_Data
- pop bx
- pop si
- jmp short read_next_page
- mem_is_OK:
- jmp mem_OK
-
- ;************ write mode 2 ***************
- memory_test:
- pop ax
- memory_test1:
- mov cx,700h
- mov al,PAGE3
- call Write_LoopBack_Data
- xor bx,bx
- mov si,bx
- write_next_page1:
- call Tx_Data
- push bx
- mov cx,RW_ADR
- loadport
- setport DAT
- write_sub_slow bl
- call delay
- write_sub_slow bh
- call delay
-
- mov bx,si
- mov bp,800h
- mov cx,WRITE
- mov ah,ch
- xor ah,08h
- wr_this_page1:
- mov al,bl
- shl al,cl
- or al,ch
- out dx,al
- call delay
-
- mov al,bl
- and al,0f0h
- or al,ah
- out dx,al
- call delay
- inc bl
- dec bp
- jnz wr_this_page1
- inc si
- pop bx
- add bx,800h
- cmp bx,1800h
- ja read_memory1
- jmp short write_next_page1
-
- ;************* read mode 2 **************
- read_memory1:
- loadport
- setport DAT
- xor bx,bx
- mov si,bx
- read_next_page1:
- push bx
- mov cx,RW_ADR
- write_sub_slow bl
- call delay
- write_sub_slow bh
- call delay
-
- mov bx,si
- mov bp,800h
- mov cx,READ
- mov ah,ch
- xor ah,08h
- rd_this_page1:
- mov al,ch
- out dx,al
- call delay
-
- inc dx
- in al,dx
- mov bh,al
- dec dx
- mov al,ah
- out dx,al
- call delay
-
- inc dx
- in al,dx
- shr bh,cl
- and al,0f0h
- or bh,al
- cmp bh,bl
- jne memory_test2
- dec dx
- inc bl
- dec bp
- jnz rd_this_page1
- inc si
- pop bx
- add bx,800h
- cmp bx,1800h
- ja mem_is_OK1
- push si
- push bx
- mov cx,700h
- mov al,PAGE0
- call Write_LoopBack_Data
- call Tx_Data
- pop bx
- pop si
- jmp read_next_page1
- mem_is_OK1:
- jmp mem_OK1
-
- ;************* write mode 3 ***************
- memory_test2:
- pop ax
- memory_test3:
- mov cx,700h
- mov al,PAGE3
- call Write_LoopBack_Data
- xor bx,bx
- mov si,bx
- write_next_page3:
- call Tx_Data
- push bx
- mov cx,RW_ADR
- loadport
- setport DAT
- write_sub_delay bl
- call delay
- write_sub_delay bh
- call delay
-
- mov bx,si
- mov bp,800h
- mov cx,WRITE
- wr_this_page3:
- mov al,bl
- shl al,cl
- or al,ch
- xor al,08h
- out dx,al
- call delay
-
- xor al,08h
- out dx,al
- call delay
-
- mov al,bl
- and al,0f0h
- or al,ch
- out dx,al
- call delay
-
- xor al,08h
- out dx,al
- call delay
- inc bl
- dec bp
- jnz wr_this_page3
- inc si
- pop bx
- add bx,800h
- cmp bx,1800h
- ja read_memory3
- jmp write_next_page3
-
- ;************* read mode 3 ***************
- read_memory3:
- loadport
- setport DAT
- xor bx,bx
- mov si,bx
- read_next_page3:
- push bx
- mov cx,RW_ADR
- write_sub_delay bl
- call delay
- write_sub_delay bh
-
- call delay
-
- mov bx,si
- mov bp,800h
- mov cx,READ
- mov ah,ch
- xor ah,08h
-
- mov al,ch
- xor al,08h
- out dx,al
- call delay
- rd_this_page3:
- mov al,ch
- out dx,al
- call delay
-
- setport STAT
- in al,dx
- mov bh,al
- setport DAT
- mov al,ah
- out dx,al
- call delay
-
- setport STAT
- in al,dx
- shr bh,cl
- and al,0f0h
- or bh,al
- cmp bh,bl
- jne mem_err
- setport DAT
- inc bl
- dec bp
- jnz rd_this_page3
- inc si
- pop bx
- add bx,800h
- cmp bx,1800h
- ja mem_OK2
- push si
- push bx
- mov cx,700h
- mov al,PAGE0
- call Write_LoopBack_Data
- call Tx_Data
- pop bx
- pop si
- jmp read_next_page3
-
- pointer dw 0
-
- mem_err:
- pop bx
- cmp pointer,9 ;too slow? Must not be working.
- ja mem_real_err
- mov bx,offset delay ;append another NOP and RET in.
- add bx,pointer
- mov [bx],0c390h
- inc pointer ;slow it down a little more and try
- jmp memory_test3 ; again.
- mem_real_err:
- mov dx,offset mem_error_msg
- stc
- ret
-
- change_routine:
- mov ax,offset recv1
- mov recv_pointer,ax
- mov ax,offset send_pkt1
- mov send_pkt_pointer,ax
- ret
-
- change_routine2:
- mov ax,offset recv2
- mov recv_pointer,ax
- mov ax,offset send_pkt2
- mov send_pkt_pointer,ax
- ret
-
- ;********** memory test passed ****************
- mem_OK1:
- call change_routine
- jmp short mem_OK
- mem_OK2:
- call change_routine2
- mem_OK:
- call speed_test
-
- push es
- xor ax,ax
- mov es,ax
- mov si,printer
- mov word ptr es:[si],ax ; Zero-out Printer Port
- pop es
-
- ; Initialize Rx buffer pointer, and start receive
- mov bl,Mode
- or bl,IRQinverse
- or bl,CurRXPage
- mov Mode_RxPg,bl
- mov cx,COMMAND
- call Write_sub
- or bl,RXEN
- call Write_sub
-
- ; Put our Receive routine in interrupt chain
- call set_recv_isr
-
- ; We didn't need to enable the receive & transmit interrupts, they were
- ; set by hardware already. (accept GOOD, SUC & T16 to generate interrupt)
-
- ; Enable Printer Adapter IRQ line
- mov al,SLT_PRN
- call CMD_sub
-
- clc
- ret
-
-
- ;*********** sub-routine *************
- ; Check DE-600 routine
- Check_DE600:
- mov al,SLT_NIC
- call CMD_sub
- call delay
-
- loadport
- setport DAT
- mov al,NUL_CMD
- out dx,al
- call delay
-
- mov bl,RESET
- mov cx,COMMAND
- call Write_sub
- call delay
- mov bl,STOP_RESET
- call Write_sub
- call delay
-
- mov cx,STATUS
- call Read_sub
- test bl,0f0h
- jz Check_OK
- stc
- ret
- Check_OK:
- clc
- ret
-
- OldIRQ5 dd 0
- OldIRQ7 dd 0
-
- NewIRQ5:
- push ax
- push bx
- push cx
- push dx
- push ds
- mov al,20h
- out 20h,al
- mov ax,cs
- mov ds,ax
- cmp LB,0
- jz DisCare_IRQ5
- mov bh,5
- call Clear_int
- DisCare_IRQ5:
- pop ds
- pop dx
- pop cx
- pop bx
- pop ax
- iret
-
- NewIRQ7:
- push ax
- push bx
- push cx
- push dx
- push ds
- mov al,20h
- out 20h,al
- mov ax,cs
- mov ds,ax
- cmp LB,0
- jz DisCare_IRQ7
- mov bh,7
- call Clear_int
- DisCare_IRQ7:
- pop ds
- pop dx
- pop cx
- pop bx
- pop ax
- iret
-
- replace_IRQ5_7:
- xor cx,cx
- mov es,cx
- mov di,034h
- mov ax,es:[di] ;save old interrupt vector
- mov word ptr OldIRQ5,ax
- mov ax,es:[di]+2
- mov word ptr OldIRQ5+2,ax
- mov ax,offset NewIRQ5
- stosw
- mov ax,cs
- stosw
-
- mov di,03ch
- mov ax,es:[di] ;save old interrupt vector
- mov word ptr OldIRQ7,ax
- mov ax,es:[di]+2
- mov word ptr OldIRQ7+2,ax
- mov ax,offset NewIRQ7
- stosw
- mov ax,cs
- stosw
-
- in al,21h
- mov intmask,al
- pause
- pause
- and al,5fh
- out 21h,al
- ret
-
- intmask db 0
- INT_come db 0
- T16_flag db 0
- LB db 0
-
- restore_IRQ5_7:
- xor cx,cx
- mov es,cx
- mov di,034h
- mov ax,word ptr OldIRQ5
- mov es:[di],ax ;save old interrupt vector
- mov ax,word ptr OldIRQ5+2
- mov es:[di]+2,ax
-
- mov di,03ch
- mov ax,word ptr OldIRQ7
- mov es:[di],ax ;save old interrupt vector
- mov ax,word ptr OldIRQ7+2
- mov es:[di]+2,ax
-
- mov al,intmask
- out 21h,al
- ret
-
- Write_LoopBack_Data:
- mov si,offset rom_address
- mov di,si
- ;set Tx Pointer for moving packet
- mov bx,BFRSIZ
- sub bx,cx ;CX= Packet Length
- or bh,al ;AL= Page Number
- mov TxStartAdd,bx ;BX= the pointer to TX
- mov cx,RW_ADR ;write memory address
- call Write_sub
- mov bl,bh
- call Write_sub
- cld
- loadport
- setport DAT
- mov bp,12
- mov cx,WRITE
- write_our_node_ID:
- lodsb
- mov bl,al
- call Write_sub
- cmp bp,7
- jne not_second_ID
- mov si,di
- not_second_ID:
- dec bp
- jnz write_our_node_ID
- ret
-
- Tx_Data:
- ;Check TXIDLE, if high then wait for previous Tx end, if low then Tx it
- mov cx,800h ; Avoid infinite loop
- loadport
- setport STAT
- wait_Txidle0:
- in al,dx
- test al,TXBUSY ; Is the previous Tx successful ?
- jz Tx_next0 ; Yes, TXBUSY is low. Then could Tx next packet.
- loop wait_Txidle0
- Tx_next0:
- ;set Tx Pointer at beginning of packet
- push bx
- mov cx,TX_ADR
- mov bx,TxStartAdd
- call Write_sub
- mov bl,bh
- call Write_sub
- ;Enable interrupt and start Tx
- mov cx,COMMAND
- mov bl,RX_NONE
- call Write_sub
- or bl,TXEN
- call Write_sub
- pop bx
- ret
-
- LoopBack_Tx:
- ;set Tx Pointer at beginning of packet
- mov bx,TxStartAdd
- mov cx,TX_ADR
- call Write_sub
- mov bl,bh
- call Write_sub
- ;Enable interrupt and start Tx
- mov bl,RX_BP
- or bl,IRQinverse
- mov cx,COMMAND
- call Write_sub
- or bl,LOOPBACK
- call Write_sub
-
- mov LB,1
- mov al,SLT_PRN
- call CMD_sub
-
- xor bx,bx
- mov cx,8000h
- wait_int:
- cmp INT_come,0
- jz have_T16
- mov bx,1
- jmp short exit_LoopBack
- have_T16:
- cmp T16_flag,0
- jz still_wait
- mov bx,-1
- jmp short exit_LoopBack
- still_wait:
- loop wait_int
-
- exit_LoopBack:
- mov LB,0
- mov al,SLT_NIC
- call CMD_sub
-
- push bx
- mov cx,STATUS
- call Read_sub
- pop bx
- ret
-
- Clear_int:
- mov al,SLT_NIC
- call CMD_sub
- pause
- mov cx,STATUS
- call Read_sub
-
- mov T16_flag,0
- test bl,GOOD ; Is Rx generating interrupt ?
- jz chk_T16
- mov INT_come,1
- mov int_no,bh
- jmp short exit_Clear_int
- chk_T16:
- test bl,T16 ; Is pending a Tx Packet ?
- jz exit_Clear_int
- mov T16_flag,1
- exit_Clear_int:
- ret
-
- Check_IRQ:
- call replace_IRQ5_7
- sti
- mov cx,RUNT
- mov al,PAGE0
- call Write_LoopBack_Data
- call LoopBack_Tx ; check IRQ= 7 or 5 but IRQ not inverse
- cmp bx,0
- jnz IRQ_OK
-
- ;Check TXIDLE, if high then wait for previous Tx end, if low then Tx it
- mov cx,800h ; Avoid infinite loop
- loadport
- setport STAT
- wait_Txidle:
- in al,dx
- test al,TXBUSY ; Is the previous Tx successful ?
- jz Tx_next ; Yes, TXBUSY is low. Then could Tx next packet.
- loop wait_Txidle
- Tx_next:
- mov IRQinverse,40h ; check IRQ= 7 or 5 but IRQ inverse
- mov PS2,0
- call LoopBack_Tx
- IRQ_OK:
- cli
- call restore_IRQ5_7
- ret
-
- check_PS2:
- mov ax,0c400h
- int 15h
- jc not_PS2
- mov PS2,1
- not_PS2:
- ret
-
- speed_test:
- xor ax,ax
- mov es,ax
- mov si,20h
- mov ax, es:[si]
- mov cs:old_int8, ax
- mov ax, es:[si+2]
- mov cs:old_int8[2], ax
- cli
- mov ax,offset new_int8
- mov es:[si],ax
- mov es:[si+2],cs
- sti
-
- next_test1:
- mov ticks_start,0
- next_test:
- cmp ticks_start,0
- jz next_test
- mov ticks,0
- xor bx,bx
- loop_again:
- mov cx,6
- loop $
- cmp ticks,2
- jae End_count
- inc bx
- jmp short loop_again
-
- End_count:
- cli
- xor ax,ax
- mov es,ax
- mov si,20h
- mov ax,old_int8
- mov es:[si],ax
- mov ax,old_int8[2]
- mov es:[si+2],ax
- sti
- cmp bx,0a000h
- jb low_speed
- mov ax,offset recv1 ; special for high speed EISA
- mov recv_pointer,ax
- low_speed:
- ret
-
- ticks_start db 0
- ticks db 0
- old_int8 dw ?
- dw ?
- new_int8:
- inc ticks
- inc ticks_start
- jmp dword ptr cs:old_int8
-
- code ends
- end
-