home *** CD-ROM | disk | FTP | other *** search
/ Stars of Shareware: Programmierung / SOURCE.mdf / programm / msdos / asm / driver6s / 3c505.asm < prev    next >
Encoding:
Assembly Source File  |  1990-04-10  |  18.8 KB  |  843 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    byte 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.     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    send_pkt 
  159. send_pkt:
  160. ;enter with es:di->upcall routine, (0:0) if no upcall is desired.
  161. ;  (only if the high-performance bit is set in driver_function)
  162. ;enter with ds:si -> packet, cx = packet length.
  163. ;exit with nc if ok, or else cy if error, dh set to error number.
  164.     assume    ds:nothing
  165.  
  166.     push    si            ; save si for  lodsw
  167.     push    ds            ; save ds
  168.     push    es            ; save es for timer
  169.     push    cs            ;
  170.     pop    ds            ; cs = ds align
  171.  
  172.     mov    tx_segment,ds        ;tx->data
  173.     mov    tx_offset,si        ;tx_offset ->segment offset 
  174.  
  175.     mov    ax,cx            ; save cx
  176.     cmp    ax,60            ; compare with minimum limit
  177.     jnb    pkt_ok            ; go if ok 
  178.     mov    ax,60            ; make length minimum allowed
  179. pkt_ok:
  180.     inc    ax            ; round up
  181.     sar    ax,1            ; divide by 2
  182.     shl    ax,1            ; multiply by 2
  183.     mov    tx_length,ax        ; put in request
  184.     
  185.     mov    fxmit,0            ; clear response received flag
  186.  
  187.     mov    si, offset txmit    ; si->request(pcb)
  188.     mov    ax,8            ;length of pcb 
  189.  
  190.     call    outpcb            ; send command to board
  191.  
  192.     mov    cx,tx_length
  193.     sar    cx,1
  194.  
  195.     pop    es
  196.     pop    ds
  197.     pop    si
  198.  
  199. tx_1:
  200.  
  201.     lodsw
  202.  
  203.     loadport
  204.     setport    EDATA
  205.     out    dx,ax            ; output word
  206.     setport    ESTATUS
  207. tx_2:
  208.     in    al,dx            ; get status
  209.     test    al, EN_DATA_READY    ; ready for next word ?
  210.     jz    tx_2            ;no
  211.  
  212.     dec    cx            ; count word
  213.     jnz    tx_1            ; loop thru buffer
  214.  
  215. tx_3:
  216.     test    fxmit,0ffh        ; is transmit over
  217.     jz    tx_3            ; no
  218.     ret
  219.  
  220.     public    get_address
  221.  
  222.  
  223. get_address:
  224. ;get the address of the interface.
  225. ;enter with es:di -> place to get the address, cx = size of address buffer.
  226. ;exit with nc, cx = actual size of address, or cy if buffer not big enough.
  227.     assume    ds:code
  228.     push    es
  229.     push    di
  230.  
  231.     cmp    cx, EADDR_LEN        ; does caller want reasonable length?
  232.     jb    get_addr_fail        ; no , fails
  233.     mov    si,offset cgeth        ; si->pcb address
  234.     mov    ax,2            ; length of pcb
  235.     mov    fgeth,0            ; clear response received flag
  236.  
  237.     call    outpcb        
  238.  
  239.     mov    ax,RESTO        ; get wait time
  240.     call    set_timeout
  241. get_addr_1:
  242.     test    fgeth,0ffh        ; answered?
  243.     jnz    get_addr_2        ; yes
  244.     call    do_timeout
  245.     jnz    get_addr_1        ; test again
  246.     jmp    get_addr_fail        ; go return
  247.  
  248. get_addr_2:
  249.     pop    di
  250.     pop    es
  251.     cld                ; make sure of string operation
  252.     mov    si,offset rgeth_ad    ; load source of address
  253.     mov    cx,EADDR_LEN        ; return length of address
  254.     rep    movsb            ; copy address
  255.     mov    cx,EADDR_LEN        ; return length of address
  256.     clc
  257.     ret
  258. get_addr_fail:
  259.     add sp,4
  260.     stc
  261.     ret
  262.  
  263.     public    set_address
  264.  
  265. set_address:
  266. ;enter with ds:si -> Ethernet address, CX = length of address.
  267. ;exit with nc if okay, or cy, dh=error if any errors.
  268.     assume    ds:nothing
  269.  
  270.     cmp    cx, EADDR_LEN        ; check if address ok
  271.     je    set_addr_1    
  272.     mov    dh,BAD_ADDRESS        ; don't like length
  273.     stc
  274.     ret
  275. set_addr_1:
  276.     mov    di,offset cseth_ad    ;di->destination offset
  277.     rep    movsb            ; return address
  278.     mov    si,offset cseth        ; si->request ethernet address
  279.     mov    ax,8            ; request length -> ax
  280.     mov    fseth,0            ; clear response received flag
  281.     call     outpcb            ; send the pcb
  282.  
  283.     mov    ax,RESTO        ; get response time
  284.     call    set_timeout
  285. set_addr_2:
  286.     test    fseth,0ffh        ; pcb answered?
  287.     jnz    set_addr_3
  288.     call    do_timeout        ; has time expired
  289.     jne    set_addr_2        ; no, go back
  290.     stc                ; error
  291.     ret
  292. set_addr_3:
  293.     mov    cx,EADDR_LEN        ;return their address length.
  294.     clc
  295.     ret
  296.  
  297. rcv_mode_3:
  298. ;receive mode 3 is the only one we support, so we don't have to do anything.
  299.     ret
  300.  
  301.  
  302.     public    set_multicast_list
  303. set_multicast_list:
  304. ;enter with ds:si ->list of multicast addresses, cx = number of addresses.
  305. ;return nc if we set all of them, or cy,dh=error if we didn't.
  306.     mov    dh,NO_MULTICAST
  307.     stc
  308.     ret
  309.  
  310.  
  311.     public    terminate
  312. terminate:
  313.     ret
  314.  
  315.     public    reset_interface
  316. reset_interface:
  317. ;reset the interface.
  318.     assume    ds:code
  319.  
  320.     mov    al, EN_ATTN OR EN_FLSH_DATA    ; hard reset command
  321.     loadport
  322.     setport    ECONTROL
  323.     out    dx,al                ; do reset
  324.     mov    ax,RESDEL            ; get reset delay
  325.     call    set_timeout
  326. rst1:
  327.     call    do_timeout
  328.     jne    rst1                ; wait for reset
  329.     mov    al,EN_COMMAND_ENABLE        ; command interrupt enable
  330.     mov    lastcon,al            ; save last command
  331.     out    dx,al                ; release reset
  332.     mov    ax,RESDEL
  333.     call    set_timeout
  334. rst2:
  335.     call    do_timeout
  336.     jne    rst2                ; wait to start reset
  337.     mov    ax,RESTO            ; add time out
  338.     call    set_timeout
  339. rst3:
  340.     call getstat                ; getstatus    
  341.     and    ax,EN_ASF1 OR EN_ASF2        ; 
  342.     cmp    ax,EN_ASF1 OR EN_ASF2        ;  both on ?
  343.     jne     resdone
  344.     call    do_timeout            ; long enough?
  345.     jne    rst3                ; no
  346.     ret
  347. resdone:
  348.     ret
  349. ;called when we want to determine what to do with a received packet.
  350. ;enter with cx = packet length, es:di -> packet type.
  351.     extrn    recv_find: near
  352.  
  353. ;called after we have copied the packet into the buffer.
  354. ;enter with ds:si ->the packet, cx = length of the packet.
  355.     extrn    recv_copy: near
  356.  
  357.     extrn    count_in_err: near
  358.     extrn    count_out_err: near
  359.  
  360.     public    recv
  361. recv:
  362. ;called from the recv isr.  All registers have been saved, and ds=cs.
  363. ; all interrupts come here
  364. ;Upon exit, the interrupt will be acknowledged.
  365.     assume    ds:code
  366.     ;sti
  367.     cld
  368. recv1:
  369.     loadport
  370.     setport    ESTATUS
  371.     in    al,dx                ; read flags
  372.     and    al,EN_ADAPTER_COMMAND_FULL    ; 
  373.     jnz    recv2                ; yes,full
  374.     jmp    interrupt_done    
  375. ;there might be a response, clear flags to check for response
  376. recv2:
  377.     mov    ax,RCMDTO            ; incoming command time out
  378.     call    set_timeout
  379.  
  380.     mov    al,lastcon            ; last control->ax
  381.     and    al,NOT (EN_HSF1 OR EN_HSF2)    ; clear flags
  382.     mov    lastcon,al
  383.  
  384.     loadport
  385.     setport    ECONTROL
  386.     out    dx,al                ; clear flags in cntl reg
  387.  
  388.     mov    di,offset icmdb            ; di->incoming command buffer
  389.  
  390. recv3:
  391.     loadport
  392.     setport    ESTATUS
  393.     in    al,dx                ; status->al
  394.  
  395.     mov    cx,ax                ; status->cx
  396.     test    al,EN_ADAPTER_COMMAND_FULL    ; is adapter register full
  397.     jnz    recv4                ; yes go ahead to read from
  398.     call    do_timeout            ; is time up ? 
  399.     jne    recv3                ; give some more time
  400.     jmp    int1                ; give up
  401. recv4:
  402.     loadport
  403.     setport    ECOMMAND
  404.     in    al,dx                ; get command byte
  405.     and    cl,EN_ASF1 OR EN_ASF2        
  406.     cmp    cl,EN_ASF1 OR EN_ASF2        ; both on?
  407.     je    recv5                ; end of command
  408.     mov    [di],al                ;save byte
  409.     inc    di                ;inc    di 
  410.     mov    ax,di                ; current pointer->ax
  411.     sub    ax,offset icmdb            ; - start of buffer
  412.     cmp    ax,cbs                ; full?
  413.     jl    recv3
  414.  
  415.     mov    si,(offset icmdb)+cbsh        ; si->middle of buffer
  416.     mov    di,offset icmdb            ; di->start of buffer
  417.     mov    cx,cbsh                ; size of half buffer->cx
  418.     push    ds
  419.     pop    es
  420.     rep    movsb
  421.  
  422.     jmp    recv3                ; loop for more bytes
  423. recv5:
  424.     push    ds
  425.     pop    es
  426.     mov    ah,0
  427.     mov    cmdlen,ax            ; save cmdlen
  428.     mov    si,di 
  429.     sub    si,cmdlen
  430.     mov    di,offset icmd    
  431.     mov    cx,cmdlen
  432.  
  433.     rep movsb                ; copy
  434.  
  435.     mov    al,icmd                ; check
  436.  
  437.     cmp    al,32h                ; Configure?
  438.     je    respconfig
  439.  
  440.     cmp    al,33h                ; get ethernet address?
  441.     je    respgetaddr            ; yes
  442.  
  443.     cmp    al,39h                ; transmit complete?
  444.     je    transmit            ; yes
  445.  
  446.     cmp    al,40h                ; set ethernet address
  447.     je    respsetaddr            ; yes
  448.     
  449.     cmp    al,38h                ; receive complete?
  450.     je    resprecv
  451.  
  452.     jmp    int1
  453.  
  454. respconfig:
  455.  
  456.     push    ds
  457.     pop    es
  458.     mov    si,offset icmd
  459.     mov    di,offset rconc
  460.     mov    cx,2
  461.     
  462.     rep    movsw
  463.     mov    fconc,1
  464.     jmp    int1
  465.     
  466. respgetaddr:
  467.     push    ds
  468.     pop    es
  469.  
  470.     mov    si,offset icmd
  471.     mov    di,offset rgeth
  472.     mov    cx,4
  473.  
  474.     rep    movsw
  475.  
  476.     mov    fgeth,1
  477.     jmp    int1
  478.  
  479. respsetaddr:
  480.  
  481.     mov    si,offset icmd        ; si->command received
  482.     mov    di,offset cseth        ; di->set ethernet address resp
  483.     push    ds
  484.     pop    es
  485.     mov    cx,2
  486.  
  487.     rep    movsw
  488.     mov    fseth,1
  489.     jmp    int1
  490.  
  491. transmit:
  492.     mov    si,offset icmd            ; si->command received
  493.     mov    di,offset rxmit            ; response,transmit packet
  494.     push    ds
  495.     pop    es
  496.     mov    cx,5                ; response length->cx
  497.     rep    movsw
  498.  
  499.     mov    fxmit,1                ; response received
  500.     jmp    int1                ; return from interrupt
  501.  
  502. resprecv:
  503.     mov    si,offset icmd            ; si->command received
  504.     mov    di,offset rr            ; di->receive response
  505.     push    ds
  506.     pop    es
  507.     mov    cx,9                ; response length->cx
  508.     
  509.     rep    movsw                ; move response
  510.     mov    di,offset recvbuf        ; di->receive buffer
  511.     mov    ax,rr_length            ; message size->ax
  512.     inc    ax                ; round up
  513.     shr    ax,1                ; convert to words
  514.     shl    ax,1                ; convert to characters
  515.     mov    rr_length,ax            ; ax->message length
  516.  
  517.     mov    cx,ax                ; message length->cx
  518.     shr    cx,1                ; convert to words
  519.  
  520.     mov    al,lastcon            ; lastcontrol->al
  521.     or    al,EN_TO_HOST OR EN_HSF1    ; set direction & ack    
  522.     mov    lastcon,al            ; response
  523.  
  524.     loadport
  525.     setport    ECONTROL
  526.     out    dx,al                ; pass direction
  527.     
  528.     setport ESTATUS
  529.  
  530. resprecv_1:
  531.  
  532.     in    al,dx                ; get status
  533.     test    al,EN_DATA_READY        ; data ready ?
  534.     jz    resprecv_1
  535.  
  536.     setport    EDATA                ; data word->ax
  537.     in    ax,dx                ; get word
  538.     stosw                    ; store word in buffer
  539.  
  540.     setport    ESTATUS
  541.     dec    cx                ; count word
  542.     jnz    resprecv_1            ; loop if more words
  543.  
  544.     mov    al,lastcon
  545.     and    al,NOT (EN_TO_HOST OR EN_HSF1)
  546.     mov    lastcon,al
  547.  
  548.     loadport                ; dx->control register
  549.     setport    ECONTROL
  550.     out    dx,al
  551.  
  552.     mov    cx,rr_length            ; cx->packet length
  553.  
  554.     push    cs                ; align cs and ds
  555.     pop    ds
  556.  
  557.     mov    di,offset recvbuf        ; reset di to beginning
  558.     add    di,EADDR_LEN+EADDR_LEN        ; point to type field
  559.                         ; of buffer
  560.     assume    ds:code
  561.  
  562.     call    recv_find            ; first call
  563.  
  564.     assume    ds:nothing
  565.     mov    ax,es                ; ax->es
  566.     or    ax,di                ; is es=di=0?
  567.     je    rcv_no_copy
  568.  
  569.     mov    cx,rr_length            ; cx->packet length
  570.     push    cx
  571.     push    es
  572.     push    di
  573.  
  574.     mov    si,offset recvbuf        ; prepare to copy the packet
  575.     rep    movsb                ; copy
  576.  
  577.     pop    si
  578.     pop    ds
  579.     pop    cx
  580.  
  581.     call    recv_copy            ; second call 
  582. rcv_no_copy:
  583.     push    cs
  584.     pop    ds
  585.     call    anotherrecv            ; start another recv
  586. int1:
  587.     jmp    recv1
  588.  
  589. interrupt_done:
  590.     ret
  591.  
  592. ;*****************************OUTPCB***********************************
  593. ;outpcb     send pcb to board, retry until accepted
  594. ; entry    ax = number of bytes in pcb
  595. ;    si = address of pcb
  596. outpcb    proc     near
  597.     mov    pcblen,ax        ; save pcb length
  598.     mov    pcbaddr,si        ; save pcb address
  599. pcb_0:
  600.     mov    cx,pcblen        ;length->cx
  601.     mov    si,pcbaddr        ; address->si
  602.     cli                ; stop interrupts
  603.     mov    al,lastcon        ; save last command
  604.     and    al, NOT (EN_HSF1 OR EN_HSF2); clear flags
  605.     mov    lastcon,al
  606.     sti                ; enable interrupts
  607.     loadport
  608.     setport    ECONTROL
  609.     out    dx,al            ; send control
  610.     setport    ECOMMAND
  611. pcb_1:
  612.     mov    al,[si]            ; 
  613.     out    dx,al            ; send command byte
  614.     mov    ax,CMDBTO        ; get time out
  615.     call    set_timeout
  616. chk_hcre:
  617.     call    getstat
  618.     and    al, EN_HOST_COMMAND_EMPTY    ; command accepted
  619.     jne    pcb_2                ; go on
  620.     call    do_timeout
  621.     jne    chk_hcre            ; time is still left
  622.     jmp    cmdretry            ; retry command
  623. pcb_2:
  624.     inc    si                ; increment source pointer
  625.     dec    cx                ; count byte
  626.     jg    pcb_1                ; loop         
  627.     loadport
  628.     setport    ECONTROL
  629.     cli                    ; disable interrupts
  630.     mov    al,lastcon            ; last control -> al
  631.     or    al,(EN_HSF1 OR EN_HSF2)        ; set end of command
  632.     mov    lastcon,al            ; save last control
  633.     out    dx,al                ; send flag bits
  634.     setport    ECOMMAND
  635.     mov    ax,pcblen
  636.     out    dx,al                ; send pcb length
  637.     sti                    ; enable interrupts
  638.     mov    ax,CMDCTO            ; time out for acceptance
  639.     call    set_timeout
  640. pcb_3:
  641.     call    getstat
  642.     and    al,(EN_ASF1 OR EN_ASF2)        ; just keep status flags
  643.     cmp    al,1                ; accepted
  644.     je    cmdaccept
  645.     cmp    al,2
  646.     je    cmdretry
  647.     call    do_timeout
  648.     jne    pcb_3
  649.  
  650. cmdretry:
  651.     mov    ax,RETRYDELAY            ;add retry delay
  652.     call    set_timeout
  653. pcb_4:
  654.     call    do_timeout
  655.     jne    pcb_4
  656.     jmp    pcb_0
  657.  
  658. cmdaccept:
  659.     cli
  660.     mov    al,lastcon
  661.     and    al, NOT (EN_HSF1 OR EN_HSF2)    ; turn off end of command flag
  662.     mov    lastcon,al            ; save last control
  663.     sti                    ; enable interrupts
  664.     loadport
  665.     setport    ECONTROL
  666.     out    dx,al                ; pass control byte
  667.     ret    
  668. outpcb    endp
  669. ;*************get status of board***********************
  670. getstat        proc    near
  671.     push    bx
  672.     push    dx
  673.     loadport
  674.     setport    ESTATUS
  675.  
  676. stat_1:
  677.     in    al,dx            ; get status into al
  678.     mov    bl,al            ; save al
  679.     in    al,dx            ; get status again
  680.     cmp    al,bl            ; same status ?
  681.     jne    stat_1
  682.     pop    dx
  683.     pop    bx
  684.     ret
  685. getstat    endp
  686.  
  687. ; UPDATE BUFFER POINTERS AND ISSUE ANOTHER RECV
  688. ;    update recv 
  689. anotherrecv    proc    near
  690.     mov    ax,rbufct
  691.     mov    crecv_offset,ax
  692.     inc    ax
  693.     mov    rbufct,ax
  694.     mov    ax,10
  695.     mov    si,offset crecv
  696.  
  697.     call    outpcb
  698.     ret
  699. anotherrecv    endp
  700.  
  701.     public    recv_exiting
  702. recv_exiting:
  703. ;called from the recv isr after interrupts have been acknowledged.
  704. ;Only ds and ax have been saved.
  705.     assume    ds:nothing
  706.     ret
  707.  
  708.     include    timeout.asm
  709.  
  710. ;any code after this will not be kept after initialization.
  711. end_resident    label    byte
  712.  
  713.     public    usage_msg
  714. usage_msg  db  "usage: 3C505 <packet_int_no> <int_level> <io_addr> <mem_base>",CR,LF,'$'
  715.     public    copyright_msg
  716. copyright_msg    db    "Packet Driver for 3c505, version ",'0'+majver, ".",CR,LF
  717.          db    "Portions copyright 1989, Krishnan Gopalan & Gregg Stefancik.",CR,LF
  718.          db     "Clemson University Engineering Comp Ops.",CR,LF,'$'
  719. no_board_msg:
  720.     db    "3c505 apparently not present at this address.",CR,LF,'$'
  721. int_no_name    db    "Interrupt number ",'$'
  722. io_addr_name    db    "I/O port ",'$'
  723. mem_base_name    db    "Memory address ",'$'
  724.  
  725.     extrn    set_recv_isr: near
  726.  
  727. ;enter with si -> argument string, di -> word to store.
  728. ;if there is no number, don't change the number.
  729.     extrn    get_number: near
  730.  
  731. ;enter with dx -> name of word, di -> dword to print.
  732.     extrn    print_number: near
  733.  
  734.     public    parse_args
  735. parse_args:
  736. ;exit with nc if all went well, cy otherwise.
  737.     mov    di,offset int_no
  738.     call     get_number
  739.     mov    di,offset io_addr
  740.     call    get_number
  741.     mov    di,offset mem_base
  742.     call    get_number
  743.     clc
  744.     ret
  745.  
  746.     public    etopen
  747. etopen:
  748. ;if all is okay,
  749. ; reset the 3c505 board takes about 15-20 seconds
  750.     loadport
  751.     setport    ECONTROL 
  752.     mov    al,EN_ATTN OR EN_FLSH_DATA    ; reset command
  753.     out    dx,al                ; do reset
  754.   if 0
  755.     mov    ax,1
  756.     call    set_timeout
  757. reset1:
  758.     call    do_timeout
  759.     jne    reset1                ; wait for reset to propagate
  760.   else
  761.   endif
  762.  
  763.     mov    al,EN_COMMAND_ENABLE        ; command interrupt enable
  764.     mov    lastcon,al            ; save last command
  765.     out    dx,al                ; release reset
  766.     mov    ax,RESDEL            ; time to wait
  767.     call    set_timeout
  768. reset2:
  769.     call    do_timeout
  770.     jne    reset2
  771.  
  772.     mov    ax,RESTO            ;this is the long wait.
  773.     call    set_timeout
  774. reset3:
  775.     call    getstat
  776.     and    ax, EN_HSF1 OR EN_HSF2
  777.     cmp    ax,EN_HSF1 OR    EN_HSF2
  778.     jne    resetdone
  779.     call    do_timeout
  780.     jne    reset3
  781.     jmp    openfail            ; open failed
  782.  
  783. resetdone:
  784.     call    set_recv_isr            ;install the interrupt handler
  785.  
  786. ;Tell the 3c505 board to receive packets
  787.     mov    si,offset cconc
  788.     mov    ax,4
  789.     mov    fconc,0
  790.  
  791.     call    outpcb
  792.  
  793.     mov    ax,RESTO
  794.     call    set_timeout
  795. open_1:
  796.     test    fconc,0ffh
  797.     jnz    setuprecv
  798.  
  799.     call    do_timeout
  800.     jne    open_1
  801.  
  802. ; set up the recv buffers
  803.  
  804. setuprecv:
  805.     mov    rbufct,0            ; clear buffer counter
  806.     mov    crecv_length,1600        ; buffer length,1600
  807.  
  808.     mov    crecv_timeout,0
  809.  
  810. startrecv:
  811.     mov    ax,rbufct            ; buffer counter->ax
  812.     mov    crecv_offset,ax            ; buf no used as offset
  813.     inc    ax                ; count buffer
  814.     mov    rbufct,ax
  815.     mov    ax,10                ; length of pcb
  816.     mov    si,offset crecv            ;si->command receive
  817.  
  818.     call    outpcb                ; pass the pcb
  819.     mov    ax,rbufct
  820.     cmp    ax,10
  821.     jl    startrecv
  822.  
  823.     mov    di,offset int_no
  824.     mov    dx,offset int_no_name
  825.     call     print_number
  826.     mov    di,offset io_addr
  827.     mov    dx,offset io_addr_name
  828.     call    print_number
  829.     mov    di,offset mem_base
  830.     mov    dx,offset mem_base_name
  831.     call    print_number
  832.  
  833.     mov    dx,offset end_resident
  834.     clc
  835.     ret
  836.  
  837. ;if we got an error,
  838. openfail:
  839.     stc
  840.     ret
  841. code    ends
  842.     end
  843.