home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / lan / drivrs30 / head.asm < prev    next >
Assembly Source File  |  1989-06-08  |  14KB  |  683 lines

  1.     include    defs.asm
  2.  
  3. ;  Copyright, 1988, 1989, Russell Nelson
  4.  
  5. ;   This program is free software; you can redistribute it and/or modify
  6. ;   it under the terms of the GNU General Public License as published by
  7. ;   the Free Software Foundation, version 1.
  8. ;
  9. ;   This program is distributed in the hope that it will be useful,
  10. ;   but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. ;   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12. ;   GNU General Public License for more details.
  13. ;
  14. ;   You should have received a copy of the GNU General Public License
  15. ;   along with this program; if not, write to the Free Software
  16. ;   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17.  
  18. code    segment byte public
  19.     assume    cs:code, ds:code
  20.  
  21.     public    phd_environ
  22.     org    2ch
  23. phd_environ    dw    ?
  24.  
  25.     public    phd_dioa
  26.     org    80h
  27. phd_dioa    label    byte
  28.  
  29.     org    100h
  30. start:
  31.     jmp    start_1
  32.     extrn    start_1: near
  33.  
  34. ;we use our dioa for a stack space.  Very hard usage has shown that only
  35. ;  27 bytes were being used, so 128 should be sufficient.
  36. our_stack    label    byte
  37.  
  38.  
  39.     extrn    int_no: byte
  40.     public    packet_int_no, is_at
  41. packet_int_no    db    ?,?,?,?        ; interrupt to communicate.
  42. is_at        dw    ?        ; =1 if we're on an AT.
  43.  
  44. functions    label    word
  45.     dw    f_driver_info        ;function 1
  46.     dw    f_access_type
  47.     dw    f_release_type
  48.     dw    f_send_pkt
  49.     dw    f_terminate
  50.     dw    f_get_address
  51.     dw    f_reset_interface    ;function 7
  52.     dw    f_set_rcv_mode        ;function 20
  53.     dw    f_get_rcv_mode
  54.     dw    f_set_multicast_list
  55.     dw    f_get_multicast_list
  56.     dw    f_get_statistics
  57.     dw    f_set_address        ;function 25
  58.  
  59.  
  60.     extrn    driver_class: byte
  61.     extrn    driver_type: byte
  62.     extrn    driver_name: byte
  63.  
  64.     extrn    send_pkt: near
  65.     extrn    get_address: near
  66.     extrn    set_address: near
  67.     extrn    reset_interface: near
  68.     extrn    recv: near
  69.  
  70.  
  71. MAX_P_LEN    equ    8        ;leave plenty of room.
  72.  
  73. per_handle    struc
  74. in_use        db    ?        ;non-zero if this handle is in use.
  75. packet_type    db    MAX_P_LEN dup(?);associated packet type.
  76. packet_type_len    dw    ?        ;associated packet type length.
  77. receiver    dd    ?        ;receiver handler.
  78.         db    ?        ;padding to get the length to 16.
  79. per_handle    ends
  80.  
  81.   if (size per_handle) NE 16
  82.     err    The size of the handle must be 16.
  83.   endif
  84.  
  85. max_handle    equ    8
  86. handles        db    max_handle*(size per_handle) dup(0)
  87. end_handles    label    byte
  88.  
  89. free_handle    dw    ?        ;->a handle not in use.
  90. found_handle    dw    ?        ;->the handle for our packet.
  91. receive_ptr    dd    ?        ;->the receive routine.
  92.  
  93. savess        dw    ?        ;saved during the stack swap.
  94. savesp        dw    ?
  95.  
  96. regs    struc
  97. _ES    dw    ?
  98. _DS    dw    ?
  99. _BP    dw    ?
  100. _DI    dw    ?
  101. _SI    dw    ?
  102. _DX    dw    ?
  103. _CX    dw    ?
  104. _BX    dw    ?
  105. _AX    dw    ?
  106. _IP    dw    ?
  107. _CS    dw    ?
  108. _F    dw    ?        ;flags, Carry flag is bit 0.
  109. regs    ends
  110.  
  111.  
  112. bytes    struc
  113.     dw    ?
  114.     dw    ?
  115.     dw    ?
  116.     dw    ?
  117.     dw    ?
  118. _DL    db    ?
  119. _DH    db    ?
  120. _CL    db    ?
  121. _CH    db    ?
  122. _BL    db    ?
  123. _BH    db    ?
  124. _AL    db    ?
  125. _AH    db    ?
  126. bytes    ends
  127.  
  128. segmoffs    struc
  129. offs        dw    ?
  130. segm        dw    ?
  131. segmoffs    ends
  132.  
  133.  
  134.     public    our_isr, their_isr
  135. their_isr    dd    ?
  136.  
  137. our_isr:
  138.     jmp    our_isr_0        ;the required signature.
  139.     db    'PKT DRVR',0
  140.  
  141. statistics_list    label    dword
  142. packets_in    dw    ?,?
  143. packets_out    dw    ?,?
  144. bytes_in    dw    ?,?
  145. bytes_out    dw    ?,?
  146. errors_in    dw    ?,?
  147. errors_out    dw    ?,?
  148. packets_dropped    dw    ?,?        ;dropped due to no type handler.
  149.  
  150. linc    macro    n
  151.     local    a
  152.     inc    n            ;increment the low word
  153.     jne    a            ;go if not overflow
  154.     inc    n+2            ;increment the high word
  155. a:
  156.     endm
  157.  
  158.     public    count_in_err
  159. count_in_err:
  160.     assume    ds:nothing
  161.     linc    errors_in
  162.     ret
  163.  
  164.     public    count_out_err
  165. count_out_err:
  166.     assume    ds:nothing
  167.     linc    errors_out
  168.     ret
  169.  
  170. our_isr_0:
  171.     assume    ds:nothing
  172.     push    ax
  173.     push    bx
  174.     push    cx
  175.     push    dx
  176.     push    si
  177.     push    di
  178.     push    bp
  179.     push    ds
  180.     push    es
  181.     cld
  182.     mov    bx,cs            ;set up ds.
  183.     mov    ds,bx
  184.     assume    ds:code
  185.     mov    bp,sp            ;we use bp to access the original regs.
  186.     and    _F[bp],not 1        ;start by clearing the carry flag.
  187.     mov    bl,ah            ;jump to the correct function.
  188.     mov    bh,0
  189.     cmp    bx,7            ;highest function is 7.
  190.     jbe    our_isr_3
  191.     cmp    bx,20
  192.     jb    our_isr_2
  193.     cmp    bx,25
  194.     ja    our_isr_2
  195.     sub    bx,20-7-1        ;map 20 right after 7.
  196. our_isr_3:
  197.     add    bx,bx            ;*2
  198.     jmp    functions-2[bx]        ;table starts at 1.
  199.  
  200. f_set_rcv_mode:
  201. f_get_rcv_mode:
  202. f_set_multicast_list:
  203. f_get_multicast_list:
  204. our_isr_2:
  205.     mov    dh,BAD_COMMAND
  206. our_isr_error:
  207.     mov    _DH[bp],dh
  208.     or    _F[bp],1        ;return their carry flag.
  209. our_isr_return:
  210.     pop    es
  211.     pop    ds
  212.     pop    bp
  213.     pop    di
  214.     pop    si
  215.     pop    dx
  216.     pop    cx
  217.     pop    bx
  218.     pop    ax
  219.     iret
  220.  
  221.  
  222. f_driver_info:
  223. ;    Under 1.08, the handle is optional, so we no longer verify it.
  224. ;    call    verify_handle
  225.     mov    _BX[bp],majver        ;version
  226.     mov    al,driver_class
  227.     mov    _CH[bp],al
  228.     mov    al,driver_type
  229.     cbw
  230.     mov    _DX[bp],ax
  231.     mov    _CL[bp],0        ;number zero.
  232.     mov    _DS[bp],ds
  233.     mov    _SI[bp],offset driver_name
  234.     mov    _AL[bp],2        ;extended driver
  235.     jmp    our_isr_return
  236.  
  237.  
  238. f_get_statistics:
  239.     call    verify_handle        ;just in case.
  240.     mov    _DS[bp],ds
  241.     mov    _SI[bp],offset statistics_list
  242.     jmp    our_isr_return
  243.  
  244.  
  245. access_type_class:
  246.     mov    dh,NO_CLASS
  247.     jmp    our_isr_error
  248.  
  249. access_type_type:
  250.     mov    dh,NO_TYPE
  251.     jmp    our_isr_error
  252.  
  253. access_type_number:
  254.     mov    dh,NO_NUMBER
  255.     jmp    our_isr_error
  256.  
  257. f_access_type:
  258.     mov    al,driver_class
  259.     cmp    _AL[bp],al        ;our class?
  260.     jne    access_type_class    ;no.
  261.     cmp    _BX[bp],-1        ;generic type?
  262.     je    access_type_2        ;yes.
  263.     mov    al,driver_type
  264.     cbw
  265.     cmp    _BX[bp],ax        ;our type?
  266.     jne    access_type_type    ;no.
  267. access_type_2:
  268.     cmp    _DL[bp],0        ;generic number?
  269.     je    access_type_3
  270.     cmp    _DL[bp],1        ;our number?
  271.     jne    access_type_number
  272. access_type_3:
  273.     cmp    _CX[bp],MAX_P_LEN    ;is the type length too long?
  274.     ja    access_type_inuse    ;yes - can't be ours.
  275. access_type_7:
  276.  
  277. ; now we do two things--look for an open handle, and check the existing
  278. ; handles to see if they're replicating a packet type.
  279.  
  280.     mov    free_handle,0        ;remember no free handle yet.
  281.     mov    bx,offset handles
  282. access_type_4:
  283.     cmp    [bx].in_use,0        ;is this handle in use?
  284.     je    access_type_5        ;no - don't check the type.
  285.     mov    es,_DS[bp]        ;get a pointer to their type.
  286.     mov    di,_SI[bp]
  287.     mov    cx,_CX[bp]        ;get the minimum of their length
  288.                     ;  and our length.  As currently
  289.                     ;  implemented, only one receiver
  290.                     ;  gets the packets, so we have to
  291.                     ;  ensure that the shortest prefix
  292.                     ;  is unique.
  293.     cmp    cx,[bx].packet_type_len    ;Are we less specific than they are?
  294.     jb    access_type_8        ;no.
  295.     mov    cx,[bx].packet_type_len    ;yes - use their count.
  296. access_type_8:
  297.     lea    si,[bx].packet_type
  298.     or    cx,cx            ;in case cx is zero.
  299.     repe    cmpsb
  300.     jne    short access_type_6    ;go look at the next one.
  301. access_type_inuse:
  302.     mov    dh,TYPE_INUSE
  303.     jmp    our_isr_error
  304. access_type_5:
  305.     cmp    free_handle,0        ;found a free handle yet?
  306.     jne    access_type_6        ;yes.
  307.     mov    free_handle,bx        ;remember a free handle
  308. access_type_6:
  309.     add    bx,(size per_handle)    ;go to the next handle.
  310.     cmp    bx,offset end_handles
  311.     jb    access_type_4
  312.  
  313.     mov    bx,free_handle        ;did we find a free handle?
  314.     or    bx,bx
  315.     je    access_type_handle    ;no - return error.
  316.  
  317.     mov    [bx].in_use,1        ;remember that we're using it.
  318.  
  319.     mov    ax,_DI[bp]        ;remember the receiver type.
  320.     mov    [bx].receiver.offs,ax
  321.     mov    ax,_ES[bp]
  322.     mov    [bx].receiver.segm,ax
  323.  
  324.     push    ds
  325.     mov    ax,ds
  326.     mov    es,ax
  327.     mov    ds,_DS[bp]        ;remember their type.
  328.     mov    si,_SI[bp]
  329.     mov    cx,_CX[bp]
  330.     mov    es:[bx].packet_type_len,cx    ;remember the length.
  331.     lea    di,[bx].packet_type
  332.     rep    movsb
  333.     pop    ds
  334.  
  335.     sub    bx,offset handles    ;compute the handle from the offset.
  336.     mov    cl,4
  337.     shr    bx,cl
  338.     mov    ax,cs            ;add our phd in.
  339.     add    bx,ax
  340.     mov    _AX[bp],bx        ;return the handle to them.
  341.  
  342.     jmp    our_isr_return
  343.  
  344.  
  345. access_type_handle:
  346.     mov    dh,BAD_HANDLE
  347.     jmp    our_isr_error
  348.  
  349.  
  350. f_release_type:
  351.     call    verify_handle        ;mark this handle as being unused.
  352.     mov    [bx].in_use,0
  353.     jmp    our_isr_return
  354.  
  355.  
  356. f_send_pkt:
  357.     linc    packets_out
  358.     add    bytes_out.offs,cx    ;add up the received bytes.
  359.     adc    bytes_out.segm,0
  360.  
  361.     push    ds        ; set up proper ds for the buffer
  362.     mov    ds,_DS[bp]    ; address for buffer
  363. ;following two instructions not needed because si and cx haven't been changed.
  364. ;    mov    si,_SI[bp]
  365. ;    mov    cx,_CX[bp]    ; count of bytes
  366.  
  367.     call    send_pkt
  368.     pop    ds
  369.     jc    send_pkt_1
  370.     jmp    our_isr_return
  371. send_pkt_1:
  372.     jmp    our_isr_error
  373.  
  374.  
  375. f_terminate:
  376. ;
  377. ; Now disable interrupts
  378. ;
  379.     mov    al,int_no
  380.     call    maskint
  381.  
  382. ;
  383. ; Now return the interrupt to their handler.
  384. ;
  385.     mov    ah,25h            ;get the old interrupt into es:bx
  386.     mov    al,int_no
  387.     add    al,8
  388.     cmp    al,8+8            ;is it a slave 8259 interrupt?
  389.     jb    terminate_1        ;no.
  390.     add    al,70h - (8+8)        ;map it to the real interrupt.
  391. terminate_1:
  392.     push    ds
  393.     lds    dx,their_recv_isr
  394.     int    21h
  395.     pop    ds
  396.  
  397.     mov    al,packet_int_no    ;release our_isr.
  398.     mov    ah,25h
  399.     push    ds
  400.     lds    dx,their_isr
  401.     int    21h
  402.     pop    ds
  403.  
  404. ;
  405. ; Now free our memory
  406. ;
  407.     push    cs
  408.     pop    es
  409.     mov    ah,49h
  410.     int    21h
  411.  
  412.     jmp    our_isr_return
  413.  
  414.  
  415. f_get_address:
  416.     call    verify_handle
  417. ;    mov    es,_ES[bp]        ; get new one
  418. ;    mov    di,_DI[bp]        ; get pointer, es:di is ready
  419. ;    mov    cx,_CX[bp]        ;Tell them how much room they have.
  420.     call    get_address
  421.     jc    get_address_space    ;no.
  422.     mov    _CX[bp],cx        ;Tell them how long our address is.
  423.     jmp    our_isr_return
  424.  
  425. get_address_space:
  426.     mov    dh,NO_SPACE
  427.     jmp    our_isr_error
  428.  
  429.  
  430. f_set_address:
  431.     mov    bx,offset handles
  432.     mov    dh,CANT_SET        ;if a handle in use, we can't set it.
  433. f_set_address_1:
  434.     cmp    [bx].in_use,0        ;is this handle in use?
  435.     je    f_set_address_error    ;yes - we can't set the address
  436.     add    bx,(size per_handle)    ;go to the next handle.
  437.     cmp    bx,offset end_handles
  438.     jb    f_set_address_1
  439.  
  440.     mov    ds,_ES[bp]        ; set new one
  441.     mov    si,_DI[bp]        ; set pointer, ds:si is ready
  442. ;    mov    cx,_CX[bp]        ;Tell them how much room they have.
  443.     call    set_address
  444. ;set_address restores ds.
  445.     jc    f_set_address_error    ;no.
  446.     mov    _CX[bp],cx        ;Tell them how long our address is.
  447.     jmp    our_isr_return
  448.  
  449. f_set_address_error:
  450.     jmp    our_isr_error
  451.  
  452.  
  453. f_reset_interface:
  454.     call    verify_handle
  455.     call    reset_interface
  456.     jmp    our_isr_return
  457.  
  458.  
  459. compute_handle:
  460. ;enter with the external representation of our handle in _BX[bp],
  461. ;exit with the offset of the handle in bx.
  462.     mov    bx,_BX[bp]        ;get the handle they gave us
  463.     mov    cx,cs
  464.     sub    bx,cx            ;subtract off our phd
  465.     mov    cl,4
  466.     shl    bx,cl            ;multiply by the size of the struct,
  467.     add    bx,offset handles    ;  and add the offset of the table.
  468.     ret
  469.  
  470.  
  471. verify_handle:
  472. ;Ensure that their handle is real.  Jump to our_isr_error if it
  473. ;isn't real.
  474.     call    compute_handle
  475.     cmp    bx,offset handles
  476.     jb    verify_handle_bad    ;no - must be bad.
  477.     cmp    bx,offset end_handles
  478.     jae    verify_handle_bad    ;no - must be bad.
  479.     cmp    [bx].in_use,0        ;if it's not in use, it's bad.
  480.     je    verify_handle_bad
  481.     ret
  482. verify_handle_bad:
  483.     mov    dh,BAD_HANDLE
  484.     add    sp,2            ;pop off our return address.
  485.     jmp    our_isr_error
  486.  
  487.  
  488.     public    set_recv_isr
  489. set_recv_isr:
  490.     mov    ah,35h            ;get the old interrupt into es:bx
  491.     mov    al,int_no
  492.     add    al,8
  493.     cmp    al,8+8            ;is it a slave 8259 interrupt?
  494.     jb    set_recv_isr_1        ;no.
  495.     add    al,70h - 8 - 8        ;map it to the real interrupt.
  496. set_recv_isr_1:
  497.     int    21h
  498.     mov    their_recv_isr.offs,bx
  499.     mov    their_recv_isr.segm,es
  500.  
  501.     mov    ah,25h            ;now set our recv interrupt.
  502.     mov    dx,offset recv_isr
  503.     int    21h
  504. ;
  505. ; Now enable interrupts
  506. ;
  507.     mov    al,int_no
  508.     call    unmaskint
  509.  
  510.     ret
  511.  
  512. their_recv_isr    dd    ?
  513.  
  514. recv_isr:
  515.     push    ax
  516.     push    ds
  517.     mov    ax,cs            ;ds = cs.
  518.     mov    ds,ax
  519.  
  520.     mov    savesp,sp
  521.     mov    savess,ss
  522.  
  523.     mov    ss,ax
  524.     mov    sp,offset our_stack
  525.     cld
  526.  
  527.     push    bx
  528.     push    cx
  529.     push    dx
  530.     push    si
  531.     push    di
  532.     push    bp
  533.     push    es
  534.  
  535.     call    recv
  536.  
  537. ;
  538. ; The following code is ruthlessly stolen from Phil Karn's NET package.
  539. ;
  540.     cmp    is_at,1
  541.     jnz    recv_isr_3    ; Only one 8259, so skip this stuff
  542.     mov    al,0bh        ; read in-service register from
  543.     out    0a0h,al        ; secondary 8259
  544.     nop            ; settling delay
  545.     nop
  546.     nop
  547.     in    al,0a0h        ; get it
  548.     or    al,al        ; Any bits set?
  549.     jz    recv_isr_3    ; nope, not a secondary interrupt
  550.     mov    al,20h        ; Get EOI instruction
  551.     out    0a0h,al        ; Secondary 8259 (PC/AT only)
  552. recv_isr_3:
  553.     mov    al,20h            ;acknowledge the interrupt.
  554.     out    20h,al
  555.  
  556.     pop    es
  557.     pop    bp
  558.     pop    di
  559.     pop    si
  560.     pop    dx
  561.     pop    cx
  562.     pop    bx
  563.  
  564.     mov    ss,savess
  565.     mov    sp,savesp
  566.  
  567.     pop    ds
  568.     pop    ax
  569.     iret
  570.  
  571.  
  572. maskint:
  573.     mov    dx,21h            ;assume the master 8259.
  574.     cmp    al,8            ;using the slave 8259 on an AT?
  575.     jb    mask_not_irq2
  576.     mov    dx,0a1h            ;go enable it on slave 8259
  577.     sub    al,8
  578. mask_not_irq2:
  579.     mov    cl,al
  580.  
  581.     in    al,dx            ;enable interrupts on the correct 8259.
  582.     mov    ah,1            ;set the bit.
  583.     shl    ah,cl
  584.     or    al,ah
  585.     out    dx,al
  586.  
  587.     ret
  588.  
  589.  
  590. unmaskint:
  591.     mov    dx,21h            ;assume the master 8259.
  592.     cmp    al,8            ;using the slave 8259 on an AT?
  593.     jb    unmask_not_irq2
  594.     mov    dx,0a1h            ;go enable it on slave 8259
  595.     sub    al,8
  596. unmask_not_irq2:
  597.     mov    cl,al
  598.  
  599.     in    al,dx            ;enable interrupts on the correct 8259.
  600.     mov    ah,1            ;clear the bit.
  601.     shl    ah,cl
  602.     not    ah
  603.     and    al,ah
  604.     out    dx,al
  605.  
  606.     ret
  607.  
  608.  
  609.     public    recv_find
  610. recv_find:
  611. ;called when we want to determine what to do with a received packet.
  612. ;enter with cx = packet length, es:di -> packet type.
  613.     assume    ds:code, es:nothing
  614.     push    cx
  615.  
  616.     mov    bx,offset handles
  617. recv_find_1:
  618.     cmp    [bx].in_use,0        ;is this handle in use?
  619.     je    recv_find_2        ;no - don't check the type.
  620.     mov    ax,[bx].receiver.offs    ;do they have a receiver?
  621.     or    ax,[bx].receiver.segm
  622.     je    recv_find_2        ;no - they're not serious about it.
  623.     mov    cx,[bx].packet_type_len    ;compare the packets.
  624.     lea    si,[bx].packet_type
  625.     or    cx,cx            ;in case cx is zero.
  626.     push    di
  627.     repe    cmpsb
  628.     pop    di
  629.     je    recv_find_3        ;we've got it!
  630. recv_find_2:
  631.     add    bx,(size per_handle)    ;go to the next handle.
  632.     cmp    bx,offset end_handles
  633.     jb    recv_find_1
  634.  
  635.     linc    packets_dropped
  636.  
  637.     pop    cx            ;we didn't find it -- discard it.
  638.     xor    di,di            ;"return" a null pointer.
  639.     mov    es,di
  640.     jmp    short recv_find_4
  641. recv_find_3:
  642.     pop    cx            ; the packet_length
  643.  
  644.     linc    packets_in
  645.     add    bytes_in.offs,cx    ;add up the received bytes.
  646.     adc    bytes_in.segm,0
  647.  
  648.     mov    ax,[bx].receiver.offs
  649.     mov    receive_ptr.offs,ax
  650.     mov    ax,[bx].receiver.segm
  651.     mov    receive_ptr.segm,ax
  652.  
  653.     sub    bx,offset handles    ;compute the handle number from
  654.     shr    bx,1            ;  the handle offset.
  655.     shr    bx,1
  656.     shr    bx,1
  657.     shr    bx,1
  658.     mov    ax,cs            ;add our phd in.
  659.     add    bx,ax
  660.  
  661.     mov    found_handle,bx        ;remember what our handle was.
  662.     mov    ax,0            ;allocate request.
  663.     call    receive_ptr        ;ask the client for a buffer.
  664. recv_find_4:
  665.     ret
  666.  
  667.  
  668.     public    recv_copy
  669. recv_copy:
  670. ;called after we have copied the packet into the buffer.
  671. ;enter with ds:si ->the packet, cx = length of the packet.
  672.     assume    ds:nothing, es:nothing
  673.     push    bx
  674.     mov    bx,found_handle
  675.     mov    ax,1            ;store request.
  676.     call    receive_ptr        ;ask the client for a buffer.
  677.     pop    bx
  678.     ret
  679.  
  680. code    ends
  681.  
  682.     end    start
  683.