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

  1. version    equ    2
  2.  
  3.     include    defs.asm
  4.  
  5. ;Ported from Bill Doster's il.c, a C-language driver for the Interlan NI5010
  6. ;by Russell Nelson.  Any bugs are due to Russell Nelson.
  7. ;Updated to version 1.08 Feb. 17, 1989 by Russell Nelson.
  8.  
  9. ;   Copyright, 1988-1992, Russell Nelson, Crynwr Software
  10.  
  11. ;   This program is free software; you can redistribute it and/or modify
  12. ;   it under the terms of the GNU General Public License as published by
  13. ;   the Free Software Foundation, version 1.
  14. ;
  15. ;   This program is distributed in the hope that it will be useful,
  16. ;   but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. ;   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  18. ;   GNU General Public License for more details.
  19. ;
  20. ;   You should have received a copy of the GNU General Public License
  21. ;   along with this program; if not, write to the Free Software
  22. ;   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  23.  
  24. code    segment    word public
  25.     assume    cs:code, ds:code
  26.  
  27. ; The various IE command registers
  28. EDLC_XSTAT    equ    0        ; EDLC transmit csr
  29. EDLC_XCLR    equ    0        ; EDLC transmit "Clear IRQ"
  30. EDLC_XMASK    equ    1        ; EDLC transmit "IRQ Masks"
  31. EDLC_RSTAT    equ    2        ; EDLC receive csr
  32. EDLC_RCLR    equ    2        ; EDLC receive "Clear IRQ"
  33. EDLC_RMASK    equ    3        ; EDLC receive "IRQ Masks"
  34. EDLC_XMODE    equ    4        ; EDLC transmit Mode
  35. EDLC_RMODE    equ    5        ; EDLC receive Mode
  36. EDLC_RESET    equ    6        ; EDLC RESET register
  37. EDLC_TDR1    equ    7        ; "Time Domain Reflectometry" reg1
  38. EDLC_ADDR    equ    8        ; EDLC station address, 6 bytes
  39.                     ; 0Eh doesn't exist for r/w
  40. EDLC_TDR2    equ    0fh        ; "Time Domain Reflectometry" reg2
  41. IE_GP        equ    10h        ; GP pointer (word register)
  42.                     ; 11h is 2nd byte of GP Pointer
  43. IE_RCNT        equ    10h        ; Count of bytes in rcv'd packet
  44.                     ; 11h is 2nd byte of "Byte Count"
  45. IE_MMODE    equ    12h        ; Memory Mode register
  46. IE_DMA_RST    equ    13h        ; IE DMA Reset.  write only
  47. IE_ISTAT    equ    13h        ; IE Interrupt Status.  read only
  48. IE_RBUF        equ    14h        ; IE Receive Buffer port
  49. IE_XBUF        equ    15h        ; IE Transmit Buffer port
  50. IE_SAPROM    equ    16h        ; window on station addr prom
  51. IE_RESET    equ    17h        ; any write causes Board Reset
  52.  
  53. ; bits in EDLC_XSTAT, interrupt clear on write, status when read
  54. XS_TPOK        equ    80h        ; transmit packet successful
  55. XS_CS        equ    40h        ; carrier sense
  56. XS_RCVD        equ    20h        ; transmitted packet received
  57. XS_SHORT    equ    10h        ; transmission media is shorted
  58. XS_UFLW        equ    08h        ; underflow.  iff failed board
  59. XS_COLL        equ    04h        ; collision occurred
  60. XS_16COLL    equ    02h        ; 16th collision occurred
  61. XS_PERR        equ    01h        ; parity error
  62.  
  63. XS_CLR_UFLW    equ    08h        ; clear underflow
  64. XS_CLR_COLL    equ    04h        ; clear collision
  65. XS_CLR_16COLL    equ    02h        ; clear 16th collision
  66. XS_CLR_PERR    equ    01h        ; clear parity error
  67.  
  68. ; bits in EDLC_XMASK, mask/enable transmit interrupts.  register is r/w
  69. XM_TPOK        equ    80h        ; =1 to enable Xmt Pkt OK interrupts
  70. XM_RCVD        equ    20h        ; =1 to enable Xmt Pkt Rcvd ints
  71. XM_UFLW        equ    08h        ; =1 to enable Xmt Underflow ints
  72. XM_COLL        equ    04h        ; =1 to enable Xmt Collision ints
  73. XM_COLL16    equ    02h        ; =1 to enable Xmt 16th Coll ints
  74. XM_PERR        equ    01h        ; =1 to enable Xmt Parity Error ints
  75.                     ; note: always clear this bit
  76.  
  77. ; bits in EDLC_RSTAT, interrupt clear on write, status when read
  78. RS_PKT_OK    equ    80h        ; received good packet
  79. RS_RST_PKT    equ    10h        ; RESET packet received
  80. RS_RUNT        equ    08h        ; Runt Pkt rcvd.  Len < 64 Bytes
  81. RS_ALIGN    equ    04h        ; Alignment error. not 8 bit aligned
  82. RS_CRC_ERR    equ    02h        ; Bad CRC on rcvd pkt
  83. RS_OFLW        equ    01h        ; overflow for rcv FIFO
  84. RS_VALID_BITS    equ    RS_PKT_OK or RS_RST_PKT or RS_RUNT or RS_ALIGN or RS_CRC_ERR or RS_OFLW
  85.                     ; all valid RSTAT bits
  86.  
  87. RS_CLR_PKT_OK    equ    80h        ; clear rcvd packet interrupt
  88. RS_CLR_RST_PKT    equ    10h        ; clear RESET packet received
  89. RS_CLR_RUNT    equ    08h        ; clear Runt Pckt received
  90. RS_CLR_ALIGN    equ    04h        ; clear Alignment error
  91. RS_CLR_CRC_ERR    equ    02h        ; clear CRC error
  92. RS_CLR_OFLW    equ    01h        ; clear rcv FIFO Overflow
  93.  
  94. ; bits in EDLC_RMASK, mask/enable receive interrupts.  register is r/w
  95. RM_PKT_OK    equ    80h        ; =1 to enable rcvd good packet ints
  96. RM_RST_PKT    equ    10h        ; =1 to enable RESET packet ints
  97. RM_RUNT        equ    08h        ; =1 to enable Runt Pkt rcvd ints
  98. RM_ALIGN    equ    04h        ; =1 to enable Alignment error ints
  99. RM_CRC_ERR    equ    02h        ; =1 to enable Bad CRC error ints
  100. RM_OFLW        equ    01h        ; =1 to enable overflow error ints
  101.  
  102. ; bits in EDLC_RMODE, set Receive Packet mode.  register is r/w
  103. RMD_TEST    equ    80h        ; =1 for Chip testing.  normally 0
  104. RMD_ADD_SIZ    equ    10h        ; =1 5-byte addr match.  normally 0
  105. RMD_EN_RUNT    equ    08h        ; =1 enable runt rcv.  normally 0
  106. RMD_EN_RST    equ    04h        ; =1 to rcv RESET pkt.  normally 0
  107.  
  108. RMD_PROMISC    equ    03h        ; receive *all* packets.  unusual
  109. RMD_MULTICAST    equ    02h        ; receive multicasts too.  unusual
  110. RMD_BROADCAST    equ    01h        ; receive broadcasts & normal. usual
  111. RMD_NO_PACKETS    equ    00h        ; don't receive any packets. unusual
  112.  
  113. ; bits in EDLC_XMODE, set Transmit Packet mode.  register is r/w
  114. XMD_COLL_CNT    equ    0f0h        ; coll's since success.  read-only
  115. XMD_IG_PAR    equ    008h        ; =1 to ignore parity.  ALWAYS set
  116. XMD_T_MODE    equ    004h        ; =1 to power xcvr. ALWAYS set this
  117. XMD_LBC        equ    002h        ; =1 for loopbakc.  normally set
  118. XMD_DIS_C    equ    001h        ; =1 disables contention. normally 0
  119.  
  120. ; bits in EDLC_RESET, write only
  121. RS_RESET    equ    80h        ; =1 to hold EDLC in reset state
  122.  
  123. ; bits in IE_MMODE, write only
  124. MM_EN_DMA    equ    80h        ; =1 begin DMA xfer, Cplt clrs it
  125. MM_EN_RCV    equ    40h        ; =1 allows Pkt rcv.  clr'd by rcv
  126. MM_EN_XMT    equ    20h        ; =1 begin Xmt pkt.  Cplt clrs it
  127. MM_BUS_PAGE    equ    18h        ; =00 ALWAYS.  Used when MUX=1
  128. MM_NET_PAGE    equ    06h        ; =00 ALWAYS.  Used when MUX=0
  129. MM_MUX        equ    01h        ; =1 means Rcv Buff on system bus
  130.                     ; =0 means Xmt Buff on system bus
  131.  
  132. ; bits in IE_ISTAT, read only
  133. IS_TDIAG    equ    80h        ; =1 if Diagnostic problem
  134. IS_EN_RCV    equ    20h        ; =1 until frame is rcv'd cplt
  135. IS_EN_XMT    equ    10h        ; =1 until frame is xmt'd cplt
  136. IS_EN_DMA    equ    08h        ; =1 until DMA is cplt or aborted
  137. IS_DMA_INT    equ    04h        ; =0 iff DMA done interrupt. 
  138. IS_R_INT    equ    02h        ; =0 iff unmasked Rcv interrupt
  139. IS_X_INT    equ    01h        ; =0 iff unmasked Xmt interrupt
  140.  
  141. BFRSIZ        equ    2048    ;number of bytes in a buffer
  142.  
  143.     public    int_no
  144. int_no        db    3,0,0,0        ; interrupt number.
  145. io_addr        dw    0300h,0        ; I/O address for card (jumpers)
  146. ipkt_size    dw    ?
  147. opkt_size    dw    ?
  148.  
  149.     public    driver_class, driver_type, driver_name, driver_function, parameter_list
  150. driver_class    db    BLUEBOOK, IEEE8023, 0        ;from the packet spec
  151. driver_type    db    3        ;from the packet spec
  152. driver_name    db    'NI5010',0    ;name of the driver.
  153. driver_function    db    2
  154. parameter_list    label    byte
  155.     db    1    ;major rev of packet driver
  156.     db    9    ;minor rev of packet driver
  157.     db    14    ;length of parameter list
  158.     db    EADDR_LEN    ;length of MAC-layer address
  159.     dw    GIANT    ;MTU, including MAC headers
  160.     dw    MAX_MULTICAST * EADDR_LEN    ;buffer size of multicast addrs
  161.     dw    0    ;(# of back-to-back MTU rcvs) - 1
  162.     dw    0    ;(# of successive xmits) - 1
  163. int_num    dw    0    ;Interrupt # to hook for post-EOI
  164.             ;processing, 0 == none,
  165.  
  166.     public    rcv_modes
  167. rcv_modes    dw    7        ;number of receive modes in our table.
  168.         dw    0               ;There is no mode zero
  169.         dw    rcv_mode_1
  170.         dw    0        ;don't want to bother.
  171.         dw    rcv_mode_3
  172.         dw    0        ;haven't set up perfect filtering yet.
  173.         dw    rcv_mode_5
  174.         dw    rcv_mode_6
  175.  
  176.     extrn    is_186: byte        ;=0 if 808[68], =1 if 80[123]86.
  177. our_type    dw    ?,?
  178. intstat        db    ?
  179.  
  180.     include    popf.asm
  181.     include    io8.asm
  182.  
  183.     public bad_command_intercept
  184. bad_command_intercept:
  185. ;called with ah=command, unknown to the skeleton.
  186. ;exit with nc if okay, cy, dh=error if not.
  187.     mov    dh,BAD_COMMAND
  188.     stc
  189.     ret
  190.  
  191.     public    as_send_pkt
  192. ; The Asynchronous Transmit Packet routine.
  193. ; Enter with es:di -> i/o control block, ds:si -> packet, cx = packet length,
  194. ;   interrupts possibly enabled.
  195. ; Exit with nc if ok, or else cy if error, dh set to error number.
  196. ;   es:di and interrupt enable flag preserved on exit.
  197. as_send_pkt:
  198.     ret
  199.  
  200.     public    drop_pkt
  201. ; Drop a packet from the queue.
  202. ; Enter with es:di -> iocb.
  203. drop_pkt:
  204.     assume    ds:nothing
  205.     ret
  206.  
  207.     public    xmit
  208. ; Process a transmit interrupt with the least possible latency to achieve
  209. ;   back-to-back packet transmissions.
  210. ; May only use ax and dx.
  211. xmit:
  212.     assume    ds:nothing
  213.     ret
  214.  
  215.  
  216.     public    send_pkt
  217. send_pkt:
  218. ;enter with es:di->upcall routine, (0:0) if no upcall is desired.
  219. ;  (only if the high-performance bit is set in driver_function)
  220. ;enter with ds:si -> packet, cx = packet length.
  221. ;exit with nc if ok, or else cy if error, dh set to error number.
  222.     assume    ds:nothing
  223.     cmp    cx,GIANT        ; Is this packet too large?
  224.     ja    send_pkt_toobig
  225.  
  226.     cmp    cx,RUNT        ; minimum length for Ether
  227.     jae    oklen
  228.     mov    cx,RUNT        ; make sure size at least RUNT
  229. oklen:
  230. ;Wait for transmitter ready, if necessary. IE_XMTBSY is valid
  231. ;only in the transmit mode, hence the initial check.
  232.  
  233.     loadport
  234.     setport    IE_ISTAT
  235.     in    al,dx
  236.     and    al,IS_EN_XMT        ;on-going xmit
  237.     je    send_pkt_2
  238.  
  239.     mov    bx,20000        ;try this many times.
  240. send_pkt_3:
  241.     in    al,dx            ;if not busy, exit.
  242.     and    al,IS_EN_XMT
  243.     je    send_pkt_2
  244.     dec    bx
  245.     jne    send_pkt_3
  246.     mov    dh,CANT_SEND        ;timed out, can't send.
  247.     stc
  248.     ret
  249.  
  250. send_pkt_toobig:
  251.     mov    dh,NO_SPACE
  252.     stc
  253.     ret
  254.  
  255. send_pkt_2:
  256.  
  257.     pushf            ; No distractions from the receiver
  258.     cli
  259.  
  260. ; Disable the Receiver
  261.     mov    al, 0        ; Mask all Receive Interrupts
  262.     loadport
  263.     setport    EDLC_RMASK
  264.     out    dx,al
  265.  
  266.     mov    al, 0        ; Put Xmt Buffer on System Bus
  267.     setport    IE_MMODE
  268.     out    dx,al
  269.  
  270.     mov    al, 0FFh    ; Clear out any pending Rcv Ints
  271.     setport    EDLC_RCLR
  272.     out    dx,al
  273.  
  274.     mov    ax, BFRSIZ    ; Point GP at beginning of packet
  275.     sub    ax,cx
  276.     setport    IE_GP
  277.     out    dx,ax
  278.  
  279.     setport    IE_XBUF
  280.  
  281.     mov    opkt_size,cx    ; opkt_size = cx;
  282.     call    repoutsb
  283.  
  284. ; Rewrite where packet starts
  285.     mov    ax,BFRSIZ
  286.     sub    ax,opkt_size
  287.     setport    IE_GP
  288.     out    dx,ax
  289.  
  290. ; Flip Xmt Buffer to EDLC Bus so it can be transmitted
  291.     mov    al, MM_MUX
  292.     setport    IE_MMODE
  293.     out    dx,al
  294.  
  295. ; Begin transmission.
  296.     mov    al, MM_EN_XMT or MM_MUX
  297.     setport    IE_MMODE
  298.     out    dx,al
  299.  
  300. ; Cause interrupt after completion (or if something fails)
  301.     mov    al, XM_TPOK or XM_RCVD or XM_UFLW or XM_COLL or XM_COLL16
  302.     setport    EDLC_XMASK
  303.     out    dx,al
  304.  
  305.     popf
  306.     clc
  307.     ret
  308.  
  309.  
  310. ;Set Ethernet address on controller
  311.     public    set_address
  312. set_address:
  313.     assume    ds:nothing
  314. ;enter with ds:si -> Ethernet address, CX = length of address.
  315. ;exit with nc if okay, or cy, dh=error if any errors.
  316. ;
  317.     cmp    cx,EADDR_LEN        ;ensure that their address is okay.
  318.     je    set_address_4
  319.     mov    dh,BAD_ADDRESS
  320.     stc
  321.     jmp    short set_address_done
  322. set_address_4:
  323.  
  324.     loadport
  325.     setport    EDLC_ADDR
  326. set_address_1:
  327.     lodsb
  328.     out    dx,al
  329.     inc    dx
  330.     loop    set_address_1
  331. set_address_okay:
  332.     mov    cx,EADDR_LEN        ;return their address length.
  333.     clc
  334. set_address_done:
  335.     movseg    ds,cs
  336.     assume    ds:code
  337.     ret
  338.  
  339.  
  340. ;skip past the following two bytes while destroying BX.
  341. skip2    macro
  342.     db    0bbh            ;opcode of "mov bx,0000"
  343.     endm
  344.  
  345. rcv_mode_1:
  346.     mov    al,RMD_NO_PACKETS    ;receive nothing
  347.     skip2
  348. rcv_mode_3:
  349.     mov    al,RMD_BROADCAST    ;receive individual address+broadcast
  350.     skip2
  351. rcv_mode_5:
  352.     mov    al,RMD_MULTICAST    ;receive individual address+group addr(multicast)
  353.     skip2
  354. rcv_mode_6:
  355.     mov    al,RMD_PROMISC + RMD_EN_RUNT    ;receive all packets (incl runts).
  356.     loadport
  357.     setport    EDLC_RMODE
  358.     out    dx,al
  359.     in    al,dx            ;flush status.
  360.     ret
  361.  
  362.  
  363.     public    set_multicast_list
  364. set_multicast_list:
  365. ;enter with ds:si ->list of multicast addresses, ax = number of addresses,
  366. ;  cx = number of bytes.
  367. ;return nc if we set all of them, or cy,dh=error if we didn't.
  368.     mov    dh,NO_MULTICAST
  369.     stc
  370.     ret
  371.  
  372.  
  373.     public    terminate
  374. terminate:
  375. ; put card in held-RESET state
  376.     loadport
  377.     setport    IE_MMODE
  378.     mov    al,0
  379.     out    dx,al
  380.  
  381.     setport    EDLC_RESET
  382.     mov    al,RS_RESET
  383.     out    dx,al
  384.  
  385.     ret
  386.  
  387.  
  388.     public    reset_interface
  389. reset_interface:
  390. ;reset the interface.
  391. ;we don't do anything.
  392.     ret
  393.  
  394.  
  395. ;called when we want to determine what to do with a received packet.
  396. ;enter with cx = packet length, es:di -> packet type, dl = packet class.
  397.     extrn    recv_find: near
  398.  
  399. ;called after we have copied the packet into the buffer.
  400. ;enter with ds:si ->the packet, cx = length of the packet.
  401.     extrn    recv_copy: near
  402.  
  403. ;call this routine to schedule a subroutine that gets run after the
  404. ;recv_isr.  This is done by stuffing routine's address in place
  405. ;of the recv_isr iret's address.  This routine should push the flags when it
  406. ;is entered, and should jump to recv_exiting_exit to leave.
  407. ;enter with ax = address of routine to run.
  408.     extrn    schedule_exiting: near
  409.  
  410. ;recv_exiting jumps here to exit, after pushing the flags.
  411.     extrn    recv_exiting_exit: near
  412.  
  413.     extrn    count_in_err: near
  414.     extrn    count_out_err: near
  415.  
  416.     public    recv
  417. recv:
  418. ;called from the recv isr.  All registers have been saved, and ds=cs.
  419. ;Upon exit, the interrupt will be acknowledged.
  420.     assume    ds:code
  421.  
  422.     loadport
  423.     setport    IE_ISTAT
  424.     in    al,dx
  425.     mov    intstat,al
  426.  
  427. ; DMA Complete Interrupt.  We don't use DMA, but just in case ...
  428.     test    al,IS_DMA_INT
  429.     jne    recv_isr_3
  430.  
  431.     mov    al, 0         ; Reset DMA Interrupt
  432.     setport    IE_DMA_RST
  433.     out    dx,al
  434.  
  435. recv_isr_3:
  436.  
  437. ; Transmit Complete/Fail Interrupt
  438.     test    intstat,IS_X_INT
  439.     jne    recv_isr_1
  440.  
  441.     loadport
  442.     setport    EDLC_XSTAT
  443.     in    al,dx
  444.     mov    ah,al
  445.  
  446.     mov    al, 0            ; Disable Xmt IRQ's
  447.     setport    EDLC_XMASK
  448.     out    dx,al
  449.  
  450.     mov    al, 0FFh        ; clr all Xmt IRQ's
  451.     setport    EDLC_XCLR
  452.     out    dx,al
  453.  
  454.     test    ah,XS_COLL
  455.     je    recv_isr_1
  456.     ;Crank counter back to beginning and restart xmt
  457.  
  458.     mov    ax,BFRSIZ        ; Point GP at beginning of packet
  459.     sub    ax,opkt_size
  460.     setport    IE_GP
  461.     out    dx,ax
  462.  
  463.     mov    al, 0        ; De-assert MM_EN_RCV bit Just In Case
  464.     setport    IE_MMODE
  465.     out    dx,al
  466.  
  467.                 ; Flip Xmt Buffer to EDLC Bus and restart xmt
  468.     mov    al, MM_EN_XMT or MM_MUX
  469.     setport    IE_MMODE
  470.     out    dx,al
  471.  
  472.             ; Interrupt for all Transmit errors along with TPOK
  473.     mov    al, XM_TPOK or XM_RCVD or XM_UFLW or XM_COLL or XM_COLL16
  474.     setport    EDLC_XMASK
  475.     out    dx,al
  476.  
  477.     ret            ; Wait for it to complete again
  478.  
  479. recv_isr_1:
  480.     ; Is this a Receive Packet Interrupt?
  481.     test    intstat,IS_R_INT
  482.     jne    recv_isr_9_j_1        ;no.
  483.  
  484.     loadport
  485.     setport    EDLC_RSTAT        ;get the status of this packet
  486.     in    al,dx
  487.     and    al,RS_VALID_BITS
  488.     cmp    al,RS_PKT_OK        ;is it ok?
  489.     jne    recv_isr_7        ;yes.
  490.  
  491.     ; Clear the interrupt
  492.     mov    al, 0FFh
  493.     setport    EDLC_RCLR
  494.     out    dx,al
  495.  
  496.     ; Flip Rcv Buffer onto the system bus
  497.     mov    al, MM_MUX
  498.     setport    IE_MMODE
  499.     out    dx,al
  500.  
  501.     ; Get the size of the packet.
  502.     setport    IE_RCNT
  503.     in    ax,dx
  504.     mov    ipkt_size,ax
  505.  
  506.     cmp    ax,GIANT        ;greater than GIANT?
  507.     jbe    recv_isr_8        ;no.
  508. recv_isr_7:
  509.     call    count_in_err
  510. recv_isr_9_j_1:
  511.     jmp    recv_isr_9
  512. recv_isr_8:
  513. ;Put it on the receive queue
  514.  
  515.     loadport
  516.     mov    ax,EADDR_LEN+EADDR_LEN            ;seek to the type word.
  517.     setport    IE_GP
  518.     out    dx,ax
  519.  
  520.     setport    IE_RBUF
  521.     in    al,dx            ;read the type word out of the board.
  522.     mov    ah,al
  523.     in    al,dx
  524.     xchg    al,ah            ;should be in network byte order.
  525.     mov    our_type,ax
  526.     in    al,dx            ;read the type word out of the board.
  527.     mov    ah,al
  528.     in    al,dx
  529.     xchg    al,ah            ;should be in network byte order.
  530.     mov    our_type+2,ax
  531.  
  532.     mov    ax,ds            ;look up our type.
  533.     mov    es,ax
  534.     mov    di,offset our_type
  535.     mov    cx,ipkt_size
  536.  
  537.     mov    dl, BLUEBOOK        ;assume bluebook Ethernet.
  538.     mov    ax, es:[di]
  539.     xchg    ah, al
  540.     cmp     ax, 1500
  541.     ja    BlueBookPacket
  542.     inc    di            ;set di to 802.2 header
  543.     inc    di
  544.     mov    dl, IEEE8023
  545. BlueBookPacket:
  546.     call    recv_find
  547.  
  548.     mov    ax,es            ;is this pointer null?
  549.     or    ax,di
  550.     je    recv_isr_9        ;yes - just free the frame.
  551.  
  552.     push    es            ;remember where the buffer pointer is.
  553.     push    di
  554.  
  555.     xor    ax,ax            ;seek to the beginning again.
  556.     loadport
  557.     setport    IE_GP
  558.     out    dx,ax
  559.  
  560.     mov    cx,ipkt_size
  561.     setport    IE_RBUF
  562.  
  563.     call    repinsb
  564.  
  565.     pop    si
  566.     pop    ds
  567.     assume    ds:nothing
  568.     mov    cx,ipkt_size
  569.     call    recv_copy        ;tell them that we copied it.
  570.  
  571.     mov    ax,cs            ;restore our ds.
  572.     mov    ds,ax
  573.     assume    ds:code
  574.  
  575. recv_isr_9:
  576.  
  577. ; Prime Interlan card for another Receive
  578. il_rcv_reset:
  579.  
  580.     ; Rcv packet at start of Boards buffer
  581.     mov    ax,0
  582.     loadport
  583.     setport    IE_GP
  584.     out    dx,ax
  585.  
  586.     ; Clear any remaining Interrupt conditions
  587.     mov    al,0FFh
  588.     setport    EDLC_RCLR
  589.     out    dx,al
  590.  
  591.     ; Set MUX to allow EDLC to access Rcv Buffer
  592.     mov    al,0
  593.     setport    IE_MMODE
  594.     out    dx,al
  595.  
  596. ;
  597. ;    Next section commented out to make promiscous mode work.
  598. ;    It makes no sense to reset the receive mode after each
  599. ;    received packet. M.K.
  600. ;
  601.     ; Enable Receive of Normal and Broadcast Packets only.
  602. ;    mov    al,RMD_BROADCAST
  603. ;    setport    EDLC_RMODE
  604. ;    out    dx,al
  605.  
  606.     ; Enable Receive Interrupts
  607.     mov    al,MM_EN_RCV
  608.     setport    IE_MMODE
  609.     out    dx,al
  610.  
  611.     ; Unmask *all* Receive related interrupts
  612.     mov    al,0FFh
  613.     setport    EDLC_RMASK
  614.     out    dx,al
  615.  
  616.     ret
  617.  
  618.  
  619.     public    timer_isr
  620. timer_isr:
  621. ;if the first instruction is an iret, then the timer is not hooked
  622.     iret
  623.  
  624. ;any code after this will not be kept.  Buffers used by the program, if any,
  625. ;are allocated from the memory between end_resident and end_free_mem.
  626.     public end_resident,end_free_mem
  627. end_resident    label    byte
  628. end_free_mem    label    byte
  629.  
  630.     public    usage_msg
  631. usage_msg    db    "usage: NI5010 [options] <packet_int_no> <hardware_irq> <io_addr>",CR,LF,'$'
  632.  
  633.     public    copyright_msg
  634. copyright_msg    db    "Packet driver for the Interlan NI5010, version ",'0'+(majver / 10),'0'+(majver mod 10),".",'0'+version,CR,LF
  635.         db    "Portions Copyright 1988 Bill Doster",CR,LF,CR,LF
  636.         db    "Promiscous mode fixed by Martin Knoblauch (22-Aug-90).",CR,LF
  637.         db    "Flame <XBR2D96D@DDATHD21.BITNET> for related problems",CR,LF,CR,LF,'$'
  638.  
  639. no_ni5010_msg    db    "No NI5010 found at that address.",CR,LF,'$'
  640. ether_bdcst    db    EADDR_LEN dup(-1)    ;ethernet broadcast address.
  641.  
  642. int_no_name    db    "Interrupt number ",'$'
  643. io_addr_name    db    "I/O port ",'$'
  644.  
  645.     extrn    set_recv_isr: near
  646.     extrn    maskint: near
  647.  
  648. ;enter with si -> argument string, di -> word to store.
  649. ;if there is no number, don't change the number.
  650.     extrn    get_number: near
  651.  
  652. ;enter with dx -> name of word, di -> dword to print.
  653.     extrn    print_number: near
  654.  
  655. ;-> the assigned Ethernet address of the card.
  656.     extrn    rom_address: byte
  657.  
  658.     public    parse_args
  659. parse_args:
  660. ;exit with nc if all went well, cy otherwise.
  661.     mov    di,offset int_no
  662.     call    get_number
  663.     mov    di,offset io_addr
  664.     call    get_number
  665.     clc
  666.     ret
  667.  
  668.  
  669. no_ni5010_error:
  670.     mov    dx,offset no_ni5010_msg
  671.     stc
  672.     ret
  673.  
  674.  
  675.     public    etopen
  676. etopen:
  677. ;  Initialize the Ethernet board, set receive type.
  678. ;
  679. ;  check for correct EPROM location
  680. ;
  681.     mov    al,int_no
  682.     call    maskint            ;disable these interrupts.
  683.  
  684.     ; Hold up EDLC RESET while the board is configured
  685.     mov    al,RS_RESET
  686.     loadport
  687.     setport    EDLC_RESET
  688.     out    dx,al
  689.  
  690.     ; Hardware reset of Interlan Board
  691.     mov    al,0
  692.     setport    IE_RESET
  693.     out    dx,al
  694.  
  695.     call    set_recv_isr
  696.  
  697.     mov    al,XMD_LBC
  698.     loadport
  699.     setport    EDLC_XMODE
  700.     out    dx,al
  701.  
  702.     movseg    es,ds
  703.     mov    di,offset rom_address
  704.     mov    cx,EADDR_LEN+3        ;get three extra signature bytes.
  705.     xor    bx,bx
  706. get_address_1:
  707.     mov    ax,bx
  708.     loadport
  709.     setport    IE_GP
  710.     out    dx,ax
  711.  
  712.     setport    IE_SAPROM
  713.     in    al,dx
  714.     stosb
  715.     inc    bx
  716.     loop    get_address_1
  717.  
  718.     mov    si,offset rom_address
  719.     mov    cx,EADDR_LEN
  720.     call    set_address
  721.  
  722. ;See if there really is a ni5010 there.
  723.     cmp    rom_address+EADDR_LEN+0,0
  724.     jne    no_ni5010
  725.     cmp    rom_address+EADDR_LEN+1,055h
  726.     jne    no_ni5010
  727.     cmp    rom_address+EADDR_LEN+2,0aah
  728.     jne    no_ni5010
  729.  
  730.     mov    cx,EADDR_LEN
  731.     mov    di,offset ether_bdcst
  732.     repe    cmpsb
  733.     jne    have_ni5010        ;not broadcast address -- must be real.
  734. no_ni5010:
  735.     jmp    no_ni5010_error        ;not there -- no ni5010.
  736. have_ni5010:
  737.  
  738.     ; Only enable Transmit-type interrupts while Transmitting
  739.     mov    al,0
  740.     loadport
  741.     setport    EDLC_XMASK
  742.     out    dx,al
  743.  
  744.     ; Establish generic Transmit mode
  745.     mov    al,XMD_IG_PAR or XMD_T_MODE or XMD_LBC
  746.     setport    EDLC_XMODE
  747.     out    dx,al
  748.  
  749.     ; Clear any startup related Transmit interrupts
  750.     mov    al,0FFh
  751.     setport    EDLC_XCLR
  752.     out    dx,al
  753.  
  754.     ; Establish generic Receive mode
  755.     mov    al,RMD_BROADCAST
  756.     setport    EDLC_RMODE
  757.     out    dx,al
  758.  
  759.     ; Reset Rcv State to allow receives
  760.     call    il_rcv_reset
  761.  
  762.     ; Finally un-reset the EDLC
  763.     mov    al,0
  764.     loadport
  765.     setport    EDLC_RESET
  766.     out    dx,al
  767.  
  768.     mov    al, int_no        ; Get board's interrupt vector
  769.     add    al, 8
  770.     cmp    al, 8+8            ; Is it a slave 8259 interrupt?
  771.     jb    set_int_num        ; No.
  772.     add    al, 70h - 8 - 8        ; Map it to the real interrupt.
  773. set_int_num:
  774.     xor    ah, ah            ; Clear high byte
  775.     mov    int_num, ax        ; Set parameter_list int num.
  776.  
  777.     clc
  778.     ret
  779.  
  780.     public    print_parameters
  781. print_parameters:
  782. ;echo our command-line parameters
  783.     mov    di,offset int_no
  784.     mov    dx,offset int_no_name
  785.     call    print_number
  786.     mov    di,offset io_addr
  787.     mov    dx,offset io_addr_name
  788.     call    print_number
  789.     ret
  790.  
  791. code    ends
  792.  
  793.     end
  794.