home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / lan / drivrs30 / ni5010.asm < prev    next >
Assembly Source File  |  1989-06-08  |  18KB  |  726 lines

  1. version    equ    0
  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, 1989, Russell Nelson
  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    byte 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
  150. driver_class    db    1        ;from the packet spec
  151. driver_type    db    3        ;from the packet spec
  152. driver_name    db    'NI5010',0    ;name of the driver.
  153.  
  154. is_186        db    0        ;=0 if 808[68], =1 if 80[123]86.
  155. our_type    dw    ?
  156. intstat        db    ?
  157.  
  158.     public    send_pkt
  159. send_pkt:
  160. ;enter with ds:si -> packet, cx = packet length.
  161. ;exit with nc if ok, or else cy if error, dh set to error number.
  162.     assume    ds:nothing
  163.     cmp    cx,RUNT        ; minimum length for Ether
  164.     jae    oklen
  165.     mov    cx,RUNT        ; make sure size at least RUNT
  166. oklen:
  167.     inc    cx            ;round size up to next even number.
  168.     and    cx,not 1
  169.  
  170. ;Wait for transmitter ready, if necessary. IE_XMTBSY is valid
  171. ;only in the transmit mode, hence the initial check.
  172.  
  173.     loadport
  174.     setport    IE_ISTAT
  175.     in    al,dx
  176.     and    al,IS_EN_XMT        ;on-going xmit
  177.     je    send_pkt_2
  178.  
  179.     mov    bx,20000        ;try this many times.
  180. send_pkt_3:
  181.     in    al,dx            ;if not busy, exit.
  182.     and    al,IS_EN_XMT
  183.     je    send_pkt_2
  184.     dec    bx
  185.     jne    send_pkt_3
  186.     mov    dh,CANT_SEND        ;timed out, can't send.
  187.     stc
  188.     ret
  189. send_pkt_2:
  190.  
  191.     pushf            ; No distractions from the receiver
  192.     cli
  193.  
  194. ; Disable the Receiver
  195.     mov    al, 0        ; Mask all Receive Interrupts
  196.     loadport
  197.     setport    EDLC_RMASK
  198.     out    dx,al
  199.  
  200.     mov    al, 0        ; Put Xmt Buffer on System Bus
  201.     setport    IE_MMODE
  202.     out    dx,al
  203.  
  204.     mov    al, 0FFh    ; Clear out any pending Rcv Ints
  205.     setport    EDLC_RCLR
  206.     out    dx,al
  207.  
  208.     mov    ax, BFRSIZ    ; Point GP at beginning of packet
  209.     sub    ax,cx
  210.     setport    IE_GP
  211.     out    dx,ax
  212.  
  213.     setport    IE_XBUF
  214.  
  215.     mov    opkt_size,cx    ; opkt_size = cx;
  216.     cmp    is_186,0    ; Can we use rep outsb?
  217.     je    out86        ; no - have to do it slowly.
  218.     rep    outsb
  219.     jmp    short ocnteven
  220. out86:
  221.     test    si,1        ; (buf & 1) ?
  222.     jz    obufeven    ; no
  223.     lodsb            ; al = *si++;
  224.     out    dx,al        ; out(dx,al);
  225.     dec    cx        ; cx--;
  226. obufeven:
  227.     mov    di,cx        ; save for later test
  228.     shr    cx,1        ; cx = cnt >> 1; (convert to word count)
  229. ; Do the bulk of the buffer, a word at a time
  230.     jcxz    onobuf        ; if(cx != 0){
  231. xb:    lodsw            ; do { ax = *si++; (si is word pointer)
  232.     out    dx,al        ; out(dx,lowbyte(ax));
  233.     mov    al,ah
  234.     out    dx,al        ; out(dx,hibyte(ax));
  235.     loop    xb        ; } while(--cx != 0); }
  236. ; now check for odd trailing byte
  237. onobuf:    shr    di,1        ; if (di & 1)
  238.     jnc    ocnteven
  239.     lodsb            ;   out(dx,*si++);
  240.     out    dx,al
  241. ocnteven:
  242.  
  243. ; Rewrite where packet starts
  244.     mov    ax,BFRSIZ
  245.     sub    ax,opkt_size
  246.     loadport
  247.     setport    IE_GP
  248.     out    dx,ax
  249.  
  250. ; Flip Xmt Buffer to EDLC Bus so it can be transmitted
  251.     mov    al, MM_MUX
  252.     setport    IE_MMODE
  253.     out    dx,al
  254.  
  255. ; Begin transmission.
  256.     mov    al, MM_EN_XMT or MM_MUX
  257.     setport    IE_MMODE
  258.     out    dx,al
  259.  
  260. ; Cause interrupt after completion (or if something fails)
  261.     mov    al, XM_TPOK or XM_RCVD or XM_UFLW or XM_COLL or XM_COLL16
  262.     setport    EDLC_XMASK
  263.     out    dx,al
  264.  
  265.     popf
  266.     clc
  267.     ret
  268.  
  269.  
  270.     public    get_address
  271. get_address:
  272. ;get the address of the interface.
  273. ;enter with es:di -> place to get the address, cx = size of address buffer.
  274. ;exit with nc, cx = actual size of address, or cy if buffer not big enough.
  275.     assume    ds:code
  276.     cmp    cx,EADDR_LEN            ;make sure that we have enough room.
  277.     jb    get_address_2
  278.     cmp    cx,9            ;do we have room for all of it?
  279.     jb    get_address_3        ;no.
  280.     mov    cx,9            ;yes - get the whole thing.
  281.     xor    bx,bx
  282.     jmp    short get_address_1
  283. get_address_3:
  284.     mov    cx,EADDR_LEN
  285.     xor    bx,bx
  286. get_address_1:
  287.     mov    ax,bx
  288.     loadport
  289.     setport    IE_GP
  290.     out    dx,ax
  291.  
  292.     setport    IE_SAPROM
  293.     in    al,dx
  294.     stosb
  295.     inc    bx
  296.     loop    get_address_1
  297.  
  298.     mov    cx,EADDR_LEN
  299.     clc
  300.     ret
  301. get_address_2:
  302.     stc
  303.     ret
  304.  
  305.  
  306. ;Set Ethernet address on controller
  307.     public    set_address
  308. set_address:
  309.     assume    ds:nothing
  310. ;enter with ds:si -> Ethernet address, CX = length of address.
  311. ;exit with nc if okay, or cy, dh=error if any errors.
  312. ;
  313.     cmp    cx,EADDR_LEN        ;ensure that their address is okay.
  314.     je    set_address_4
  315.     mov    dh,BAD_ADDRESS
  316.     stc
  317.     jmp    short set_address_done
  318. set_address_4:
  319.  
  320.     loadport
  321.     setport    EDLC_ADDR
  322. set_address_1:
  323.     lodsb
  324.     out    dx,al
  325.     inc    dx
  326.     loop    set_address_1
  327. set_address_okay:
  328.     clc
  329. set_address_done:
  330.     push    cs
  331.     pop    ds
  332.     assume    ds:code
  333.     ret
  334.  
  335.  
  336. terminate:
  337.     ; put card in held-RESET state
  338.     mov    al,0
  339.     loadport
  340.     setport    IE_MMODE
  341.     out    dx,al
  342.     mov    al,RS_RESET
  343.     loadport
  344.     setport    EDLC_RESET
  345.     out    dx,al
  346.  
  347.     ret
  348.  
  349.  
  350.     public    reset_interface
  351. reset_interface:
  352. ;reset the interface.
  353. ;we don't do anything.
  354.     ret
  355.  
  356.  
  357. ;called when we want to determine what to do with a received packet.
  358. ;enter with cx = packet length, es:di -> packet type.
  359.     extrn    recv_find: near
  360.  
  361. ;called after we have copied the packet into the buffer.
  362. ;enter with ds:si ->the packet, cx = length of the packet.
  363.     extrn    recv_copy: near
  364.  
  365.     extrn    count_in_err: near
  366.     extrn    count_out_err: near
  367.  
  368.     public    recv
  369. recv:
  370. ;called from the recv isr.  All registers have been saved, and ds=cs.
  371. ;Upon exit, the interrupt will be acknowledged.
  372.     assume    ds:code
  373.  
  374.     loadport
  375.     setport    IE_ISTAT
  376.     in    al,dx
  377.     mov    intstat,al
  378.  
  379. ; DMA Complete Interrupt.  We don't use DMA, but just in case ...
  380.     test    al,IS_DMA_INT
  381.     jne    recv_isr_3
  382.  
  383.     mov    al, 0         ; Reset DMA Interrupt
  384.     setport    IE_DMA_RST
  385.     out    dx,al
  386.  
  387. recv_isr_3:
  388.  
  389. ; Transmit Complete/Fail Interrupt
  390.     test    intstat,IS_X_INT
  391.     jne    recv_isr_1
  392.  
  393.     loadport
  394.     setport    EDLC_XSTAT
  395.     in    al,dx
  396.     mov    ah,al
  397.  
  398.     mov    al, 0            ; Disable Xmt IRQ's
  399.     setport    EDLC_XMASK
  400.     out    dx,al
  401.  
  402.     mov    al, 0FFh        ; clr all Xmt IRQ's
  403.     setport    EDLC_XCLR
  404.     out    dx,al
  405.  
  406.     test    ah,XS_COLL
  407.     je    recv_isr_1
  408.     ;Crank counter back to beginning and restart xmt
  409.  
  410.     mov    ax,BFRSIZ        ; Point GP at beginning of packet
  411.     sub    ax,opkt_size
  412.     setport    IE_GP
  413.     out    dx,ax
  414.  
  415.     mov    al, 0        ; De-assert MM_EN_RCV bit Just In Case
  416.     setport    IE_MMODE
  417.     out    dx,al
  418.  
  419.                 ; Flip Xmt Buffer to EDLC Bus and restart xmt
  420.     mov    al, MM_EN_XMT or MM_MUX
  421.     setport    IE_MMODE
  422.     out    dx,al
  423.  
  424.             ; Interrupt for all Transmit errors along with TPOK
  425.     mov    al, XM_TPOK or XM_RCVD or XM_UFLW or XM_COLL or XM_COLL16
  426.     setport    EDLC_XMASK
  427.     out    dx,al
  428.  
  429.     ret            ; Wait for it to complete again
  430.  
  431. recv_isr_1:
  432.     ; Is this a Receive Packet Interrupt?
  433.     test    intstat,IS_R_INT
  434.     jne    recv_isr_9_j_1        ;no.
  435.  
  436.     loadport
  437.     setport    EDLC_RSTAT        ;get the status of this packet
  438.     in    al,dx
  439.     and    al,RS_VALID_BITS
  440.     cmp    al,RS_PKT_OK        ;is it ok?
  441.     jne    recv_isr_7        ;yes.
  442.  
  443.     ; Clear the interrupt
  444.     mov    al, 0FFh
  445.     loadport
  446.     setport    EDLC_RCLR
  447.     out    dx,al
  448.  
  449.     ; Flip Rcv Buffer onto the system bus
  450.     mov    al, MM_MUX
  451.     setport    IE_MMODE
  452.     out    dx,al
  453.  
  454.     ; Get the size of the packet.
  455.     setport    IE_RCNT
  456.     in    ax,dx
  457.     mov    ipkt_size,ax
  458.  
  459.     cmp    ax,GIANT        ;greater than GIANT?
  460.     jbe    recv_isr_8        ;no.
  461. recv_isr_7:
  462.     call    count_in_err
  463. recv_isr_9_j_1:
  464.     jmp    recv_isr_9
  465. recv_isr_8:
  466. ;Put it on the receive queue
  467.  
  468.     mov    ax,EADDR_LEN+EADDR_LEN            ;seek to the type word.
  469.     setport    IE_GP
  470.     out    dx,ax
  471.  
  472.     setport    IE_RBUF
  473.     in    al,dx            ;read the type word out of the board.
  474.     mov    ah,al
  475.     in    al,dx
  476.     xchg    al,ah            ;should be in network byte order.
  477.     mov    our_type,ax
  478.  
  479.     mov    ax,ds            ;look up our type.
  480.     mov    es,ax
  481.     mov    di,offset our_type
  482.     mov    cx,ipkt_size
  483.     call    recv_find
  484.  
  485.     mov    ax,es            ;is this pointer null?
  486.     or    ax,di
  487.     je    recv_isr_9        ;yes - just free the frame.
  488.  
  489.     push    es            ;remember where the buffer pointer is.
  490.     push    di
  491.  
  492.     xor    ax,ax            ;seek to the beginning again.
  493.     loadport
  494.     setport    IE_GP
  495.     out    dx,ax
  496.  
  497.     mov    cx,ipkt_size
  498.     setport    IE_RBUF
  499.  
  500.     cmp    is_186,0    ; Can we use rep insb?
  501.     je    in86        ; no - have to do it slowly.
  502.     rep    insb
  503.     jmp    short icnteven
  504. in86:
  505. ; If buffer doesn't begin on a word boundary, get the first byte
  506.     test    di,1    ; if(buf & 1){
  507.     jz    ibufeven ;
  508.     in    al,dx    ; al = in(dx);
  509.     stosb        ; *di++ = al
  510.     dec    cx    ; cx--;
  511. ibufeven:
  512.     mov    si,cx    ; size = cx;
  513.     shr    cx,1    ; cx = cnt >> 1; (convert to word count)
  514. ; Do the bulk of the buffer, a word at a time
  515.     jcxz    inobuf    ; if(cx != 0){
  516. rb:    in    al,dx    ; do { al = in(dx);
  517.     mov    ah,al
  518.     in    al,dx    ; ah = in(dx);
  519.     xchg    al,ah
  520.     stosw        ; *si++ = ax; (di is word pointer)
  521.     loop    rb    ; } while(--cx != 0);
  522. ; now check for odd trailing byte
  523. inobuf:    shr    si,1
  524.     jnc    icnteven
  525.     in    al,dx
  526.     stosb        ; *di++ = al
  527. icnteven:
  528.  
  529.     pop    si
  530.     pop    ds
  531.     assume    ds:nothing
  532.     mov    cx,ipkt_size
  533.     call    recv_copy        ;tell them that we copied it.
  534.  
  535.     mov    ax,cs            ;restore our ds.
  536.     mov    ds,ax
  537.     assume    ds:code
  538.  
  539. recv_isr_9:
  540.  
  541. ; Prime Interlan card for another Receive
  542. il_rcv_reset:
  543.  
  544.     ; Rcv packet at start of Boards buffer
  545.     mov    ax,0
  546.     loadport
  547.     setport    IE_GP
  548.     out    dx,ax
  549.  
  550.     ; Clear any remaining Interrupt conditions
  551.     mov    al,0FFh
  552.     setport    EDLC_RCLR
  553.     out    dx,al
  554.  
  555.     ; Set MUX to allow EDLC to access Rcv Buffer
  556.     mov    al,0
  557.     setport    IE_MMODE
  558.     out    dx,al
  559.  
  560.     ; Enable Receive of Normal and Broadcast Packets only.
  561.     mov    al,RMD_BROADCAST
  562.     setport    EDLC_RMODE
  563.     out    dx,al
  564.  
  565.     ; Enable Receive Interrupts
  566.     mov    al,MM_EN_RCV
  567.     setport    IE_MMODE
  568.     out    dx,al
  569.  
  570.     ; Unmask *all* Receive related interrupts
  571.     mov    al,0FFh
  572.     setport    EDLC_RMASK
  573.     out    dx,al
  574.  
  575.     ret
  576.  
  577.  
  578. end_resident    label    byte
  579.  
  580.     public    usage_msg
  581. usage_msg    db    "usage: NI5010 <packet_int_no> <int_no> <io_addr>",CR,LF,'$'
  582.  
  583.     public    copyright_msg
  584. copyright_msg    db    "Packet driver for the Interlan NI5010, version ",'0'+majver,".",'0'+version,CR,LF
  585.         db    "Portions Copyright 1988 Bill Doster",CR,LF,'$'
  586.  
  587.  
  588. using_186_msg    db    "Using 80[123]86 I/O instructions.",CR,LF,'$'
  589. no_ni5010_msg    db    "No NI5010 found at that address.",CR,LF,'$'
  590. ether_bdcst    db    EADDR_LEN dup(-1)    ;ethernet broadcast address.
  591. our_address    db    EADDR_LEN+3 dup(?)    ;temporarily hold our address
  592.  
  593. int_no_name    db    "Interrupt number ",'$'
  594. io_addr_name    db    "I/O port ",'$'
  595.  
  596.     extrn    set_recv_isr: near
  597.  
  598. ;enter with si -> argument string, di -> word to store.
  599. ;if there is no number, don't change the number.
  600.     extrn    get_number: near
  601.  
  602.     public    parse_args
  603. parse_args:
  604.     mov    di,offset int_no
  605.     mov    bx,offset int_no_name
  606.     call    get_number
  607.     mov    di,offset io_addr
  608.     mov    bx,offset io_addr_name
  609.     call    get_number
  610.     ret
  611.  
  612.  
  613. no_ni5010_error:
  614.     mov    dx,offset no_ni5010_msg
  615.     mov    ah,9
  616.     int    21h
  617.     stc
  618.     ret
  619.  
  620.  
  621.     public    etopen
  622. etopen:
  623. ;  Initialize the Ethernet board, set receive type.
  624. ;
  625. ;  check for correct EPROM location
  626. ;
  627.     pushf        ; No distractions from the receiver
  628.     cli
  629.  
  630.     ; Hold up EDLC RESET while the board is configured
  631.     mov    al,RS_RESET
  632.     loadport
  633.     setport    EDLC_RESET
  634.     out    dx,al
  635.  
  636.     ; Hardware reset of Interlan Board
  637.     mov    al,0
  638.     loadport
  639.     setport    IE_RESET
  640.     out    dx,al
  641.  
  642.     call    set_recv_isr
  643.  
  644.     popf        ; Shouldn't be any interrupts from here on out
  645.  
  646.     mov    al,XMD_LBC
  647.     loadport
  648.     setport    EDLC_XMODE
  649.     out    dx,al
  650.  
  651. ;Determine the processor type.  The 8088 and 8086 will actually shift ax
  652. ;over by 33 bits, while the 80[123]86 use a shift count mod 32.
  653.     mov    cl,33
  654.     mov    ax,0ffffh
  655.     shl    ax,cl
  656.     jz    not_186
  657.     mov    is_186,1
  658.     mov    dx,offset using_186_msg
  659.     mov    ah,9
  660.     int    21h
  661. not_186:
  662.  
  663.     push    ds
  664.     pop    es
  665.     mov    di,offset our_address
  666.     mov    cx,EADDR_LEN+3        ;get three extra signature bytes.
  667.     call    get_address
  668.     mov    si,offset our_address
  669.     mov    cx,EADDR_LEN
  670.     call    set_address
  671.  
  672. ;See if there really is a ni5010 there.
  673.     cmp    our_address+EADDR_LEN+0,0
  674.     jne    no_ni5010
  675.     cmp    our_address+EADDR_LEN+1,055h
  676.     jne    no_ni5010
  677.     cmp    our_address+EADDR_LEN+2,0aah
  678.     jne    no_ni5010
  679.  
  680.     mov    cx,EADDR_LEN
  681.     mov    di,offset ether_bdcst
  682.     repe    cmpsb
  683.     jne    have_ni5010        ;not broadcast address -- must be real.
  684. no_ni5010:
  685.     jmp    no_ni5010_error        ;not there -- no ni5010.
  686. have_ni5010:
  687.  
  688.     ; Only enable Transmit-type interrupts while Transmitting
  689.     mov    al,0
  690.     loadport
  691.     setport    EDLC_XMASK
  692.     out    dx,al
  693.  
  694.     ; Establish generic Transmit mode
  695.     mov    al,XMD_IG_PAR or XMD_T_MODE or XMD_LBC
  696.     setport    EDLC_XMODE
  697.     out    dx,al
  698.  
  699.     ; Clear any startup related Transmit interrupts
  700.     mov    al,0FFh
  701.     setport    EDLC_XCLR
  702.     out    dx,al
  703.  
  704.     ; Establish generic Receive mode
  705.     mov    al,RMD_BROADCAST
  706.     setport    EDLC_RMODE
  707.     out    dx,al
  708.  
  709.     ; Reset Rcv State to allow receives
  710.     call    il_rcv_reset
  711.  
  712.     ; Finally un-reset the EDLC
  713.     mov    al,0
  714.     loadport
  715.     setport    EDLC_RESET
  716.     out    dx,al
  717.  
  718.     mov    dx,offset end_resident
  719.     clc
  720.     ret
  721.  
  722.  
  723. code    ends
  724.  
  725.     end
  726.