📄 head.asm
字号:
stc
ret
access_type_type:
mov dh,NO_TYPE
stc
ret
access_type_number:
mov dh,NO_NUMBER
stc
ret
access_type_bad:
mov dh,BAD_TYPE
stc
ret
;register caller of pkt TYPE
f_access_type:
mov bx, offset cgroup:driver_class
access_type_9:
mov al, [bx] ;get the next class.
inc bx
or al,al ;end of the list?
je access_type_class ;class failed (story of my life)
cmp _AL[bp],al ;our class?
jne access_type_9 ;no, try again
access_type_1:
cmp _BX[bp],-1 ;generic type?
je access_type_2 ;yes.
mov al,driver_type
cbw
cmp _BX[bp],ax ;our type?
jne access_type_type ;no.
access_type_2:
cmp _DL[bp],0 ;generic number?
je access_type_3
cmp _DL[bp],1 ;our number?
jne access_type_number
access_type_3:
cmp _CX[bp],MAX_P_LEN ;is the type length too long?
ja access_type_bad ;yes - can't be ours.
; now we do two things--look for an open handle, and check the existing
; handles to see if they're replicating a packet type.
mov free_handle,0 ;remember no free handle yet.
mov bx,offset cgroup:handles
access_type_4:
cmp [bx].in_use,0 ;is this handle in use?
je access_type_5 ;no - don't check the type.
mov al, _AL[bp] ;is this handle the same class as
cmp al, [bx].class ; they're want?
jne short access_type_6
mov es,_DS[bp] ;get a pointer to their type
mov di,_SI[bp] ; from their ds:si to our es:di
mov cx,_CX[bp] ;get the minimum of their length
; and our length. As currently
; implemented, only one receiver
; gets the packets, so we have to
; ensure that the shortest prefix
; is unique.
cmp cx,[bx].packet_type_len ;Are we less specific than they are?
jb access_type_8 ;no.
mov cx,[bx].packet_type_len ;yes - use their count.
access_type_8:
lea si,[bx].packet_type
or cx,cx ; pass-all TYPE? (zero TYPE length)
jne access_type_7 ; ne = no
mov bx,offset cgroup:handles+(MAX_HANDLE-1)*(size per_handle)
jmp short access_type_5 ; put pass-all last
access_type_7:
repe cmpsb
jne short access_type_6 ;go look at the next one.
access_type_inuse:
mov dh,TYPE_INUSE ;a handle has been assigned for TYPE
stc ;and we can't assign another
ret
access_type_5: ;handle is not in use
cmp free_handle,0 ;found a free handle yet?
jne access_type_6 ;yes.
mov free_handle,bx ;remember a free handle
access_type_6:
add bx,(size per_handle) ;go to the next handle.
cmp bx,offset cgroup:end_handles ;examined all handles?
jb access_type_4 ;no, continue.
mov bx,free_handle ;did we find a free handle?
or bx,bx
je access_type_space ;no - return error.
mov ax,_DI[bp] ;remember the receiver type.
mov [bx].receiver.offs,ax
mov ax,_ES[bp]
mov [bx].receiver.segm,ax
push ds
mov ax,ds
mov es,ax
mov ds,_DS[bp] ;remember their type.
mov si,_SI[bp]
mov cx,_CX[bp]
mov es:[bx].packet_type_len,cx ; remember the TYPE length
lea di,[bx].packet_type
rep movsb
lds si,es:[bx].receiver ;copy the first 8 bytes
lea di,[bx].receiver_sig ; to the receiver signature.
mov cx,8/2
rep movsw
pop ds
mov al, _AL[bp]
mov [bx].class, al
mov [bx].in_use,1 ;remember that we're using it.
mov _AX[bp],bx ;return the handle to them.
clc
ret
access_type_space:
mov dh,NO_SPACE
stc
ret
f_release_type:
call verify_handle ;mark this handle as being unused.
mov [bx].in_use,0
call count_handles ;All handles gone now?
cmp cl,0
jne f_release_type_1 ;no, don't change the receive mode.
if 0
cmp rcv_modes+2[3*2],0 ;does mode 3 exist?
je f_release_type_1 ;no.
mov rcv_mode_num,3 ;yes - remember the number and
call rcv_modes+2[3*2] ; call it.
endif
f_release_type_1:
clc
ret
f_send_pkt:
;ds:si -> buffer, cx = length
; XXX Should re-enable interrupts here, but some drivers are broken.
; Possibly re-enable interrupts.
; test _F[bp], EI ; Were interrupts enabled on pkt driver entry?
; je f_send_pkt_1 ; No.
; sti ; Yes, re-enable interrupts now.
;f_send_pkt_1:
;following two instructions not needed because si and cx haven't been changed.
; mov si,_SI[bp]
; mov cx,_CX[bp] ; count of bytes in the packet.
add2 packets_out,1
add2 bytes_out,cx ;add up the received bytes.
mov ds,_DS[bp] ; address of buffer from caller's ds.
assume ds:nothing, es:nothing
; If -n option take Ethernet encapsulated Novell IPX packets (from BYU's
; PDSHELL) and change them to be IEEE 802.3 encapsulated.
EPROT_OFF equ EADDR_LEN*2
test cs:flagbyte,N_OPTION
jnz f_send_pkt_2
call send_pkt
ret
f_send_pkt_2:
cmp ds:[si].EPROT_OFF,3781h ; if not Novell (prot 8137)
jne f_send_pkt_3 ; don't tread on it
push ax ; get scratch reg
mov ax,[si].EPROT_OFF+4 ; get len
xchg ah,al
inc ax ; make even (rounding up)
and al,0feh
xchg ah,al
mov ds:[si].EPROT_OFF,ax ; save in prot field
pop ax ; restore old contents
f_send_pkt_3:
call send_pkt
ret
assume ds:cgroup
f_as_send_pkt:
;es:di -> iocb.
test driver_function,4 ; is this a high-performance driver?
je f_as_send_pkt_2 ; no.
; Possibly re-enable interrupts.
test _F[bp], EI ; Were interrupts enabled on pkt driver entry?
je f_as_send_pkt_1 ; No.
sti ; Yes, re-enable interrupts now.
f_as_send_pkt_1:
push ds ; set up proper ds for the buffer
lds si,es:[di].buffer ; ds:si -> buffer
assume ds:nothing
mov cx,es:[di].len ; cx = length
add2 packets_out,1
add2 bytes_out,cx ; add up the received bytes.
;ds:si -> buffer, cx = length, es:di -> iocb.
call as_send_pkt
pop ds
assume ds:cgroup
ret
f_as_send_pkt_2:
mov dh, BAD_COMMAND ; return an error.
stc
ret
f_drop_pkt:
; es:di -> iocb.
test driver_function,4 ; is this a high-performance driver?
je f_as_send_pkt_2 ; no.
push ds ; Preserve ds
mov si,offset cgroup:send_head ; Get head offset
dp_loop:
mov ax,ds:[si] ; Get offset
mov dx,ds:[si+2] ; Get segment
mov bx,ax
or bx,dx ; End of list?
je dp_endlist ; Yes
cmp ax,di ; Offsets equal?
jne dp_getnext ; No
mov bx,es
cmp dx,bx ; Segments equal?
jne dp_getnext ; No
call drop_pkt ; Pass to driver
les di,es:[di].next ; Get next segment:offset
mov ds:[si],di ; Set next offset
mov ds:[si+2],es ; Set next segment
pop ds ; Restore ds
clc
ret
dp_getnext:
mov ds,dx ; Get next segment
mov si,ax ; Get next iocb offset
lea si,ds:[si].next ; Get next iocb next ptr offset
jmp dp_loop ; Try again
dp_endlist:
pop ds ; Restore ds
mov dh,BAD_IOCB ; Return error
stc ; Set carry
ret
f_terminate:
call verify_handle ; must have a handle
mov [bx].in_use,0 ; mark handle as free
call count_handles ; all handles gone?
or cl,cl
jne f_terminate_4 ; no, can't exit completely
;
; Now disable interrupts
;
mov al,int_no
or al,al ;are they using a hardware interrupt?
je f_terminate_no_irq ;no.
cmp original_mask,0 ;was it enabled?
je f_terminate_no_mask ;yes, don't mask it now.
call maskint
f_terminate_no_mask:
;
; Now return the interrupt to their handler.
;
mov ah,25h ;get the old interrupt into es:bx
mov al,int_no
add al,8
cmp al,8+8 ;is it a slave 8259 interrupt?
jb f_terminate_3 ;no.
add al,70h - (8+8) ;map it to the real interrupt.
f_terminate_3:
push ds
lds dx,their_recv_isr
int 21h
pop ds
f_terminate_no_irq:
cmp their_timer.segm,0 ;did we hook the timer interrupt?
je f_terminate_no_timer
mov ax,2508h ;restore the timer interrupt.
push ds
lds dx,their_timer
int 21h
pop ds
f_terminate_no_timer:
call terminate ;terminate the hardware.
mov al,entry_point ;release our_isr.
mov ah,25h
push ds
lds dx,their_isr
int 21h
pop ds
;
; Now free our memory
;
movseg es,cs
mov ah,49h
int 21h
clc
ret
f_terminate_4:
mov dh, CANT_TERMINATE
stc
ret
f_get_address:
; call verify_handle
; mov es,_ES[bp] ; get new one
; mov di,_DI[bp] ; get pointer, es:di is ready
; mov cx,_CX[bp] ;Tell them how much room they have.
cmp cx,address_len ;is there enough room for our address?
jb get_address_space ;no.
mov cx,address_len ;yes - get our address length.
mov _CX[bp],cx ;Tell them how long our address is.
mov si,offset cgroup:my_address ;copy it into their area.
rep movsb
clc
ret
get_address_space:
mov dh,NO_SPACE
stc
ret
f_set_address:
call count_handles
cmp cl,1 ;more than one handle in use?
ja f_set_address_inuse ;yes - we can't set the address
mov cx,_CX[bp] ;get the desired address length.
cmp ch,0
cmp cl,parameter_list[3] ;is it the right length?
ja f_set_address_too_long ;no.
mov ds,_ES[bp] ; set new one
assume ds:nothing
mov si,_DI[bp] ; set pointer, ds:si is ready
mov ax,cs
mov es,ax
mov di,offset cgroup:my_address
rep movsb
mov ds,ax ;restore ds.
assume ds:cgroup
mov cx,_CX[bp] ;get the desired address length.
mov si,offset cgroup:my_address
call set_address
jc f_set_address_err ;Did it work?
mov cl,parameter_list[3]
xor ch,ch
mov _CX[bp],cx ;yes - return our address length.
clc
ret
f_set_address_inuse:
mov dh,CANT_SET
stc
ret
f_set_address_too_long:
mov dh,NO_SPACE
stc
ret
f_set_address_err:
;we get here with cy set - leave it set.
mov si,offset cgroup:rom_address ;we can't set the address, restore
mov di,offset cgroup:my_address ; to original.
mov cx,MAX_ADDR_LEN/2
rep movsw
ret
f_reset_interface:
call verify_handle
call reset_interface
clc
ret
; Stop the packet driver doing upcalls. Also a following terminate will
; always succed (no in use handles any longer).
f_stop:
mov bx,offset cgroup:handles
f_stop_2:
mov [bx].in_use,0
add bx,(size per_handle) ; next handle
cmp bx,offset cgroup:end_handles
jb f_stop_2
clc
ret
f_get_parameters:
;strictly speaking, this function only works for high-performance drivers.
test driver_function,4 ;is this a high-performance driver?
jne f_get_parameters_1 ;yes.
mov dh,BAD_COMMAND ;no - return an error.
stc
ret
f_get_parameters_1:
mov _ES[bp],cs
mov _DI[bp],offset cgroup:parameter_list
clc
ret
count_handles:
;exit with cl = number of handles currently in use.
mov bx,offset cgroup:handles
mov cl,0 ;number of handles in use.
count_handles_1:
add cl,[bx].in_use ;is this handle in use?
add bx,(size per_handle) ;go to the next handle.
cmp bx,offset cgroup:end_handles
jb count_handles_1
ret
verify_handle:
;Ensure that their handle is real. If it isn't, we pop off our return
;address, and return to *their* return address with cy set.
mov bx,_BX[bp] ;get the handle they gave us
cmp bx,offset cgroup:handles
jb verify_handle_bad ;no - must be bad.
cmp bx,offset cgroup:end_handles
jae verify_handle_bad ;no - must be bad.
cmp [bx].in_use,1 ;if it's not in use, it's bad.
jne verify_handle_bad
ret
verify_handle_bad:
mov dh,BAD_HANDLE
add sp,2 ;pop off our return address.
stc
ret
public set_recv_isr
set_recv_isr:
mov ah,35h ;get the old interrupt into es:bx
mov al,int_no ; board's interrupt vector
or al,al
je set_isr_no_irq
add al,8
cmp al,8+8 ;is it a slave 8259 interrupt?
jb set_recv_isr_1 ;no.
add al,70h - 8 - 8 ;map it to the real interrupt.
set_recv_isr_1:
int 21h
mov their_recv_isr.offs,bx ;remember the old seg:off.
mov their_recv_isr.segm,es
mov ah,25h ;now set our recv interrupt.
mov dx,offset cgroup:recv_isr
int 21h
cmp byte ptr timer_isr,0cfh ;is there just an iret at their handler?
je set_isr_no_timer ;yes, don't bother hooking the timer.
mov ax,3508h ;get the old interrupt into es:bx
int 21h
mov their_timer.offs,bx ;remember the old seg:off.
mov their_timer.segm,es
mov ah,25h ;now set our recv interrupt.
mov dx,offset cgroup:timer_isr
int 21h
set_isr_no_timer:
mov al,int_no ; Now enable interrupts
call unmaskint
mov original_mask,al
set_isr_no_irq:
ret
public count_in_err
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -