|
|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T p
Length: 11387 (0x2c7b)
Types: TextFile
Names: »pktd.asm«
└─⟦9ae75bfbd⟧ Bits:30007242 EUUGD3: Starter Kit
└─⟦349c9a24c⟧ »EurOpenD3/network/ka9q/pktd.tar.Z«
└─⟦613ecc654⟧
└─⟦this⟧ »./src/pktd.asm«
; @(#)pktd.asm.u 1.5 2/7/90\r
;\r
; Copyright (c) 1989, 1990 by Sun Microsystems, Inc.\r
;\r
\r
title Sun Packet Driver Interface Driver\r
page ,132\r
\r
;\r
; The following driver is derived from two sources:\r
; (1) Version 1.08 of the Packet Driver Specification,\r
; developed at FTP Software Inc.\r
; (2) The PC-NFS Link Level Driver Kit.\r
;\r
; In addition, Karl Auerbach (karl@asylum.sf.ca.us) contributed\r
; a couple of fixes; his mods are marked "***KAA". Thanks, Karl.\r
;\r
; This version includes the fixes suggested by many users to allow\r
; PC-NFS to co-exist with Netware using the New York code. Thanks\r
; to Russ Nelson at Clarkson and James Van Bokkelen at FTP for\r
; their help.\r
;\r
; This material is provided "as is." It is NOT a supported\r
; Sun product, and has not been tested against more than\r
; a handful of packet drivers. Please send any comments,\r
; fixes, etc. to me (geoff@east.sun.com).\r
;\r
; Geoff Arnold\r
\r
_OPERATING_STATISTICS equ 1\r
\r
cseg segment para public 'code'\r
assume cs:cseg\r
assume ds:nothing\r
assume es:nothing\r
\r
\r
include pktdd.asm\r
include pktd.mac\r
include protocol.inc\r
include log.inc\r
include select.inc\r
\r
;\r
; EXTRNS\r
;\r
extrn demux:near\r
extrn upcall:near\r
\r
; PUBLICS\r
;\r
\r
public select_table_pointer ; new name for universal demux routine\r
\r
public log_seg\r
public log_base\r
public ethsend\r
\r
; variables which live in cseg\r
;\r
\r
;\r
; Pointer to select table - used by demux.asm\r
;\r
select_table_pointer dw 2 dup (0) ; address of select table\r
\r
\r
\r
; the following are the segment & offset for the log table\r
log_seg dw ?\r
log_base dw ?\r
; The log routine follows:\r
logproc\r
;............................................................\r
; see the pop_f macro in pktd.mac for why this is here\r
iretins:\r
iret\r
\r
; initialize the ethernet interface and driver\r
; es:di contains address of select table\r
ethinit proc far\r
push es\r
push ds ; save old ds and set to cs\r
push cs\r
pop ds\r
mov select_table_pointer,di ; save the table address away\r
mov select_table_pointer+2,es\r
mov es:sel_largest[di], largest_packet ; ret size of buffer\r
;\r
; get log info\r
;\r
mov ax, es:sel_logtab_s[di]\r
mov log_seg, ax\r
mov ax, es:sel_logtab_o[di]\r
mov log_base, ax\r
;\r
; (we can now use the log macro)\r
;\r
push es\r
call setup\r
pop es\r
push cs\r
pop ds\r
lea di,sel_ethaddr[di] ;point to ether address entry\r
mov si, offset pd_addr\r
movsw\r
movsw\r
movsw\r
ethinitdone:\r
sub ax,ax\r
pop ds\r
pop es\r
sti\r
ret\r
ethinit endp\r
\r
ethsend proc far\r
call sender\r
ret\r
ethsend endp\r
\r
\f
\r
\r
;-- The packet driver code looks like this:\r
;--\r
;-- setup() {\r
;-- if(state==UP)\r
;-- return; /* state starts out as DOWN */\r
;-- if(find_driver() == FALSE)\r
;-- return;\r
;-- stuff = call_driver(DRIVER_INFO);\r
;-- handle = call_driver(ACCESS_TYPE, IP_TYPE, 2, receiver);\r
;-- handle = call_driver(ACCESS_TYPE, ARP_TYPE, 2, receiver);\r
;-- handle = call_driver(ACCESS_TYPE, RARP_TYPE, 2, receiver);\r
;-- call_driver(GET_ADDRESS, handle, &my_link_addr, &my_link_addr_len);\r
;-- state = UP;\r
;-- }\r
;--\r
;-- find_driver() {\r
;-- vecptr = PTR(0, 0x60*4); /* point into vectors */\r
;-- for(vector = 0x60; vector <= 0x80; vector++) {\r
;-- driverptr = *vecptr; /* deref ptr to dword ptr */\r
;-- if (strcmp(*(driverptr+3), "PKT DRVR") == 0)\r
;-- return(TRUE);\r
;-- vecptr += 4; /* step to next vector */\r
;-- }\r
;-- return(FALSE);\r
;-- }\r
;--\r
;-- call_driver(func,args) {\r
;-- load args into registers;\r
;-- set AH = func;\r
;-- soft int to vector; /* ?far call to driverptr with ints off? */\r
;-- }\r
;--\r
;-- sender() {\r
;-- if(multiple fragments) {\r
;-- marshal fragments into sendbuf;\r
;-- call_driver(SEND_PKT, sendbuf);\r
;-- } else {\r
;-- call_driver(SEND_PKT, caller_buf);\r
;-- }\r
;-- }\r
;--\r
;-- receiver(ax) {\r
;-- if(ax == 0) { /* first call for a packet */\r
;-- set es:di to pint at rcvbuf; cx = sizeof(rcvbuf);\r
;-- } else { /* data copied - test and demux */\r
;-- demux_and_upcall(rcvbuf);\r
;-- }\r
;-- }\r
;------ The descriptions above are replicated before each routine\r
\f
\r
\r
DRIVER_INFO equ 1\r
ACCESS_TYPE equ 2\r
SEND_PKT equ 4\r
GET_ADDRESS equ 6\r
\r
buflen equ 1518\r
pd_sig db 'PKT DRVR',0\r
pd_sig_len equ $-pd_sig\r
pd_int db 0\r
pd_setup db 0\r
pd_class db 0\r
pd_num db 0\r
pd_type dw 0\r
pd_alen dw 6\r
pd_addr db 6 dup (0)\r
pd_handle dw 0\r
pd_rbuf db buflen dup (?)\r
pd_sbuf db buflen dup (?)\r
pd_rlen dw 0\r
;\r
ip_type db 8,0\r
arp_type db 8,6\r
rarp_type db 80h,35h\r
;\r
\r
pd_stklev dw 0\r
pd_stack db 256 dup ('x')\r
pd_stktop dw 0\r
; Save the SI returned by demux() in the following locations ***KAA\r
si_save dw 0 ;***KAA\r
\f
\r
;--\r
;-- call_driver(func,args) {\r
;-- load args into registers;\r
;-- set AH = func;\r
;-- soft int to vector; /* ?far call to driverptr with ints off? */\r
;-- }\r
public call_driver\r
call_driver proc near\r
int 0\r
ret\r
call_driver endp\r
\r
pd_patch equ call_driver+1\r
\r
\f
\r
;--\r
;-- setup() {\r
;-- if(state==UP)\r
;-- return; /* state starts out as DOWN */\r
;-- if(find_driver() == FALSE)\r
;-- return;\r
;-- stuff = call_driver(DRIVER_INFO);\r
;-- handle = call_driver(ACCESS_TYPE, IP_TYPE, 2, receiver);\r
;-- handle = call_driver(ACCESS_TYPE, ARP_TYPE, 2, receiver);\r
;-- handle = call_driver(ACCESS_TYPE, RARP_TYPE, 2, receiver);\r
;;-- call_driver(GET_ADDRESS, handle, &my_link_addr, &my_link_addr_len);\r
;-- state = UP;\r
;-- }\r
public setup\r
setup proc near\r
push ax\r
push bx\r
push cx\r
push dx\r
push es\r
push di\r
push si\r
cmp pd_setup, 0\r
jne se_900\r
inc pd_setup\r
call find_driver\r
jc se_900\r
mov ah, DRIVER_INFO\r
call call_driver\r
push cs\r
pop ds ; deliberately ignoring the name\r
jc se_900\r
mov pd_class, ch\r
mov pd_num, cl\r
mov pd_type, dx\r
;\r
mov si, offset ip_type\r
call register_type\r
jc se_900\r
mov si, offset arp_type\r
call register_type\r
jc se_900\r
mov si, offset rarp_type\r
call register_type\r
jc se_900\r
\r
mov bx, pd_handle\r
mov ah, GET_ADDRESS\r
push cs\r
pop es\r
mov di, offset pd_addr\r
mov cx, pd_alen\r
call call_driver\r
jc se_900\r
mov pd_alen, cx\r
se_900:\r
pop si\r
pop di\r
pop es\r
pop dx\r
pop cx\r
pop bx\r
pop ax\r
ret\r
setup endp\r
\r
;\r
; register_type, entered with ds:si pointing at the packet type code\r
;\r
public register_type\r
register_type proc near\r
mov ah, ACCESS_TYPE\r
mov al, pd_class\r
mov bx, pd_type\r
mov dl, pd_num\r
mov cx, 2 ; 2 bytes of filter\r
push cs\r
pop es\r
mov di, offset receiver\r
call call_driver\r
jc rt_900\r
mov pd_handle, ax\r
ret\r
rt_900: \r
; int 3\r
ret\r
register_type endp\r
\f
\r
;--\r
;-- find_driver() {\r
;-- vecptr = PTR(0, 0x60*4); /* point into vectors */\r
;-- for(vector = 0x60; vector <= 0x80; vector++) {\r
;-- driverptr = *vecptr; /* deref ptr to dword ptr */\r
;-- if (strcmp(*(driverptr+3), "PKT DRVR") == 0)\r
;-- return(TRUE);\r
;-- vecptr += 4; /* step to next vector */\r
;-- }\r
;-- return(FALSE);\r
;-- }\r
public find_driver\r
find_driver proc near\r
mov bx, 60h*4\r
mov dx, 60h\r
xor ax, ax\r
cld\r
fd_010:\r
mov es, ax\r
les di, es:[bx] ; get vector in ES:BX\r
lea di, 3[di] ; point at signature\r
mov si, offset pd_sig\r
mov cx, pd_sig_len\r
repe cmpsb\r
je fd_100 ; found it\r
add bx, 4\r
inc dx\r
cmp dx, 80h\r
jle fd_010\r
stc\r
ret\r
fd_100:\r
mov pd_int, dl\r
mov byte ptr cs:pd_patch, dl\r
clc\r
ret\r
find_driver endp\r
\r
\f
\r
;--\r
;-- sender() {\r
;-- if(multiple fragments) {\r
;-- marshal fragments into sendbuf;\r
;-- call_driver(SEND_PKT, sendbuf);\r
;-- } else {\r
;-- call_driver(SEND_PKT, caller_buf);\r
;-- }\r
;-- }\r
public sender\r
sender proc near\r
log _LOG_ETH_XMIT\r
push bx\r
push cx\r
push dx\r
push si\r
push ds\r
push es\r
mov ah, SEND_PKT\r
add di, 2 ; step over status\r
mov cx, word ptr es:[di]\r
lds si, dword ptr es:[di+2]\r
add di, 6\r
cmp word ptr es:[di], 0 ; any more?\r
jne send_010 ; if so, go do multiple...\r
call call_driver\r
jmp send_090\r
send_010:\r
; we must copy the data into a local buffer first\r
push es\r
push di\r
mov dx, cx ; save count\r
push cs\r
pop es\r
mov di, offset pd_sbuf\r
call copydata\r
pop si\r
pop ds\r
mov cx, word ptr [si]\r
lds si, dword ptr [si+2]\r
add dx, cx\r
call copydata\r
push cs\r
pop ds\r
mov si, offset pd_sbuf\r
mov cx, dx\r
call call_driver\r
send_090:\r
pop es\r
pop ds\r
pop si\r
pop dx\r
pop cx\r
pop bx\r
sub ax, ax ; no error\r
ret\r
sender endp\r
\r
public copydata\r
copydata proc near\r
inc cx ; if odd (illegal?) ...\r
shr cx, 1 ; ... round up (otherwise inc is benign)\r
rep movsw\r
ret\r
copydata endp\r
\f
\r
;--\r
;-- receiver(ax) {\r
;-- if(ax == 0) { /* first call for a packet */\r
;-- set es:di to pint at rcvbuf; cx = sizeof(rcvbuf);\r
;-- } else { /* data copied - test and demux */\r
;-- demux_and_upcall(rcvbuf);\r
;-- }\r
;-- }\r
public receiver\r
receiver proc far\r
cmp ax, 0\r
jne rcv_010\r
push cs\r
pop es\r
mov di, offset pd_rbuf\r
mov cs:pd_rlen, cx\r
ret\r
rcv_010:\r
; we first switch to our stack. we can trash ax/bx/dx, per spec\r
pushf\r
pop dx\r
cli\r
cmp cs:pd_stklev, 0\r
jne rcv_015\r
inc cs:pd_stklev\r
mov ax, ss\r
mov bx, sp\r
push cs\r
pop ss\r
mov sp, offset pd_stktop\r
push ax\r
push bx\r
rcv_015:\r
push dx ; saved flags\r
popf\r
\r
push ds ; general save\r
\r
push ds ; save...\r
push si ; ... over ...\r
push cx ; ... demux\r
\r
push ds\r
pop es\r
\r
push si\r
pop di\r
\r
mov cx,64 ; Limit demux's view (why ???) ***KAA\r
call demux ; and remember to preserve BX cookie\r
mov si_save,si ; It is necessary to save the SI returned\r
; from demux and pass it to upcall ***KAA\r
\r
pop ax ; original len\r
pop si\r
pop ds\r
\r
jc rcv_800 ; carry from demux call\r
log _LOG_ETH_RCV\r
cmp ax, cx\r
jge rcv_200\r
mov cx, ax\r
rcv_200:\r
call copydata\r
mov si,si_save ;***KAA\r
call upcall\r
jmp rcv_900\r
rcv_800:\r
log _LOG_ETH_DROPPED\r
rcv_900:\r
pop ds\r
pushf\r
pop dx ; save those flags\r
cli\r
dec cs:pd_stklev\r
jne rcv_990\r
pop bx\r
pop ax\r
mov ss, ax\r
mov sp, bx\r
rcv_990:\r
push dx ; the flags, the flags....\r
popf\r
ret\r
receiver endp\r
\r
cseg ends\r
end begin\r