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

  1. version    equ    0
  2.  
  3. ;   This program is free software; you can redistribute it and/or modify
  4. ;   it under the terms of the GNU General Public License as published by
  5. ;   the Free Software Foundation, version 1.
  6. ;
  7. ;   This program is distributed in the hope that it will be useful,
  8. ;   but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. ;   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  10. ;   GNU General Public License for more details.
  11. ;
  12. ;   You should have received a copy of the GNU General Public License
  13. ;   along with this program; if not, write to the Free Software
  14. ;   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  15.  
  16.     include    defs.asm
  17.  
  18. ;        ntinet.mac
  19. ;
  20. ;  macros used for calling c routines.
  21. ;
  22. pusharg    macro    seg, off
  23.     ifnb    <seg>
  24.       push    seg
  25.     $$cnt = $$cnt+2
  26.     endif
  27.     ifnb    <off>
  28.       push    off
  29.     $$cnt = $$cnt+2
  30.     endif
  31.     endm
  32.  
  33.  
  34. ccall    macro    rtn, p1, p2, p3, p4, p5
  35. $$cnt = 0
  36.     ifnb    <p5>
  37.       pusharg    p5
  38.     endif
  39.     ifnb    <p4>
  40.       pusharg    p4
  41.     endif
  42.     ifnb    <p3>
  43.       pusharg    p3
  44.     endif
  45.     ifnb    <p2>
  46.       pusharg    p2
  47.     endif
  48.     ifnb    <p1>
  49.       pusharg    p1
  50.     endif
  51.       call    rtn
  52.     if $$cnt
  53.       add    sp,$$cnt
  54.     endif
  55.     endm
  56.  
  57. save    macro    regs
  58.       irp    arg,<regs>
  59.       push    arg
  60.       endm
  61.     endm
  62.     
  63. restore    macro    regs
  64.       irp    arg,<regs>
  65.       pop    arg
  66.       endm
  67.     endm
  68.  
  69. ;
  70.  
  71.     include    lance.inc
  72.  
  73. ;
  74. ;  GLBL.INC
  75. ;
  76. ;  global equates for lance dumb board
  77. ;
  78. pt_status    equ    0        ;read status port
  79. pt_clrclk    equ    0        ;write to clear clock interrupt
  80. pt_etaddr    equ    1        ;read ether address rom offset
  81. pt_resetl    equ    1        ;write to reset lance
  82. pt_ldata    equ    2        ;lance data port 2,3
  83. pt_laddr    equ    4        ;lance address port 4,5
  84.  
  85. st_mask        equ    0ch        ;00001100B for (is1 is0)
  86.  
  87. ;int selects
  88. irqn_10    equ    00h            ;(is0 is1) = (0 0)
  89. irqn_11    equ    04h            ;(0 1)
  90. irqn_12    equ    08h            ;(1 0)
  91. irqn_15    equ    0ch            ;(1 1)
  92.  
  93. IRQ10        equ    10
  94.  
  95. ; status port bits
  96.  
  97. NET_INT    equ    01h        ;bit for net interrupt status
  98. CLK_INT    equ    02h        ;bit for clock interrupt status
  99. IPL    equ    04h        ;ipl bit
  100. HILO    equ    08h        ;ram at 0000, or ram at 8000
  101. MINT    equ    net_int+clk_int        ;interrupt mask
  102. ADDR    equ    0F0h        ;mask for dual port segment
  103.  
  104.  
  105. DPLEN    equ    8000h        ;length of dual port ram
  106. BUFSIZE equ    1518        ;should change to GIANT + 4(CRC)
  107.  
  108. ; Packet sizes = source(6) + destination(6) + type (2) + I field. (803.2 spec)
  109. ;
  110.  
  111. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  112. ;
  113. ;Following is the list of variables that need to be adjusted if the dp
  114. ;usage is changed:
  115. ;
  116. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  117.  
  118. XAREA        equ    5F78H        ;start of transmit descriptors
  119. RAREA        equ    0018h        ;start of receive descriptors
  120.  
  121. NUMTDESC    equ    4        ;number of transmit descriptors
  122. NUMRDESC    equ    16         ;number of receive descriptors
  123.  
  124. TBAREA    equ    XAREA+(NUMTDESC*tdesclen)    ;xmit buf pool
  125. RBAREA    equ    RAREA+(NUMRDESC*rdesclen)       ;rcv buffer pool
  126.  
  127. ;our data segment is a constant distance from the es!
  128. OUROFFSET    equ    TBAREA + NUMTDESC*BUFSIZE
  129.  
  130. RLEN    equ    RLEN16            ;lance mask for rcv-descriptors
  131. TLEN    equ    TLEN4            ;lance mask for snd-descriptors
  132.  
  133. ;the total dp size reserved for lance use
  134. LANCE_SZ equ    INITBLK_SZ+ NUMRDESC*(RDESCLEN+BUFSIZE)+ NUMTDESC*(TDESCLEN+BUFSIZE)
  135.  
  136. ;the end of RAERA
  137. OUTOF_BOUND    equ     RBAREA        ;98; for wrap up checking of r-descs
  138.  
  139.  
  140. code    segment    word public
  141.     assume    cs:code, ds:code
  142.  
  143.     extrn    maskint:near
  144.     extrn    set_recv_isr: near
  145.  
  146.  
  147.     public    int_no, io_addr, base_addr
  148. int_no        db    3,0,0,0        ; interrupt number. 
  149. io_addr        dw    0338h,0        ; I/O address for card (jumpers)
  150. base_addr    dw      0d000h,0    ; base segment for board (jumper set)
  151.  
  152. int_no_name    db    "Interrupt number ",'$'
  153. io_addr_name    db    "I/O port ",'$'
  154. base_addr_name    db    "Memory address ",'$'
  155.  
  156. nosdesc_msg    db    "no send descriptor.",CR,LF,'$'
  157. chperr_msg    db    "chip doesn't want to finish init",CR,LF,'$'
  158. porterr_msg    db    "wrong port #",CR,LF,'$'
  159. hwerr_msg    db    "hardware error",CR,LF,'$'
  160. initerr_msg    db     "can't init lance chip",CR,LF,'$'
  161. good_msg    db    "Lance initialized successfully.",CR,LF,'$'
  162. reset_msg    db    "Can't reset the interface",CR,LF,'$'
  163. interr_msg    db    "IRQ# parameter wrong.",CR,LF,'$'
  164.  
  165.     public    driver_class, driver_type, driver_name, driver_function, parameter_list
  166. driver_class    db    BLUEBOOK, IEEE8023, 0        ;from the packet spec
  167. driver_type    db    100        ;--mz?
  168. driver_name    db    'nti',0,'$'    ;name of the driver.
  169. driver_function    db    2
  170. parameter_list    label    byte
  171.     db    1    ;major rev of packet driver
  172.     db    9    ;minor rev of packet driver
  173.     db    14    ;length of parameter list
  174.     db    EADDR_LEN    ;length of MAC-layer address
  175.     dw    GIANT    ;MTU, including MAC headers
  176.     dw    MAX_MULTICAST * EADDR_LEN    ;buffer size of multicast addrs
  177.     dw    0    ;(# of back-to-back MTU rcvs) - 1
  178.     dw    0    ;(# of successive xmits) - 1
  179. int_num    dw    0    ;Interrupt # to hook for post-EOI
  180.             ;processing, 0 == none,
  181.  
  182.     public    rcv_modes
  183. rcv_modes    dw    4        ;number of receive modes in our table.
  184.         dw    0,0,0,rcv_mode_3
  185.  
  186.  
  187.     ;begin importing data
  188.     public    UNITID, sdesc_cnt, rdesc_cnt, actsdesc, actrdesc
  189. UNITID    db    6 dup (0)        ;current ether address of the interface
  190. sdesc_cnt    dw    2        ;
  191. rdesc_cnt    dw    8
  192. actsdesc    dw    0
  193. actrdesc    dw    0
  194.  
  195.  
  196.     public bad_command_intercept
  197. bad_command_intercept:
  198. ;called with ah=command, unknown to the skeleton.
  199. ;exit with nc if okay, cy, dh=error if not.
  200.     mov    dh,BAD_COMMAND
  201.     stc
  202.     ret
  203.  
  204.  
  205. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  206. ; send_pkt:
  207. ;
  208. ;enter with ds:si -> packet, cx = packet length.
  209. ;exit with nc if ok, or else cy if error, dh set to error number.
  210. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  211.  
  212.     public    as_send_pkt
  213. ; The Asynchronous Transmit Packet routine.
  214. ; Enter with es:di -> i/o control block, ds:si -> packet, cx = packet length,
  215. ;   interrupts possibly enabled.
  216. ; Exit with nc if ok, or else cy if error, dh set to error number.
  217. ;   es:di and interrupt enable flag preserved on exit.
  218. as_send_pkt:
  219.     ret
  220.  
  221.     public    drop_pkt
  222. ; Drop a packet from the queue.
  223. ; Enter with es:di -> iocb.
  224. drop_pkt:
  225.     assume    ds:nothing
  226.     ret
  227.  
  228.     public    xmit
  229. ; Process a transmit interrupt with the least possible latency to achieve
  230. ;   back-to-back packet transmissions.
  231. ; May only use ax and dx.
  232. xmit:
  233.     assume    ds:nothing
  234.     ret
  235.  
  236.  
  237.     public    send_pkt
  238. send_pkt:
  239.     assume    ds:nothing
  240.     push    es
  241.     mov    es,cs:[base_addr]
  242.  
  243.     push    ds
  244.     movseg    ds,cs            ;set out ds-->cs
  245.  
  246.     mov    dx,cx            ;a copy of length
  247.  
  248.     cmp    dx,GIANT        ; Is this packet too large?
  249.     ja    send_pkt_toobig
  250.  
  251.     cmp    dx,RUNT            ; minimum length for Ether
  252.     jnb    oklen
  253.     mov    dx,RUNT            ; make sure size at least RUNT
  254. oklen:
  255.     mov    bx,[actsdesc]        ;get pointer to active snd desc
  256.     mov    cx,0            ;set up count down parameters
  257. td10:
  258.     test    es:td_stat[bx],t_own    ;have empty buffer?
  259.     jz    dox0            ;yes, then send message
  260.     loop    td10            ;otherwise, wait for it
  261.     mov    dx,offset nosdesc_msg
  262.     ccall    _dispMSG,dx
  263.     mov    dh,CANT_SEND
  264.     stc                ;error ret
  265.     pop    ds
  266.     pop    es
  267.     ret
  268.  
  269. dox0:
  270.     pop    ds
  271.     mov    cx,dx            ;get back the real length
  272.     call    fill            ;ds:si - source, es:bx - dest, cx:length
  273.     ;ax has the return code, either 0 or 0ffh
  274.  
  275.     ;is chip functioning?
  276.     cmp    ax,0ffh            ;fatal error happened last time?
  277.     je    td15            ;error!
  278.     clc                ;good ret
  279.     pop es
  280.     ret
  281. td15:
  282.     mov    dh,CANT_SEND
  283.     stc
  284.     pop    es
  285.     ret
  286.  
  287. send_pkt_toobig:
  288.     mov    dh,NO_SPACE
  289.     stc
  290.     pop    ds
  291.     pop    es
  292.     ret
  293.  
  294.     include    movemem.asm
  295.  
  296. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  297. ; fill - proc the xerror  & copy message to xmit buffer
  298. ;
  299. ; entry - es:bx points to free xmit descriptor (dest)
  300. ;      ds:si --> source buf pointer
  301. ;        cx:length of data
  302. ;
  303. ; exit  - xmit buffer (bx) filled
  304. ;      ax = 0: OK; 0ffh: fatal error happened last send
  305. ;      bx changed
  306. ;
  307. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  308.     public    fill
  309. fill:
  310.     assume    ds:nothing
  311.     push    ds                ;save theirs
  312.  
  313.     movseg    ds,cs                ;set ours
  314.  
  315.     call    xmt_errs            ;process previous errors
  316.     cmp    ax,0
  317.     je    success
  318.     pop    ds
  319.     ret                    ;ax == ffh
  320.  
  321. success:    
  322.     ;ds:si - source, es:bx - dest, cx - length
  323.     ;simply send whatever given by the application, assuming the
  324.     ;destination address and everything has been taken care of
  325.  
  326.     pop    ds
  327.     push    cx            ;save it
  328.     mov    di,es:td_addr[bx]    ;get dest buf pointer 
  329.     call    movemem            ;ds:si --> es:di
  330.     pop    cx
  331.     
  332.     push    ds
  333.     movseg    ds,cs
  334.     ;get the sdesc ready and pump the data out
  335.     neg    cx            ;two's compliment
  336.     or    cx,td_bmask        ;set these bits
  337.     mov    es:td_bcnt[bx],cx    ;set in length to descriptor
  338.     mov    ax,0            ;set descriptor status for lance
  339.     or    ax,t_own        ;he now owns it
  340.     or    ax,t_stp        ;start of packet
  341.     or    ax,t_enp        ;end of packet
  342.     mov    es:td_stat[bx],ax    ;give it away        
  343.     mov    ax,l_tdnd+l_inea    ;tell lance we have data
  344.     call    w_csr                ;send it
  345.  
  346.     ;all done, update the actsdesc
  347.     add    bx,tdesclen        ;point at next descriptor
  348.     dec    word ptr[sdesc_cnt]        ;dec counter
  349.     jnz    tfl                ;used all?
  350.     mov    word ptr[sdesc_cnt],NUMTDESC    ;yes start at begining    
  351.     mov    bx,XAREA
  352. tfl:
  353.     mov    [actsdesc],bx        ;set pointer
  354.  
  355.     mov    ax,0            
  356.     pop    ds
  357.     ret                ;good ret
  358.  
  359. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  360. ; xmt_errs:
  361. ;    Check at if the previous send has any errors or not.
  362. ;     entry - es:bx sdesc
  363. ;    exit  - ax:0 - ok; ffh:fatal error
  364. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  365.  
  366.     public    xmt_errs
  367. xmt_errs:
  368.     mov    ax,es:td_tdr[bx]    ;get rest of status
  369.     test    ax,t_more        ;more than one retry needed
  370.     jz    xisr2
  371.     call    count_out_err
  372.     jmp    xisr3
  373. xisr2:
  374.     test    ax,t_one        ;one retry?
  375.     jz    xisr3            ;no
  376.     call    count_out_err
  377. xisr3:
  378.     test    ax,t_lcol        ;late collision
  379.     jz    xisr4            ;no
  380.     call    count_out_err
  381. xisr4:
  382.     test    ax,t_def        ;deferred xmit?
  383.     jz    xisr5
  384.     call    count_out_err
  385. xisr5:
  386.     test    ax,t_lcar        ;loss of carrier
  387.     jz    xisr6
  388.     call    count_out_err
  389. xisr6:
  390.     test    ax,t_uflo        ;silo underflow?
  391.     jz    xisr7    
  392.     jmp    fatal_err
  393. xisr7:    
  394.     test    ax,t_buff        ;buffer error no end
  395.     jz    all_rite        ;last sent all right
  396. fatal_err:
  397.     call    count_out_err
  398.     mov    ax,0ffh            ;fatal error
  399.     ret                ;
  400.  
  401. all_rite:
  402.     mov    ax,0
  403.     ret
  404.  
  405. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  406. ;get_address:
  407. ;    We get the interface address from our internal version UNITID. 
  408. ;    set_address() could change the value of UNITID.
  409. ;
  410. ;enter with es:di -> place to put the address, cx = size of address buffer.
  411. ;exit with nc, cx = actual size of address, or cy if buffer not big enough.
  412. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  413.  
  414.     public    get_address
  415. get_address:
  416.     assume    ds:code
  417.     cmp    cx,EADDR_LEN        ;make sure that we have enough room.
  418.     jb    get_address_2
  419.     mov    cx,EADDR_LEN
  420.     lea    si,UNITID
  421. get_address_1:
  422.     call    movemem
  423.     mov    cx,EADDR_LEN
  424.     clc
  425.     ret
  426. get_address_2:
  427.     stc
  428.     ret
  429.     
  430. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  431. ; set_address:
  432. ;    set current ethernet address in UNITID, also change the init block
  433. ;       
  434. ;enter with ds:si -> Ethernet address, CX = length of address.
  435. ;exit with nc if okay, or cy, dh=error if any errors.
  436. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  437.  
  438.     public    set_address
  439. set_address:
  440.     assume    ds:code
  441.     cmp    cx,EADDR_LEN
  442.     jne    set_address2
  443.  
  444.     push    si                ;save it for later use
  445.     push    cx
  446.  
  447.     mov    di,offset UNITID
  448.     call    movemem
  449.  
  450.     ;should also change the init_block
  451.     mov    es,cs:[base_addr]
  452.     mov    di,offset i_padr
  453.     pop    cx
  454.     pop    si                ;get back the old pointer
  455.     call    movemem
  456.  
  457.     clc
  458.     ret
  459.  
  460. set_address2:
  461.     mov    dh,BAD_ADDRESS
  462.     stc
  463.     ret
  464.  
  465.  
  466.  
  467. rcv_mode_3:
  468. ;receive mode 3 is the only one we support, so we don't have to do anything.
  469.     ret
  470.  
  471.  
  472.     public    set_multicast_list
  473. set_multicast_list:
  474. ;enter with ds:si ->list of multicast addresses, cx = number of addresses.
  475. ;return nc if we set all of them, or cy,dh=error if we didn't.
  476.     mov    dh,NO_MULTICAST
  477.     stc
  478.     ret
  479.  
  480.  
  481.     public    terminate
  482. terminate:
  483.     ret
  484.  
  485.     public    reset_interface
  486. reset_interface:
  487. ;reset the interface.
  488.     assume    ds:code
  489.     call    hardware        ;reset the UNITID
  490.     cmp    al,0
  491.     jne    port_err
  492.  
  493.     cli
  494.  
  495.     call    lance_init        ;init_blk, xmt, rcv
  496.     cmp    ax,0            ;init ok?
  497.     jne    lance_err
  498.     sti
  499.     clc
  500.     ret
  501.  
  502. lance_err:
  503.     mov    dx,offset initerr_msg
  504.     ccall    _dispMSG,dx
  505.     jmp    error
  506.  
  507. port_err:    
  508.     mov    dx,offset reset_msg
  509.     ccall    _dispMSG,dx
  510. error:
  511.     mov    dh,CANT_RESET
  512.     stc
  513.     ret
  514.  
  515. ;called when we want to determine what to do with a received packet.
  516. ;enter with cx = packet length, es:di -> packet type, dl = packet class.
  517.     extrn    recv_find: near
  518.  
  519. ;called after we have copied the packet into the buffer.
  520. ;enter with ds:si ->the packet, cx = length of the packet.
  521.     extrn    recv_copy: near
  522.  
  523.     extrn    count_in_err: near
  524.     extrn    count_out_err: near
  525.  
  526. ;called from the net_isr isr.  All registers have been saved, and ds=cs.
  527. ;Upon exit, the interrupt will be acknowledged.
  528. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  529. ; risr 
  530. ; receive interrupt service routine 
  531. ; exit: es,bx not changed
  532. ; registers: si,ax
  533. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  534.  
  535.     public    risr
  536. risr    proc    near
  537.     assume    ds:code
  538.     save    <es,bx>
  539.     mov    es,cs:[base_addr]
  540. begin:
  541.     mov    si,[actrdesc]        ;active receive descriptor
  542.     mov    ax,es:rd_stat[si]    ;get descriptor status
  543.     test    ax,r_own        ;do we own it?
  544.     jnz    risr_done        ;this one is not filled
  545.  
  546.     call    dp_rcv            ;lance chip has rev'd a new packet
  547.                     ;reserve si 
  548.     ;One rint might indicate multiple recv's, check at the next one
  549.     add    si,SIZE rec_desc_ring        ;point at next descriptor
  550.     cmp    si,OUTOF_BOUND            ;RAREA+(numrxbuf-1)*(SIZE rec_desc_ring) = XAREA
  551.     jl    within
  552.     mov    si,RAREA
  553. within:
  554.     mov    [actrdesc],si            ;set active pointer
  555.     jmp    begin
  556. risr_done:
  557.     restore <bx,es>
  558.     ret
  559. risr    endp
  560.  
  561. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  562. ;  dp_rcv:
  563. ;    lance chip has one buffer filled, process it.
  564. ;    enter: es:si = actrdesc
  565. ;    exit:  actrdesc updated to next desc, si unchanged
  566. ;    registers: di,ax,bx
  567. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  568.  
  569.     public    dp_rcv
  570. dp_rcv     proc     near
  571.     push    si                ;save the old actdesc
  572.     push    es            ;gonna be changed in recv_find()
  573.  
  574.     mov    ax,es:rd_stat[si]    ;is it errored packet?
  575.     test    ax,r_err        ;
  576.     jz    noerr                 ;no err
  577.     call     rcverror        ;handle the err 
  578.     jmp    clrup
  579.  
  580. noerr:
  581.     mov     di,es:rd_addr[si]    ;received packet pointer es:di
  582.     add    di,EADDR_LEN + EADDR_LEN;stript off the two ether addresses
  583.                     ; & get to the packet type field
  584.     mov    cx,es:rd_mcnt[si]    ;everything (icl'g addresses)
  585.     and    cx,mcnt_mask        ;mask out the reserved bits
  586.  
  587.     push    ds            ;entry value saved
  588.  
  589.     push    es            ;es:di --> rcv'd data (icl'ing type)
  590.     push    di
  591.  
  592.     mov    dl, BLUEBOOK        ;assume bluebook Ethernet.
  593.     mov    ax, es:[di]
  594.     xchg    ah, al
  595.     cmp     ax, 1500
  596.     ja    BlueBookPacket
  597.     inc    di            ;set di to 802.2 header
  598.     inc    di
  599.     mov    dl, IEEE8023
  600. BlueBookPacket:
  601.  
  602.     call    recv_find        ;ask for buffer from application es:di
  603.     mov    ax,es            ;is this pointer null?
  604.     or    ax,di
  605.     jz    too_bad            ;yes - just free the frame.
  606.     pop    si            ;put rcv'd data in ds:si, di->si
  607.     sub    si,EADDR_LEN + EADDR_LEN;we hand everything to the client
  608.     pop    ds            ;es->ds
  609.  
  610.     push    cx
  611.     push    es            ;for recv_copy(), es:di is user buf
  612.     push    di            
  613.  
  614.     call    movemem            ;do the copy (including ether header)
  615.  
  616.     pop    si            ;di->si, es->ds
  617.     pop    ds            ;ds:si --> user buffer now
  618.     pop    cx            ;get back the length
  619.     call    recv_copy
  620.  
  621.     pop    ds            ;original ds restored
  622.     jmp    clrup
  623.  
  624. too_bad:
  625.     pop    di
  626.     pop    es
  627.     pop    ds
  628. clrup:
  629.     ;either a bad or a good packet, we're done with it now
  630.     pop    es            ;good old dp seg
  631.     pop    si
  632.     mov    es:rd_stat[si],r_own    ;desc reusable now
  633.     ret
  634. dp_rcv    endp
  635.  
  636. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  637. ; eisr
  638. ; for lance error service routine
  639. ;
  640. ; entry - bx has status
  641. ; exit  - bx unchanged, ax,cx changed
  642. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  643.  
  644.     public    eisr
  645. eisr    proc    near
  646.     test    bx,l_babl        ;transmission timeout?
  647.     jz    eisr1            ;no
  648.     call    count_out_err
  649. eisr1:
  650.     test    bx,l_cerr    
  651.     jz    eisr2            ;no
  652.     call    count_out_err
  653. eisr2:
  654.     test    bx,l_miss        ;missed packet?
  655.     jz    eisr3
  656.     call    count_out_err
  657. eisr3:
  658.     test    bx,l_merr        ;bus timeout?
  659.     jz    eisr4            ;no
  660.     call    count_out_err        ;this is a fatal error
  661. eisr4:
  662.     ret
  663. eisr    endp
  664.  
  665. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  666. ; rcverror:
  667. ;    entry    ax has rd_stat
  668. ;
  669. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  670.  
  671.     public    rcverror
  672. rcverror    proc    near
  673.  
  674.     test    ax,r_fram        ;framing error?
  675.     jz    rerr0
  676.     call     count_in_err
  677. rerr0:
  678.     test    ax,r_crc        ;crc error?
  679.     jz    rerr1
  680.     call     count_in_err
  681. rerr1:
  682.     test    ax,r_oflo          ;silo overflow?
  683.     jz    rerr2
  684.     call     count_in_err
  685. rerr2:
  686.     test    ax,r_buff        ;buffer error?
  687.     jz    rerr3
  688.     call     count_in_err
  689. rerr3:
  690.     ret
  691. rcverror    endp
  692.  
  693. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  694. ; init_csr:
  695. ;
  696. ; initialize lance registers csr1, csr2, csr3
  697. ;  entry - csr0 stop bit must have been set
  698. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  699.  
  700.     public    init_csr
  701. init_csr    proc    near
  702.     mov    al,csr1            ;set rap to csr1
  703.     call    set_rap
  704.     mov    ax,i_mode        ;init block starts at 0
  705.     call    w_csr
  706.  
  707.     mov    al,csr2            ;set rap to csr2
  708.     call    set_rap
  709.     mov    ax,0            ;init block upper 8 bits are 0
  710.     call    w_csr
  711.  
  712.     mov    al,csr3            ;set rap for csr3
  713.     call    set_rap
  714.     mov    ax,bus_master        ;bswp,acon,bcon
  715.     call    w_csr
  716.  
  717.     mov    al,csr0            ;leave rap at csr0
  718.     call    set_rap
  719.     ret
  720. init_csr    endp    
  721.  
  722. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  723. ; r_csr:
  724. ;
  725. ; read lance csr already selected into ax
  726. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  727.  
  728.     public    r_csr
  729. r_csr    proc    near
  730.     push    dx
  731.     mov    dx,io_addr        ;now data port
  732.     add    dx,pt_ldata
  733.     in    ax,dx
  734.     pop    dx
  735.     ret
  736. r_csr    endp
  737. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  738. ; r_csr0
  739. ;
  740. ; read lance csr0
  741. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  742.  
  743.     public    r_csr0
  744. r_csr0    proc    near
  745.     push    dx
  746.     mov    al,csr0            ;set rap to csr1
  747.     call    set_rap
  748.     mov    dx,io_addr        ;now data port
  749.     add    dx,pt_ldata
  750.     in    ax,dx
  751.     pop    dx
  752.     ret
  753. r_csr0    endp
  754.  
  755. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  756. ; set_initblk:  
  757. ;
  758. ; set up lance initialization block in the dual port  
  759. ;
  760. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;                       ;
  761.  
  762.     public    set_initblk,si11
  763. set_initblk  proc    near
  764.     push    es
  765.     mov    es,cs:[base_addr]
  766.  
  767.     mov    ax,run_mode        ;mode
  768.     mov    es:[i_mode],ax        ;(es = dpseg);1st word in the dp
  769.     lea    si,UNITID        ;set in physical address
  770.     mov    di,i_padr        ; from the board
  771. si11:
  772.     mov    cx,6
  773.     rep    movsb
  774. ;
  775. ;forget about the logical address filter for now --mz??
  776. ;
  777.     mov    ax,RAREA        ;set in pointer to 1ST receive desc.
  778.     mov    es:[i_rdra],ax        ;set lo addr (0-15)
  779.     mov    ah,rlen            ;set in rlen parameter & hi addr (00s)
  780.     mov    al,0
  781.     mov    es:[i_rlen],ax        ;4 rcv descriptors
  782.     mov    ax,XAREA        ;pointer to xmit descriptors
  783.     mov    es:[i_tdra],ax
  784.     mov    ah,tlen            ;set in tlen parameter 1 = 2
  785.     mov    al,0
  786.     mov     es:[i_tlen],ax
  787.     pop    es
  788.     ret
  789. set_initblk    endp
  790.  
  791. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  792. ; set up transmit message descriptors
  793. ;
  794. ; entry - cx has number of descriptors and buffers to set up
  795. ;         bx has pointer of start of descriptors
  796. ;         di has pointer to start of buffer area
  797. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  798.  
  799.     public    su_tmd
  800. su_tmd    proc    near
  801.     push    es
  802.     mov    es,cs:[base_addr]
  803.  
  804.     ;first set the relative parameters
  805.     mov    [sdesc_cnt],cx        ;set in count
  806.     mov    [actsdesc],bx
  807.  
  808. su_t0:
  809.     mov    es:td_addr[bx],di    ;set in pointer
  810.     mov    ax,BUFSIZE        ;total size
  811.     neg    ax            ;two's compliment
  812.     or    ax,td_bmask        ;set these bits
  813.     mov    es:td_bcnt[bx],ax    ;set in length to descriptor
  814.     mov    ax,0            ;set descriptor status for lance
  815.     or    ax,t_stp        ;start of packet
  816.     or    ax,t_enp        ;end of packet
  817.     mov    es:td_stat[bx],ax    ;give it away        
  818.     mov    es:td_tdr[bx],0
  819.     add    bx,tdesclen        ;point at next descriptor
  820.     add    di,BUFSIZE        ;and next buffer
  821.     loop    su_t0            ;do all
  822.     pop    es
  823.     ret
  824. su_tmd    endp
  825.  
  826. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  827. ; set up receive message descriptors
  828. ;
  829. ; entry - cx has number of descriptors and buffers to set up
  830. ;         bx has pointer of start of descriptors
  831. ;         di has pointer to start of buffer area
  832. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  833.  
  834.     public    su_rmd
  835. su_rmd    proc    near
  836.     push    es
  837.     mov    es,cs:[base_addr]
  838.  
  839.     mov    [actrdesc],bx          ;pointer to active descriptor
  840.     mov    [rdesc_cnt],cx        ;descriptor count
  841. su_r0:
  842.     mov    es:rd_addr[bx],di       ;set in pointer to pointer
  843.     mov    ax,r_own        ;set up descriptor status 
  844.     mov    es:rd_stat[bx],ax
  845.     xor    ax,ax            ;zero out count
  846.     mov    es:rd_mcnt[bx],ax
  847.     mov    ax,BUFSIZE        ;set in length of buffer
  848.     neg    ax            ;must be two's compliment
  849.     or    ax,rd_mask        ;need these bits set
  850.     mov    es:rd_bcnt[bx],ax
  851.     add    bx,rdesclen        ;point at next descriptor
  852.     add    di,BUFSIZE        ;and next buffer
  853.     loop    su_r0            ;do all
  854.     
  855.     pop    es
  856.     ret
  857. su_rmd    endp
  858.  
  859. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  860. ; lance_reset:
  861. ;
  862. ;     reset lance chip; select csr0 and set the stop bit
  863. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;        
  864.  
  865.     public    lance_reset
  866. lance_reset    proc    near
  867.     mov    dx,io_addr        ;pop the reset line
  868.     add    dx,pt_resetl    
  869.     out    dx,al
  870.     mov    al,csr0            ;set lance address port to csr0
  871.     call    set_rap
  872.     mov    ax,l_stop         ;and set stop bit
  873.     call    w_csr
  874.     ret
  875. lance_reset    endp
  876.  
  877. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  878. ; w_csr:
  879. ;
  880. ; output ax to lance csr already selected
  881. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  882.  
  883.     public    w_csr
  884. w_csr    proc    near
  885.     push    dx
  886.     mov    dx,io_addr        ;now data port
  887.     add    dx,pt_ldata
  888.     out    dx,ax
  889.     pop    dx
  890.     ret    
  891. w_csr    endp
  892.  
  893. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  894. ; set_rap:
  895. ;
  896. ; set lance address port to register in al
  897. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  898.  
  899.     public    set_rap
  900. set_rap    proc    near
  901.     push    dx
  902.     mov    dx,io_addr        ;get base address
  903.     add    dx,pt_laddr                ;point at lance address port
  904.     xor    ah,ah            ;point at csr
  905.     out    dx,ax
  906.     pop    dx
  907.     ret
  908. set_rap        endp
  909.  
  910. ; hardwre() and lance_init() are TSR just for the 
  911. ; support of reset_interface();
  912.  
  913. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  914. ; hardware: 
  915. ;    verify the port #;
  916. ;    set ethernet addr in _UNITID
  917. ;
  918. ; exit:
  919. ;    [_UNITID] = board ethernet address
  920. ;       al = 0 (ok)
  921. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  922.  
  923.     public    hardware
  924. hardware    proc    near
  925.     ;verify the port #
  926.     mov    dx,io_addr
  927.     call    chkaddr
  928.     cmp    al,0            ;ok?
  929.     jz    hw1            ;yes, use #1
  930.     mov    ax,offset porterr_msg
  931.     ccall    _dispMSG,ax
  932.     jmp    hw_error
  933.  
  934. hw1:
  935.     ;ok, now zero the ram out so that we can use it
  936.     mov    es,cs:[base_addr]
  937.     call     zeroram
  938.  
  939.     ;get ether address
  940.     mov    cx,6            ;get the ethernet address
  941.     add    dx,pt_etaddr
  942.     mov    bx,offset UNITID    ;to here
  943. hw3:
  944.     in    al,dx
  945.     mov    byte ptr[bx],al
  946.     inc    bx
  947.     loop    hw3
  948.  
  949.     ;validate int_no (only support 10,11,12,15)
  950.     
  951.     mov    bl,IRQ10        ;assume it's irq10
  952.     mov    dx,io_addr        ;port base
  953.     add     dx,pt_status        ;status port
  954.     in    al,dx            ;get status
  955.     and    al,st_mask        ;get the 2 bits
  956.     cmp    al,irqn_10        ;(IS0 IS1)=(0 0) selects irq10
  957.     je    alset
  958.     inc    bl            ;try irq11
  959.     cmp    al,irqn_11
  960.     je    alset
  961.     inc    bl            ;try irq12
  962.     cmp    al,irqn_12
  963.     je    alset
  964.     mov    bl,15            ;try irq15
  965.     cmp    al,irqn_15
  966.     jne    hw_error
  967.  
  968. alset:
  969.     ;did we get the right int_no in bl?
  970.     cmp    bl,int_no
  971.         jmp     ok                      ; #### temp patch, BKC
  972. ;    je    ok
  973.     ;otherwise, error
  974.     mov    ax,offset interr_msg
  975.     ccall    _dispMSG,ax
  976. hw_error:
  977.     mov    al,0ffh
  978.     ret
  979. ok:
  980.     mov    al,0            ;good return code
  981.     ret
  982. hardware    endp
  983.  
  984. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  985. ; chkaddr: check if we are using the right i/o port
  986. ;          this is done by reading the port status and comparing
  987. ;       with cs - 800h
  988. ;
  989. ; entry:     io_addr == i/o port #
  990. ; exit:     ah -- dual port segment
  991. ;        al -- 00h (succ) or ffh (error)
  992. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  993.  
  994.     public    chkaddr
  995. chkaddr    proc    near
  996.     push    dx
  997.  
  998.     mov    dx,io_addr
  999.     in    al,dx            ;read in status byte
  1000.     and    al,addr            ;get dp seg, addr = 0f0h
  1001.     mov    ah,al            ;save
  1002.  
  1003.     mov    dx,base_addr
  1004.     and    dh,addr
  1005.     cmp    al,dh
  1006.     je    chk2
  1007.     mov    al,0ffh            ;error
  1008.     pop    dx
  1009.     ret
  1010. chk2:
  1011.     mov    al,0            ;ok
  1012.     pop    dx
  1013.     ret
  1014. chkaddr    endp
  1015.  
  1016. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  1017. ; zeroram - zero dual port ram
  1018. ;    seg in [dpseg]
  1019. ;    registers: di,cx,al
  1020. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  1021.  
  1022.     public    zeroram
  1023. zeroram    proc    near
  1024.     cld                ;auto increment
  1025. zram1:    
  1026.     mov    di,0            ;start at 0;dpseg:di
  1027.     mov    cx,dplen        ;dual port length
  1028.     mov    al,0            ;data to go
  1029.     rep    stosb            ;zero em all
  1030.     ret
  1031. zeroram    endp
  1032.  
  1033. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  1034. ; lance_init:
  1035. ;
  1036. ; init lance chip; first setup init_blk, r & s descriptors in dp
  1037. ;           then set the chip to go.
  1038. ;    exit: ax = 1: error; 0 OK. 
  1039. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  1040.  
  1041.     public    lance_init, il0, il1
  1042. lance_init    proc    near
  1043.     call    set_initblk        ;set up lance initialization block
  1044.  
  1045.     ;set up transmit descriptors & buffers
  1046.     mov    cx,NUMTDESC        ;get no. of transmit blocks to build
  1047.     mov    bx,XAREA        ;point at descriptor memory pool
  1048.     mov    di,TBAREA        ;and buffer pool
  1049.     call    su_tmd            ;set up transmit descriptors
  1050.  
  1051.     ;set up receive descriptors & buffers
  1052.     mov    cx,NUMRDESC        ;set up receive descriptors
  1053.     mov    bx,RAREA        ;descriptor area
  1054.     mov    di,RBAREA        ;buffer area
  1055.     call    su_rmd            ;set up receive descriptors
  1056.  
  1057.     call    lance_reset        ;ensure reset
  1058.     call    init_csr        ;initialize lance registers
  1059.                     ;also set rap to csr0 with stop set
  1060.     ;now start the lance initialization action
  1061.     CLI
  1062.     mov    ax,l_init+l_strt    ;write init & start to csr0
  1063.     call    w_csr
  1064.  
  1065.     ;rap = csr0 now, let's check at csr0
  1066.        mov    cx,0
  1067.     dec    cx
  1068. il0:
  1069.     call    r_csr            ;get lance status register
  1070.     test    ax,l_idon        ;init done set?
  1071.     jnz    il1
  1072.     loop    il0
  1073.     ;sth wrong with the chip, can't init
  1074.     mov    ax,offset chperr_msg
  1075.     ccall    _dispMSG,ax
  1076.     mov    ax,1            ;error return
  1077.     ret
  1078. il1:
  1079.     mov    ax,l_idon+l_inea    ;this drives /intr pin to low
  1080.     call    w_csr            ;enable network ints
  1081.     STI
  1082.     mov    ax,0            ;good return
  1083.     ret
  1084. lance_init    endp
  1085.  
  1086. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  1087. ;  tickscreen
  1088. ;
  1089. ;  For debug this routine can be called to tick over the screen at the 
  1090. ;  specified location.
  1091. ;
  1092. ;    c callable:    tickscreen(loc);
  1093. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  1094.  
  1095.     public    _tickscreen
  1096. _tickscreen    proc near
  1097.     push    bp
  1098.     mov    bp,sp
  1099.     save    <ax,bx,ds>
  1100.     mov    bx,04[bp]        ;get screen position
  1101.     add    bx,bx            ;*2
  1102. IFDEF COLOR
  1103.     mov    ax,0b800h
  1104. ELSE
  1105.     mov    ax,0b000h
  1106. ENDIF
  1107.     mov    ds,ax
  1108.     inc    byte ptr [bx]            ;tick it
  1109.     restore    <ds,bx,ax>
  1110.     pop    bp
  1111.     ret
  1112. _tickscreen    endp
  1113.  
  1114. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  1115. ; _dispMSG:
  1116. ;    c call: dispMSG(&msg);
  1117. ;    put the '$' terminated message to screen
  1118. ;    entry: dx - point to the message
  1119. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  1120.  
  1121.     public    _dispMSG
  1122. _dispMSG proc near
  1123.     push    bp
  1124.     mov    bp,sp
  1125.     push    dx
  1126.     mov    dx,4[bp]
  1127.  
  1128.     push    ax
  1129.     mov    ah,9
  1130.     int    21h
  1131.     pop    ax
  1132.  
  1133.     pop    dx
  1134.     pop    bp
  1135.     ret
  1136. _dispMSG endp
  1137.  
  1138.  
  1139.     public    recv
  1140. recv:
  1141. ;called from the recv isr.  All registers have been saved, and ds=cs.
  1142. ;Upon exit, the interrupt will be acknowledged.
  1143.     assume    ds:code
  1144.  
  1145. recv_0:
  1146.     mov    dx,io_addr        ;get the iobase
  1147.     add    dx,pt_status        ;the read status port
  1148.     in    al,dx            ;get board status
  1149.  
  1150.     test    al,clk_int        ;look for clock interrupt
  1151.     jz    ni10            ;no clock int
  1152.     mov    dx,base_addr
  1153.     add    dx,pt_clrclk        ;reset the ckock
  1154.     out     dx,al
  1155. ni10:
  1156.     test    al,net_int        ;network int bit cleared?
  1157.     jnz    nisr5            ;look for 0 here, set means none
  1158.  
  1159.     call    r_csr            ;get lance status register -- in ax
  1160.     mov    bx,ax
  1161.     and    ax,l_mask         ;clear out ints and mask any more
  1162.     call    w_csr
  1163.  
  1164.     test    bx,l_err        ;check for errors first
  1165.     jz    nisr2            ;no error
  1166.     call    eisr
  1167. nisr2:
  1168.     test    bx,l_rint        ;test for receive active
  1169.     jz    nisr6            ;no r_int
  1170.     call    risr
  1171. nisr6:
  1172.     mov     ax,l_inea        ;re-enable the int
  1173.     call    w_csr
  1174.     jmp    recv_0            ;check again for ints
  1175. nisr5:
  1176.     ret
  1177.  
  1178.  
  1179.     public    recv_exiting
  1180. recv_exiting:
  1181. ;called from the recv isr after interrupts have been acknowledged.
  1182. ;Only ds and ax have been saved.
  1183.     assume    ds:nothing
  1184.     ret
  1185.  
  1186.  
  1187.     public    timer_isr
  1188. timer_isr:
  1189. ;if the first instruction is an iret, then the timer is not hooked
  1190.     iret
  1191.  
  1192. ;any code after this will not be kept.  Buffers used by the program, if any,
  1193. ;are allocated from the memory between end_resident and end_free_mem.
  1194.     public end_resident,end_free_mem
  1195. end_resident    label    byte
  1196. end_free_mem    label    byte
  1197.  
  1198.     public    usage_msg
  1199. usage_msg    db    "usage: nti16 [options] <packet_int_no> <irq_no> <port_no> <base_addr>",CR,LF,'$'
  1200.  
  1201.     public    copyright_msg
  1202. copyright_msg    db    "Packet driver for nti network device, version ",'0'+(majver / 10),'0'+(majver mod 10),".",'0'+version,CR,LF
  1203.         db    "Copyright 1990, Michael Zheng",CR,LF,'$'
  1204.  
  1205.  
  1206. ;enter with si -> argument string, di -> wword to store.
  1207. ;if there is no number, don't change the number.
  1208.     extrn    get_number: near
  1209.  
  1210. ;enter with dx -> name of word, di -> dword to print.
  1211.     extrn    print_number: near
  1212.  
  1213.     public    parse_args
  1214. parse_args:
  1215.     mov    di,offset int_no
  1216.     call    get_number
  1217.     mov    di,offset io_addr
  1218.     call    get_number
  1219.     mov    di,offset base_addr
  1220.     call    get_number
  1221.     ret
  1222.  
  1223. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  1224. ; etopen:
  1225. ;    initialize the interface in order to function
  1226. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  1227.  
  1228.     public    etopen
  1229. etopen:
  1230.  
  1231.  
  1232.     call     hardware        ;decide port #; _UNITID; zeroram
  1233.                     ;and 16-bit board specific:
  1234.                     ;decide the int_no validity --mz!!
  1235.     cmp    al,0
  1236.     jz    beg0            ;ok
  1237.     mov    ax,offset hwerr_msg    ;error return
  1238.     ccall    _dispMSG,ax
  1239.     mov    ax, 4c00H
  1240.     int    21h            ;terminate it
  1241. beg0:
  1242.  
  1243.     mov    al,int_no
  1244.     call    maskint
  1245.     call    lance_init        ;init the lance chip
  1246.     cmp    ax,1            ;init error?
  1247.     jne    good            ;ok
  1248.  
  1249.     mov    ax,offset initerr_msg    ;can't init message
  1250.     ccall    _dispMSG,ax
  1251.     stc    
  1252.     ret
  1253.  
  1254. good:
  1255.     call    set_recv_isr
  1256.  
  1257.     mov    al, int_no        ; Get board's interrupt vector
  1258.     add    al, 8
  1259.     cmp    al, 8+8            ; Is it a slave 8259 interrupt?
  1260.     jb    set_int_num        ; No.
  1261.     add    al, 70h - 8 - 8        ; Map it to the real interrupt.
  1262. set_int_num:
  1263.     xor    ah, ah            ; Clear high byte
  1264.     mov    int_num, ax        ; Set parameter_list int num.
  1265.  
  1266.     mov    ax,offset good_msg
  1267.     ccall    _dispMSG,ax
  1268.  
  1269.     mov    dx,offset end_resident    ;in paragraphs
  1270.     clc
  1271.     ret
  1272.  
  1273.     public    print_parameters
  1274. print_parameters:
  1275. ;echo our command-line parameters
  1276.     mov    di,offset int_no
  1277.     mov    bx,offset int_no_name
  1278.     call    get_number
  1279.     mov    di,offset io_addr
  1280.     mov    bx,offset io_addr_name
  1281.     call    get_number
  1282.     mov    di,offset base_addr
  1283.     mov    bx,offset base_addr_name
  1284.     call    get_number
  1285.     ret
  1286.  
  1287. code    ends
  1288.  
  1289.     end
  1290.