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

  1. version        equ    0                       ; VES
  2.  
  3. ;  Copyright, 1991-1992, Russell Nelson, Crynwr Software
  4.  
  5. ;   This program is free software; you can redistribute it and/or modify
  6. ;   it under the terms of the GNU General Public License as published by
  7. ;   the Free Software Foundation, version 1.
  8. ;
  9. ;   This program is distributed in the hope that it will be useful,
  10. ;   but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. ;   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12. ;   GNU General Public License for more details.
  13. ;
  14. ;   You should have received a copy of the GNU General Public License
  15. ;   along with this program; if not, write to the Free Software
  16. ;   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17. ;
  18. ; Minor modifications for DEC VAXmate by:
  19. ;
  20. ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  21. ;  Blair Vessey                          |          E-Mail: VESSEY@UPEI.CA
  22. ;  Computer Services, Network Services   |       Telephone: (902) 566-0659
  23. ;  University of Prince Edward Island    |             FAX: (902) 566-0958
  24. ;  Charlottetown, P.E.I. CANADA  C1A 4P3 |          Mailer: Pegasus/Charon
  25. ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  26. ;         "An ounce of perception, a pound of obscure" - N. Peart
  27. ;
  28. ; 04/27/92
  29.  
  30.     .286                ;the VAXmate has an 80286.
  31.  
  32.     include    defs.asm
  33.  
  34. NI_CSR        equ    048h            ; VES
  35. RBI        equ    2
  36. DATA_REG    equ    040h            ; VES
  37. ADDR_REG    equ    042h            ; VES
  38. CSR0        equ    0
  39. CSR1        equ    1
  40. CSR2        equ    2
  41. CSR3        equ    3
  42. EBASE        equ    00h             ; VES
  43.  
  44. NI_CSR_VALUE    equ    81h             ; VES
  45.  
  46. outport    macro    reg
  47.     push    ax
  48.     setport    ADDR_REG
  49.     mov    ax,reg
  50.     out    dx,ax
  51.     in    ax,dx            ;always follow a write by a read
  52.  
  53.     setport    DATA_REG
  54.     pop    ax
  55.     out    dx,ax
  56.     in    ax,dx            ;always follow a write by a read
  57.  
  58.     endm
  59.  
  60.  
  61. ;
  62. ;     Control and Status Register 0 (CSR0) bit definitions
  63. ;
  64. CSR0_ERR    equ     8000h    ; Error summary
  65. CSR0_BABL    equ     4000h    ; Babble transmitter timeout error
  66. CSR0_CERR    equ    2000h    ; Collision Error
  67. CSR0_MISS    equ    1000h    ; Missed packet
  68. CSR0_MERR    equ    0800h    ; Memory Error
  69. CSR0_RINT    equ    0400h    ; Reciever Interrupt
  70. CSR0_TINT       equ    0200h    ; Transmit Interrupt
  71. CSR0_IDON    equ    0100h    ; Initialization Done
  72. CSR0_INTR    equ    0080h    ; Interrupt Flag
  73. CSR0_INEA    equ    0040h    ; Interrupt Enable
  74. CSR0_RXON    equ    0020h    ; Receiver on
  75. CSR0_TXON    equ    0010h   ; Transmitter on
  76. CSR0_TDMD    equ    0008h    ; Transmit Demand
  77. CSR0_STOP    equ    0004h     ; Stop
  78. CSR0_STRT    equ    0002h    ; Start
  79. CSR0_INIT    equ    0001h    ; Initialize
  80.  
  81. ;
  82. ;     Initialization Block  Mode operation Bit Definitions.
  83. ;
  84. M_PROM        equ    8000h    ; Promiscuous Mode
  85. M_INTL        equ    0040h   ; Internal Loopback
  86. M_DRTY        equ    0020h   ; Disable Retry
  87. M_COLL        equ    0010h    ; Force Collision
  88. M_DTCR        equ    0008h    ; Disable Transmit CRC)
  89. M_LOOP        equ    0004h    ; Loopback
  90. M_DTX        equ    0002h    ; Disable the Transmitter
  91. M_DRX        equ    0001h   ; Disable the Reciever
  92.  
  93.  
  94. ;
  95. ;     Receive message descriptor bit definitions.
  96. ;
  97. RCV_OWN        equ    8000h    ; owner bit 0 = host, 1 = lance
  98. RCV_ERR        equ    4000h    ; Error Summary
  99. RCV_FRAM    equ     2000h    ; Framing Error
  100. RCV_OFLO    equ    1000h    ; Overflow Error
  101. RCV_CRC        equ    0800h    ; CRC Error
  102. RCV_BUF_ERR    equ     0400h    ; Buffer Error
  103. RCV_START    equ    0200h    ; Start of Packet
  104. RCV_END        equ    0100h    ; End of Packet
  105.  
  106.  
  107. ;
  108. ;    Transmit  message descriptor bit definitions.
  109. ;
  110. XMIT_OWN    equ    8000h    ; owner bit 0 = host, 1 = lance
  111. XMIT_ERR    equ    4000h   ; Error Summary
  112. XMIT_RETRY    equ    1000h   ; more the 1 retry needed to Xmit
  113. XMIT_1_RETRY    equ    0800h    ; one retry needed to Xmit
  114. XMIT_DEF    equ    0400h    ; Deferred
  115. XMIT_START    equ    0200h    ; Start of Packet
  116. XMIT_END    equ    0100h    ; End of Packet
  117.  
  118. ;
  119. ;    Miscellaneous Equates
  120. ;
  121.  
  122. TRANSMIT_BUF_COUNT    equ    1
  123. RECEIVE_BUF_COUNT    equ    8
  124. TRANSMIT_BUF_SIZE    equ    1518
  125. RECEIVE_BUF_SIZE    equ    1518
  126.  
  127. ;
  128. ;    Receive Message Descriptor
  129. ;
  130. rcv_msg_dscp struc
  131.     rmd0    dw    ?    ; Rec. Buffer Lo-Address
  132.     rmd1    dw    ?    ; Status bits / Hi-Address
  133.     rmd2    dw    ?    ; Buff Byte-length (2's Comp)
  134.     rmd3    dw    ?    ; Receive message length
  135. rcv_msg_dscp ends
  136.  
  137.  
  138. ;
  139. ;    Transmit Message Descriptor
  140. ;
  141. xmit_msg_dscp struc
  142.     tmd0    dw    ?    ; Xmit Buffer Lo-Address
  143.     tmd1    dw    ?    ; Status bits / Hi-Address
  144.     tmd2     dw    ?    ; Buff Byte-length (2's Comp)
  145.     tmd3    dw    ?    ; Buffer Status bits & TDR value
  146. xmit_msg_dscp ends
  147.  
  148. lance_seg    segment at 0
  149.  
  150. ;
  151. ;the LANCE requires that the descriptor pointers be on a qword boundary.
  152. ;
  153.     align    8
  154.  
  155. transmit_dscps    xmit_msg_dscp    TRANSMIT_BUF_COUNT dup(<>)
  156. receive_dscps    rcv_msg_dscp    RECEIVE_BUF_COUNT dup(<>)
  157.  
  158. ;
  159. ;      LANCE Initialization Block
  160. ;
  161.     align    2
  162. init_block        label    byte
  163. init_mode        dw    0
  164. init_addr        db    EADDR_LEN dup(?)    ; Our Ethernet address
  165. init_filter        db    8 dup(0)    ;Multicast filter.
  166. init_receive        dw    ?,?        ;Receive Ring Pointer.
  167. init_transmit          dw    ?,?          ;Transmit Ring Pointer.
  168.  
  169. transmit_bufs    equ    $
  170. receive_bufs    equ    transmit_bufs + TRANSMIT_BUF_COUNT * TRANSMIT_BUF_SIZE
  171.  
  172. lance_seg    ends
  173.  
  174. code    segment    para public
  175.     assume    cs:code, ds:code
  176.  
  177.         public    int_no
  178. int_no        db    2,0,0,0            ;must be four bytes long for get_number.
  179. io_addr        dw    -1,-1
  180. base_addr    dw    -1,-1
  181.  
  182.     public    driver_class, driver_type, driver_name, driver_function, parameter_list
  183. driver_class    db    BLUEBOOK, IEEE8023, 0        ;from the packet spec
  184. driver_type    db    66        ;from the packet spec
  185. driver_name    db    'DEPCA',0    ;name of the driver.
  186. driver_function    db    2        ;basic, extended
  187. parameter_list    label    byte
  188.     db    1    ;major rev of packet driver
  189.     db    9    ;minor rev of packet driver
  190.     db    14    ;length of parameter list
  191.     db    EADDR_LEN    ;length of MAC-layer address
  192.     dw    GIANT    ;MTU, including MAC headers
  193.     dw    MAX_MULTICAST * EADDR_LEN    ;buffer size of multicast addrs
  194.     dw    RECEIVE_BUF_COUNT-1    ;(# of back-to-back MTU rcvs) - 1
  195.     dw    TRANSMIT_BUF_COUNT-1    ;(# of successive xmits) - 1
  196. int_num    dw    0    ;Interrupt # to hook for post-EOI
  197.             ;processing, 0 == none,
  198.  
  199.     public    rcv_modes
  200. rcv_modes    dw    7        ;number of receive modes in our table.
  201.         dw    0               ;There is no mode zero
  202.         dw    0        ;none at all.
  203.         dw    0        ;only ours.
  204.         dw    rcv_mode_3    ;ours plus broadcast
  205.         dw    0        ;some multicasts
  206.         dw    0        ;all multicasts
  207.         dw    rcv_mode_6    ;all packets
  208.  
  209. save_csr1    dw    ?
  210. save_csr2    dw    ?
  211.  
  212. transmit_head    dw    transmit_dscps    ;->next packet to be filled by host.
  213. receive_head    dw    receive_dscps    ;->next packet to be filled by LANCE.
  214.  
  215.     public bad_command_intercept
  216. bad_command_intercept:
  217. ;called with ah=command, unknown to the skeleton.
  218. ;exit with nc if okay, cy, dh=error if not.
  219.     mov    dh,BAD_COMMAND
  220.     stc
  221.     ret
  222.  
  223.     public    as_send_pkt
  224. ; The Asynchronous Transmit Packet routine.
  225. ; Enter with es:di -> i/o control block, ds:si -> packet, cx = packet length,
  226. ;   interrupts possibly enabled.
  227. ; Exit with nc if ok, or else cy if error, dh set to error number.
  228. ;   es:di and interrupt enable flag preserved on exit.
  229. as_send_pkt:
  230.     ret
  231.  
  232.     public    drop_pkt
  233. ; Drop a packet from the queue.
  234. ; Enter with es:di -> iocb.
  235. drop_pkt:
  236.     assume    ds:nothing
  237.     ret
  238.  
  239.     public    xmit
  240. ; Process a transmit interrupt with the least possible latency to achieve
  241. ;   back-to-back packet transmissions.
  242. ; May only use ax and dx.
  243. xmit:
  244.     assume    ds:nothing
  245.     ret
  246.  
  247.  
  248.     public    send_pkt
  249. send_pkt:
  250. ;enter with ds:si -> packet, cx = packet length.
  251. ;exit with nc if ok, or else cy if error, dh set to error number.
  252.     assume    ds:nothing
  253.  
  254.     cmp    cx,GIANT        ; Is this packet too large?
  255.     ja    send_pkt_toobig
  256.  
  257.     mov    es,base_addr
  258.     assume    es:lance_seg
  259.  
  260.     xor    bx,bx
  261.  
  262.     mov    ax,18
  263.     call    set_timeout
  264. send_pkt_1:
  265.     test    transmit_dscps[bx].tmd1,XMIT_OWN    ;Did the lance chip give it back?
  266.     je    send_pkt_2
  267.     call    do_timeout
  268.     jne    send_pkt_1
  269.     mov    dh,CANT_SEND
  270.     stc
  271.     ret
  272. send_pkt_toobig:
  273.     mov    dh,NO_SPACE
  274.     stc
  275.     ret
  276. send_pkt_2:
  277. ;reset error indications.
  278.     and    transmit_dscps[bx].tmd1,not (XMIT_ERR or XMIT_DEF or XMIT_1_RETRY or XMIT_RETRY)    ;Did the lance chip give it back?
  279.     mov    transmit_dscps[bx].tmd3,0    ;reset all error bits.
  280.  
  281.     mov    ax,cx            ;store the count.
  282.     cmp    ax,RUNT            ; minimum length for Ether
  283.     ja    oklen
  284.     mov    ax,RUNT            ; make sure size at least RUNT
  285. oklen:
  286.     neg    ax
  287.     mov    transmit_dscps[bx].tmd2,ax    ;store the negative of the cnt.
  288.  
  289.     mov    ax,transmit_dscps[bx].tmd0    ;store the packet.
  290.     mov    dx,transmit_dscps[bx].tmd1
  291.     call    phys_to_segmoffs
  292.     assume    es:nothing
  293.     rep    movsb
  294.  
  295.     mov    es,base_addr
  296.     assume    es:lance_seg
  297.     or    transmit_dscps[bx].tmd1,XMIT_OWN    ;give it to the lance chip.
  298.  
  299. ;Inform LANCE that it should poll for a packet.
  300.     loadport
  301.     mov    ax,CSR0_INEA or CSR0_TDMD
  302.     outport    CSR0
  303.     clc
  304.     ret
  305.  
  306.  
  307. detect_board:
  308. ;test to see if a board is located at io_addr.
  309. ;setup to read first byte of ethernet address rom when successful.
  310. ;return nz if not.
  311.     assume    cs:code, ds:code
  312.  
  313.     loadport
  314.     setport    NI_CSR            ;enable the rev. E DEPCA card.
  315.     mov    al,8
  316.     out    dx,al
  317.     setport    EBASE            ;is it in this port?
  318.     call    detect_port
  319.     je    detect_board_1        ;yup!
  320.     setport    EBASE+1            ;look on the next port for rev. E
  321.     call    detect_port
  322. detect_board_1:
  323.     pushf                ;preserve the result.
  324.     loadport
  325.     setport    NI_CSR            ;restore the NI_CSR contents.
  326.     mov    al,NI_CSR_VALUE
  327.     out    dx,al
  328.     popf
  329.     ret
  330.  
  331.  
  332. depca_pattern    db    0FFh, 00h, 55h, 0AAh, 0FFh, 00h, 55h, 0AAh
  333.  
  334. detect_port:
  335. ;enter with dx = port to read from, looking for depca_pattern.
  336. ;exit with zr if we found it, nz if not.
  337.     mov    cx,32+8            ;do 32 reps, plus look at 8 to match.
  338.     mov    di,0            ;start at the beginning of the string.
  339. detect_port_1:
  340.     in    al,dx            ;input byte.
  341.     cmp    al,depca_pattern[di]    ;do they match?
  342.     jne    detect_port_2        ;no, try again.
  343.     inc    di            ;yes, look at another character.
  344.     cmp    di, 8            ;need to match eight chars.
  345.     jne    short detect_port_3
  346.     ret
  347. detect_port_2:
  348.     xor    di,di            ;start at the beginning of the pattern.
  349. detect_port_3:
  350.     loop    detect_port_1
  351.     or    sp,sp            ;return nz.
  352.     ret
  353.  
  354.  
  355.     public    set_address
  356. set_address:
  357. ;enter with ds:si -> Ethernet address, CX = length of address.
  358. ;exit with nc if okay, or cy, dh=error if any errors.
  359.     assume    ds:nothing
  360.     cmp    cx,EADDR_LEN        ;ensure that their address is okay.
  361.     je    set_address_4
  362.     mov    dh,BAD_ADDRESS
  363.     stc
  364.     jmp    short set_address_done
  365. set_address_4:
  366.  
  367.     mov    es,base_addr
  368.     mov    di,offset init_addr
  369.     rep    movsb
  370.     call    initialize        ;initialize with our new address.
  371.  
  372. set_address_okay:
  373.     mov    cx,EADDR_LEN        ;return their address length.
  374.     clc
  375. set_address_done:
  376.     movseg    ds,cs
  377.     assume    ds:code
  378.     ret
  379.  
  380.  
  381. rcv_mode_1:
  382.     mov    ax,M_DRX or M_DTX    ;disable the receiver and transmitter.
  383.     jmp    initialize_nomulti
  384. rcv_mode_3:
  385.     xor    ax,ax            ;don't accept any multicast frames.
  386.     call    initialize_multi
  387.     mov    ax,0            ;non-promiscuous mode
  388.     jmp    short initialize_nomulti
  389. rcv_mode_5:
  390.     mov    ax,-1            ;accept any multicast frames.
  391.     call    initialize_multi
  392.     mov    ax,0            ;non-promiscuous mode
  393.     jmp    short initialize_nomulti
  394. rcv_mode_6:
  395.     mov    ax,M_PROM        ;promiscuous mode
  396. initialize_nomulti:
  397.     mov    es,base_addr
  398.     mov    es:init_mode,ax
  399.  
  400. initialize:
  401.     loadport
  402.     mov    ax,CSR0_STOP        ;reset the INIT bit.
  403.     outport    CSR0
  404.  
  405.     mov    ax,2            ;write the bus config register.
  406.     outport    CSR3
  407.  
  408.     mov    ax,save_csr1        ;write the low word.
  409.     outport    CSR1
  410.  
  411.     mov    ax,save_csr2        ;write the high word.
  412.     outport    CSR2
  413.  
  414.     mov    ax,CSR0_INEA or CSR0_STRT or CSR0_INIT    ;reinit and restart.
  415.     outport    CSR0
  416.  
  417.     setport    DATA_REG
  418.  
  419.     mov    ax,36            ;wait one second for the board
  420.     call    set_timeout        ;  to timeout.
  421. initialize_1:
  422.     in    ax,dx
  423.     test    ax,CSR0_IDON
  424.     jne    initialize_2
  425.     call    do_timeout
  426.     jne    initialize_1
  427.     stc
  428.     ret
  429. initialize_2:
  430.     clc
  431.     ret
  432.  
  433.  
  434. initialize_multi:
  435. ;enter with ax = value for all multicast hash bits.
  436.     mov    es,base_addr
  437.     mov    di,offset init_filter
  438.     mov    cx,8/2
  439.     rep    stosw
  440.     ret
  441.  
  442.  
  443.     public    set_multicast_list
  444. set_multicast_list:
  445. ;enter with ds:si ->list of multicast addresses, ax = number of addresses,
  446. ;  cx = number of bytes.
  447. ;return nc if we set all of them, or cy,dh=error if we didn't.
  448.     mov    dh,NO_MULTICAST        ;for some reason we can't do multi's.
  449.     stc
  450.     ret
  451.  
  452.  
  453.     public    terminate
  454. terminate:
  455.     call    rcv_mode_1        ;don't receive any apckets.
  456.  
  457.     ret
  458.  
  459.     public    reset_interface
  460. reset_interface:
  461. ;reset the interface.
  462.     assume    ds:code
  463.     ret
  464.  
  465.  
  466. ;called when we want to determine what to do with a received packet.
  467. ;enter with cx = packet length, es:di -> packet type, dl = packet class.
  468.     extrn    recv_find: near
  469.  
  470. ;called after we have copied the packet into the buffer.
  471. ;enter with ds:si ->the packet, cx = length of the packet.
  472.     extrn    recv_copy: near
  473.  
  474. ;call this routine to schedule a subroutine that gets run after the
  475. ;recv_isr.  This is done by stuffing routine's address in place
  476. ;of the recv_isr iret's address.  This routine should push the flags when it
  477. ;is entered, and should jump to recv_exiting_exit to leave.
  478. ;enter with ax = address of routine to run.
  479.     extrn    schedule_exiting: near
  480.  
  481. ;recv_exiting jumps here to exit, after pushing the flags.
  482.     extrn    recv_exiting_exit: near
  483.  
  484.     extrn    count_in_err: near
  485.     extrn    count_out_err: near
  486.  
  487. LANCE_ISR_ACKNOWLEDGE equ (CSR0_INEA or CSR0_TDMD or CSR0_STOP or CSR0_STRT or CSR0_INIT)
  488.  
  489.     public    recv
  490. recv:
  491. ;called from the recv isr.  All registers have been saved, and ds=cs.
  492. ;Upon exit, the interrupt will be acknowledged.
  493.     assume    ds:code
  494.  
  495.     loadport
  496.     setport    ADDR_REG
  497.     mov    ax,CSR0
  498.     out    dx,ax
  499.     in    ax,dx
  500.     setport    DATA_REG
  501.     in    ax,dx
  502.     mov    bx,ax            ;make a copy.
  503.  
  504. ; Acknowledge the Interrupt from the controller, but disable further
  505. ; controller Interrupts until we service the current interrupt.
  506. ;
  507. ;(CSR0_INEA or CSR0_TDMD or CSR0_STOP or CSR0_STRT or CSR0_INIT)
  508. ;
  509.     and    ax,not LANCE_ISR_ACKNOWLEDGE
  510.     out    dx,ax
  511.     in    ax,dx            ; follow all writes by a read
  512.  
  513.     test    bx,CSR0_RINT        ;receive interrupt?
  514.     jne    recv_RINT        ;yes.
  515.     jmp    recv_done        ;no, we're done.
  516. recv_RINT:
  517.  
  518.     mov    es,base_addr
  519.     assume    es:lance_seg
  520.     mov    bx,receive_head
  521.  
  522. recv_search:
  523.     test    lance_seg:[bx].rmd1,RCV_OWN    ;do we own this buffer?
  524.     je    recv_own        ;yes - process it.
  525.     call    inc_recv_ring        ;go to the next one.
  526.     cmp    bx,receive_head        ;did we get back to the beginning?
  527.     jne    recv_search        ;not yet.
  528.     jmp    recv_done        ;yes -- spurious interrupt!
  529. recv_own:
  530.     test    lance_seg:[bx].rmd1,RCV_ERR    ;Any errors in this buffer?
  531.     jne    recv_err        ;yes -- ignore this packet.
  532.  
  533.     mov    cx,lance_seg:[bx].rmd3
  534.     and    cx,0fffh        ;strip off the reserved bits
  535.     sub    cx,4            ;leave the CRC behind.
  536.  
  537.     mov    ax,lance_seg:[bx].rmd0    ;fetch the packet.
  538.     mov    dx,lance_seg:[bx].rmd1
  539.     call    phys_to_segmoffs
  540.     assume    es:nothing
  541.  
  542.     push    es
  543.     push    di
  544.     push    bx
  545.  
  546.     add    di,EADDR_LEN+EADDR_LEN    ;skip the ethernet addreses and
  547.                     ;  point to the packet type.
  548.     mov    dl, BLUEBOOK        ;assume bluebook Ethernet.
  549.     mov    ax, es:[di]
  550.     xchg    ah, al
  551.     cmp    ax, 1500
  552.     ja    BlueBookPacket
  553.     inc    di            ;set di to 802.2 header
  554.     inc    di
  555.     mov    dl, IEEE8023
  556. BlueBookPacket:
  557.     push    cx
  558.     call    recv_find
  559.     pop    cx
  560.  
  561.     pop    bx
  562.     pop    si
  563.     pop    ds
  564.     assume    ds:nothing, es:nothing
  565.  
  566.     mov    ax,es            ;is this pointer null?
  567.     or    ax,di
  568.     je    recv_free        ;yes - just free the frame.
  569.  
  570.     push    es
  571.     push    di
  572.     push    cx
  573.     rep    movsb
  574.     pop    cx
  575.     pop    si
  576.     pop    ds
  577.     assume    ds:nothing
  578.  
  579.     call    recv_copy
  580.  
  581.     jmp    short recv_free
  582.  
  583. recv_err:
  584.     call    count_in_err
  585. recv_free:
  586.     movseg    ds,cs
  587.     assume    ds:code
  588.     mov    es,base_addr
  589.     assume    es:lance_seg
  590.  
  591. ;clear any error bits.
  592.     and    lance_seg:[bx].rmd1,not (RCV_ERR or RCV_FRAM or RCV_OFLO or RCV_CRC or RCV_BUF_ERR)
  593.     or    lance_seg:[bx].rmd1,RCV_OWN    ;give it back to the lance.
  594.     call    inc_recv_ring            ;go to the next one.
  595.     test    lance_seg:[bx].rmd1,RCV_OWN    ;Do we own this one?
  596.     je    recv_own
  597.     mov    receive_head,bx        ;remember where the next one starts.
  598. recv_done:
  599.     loadport            ;enable interrupts again.
  600.     setport    DATA_REG
  601.     mov    ax,CSR0_INEA
  602.     out    dx,ax
  603.  
  604.     ret
  605.  
  606.  
  607. inc_recv_ring:
  608. ;advance bx to the next receive ring descriptor.
  609.     assume    ds:nothing
  610.     add    bx,(size rcv_msg_dscp)
  611.     cmp    bx,offset receive_dscps + RECEIVE_BUF_COUNT * (size rcv_msg_dscp)
  612.     jb    inc_recv_ring_1
  613.     mov    bx,offset receive_dscps
  614. inc_recv_ring_1:
  615.     ret
  616.  
  617.  
  618. phys_to_segmoffs:
  619. ;enter with dx:ax as the physical address of the buffer,
  620. ;exit with es:di -> buffer.
  621.     assume    ds:nothing
  622.     shl    dx,16-4            ;move the upper four bits into position.
  623.     mov    di,ax            ;now get the low 12 bits of the segment.
  624.     shr    di,4
  625.     or    dx,di            ;combine them.
  626.     mov    es,dx
  627.     mov    di,ax
  628.     and    di,0fh            ;now compute the offset.
  629.     ret
  630.  
  631.     include    popf.asm
  632.     include    timeout.asm
  633.  
  634.     public    timer_isr
  635. timer_isr:
  636. ;if the first instruction is an iret, then the timer is not hooked
  637.     iret
  638.  
  639. ;any code after this will not be kept.  Buffers used by the program, if any,
  640. ;are allocated from the memory between end_resident and end_free_mem.
  641.     public end_resident,end_free_mem
  642. end_resident    label    byte
  643. end_free_mem    label    byte
  644.  
  645.     public    usage_msg
  646. usage_msg    db    "usage: vaxmate [options] <packet_int_no> <hardware_irq> <io_addr> <mem_addr>",CR,LF,'$'
  647. no_board_msg    db    "No DEPCA detected.",CR,LF,'$'
  648. io_addr_funny_msg    label    byte
  649.         db    "No DEPCA detected, continuing anyway.",CR,LF,'$'
  650. bad_reset_msg    db    "Unable to reset the DEPCA.",CR,LF,'$'
  651. bad_init_msg    db    "Unable to initialize the DEPCA.",CR,LF,'$'
  652. no_depca_mem_msg    db    "No DEPCA memory found at that memory address.",CR,LF,'$'
  653. addr_bad_msg    db    "Memory address should be less than 65536.",CR,LF,'$'
  654.  
  655.     public    copyright_msg
  656. copyright_msg    db    "Packet driver for a Digital Equipment Corporation VAXmate, version ",'0'+(majver / 10),'0'+(majver mod 10),".",'0'+version,CR,LF
  657.     db    "Portions copyright (C) 1992 Blair Vessey, Computer Services, U.P.E.I., Canada.",CR,LF
  658.     db    '$'
  659.  
  660. int_no_name    db    "Interrupt number ",'$'
  661. io_addr_name    db    "I/O port ",'$'
  662. base_addr_name    db    "Memory address ",'$'
  663.  
  664.     extrn    set_recv_isr: near
  665.     extrn    maskint: near
  666.  
  667. ;enter with si -> argument string, di -> dword to store.
  668. ;if there is no number, don't change the number.
  669.     extrn    get_number: near
  670.  
  671. ;enter with dx -> name of word, di -> dword to print.
  672.     extrn    print_number: near
  673.  
  674. ;-> the assigned Ethernet address of the card.
  675.     extrn    rom_address: byte
  676.  
  677.     public    parse_args
  678. parse_args:
  679. ;exit with nc if all went well, cy otherwise.
  680.     assume    ds:code
  681.     mov    di,offset int_no
  682.     call    get_number
  683.     mov    di,offset io_addr
  684.     call    get_number
  685.     mov    di,offset base_addr
  686.     call    get_number
  687.     clc
  688.     ret
  689.  
  690.  
  691.     public    etopen
  692. etopen:
  693.     assume    ds:code
  694.  
  695.     cmp    io_addr,-1        ;Did they ask for auto-detect?
  696.     je    find_board
  697.  
  698.     call    detect_board        ;no, just verify its existance.
  699.     je    find_board_found
  700.  
  701.     mov    dx,offset io_addr_funny_msg
  702.     mov    ah,9
  703.     int    21h
  704.  
  705.     jmp    find_board_found
  706.  
  707. find_board:
  708.     mov    io_addr,300h        ;Search for the Ethernet address at 300h
  709.     mov    io_addr+2,0
  710.     call    detect_board
  711.     je    find_board_found
  712.     mov    io_addr,200h        ;Search at 200h
  713.     call    detect_board
  714.     je    find_board_found
  715.  
  716.     mov    dx,offset no_board_msg    ;Tell them that we can't find it.
  717.     stc
  718.     ret
  719. find_board_found:
  720.     cmp    base_addr.offs,0    ;low word of segment can't be zero.
  721.     je    etopen_1
  722.     cmp    base_addr.segm,0    ;high word of segment must be zero.
  723.     je    etopen_2
  724. etopen_1:
  725.     mov    dx,offset addr_bad_msg
  726.     stc
  727.     ret
  728. etopen_2:
  729.  
  730.     mov    ax,base_addr
  731.     mov    cx,4000h        ;test only what we are going to use.
  732.     call    memory_test
  733.     jz    have_depca_mem
  734.  
  735.     mov    dx,offset no_depca_mem_msg
  736.     stc
  737.     ret
  738. have_depca_mem:
  739.  
  740.     movseg    es,cs
  741.     mov    di,offset rom_address
  742.     mov    cx,EADDR_LEN
  743.     loadport            ; Get our Ethernet address base.
  744.     setport    EBASE
  745. get_address_1:
  746.     in    al,dx            ; get a byte of the eprom address
  747.     stosb
  748.     loop    get_address_1        ; go back for rest
  749.  
  750.     mov    si,offset rom_address    ; copy it to the init table.
  751.     mov    es,base_addr
  752.     mov    di,offset init_addr
  753.     mov    cx,EADDR_LEN
  754.     rep    movsb
  755.  
  756.     mov    al, int_no        ; Get board's interrupt vector
  757.     add    al, 8
  758.     cmp    al, 8+8            ; Is it a slave 8259 interrupt?
  759.     jb    set_int_num        ; No.
  760.     add    al, 70h - 8 - 8        ; Map it to the real interrupt.
  761. set_int_num:
  762.     xor    ah, ah            ; Clear high byte
  763.     mov    int_num, ax        ; Set parameter_list int num.
  764.  
  765.     mov    al,int_no
  766.     call    maskint            ;disable these interrupts.
  767.  
  768.     loadport
  769.     mov    ax,CSR0_STOP        ;reset the INIT bit.
  770.     outport    CSR0
  771.  
  772. ;set up transmit descriptor ring.
  773.     mov    es,base_addr
  774.     assume    es:lance_seg
  775.     mov    cx,TRANSMIT_BUF_COUNT
  776.     mov    bx,offset transmit_dscps
  777.     mov    di,offset transmit_bufs
  778. setup_transmit:
  779.     call    segmoffs_to_phys
  780.  
  781.     or    dx,XMIT_START or XMIT_END
  782.     mov    lance_seg:[bx].tmd0,ax    ;points to the buffer.
  783.     mov    lance_seg:[bx].tmd1,dx
  784.  
  785.     add    bx,(size xmit_msg_dscp)
  786.     add    di,TRANSMIT_BUF_SIZE
  787.     loop    setup_transmit
  788.  
  789. ;set up receive descriptor ring.
  790.     mov    cx,RECEIVE_BUF_COUNT
  791.     mov    bx,offset receive_dscps
  792.     mov    di,offset receive_bufs
  793. setup_receive:
  794.     call    segmoffs_to_phys
  795.  
  796.     or    dx,RCV_OWN
  797.     mov    lance_seg:[bx].rmd0,ax    ;points to the buffer.
  798.     mov    lance_seg:[bx].rmd1,dx
  799.  
  800.     mov    lance_seg:[bx].rmd2,-RECEIVE_BUF_SIZE
  801.     mov    lance_seg:[bx].rmd3,0
  802.  
  803.     add    bx,(size rcv_msg_dscp)
  804.     add    di,RECEIVE_BUF_SIZE
  805.     loop    setup_receive
  806.  
  807.     mov    cx,RECEIVE_BUF_COUNT
  808.     call    compute_log2
  809.  
  810.     mov    di,offset receive_dscps
  811.     call    segmoffs_to_phys
  812.     or    dx,cx            ;include the buffer size bits.
  813.     mov    init_receive[0],ax
  814.     mov    init_receive[2],dx
  815.  
  816.     mov    cx,TRANSMIT_BUF_COUNT
  817.     call    compute_log2
  818.  
  819.     mov    di,offset transmit_dscps
  820.     call    segmoffs_to_phys
  821.     or    dx,cx            ;include the buffer size bits.
  822.     mov    init_transmit[0],ax
  823.     mov    init_transmit[2],dx
  824.  
  825.     mov    di,offset init_block    ;now tell the board where the init
  826.     call    segmoffs_to_phys    ;  block is.
  827.     mov    save_csr1,ax
  828.     mov    save_csr2,dx
  829.  
  830.     call    rcv_mode_3
  831.     jnc    init_ok
  832.  
  833.     mov    dx,offset bad_init_msg
  834.     stc
  835.     ret
  836.  
  837. init_ok:
  838. ;
  839. ; Now hook in our interrupt
  840. ;
  841.     call    set_recv_isr
  842.  
  843.     loadport
  844.     setport    NI_CSR
  845.     mov    al,NI_CSR_VALUE        ;disable ROM, enable rev. E DEPCA,
  846.                     ;  enable the interrupt line,
  847.     out    dx,al
  848.  
  849.     clc
  850.     ret
  851.  
  852.     public    print_parameters
  853. print_parameters:
  854. ;echo our command-line parameters
  855.     mov    di,offset int_no
  856.     mov    dx,offset int_no_name
  857.     call    print_number
  858.     mov    di,offset io_addr
  859.     mov    dx,offset io_addr_name
  860.     call    print_number
  861.     mov    di,offset base_addr
  862.     mov    dx,offset base_addr_name
  863.     call    print_number
  864.     ret
  865.  
  866. compute_log2:
  867. ;enter with cx = number of buffers.
  868. ;exit with cx = log2(number of buffers) << 13.
  869.     mov    ax,-1
  870. compute_log2_1:
  871.     inc    ax
  872.     shr    cx,1
  873.     jne    compute_log2_1
  874.     mov    cl,13
  875.     shl    ax,cl
  876.     mov    cx,ax
  877.     ret
  878.  
  879.  
  880. segmoffs_to_phys:
  881. ;enter with es:di -> buffer.
  882. ;exit with dx:ax as the physical address of the buffer,
  883.  
  884.     mov    dx,es            ;get the high 4 bits of the segment,
  885.     shr    dx,16-4
  886.     mov    ax,es            ;and the low 12 bits of the segment.
  887.     shl    ax,4
  888.     add    ax,di            ;add in the offset.
  889.     adc    dx,0
  890.     ret
  891.  
  892.  
  893.     include    memtest.asm
  894.  
  895. code    ends
  896.  
  897.     end
  898.