home *** CD-ROM | disk | FTP | other *** search
- PAGE 60,132
- NAME UART
- TITLE UART Version 1.2 1993 June 17
- COMMENT √
-
- UART C:
- Detect UART type of serial port
- UART COM1:
- If Errorlevel 5 GoTo SyntaxError
- If Errorlevel 4 GoTo PS2TYPE3
- If ErrorLevel 3 GoTo AT16550FIFO
- If ErrorLevel 2 GoTo AT16450
- If ErrorLevel 1 GoTo XT8250
- If ErrorLevel 0 GoTo NoSuchPort
-
- UART by itself is considered a syntax error and generates a
- usage message.
-
- Sets errorlevel to type of UART detected.
-
- This code is based on the MASM routines on page 364 Of PC
- Magazine May 26, 1992.
-
- In DESQview often ports COM1: and COM2: are not accessible. You
- must have access priviledge in your PIF.
-
- Under OS/2 virtualization makes all com ports look like 8250s.
-
- Supports only COM1: .. COM4:. Looks in BIOS Table to find the
- corresponding physical addresses.
-
- It expects this pattern COM1: COM2: COM3: COM4:
- port: 3f8 2f8 3e8 2e8
- irq: 4 3 4 3
- int: C B C B
-
- If for example COM1: has port 2f8, then irq 3 would be
- anticipated and its interrupts would be fielded on int vector B.
- Port has precedence over com port number in determining irq.
-
- To Do
-
- - extend support to COM5..COM8
- I don't know the expected IRQs or port addresses for these beasts.
- If you have info on how these are supposed to work, please pass
- it along. Also I would need someone with a machine with such ports
- to beta test.
-
- √ ; end of comment
-
- ;======
- ; M A C R O S
-
- PEEK MACRO portoffset
- ;; read port then delay
- if (portoffset NE DITTO)
- lea dx,[bx+portoffset]
- endif
- in al,dx
- call breath
- ENDM
-
- POKE MACRO portoffset
- ;; write port then delay
- if (portoffset NE DITTO)
- lea dx,[bx+portoffset]
- endif
- out dx,al
- call breath
- ENDM
-
- ;======
- ; E Q U A T E S
- PIC EQU 21h ; 21h PIC interrupt controller
- ; bits 76543210 - 1-disable interrupt
- RBR EQU 0 ; 3F8 Receive Buffer Register
- THR EQU 0 ; 3F8 Transmit Holding Register
- LSBDIV EQU 0 ; 3F8 LSB divisor, latch bit must be on
- ; in the LCR
- IER EQU 1 ; 3F9 Interrupt Enable Register
- ; 0000MLTR 1=enable
- ; Modem status, Line, Transmit, Receive
- MSBDIV EQU 1 ; 3F9 MSB divisor, DBLAB bit must be on
- IIR EQU 2 ; 3FA Interrupt Ident Register
- ; 001 none
- ; 110 line error, read line status
- ; 100 data avail, read char
- ; 010 thr empty, read IIR, send char
- ; 000 modem status, read MSR
- FIFO EQU 2 ; 3FA Fifo Control Register
- LCR EQU 3 ; 3FB Line Control Register
- ; DBSEPSWW
- ; Divisor latch, Break, Stick, Even
- ; Parity, Stop bits, word length11=8
- MCR EQU 4 ; 3FC Modem Control Register
- ; 000L21RD
- ; Loopback, Out-2, Out-1, RTS, DTR
- ; Out-2 enables ints, Out-1 does reset
- LSR EQU 5 ; 3FD Line Status Register
- ; 0THBFPOD
- ; Tx shift, Tx Hold, Break, Frame, Parity,
- ; Overrun, Data ready
- MSR EQU 6 ; 3FE Modem Status Register
- ; SRDCSRDC
- ; line Signal, Ring, DSR, CTS
- ; delta line Signal, Ring, DSR, CTS
- SCR EQU 7 ; 3FF Scratch
- ENH EQU 8003h ; 83FB Enhanced register
- DITTO EQU 9999 ; use same port as previously.
-
- stack segment stack ; keep MS link happy by providing null stack
- stack ends
-
- ;==============================================================
-
- CODE SEGMENT PARA ; start off in code.
-
- ;==============================================================
-
- data segment word ; provide a separate DATA segment
- ; Even though it appears in the source
- ; before the code, it the COM file it
-
- ;=============================================
-
-
- BIOSDATA segment AT 40h ; dummy segment in low RAM
- org 0h
-
- BIOSComAddrs dw ? ; 4 words of COM1: .. COM4:
- dw ? ; device addresses
- dw ?
- dw ?
-
- BIOSDATA ends
-
- ;=============================================
- ; E R R O R M E S S A G E S
- ;=============================================
-
- CopyrightMsg label byte
- db 13,10
- db '░▒▓█ UART 1.2 █▓▒░',13,10
- db 13,10
- db 'Determines UART type on specified COM port.',13,10
- db 13,10
- DB '(c) Copyright Roedy Green Canadian Mind Products 1992,1993.',13,10
- DB '#601 - 1330 Burrard Street, Vancouver BC CANADA V6Z 2B8 (604) 685-8412',13,10
- db 'May be freely distributed and used for any purpose except military.',13,10
- db 13,10,'$'
-
- UsageMsg label Byte
- db 'Error in command line. Note the mandatory colon. Try:',13,10
- db 13,10
- db 'UART COM1:',13,10
- db 'If Errorlevel 5 GoTo SyntaxError',13,10
- db 'If Errorlevel 4 GoTo PS2TYPE3',13,10
- db 'If ErrorLevel 3 GoTo AT16550FIFO',13,10
- db 'If ErrorLevel 2 GoTo AT16450',13,10
- db 'If ErrorLevel 1 GoTo XT8250',13,10
- db 'If ErrorLevel 0 GoTo NoSuchPort',13,10,'$'
-
- PortMsg db "COM"
- PortPatch1 db "x: is at hex port address: "
- HexPatch1 db "xxxx.",13,10,'$'
-
- ; Messages to describe the various types of chip found.
-
- code0 db "Port not accessible or not installed.",13,10,'$'
- code1 db "XT style 8250 UART.",13,10,'$'
- code2 db "AT style 16450 unbuffered UART (might possibly be old-style 16550 or 8250a).",13,10,'$'
- code3 db "AT style 16550AF buffered FIFO UART",13,10,'$'
- code4 db "PS/2 style IBM type 3 DMA serial port",13,10,'$'
-
- WrongPortMsg db "Warning, COM"
- portpatch2 db "x: should be at hex port address: "
- HexPatch2 db "xxxx. ",13,10,'$'
-
- GoodIRQmsg db "Port correctly configured to IRQ "
- IrqPatch1 db "x.",13,10,'$'
- BadIRQMsg db "ERROR: port not properly configured to IRQ "
- IrqPatch2 db "x.",13,10
- db 13,10
- db "If the port appears to be configured correctly, retry the UART test",13,10
- db "but first try one or more of the following:",13,10
- db 13,10
- db " 1. Remove any external devices (e.g. modems or serial mice)",13,10
- db " connected to the COM ports.",13,10
- db 13,10
- db " 2. Install a loopback plug on the COM port under test.",13,10
- db 13,10
- db " 3. Boot from a floppy disk you are sure installs no drivers on the COM ports.",13,10,"$"
-
- ConfusedIRQMsg db "WARNING: another port sharing IRQ "
- IrqPatch3 db "x or driver software",13,10
- db " is interfering with this test.",13,10,"$"
-
- DescList dw offset COM:code0
- dw offset com:code1
- dw offset com:code2
- dw offset com:code3
- dw offset com;code4
-
- ExpectedList dw 3f8h ; expected port address for COM1
- dw 2f8h ; COM2
- dw 3E8h ; COM3
- dw 2e8h ; COM4
-
- OldVect dd 0 ; CS:IP of current interrupt vector
-
- OldPIC db 0 ; old value of PIC interrupt enable reg.
- OldIER db 0 ; old value of Interrupt Enable Register
- OldMCR db 0 ; old value of Modem Control Register
- OldLCR db 0 ; old value for Line Control Register
- OldLSBDivisor db 0 ; old value of latch baud rate divisor
- OldMSBDivisor db 0 ; " MSB
- OldScr db 0 ; old value of Scratch register
- OldENH db 0 ; old value of Enhance register 1
-
-
- ComNo dw 0 ; 0=COM1: 1=COM2:
-
- Comaddr dw 0 ; 3F8=COM1: 2F8=COM2: 3E8=COM3: 2E8=COM4:
-
- IRQ db 0 ; 3 or 4, corresponds to int B or C.
-
- Vector db 0 ; B or C interrupt vector
-
- EventCount dw 0 ; counts how many interrupts. Should be one.
-
- data endS
-
- ;==============================================================
-
- com group code,data
-
- ASSUME CS:COM,DS:COM,ES:COM
- ORG 100H
- Start:
- Call Parse ; prepare the command line
- Call Analyse ; analyse the command line for drive letter
- mov bx,ComAddr ; hex port address for com port
- Call UartType ; return code in bx
- push bx
- Call DisplayUARTType ; message to describe type we found.
- Call CheckPort ; check if port is one expected
- Call CheckIRQ ; Check that IRQ is one expected
- ; This code does not work yet.
- pop bx
- mov al,bl
- mov ah,04ch ; exit to dos, errorlevel in AL
- int 21h
-
- Failed:
- lea dx,Copyrightmsg
- call say
- lea dx,usagemsg
- call say
- mov ax,4c05h ; exit back to DOS with error code 5
- int 21h
-
-
- ;==============================================================
-
- UARTTYPE Proc Near
-
- ; on entry BX is serial I/O port: e.g. 3F8
- ; On exit BX contains the serial port type
- ; This code is very similar to code in PC Magazine page 364
- ; May 26, 1992. I added two null checks and tighted up the code.
- ; 0=not present, and sets carry
- ; 1=8250
- ; 2=16450, old style 16550, 8250A
- ; 3=16550AF with FIFO queues
- ; 4=IBM type 3 serial port with DMA
- ; trashes bx,cx,dx
-
- test bx,bx
- jz isNullComm
- Call SaveChipState
- cli ; port might be in use, e.g. mouse
- ; attempt to do as little damage as possible.
- mov al,00000011b ; set up a vanilla n81 setting
- POKE LCR ; 3FB attempt to write to line control register
- PEEK DITTO ; see if it took
- sti
- cmp al,00000011b
- jne isNullComm ; no, must be no port at all.
- PEEK MCR ; 3FC modem control reg
- and al,11110011b ; disable serial interrupt
- ; Out-2 must be on for interrupts to happen
- ; out-1 does a reset
- ; Where is this documented?
- POKE DITTO
- cli
- mov al,55h ; see if scratch register exists
- POKE SCR
- PEEK DITTO ; see if 55 comes back.
- sti
- cmp al,55h
- jne is8250 ; 8250 has no scratch reg
-
- mov al,0aah ; just in case, try that again
- cli
- POKE DITTO
- PEEK DITTO
- sti
- cmp al,0aah
- jne is8250 ; 8250 has no scratch reg
-
- ; must be something more advanced than the 8250
-
- mov al,7 ; attempt to enable FIFOs
- cli
- POKE FIFO ; 3FA
- PEEK IIR ; 3FA interrupt id reg
- sti
- and al,0c0h ; strip out all but FIFO bits
- jz Is16450 ; all 0 if no FIFO.
-
- ; must be more advanced than the 16450
- cli
- PEEK ENH ; 83FB read enhanced register 1
- or al,01000000b ; enable DMA Xmit mode
- POKE DITTO
- PEEK IIR
- sti
- and al,0c0h ; mask all but FIFO ID
- cmp al,040h
- jne Is16550
-
- jmp IsIBMType3
-
-
- IsNullComm:
- mov bx,0
- stc
- ret
-
- Is8250:
- mov cx,1
- jmp UARTTypeDone
-
- Is16450:
- mov cx,2
- jmp UARTTypeDone
-
- Is16550:
- mov cx,3
- jmp UARTTypeDone
-
- IsIBMType3:
- mov cx,4
-
- UARTTypeDone:
-
- Call RestoreChipState
- mov bx,cx
- clc
- ret
-
- UARTTYPE EndP
-
- ;=============================================
-
- DisplayUARTType Proc Near
-
- ; on entry BX is the type code for the UART type.
- ; we display a message describing it.
- ; trash everything
-
- push bx
-
- mov ax,Comaddr ; get hex address
- call AsHex ; patch in the hex address to the
- ; output message.
- lea si,AsHexBuf
- lea di,HexPatch1
- movsw
- movsw
- mov ax,ComNo ; 0=COM1: 1=COM2:
- add al,'1'
- mov PortPatch1,al ; patch com port number in message.
- lea dx,PortMsg ; echo port number and address.
- call Say
-
- pop bx
- shl bx,1 ; index table of words
- mov dx,DescList[BX]
- Call Say ; display corresponding description
- ret
-
- DisplayUARTType EndP
-
- ;==============================================================
-
- CheckPort Proc Near
-
- ; check that ComPort is usual value for this ComNo.
- ; If not, print a warning message.
- ; Presume Comaddr has been calculated already.
- ; trash everything
-
- test Comaddr,-1
- jz UsingProperPort ; if not in use, don't count as error.
- mov bx,ComNo
- shl bx,1
- mov bx,ExpectedList[bx]
- ; expect comport #
- cmp bx,ComAddr
- je UsingProperPort
-
- ; Oops, this is not the port we would usually use
-
- mov ax,bx
- call AsHex ; patch in the hex address to the
- ; output message.
- lea si,AsHexBuf
- lea di,HexPatch2
- movsw
- movsw
- mov ax,ComNo ; 0=COM1: 1=COM2:
- add al,'1'
- mov PortPatch2,al ; patch com port number in message.
- lea dx,WrongPortMsg ; echo port number and address.
- call Say
-
- UsingProperPort:
- ret
-
- CheckPort EndP
-
- ;==============================================================
-
- SaveChipState Proc Near
-
- ; Save values of UART registers so we can restore later
-
- mov dx,PIC ; save state of PIC
- in al,dx
- mov OldPIC,al
-
- mov bx,ComAddr ; e.g 3F8
- PEEK MCR ; 3FC save current modem control reg.
- mov OldMCR,al
-
- PEEK IER ; 3F9 save current interrupt enable register
- mov OldIER,al
-
- PEEK LCR ; 3FB save current line control register
- mov OldLCR,al
-
- PEEK SCR ; 3FF save old scratch register
- mov oldSCR,al
-
- PEEK ENH ; 83FB save old enhanced reg1
- mov oldENH,al
-
- mov al,10000011b ; set up n81, access divisor
- POKE DITTO
- PEEK LSBDIV ; save old baud rate divisor
- mov OldLSBDivisor,al
- PEEK MSBDIV
- mov OldMSBDivisor,al
-
- mov al,OldLCR ; 3FB just save LCR, don't change it yet.
- POKE LCR
-
-
- ret
-
- SaveChipState EndP
-
- ;=============================================
-
- RestoreChipState Proc Near
-
- ; put all registers in chip back the way they were.
-
- cli ; restore PIC back the way it
- mov dx,PIC ; was. Non 3/4 IRQs may have legitimately
- in al,dx ; changed during our run. We don't put them
- and al,0e7h ; back, just irq 3/4.
- mov ah,OldPic ; 0=enabled 1=disabled
- and ah,018h
- or al,ah
- out dx,al
- sti
-
- mov bx,ComAddr ; e.g 3F8
- mov al,OldIER ; 3F9 restore interrupt enable register 3F9
- POKE IER
-
- mov al,OldMCR ; 3FC restore original modem control register 3FC
- POKE MCR
-
- mov al,oldSCR
- POKE SCR ; 3FF restore old scratch register
-
- mov al,oldENH
- POKE ENH ; 83FB restore old enhanced reg1
-
- mov al,10000011b ; set up n81, access divisor
- POKE LCR ; 3FB restore divisor
- mov al,OldLSBdivisor
- POKE LSBDIV
- mov al,OldMSBDivisor
- POKE MSBDIV
-
- mov al,OldLCR ; 3FB restore line status register
- POKE LCR
- ; we cannot directly restore the IIR
- ; but we can turn off the FIFO
- mov al,0
- POKE FIFO ; 3FA
-
- ret
-
- RestoreChipState EndP
-
- ;=============================================
-
- ;COMMENT √ ; this routine does not work yet. WHY???
- ; I have chewed on this for days!!!
-
- CheckIRQ Proc Near
-
- ; Check the that exactly one interrupt at the expected IRQ
-
- Call CalcIRQ ; figure out which IRQ should be used
- Call SetTrap ; trap interrupts from expected IRQ
- Call Trigger1Int ; Trigger 1 interrupt using loopback
- Call RestoreIRQ ; put trap back the way it was
- Call PatchIRQ ; patch expected IRQ # into error messages.
- cmp Eventcount,1 ; should see 1 int
- jb BadIRQ
- ja ConfusedIRQ
-
- ; Just right, saw 1 interrupt
- GoodIRQ:
- lea dx,GoodIRQMsg
- call Say
- ret
-
- BadIRQ:
- lea dx,BadIRQMsg
- call Say
- ret
-
- ConfusedIRQ:
- lea dx,ConfusedIRQMsg
- call Say
- ret
-
- CheckIRQ EndP
-
- ;==============================================================
-
- CalcIRQ Proc Near
-
- ; Calculate the IRQ 4 or 3 to match hex address
-
- mov ax,ComAddr
- lea di,Expectedlist ; scan list of legal port #s
- mov cx,4 ; to make sure it is in the list.
- repne scasw
- jne NoIrq
- ; ax still has the address.
- mov al,ah ; 3f8 2f8 3e8 2e8 -> 2 or 3
- sub ah,ah
- inc ax ; 3 -> 4 2 -> 3
- mov IRQ,al
- add al,8 ; 3->B 4->C
- mov Vector,al ; which interrupt vector,
- ; not same as IRQ
- clc
-
- ret
-
- NoIRQ: mov IRQ,0
- mov Vector,0
- stc
- ret
-
- CalcIRQ EndP
-
- ; =============================================
-
- PatchIRQ Proc Near
-
- ; Patch expected the IRQ number into various possible error messages.
-
- mov al,IRQ ; 3 or 4 binary
- add al,030h ; 3 or 4 ASCII
- mov IrqPatch1,al
- mov IrqPatch2,al
- mov IrqPatch3,al
- ret
-
- PatchIRQ EndP
-
- ; =============================================
-
- ASSUME DS:nothing,ES:nothing
-
- SetTrap Proc near
-
- ; Trap interrupts from the expected source irq 3 or 4.
-
- push DS
- push ES
- mov ah,35h
- mov al,Vector ; save old B/C vector
- int 21h ; result in ES:BX
- mov word ptr OldVect, bx
- mov word ptr OldVect+2, ES
- pop ES
- push CS
- pop DS
-
- lea dx,CS:IntHandler
- mov ah,25h
- mov al,Vector ; set up new B/C vector to point to our
- ; miniature handler
- int 21h
- pop DS
- ret
-
- SetTrap EndP
-
-
- ; =============================================
-
- ASSUME DS:NOTHING,ES:NOTHING
-
- IntHandler Proc Near
-
- ; Interrupt handler for irq 3 or 4 int B or C.
-
- ; ints are off right now
- push ax ; must not disturb ANYTHING!
- push bx
- push cx
- push dx
- inc CS:EventCount ; only CS: works,
- ; count how many interrupts.
- ; should be only one.
- mov al,20h
- out 20h,al ; send eoi command to PIC
- call Breath
-
- Call ClearPendingInterrupt
- sti
- pop dx
- pop cx
- pop bx
- pop ax
-
- iret
-
- IntHandler EndP
-
-
- ;=============================================
- ASSUME DS:COM,ES:COM
-
- Trigger1Int Proc Near
-
- ; Trigger one interrupt and count how many ints appeared at the
- ; expected interrupt.
-
-
- Call SaveChipState ; save current values of all regs we will wreck.
-
-
- mov al,10000011b ; set up n81, access divisor
- POKE LCR ; 3FB
- mov al,030h
- POKE LSBDIV ; set up 2400 baud
- mov al,0
- POKE MSBDIV
-
- mov al,00000011b ; set up n81, access regular regs
- POKE LCR ; 3FB
-
- cli ; Turn on ints 3 and 4 in the PIC
- mov dx,PIC
- in al,dx
- and al,0e7h ; 0=enabled 1=disabled.
- out dx,al
- sti
-
- mov al,0 ; disable any FIFOs
- POKE FIFO ; 3FA
-
- mov al,00000110b ; enable interrupts, just THR empty & overrun
- POKE IER ; 3F9 Some pending interrupt might trigger
-
- ; Loopback does not work. IBM does not let the PIC see the
- ; interrupts in loopback mode.
-
- mov al,00001000b ; out-1 does a reset of attached modem
- ; must clear
- ; out-2 enables interrupts
- ; turn off DTR and RTS, to reset
- ; any attached modem
-
- POKE MCR ; 3FC might generate an interrupt
- call BigBreath
-
- mov al,00001011b ; out-1 does a reset of attached modem
- ; must clear
- ; out-2 enables interrupts
- ; turn on DTR and RTS
-
- POKE MCR ; 3FC might generate an interrupt
- call BigBreath
-
- mov EventCount,0 ; clear interrupt counter
- sti ; ints should be on anyway.
- mov al,0 ; send a null character
- POKE THR ; Five things can happen:
- ; 1. device accepts the char
- ; 2. device keeps CTS low, so char
- ; never goes out. We never get an int.
- ; 3. device is powered off or missing.
- ; Then we get a line status int.
- ; 4. IRQ not set properly. We see no int.
- ; 5. Some other device is using same IRQ.
- ; We see multiple ints.
-
- Call BigBreath ; Wait long enough for interrupt to happen
-
- call ClearPendingInterrupt
- Call RestoreChipState
- ret
-
- Trigger1Int EndP
-
- ;=============================================
-
- ClearPendingInterrupt Proc Near
-
- ; If there is a pending interrupt, get it cleared
- ; See page 1-242 XT tech ref.
- ; trashes ax,bx,dx
- ; Called from Int handler. Cannot use DS:
-
- mov bx,CS:ComAddr ; e.g 3F8
-
- PEEK IIR ; 3FA read IIR to clear
- ; any modem transmitter holding empty interrupt
-
- PEEK RBR ; 3F8 read receive buffer register to clear
- ; any char in interrupt
-
- PEEK LSR ; e.g. 3FD read line status register to clear
- ; any parity interrupt
-
- PEEK MSR ; e.g. 3FE read modem status register to clear
- ; any modem status interrupt
- ret
-
- ClearPendingInterrupt EndP
-
- ;=============================================
-
- ASSUME DS:NOTHING,ES:NOTHING
-
- RestoreIRQ proc near
-
- ; Put the B/C vector back the way it was
-
- push DS
- mov dx,word ptr OldVect
- mov ax,word ptr OldVect+2
- mov DS,ax
- mov ah,25h
- mov al,Vector ; set B/C vector
- int 21h
- pop DS
- ret
-
- RestoreIRQ EndP
- ; end of commented out code
-
- ASSUME DS:COM,ES:COM
-
- ;=============================================
- ; C O M M A N D L I N E P A R S I N G R O U T I N E S
- ;=============================================
-
- MLeading PROC Near
-
- ; Remove leading blanks
- ; on entry ES:BX is addr of string, CX its length
- ; trims off any leading blanks, leaving result in BX CX
- ; length may also be 0 or 1, but not -ve
- ; If the entire string is blank the result is the null string
-
- mov di,bx
- mov al,20H ; AL = blank -- the search char
- jcxz mleading2 ; jump if null string
- repe scasb ; scan ES:DI forwards till hit non blank
- ; DI points just after it (wrap ok)
- ; cx IS ONE TOO SMALL, OR 0 IF NONE FOUND
- je mleading1 ; jump if entire string was blank
- inc cx ; CX is length of remainder of string
- mleading1:
- dec di ; DI points to non-blank
- mleading2:
- mov bx,di ; put address back
- ret
-
- MLeading ENDP
-
- ;========================================
-
- MTrailing PROC Near
-
- ; Remove trailing blanks.
- ; on entry ES:BX is addr of string, CX its length
- ; trims off any trailing blanks, leaving result in BX CX
- ; length may also be 0 or 1, but not -ve
- ; If the entire string is blank the result is the null string
-
- mov di,bx
- add di,cx ; calc addr last char in string
- dec di
- mov al,20H ; AL = blank -- the search char
- jcxz mtrailing1 ; jump if null string
- std
- repe scasb ; scan ES:DI backwards till hit non blank
- ; DI points just ahead of it (wrap ok)
- ; CX is one too small, or 0 if none found
- cld
- je mtrailing1 ; jump if whole string was blank
- inc cx
- mtrailing1:
- ret
-
- MTrailing ENDP
-
- ;========================================
-
- Parse PROC NEAR
- ; Parse the command line to remove lead/trail blanks from
- ; the single drive parameter and terminate it by 2 nulls.
- ; sample inputs
- ; UART COM1:
- ; UART COM2:
- ; UART
- ; ES: points to PSP
- ; When Done ES:BX points to start of string.
- ; String will be terminated by 2 nulls
- ; CX counts bytes in string exclusive of nulls
- ; counted string at HEX 80 PSP
- ; contains command line.
- ; Preceeded by unwanted spaces.
- ; possibly followed by unwanted spaces.
- ; currently missing a trailing null.
- xor ch,ch
- mov cl,es:[80H]
- mov bx,81H
- call Mleading ; get rid of leading blanks
- call MTrailing ; get rid of trailing blanks
- mov di,bx ; calc addr of byte just past end
- add di,cx
- mov word ptr ES:[di],0 ; plop in pair of nulls after string
- ret
-
- Parse ENDP
-
- ;======================================
- Analyse PROC NEAR
- ; analyses the command line allowing COM1: COM2:
- ; On entry ES:BX points to start of string.
- ; String will be terminated by 2 nulls
- ; CX counts bytes in string exclusive of nulls
- ; lead/trail spaces are gone.
- jcxz BadCmd ; was no command
- cmp cx,5 ; COM1: - must be 5 chars
- jne BadCmd
- mov al,ES:[bx+4]
- cmp al,':' ; make sure last char is :
- jne BadCmd
- mov al,ES:[bx+3]
- sub al,'1' ; '1'->0 '2'->1 '3'->2 '4'->3
- cmp al,3
- ja BadCmd ; allow only COM1: to COM4:
- mov Byte Ptr ComNo,AL
- push ES
- mov ax,BIOSDATA ; convert to port address
- mov es,ax
- ASSUME ES:BIOSDATA
- mov di,word Ptr ComNo
- shl di,1 ; address a table of words it low RAM
- mov ax,ES:BIOSComAddrs[di]
- ASSUME ES:COM
- pop ES
- mov ComAddr,ax
- AnalDone:
- RET
- BadCmd:
- Jmp Failed
-
- Analyse ENDP
-
- ;=============================================
-
- AsHex Proc Near
-
- ; calculates 4 digit (16 bits) hex number in AX
- ; get digits into place, don't worry about excess high order stuff.
- ; leaves result in AsHexBuf
-
- mov AsHexBuf+3,al
- mov cx,4
- shr al,cl
- mov AsHexBuf+2,al
- mov AsHexBuf+1,ah
- shr ah,cl
- mov AsHexbuf+0,ah
- lea si,AsHexBuf
- mov cx,4
- AsHexLoop:
- lodsb ; fix up each character in turn
- and al,0Fh
- cmp al,0Ah
- jle IsDigit
- add al,'A'-0ah
- jmp SaveDigit
- IsDigit:
- add al,'0'
- SaveDigit:
- mov [si-1],al ; lodsb incremented si already
- loop AsHexLoop
- ret
-
- Data segment
- AsHexBuf db '0000$'
- Data Ends
-
- AsHex EndP
-
- ;=============================================
- Say Proc Near
- ; on entry DX points to a string to display on screen
- MOV AH,9
- Int 21h
- ret
- Say EndP
-
- ;=======================================
-
- BigBreath Proc Near
-
- ; Wait a decent length of time for triggered interrupt to happen.
-
- push cx
- mov cx,20d ; nested wait loop
- wait1:
-
- push cx
- mov cx,60000d
- wait2:
- loop Wait2
- pop cx
-
- loop Wait1
- pop cx
- ret
-
- BigBreath EndP
-
- ;=======================================
-
- Breath Proc Near
-
- ; Take a breath between pokes to the UART chip to give it time to
- ; recover ready for next i/o command. JMP $+2 is a little too tight.
-
- push cx
- mov cx,10d
- wait3:
- loop Wait3
- pop cx
-
- ret
-
- Breath EndP
-
- ;=======================================
-
- CODE ends
- end start
-