home *** CD-ROM | disk | FTP | other *** search
- version equ 1
- ;History:697,1
-
- include defs.asm
-
- ; Copyright, 1988-1992, Russell Nelson, Crynwr Software
-
- ; 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
-
- org 2ch
- phd_env label word
-
- org 5ch
- phd_fcb1 label byte
-
- org 6ch
- phd_fcb2 label byte
-
- org 80h
- phd_dioa label byte
-
- org 100h
- start:
- jmp start_1
-
- stack label byte
-
- comment /
-
- Plan:
-
- Keep a circular queue of events. The size of the queue is a settable
- parameter. Discard events that fall off the end. Remember how many events
- were discarded. Remember when the events occurred.
-
- Type of events to remember:
- calls to the packet driver
- upcalls to the receiver handler (both kinds)
-
- /
-
- ; In addition to the function numbers specified in the FTP Software
- ; packet driver spec, the following pseudo-functions are defined:
-
- EVENT_RECEIVE equ 255 ;receiver upcall.
-
- event_struc struc
- event_length dw ? ;length of this event.
- event_function db ? ;the event function number.
- event_time dw ?,? ;timer tick at the time of the call.
- event_error db ? ;set to value of dh after the SWI.
- event_struc ends
-
- di_struc struc
- db (size event_struc) dup (?)
- di_version dw ?
- di_class db ?
- di_type dw ?
- di_number db ?
- di_basic db ?
- di_struc ends
-
- at_struc struc
- db (size event_struc) dup (?)
- at_if_class db ?
- at_if_type dw ?
- at_if_number db ?
- at_typelen dw ?
- at_handle dw ?
- at_struc ends
-
- handle_struc struc
- db (size event_struc) dup (?)
- event_handle dw ?
- handle_struc ends
-
- ga_struc struc
- db (size event_struc) dup (?)
- ga_handle dw ?
- ga_length dw ?
- ga_struc ends
-
- srm_struc struc
- db (size event_struc) dup (?)
- srm_mode dw ?
- srm_handle dw ?
- srm_struc ends
-
- queue_length dw 10000,? ;length of the queue.
- queue_tail dw ? ;points after the last item in the queue.
- queue_ptr dw ? ;points to the new item in the queue.
- queue_head dw ? ;points to the first item in the queue.
- queue_end dw ? ;points to the end of the queue, but
- ;there is room for one more event after
- ;this one.
-
- entry_point db ?,0,0,0
-
- parm dw 0
- parm2 dw their_dioa,?
- parm3 dw phd_fcb1,?
- parm4 dw phd_fcb2,?
-
- comspec_env_str db "COMSPEC="
- comspec_env_len equ $-comspec_env_str
-
- program db 64 dup(?)
- their_dioa db 0,0dh,128-2 dup(?)
-
- saved_ax label word
- saved_al db ?
- saved_ah db ?
- saved_bx dw ?
- saved_ds dw ?
- saved_f dw ?
-
- functions label word
- dw f_driver_info ;function 1
- dw f_access_type
- dw f_release_type
- dw f_send_pkt
- dw f_terminate
- dw f_get_address
- dw f_reset_interface ;function 7
- dw f_set_rcv_mode ;function 20
- dw f_get_rcv_mode
- dw f_set_multicast_list
- dw f_get_multicast_list
- dw f_get_statistics
- dw f_set_address ;function 25
-
- their_isr dd ?
-
- our_isr:
- jmp our_isr_0 ;the required signature.
- db 'PKT DRVR',0
-
- our_isr_0:
- assume ds:nothing
- mov saved_ds,ds
- mov saved_bx,bx
- mov saved_ax,ax
- cld
-
- mov bx,sp
- mov bx,ss:[bx+4] ;get the original flags.
- mov saved_f,bx
-
-
- mov bx,cs ;set up ds.
- mov ds,bx
- assume ds:code
-
- ;the following code runs with ax, bx, ds, and flags saved in save_*.
- ;otherwise, all the registers are the same as those we were called with.
-
- mov bl,ah ;jump to the correct function.
- mov bh,0
- cmp bx,7 ;highest function is 7.
- jbe our_isr_3
- cmp bx,20
- jb our_isr_bad
- cmp bx,25
- ja our_isr_bad
- sub bx,20-7-1 ;map 20 right after 7.
- our_isr_3:
- add bx,bx ;*2
- jmp functions-2[bx] ;table starts at 1.
-
- our_isr_bad:
- call do_their_isr
- jmp our_isr_done
-
- f_driver_info:
- mov bx,(size di_struc)
- call queue_advance
- call do_their_isr
- jc f_driver_info_1
-
- mov ax,saved_bx
- mov [bx].di_version,ax
- mov [bx].di_class,ch
- mov [bx].di_type,dx
- mov [bx].di_number,cl
- mov al,saved_al
- mov [bx].di_basic,al
- ;we ignore the name -- too much work.
- f_driver_info_1:
- jmp our_isr_done
-
- f_get_statistics:
- ;strictly speaking, we should remember the statistics, but I'm not going to now.
- f_terminate:
- f_reset_interface:
- f_release_type:
- f_get_rcv_mode:
- mov bx,(size handle_struc)
- call queue_advance
- mov ax,saved_bx
- mov [bx].event_handle,ax
- call do_their_isr
- jmp our_isr_done
-
- f_access_type:
- mov bx,(size at_struc)
- call queue_advance
- mov al,saved_al
- mov [bx].at_if_class,al
- mov ax,saved_bx
- mov [bx].at_if_type,ax
- mov [bx].at_if_number,dl
- mov [bx].at_typelen,cx
- mov their_recv.segm,es
- mov their_recv.offs,di
- mov ax,cs ;and stick our receiver in.
- mov es,ax
- mov di,offset our_recv
- call do_their_isr
- jc f_access_type_1
- mov ax,saved_ax
- mov [bx].at_handle,ax
- f_access_type_1:
- les di,their_recv ;now restore ds and si.
- jmp our_isr_done
-
-
- f_send_pkt:
- mov bx,(size event_struc)
- add bx,cx
- call queue_advance
- ;make a copy of their packet.
- push cx
- push si
- push di
- push ds
- push es
- lea di,[bx] + (size event_struc)
- mov ax,cs
- mov es,ax
- mov ds,saved_ds
- rep movsb
- pop es
- pop ds
- pop di
- pop si
- pop cx
- call do_their_isr
- jmp our_isr_done
-
- f_get_address:
- mov bx,(size ga_struc)
- add bx,cx
- call queue_advance
- mov ax,saved_bx ;save their handle
- mov [bx].ga_handle,ax
- call do_their_isr
- jc f_get_address_1
- ;make a copy of their address.
- mov [bx].ga_length,cx ;we need to save this because it
- ;might be less than the total allocated.
- push cx
- push si
- push di
- push ds
- push es
- mov si,di ;get es:di into ds:si
- mov ax,es
- mov ds,ax
- lea di,[bx] + (size ga_struc) ;get our pointer into es:di.
- mov ax,cs
- mov es,ax
- rep movsb
- pop es
- pop ds
- pop di
- pop si
- pop cx
- f_get_address_1:
- jmp our_isr_done
-
-
- f_set_rcv_mode:
- mov bx,(size srm_struc)
- add bx,2
- call queue_advance
- mov ax,saved_bx ;save their handle.
- mov [bx].srm_handle,ax
- mov [bx].srm_mode,cx ;save their mode.
- call do_their_isr
- jmp our_isr_done
-
- f_set_multicast_list:
- f_get_multicast_list:
- f_set_address:
- mov bx,(size event_struc)
- call queue_advance
- call do_their_isr
-
- our_isr_done:
- push saved_f ;restore their flags, see [2]
- popf
-
- mov ax,saved_ax
- mov bx,saved_bx
- mov ds,saved_ds ;restore the two registers we destroyed.
- assume ds:nothing
-
- retf 2 ;return, popping their old flags, [2].
- assume ds:code
-
-
- ;do_their_isr executes their isr with the original registers.
- ;called with all their registers except f, ds, and bx.
- ;exits with all their registers except ds, ax, and bx. bx is queue_ptr
- do_their_isr:
-
- ;setup their context.
- mov ax,saved_f ;restore their flags, see [1]
- and ax,not 200h ;clear the interrupt flag, as required
- push ax ; when faking an interrupt.
- mov ax,saved_ax
- mov bx,saved_bx
- mov ds,saved_ds ;restore the two registers we destroyed.
- assume ds:nothing
-
- ; [1] we pushed the flags earlier.
- call their_isr ;now fake their interrupt.
-
- ;save their context.
- mov saved_ax,ax ;save the new registers.
- mov saved_bx,bx
- mov saved_ds,ds
- mov ax,cs ;set up a pointer to the next event.
- mov ds,ax
- assume ds:code
- pushf ;save the new flags.
- pop ax
- and saved_f,200h ;merge the interrupt flag in saved_f
- or saved_f,ax ; with the new flags.
-
- ;remember whether it succeeded or not.
- mov bx,queue_ptr
- mov [bx].event_error,NO_ERROR ;assume that all was okay.
- jnc our_isr_1
- mov [bx].event_error,dh ;it wasn't.
- our_isr_1:
- ret
-
-
- their_recv dd ?
-
- our_recv:
- assume ds:nothing
- mov saved_ds,ds
- mov saved_bx,bx
- mov saved_ax,ax
- cld
-
- mov bx,cs ;set up ds.
- mov ds,bx
- assume ds:code
-
- or ax,ax ;first call or second?
- je our_recv_first
-
- mov bx,(size handle_struc)
- add bx,cx
- call queue_advance
- mov [bx].event_function,EVENT_RECEIVE ;not a real function.
- mov [bx].event_error,0 ;no errors possible.
- mov ax,saved_bx
- mov [bx].event_handle,ax ;remember which handle it was.
-
- push cx
- push si
- push di
- push ds
- push es
- lea di,[bx] + (size handle_struc)
- mov ax,cs
- mov es,ax
- mov ds,saved_ds
- rep movsb
- pop es
- pop ds
- pop di
- pop si
- pop cx
-
- jmp short our_recv_done
- our_recv_first:
- ;ignore the first upcall.
- our_recv_done:
- mov ax,saved_ax
- mov bx,saved_bx
- mov ds,saved_ds ;restore the two registers we destroyed.
- assume ds:nothing
-
- jmp their_recv
- assume ds:code
-
-
- queue_advance:
- ;enter with bx = number of bytes that we require in the queue.
- ;exit with bx,queue_ptr set to a pointer to our entry.
- ;preserve everything but ds, bx, and the flags.
- queue_advance_3:
- mov ax,queue_tail
- add ax,bx
- cmp ax,queue_head ;if we don't overlap the head, we're
- jbe queue_advance_1 ; okay.
-
- xchg bx,queue_head ;get queue_head and save bx.
- add bx,[bx].event_length
- cmp bx,queue_end ;see if we hit the end.
- xchg queue_head,bx ;store queue_head and restore bx.
- jb queue_advance_3 ;if we're less than the end, continue.
- ;we have to wrap here.
- push bx
- mov bx,queue_tail
- mov ax,queue_end ;make an event length that's too large.
- sub ax,offset queue_begin
- mov [bx].event_length,ax
- mov bx,offset queue_begin ;and restart from the beginning.
- mov queue_tail,bx ;ensure that we nuke some more.
- mov queue_head,bx
- pop bx
- jmp queue_advance_3
- queue_advance_1:
- xchg ax,queue_tail ;update the tail and get this ptr.
- mov queue_ptr,ax ;save this pointer.
- xchg ax,bx
- mov [bx].event_length,ax ;store the length of this entry here.
-
- mov ah,saved_ah ;store their function value.
- mov [bx].event_function,ah
-
- ;remember when it happened.
- push dx
- push ds
- mov ax,40h
- mov ds,ax
- mov ax,ds:6ch ;get the timer tick count.
- mov dx,ds:6eh
- pop ds
- mov [bx].event_time+0,ax
- mov [bx].event_time+2,dx
- pop dx
-
- ret
-
-
- copyleft_msg label byte
- db "Packet driver tracer version ",'0'+(majver / 10),'0'+(majver mod 10),'.',version+'0'," copyright 1988-92, Russell Nelson.",CR,LF
- db "This program is free software; see the file COPYING for details.",CR,LF
- db "NO WARRANTY; see the file COPYING for details.",CR,LF
- crlf_msg db CR,LF,'$'
-
- entry_point_name db "Packet interrupt number ",'$'
- buffer_size_name db "Buffer size ",'$'
-
- before_exec_msg db "Now run your network software and type 'exit' when finished",CR,LF,'$'
- run_dump_msg db "Now run 'dump' to interpret 'trace.out'",CR,LF,'$'
-
- disk_full_msg db "Disk Full!",'$'
-
- already_msg db CR,LF,"There is no packet driver at ",'$'
- packet_int_msg db CR,LF
- db "Error: <packet_int_no> should be in the range 0x60 to 0x80"
- db '$'
-
- usage_msg db "usage: trace entry_point <buffer_size>",'$'
-
- queue_error_msg db "Error: <buffer_size> should be larger than 2000 and less than 64000",'$'
-
- trace_out db "TRACE.OUT",0 ;filename that we write the dump to.
-
- usage_error:
- mov dx,offset usage_msg
- error:
- mov ah,9
- int 21h
- int 20h
-
- already_error:
- mov dx,offset already_msg
- mov di,offset entry_point
- call print_number
- int 20h
-
- start_1:
- mov sp,offset stack
-
- mov dx,offset copyleft_msg
- mov ah,9
- int 21h
-
- mov si,offset phd_dioa+1
- cmp byte ptr [si],CR ;end of line?
- je usage_error
-
- mov di,offset entry_point ;parse the packet interrupt number
- call get_number ; for them.
-
- mov di,offset queue_length ;parse the packet interrupt number
- call get_number ; for them.
-
- cmp byte ptr [si],CR ;end of line?
- jne usage_error
-
- cmp queue_length+2,0
- jne start_3
- cmp queue_length,2000
- ja start_2
- start_3:
- mov dx,offset queue_error_msg
- jmp error
- start_2:
-
- mov di,offset entry_point ;parse the packet interrupt number
- mov dx,offset entry_point_name
- call print_number ; for them.
-
- mov di,offset queue_length ;parse the packet interrupt number
- mov dx,offset buffer_size_name
- call print_number ; for them.
-
- ;initialize the queue
- mov bx,offset queue_begin
- mov queue_tail,bx
- add bx,queue_length
- mov queue_end,bx ;initialize the head of the queue.
- mov [bx].event_length,1 ;anything >0 will ensure that we're >end.
- mov queue_head,bx
-
- ;do some error checking.
- cmp entry_point,60h ;make sure that the packet interrupt
- jae pkt_int_ok ; number is in range.
- cmp entry_point,80h
- jbe pkt_int_ok
- mov dx,offset packet_int_msg
- jmp error
- pkt_int_ok:
-
- mov al,entry_point ;is there a packet driver there?
- call chk_int
- je start_4 ;yes, so we can trace it.
- jmp already_error ;no, give them an error.
- start_4:
- mov their_isr.offs,bx
- mov their_isr.segm,es
-
- mov ah,25h ;install our packet interrupt
- mov dx,offset our_isr
- int 21h
-
- mov dx,offset before_exec_msg
- mov ah,9
- int 21h
-
- ;
- ; Now free the memory we don't need.
- ;
- mov bx,queue_end
- add bx,size event_struc ;leave room for one more.
- add bx,0fh ;round up to next highest paragraph.
- mov cl,4
- shr bx,cl
- movseg es,cs
- mov ah,4ah
- int 21h
-
- ; Now we execute command.com
-
- mov ax,cs
- mov word ptr parm2+2,ax
- mov word ptr parm3+2,ax
- mov word ptr parm4+2,ax
-
- mov si,offset their_dioa+1 ;re-parse the two fcbs.
- mov di,offset phd_fcb1
- movseg es,ds
- mov ax,2901h
- int 21h
-
- mov di,offset phd_fcb2
- mov ax,2901h
- int 21h
-
- mov si,offset comspec_env_str ;see if this is the one.
- mov cx,comspec_env_len
- call getenv
-
- mov si,offset program
- copyname:
- mov al,es:[di]
- mov ds:[si],al
- inc si
- inc di
- or al,al
- jne copyname
-
- movseg es,cs
-
- mov ah,4bh
- mov bx,offset parm
- mov dx,offset program
- mov al,0
- int 21h
-
- mov bx,cs ;restore our segment registers.
- mov ds,bx
- mov es,bx
- mov ss,bx
- mov sp,offset stack
-
- ; Give up our packet interception.
-
- mov al,entry_point ;release our_isr.
- mov ah,25h
- push ds
- lds dx,their_isr
- int 21h
- pop ds
-
- ; Now we write our captured information out to disk.
-
- mov dx,offset trace_out ;create "trace.out".
- mov ah,3ch
- mov cx,0
- int 21h
-
- mov bx,ax
-
- mov si,queue_head
- write_out:
- mov dx,si
- mov cx,[si].event_length ;write this event out.
- add si,cx ;is this the end of the queue?
- cmp si,queue_end ;
- ja write_out_1
-
- mov ah,40h
- int 21h
- cmp ax,cx
- jne write_out_full
-
- jmp write_out
-
- write_out_1:
- mov si,offset queue_begin ;yes.
- write_out_2:
- cmp si,queue_tail ;quit when we hit the tail.
- jae write_out_3
-
- mov dx,si ;set dx for the file write below.
- mov cx,[si].event_length ;write this event out.
- add si,cx
-
- mov ah,40h
- int 21h
- cmp ax,cx
- jne write_out_full
-
- jmp write_out_2
- write_out_3:
- mov ah,3eh ;close the file.
- int 21h
-
- mov dx,offset run_dump_msg
- mov ah,9
- int 21h
-
- int 20h
-
- write_out_full:
- mov ah,9
- mov dx,offset disk_full_msg
- int 21h
- int 20h
-
-
- include intchk.asm
- include getnum.asm
- include printnum.asm
- include skipblk.asm
- include getdig.asm
- include decout.asm
- include digout.asm
- include chrout.asm
- include getenv.asm
- include crlf.asm
-
- end_code label byte
-
- queue_begin label byte
-
- code ends
-
- end start
-