home *** CD-ROM | disk | FTP | other *** search
- name asynch
- page 55,132
- title 'ASYNCH --- asynchronous driver'
- .lfcond
-
- ;
- ; Asynchronous Port Driver (COM1 or COM2)
- ; version 1.0 April 16, 1985
- ;
- ; Copyright (C) 1985 Ray Duncan
- ;
- ; To assemble, link, and convert this program into
- ; a BIN file, follow these steps:
- ;
- ; C>MASM ASYNCH;
- ; C>LINK ASYNCH;
- ; C>EXE2BIN ASYNCH.EXE ASYNCH.BIN
- ; C>DEL ASYNCH.EXE
- ;
- ; Ignore the message "Warning: no stack segment" from the Linker.
- ;
- ; Then add the line:
- ;
- ; DEVICE=ASYNCH.BIN
- ;
- ; to your CONFIG.SYS file.
- ;
-
- code segment public 'CODE'
-
- driver proc far
-
- assume cs:code,ds:code,es:code
-
- org 0
-
- comm_port equ 0 ;0=COM1, <>0=COM2
-
- if comm_port ;define physical port assignments
-
- ; COM2 port assignments
- comm_irqm equ 08h ; Mask for IRQ3
- comm_int equ 0bh
- comm_data equ 02f8h
- comm_ier equ 02f9h
- comm_lcr equ 02fbh
- comm_mcr equ 02fch
- comm_stat equ 02fdh
- else
- ; COM1 port assignments
- comm_irqm equ 10h ; Mask for IRQ4
- comm_int equ 0ch
- comm_data equ 03f8h
- comm_ier equ 03f9h
- comm_lcr equ 03fbh
- comm_mcr equ 03fch
- comm_stat equ 03fdh
- endif
-
- Max_Cmd equ 15 ; MS-DOS command code maximum
-
- In_Len equ 2048 ; length of ring buffer for reads
- Out_Len equ 2048 ; length of ring buffer for writes
-
- cr equ 0dh ; ASCII carriage return
- lf equ 0ah ; ASCII line feed
- eom equ '$' ; end of message signal
-
- page
- ;
- ; Device Driver Header
- ;
- Header dd -1 ;link to next device,-1= end of list
-
- dw 8000h ;attribute word
- ;bit 15=1 for character devices
-
- dw Strat ;device "Strategy" entry point
-
- dw Intr ;device "Intrrupt" entry point
-
- db 'ASYNCH1 ' ;char device name, 8 char, or
- ;if block device, no. of units
- ;in first byte followed by
- ;7 don't care bytes
-
- ;
- ; local variables for use by driver
- ;
- Rq_Ptr dd ? ; pointer to request header
- ; passed to Strat by BDOS
-
- Ident db cr,lf,lf
- db 'LMI Asynchronous Port Driver 1.0'
- db cr,lf
- db 'Copyright (c) 1985 '
- db 'Laboratory Microsystems Inc.'
- db cr,lf,lf,eom
-
- rcv_in dw 0 ; input ptr to read ring buffer
- rcv_out dw 0 ; output ptr to read ring buffer
-
- xmt_in dw 0 ; input ptr to write ring buffer
- xmt_out dw 0 ; output ptr to write ring buffer
-
- page
-
- ;
- ; MS-DOS Command Codes dispatch table
-
- ; The "Intr" routine uses this table and the Command Code
- ; supplied in the Request Header to transfer to the
- ; appropriate driver subroutine.
-
- Dispatch:
-
- dw Init ; 0 = init driver into system
- dw Media_Chk ; 1 = media check on blk dev
- dw Build_Bpb ; 2 = build BIOS param block
- dw Ioctl_Inp ; 3 = I/O ctrl read from dev
- dw Input ; 4 = normal destructive read
- dw Nd_Input ; 5 = non-destructive read,no wait
- dw Inp_Stat ; 6 = return current input status
- dw Inp_Flush ; 7 = flush device input buffers
- dw Output ; 8 = normal output to device
- dw Outp_Vfy ; 9 = output with verify
- dw Outp_Stat ; 10 = return current output status
- dw Outp_Flush ; 11 = flush output buffers
- dw Ioctl_Outp ; 12 = I/O control output
- dw Dev_Open ; 13 = device open (MS-DOS 3.x)
- dw Dev_Close ; 14 = device close (MS-DOS 3.x)
- dw Rem_Media ; 15 = removeable media (MS-DOS 3.x)
-
- page
- ;
- ; MS-DOS Request Header structure definition
- ;
- Request struc ; request header template structure
-
- Rlength db ? ; length of request header
- Unit db ? ; unit number for this request
- Command db ? ; request header's command code
- Status dw ? ; driver's return status word
- Reserve db 8 dup (?) ; reserved area
- Media db ? ; media descriptor byte
- Address dd ? ; memory address for transfer
- Count dw ? ; byte/sector count value
- Sector dw ? ; starting sector value
-
- Request ends ; end of request header template
-
- ;
- ; Status word is interpreted as follows:
- ;
- ; Bit(s) Significance
- ; 15 Error
- ; 10-14 Reserved
- ; 9 Busy
- ; 8 Done
- ; 0-7 Error code if bit 15=1
-
- ; Predefined BDOS error codes are:
- ;
- ; 0 Write protect violation
- ; 1 Unknown unit
- ; 2 Drive not ready
- ; 3 Unknown command
- ; 4 CRC error
- ; 5 Bad drive request structure length
- ; 6 Seek error
- ; 7 Unknown media
- ; 8 Sector not found
- ; 9 Printer out of paper
- ; 10 Write fault
- ; 11 Read fault
- ; 12 General failure
- ; 13-14 Reserved
- ; 15 Invalid disk change (MS-DOS 3.x)
- page
-
- ;
- ; Media descriptor byte is interpreted as follows
- ; if Non-IBM-Format bit is zero
- ;
- ; Bit(s) Significance
- ; 3-7 always set
- ; 2 1=removeable 0=not removeable
- ; 1 1=8 sector 0=not 8 sector
- ; 0 1=2 sided 0=not 2 sided
- ;
- ; Current valid DOS descriptor bytes, 5 1/4" disks
- ; 0F9H 2 sided 15 sector
- ; 0FCH 1 sided 9 sector
- ; 0FDH 2 sided 9 sector
- ; 0FEH 1 sided 8 sector
- ; 0FFH 2 sided 8 sector
- ;
- ; 0F8H (fixed disk)
-
- page
-
- ;
- ; this is the hardware interrupt handler for
- ; Asynch Communications Adaptor
- ;
-
- Svc_Int proc far ;interrupt service routine
- ;for asynch controller
-
- sti ;turn interrupts back on
- push ax ;save all necessary registers
- push bx
- push dx
- push ds
- mov ax,cs ;make local data addressable
- mov ds,ax
- call Recv ;receive a character
- cli ;disable interrupts
- ;for clean exit
- mov al,20h ;send EOI to 8259
- out 20h,al
- pop ds ;restore all registers
- pop dx
- pop bx
- pop ax
- iret ;and exit handler
-
- Svc_Int endp
-
- page
- ;
- ; This is the input interrupt driver.
- ; Check for RDA status on interrupt,
- ; if RDA = True then input character
- ; Called on each interrupt.
- ;
- Recv proc near ;assumes CS = DS
-
- mov dx,comm_stat ;read status
- in al,dx
- and al,1 ;RDA ?
- jz Recv2 ;no, jump
- mov dx,comm_data
- in al,dx ;read this character
- cli ;clear interrupts for
- ;pointer manipulation
- mov bx,rcv_in ;get buffer pointer
- ;store this character
- mov byte ptr [In_Buf+bx],al
- inc bx ;bump pointer
- cmp bx,In_Len ;time for wrap?
- jne Recv1 ;no,jump
- xor bx,bx ;yes,reset pointer
- Recv1: mov rcv_in,bx ;store back updated pointer
- sti ;unmask interrupts
- Recv2: ret
-
- Recv endp
-
- page
- ;
- ; This is the interrupt output driver.
- ; Check for TBE status on interrupt, if TBE = True
- ; then transmit another character if any waiting.
- ; Called by Command Codes 8 & 9 to start I/O,
- ; and will be called on interrupt in final version.
- ;
- Xmit proc near ;assumes CS = DS
-
- mov dx,comm_stat ;read status
- in al,dx
- and al,20h ;TBE?
- jz Xmit9 ;no, jump
- mov bx,xmt_out ;any characters waiting
- cmp bx,xmt_in ;in output buffer?
- je Xmit9 ;no, jump
- mov al,[bx+Out_Buf] ;yes, get next char
- inc bx
- cmp bx,Out_Len ;time to wrap?
- jne Xmit1 ;no
- xor bx,bx ;yes,reset ring buffer ptr
- Xmit1:
- mov xmt_out,bx ;store updated pointer
- mov dx,comm_data ;transmit this char.
- out dx,al
- Xmit9: ret
-
- Xmit endp
-
- page
-
- ; Device Driver "Strategy Routine"
-
- ; Each time a request is made for this device, the BDOS
- ; first calls "Strategy routine", then immediately calls
- ; the "Interrupt routine".
-
- ; The Strategy routine is passed the address of the
- ; Request Header in ES:BX, which it saves in a local
- ; variable and then returns to BDOS.
-
- Strat proc far
- ; save address of Request Header
- mov word ptr cs:[Rq_Ptr],bx
- mov word ptr cs:[Rq_Ptr+2],es
-
- ret ; back to BDOS
-
- Strat endp
-
- page
-
-
- ; Device Driver "Interrupt Routine"
-
- ; This entry point is called by the BDOS immediately after
- ; the call to the "Strategy Routine", which saved the long
- ; address of the Request Header in the local variable "Rq_Ptr".
-
- ; The "Interrupt Routine" uses the Command Code passed in
- ; the Request Header to transfer to the appropriate device
- ; handling routine. Each command code routine is responsible
- ; for any necessary return information into the Request Header,
- ; then transfers to Error or Exit to set the Return Status code.
-
- Intr proc far
-
- push ax ; save general registers
- push bx
- push cx
- push dx
- push ds
- push es
- push di
- push si
- push bp
-
- push cs ; make local data addressable
- pop ds
-
- les di,[Rq_Ptr] ; ES:DI = Request Header
-
- ; get BX = Command Code
- mov bl,es:[di.Command]
- xor bh,bh
- cmp bx,Max_Cmd ; make sure its legal
- jg Unk_Command ; too big, exit with error code
- shl bx,1 ; form index to Dispatch table
- ; and branch to driver routine
- jmp word ptr [bx+Dispatch]
-
- page
-
-
- ; General collection of exit points for the driver routines.
-
-
- Unk_Command: ; Come here if Command Code > 12
- mov al,3 ; Sets "Unknown Command" error
- ; code and "Done" bit.
-
- Error: ; Transfer here with AL = error code.
- mov ah,81h ; Sets "Error" and "Done" bits.
- jmp Exit
-
- Done: mov ah,1 ; Come here if I/O complete and
- ; no error, sets "Done" bit only.
-
-
- Exit: ; General purpose exit point.
- ; Transfer here with AX =
- ; Return Status word to be
- ; placed into Request Header.
-
- lds bx,cs:[Rq_Ptr] ; set status
- mov ds:[bx.Status],ax
-
- pop bp ;restore general registers
- pop si
- pop di
- pop es
- pop ds
- pop dx
- pop cx
- pop bx
- pop ax
- ret ; back to BDOS
-
- page
-
-
- ; MS-DOS Command Code # 1 Media Check
-
- ; Block devices only. Should be a NOP for character devices.
- ;
- ; This routine is called first by BDOS for a block device transfer,
- ; passing current media descriptor byte at Request Header +
- ;
- ; Media Check routine sets status word and in addition passes back
- ; return byte at Request Header + 14 as follows:
-
- ; -1 Media has been changed
- ; 0 Don't know if media changed
- ; 1 Media has not been changed
- ;
- ; If driver can return 1 or -1, performance is improved because
- ; MS-DOS does not need to reread the FAT for each directory access.
-
-
- Media_Chk:
-
- jmp Done
-
- page
-
- ;
- ; MS-DOS Command Code # 2 Build BIOS Parameter Block
- ;
- ; Block devices only. Should be a NOP for character devices.
- ;
- ; This routine is called by MS-DOS when Media-Changed code is
- ; returned by Media Check routine, or if Not Sure code is returned
- ; and there are no dirty buffers.
- ;
- ; Build BPB call receives pointer to one-sector buffer in Address
- ; Field of Request Header (offset 14). If "Non-IBM-Format" bit
- ; in attribute word is zero, the buffer contains the first sector
- ; of the FAT including the media identification byte and should not
- ; be altered by the driver. If the "Non-IBM-Format" bit is set,
- ; the buffer may be used as scratch space.
- ;
- ; The Build BPB routine sets status and returns a DWORD pointer to
- ; the new Bios Parameter Block at Request Header + 18.
- ;
-
- Build_Bpb:
-
- jmp Done
-
- page
-
- ;
- ; MS-DOS Command Code # 3 I/O Control Read from device
- ;
- ; Only called if IOCTL bit set in Device Header Attribute word.
- ;
- ; Called with:
- ;
- ; Request Header + 13 BYTE Media descriptor byte from DPB
- ; Request Header + 14 DWORD Transfer address
- ; Request Header + 18 WORD byte/sector count
- ; Request Header + 20 WORD starting sector no. (block dev.)
- ;
- ; Returns the Return Status word set appropriately, and
- ; Request Header + 18 WORD actual bytes or sectors transferred
- ;
- ; No error check is performed on IOCTL I/O calls.
-
- Ioctl_Inp:
-
- jmp Done
-
- page
-
- ;
- ; MS-DOS Command Code # 4 Read from device
- ;
- ; Called with
- ;
- ; Request Header + 13 BYTE Media descriptor byte from DPB
- ; Request Header + 14 DWORD Transfer address
- ; Request Header + 18 WORD byte/sector count
- ; Request Header + 20 WORD starting sector no. (block dev.)
- ;
- ; Returns the Return Status word set appropriately, and
- ; Request Header + 18 WORD actual bytes or sectors transferred
-
- Input:
-
- mov si,rcv_out ;receive buffer output pointer
- cmp si,rcv_in ;compare to buffer input ptr
- jne Input1 ;something is in buffer
- ;set characters xfer'd = 0
- mov word ptr es:[di.Count],0
- jmp Done ;go set Done flag
-
- Input1:
- xor dx,dx ;set chars xferd count=0
- ;get requested transfer count
- mov cx,word ptr es:[di.Count]
- ;given DS:SI = addr input buffer
- ;set ES:DI = addr user's buffer
- push word ptr es:[di.Address]
- push word ptr es:[di.Address+2]
- pop es
- pop di
-
- Input2: ;transfer one character
- mov al,byte ptr ds:[si+In_Buf]
- mov byte ptr es:[di],al
- inc si
- inc di
- inc dx ;count characters given to user
- cmp si,In_Len ;buffer pointer wrap?
- jne Input3 ;no
- xor si,si ;yes
-
- Input3: cmp si,rcv_in ;input buffer exhausted?
- je Input4 ;yes, user got all he can get
- cmp dx,cx ;user got max requested?
- jne Input2 ;not yet
-
- Input4: mov rcv_out,si ;update buffer out pointer
- les di,cs:[Rq_Ptr] ;let ES:DI = Request Header
- ;store length actually transferred
- mov word ptr es:[di.Count],dx
- jmp Done ;go set Done & No Error flags
-
- page
-
- ;
- ; MS-DOS Command Code # 5 Non-destructive Read from Device
- ;
- ; Character devices only.
- ;
- ; If Input Status request returns Busy bit=0 (characters
- ; waiting), the next character that would be read is returned
- ; at Request Header + 13. This character is not removed from
- ; the Input Buffer. This basically provides the capability to
- ; "look-ahead" by one character.
-
- Nd_Input:
-
- mov bx,rcv_out
- cmp bx,rcv_in
- je Nd_Input1 ;jump, nothing in buffer
-
- ;something in read buffer,
- ;fetch first waiting char
- mov al,byte ptr [bx+In_Buf]
- jmp Nd_Input2
-
- Nd_Input1: ;nothing in read buffer,
- mov al,0 ;return a null character
-
- Nd_Input2: ;put char into Request Header
- mov byte ptr es:[di+13],al
- jmp done ;set Done status, no error
-
- page
-
- ;
- ; MS-DOS Command Code # 6 Return current device input status
- ;
- ; Character devices only.
- ;
- ; Sets the Returned Status word:
- ; Done bit = 1
- ; Busy bit = 1 read request would go to physical device
- ; = 0 characters already in device buffer, read request
- ; would return quickly.
- ;
- ; MS-DOS assumes all character devices have type-ahead buffer.
- ; If device does not have type-ahead buffer, should always
- ; return Busy bit=0 so MS-DOS will not hang.
-
- Inp_Stat:
-
- mov ax,rcv_in ;anything in read buffer?
- cmp ax,rcv_out
- je Inp_Stat1 ;no,jump
- jmp Done ;yes, let busy bit=0
-
- Inp_Stat1:
- mov ax,300h ;request goes to device
- jmp Exit ;so let busy bit=1
-
- page
-
- ;
- ; MS-DOS Command Code # 7 Flush device input buffers
- ;
- ; Character devices only.
- ;
- ; Terminate all pending requests, i.e. the Input buffer is
- ; emptied.
-
- Inp_Flush:
-
- cli ; block interrupts
- mov rcv_in,0 ; reset buffer pointers
- mov rcv_out,0
- sti ; restore interrupts
- jmp Done
-
- page
-
- ;
- ; MS-DOS Command Code # 8 Write to device
- ;
- ; Called with
- ;
- ; Request Header + 13 BYTE Media descriptor byte from DPB
- ; Request Header + 14 DWORD Transfer address
- ; Request Header + 18 WORD byte/sector count
- ; Request Header + 20 WORD starting sector no. (block dev.)
- ;
- ; Returns the Return Status word set appropriately, and
- ; Request Header + 18 WORD actual bytes or sectors transferred
-
- Output:
-
- ;DS:SI = user's data address
- mov si,word ptr es:[di.Address]
- mov ds,word ptr es:[di.Address+2]
- ;CX = length of user's data
- mov cx,word ptr es:[di.Count]
- jcxz Output3 ;exit if length=0
-
- mov di,cs:xmt_in ;ES:DI = output buffer address
- push cs
- pop es
-
- Output1:
- mov al,byte ptr ds:[si]
- mov byte ptr es:[di+Out_Buf],al
- inc si
- inc di
- cmp di,Out_Len ;buffer pointer wrap?
- jne Output2 ;no
- xor di,di ;reset output buffer pointer
-
- Output2:
- loop Output1 ;loop until all string moved
- mov cs:xmt_in,di ;store updated buffer input ptr
-
- Output3:
- mov ax,cs ;make buffers addressable for
- mov ds,ax ;XMIT routine,
- Output4:
- mov ax,xmt_in
- cmp ax,xmt_out
- je Output5
- call Xmit ;transmit one character
- jmp Output4
- Output5:
- jmp Done ;go set Done & No Error flags
-
- page
-
- ;
- ; MS-DOS Command Code # 9 Write with verify to device
- ;
- ; Called with
- ;
- ; Request Header + 13 BYTE Media descriptor byte from DPB
- ; Request Header + 14 DWORD Transfer address
- ; Request Header + 18 WORD byte/sector count
- ; Request Header + 20 WORD starting sector no. (block dev.)
- ;
- ; Returns the Return Status word set appropriately, and
- ; Request Header + 18 WORD actual bytes or sectors transferred
-
- Outp_Vfy:
-
- jmp Output
-
- page
-
- ;
- ; MS-DOS Command Code # 10 Return device output status
- ;
- ; Character devices only.
- ;
- ; Sets the Returned Status word:
- ; Done bit = 1
- ; Busy bit = 1 write request would wait for completion of
- ; current request
- ; = 0 device idle, write request would start immediately.
- ;
-
- Outp_Stat:
-
- ; always return Not Busy for now
- ; *** later should return Busy if
- ; transmit buffer is full ***
- jmp Done
-
- page
-
- ;
- ; MS-DOS Command Code # 11 Flush output buffers
- ;
- ; Character devices only.
- ;
- ; Terminate pending requests. The output buffer is emptied.
-
- Outp_Flush:
-
- cli ; block interrupts
- mov xmt_in,0 ; reset buffer pointers
- mov xmt_out,0
- sti ; re-enable interrupts
- jmp Done
-
- page
-
- ;
- ; MS-DOS Command Code # 12 I/O Control write to device
- ;
- ; Only called if IOCTL bit in Device Header Attribute word is set.
- ;
- ; Called with
- ;
- ; Request Header + 13 BYTE Media descriptor byte from DPB
- ; Request Header + 14 DWORD Transfer address
- ; Request Header + 18 WORD byte/sector count
- ; Request Header + 20 WORD starting sector no. (block dev.)
- ;
- ; Returns the Return Status word set appropriately, and
- ; Request Header + 18 WORD actual bytes or sectors transferred
- ;
- ; No error check is performed on IOCTL calls.
-
- Ioctl_Outp:
-
- jmp Done
-
- page
-
- ;
- ; MS-DOS Command Code # 13 Device Open
- ;
- ; MS-DOS version 3.0 and above only.
- ; Only called if OPEN/CLOSE/RM bit set in Attribute word.
- ; May be used to manage local buffering. Reference count
- ; is incremented keeping track of number of open files on
- ; the device. On character devices can be used to send
- ; device initialization string, which can be set by IOCTL
- ; Write. Note that CON AUX and PRN devices are always open.
- ;
- ; Returns the Return Status word set to "Done.
- ;
- Dev_Open:
-
- jmp Done
-
- page
-
- ;
- ; MS-DOS Command Code # 14 Device Close
- ;
- ; MS-DOS version 3.0 and above only.
- ; Only called if OPEN/CLOSE/RM bit set in Attribute word.
- ; May be used to manage local buffering. Reference count
- ; is decremented keeping track of number of open files on
- ; the device; when count reaches zero all files have been closed
- ; and the driver should flush buffers as user may change disks.
- ; On character devices can be used to send device post-I/O
- ; string such as a form feed, which can be set by IOCTL
- ; Write. Note that CON AUX and PRN devices are never closed.
- ;
- ; Returns the Return Status word set to "Done".
- ;
- Dev_Close:
-
- jmp Done
-
- page
-
- ;
- ; MS-DOS Command Code # 15 Removeable Media
- ;
- ; MS-DOS version 3.0 and above only.
- ; Only called if OPEN/CLOSE/RM bit set in Attribute word
- ; and device type is block.
- ;
- ; Returns the Return Status word set to "Done" and
- ; Busy bit = 1 if media is non-removable.
- ; = 0 if media is removable.
- ;
- Rem_Media:
-
- jmp Error
-
- page
-
- ; This initialization code for the driver is called only
- ; once when the driver is loaded. It returns its own
- ; address to the DOS as the start of free memory after the
- ; driver, so that the memory occupied by INIT will be
- ; reclaimed after it is finished with its work. If it
- ; is a block device driver it must also return the address of
- ; the Bios Parameter Block pointer array; if all units are the
- ; same all pointers can point to the same BPB.
- ;
- ; Only MS-DOS services 01-0CH and 30H can be called
- ; by the INIT code.
- ;
- ; Called with:
- ;
- ; Request Header + 18 DWORD pointer to the character after the "="
- ; on the CONFIG.SYS line that loaded
- ; driver; this information is read only.
- ; 22 BYTE drive letter for first unit of a
- ; block driver (0=A 1=B etc)
- ;
- ; Returns:
- ;
- ; Request Header + 13 BYTE Number of units (block devices only)
- ; + 14 DWORD address of first free memory above driver
- ; + 18 DWORD BPB pointer array (block devices only)
- ;
-
- Init: ; MS-DOS Command Code # 0
- ; initialize device driver
-
- push es ; push Request Header addr
- push di
-
- mov ah,9 ; print sign-on message
- mov dx,offset Ident
- int 21h
-
- pop di ; restore Request Header addr
- pop es
-
- ; set addr of interrupt handler
- push ds
- xor ax,ax
- mov ds,ax
- mov bx,comm_int*4
- mov word ptr [bx],offset Svc_Int
- mov word ptr [bx+2],cs
- pop ds
-
- mov dx,comm_lcr ;make sure DLAB is off
- in al,dx
- and al,07fh
- out dx,al
-
- mov dx,comm_mcr ;modem controller DTR, RTS,
- mov al,0bh ;and OUT2 to enable interrupts.
- out dx,al
-
- mov dx,comm_ier ;enable interrupts for TBE
- mov al,1 ;and RDA on asynch controller.
- out dx,al
-
- in al,21h ;8259 int mask register
- ;Reset IRQ3 or IRQ4 mask
- and al,not comm_irqm
- out 21h,al
-
- ; set first usable memory addr.
- mov word ptr es:[di.Address],offset End_Buf
- mov word ptr es:[di.Address+2],cs
-
- jmp Done
-
-
- Intr endp
-
-
- Driver endp
-
-
- In_Buf db In_Len dup (?)
-
- Out_Buf db Out_Len dup (?)
-
- End_Buf equ $
-
-
- code ends
-
- end