home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / PROGRAMS / UTILS / NOVELL / PKTDRV7.ZIP / 3C505.ASM < prev    next >
Encoding:
Assembly Source File  |  1990-07-27  |  19.7 KB  |  880 lines

  1. version    equ    1
  2.  
  3.     include    defs.asm    ;SEE ENCLOSED COPYRIGHT MESSAGE
  4.  
  5. ; PC/FTP Packet Driver Source, conforming to version 1.08 of spec
  6. ; Krishnan Gopalan and Gregg Stefancik, Clemson Univesity Engineering
  7. ; Computer Operations.
  8. ; Date: September 1, 1989
  9. ; Portions of the code have been adapted from the 3c505 driver for NCSA
  10. ; Telnet by Bruce Orchard and later modified by Warren Van Houten and krus
  11. ; @diku.dk.
  12.  
  13. ; Permission is granted to any individual or institution to use,copy,
  14. ; modify or redistribute this software provided this notice is retained.
  15. ; The authors make no guarantee to the suitability of the software for
  16. ; any purpose. Any damage caused by using this program is the responsibility
  17. ; of the user and not the authors. 
  18.  
  19. code    segment    word public
  20.     assume    cs:code, ds:code
  21.  
  22. ;    3c505 card definitions
  23. ;control register    bit definitions
  24. EN_ATTN            equ    0200q
  25. EN_FLSH_DATA        equ    0100q
  26. EN_DMA_ENABLE        equ    0040q
  27. EN_TO_HOST        equ    0020q
  28. EN_TERMINAL_CNT_ENBLE     equ    0010q
  29. EN_COMMAND_ENABLE    equ    0004q
  30. EN_HSF2            equ    0002q
  31. EN_HSF1            equ    0001q
  32.  
  33. ;status register    bit definitions
  34.  
  35. EN_DATA_READY        equ    0200q
  36. EN_HOST_COMMAND_EMPTY    equ    0100q
  37. EN_ADAPTER_COMMAND_FULL equ    0040q
  38. EN_TO_HOST        equ    0020q
  39. EN_DMA_DONE        equ    0010q
  40. EN_ASF3            equ    0004q
  41. EN_ASF2            equ    0002q
  42. EN_ASF1            equ    0001q
  43. ; auxiliary dma register  bit definition
  44. EN_BURST        equ    0001q
  45.  
  46. ; timeout values
  47. SECOND        EQU    36
  48. RESDEL        EQU    6
  49. RESTO        EQU    15*SECOND
  50. CMDBTO        EQU    6
  51. CMDCTO        EQU    6
  52. RETRYDELAY      EQU    6
  53. RCMDTO        EQU    6
  54. RESPTO        EQU    6
  55.  
  56. ;port addresses
  57. ECOMMAND    equ    0
  58. ESTATUS     equ    2
  59. EDATA         equ    4
  60. ECONTROL     equ    6
  61.  
  62. recvbuf        db  4096 dup(?)        ; size of receive buffer
  63. rbufct        dw    ?        ; recv buffer count
  64.  
  65. pcblen        dw     ?        ; length of pcb
  66. pcbaddr        dw    ?        ; address of pcb
  67.  
  68. lastcon        db    ?        ; last control to board
  69. cmdlen        dw    ?        ; length of command
  70.  
  71. cbsh        equ    50
  72. cbs        equ    cbsh*2    
  73.  
  74. icmdb        db    cbs dup(?)
  75. icmd        db    cbsh dup(?)
  76.  
  77. fconc        db    0    ; flag configure 82586
  78. fgeth        db    0    ; flag:get ethernet address
  79. fseth        db    0    ; flag:set ethernet address
  80. fxmit        db    0    ; flag:transmit packet
  81.  
  82. cconc        db    02h    ; command configure 82586
  83.         db    2    ; 2 more bytes
  84.         dw    1    ; receive broadcasts
  85.  
  86. rconc        db    2 dup(?);Response; configure
  87. rconc_st    dw    ?    ; status
  88.  
  89. cgeth        db    03h    ; command get ethernet address
  90.         db    00    ; no more bytes
  91.  
  92. txmit        db    09h    ; command ; transmit packet
  93.         db    06    ; 6 more bytes
  94. tx_offset    dw    ?    ; offset of host transmit buffer 
  95. tx_segment    dw    ?    ; segment of host transmit buffer 
  96. tx_length    dw    ?    ; packet length
  97.  
  98. rxmit        db    2 dup(?); Response tx packet
  99. rx_offset    dw    ?    ; buffer offset
  100. rx_segment    dw    ?    ; buffer segment
  101. rx_status    dw    ?    ; completion status
  102. rx_cstatus    dw    ?    ; 82586 status
  103.  
  104. rgeth        db    2 dup(?); Response get Ethernet address
  105. rgeth_ad    db    6 dup(?); -- address
  106.  
  107. cseth        db    10h    ; command :set station address
  108.         db    6    ; 6 more bytes
  109. cseth_ad    db    6 dup(?); ethernet address
  110.  
  111. rseth        db    2 dup(?); response set ethernet address
  112. rseth_status    dw    ?    ; status
  113.  
  114. crecv        db    08h    ; command receive
  115.         db    08    ; 8 more bytes
  116. crecv_offset    dw    ?    ; buffer offset
  117. crecv_segment    dw    ?    ; buffer segment
  118. crecv_length    dw    ?    ; buffer length
  119. crecv_timeout    dw    ?    ; timeout
  120.  
  121. rr        db    2 dup(?); Response; receive
  122. rr_offset    dw    ?    ; buffer offset
  123. rr_segment    dw    ?    ; buffer segment
  124. rr_dmalen    dw    ?    ; buffer dmalen
  125. rr_length    dw    ?    ; packet length
  126. rr_status    dw    ?    ; completion status
  127. rr_rstatus    dw    ?    ; 82586 receive status
  128. rr_time        dd    ?    ; time tag
  129.         
  130. public    int_no,io_addr,mem_base
  131.  
  132. int_no     db    2,0,0,0            ;must be four bytes long for get_number.
  133. io_addr dw    0300h,0            ; io addr for card(jumpers)
  134. mem_base dw    0d000h,0        ; shared memory address(software)
  135.  
  136. public    driver_class, driver_type, driver_name, driver_function, parameter_list
  137.  
  138. driver_class    db    1        ;from the packet spec 
  139. driver_type    db    2        ;from the packet spec 
  140. driver_name    db    '3C505',0    ;name of the driver.  
  141. driver_function    db    2
  142. parameter_list    label    byte
  143.     db    1    ;major rev of packet driver
  144.     db    9    ;minor rev of packet driver
  145.     db    14    ;length of parameter list
  146.     db    EADDR_LEN    ;length of MAC-layer address
  147.     dw    GIANT    ;MTU, including MAC headers
  148.     dw    MAX_MULTICAST * EADDR_LEN    ;buffer size of multicast addrs
  149.     dw    0    ;(# of back-to-back MTU rcvs) - 1
  150.     dw    0    ;(# of successive xmits) - 1
  151. int_num    dw    0    ;Interrupt # to hook for post-EOI
  152.             ;processing, 0 == none,
  153.  
  154.     public    rcv_modes
  155. rcv_modes    dw    4        ;number of receive modes in our table.
  156.         dw    0,0,0,rcv_mode_3
  157.  
  158.     public    as_send_pkt
  159. ; The Asynchronous Transmit Packet routine.
  160. ; Enter with es:di -> i/o control block, ds:si -> packet, cx = packet length,
  161. ;   interrupts possibly enabled.
  162. ; Exit with nc if ok, or else cy if error, dh set to error number.
  163. ;   es:di and interrupt enable flag preserved on exit.
  164. as_send_pkt:
  165.     ret
  166.  
  167.     public    drop_pkt
  168. ; Drop a packet from the queue.
  169. ; Enter with es:di -> iocb.
  170. drop_pkt:
  171.     assume    ds:nothing
  172.     ret
  173.  
  174.     public    xmit
  175. ; Process a transmit interrupt with the least possible latency to achieve
  176. ;   back-to-back packet transmissions.
  177. ; May only use ax and dx.
  178. xmit:
  179.     assume    ds:nothing
  180.     ret
  181.  
  182.  
  183.     public    send_pkt
  184. send_pkt:
  185. ;enter with es:di->upcall routine, (0:0) if no upcall is desired.
  186. ;  (only if the high-performance bit is set in driver_function)
  187. ;enter with ds:si -> packet, cx = packet length.
  188. ;exit with nc if ok, or else cy if error, dh set to error number.
  189.     assume    ds:nothing
  190.  
  191.     push    si            ; save si for  lodsw
  192.     push    ds            ; save ds
  193.     push    es            ; save es for timer
  194.     push    cs            ;
  195.     pop    ds            ; cs = ds align
  196.  
  197.     mov    tx_segment,ds        ;tx->data
  198.     mov    tx_offset,si        ;tx_offset ->segment offset 
  199.  
  200.     mov    ax,cx            ; save cx
  201.     cmp    ax,60            ; compare with minimum limit
  202.     jnb    pkt_ok            ; go if ok 
  203.     mov    ax,60            ; make length minimum allowed
  204. pkt_ok:
  205.     inc    ax            ; round up
  206.     sar    ax,1            ; divide by 2
  207.     shl    ax,1            ; multiply by 2
  208.     mov    tx_length,ax        ; put in request
  209.     
  210.     mov    fxmit,0            ; clear response received flag
  211.  
  212.     mov    si, offset txmit    ; si->request(pcb)
  213.     mov    ax,8            ;length of pcb 
  214.  
  215.     call    outpcb            ; send command to board
  216.  
  217.     mov    cx,tx_length
  218.     sar    cx,1
  219.  
  220.     pop    es
  221.     pop    ds
  222.     pop    si
  223.  
  224. tx_1:
  225.  
  226.     lodsw
  227.  
  228.     loadport
  229.     setport    EDATA
  230.     out    dx,ax            ; output word
  231.     setport    ESTATUS
  232. tx_2:
  233.     in    al,dx            ; get status
  234.     test    al, EN_DATA_READY    ; ready for next word ?
  235.     jz    tx_2            ;no
  236.  
  237.     dec    cx            ; count word
  238.     jnz    tx_1            ; loop thru buffer
  239.  
  240. tx_3:
  241.     test    fxmit,0ffh        ; is transmit over
  242.     jz    tx_3            ; no
  243.     ret
  244.  
  245.     public    get_address
  246.  
  247.  
  248. get_address:
  249. ;get the address of the interface.
  250. ;enter with es:di -> place to get the address, cx = size of address buffer.
  251. ;exit with nc, cx = actual size of address, or cy if buffer not big enough.
  252.     assume    ds:code
  253.     push    es
  254.     push    di
  255.  
  256.     cmp    cx, EADDR_LEN        ; does caller want reasonable length?
  257.     jb    get_addr_fail        ; no , fails
  258.     mov    si,offset cgeth        ; si->pcb address
  259.     mov    ax,2            ; length of pcb
  260.     mov    fgeth,0            ; clear response received flag
  261.  
  262.     call    outpcb        
  263.  
  264.     mov    ax,RESTO        ; get wait time
  265.     call    set_timeout
  266. get_addr_1:
  267.     test    fgeth,0ffh        ; answered?
  268.     jnz    get_addr_2        ; yes
  269.     call    do_timeout
  270.     jnz    get_addr_1        ; test again
  271.     jmp    get_addr_fail        ; go return
  272.  
  273. get_addr_2:
  274.     pop    di
  275.     pop    es
  276.     cld                ; make sure of string operation
  277.     mov    si,offset rgeth_ad    ; load source of address
  278.     mov    cx,EADDR_LEN        ; return length of address
  279.     rep    movsb            ; copy address
  280.     mov    cx,EADDR_LEN        ; return length of address
  281.     clc
  282.     ret
  283. get_addr_fail:
  284.     add sp,4
  285.     stc
  286.     ret
  287.  
  288.     public    set_address
  289.  
  290. set_address:
  291. ;enter with ds:si -> Ethernet address, CX = length of address.
  292. ;exit with nc if okay, or cy, dh=error if any errors.
  293.     assume    ds:nothing
  294.  
  295.     cmp    cx, EADDR_LEN        ; check if address ok
  296.     je    set_addr_1    
  297.     mov    dh,BAD_ADDRESS        ; don't like length
  298.     stc
  299.     ret
  300. set_addr_1:
  301.     mov    di,offset cseth_ad    ;di->destination offset
  302.     rep    movsb            ; return address
  303.     mov    si,offset cseth        ; si->request ethernet address
  304.     mov    ax,8            ; request length -> ax
  305.     mov    fseth,0            ; clear response received flag
  306.     call     outpcb            ; send the pcb
  307.  
  308.     mov    ax,RESTO        ; get response time
  309.     call    set_timeout
  310. set_addr_2:
  311.     test    fseth,0ffh        ; pcb answered?
  312.     jnz    set_addr_3
  313.     call    do_timeout        ; has time expired
  314.     jne    set_addr_2        ; no, go back
  315.     stc                ; error
  316.     ret
  317. set_addr_3:
  318.     mov    cx,EADDR_LEN        ;return their address length.
  319.     clc
  320.     ret
  321.  
  322. rcv_mode_3:
  323. ;receive mode 3 is the only one we support, so we don't have to do anything.
  324.     ret
  325.  
  326.  
  327.     public    set_multicast_list
  328. set_multicast_list:
  329. ;enter with ds:si ->list of multicast addresses, cx = number of addresses.
  330. ;return nc if we set all of them, or cy,dh=error if we didn't.
  331.     mov    dh,NO_MULTICAST
  332.     stc
  333.     ret
  334.  
  335.  
  336.     public    terminate
  337. terminate:
  338.     ret
  339.  
  340.     public    reset_interface
  341. reset_interface:
  342. ;reset the interface.
  343.     assume    ds:code
  344.  
  345.     mov    al, EN_ATTN OR EN_FLSH_DATA    ; hard reset command
  346.     loadport
  347.     setport    ECONTROL
  348.     out    dx,al                ; do reset
  349.     mov    ax,RESDEL            ; get reset delay
  350.     call    set_timeout
  351. rst1:
  352.     call    do_timeout
  353.     jne    rst1                ; wait for reset
  354.     mov    al,EN_COMMAND_ENABLE        ; command interrupt enable
  355.     mov    lastcon,al            ; save last command
  356.     out    dx,al                ; release reset
  357.     mov    ax,RESDEL
  358.     call    set_timeout
  359. rst2:
  360.     call    do_timeout
  361.     jne    rst2                ; wait to start reset
  362.     mov    ax,RESTO            ; add time out
  363.     call    set_timeout
  364. rst3:
  365.     call getstat                ; getstatus    
  366.     and    ax,EN_ASF1 OR EN_ASF2        ; 
  367.     cmp    ax,EN_ASF1 OR EN_ASF2        ;  both on ?
  368.     jne     resdone
  369.     call    do_timeout            ; long enough?
  370.     jne    rst3                ; no
  371.     ret
  372. resdone:
  373.     ret
  374. ;called when we want to determine what to do with a received packet.
  375. ;enter with cx = packet length, es:di -> packet type.
  376.     extrn    recv_find: near
  377.  
  378. ;called after we have copied the packet into the buffer.
  379. ;enter with ds:si ->the packet, cx = length of the packet.
  380.     extrn    recv_copy: near
  381.  
  382.     extrn    count_in_err: near
  383.     extrn    count_out_err: near
  384.  
  385.     public    recv
  386. recv:
  387. ;called from the recv isr.  All registers have been saved, and ds=cs.
  388. ; all interrupts come here
  389. ;Upon exit, the interrupt will be acknowledged.
  390.     assume    ds:code
  391.     ;sti
  392.     cld
  393. recv1:
  394.     loadport
  395.     setport    ESTATUS
  396.     in    al,dx                ; read flags
  397.     and    al,EN_ADAPTER_COMMAND_FULL    ; 
  398.     jnz    recv2                ; yes,full
  399.     jmp    interrupt_done    
  400. ;there might be a response, clear flags to check for response
  401. recv2:
  402.     mov    ax,RCMDTO            ; incoming command time out
  403.     call    set_timeout
  404.  
  405.     mov    al,lastcon            ; last control->ax
  406.     and    al,NOT (EN_HSF1 OR EN_HSF2)    ; clear flags
  407.     mov    lastcon,al
  408.  
  409.     loadport
  410.     setport    ECONTROL
  411.     out    dx,al                ; clear flags in cntl reg
  412.  
  413.     mov    di,offset icmdb            ; di->incoming command buffer
  414.  
  415. recv3:
  416.     loadport
  417.     setport    ESTATUS
  418.     in    al,dx                ; status->al
  419.  
  420.     mov    cx,ax                ; status->cx
  421.     test    al,EN_ADAPTER_COMMAND_FULL    ; is adapter register full
  422.     jnz    recv4                ; yes go ahead to read from
  423.     call    do_timeout            ; is time up ? 
  424.     jne    recv3                ; give some more time
  425.     jmp    int1                ; give up
  426. recv4:
  427.     loadport
  428.     setport    ECOMMAND
  429.     in    al,dx                ; get command byte
  430.     and    cl,EN_ASF1 OR EN_ASF2        
  431.     cmp    cl,EN_ASF1 OR EN_ASF2        ; both on?
  432.     je    recv5                ; end of command
  433.     mov    [di],al                ;save byte
  434.     inc    di                ;inc    di 
  435.     mov    ax,di                ; current pointer->ax
  436.     sub    ax,offset icmdb            ; - start of buffer
  437.     cmp    ax,cbs                ; full?
  438.     jl    recv3
  439.  
  440.     mov    si,(offset icmdb)+cbsh        ; si->middle of buffer
  441.     mov    di,offset icmdb            ; di->start of buffer
  442.     mov    cx,cbsh                ; size of half buffer->cx
  443.     push    ds
  444.     pop    es
  445.     rep    movsb
  446.  
  447.     jmp    recv3                ; loop for more bytes
  448. recv5:
  449.     push    ds
  450.     pop    es
  451.     mov    ah,0
  452.     mov    cmdlen,ax            ; save cmdlen
  453.     mov    si,di 
  454.     sub    si,cmdlen
  455.     mov    di,offset icmd    
  456.     mov    cx,cmdlen
  457.  
  458.     rep movsb                ; copy
  459.  
  460.     mov    al,icmd                ; check
  461.  
  462.     cmp    al,32h                ; Configure?
  463.     je    respconfig
  464.  
  465.     cmp    al,33h                ; get ethernet address?
  466.     je    respgetaddr            ; yes
  467.  
  468.     cmp    al,39h                ; transmit complete?
  469.     je    transmit            ; yes
  470.  
  471.     cmp    al,40h                ; set ethernet address
  472.     je    respsetaddr            ; yes
  473.     
  474.     cmp    al,38h                ; receive complete?
  475.     je    resprecv
  476.  
  477.     jmp    int1
  478.  
  479. respconfig:
  480.  
  481.     push    ds
  482.     pop    es
  483.     mov    si,offset icmd
  484.     mov    di,offset rconc
  485.     mov    cx,2
  486.     
  487.     rep    movsw
  488.     mov    fconc,1
  489.     jmp    int1
  490.     
  491. respgetaddr:
  492.     push    ds
  493.     pop    es
  494.  
  495.     mov    si,offset icmd
  496.     mov    di,offset rgeth
  497.     mov    cx,4
  498.  
  499.     rep    movsw
  500.  
  501.     mov    fgeth,1
  502.     jmp    int1
  503.  
  504. respsetaddr:
  505.  
  506.     mov    si,offset icmd        ; si->command received
  507.     mov    di,offset cseth        ; di->set ethernet address resp
  508.     push    ds
  509.     pop    es
  510.     mov    cx,2
  511.  
  512.     rep    movsw
  513.     mov    fseth,1
  514.     jmp    int1
  515.  
  516. transmit:
  517.     mov    si,offset icmd            ; si->command received
  518.     mov    di,offset rxmit            ; response,transmit packet
  519.     push    ds
  520.     pop    es
  521.     mov    cx,5                ; response length->cx
  522.     rep    movsw
  523.  
  524.     mov    fxmit,1                ; response received
  525.     jmp    int1                ; return from interrupt
  526.  
  527. resprecv:
  528.     mov    si,offset icmd            ; si->command received
  529.     mov    di,offset rr            ; di->receive response
  530.     push    ds
  531.     pop    es
  532.     mov    cx,9                ; response length->cx
  533.     
  534.     rep    movsw                ; move response
  535.     mov    di,offset recvbuf        ; di->receive buffer
  536.     mov    ax,rr_length            ; message size->ax
  537.     inc    ax                ; round up
  538.     shr    ax,1                ; convert to words
  539.     shl    ax,1                ; convert to characters
  540.     mov    rr_length,ax            ; ax->message length
  541.  
  542.     mov    cx,ax                ; message length->cx
  543.     shr    cx,1                ; convert to words
  544.  
  545.     mov    al,lastcon            ; lastcontrol->al
  546.     or    al,EN_TO_HOST OR EN_HSF1    ; set direction & ack    
  547.     mov    lastcon,al            ; response
  548.  
  549.     loadport
  550.     setport    ECONTROL
  551.     out    dx,al                ; pass direction
  552.     
  553.     setport ESTATUS
  554.  
  555. resprecv_1:
  556.  
  557.     in    al,dx                ; get status
  558.     test    al,EN_DATA_READY        ; data ready ?
  559.     jz    resprecv_1
  560.  
  561.     setport    EDATA                ; data word->ax
  562.     in    ax,dx                ; get word
  563.     stosw                    ; store word in buffer
  564.  
  565.     setport    ESTATUS
  566.     dec    cx                ; count word
  567.     jnz    resprecv_1            ; loop if more words
  568.  
  569.     mov    al,lastcon
  570.     and    al,NOT (EN_TO_HOST OR EN_HSF1)
  571.     mov    lastcon,al
  572.  
  573.     loadport                ; dx->control register
  574.     setport    ECONTROL
  575.     out    dx,al
  576.  
  577.     mov    cx,rr_length            ; cx->packet length
  578.  
  579.     push    cs                ; align cs and ds
  580.     pop    ds
  581.  
  582.     mov    di,offset recvbuf        ; reset di to beginning
  583.     add    di,EADDR_LEN+EADDR_LEN        ; point to type field
  584.                         ; of buffer
  585.     assume    ds:code
  586.  
  587.     call    recv_find            ; first call
  588.  
  589.     assume    ds:nothing
  590.     mov    ax,es                ; ax->es
  591.     or    ax,di                ; is es=di=0?
  592.     je    rcv_no_copy
  593.  
  594.     mov    cx,rr_length            ; cx->packet length
  595.     push    cx
  596.     push    es
  597.     push    di
  598.  
  599.     mov    si,offset recvbuf        ; prepare to copy the packet
  600.     rep    movsb                ; copy
  601.  
  602.     pop    si
  603.     pop    ds
  604.     pop    cx
  605.  
  606.     call    recv_copy            ; second call 
  607. rcv_no_copy:
  608.     push    cs
  609.     pop    ds
  610.     call    anotherrecv            ; start another recv
  611. int1:
  612.     jmp    recv1
  613.  
  614. interrupt_done:
  615.     ret
  616.  
  617. ;*****************************OUTPCB***********************************
  618. ;outpcb     send pcb to board, retry until accepted
  619. ; entry    ax = number of bytes in pcb
  620. ;    si = address of pcb
  621. outpcb    proc     near
  622.     mov    pcblen,ax        ; save pcb length
  623.     mov    pcbaddr,si        ; save pcb address
  624. pcb_0:
  625.     mov    cx,pcblen        ;length->cx
  626.     mov    si,pcbaddr        ; address->si
  627.     cli                ; stop interrupts
  628.     mov    al,lastcon        ; save last command
  629.     and    al, NOT (EN_HSF1 OR EN_HSF2); clear flags
  630.     mov    lastcon,al
  631.     sti                ; enable interrupts
  632.     loadport
  633.     setport    ECONTROL
  634.     out    dx,al            ; send control
  635.     setport    ECOMMAND
  636. pcb_1:
  637.     mov    al,[si]            ; 
  638.     out    dx,al            ; send command byte
  639.     mov    ax,CMDBTO        ; get time out
  640.     call    set_timeout
  641. chk_hcre:
  642.     call    getstat
  643.     and    al, EN_HOST_COMMAND_EMPTY    ; command accepted
  644.     jne    pcb_2                ; go on
  645.     call    do_timeout
  646.     jne    chk_hcre            ; time is still left
  647.     jmp    cmdretry            ; retry command
  648. pcb_2:
  649.     inc    si                ; increment source pointer
  650.     dec    cx                ; count byte
  651.     jg    pcb_1                ; loop         
  652.     loadport
  653.     setport    ECONTROL
  654.     cli                    ; disable interrupts
  655.     mov    al,lastcon            ; last control -> al
  656.     or    al,(EN_HSF1 OR EN_HSF2)        ; set end of command
  657.     mov    lastcon,al            ; save last control
  658.     out    dx,al                ; send flag bits
  659.     setport    ECOMMAND
  660.     mov    ax,pcblen
  661.     out    dx,al                ; send pcb length
  662.     sti                    ; enable interrupts
  663.     mov    ax,CMDCTO            ; time out for acceptance
  664.     call    set_timeout
  665. pcb_3:
  666.     call    getstat
  667.     and    al,(EN_ASF1 OR EN_ASF2)        ; just keep status flags
  668.     cmp    al,1                ; accepted
  669.     je    cmdaccept
  670.     cmp    al,2
  671.     je    cmdretry
  672.     call    do_timeout
  673.     jne    pcb_3
  674.  
  675. cmdretry:
  676.     mov    ax,RETRYDELAY            ;add retry delay
  677.     call    set_timeout
  678. pcb_4:
  679.     call    do_timeout
  680.     jne    pcb_4
  681.     jmp    pcb_0
  682.  
  683. cmdaccept:
  684.     cli
  685.     mov    al,lastcon
  686.     and    al, NOT (EN_HSF1 OR EN_HSF2)    ; turn off end of command flag
  687.     mov    lastcon,al            ; save last control
  688.     sti                    ; enable interrupts
  689.     loadport
  690.     setport    ECONTROL
  691.     out    dx,al                ; pass control byte
  692.     ret    
  693. outpcb    endp
  694. ;*************get status of board***********************
  695. getstat        proc    near
  696.     push    bx
  697.     push    dx
  698.     loadport
  699.     setport    ESTATUS
  700.  
  701. stat_1:
  702.     in    al,dx            ; get status into al
  703.     mov    bl,al            ; save al
  704.     in    al,dx            ; get status again
  705.     cmp    al,bl            ; same status ?
  706.     jne    stat_1
  707.     pop    dx
  708.     pop    bx
  709.     ret
  710. getstat    endp
  711.  
  712. ; UPDATE BUFFER POINTERS AND ISSUE ANOTHER RECV
  713. ;    update recv 
  714. anotherrecv    proc    near
  715.     mov    ax,rbufct
  716.     mov    crecv_offset,ax
  717.     inc    ax
  718.     mov    rbufct,ax
  719.     mov    ax,10
  720.     mov    si,offset crecv
  721.  
  722.     call    outpcb
  723.     ret
  724. anotherrecv    endp
  725.  
  726.     public    recv_exiting
  727. recv_exiting:
  728. ;called from the recv isr after interrupts have been acknowledged.
  729. ;Only ds and ax have been saved.
  730.     assume    ds:nothing
  731.     ret
  732.  
  733.     include    timeout.asm
  734.  
  735. ;any code after this will not be kept after initialization.
  736. end_resident    label    byte
  737.  
  738.     public    usage_msg
  739. usage_msg  db  "usage: 3C505 [-n] [-d] [-w] <packet_int_no> <int_level> <io_addr> <mem_base>",CR,LF,'$'
  740.     public    copyright_msg
  741. copyright_msg    db    "Packet Driver for 3c505, version ",'0'+majver, ".",CR,LF
  742.          db    "Portions copyright 1989, Krishnan Gopalan & Gregg Stefancik.",CR,LF
  743.          db     "Clemson University Engineering Comp Ops.",CR,LF,'$'
  744. no_board_msg:
  745.     db    "3c505 apparently not present at this address.",CR,LF,'$'
  746. int_no_name    db    "Interrupt number ",'$'
  747. io_addr_name    db    "I/O port ",'$'
  748. mem_base_name    db    "Memory address ",'$'
  749.  
  750.     extrn    set_recv_isr: near
  751.  
  752. ;enter with si -> argument string, di -> word to store.
  753. ;if there is no number, don't change the number.
  754.     extrn    get_number: near
  755.  
  756. ;enter with dx -> name of word, di -> dword to print.
  757.     extrn    print_number: near
  758.  
  759.     public    parse_args
  760. parse_args:
  761. ;exit with nc if all went well, cy otherwise.
  762.     mov    di,offset int_no
  763.     call     get_number
  764.     mov    di,offset io_addr
  765.     call    get_number
  766.     mov    di,offset mem_base
  767.     call    get_number
  768.     clc
  769.     ret
  770.  
  771.     public    etopen
  772. etopen:
  773. ;if all is okay,
  774. ; reset the 3c505 board takes about 15-20 seconds
  775.     loadport
  776.     setport    ECONTROL 
  777.     mov    al,EN_ATTN OR EN_FLSH_DATA    ; reset command
  778.     out    dx,al                ; do reset
  779.   if 0
  780.     mov    ax,1
  781.     call    set_timeout
  782. reset1:
  783.     call    do_timeout
  784.     jne    reset1                ; wait for reset to propagate
  785.   else
  786.   endif
  787.  
  788.     mov    al,EN_COMMAND_ENABLE        ; command interrupt enable
  789.     mov    lastcon,al            ; save last command
  790.     out    dx,al                ; release reset
  791.     mov    ax,RESDEL            ; time to wait
  792.     call    set_timeout
  793. reset2:
  794.     call    do_timeout
  795.     jne    reset2
  796.  
  797.     mov    ax,RESTO            ;this is the long wait.
  798.     call    set_timeout
  799. reset3:
  800.     call    getstat
  801.     and    ax, EN_HSF1 OR EN_HSF2
  802.     cmp    ax,EN_HSF1 OR    EN_HSF2
  803.     jne    resetdone
  804.     call    do_timeout
  805.     jne    reset3
  806.     jmp    openfail            ; open failed
  807.  
  808. resetdone:
  809.     call    set_recv_isr            ;install the interrupt handler
  810.  
  811. ;Tell the 3c505 board to receive packets
  812.     mov    si,offset cconc
  813.     mov    ax,4
  814.     mov    fconc,0
  815.  
  816.     call    outpcb
  817.  
  818.     mov    ax,RESTO
  819.     call    set_timeout
  820. open_1:
  821.     test    fconc,0ffh
  822.     jnz    setuprecv
  823.  
  824.     call    do_timeout
  825.     jne    open_1
  826.  
  827. ; set up the recv buffers
  828.  
  829. setuprecv:
  830.     mov    rbufct,0            ; clear buffer counter
  831.     mov    crecv_length,1600        ; buffer length,1600
  832.  
  833.     mov    crecv_timeout,0
  834.  
  835. startrecv:
  836.     mov    ax,rbufct            ; buffer counter->ax
  837.     mov    crecv_offset,ax            ; buf no used as offset
  838.     inc    ax                ; count buffer
  839.     mov    rbufct,ax
  840.     mov    ax,10                ; length of pcb
  841.     mov    si,offset crecv            ;si->command receive
  842.  
  843.     call    outpcb                ; pass the pcb
  844.     mov    ax,rbufct
  845.     cmp    ax,10
  846.     jl    startrecv
  847.  
  848.     mov    al, int_no        ; Get board's interrupt vector
  849.     add    al, 8
  850.     cmp    al, 8+8            ; Is it a slave 8259 interrupt?
  851.     jb    set_int_num        ; No.
  852.     add    al, 70h - 8 - 8        ; Map it to the real interrupt.
  853. set_int_num:
  854.     xor    ah, ah            ; Clear high byte
  855.     mov    int_num, ax        ; Set parameter_list int num.
  856.  
  857.     mov    dx,offset end_resident
  858.     clc
  859.     ret
  860.  
  861.     public    print_parameters
  862. print_parameters:
  863.     mov    di,offset int_no
  864.     mov    dx,offset int_no_name
  865.     call     print_number
  866.     mov    di,offset io_addr
  867.     mov    dx,offset io_addr_name
  868.     call    print_number
  869.     mov    di,offset mem_base
  870.     mov    dx,offset mem_base_name
  871.     call    print_number
  872.     ret
  873.  
  874. ;if we got an error,
  875. openfail:
  876.     stc
  877.     ret
  878. code    ends
  879.     end
  880.