home *** CD-ROM | disk | FTP | other *** search
- version equ 6
-
- include defs.asm
-
- ;Ported from Phil Karn's asy.c and slip.c, a C-language driver for the IBM-PC
- ;8250 by Russell Nelson. Any bugs are due to Russell Nelson.
- ;16550 support ruthlessly stolen from Phil Karn's 8250.c.
- ; Bugs by Denis DeLaRoca
- ; Stopped failures from lost transmit interrupts (by eliminating the ints
- ; altogether). Remove unneeded transmitter buffer.
- ; Version 6 by Joe Doupnik, jrd@cc.usu.edu, Utah State University, Dec 1991.
-
- ; Copyright, 1988, 1991, Russell Nelson
-
- ; This program is free software; you can redistribute it and/or modify
- ; it under the terms of the GNU General Public License as published by
- ; the Free Software Foundation, version 1.
- ;
- ; This program is distributed in the hope that it will be useful,
- ; but WITHOUT ANY WARRANTY; without even the implied warranty of
- ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- ; GNU General Public License for more details.
- ;
- ; You should have received a copy of the GNU General Public License
- ; along with this program; if not, write to the Free Software
- ; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
- code segment word public
- assume cs:code, ds:code
-
- include 8250defs.asm
-
- ;Slip Definitions
- FR_END equ 0c0h ;Frame End
- FR_ESC equ 0dbh ;Frame Escape
- T_FR_END equ 0dch ;Transposed frame end
- T_FR_ESC equ 0ddh ;Transposed frame escape
-
- public int_no
- int_no db 4,0,0,0 ; interrupt number.
- io_addr dw 03f8h,0 ; I/O address for COM1
- baud_rate dw 12c0h,0 ; support baud higher than 65535
- baudclk label word
- dd 115200 ; 1.8432 Mhz / 16
- hardware_switch db 0 ; if zero, don't use hw handshaking
- is_16550 db 0 ; 0=no, 1=yes (try using fifo)
-
- public driver_class, driver_type, driver_name
- public driver_function, parameter_list
- driver_class db 6,0,0,0 ;from the packet spec
- driver_type db 0,0,0,0 ;from the packet spec
- driver_name db 'SLIP8250',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,
-
- ifdef debug
- public recv_buf_size, recv_buf, recv_buf_end, recv_buf_head
- public recv_buf_tail, recv_pkt_ready
- endif
- recv_buf_size dw 3000,0 ;receive buffer size
- recv_buf dw ? ;->receive buffer
- recv_buf_end dw ? ;->after end of buffer
- recv_buf_head dw ? ;->next character to get
- recv_buf_tail dw ? ;->next character to store
- recv_pkt_ready dw 0 ; flag indicating a packet is ready
- IP_TYPE DW 0800H
-
- ifdef debug
- public packet_sem, xmit_time
- endif
- packet_sem dw 0 ; semaphore for packets received
- asyrxint_cnt dw 0 ; loop counter in asyrxint
- xmit_time dw 0 ; loop timer for asyrxint
-
- public rcv_modes
- rcv_modes dw 4 ;number of receive modes in our table
- dw 0,0,0,rcv_mode_3
-
-
- 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
- ;
- ; mod 7/25/89 John Grover
- ; - operates with interrupts on. Xmits one byte per interrupt
- ; - only turns transmitter buffer empty interrupt off when
- ; - all bytes of all packets are transmitted.
-
- send_pkt:
- ;enter with es:di->upcall routine, (0:0) if no upcall is desired.
- ; (only if the high-performance bit is set in driver_function)
-
- ;enter with ds:si -> packet, cx = packet length.
- ;exit with nc if ok, or else cy if error, dh set to error number.
- ;called from telnet layer via software interrupt
- ; We just send each byte in turn. No UART interrupts are needed nor wanted.
- ; In fact the overdone receiver material omits to note that xmtr interrupts
- ; can be lost while processing rcvr ones. Small benefits are no stalled
- ; programs, no transmitter buffer, no problems at 19200 b/s. Joe Doupnik
- assume ds:nothing, es:nothing
- sti ; enable interrupts
- cld
- mov al,FR_END ; Flush out any line garbage
- call send_char
- jc send_pkt_end ; c = failure to send
-
- ;Copy input to output, escaping special characters
- send_pkt_1:
- lodsb
- cmp al,FR_ESC ; escape FR_ESC with FR_ESC and T_FR_ESC
- jne send_pkt_2
- mov al,FR_ESC
- call send_char
- jc send_pkt_end
- mov al,T_FR_ESC
- jmp short send_pkt_3
- send_pkt_2:
- cmp al,FR_END ; escape FR_END with FR_ESC and T_FR_END
- jne send_pkt_3
- mov al,FR_ESC
- call send_char
- jc send_pkt_end
- mov al,T_FR_END
- send_pkt_3:
- call send_char
- jc send_pkt_end
- loop send_pkt_1 ; do cx user characters
- mov al,FR_END ; terminate it with a FR_END
- call send_char
- jc send_pkt_end
- clc
- send_pkt_end:
- ret
-
- ; mod 7/25/89 John Grover
- ; redone by Joe Doupnik, Dec 1991
- assume ds:nothing, es:nothing
- send_char: ; send the character in al
- push dx
- push cx
- xchg ah,al ; put data char into ah
- xor cx,cx ; 64K retry counter
- sendch1:mov dx,io_addr ; 03f8h base address
- add dx,LSR ; 03fdh get port status
- in al,dx
- test al,LSR_THRE ; Transmitter (THRE) ready?
- jnz sendch2 ; nz = yes
- jmp $+2 ; use time, prevent overdriving UART
- jmp $+2
- loop sendch1
- stc ; carry set for failure
- jmp short sendch3 ; timeout
- sendch2:xchg al,ah ; now send it
- mov dx,io_addr ; 03f8h, use a little time
- jmp $+2
- out dx,al ; send the byte
- clc ; status of success
- sendch3:pop cx
- pop dx
- ret
-
-
- public get_address
- get_address:
- ;get the address of the interface.
- ;enter with es:di -> place to get the address, cx = size of address buffer.
- ;exit with nc, cx = actual size of address, or cy if buffer not big enough.
- assume ds:code
- xor cx,cx
- clc
- ret
-
-
- public set_address
- set_address:
- ;set the address of the interface.
- ;enter with es:di -> place to get the address, cx = size of address buffer.
- ;exit with nc, cx = actual size of address, or cy if buffer not big enough.
- assume ds:nothing
- clc
- ret
-
-
- rcv_mode_3:
- ;receive mode 3 is the only one we support, so we don't have to do anything.
- ret
-
-
- public set_multicast_list
- set_multicast_list:
- ;enter with ds:si ->list of multicast addresses, cx = number of addresses.
- ;return nc if we set all of them, or cy,dh=error if we didn't.
- mov dh,NO_MULTICAST
- stc
- ret
-
-
- public get_multicast_list
- get_multicast_list:
- ;return with nc, es:di ->list of multicast addresses, cx = number of bytes.
- ;return cy, NO_ERROR if we don't remember all of the addresses ourselves.
- ;return cy, NO_MULTICAST if we don't implement multicast.
- mov dh,NO_MULTICAST
- stc
- ret
-
-
- public terminate
- terminate:
- ret
-
- public reset_interface
- reset_interface:
- ;reset the interface.
- assume ds:code
- 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
-
- public recv
-
- ;
- ; mod 7/25/89 John Grover
- ;
- ; - added code to check modem status change interrupt. If CTS is
- ; - low turn off transmitter buffer empty interrupt. If CTS is
- ; - high turn it on.
-
- recv:
- ;called from the recv isr. All registers have been saved, and ds=cs.
- ;Upon exit, the interrupt will be acknowledged.
- assume ds:code
- recv_2:
- loadport
- setport IIR
- in al,dx ;any interrupts at all?
- test al,IIR_IP
- jne recv_1 ;no.
- and al,IIR_ID
- cmp al,IIR_RDA ;Receiver interrupt
- jne recv_3
- call asyrxint
- jmp recv_2
- recv_3:
- recv_5:
- ;process IIR_MSTAT here.
- ; If CTS and packet ready then
- ; enable the transmit buffer empty interrupt
- ; else
- ; disable the transmit buffer empty interrupt
- ;
- cmp al, IIR_MSTAT
- jne recv_1
- setport MSR ; make sure of CTS status
- in al, dx
- ; test al, MSR_CTS ; is CTS bit set
- ; jz recv_5_1 ; no - disable xmit buffer empty int
- jmp recv_2
-
- recv_5_1:
- jmp recv_2
-
- ;process IIR_RLS here
- recv_1:
- ret
-
-
- ;Process 8250 receiver interrupts
- ;
- ; mod 7/25/89 John Grover
- ; - this branches off when bps < 9600. See asyrxint_a.
- ; - Above 9600 bps we go into a loop to process a packet at
- ; - a time. If not data ready for a certain amount of time,
- ; - the process exits and waits for the next byte. This certain
- ; - amount of time to wait depends on the bps and CPU processor speed
- ; - and is determined in the initialization of the driver.
- ; - Upon receiving the FR_END character for the first frame in the
- ; - buffer a semaphore is set which tells recv_frame to run.
-
- asyrxint:
-
- push ds ; get set up for the routine
- pop es
- xor bx, bx
- cmp baud_rate, 9600 ; below 9600 we're strictly
- jbe asyrxint_a ; interrupt driven
- mov bx, xmit_time
- asyrxint_a:
- mov di,recv_buf_tail
- xor bp, bp ; set flag to indicate 1st char
- ; processed
- mov si, packet_sem ; optimization
- loadport
- mov ah, LSR_DR
-
- asyrxint_again:
- xor cx, cx ; initialize counter
- setport LSR
- asyrxint_in:
- in al,dx ; check for data ready
- test al,LSR_DR
- jnz asyrxint_gotit ; yes - break out of loop
- inc cx ; no - increase loop counter
- cmp cx, bx ; timeout?
- jae asyrxint_exit ; yes - leave
- jmp asyrxint_in ; no - keep looping
-
- asyrxint_gotit:
- setport RBR
- in al,dx
-
- ;Process incoming data;
- ; If buffer is full, we have no choice but
- ; to drop the character
- cmp di,recv_buf_head ; check for buffer collision
- jne asyrxint_ok ; none - continue
- or si, si ; maybe - if there are packets
- jnz asyrxint_exit ; yes exit
-
- asyrxint_ok:
- stosb
-
- cmp di,recv_buf_end ; did we hit the end of the buffer?
- jne asyrxint_3 ; no.
- mov di,recv_buf ; yes - wrap around.
-
- asyrxint_3:
- cmp al,FR_END ; might this be the end of a frame?
- jne asyrxint_reset ; no - reset flag and loop
- inc si ; yes - indicate packet ready
- cmp si, 1 ; determine if semaphore is <> 1
- jne asyrxint_chk_flg ; yes - recv_frame must be active
- inc recv_pkt_ready ; no - set flag to start recv_frame
-
- asyrxint_chk_flg:
- cmp bp, 0 ; was this the first char?
- jne asyrxint_1 ; no - exit handler
- asyrxint_reset:
- inc bp ; set 1st character flag
- jmp asyrxint_again ; get another character
-
- asyrxint_exit:
- asyrxint_1:
- mov recv_buf_tail,di
- mov packet_sem, si
-
- ret
-
-
- ; --------------------------------------------------------------
- ;
- ; recv_exiting
- ;
- public recv_exiting
- recv_exiting:
- cmp recv_pkt_ready, 1 ; is a packet ready?
- jne recv_isr_exit ; no - skip to end
- push ax
- push bx
- push cx
- push dx
- push ds
- push es
- push bp
- push di
- push si
- push cs ; point ds properly
- pop ds
- mov recv_pkt_ready, 0 ; reset flag
- sti ; enable interrupts
-
- call recv_frame
-
- cli
- pop si
- pop di
- pop bp
- pop es
- pop ds
- pop dx
- pop cx
- pop bx
- pop ax
- recv_isr_exit:
- ret
-
-
- ; --------------------------------------------------------------
- ;
- ; recv_frame
- ;
- ; mod 7/25/89 John Grover
- ;
- ; - recv_frame now operates with interrupts on. It is triggered
- ; - by the recv_pkt_ready flag and continues until all bytes
- ; - in all packets in the buffer have been transmitted to the upper
- ; - layer.
- ;
- ifdef debug
- public recv_frame
- endif
- recv_frame:
- cmp packet_sem, 0 ; should we do this?
- jz recv_frame_end ; no - exit
- mov si,recv_buf_head ;process characters.
- xor cx,cx ;count up the size here.
- recv_frame_1:
-
- call recv_char ;get a char.
- je recv_frame_2 ;go if no more chars.
- cmp al,FR_ESC ;an escape?
- je recv_frame_1 ;yes - don't count this char.
- inc cx ;no - count this one.
- jmp recv_frame_1
- recv_frame_2:
-
- jcxz recv_frame_3 ;count zero? yes - free the frame
- ;we don't need to set the type because none are defined for SLIP.
- push si ;save si in case we reject it.
- push bx
- MOV DI,CS
- MOV ES,DI
- mov di,0
- mov dl,cs:driver_class
- call recv_find ;look up our type.
- pop bx
- pop si
-
- mov ax,es ;is this pointer null?
- or ax,di
- je recv_frame_3 ;yes - just free the frame.
-
- push cx
- push es ;remember where the buffer pointer is
- push di
-
- mov si,recv_buf_head ;process characters.
- recv_frame_4:
- call recv_char
- je recv_frame_6 ;yes - we're all done.
- cmp al,FR_ESC ;an escape?
- jne recv_frame_5 ;no - just store it.
-
- call recv_char ;get the next character.
- je recv_frame_6
- cmp al,T_FR_ESC
- mov al,FR_ESC ;assume T_FR_ESC
- je recv_frame_5 ;yup, that's it - store FR_ESC
- mov al,FR_END ;nope, store FR_END
- recv_frame_5:
- stosb ;store the byte.
- jmp recv_frame_4
- recv_frame_6:
- mov recv_buf_head,si ;we're skipped to the end.
-
- pop si ;now give the frame to the client.
- pop ds
- pop cx
- assume ds:nothing
-
- call recv_copy
- push cs
- pop ds
- assume ds:code
- jmp recv_frame_end
-
- recv_frame_3:
- mov recv_buf_head,si ;remember the new starting point.
- recv_frame_end:
- dec packet_sem
- cmp packet_sem, 0 ; are there more packets ready?
- ja recv_frame ; yes - execute again
- ret
-
-
- ; --------------------------------------------------------------
- ;
- ; recv_char
- ;
- ; mod 7/25/89 John Grover
- ; - Now uses buffer pointers to determine if there are
- ; - characters left.
- ;
-
- recv_char:
- ;enter with si -> receive buffer, bx = receive count. Wrap around if needed.
- ;return with nz, al = next char. Return zr if there are no more chars in
- ; this frame.
- ;
- lodsb
- cmp si,recv_buf_end
- jb recv_char_1
- mov si,recv_buf
- recv_char_1:
- mov bx, recv_buf_tail
- cmp si, bx
- je recv_char_2
- cmp al,FR_END
- recv_char_2:
- ret
-
-
- ;Set bit(s) in I/O port
- setbit:
- ;enter with dx = port, ah = bit to set.
- in al,dx
- or al,ah
- out dx,al
- ret
-
-
- ;Clear bit(s) in I/O port
- clrbit:
- ;enter with dx = port, ah = bit to set.
- in al,dx
- not al ;perform an and-not using DeMorgan's.
- or al,ah
- not al
- out dx,al
- ret
-
-
- ;any code after this will not be kept after initialization.
- end_resident label byte
-
- public usage_msg
- usage_msg db "usage: SLIP8250 [-n] [-d] [-w] packet_int_no "
- db "[-h] [driver_class] [int_no]",CR,LF
- db " [io_addr] [baud_rate]",CR,LF
- db " [recv_buf_size]",CR,LF
- db " -h enables hardware handshaking",CR,LF
- db " The driver_class should be SLIP, KISS, AX.25,"
- db " or a number.",CR,LF,'$'
-
- public copyright_msg
- copyright_msg db "Packet driver for SLIP8250, version ",'0'+majver
- db ".",'0'+version,CR,LF
- db "Portions Copyright 1988 Phil Karn",CR,LF
- db "Portions Copyright 1991 Joe Doupnik",cr,lf,'$'
-
- approximate_msg db "Warning: This baud rate can only be approximated"
- db "using the 8250",CR,LF
- db "because it is not an even divisor of 115200"
- db cr,lf,'$'
-
- is_16550_msg db "16550 Uart detected, FIFO will be used",CR,LF,'$'
-
- class_name_ptr dw ?
- class_name db "Interface class ",'$'
- kiss_name db "KISS",CR,LF,'$'
- ax25_name db "AX.25",CR,LF,'$'
- slip_name db "SLIP",CR,LF,'$'
- int_no_name db "Interrupt number ",'$'
- io_addr_name db "I/O port ",'$'
- baud_rate_name db "Baud rate ",'$'
- recv_buf_name db "Receive buffer size ",'$'
- unusual_com1 db "That's unusual! Com1 (0x3f8) usually uses IRQ 4!"
- db CR,LF,'$'
- unusual_com2 db "That's unusual! Com2 (0x2f8) usually uses IRQ 3!"
- db 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
-
- ;enter with si -> argument string.
- ;skip spaces and tabs. Exit with si -> first non-blank char.
- extrn skip_blanks: near
-
-
- public parse_args
- parse_args:
- ;exit with nc if all went well, cy otherwise.
- call skip_blanks
- cmp al,'-' ;did they specify a switch?
- jne not_switch
- cmp byte ptr [si+1],'h' ;did they specify '-h'?
- je got_hardware_switch
- stc ;no, must be an error.
- ret
- got_hardware_switch:
- mov hardware_switch,1
- add si,2 ;skip past the switch's characters.
- jmp parse_args ;go parse more arguments.
- not_switch:
- or al,20h ; to lower case (assuming letter)
- cmp al,'k'
- jne parse_args_2
- mov driver_class,10 ;KISS, from packet spec
- mov dx,offset kiss_name
- jmp short parse_args_1
- parse_args_2:
- cmp al,'s'
- jne parse_args_3
- mov driver_class,6 ;SLIP, from packet spec
- mov dx,offset slip_name
- jmp short parse_args_1
- parse_args_3:
- cmp al,'a'
- jne parse_args_4
- mov driver_class,9 ;AX.25, from packet spec.
- mov dx,offset ax25_name
- jmp short parse_args_1
- parse_args_4:
- mov di,offset driver_class
- mov bx,offset class_name
- call get_number
- mov class_name_ptr,0
- jmp short parse_args_6
- parse_args_1:
- mov class_name_ptr,dx
- parse_args_5:
- mov al,[si] ;skip to the next blank or CR.
- cmp al,' '
- je parse_args_6
- cmp al,CR
- je parse_args_6
- inc si ;skip the character.
- jmp parse_args_5
- parse_args_6:
- mov di,offset int_no
- call get_number
- mov di,offset io_addr
- call get_number
- mov di,offset baud_rate
- call get_number
- mov di,offset recv_buf_size
- call get_number
- clc
- ret
-
-
- ; --------------------------------------------------------------
- ;
- ; etopen
- ;
- ; mod 7/25/89 John Grover
- ; - Contains a loop to determine a pseudo timeout for asyrxint.
- ; - The value is determined by transmitting characters in a
- ; - loop whose clock cycles are nearly the same as the "sister"
- ; - loop in asyrxint. The per character, maximum time used
- ; - basis which is then multiplied by a factor to achieve a timeout
- ; - value for the particular bps and CPU speed of the host.
-
- public etopen
- etopen:
- pushf
- cli
- ;
- ; mod 3/16/90 Denis DeLaRoca
- ; - determine if 16550 uart is present
- ; - if so initialize fifo buffering
- ;
- loadport
- setport FCR
- mov al,FIFO_ENABLE
- out dx,al ;outportb(base+FCR,(char) FIFO_ENABLE)
- setport IIR
- in al,dx ;inportb(base+IIR)
- and al,IIR_FIFO_ENABLED ; & IIR_FIFO_ENABLED
- cmp al,IIR_FIFO_ENABLED ;both bits must be on NEW, 11/20/90
- jnz not_16550 ;nope, we don't have 16550 chip
- mov is_16550,1 ;yes, note fact
- mov al,FIFO_SETUP ;and setup FIFO
- setport FCR
- out dx,al ;outportb(base+FCR,(char) FIFO_SETUP)
-
- mov dx,offset is_16550_msg
- mov ah,9
- int 21h ;let user know about 16550
-
- not_16550:
- loadport ;Purge the receive data buffer
- setport RBR
- in al,dx
-
- ;Set line control register: 8 bits, no parity
- mov al,LCR_8BITS
- setport LCR
- out dx,al
-
- ;Turn on receive interrupt enable in 8250, leave transmit
- ; and modem status interrupts turned off for now
- mov al,IER_DAV
- setport IER
- out dx,al
-
- ;Set modem control register: assert DTR, RTS, turn on 8250
- ; master interrupt enable (connected to OUT2)
-
- mov al,MCR_DTR or MCR_RTS or MCR_OUT2
- setport MCR
- out dx,al
-
- ;compute the divisor given the baud rate.
- mov dx,baudclk+2
- mov ax,baudclk
- mov bx,0
- asy_speed_1:
- inc bx
- sub ax,baud_rate
- sbb dx,baud_rate+2
- jnc asy_speed_1
- dec bx
- add ax,baud_rate
- adc dx,baud_rate+2
- or ax,dx
- je asy_speed_2
-
- mov dx,offset approximate_msg
- mov ah,9
- int 21h
-
- asy_speed_2:
-
- loadport ;Purge the receive data buffer
- setport RBR
- in al,dx
-
- mov ah,LCR_DLAB ;Turn on divisor latch access bit
- setport LCR
- call setbit
-
- mov al,bl ;Load the two bytes of the divisor.
- setport DLL
- out dx,al
- mov al,bh
- setport DLM
- out dx,al
-
- mov ah,LCR_DLAB ;Turn off divisor latch access bit
- setport LCR
- call clrbit
-
- call set_recv_isr ;Set interrupt vector to SIO handler
-
- ;set up the various pointers.
- mov dx,offset end_resident
-
- mov recv_buf,dx
- mov recv_buf_head,dx
- mov recv_buf_tail,dx
- add dx,recv_buf_size
- mov recv_buf_end,dx
- push dx ;save the ending address.
-
- ; the following code attempts to determine a pseudo timeout
- ; value to use in the loop that waits for an incoming character
- ; in asyrxint. The value returned in xmit_time is the number of
- ; loops processed between characters - therefore the loop used below
- ; is and should remain similar to the loop used in asyrxint.
-
- xor ax, ax ; we'll send a 0
- mov ah, LSR_THRE
- mov cx, 10h ; take the highest of 16 runs
- xor si, si ; will hold highest value
-
- xmit_time_start:
-
- xor di, di ; initialize counter
- loadport
- setport THR ; xmit a character
- out dx, al
- setport LSR ; set up to check for an empty buffer
-
- ; next is the loop actually being timed
-
- xmit_time_top:
- in al, dx
- test al, ah
- jnz xmit_time_done
- inc di
- cmp cx, cx ; these next few instructions do nothing
- jmp xmit_time_1 ; except maintain similarity with the
- ; "sister" loop in asyrxint
- xmit_time_1:
- jmp xmit_time_top
-
- xmit_time_done: ; end of timed loop
-
-
-
- cmp si, di ; compare highest value with new value
- ja xmit_time_end ; no bigger - just loop
- mov si, di ; bigger - save it
-
- xmit_time_end:
- loop xmit_time_start ; bottom of outer loop
-
- shl si, 1 ; we'll wait 8 characters worth
- shl si, 1
- shl si, 1
- mov xmit_time, si ; retain largest value
-
- ; end of pseudo timer determination
-
- 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.
-
- pop dx ;return the ending address.
- popf
- clc ;indicate no errors.
- ret
-
- public print_parameters
- print_parameters:
- ;echo our command-line parameters
- cmp class_name_ptr,0
- je echo_args_1
-
- mov dx,offset class_name
- mov ah,9
- int 21h
- mov dx,class_name_ptr
- mov ah,9
- int 21h
- jmp short echo_args_2
- echo_args_1:
- mov di,offset driver_class
- mov dx,offset class_name
- call print_number
- echo_args_2:
-
- 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
-
- cmp io_addr,03f8h ;is this com1?
- jne ia_com2
- mov dx,offset unusual_com1
- cmp int_no,4 ;com1 usually uses IRQ 4.
- jne ia_unusual
- jmp short ia_usual
- ia_com2:
- cmp io_addr,02f8h ;is this com2?
- jne ia_usual ;no.
- mov dx,offset unusual_com2
- cmp int_no,3 ;com2 usually uses IRQ 3.
- je ia_usual
- ia_unusual:
- mov ah,9
- int 21h
- ia_usual:
- mov di,offset baud_rate
- mov dx,offset baud_rate_name
- call print_number
- mov di,offset recv_buf_size
- mov dx,offset recv_buf_name
- call print_number
- ret
- code ends
- end
-
-