home *** CD-ROM | disk | FTP | other *** search
/ Shareware Overload / ShartewareOverload.cdr / windows / w3pktdr2.zip / HEAD.ASM < prev    next >
Assembly Source File  |  1990-06-28  |  22KB  |  941 lines

  1. include    defs.asm
  2.  
  3. ; WARNING !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  4. ; Modifications make to enchance use under muti-taskers (windows etc)
  5. ; Steven Wallace
  6. ; Indiana University
  7. ; Bloomington, IN
  8. ; wallaces@ucs.indiana.edu
  9.  
  10. ; this version of the packet drivers may be buggy!!!
  11.  
  12. ;  Copyright, 1988-9, 1990, Russell Nelson
  13.  
  14. ;   This program is free software; you can redistribute it and/or modify
  15. ;   it under the terms of the GNU General Public License as published by
  16. ;   the Free Software Foundation, version 1.
  17. ;
  18. ;   This program is distributed in the hope that it will be useful,
  19. ;   but WITHOUT ANY WARRANTY; without even the implied warranty of
  20. ;   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  21. ;   GNU General Public License for more details.
  22. ;
  23. ;   You should have received a copy of the GNU General Public License
  24. ;   along with this program; if not, write to the Free Software
  25. ;   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  26.  
  27. code    segment byte public
  28.     assume    cs:code, ds:code
  29.  
  30.     public    phd_environ
  31.     org    2ch
  32. phd_environ    dw    ?
  33.  
  34.     public    phd_dioa
  35.     org    80h
  36. phd_dioa    label    byte
  37.  
  38.     org    100h
  39. start:
  40.     jmp    start_1
  41.     extrn    start_1: near
  42.  
  43. ;we use our dioa for a stack space.  Very hard usage has shown that only
  44. ;  27 bytes were being used, so 128 should be sufficient.
  45. our_stack    label    byte
  46.  
  47.  
  48.     extrn    int_no: byte
  49.     public    packet_int_no, is_at, sys_features
  50. packet_int_no    db    ?,?,?,?        ; interrupt to communicate.
  51. is_at        db    0        ; =1 if we're on an AT.
  52. sys_features    db    0        ; 2h = MC   40h = 2nd 8259
  53.  
  54. functions    label    word
  55.     dw    f_not_implemented
  56.     dw    f_driver_info
  57.     dw    f_access_type
  58.     dw    f_release_type
  59.     dw    f_send_pkt
  60.     dw    f_terminate
  61.     dw    f_get_address
  62.     dw    f_reset_interface
  63.     dw    f_not_implemented
  64.     dw    f_not_implemented
  65.     dw    f_get_parameters
  66.     dw    f_as_send_pkt
  67.     dw    f_not_implemented
  68.     dw    f_not_implemented
  69.     dw    f_not_implemented
  70.     dw    f_not_implemented
  71.     dw    f_not_implemented
  72.     dw    f_not_implemented
  73.     dw    f_not_implemented
  74.     dw    f_not_implemented
  75.     dw    f_set_rcv_mode
  76.     dw    f_get_rcv_mode
  77.     dw    f_set_multicast_list
  78.     dw    f_get_multicast_list
  79.     dw    f_get_statistics
  80.     dw    f_set_address
  81.  
  82.     extrn    driver_class: byte
  83.     extrn    driver_type: byte
  84.     extrn    driver_name: byte
  85.     extrn    driver_function: byte
  86.     extrn    parameter_list: byte
  87.  
  88.     extrn    send_pkt: near
  89.     extrn    get_address: near
  90.     extrn    set_address: near
  91.     extrn    terminate: near
  92.     extrn    reset_interface: near
  93.     extrn    recv: near
  94.     extrn    recv_exiting: near
  95.  
  96.     extrn    rcv_modes: word        ;count of modes followed by mode handles.
  97.  
  98.     extrn    set_multicast_list: near
  99.  
  100. linc    macro    n            ; inc a 32 bit integer
  101.     local    a
  102.     inc    n            ;increment the low word
  103.     jne    a            ;go if not overflow
  104.     inc    n+2            ;increment the high word
  105. a:
  106.     endm
  107.  
  108. per_handle    struc
  109. in_use        db    0        ;non-zero if this handle is in use.
  110. packet_type    db    MAX_P_LEN dup(0);associated packet type.
  111. packet_type_len    dw    0        ;associated packet type length.
  112. receiver    dd    0        ;receiver handler.
  113. ; ssw
  114. sig1        dw    0        ;We'll store the first 4 words
  115. sig2        dw    0        ; of the receiver function
  116. sig3        dw    0        ; and use them as a signature
  117. sig4        dw    0
  118. ; ssw
  119. per_handle    ends
  120. handles        per_handle max_handle dup(<>)
  121. end_handles    label    byte
  122. cur_handle    dw
  123.     public    multicast_count, multicast_addrs, multicast_broad
  124. multicast_count    dw    0        ;count of stored multicast addresses.
  125. multicast_broad    db    0ffh,0ffh,0ffh,0ffh,0ffh,0ffh    ; entry for broadcast
  126. multicast_addrs    db    MAX_MULTICAST*EADDR_LEN dup(?)
  127.  
  128. have_my_address    db    0        ;nonzero if our address has been set.
  129. my_address    db    MAX_ADDR_LEN dup(?)
  130. my_address_len    dw    ?
  131.  
  132. rcv_mode_num    dw    3
  133.  
  134. free_handle    dw    0        ; temp, a handle not in use
  135. found_handle    dw    0        ; temp, handle for our packet
  136. receive_ptr    dd    0        ; the pkt receive service routine
  137.  
  138. statistics_list    label    dword
  139. packets_in    dw    ?,?
  140. packets_out    dw    ?,?
  141. bytes_in    dw    ?,?
  142. bytes_out    dw    ?,?
  143. errors_in    dw    ?,?
  144. errors_out    dw    ?,?
  145. packets_dropped    dw    ?,?        ;dropped due to no type handler.
  146.  
  147. savess        dw    ?        ;saved during the stack swap.
  148. savesp        dw    ?
  149.  
  150. regs    struc                ; stack offsets of incoming regs
  151. _ES    dw    ?
  152. _DS    dw    ?
  153. _BP    dw    ?
  154. _DI    dw    ?
  155. _SI    dw    ?
  156. _DX    dw    ?
  157. _CX    dw    ?
  158. _BX    dw    ?
  159. _AX    dw    ?
  160. _IP    dw    ?
  161. _CS    dw    ?
  162. _F    dw    ?            ; flags, Carry flag is bit 0
  163. regs    ends
  164.  
  165. CY    equ    0001h
  166. EI    equ    0200h
  167.  
  168.  
  169. bytes    struc                ; stack offsets of incoming regs
  170.     dw    ?            ; es, ds, bp, di, si are 16 bits
  171.     dw    ?
  172.     dw    ?
  173.     dw    ?
  174.     dw    ?
  175. _DL    db    ?
  176. _DH    db    ?
  177. _CL    db    ?
  178. _CH    db    ?
  179. _BL    db    ?
  180. _BH    db    ?
  181. _AL    db    ?
  182. _AH    db    ?
  183. bytes    ends
  184.  
  185.     public    our_isr, their_isr
  186. their_isr    dd    0        ; original owner of pkt driver int
  187.  
  188. our_isr:
  189.     jmp    our_isr_0        ;the required signature.
  190.     db    'PKT DRVR',0
  191. our_isr_0:
  192.     assume    ds:nothing
  193.     push    ax
  194.     push    bx
  195.     push    cx
  196.     push    dx
  197.     push    si
  198.     push    di
  199.     push    bp
  200.     push    ds
  201.     push    es
  202.     cld
  203.     mov    bx,cs            ;set up ds.
  204.     mov    ds,bx
  205.     assume    ds:code
  206.     mov    bp,sp            ;we use bp to access the original regs.
  207.     and    _F[bp],not CY        ;start by clearing the carry flag.
  208.     mov    bl,ah            ;jump to the correct function.
  209.     mov    bh,0
  210.     cmp    bx,25            ;only twenty five functions right now.
  211.     mov    dh,BAD_COMMAND        ;in case we find a bad number.
  212.     ja    our_isr_error
  213.     add    bx,bx            ;*2
  214.     call    functions[bx]
  215.     jnc    our_isr_return
  216. our_isr_error:
  217.     mov    _DH[bp],dh
  218.     or    _F[bp],CY        ;return their carry flag.
  219. our_isr_return:
  220.     pop    es
  221.     pop    ds
  222.     pop    bp
  223.     pop    di
  224.     pop    si
  225.     pop    dx
  226.     pop    cx
  227.     pop    bx
  228.     pop    ax
  229.     iret
  230.  
  231.  
  232. f_not_implemented:
  233.     mov    dh,BAD_COMMAND
  234.     stc
  235.     ret
  236.  
  237.  
  238. f_driver_info:
  239. ;    As of 1.08, the handle is optional, so we no longer verify it.
  240. ;    call    verify_handle
  241.     cmp    _AL[bp],0ffh        ; correct calling convention?
  242.     jne    f_driver_info_1        ; ne = incorrect, fail
  243.     mov    _BX[bp],majver        ;version
  244.     mov    al,driver_class
  245.     mov    _CH[bp],al
  246.     mov    al,driver_type
  247.     cbw
  248.     mov    _DX[bp],ax
  249.     mov    _CL[bp],0        ;number zero.
  250.     mov    _DS[bp],ds        ; point to our name in their ds:si
  251.     mov    _SI[bp],offset driver_name
  252.     mov    al,driver_function
  253.     mov    _AL[bp],al
  254.     clc
  255.     ret
  256. f_driver_info_1:
  257.     stc
  258.     ret
  259.  
  260.  
  261. f_set_rcv_mode:
  262.     call    verify_handle
  263.     mov    cx,_CX[bp]        ;Tell them how much room they have.
  264.     cmp    cx,rcv_modes        ;do they have this many modes?
  265.     jae    f_set_rcv_mode_1    ;no - must be a bad mode for us.
  266.     mov    bx,cx
  267.     add    bx,bx            ;we're accessing words, not bytes.
  268.     mov    ax,rcv_modes[bx]+2    ;get the handler for this mode.
  269.     or    ax,ax            ;do they have one?
  270.     je    f_set_rcv_mode_1    ;no - must be a bad mode for us.
  271.     mov    rcv_mode_num,cx        ;yes - remember the number and
  272.     call    ax            ;  call it.
  273.     clc
  274.     ret
  275. f_set_rcv_mode_1:
  276.     mov    dh,BAD_MODE
  277.     stc
  278.     ret
  279.  
  280.  
  281. f_get_rcv_mode:
  282.     call    verify_handle
  283.     mov    ax,rcv_mode_num        ;return the current receive mode.
  284.     mov    _AX[bp],ax
  285.     clc
  286.     ret
  287.  
  288.  
  289. f_set_multicast_list:
  290. ;    mov    cx,_CX[bp]        ;Tell them how much room they have.
  291.  
  292. ;verify that they supplied an even number of EADDR's.
  293.     mov    ax,cx
  294.     xor    dx,dx
  295.     mov    bx,EADDR_LEN
  296.     div    bx
  297.     or    dx,dx            ;zero remainder?
  298.     jne    f_set_multicast_list_2    ;no, we don't have an even number of
  299.                     ;  addresses.
  300.  
  301.     cmp    ax,MAX_MULTICAST    ;is this too many?
  302.     ja    f_set_multicast_list_3    ;yes - return NO_SPACE
  303. f_set_multicast_list_1:
  304.     mov    multicast_count,ax    ;remember the number of addresses.
  305.     push    cs
  306.     pop    es
  307.     mov    di,offset multicast_addrs
  308.     push    ds
  309.     mov    ds,_ES[bp]        ; get ds:si -> new list.
  310.     mov    si,_DI[bp]
  311.     push    cx
  312.     rep    movsb
  313.     pop    cx
  314.     pop    ds
  315.  
  316.     mov    si,offset multicast_addrs
  317.     call    set_multicast_list
  318.     ret
  319. f_set_multicast_list_2:
  320.     mov    dh,BAD_ADDRESS
  321.     stc
  322.     ret
  323. f_set_multicast_list_3:
  324.     mov    dh,NO_SPACE
  325.     stc
  326.     ret
  327.  
  328.  
  329. f_get_multicast_list:
  330.     mov    _ES[bp],ds        ;return what we have remembered.
  331.     mov    _DI[bp],offset multicast_addrs
  332.     mov    ax,EADDR_LEN        ;multiply the count by the length.
  333.     mul    multicast_count
  334.     mov    _CX[bp],ax        ;because they want total bytes.
  335.     clc
  336.     ret
  337.  
  338.  
  339. f_get_statistics:
  340.     call    verify_handle        ;just in case.
  341.     mov    _DS[bp],ds
  342.     mov    _SI[bp],offset statistics_list
  343.     clc
  344.     ret
  345.  
  346.  
  347. access_type_class:
  348.     mov    dh,NO_CLASS
  349.     stc
  350.     ret
  351.  
  352. access_type_type:
  353.     mov    dh,NO_TYPE
  354.     stc
  355.     ret
  356.  
  357. access_type_number:
  358.     mov    dh,NO_NUMBER
  359.     stc
  360.     ret
  361.  
  362. access_type_bad:
  363.     mov    dh,BAD_TYPE
  364.     stc
  365.     ret
  366.  
  367. access_type_space:
  368.     mov    dh,NO_SPACE
  369.     stc
  370.     ret
  371.  
  372. ;register caller of pkt TYPE
  373. f_access_type:
  374.     mov    al,driver_class
  375.     cmp    _AL[bp],al        ;our class?
  376.     jne    access_type_class    ;no.
  377.     cmp    _BX[bp],-1        ;generic type?
  378.     je    access_type_2        ;yes.
  379.     mov    al,driver_type
  380.     cbw
  381.     cmp    _BX[bp],ax        ;our type?
  382.     jne    access_type_type    ;no.
  383. access_type_2:
  384.     cmp    _DL[bp],0        ;generic number?
  385.     je    access_type_3
  386.     cmp    _DL[bp],1        ;our number?
  387.     jne    access_type_number
  388. access_type_3:
  389.     cmp    _CX[bp],MAX_P_LEN    ;is the type length too long?
  390.     ja    access_type_bad        ;yes - can't be ours.
  391.  
  392. ; now we do two things--look for an open handle, and check the existing
  393. ; handles to see if they're replicating a packet type.
  394.  
  395.     mov    free_handle,0        ;remember no free handle yet.
  396.     mov    bx,offset handles
  397. access_type_4:
  398.     cmp    [bx].in_use,0        ;is this handle in use?
  399.     je    access_type_5        ;no - don't check the type.
  400.     mov    es,_DS[bp]        ;get a pointer to their type
  401.     mov    di,_SI[bp]        ;  from their ds:si to our es:di
  402.     mov    cx,_CX[bp]        ;get the minimum of their length
  403.                     ;  and our length.  As currently
  404.                     ;  implemented, only one receiver
  405.                     ;  gets the packets, so we have to
  406.                     ;  ensure that the shortest prefix
  407.                     ;  is unique.
  408.     cmp    cx,[bx].packet_type_len    ;Are we less specific than they are?
  409.     jb    access_type_8        ;no.
  410.     mov    cx,[bx].packet_type_len    ;yes - use their count.
  411. access_type_8:
  412.     lea    si,[bx].packet_type
  413.     or    cx,cx            ; pass-all TYPE? (zero TYPE length)
  414.     jne    access_type_7        ; ne = no
  415.     mov    bx,offset handles+(max_handle -1)*(size per_handle)
  416.     jmp    short access_type_5    ; put pass-all last
  417. access_type_7:
  418.     repe    cmpsb
  419.     jne    short access_type_6    ;go look at the next one.
  420. access_type_inuse:
  421.     mov    dh,TYPE_INUSE        ;a handle has been assigned for TYPE
  422.     stc                ;and we can't assign another
  423.     ret
  424. access_type_5:                ;handle is not in use
  425.     cmp    free_handle,0        ;found a free handle yet?
  426.     jne    access_type_6        ;yes.
  427.     mov    free_handle,bx        ;remember a free handle
  428. access_type_6:
  429.     add    bx,(size per_handle)    ;go to the next handle.
  430.     cmp    bx,offset end_handles    ;examined all handles?
  431.     jb    access_type_4        ;no, continue.
  432.  
  433.     mov    bx,free_handle        ;did we find a free handle?
  434.     or    bx,bx
  435.     je    access_type_space    ;no - return error.
  436.  
  437.     mov    [bx].in_use,1        ;remember that we're using it.
  438.  
  439.     mov    ax,_DI[bp]        ;remember the receiver type.
  440.     mov    [bx].receiver.offs,ax
  441.     mov    ax,_ES[bp]
  442.  
  443.     mov    [bx].receiver.segm,ax
  444.     push    ds
  445.     mov    ax,ds
  446.     mov    es,ax
  447.     mov    ds,_DS[bp]        ;remember their type.
  448.     mov    si,_SI[bp]
  449.     mov    cx,_CX[bp]
  450.     mov    es:[bx].packet_type_len,cx    ; remember the TYPE length
  451.     lea    di,[bx].packet_type
  452.     rep    movsb
  453.     pop    ds
  454.  
  455.     mov    _AX[bp],bx        ;return the handle to them.
  456.     clc
  457. ; ssw
  458.     mov    ax, [bx].receiver.segm    ;copy the first 4 words 
  459.     mov    es, ax            ; pointed to by receiver
  460.     mov    di, [bx].receiver.offs    ; to sig1, sig2, sig3, sig4
  461.     mov    ax, es:[di]        ; will be used latter 
  462.     mov    [bx].sig1, ax        ; to test if the real receiver
  463.     inc    di            ; is loaded in memory
  464.     mov    ax, es:[di]
  465.     mov    [bx].sig2, ax
  466.     inc    di
  467.     mov    ax, es:[di]
  468.     mov    [bx].sig3, ax
  469.     inc    di
  470.     mov    ax, es:[di]
  471.     mov    [bx].sig4, ax
  472.     ret
  473.  
  474.  
  475. f_release_type:
  476.     call    verify_handle        ;mark this handle as being unused.
  477.     mov    [bx].in_use,0
  478.     clc
  479.     ret
  480.  
  481.  
  482. f_as_send_pkt:
  483. ;ds:si -> buffer, cx = length, es:di -> upcall.
  484.     test    driver_function,4    ;is this a high-performance driver?
  485.     jne    f_send_pkt_1        ;yes.
  486.     mov    dh,BAD_COMMAND        ;no - return an error.
  487.     stc
  488.     ret
  489.  
  490. f_send_pkt:
  491. ;ds:si -> buffer, cx = length
  492.     xor    di,di
  493.     mov    es,di
  494. f_send_pkt_1:
  495. ;ds:si -> buffer, cx = length, es:di -> upcall (only used if high-pref driver).
  496.     linc    packets_out
  497.     add    bytes_out.offs,cx    ;add up the received bytes.
  498.     adc    bytes_out.segm,0
  499.  
  500.     push    ds        ; set up proper ds for the buffer
  501.     mov    ds,_DS[bp]    ; address of buffer from caller's ds.
  502. ;following two instructions not needed because si and cx haven't been changed.
  503. ;    mov    si,_SI[bp]
  504. ;    mov    cx,_CX[bp]    ; count of bytes in the packet.
  505.  
  506.     call    send_pkt
  507.     pop    ds
  508.     ret
  509.  
  510.  
  511. f_terminate:
  512.     call    verify_handle        ; must have a handle
  513.  
  514. f_terminate_1:
  515.     mov    [bx].in_use,0        ; mark handle as free
  516.     mov    bx,offset handles    ; check that all handles are free
  517. f_terminate_2:
  518.     cmp    [bx].in_use,0        ; is this handle free?
  519.     jne    f_terminate_4        ; ne = no, so can't exit completely
  520.     add    bx,(size per_handle)    ; next handle
  521.     cmp    bx,offset end_handles    ; examined all handles?
  522.     jb    f_terminate_2        ; b = no, continue examination
  523.  
  524.     call    terminate        ;terminate the hardware.
  525. ;
  526. ; Now disable interrupts
  527. ;
  528.     mov    al,int_no
  529.     call    maskint
  530.  
  531. ;
  532. ; Now return the interrupt to their handler.
  533. ;
  534.     mov    ah,25h            ;get the old interrupt into es:bx
  535.     mov    al,int_no
  536.     add    al,8
  537.     cmp    al,8+8            ;is it a slave 8259 interrupt?
  538.     jb    f_terminate_3        ;no.
  539.     add    al,70h - (8+8)        ;map it to the real interrupt.
  540. f_terminate_3:
  541.     push    ds
  542.     lds    dx,their_recv_isr
  543.     int    21h
  544.     pop    ds
  545.  
  546.     mov    al,packet_int_no    ;release our_isr.
  547.     mov    ah,25h
  548.     push    ds
  549.     lds    dx,their_isr
  550.     int    21h
  551.     pop    ds
  552.  
  553. ;
  554. ; Now free our memory
  555. ;
  556.     push    cs
  557.     pop    es
  558.     mov    ah,49h
  559.     int    21h
  560. f_terminate_4:
  561.     clc
  562.     ret
  563.  
  564.  
  565.  
  566. f_get_address:
  567.     call    verify_handle
  568. ;    mov    es,_ES[bp]        ; get new one
  569. ;    mov    di,_DI[bp]        ; get pointer, es:di is ready
  570.     mov    cx,_CX[bp]        ;Tell them how much room they have.
  571.     cmp    have_my_address,0    ;has our address been set?
  572.     jne    get_address_set        ;yes - go report it.
  573.     call    get_address        ;no, can we get the address?
  574.     jc    get_address_space    ;no - we must not have enough space.
  575.     mov    _CX[bp],cx        ;Tell them how long our address is.
  576.     clc
  577.     ret
  578. get_address_set:
  579.     cmp    cx,my_address_len    ;is there enough room?
  580.     jb    get_address_space    ;no.
  581.     mov    cx,my_address_len    ;yes - get our address length.
  582.     mov    _CX[bp],cx        ;Tell them how long our address is.
  583.     mov    si,offset my_address    ;copy it into their area.
  584.     rep    movsb
  585.     clc
  586.     ret
  587.  
  588. get_address_space:
  589.     mov    dh,NO_SPACE
  590.     stc
  591.     ret
  592.  
  593.  
  594. f_set_address:
  595.     mov    bx,offset handles
  596.     mov    cl,0            ;number of handles in use.
  597. f_set_address_1:
  598.     add    cl,[bx].in_use        ;is this handle in use?
  599.     add    bx,(size per_handle)    ;go to the next handle.
  600.     cmp    bx,offset end_handles
  601.     jb    f_set_address_1
  602.  
  603.     cmp    cl,1            ;more than one handle in use?
  604.     ja    f_set_address_inuse    ;yes - we can't set the address
  605.  
  606.     mov    ds,_ES[bp]        ; set new one
  607.     assume    ds:nothing
  608.     mov    si,_DI[bp]        ; set pointer, ds:si is ready
  609. ;    mov    cx,_CX[bp]        ;Tell them how much address is being set.
  610.     call    set_address
  611. ;set_address restores ds.
  612.     jc    f_set_address_exit    ;Did it work?
  613.     mov    _CX[bp],cx        ;yes - return our address length.
  614.  
  615.     cmp    cx,MAX_ADDR_LEN        ;is it too long for us to remember?
  616.     ja    f_set_address_too_long    ;yes, return a too-long error.
  617.  
  618.     mov    ds,_ES[bp]        ; set new one
  619.     mov    si,_DI[bp]        ; set pointer, ds:si is ready
  620.     mov    ax,cs
  621.     mov    es,ax
  622.     mov    my_address_len,cx    ;remember how long our address is.
  623.     mov    di,offset my_address
  624.     rep    movsb
  625.     mov    have_my_address,1
  626.     mov    ds,ax            ;restoer ds.
  627.     assume    ds:code
  628.     clc
  629.     ret
  630. f_set_address_inuse:
  631.     mov    dh,CANT_SET
  632.     stc
  633.     ret
  634. f_set_address_too_long:
  635.     mov    dh,NO_SPACE
  636.     stc
  637. f_set_address_exit:
  638.     ret
  639.  
  640.  
  641. f_reset_interface:
  642.     call    verify_handle
  643.     call    reset_interface
  644.     clc
  645.     ret
  646.  
  647.  
  648. f_get_parameters:
  649. ;strictly speaking, this function only works for high-performance drivers.
  650.     test    driver_function,4    ;is this a high-performance driver?
  651.     jne    f_get_parameters_1    ;yes.
  652.     mov    dh,BAD_COMMAND        ;no - return an error.
  653.     stc
  654.     ret
  655. f_get_parameters_1:
  656.     mov    _ES[bp],cs
  657.     mov    _DI[bp],offset parameter_list
  658.     clc
  659.     ret
  660.  
  661.  
  662. verify_handle:
  663. ;Ensure that their handle is real.  If it isn't, we pop off our return
  664. ;address, and return to *their* return address with cy set.
  665.     mov    bx,_BX[bp]        ;get the handle they gave us
  666.     cmp    bx,offset handles
  667.     jb    verify_handle_bad    ;no - must be bad.
  668.     cmp    bx,offset end_handles
  669.     jae    verify_handle_bad    ;no - must be bad.
  670.     cmp    [bx].in_use,0        ;if it's not in use, it's bad.
  671.     je    verify_handle_bad
  672.     ret
  673. verify_handle_bad:
  674.     mov    dh,BAD_HANDLE
  675.     add    sp,2            ;pop off our return address.
  676.     stc
  677.     ret
  678.  
  679.  
  680.     public    set_recv_isr
  681. set_recv_isr:
  682.     mov    ah,35h            ;get the old interrupt into es:bx
  683.     mov    al,int_no        ; board's interrupt vector
  684.     add    al,8
  685.     cmp    al,8+8            ;is it a slave 8259 interrupt?
  686.     jb    set_recv_isr_1        ;no.
  687.     add    al,70h - 8 - 8        ;map it to the real interrupt.
  688. set_recv_isr_1:
  689.     int    21h
  690.     mov    their_recv_isr.offs,bx    ;remember the old seg:off.
  691.     mov    their_recv_isr.segm,es
  692.  
  693.     mov    ah,25h            ;now set our recv interrupt.
  694.     mov    dx,offset recv_isr
  695.     int    21h
  696.  
  697.     mov    al,int_no        ; Now enable interrupts
  698.     call    unmaskint
  699.  
  700.     ret
  701.  
  702.     public    count_in_err
  703. count_in_err:
  704.     assume    ds:nothing
  705.     linc    errors_in
  706.     ret
  707.  
  708.     public    count_out_err
  709. count_out_err:
  710.     assume    ds:nothing
  711.     linc    errors_out
  712.     ret
  713.  
  714. their_recv_isr    dd    0        ; original owner of board int
  715.  
  716. recv_isr:
  717.     push    ax
  718.     push    ds
  719.     mov    ax,cs            ;ds = cs.
  720.     mov    ds,ax
  721.     assume    ds:code
  722.  
  723.     mov    savesp,sp
  724.     mov    savess,ss
  725.  
  726.     mov    ss,ax
  727.     mov    sp,offset our_stack
  728.     cld
  729.     sti
  730.  
  731.     push    bx
  732.     push    cx
  733.     push    dx
  734.     push    si
  735.     push    di
  736.     push    bp
  737.     push    es
  738.  
  739.     call    recv
  740.  
  741.     cli                ;interrupts *must* be off between
  742.                     ;here and the stack restore, because
  743.                     ;if we have one of our interrupts
  744.                     ;pending, we would trash our stack.
  745. ;
  746. ; The following code is ruthlessly stolen from Phil Karn's NET package.
  747. ;
  748.     test    sys_features,40h ; 2nd 8259 installed?
  749.     jz    recv_isr_3    ; Only one 8259, so skip this stuff
  750.     mov    al,0bh        ; read in-service register from
  751.     out    0a0h,al        ; secondary 8259
  752.     nop            ; settling delay
  753.     nop
  754.     nop
  755.     in    al,0a0h        ; get it
  756.     or    al,al        ; Any bits set?
  757.     jz    recv_isr_3    ; nope, not a secondary interrupt
  758.     mov    al,20h        ; Get EOI instruction
  759.     out    0a0h,al        ; Secondary 8259 (PC/AT only)
  760. recv_isr_3:
  761.     mov    al,20h            ;acknowledge the interrupt.
  762.     out    20h,al
  763.  
  764.     pop    es
  765.     pop    bp
  766.     pop    di
  767.     pop    si
  768.     pop    dx
  769.     pop    cx
  770.     pop    bx
  771.  
  772.     mov    ss,savess
  773.     mov    sp,savesp
  774.  
  775.     call    recv_exiting        ;this routine can enable interrupts.
  776.  
  777.     pop    ds
  778.     pop    ax
  779.     iret
  780.  
  781.  
  782.     public    maskint
  783. maskint:
  784.     or    al,al            ;are they using a hardware interrupt?
  785.     je    maskint_1        ;no, don't mask off the timer!
  786.  
  787.     assume    ds:code
  788.     mov    dx,21h            ;assume the master 8259.
  789.     cmp    al,8            ;using the slave 8259 on an AT?
  790.     jb    mask_not_irq2
  791.     mov    dx,0a1h            ;go disable it on slave 8259
  792.     sub    al,8
  793. mask_not_irq2:
  794.     mov    cl,al
  795.  
  796.     in    al,dx            ;disable them on the correct 8259.
  797.     mov    ah,1            ;set the bit.
  798.     shl    ah,cl
  799.     or    al,ah
  800.     out    dx,al
  801. maskint_1:
  802.     ret
  803.  
  804.  
  805. unmaskint:
  806.     assume    ds:code
  807.     mov    dx,21h            ;assume the master 8259.
  808.     cmp    al,8            ;using the slave 8259 on an AT?
  809.     jb    unmask_not_irq2
  810.     mov    dx,0a1h            ;go enable it on slave 8259
  811.     sub    al,8
  812. unmask_not_irq2:
  813.     mov    cl,al
  814.  
  815.     in    al,dx            ;enable interrupts on the correct 8259.
  816.     mov    ah,1            ;clear the bit.
  817.     shl    ah,cl
  818.     not    ah
  819.     and    al,ah
  820.     out    dx,al
  821.  
  822.     ret
  823.  
  824.  
  825.     public    recv_find
  826. recv_find:
  827. ;called when we want to determine what to do with a received packet.
  828. ;enter with cx = packet length, es:di -> packet type.
  829. ;exit with es:di = 0 if the packet is not desired, or es:di -> packet buffer
  830. ;  to be filled by the driver.
  831.     assume    ds:code, es:nothing
  832.     push    cx
  833.  
  834.     mov    bx,offset handles
  835. recv_find_1:
  836.     cmp    [bx].in_use,0        ;is this handle in use?
  837.     je    recv_find_2        ;no - don't check the type.
  838.     mov    ax,[bx].receiver.offs    ;do they have a receiver?
  839.     or    ax,[bx].receiver.segm
  840.     je    recv_find_2        ;no - they're not serious about it.
  841.     mov    cx,[bx].packet_type_len    ;compare the packets.
  842.     lea    si,[bx].packet_type
  843.     jcxz    recv_find_3        ;if cx is zero, they want them all.
  844.     push    di
  845.     repe    cmpsb
  846.     pop    di
  847.     je    recv_find_3        ;we've got it!
  848. recv_find_2:
  849.     add    bx,(size per_handle)    ;go to the next handle.
  850.     cmp    bx,offset end_handles
  851.     jb    recv_find_1
  852.  
  853.     linc    packets_dropped
  854.  
  855.     pop    cx            ;we didn't find it -- discard it.
  856.     xor    di,di            ;"return" a null pointer.
  857.     mov    es,di
  858.     ret
  859. recv_find_3:
  860.     pop    cx            ; the packet_length
  861.  
  862.     linc    packets_in
  863.     add    bytes_in.offs,cx    ;add up the received bytes.
  864.     adc    bytes_in.segm,0
  865.  
  866.     mov    ax,[bx].receiver.offs
  867.     mov    receive_ptr.offs,ax
  868.     mov    ax,[bx].receiver.segm
  869.     mov    receive_ptr.segm,ax
  870.     mov    found_handle,bx        ;remember what our handle was.
  871.     mov    ax,0            ;allocate request.
  872.     stc                ;with stc, flags must be an odd number
  873.     push    ax            ; save a number that cant be flags
  874.     pushf                ;save flags incase iret used.
  875. ; ssw
  876.  
  877.     mov    ax, [bx].receiver.segm    ;does the receiver signature
  878.     mov    es, ax            ; match whats currently in
  879.     mov    di, [bx].receiver.offs    ; memory?
  880.     mov    ax, es:[di]        ; if not, jump to fake return
  881.     cmp    ax, [bx].sig1
  882.     jne    not_there
  883.     inc    di
  884.     mov    ax, es:[di]
  885.     cmp    ax, [bx].sig2
  886.     jne    not_there
  887.     inc    di
  888.     mov    ax, es:[di]
  889.     cmp    ax, [bx].sig3
  890.     jne    not_there
  891.     inc    di
  892.     mov    ax, es:[di]
  893.     cmp    ax, [bx].sig4
  894.     jne    not_there
  895.     stc
  896.     mov    ax, 0
  897.     call    receive_ptr        ;ask the client for a buffer.
  898.     jmp     there
  899. not_there:
  900.     ; on return, flags should be at top of stack. if an IRET has nbeen used,
  901.     ; then 0 will be at the top of the stack
  902. ; ssw
  903.     mov     ax, 0            ; receiver was not there
  904.     mov     es, ax            ; fake a return from receiver
  905.     mov     di, ax            ; no buffer space
  906. ; ssw         
  907. there:
  908.     pop    bx
  909.     cmp    bx,0
  910.     je    recv_find_4        ;0 is at top of stack
  911.     add    sp,2
  912. recv_find_4:
  913.     ret
  914.  
  915.     public    recv_copy
  916. recv_copy:
  917. ;called after we have copied the packet into the buffer.
  918. ;enter with ds:si ->the packet, cx = length of the packet.
  919. ;preserve bx.
  920.     assume    ds:nothing, es:nothing
  921.     push    bx
  922.     mov    bx,found_handle
  923.  
  924.     mov    ax,1            ;store request.
  925.     clc                ;with clc, flags must be an even number
  926.     push    ax            ; save a number that cant be flags
  927.     pushf                ;save flags incase iret used.
  928.     call    receive_ptr        ;ask the client for a buffer.
  929.     pop    bx
  930.     cmp    bx,1            ;if this is a 1, IRET was used.
  931.     je    recv_copy_1
  932.     pop    bx
  933. recv_copy_1:
  934.     pop    bx
  935.     ret
  936.  
  937. code    ends
  938.  
  939.     end    start
  940.