home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / archives / packetdrivers.tar.gz / pd.tar / src / 3c505.asm < prev    next >
Assembly Source File  |  1995-06-25  |  19KB  |  869 lines

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