|
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