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

  1. version equ     4
  2.  
  3.         include defs.asm        ;SEE ENCLOSED COPYRIGHT MESSAGE
  4. NCB_NOWAIT         equ 80h         ;  Command wait flag
  5.  
  6. NCB_RESET          equ 32h         ;  Reset adapter
  7. NCB_CANCEL         equ 35h         ;  Cancel command
  8. NCB_STATUS         equ 33h         ;  Get NETBIOS intf status
  9. NCB_UNLINK         equ 70h         ;  Unlink   (RPL)
  10. NCB_ADDNAME        equ 30h         ;  Add name
  11. NCB_ADDGNAME       equ 36h         ;  Add group name
  12. NCB_DELNAME        equ 31h         ;  Delete name
  13. NCB_FINDNAME       equ 78h         ;  Find name
  14. NCB_CALL           equ 10h         ;  Call
  15. NCB_LISTEN         equ 11h         ;  Listen
  16. NCB_HANGUP         equ 12h         ;  Hang up
  17. NCB_SEND           equ 14h         ;  Send
  18. NCB_CHSEND         equ 17h         ;  Chain send
  19. NCB_RECEIVE        equ 15h         ;  Receive
  20. NCB_RECANY         equ 16h         ;  Receive any
  21. NCB_SESSTATUS      equ 34h         ;  Get session status
  22. NCB_SDATAGRAM      equ 20h         ;  Send datagram
  23. NCB_SBROADCAST     equ 22h         ;  Send broadcast
  24. NCB_RDATAGRAM      equ 21h         ;  Receive datagram
  25. NCB_RBROADCAST     equ 23h         ;  Receive broadcast
  26. NCB_TRACE          equ 79h         ;  Start trace
  27.  
  28. ;
  29. ; Network Control Block structure
  30. ;
  31. ncb             struc
  32. ncb_command     db ?
  33. ncb_retcode     db ?
  34. ncb_lsn         db ?
  35. ncb_num         db ?
  36. ncb_buffer      dd ?
  37. ncb_length      dw ?
  38. ncb_callname    db 16 dup(?)
  39. ncb_name        db 16 dup(?)
  40. ncb_rto         db ?
  41. ncb_sto         db ?
  42. ncb_post        dd ?
  43. ncb_lana_num    db ?
  44. ncb_cmd_cplt    db ?
  45. ncb_reserve     db 14 dup(?)
  46. ncb             ends
  47.  
  48. ;
  49. ; ARP packet structure
  50. ;
  51. arp        struc 
  52. arp_hw        dw ?         ; Hardware address length, bytes 
  53. arp_prot    dw ?         ; Protocol type 
  54. arp_hwalen    db ?         ; hardware address length, bytes 
  55. arp_pralen     db ?         ; Length of protocol address 
  56. arp_opcode      dw ?         ; ARP opcode (request/reply) 
  57. arp_shwaddr    db 6 dup(?)    ; Sender hardware address field 
  58. arp_sprotaddr    dd ?        ; Sender Protocol address field 
  59. arp_thwaddr    db 6 dup(?)    ; Target hardware address field 
  60. arp_tprotaddr    dd ?        ; Target protocol address field 
  61. arp        ends
  62.  
  63. code    segment word public
  64.         assume  cs:code, ds:code
  65. ;***************************************************************
  66. prefix          db "TCPIP"
  67.  
  68.         public  int_no
  69. int_no  db      0,0,0,0
  70. ip_adress       dw      2 dup(0)
  71. rq_size         dw      3
  72. padding         dd      0
  73.  
  74.     public    driver_class, driver_type, driver_name, driver_function, parameter_list
  75. driver_class    db      1,0             ;from the packet spec
  76. driver_type     db      0               ;from the packet spec
  77. driver_name     db      'netbios',0     ;name of the driver.
  78. driver_function    db    2
  79. parameter_list    label    byte
  80.     db    1            ;major rev of packet driver
  81.     db    9            ;minor rev of packet driver
  82.     db    14            ;length of parameter list
  83.     db    EADDR_LEN        ;length of MAC-layer address
  84.     dw    1500            ;MTU, including MAC headers
  85.     dw    MAX_MULTICAST * EADDR_LEN    ;buffer size of multicast addrs
  86.     dw    0            ;(# of back-to-back MTU rcvs) - 1
  87.     dw    0            ;(# of successive xmits) - 1
  88. int_num    dw    0            ;Interrupt # to hook for post-EOI
  89.                     ;processing, 0 == none,
  90.  
  91.     public    rcv_modes
  92. rcv_modes    dw    4        ;number of receive modes in our table.
  93.         dw    0,0,0,rcv_mode_3
  94.  
  95. lana_num        db 0
  96. local_ncb_num   db 0              ; handle returned by add_name
  97.  
  98.  
  99.         public  nbsend, nbrcv1, nbrcv2, rcv_buffer1 ; MAP
  100. nbsend          ncb <>
  101. nbrcv1          ncb <>
  102. nbrcv2          ncb <>
  103.  
  104.  
  105. MAX_DG          equ 1500 
  106. rcv_buffer1     db MAX_DG dup(?)
  107.  
  108.     public bad_command_intercept
  109. bad_command_intercept:
  110. ;called with ah=command, unknown to the skeleton.
  111. ;exit with nc if okay, cy, dh=error if not.
  112.     mov    dh,BAD_COMMAND
  113.     stc
  114.     ret
  115.  
  116.     public    as_send_pkt
  117. ; The Asynchronous Transmit Packet routine.
  118. ; Enter with es:di -> i/o control block, ds:si -> packet, cx = packet length,
  119. ;   interrupts possibly enabled.
  120. ; Exit with nc if ok, or else cy if error, dh set to error number.
  121. ;   es:di and interrupt enable flag preserved on exit.
  122. as_send_pkt:
  123.     ret
  124.  
  125.     public    drop_pkt
  126. ; Drop a packet from the queue.
  127. ; Enter with es:di -> iocb.
  128. drop_pkt:
  129.     assume    ds:nothing
  130.     ret
  131.  
  132.     public    xmit
  133. ; Process a transmit interrupt with the least possible latency to achieve
  134. ;   back-to-back packet transmissions.
  135. ; May only use ax and dx.
  136. xmit:
  137.     assume    ds:nothing
  138.     ret
  139.  
  140.  
  141. ;
  142. ; recv_find() requires a pointer to the Ethernet packet type.  Since
  143. ; the incoming packet does not contain an Ethernet packet type field,
  144. ; memory must be allocated to hold the Ethernet packet type.  Space is
  145. ; required for both IP and ARP types.
  146. ;
  147. ip_type        label    byte
  148.         db    08
  149.         db    00    
  150.  
  151. arp_type    label    byte
  152.         db    08
  153.         db    06    
  154.  
  155. gw_switch    db    00
  156.  
  157.  
  158.         public  send_pkt
  159. send_pkt:
  160.         assume ds: nothing
  161. ;enter with ds:si -> packet, cx = packet length.
  162. ;exit with nc if ok, or else cy if error, dh set to error number.
  163.     cmp    cx,GIANT        ; Is this packet too large?
  164.     ja    send_pkt_toobig
  165.  
  166.         push    es
  167.         push    bx
  168.         push    ds
  169.  
  170. ;strip off Ethernet header
  171.     add    si,12
  172.     mov    ax, word ptr ds:[si]
  173.     add    si,2
  174.     sub    cx,14
  175. ;
  176. ; Check packet type.  If an ARP packet then construct an ARP reply
  177. ; packet. Otherwise, process the incoming IP packet.
  178. ;
  179.     cmp    ax,0608h
  180.     jne    noarp
  181.     call    arp_reply
  182.     jmp    send_ok
  183. noarp:
  184.     
  185.         push    cs
  186.         pop     es
  187. ;
  188. ; Set up NCB for a "SEND DATAGRAM" operation
  189. ;
  190.         mov     bx,offset cs:nbsend
  191.  
  192.         mov     cs:[bx].ncb_buffer.offs,si
  193.         mov     ax,ds
  194.         mov     cs:[bx].ncb_buffer.segm,ds
  195.         mov     cs:[bx].ncb_length,cx
  196.  
  197.         push    bx
  198.         lea     di,cs:nbsend.ncb_callname
  199. ;
  200. ; If gateway switch set then contruct NETBIOS name based on the destination
  201. ; IP address in the IP packet. Otherwise, construct the NETBIOS name
  202. ; based on the destination Ethernet address.
  203. ;
  204.     mov    al,gw_switch
  205.     cmp    al,0
  206.     je    use_hw_addr
  207.     mov    bx, word ptr ds:[si+16]
  208.     mov    dx, word ptr ds:[si+18]
  209.     jmp    conv_addr
  210. use_hw_addr:
  211.     mov    bx, word ptr ds:[si-12]
  212.     mov    dx, word ptr ds:[si-10]
  213. conv_addr:
  214.         push    cs
  215.         pop     ds
  216.         call    ip_to_nbname
  217.         pop     bx
  218. ;
  219. ; Pass "Send Datagram" NCB to NETBIOS
  220. ;
  221.         int     5ch
  222. ;
  223. ; If "Send Datagram" operation is unsuccessful then print return code and
  224. ; set carry bit.  Otherwise, clear the carry bit.
  225. ;
  226.         cmp     al,0
  227.         jz      send_ok
  228.         add     ax,32
  229.         call    tty
  230.         mov     al,'S'
  231.         call    tty
  232.         stc
  233.         jmp     send_done
  234. send_ok:
  235.         clc
  236. send_done:
  237.         pop     ds
  238.         pop     bx
  239.         pop     es
  240.         ret
  241.  
  242. send_pkt_toobig:
  243.     mov    dh,NO_SPACE
  244.     stc
  245.     ret
  246.  
  247. ;
  248. ; Formulate a dummy ARP reply packet.  ds:si points at the incoming
  249. ; IP packet.
  250. ;
  251. arp_reply:
  252. ;
  253. ; Save the registers.  Not sure that we need to but it works and I 
  254. ; don't want to change it right now.
  255. ;
  256.     push    ds
  257.     push    es
  258.     push    si
  259.     push    di
  260.     push    cx
  261. ;
  262. ; Check to see if the ARP request is to find the hardware address
  263. ; of the local host.  If so, then don't formulate a reply packet.
  264. ;
  265.     mov    cx,4
  266.     mov    ax,si
  267.     mov    di,ax
  268.     mov    ax,ds
  269.     mov    es,ax
  270.     add    di,arp_sprotaddr
  271.     add    si,arp_tprotaddr
  272.     repe    cmpsb            ; Compare source and target
  273.                     ; protocol address
  274.     jnz    arp_reply_2
  275.     pop    cx
  276.     pop    di
  277.     pop    si
  278.     pop    es
  279.     pop    ds
  280.     ret
  281. arp_reply_2:
  282. ;
  283. ; Restore registers.
  284. ;
  285.     pop    cx
  286.     pop    di
  287.     pop    si
  288.     push    si
  289.     push    di
  290.     push    cx
  291. ;
  292. ; Restore Ethernet header.
  293. ;
  294.     add    cx,14
  295.     sub    si,14 
  296. ;
  297. ; Ask application layer for a memory buffer in which to store
  298. ; incoming packet.
  299. ;
  300.     push    ds
  301.     push    si            ;save si in case we reject it.
  302.     push    bx
  303.     push    cx
  304.  
  305.     mov    ax,cs
  306.     mov    es,ax
  307.     mov    ds,ax
  308.     mov    di, offset arp_type
  309.     mov    dl,cs:driver_class
  310.     call    recv_find        ;look up our type.
  311.     pop    cx
  312.     pop    bx
  313.     pop    si
  314.     pop    ds
  315.  
  316.     mov    ax,es            ;is this pointer null?
  317.     or    ax,di
  318.     je    arp_reply_1        ;yes - just free the frame.
  319.  
  320.     push    cx
  321.     push    es
  322.     push    di
  323. ;
  324. ; Save si,di for future use.
  325. ;
  326.     mov    bx,si
  327.     mov    dx,di
  328. ;
  329. ; Set up ARP Reply by first copying the ARP Request packet.
  330. ;
  331.     rep    movsb
  332. ;
  333. ; Skip Ethernet header
  334. ;
  335.     add    bx,14
  336.     add     dx,14
  337. ;
  338. ; Swap target and source protocol addresses from ARP request to ARP 
  339. ; reply packet.
  340. ;
  341.     mov    si,bx
  342.     mov    di,dx    
  343.     mov    cx,4
  344.     add    si,arp_tprotaddr
  345.     add    di,arp_sprotaddr
  346.     rep    movsb
  347.  
  348.     mov    si,bx
  349.     mov    di,dx
  350.     mov    cx,4
  351.     add    si,arp_sprotaddr
  352.     add    di,arp_tprotaddr
  353.     rep    movsb
  354. ;
  355. ; Swap target and source hardware addresses from ARP request to ARP 
  356. ; reply packet.
  357. ;
  358.     mov    si,bx
  359.     mov    di,dx
  360.     mov    cx,6
  361.     add    si,arp_shwaddr
  362.     add    di,arp_thwaddr
  363.     rep    movsb
  364. ;
  365. ; Load source hardware address in ARP reply packet.
  366. ;
  367.     mov    si,bx
  368.     mov    di,dx
  369.     add    di,arp_shwaddr
  370.     mov    es:[di],word ptr 0000h
  371.     add    di,2
  372.     mov    cx,4
  373.     add    si,arp_tprotaddr    ; Set Ethernet address in ARP reply
  374.                     ; to target IP address
  375.     rep    movsb
  376. ;
  377. ; Set opcode to REPLY.
  378. ;
  379.     mov    di,dx
  380.     mov    word ptr es:[di].arp_opcode,0200h
  381. ; Give ARP reply packet that has been constructed to the application
  382. ; layer.
  383. ;
  384.     pop    si
  385.     pop    ds
  386.     pop    cx
  387.     assume    ds:nothing
  388.  
  389.     call    recv_copy
  390.     assume    ds:code
  391.  
  392. arp_reply_1:
  393.  
  394.     pop    cx
  395.     pop    di
  396.     pop    si
  397.     pop    es
  398.     pop    ds
  399.  
  400.     ret
  401.  
  402.  
  403.     public    set_address
  404. set_address:
  405. ;enter with ds:si -> Ethernet address, CX = length of address.
  406. ;exit with nc if okay, or cy, dh=error if any errors.
  407.     assume    ds:nothing
  408.     ret
  409.  
  410.  
  411. rcv_mode_3:
  412. ;receive mode 3 is the only one we support, so we don't have to do anything.
  413.     ret
  414.  
  415.  
  416.     public    set_multicast_list
  417. set_multicast_list:
  418. ;enter with ds:si ->list of multicast addresses, ax = number of addresses,
  419. ;  cx = number of bytes.
  420. ;return nc if we set all of them, or cy,dh=error if we didn't.
  421.     mov    dh,NO_MULTICAST
  422.     stc
  423.     ret
  424.  
  425.  
  426.     public    terminate
  427. terminate:
  428.     ret
  429.  
  430.         public  reset_interface
  431. reset_interface:
  432. ;reset the interface.
  433.         ret
  434.  
  435.  
  436. ;called when we want to determine what to do with a received packet.
  437. ;enter with cx = packet length, es:di -> packet type.
  438.         extrn   recv_find: near
  439.  
  440. ;called after we have copied the packet into the buffer.
  441. ;enter with ds:si ->the packet, cx = length of the packet.
  442.         extrn   recv_copy: near
  443.  
  444.         extrn   count_in_err: near
  445.         extrn   count_out_err: near
  446.         extrn   dwordout: near
  447.         extrn   error: near
  448.  
  449.         public  recv
  450. recv:
  451. ;called from the recv isr.  All registers have been saved, and ds=cs.
  452. ;Upon exit, the interrupt will be acknowledged.
  453.         assume  ds:code
  454.         ret
  455.  
  456.         public nbint  ; MAP
  457. nbint   proc far
  458.         push ds
  459. ;
  460. ; Set data segment to code segment so that we can reference local
  461. ; variables.
  462. ;
  463.         push cs
  464.         pop  ds
  465. ;
  466. ; Retrieve size of received packet
  467. ;
  468.         mov  cx,[bx].ncb_length
  469. ;
  470. ; Check return code.  If there was an error then don't process the
  471. ; packet any further.
  472. ;
  473.         mov  al,[bx].ncb_retcode
  474.         cmp  al,0               ; ok
  475.         jnz  bad_nbint
  476. ;
  477. ; Add Ethernet header.  As well, ensure that minimum packet size is 60
  478. ; bytes; some application packages actually check for minimum packet size.
  479. ;
  480.     add    cx,14 
  481.     cmp    cx,60
  482.     jge    recv_next
  483.     mov    cx,60
  484. recv_next:
  485.     push    si            ;save si in case we reject it.
  486.     push    bx
  487.     push    cx
  488.  
  489.     movseg    es,cs
  490.     mov    di, offset ip_type
  491.     mov    dl,cs:driver_class
  492.     call    recv_find        ;look up our type.
  493.  
  494.     pop    cx
  495.     pop    bx
  496.     pop    si
  497.     mov    ax,es            ;is this pointer null?
  498.     or    ax,di
  499.  
  500.     jne  nb_next 
  501.         jmp  skip_copy 
  502. nb_next:
  503.     push bx
  504.     push cx
  505.     push es
  506.     push di
  507. ;
  508. ; Fix up the Ethernet header added to the incoming packet.
  509. ;
  510.     call    fix_header
  511. ;
  512. ; Copy the received packet into buffer allocated by the application
  513. ; software.
  514. ;
  515.     sub    cx,14
  516.         mov     si,[bx].ncb_buffer.offs
  517.         rep     movsb
  518.     pop si
  519.     pop ds
  520.     pop cx
  521.     assume ds:nothing
  522.         call    recv_copy
  523.     push cs
  524.     pop ds
  525.     assume ds:code
  526.     pop bx
  527. skip_copy:
  528.         mov     [bx].ncb_length,MAX_DG  ; reestablish dg-length
  529. ;
  530. ; Set up to receive another packet.  Construct "receive datagram"
  531. ; NCB.
  532. ;
  533.         push    ds
  534.         pop     es
  535.         int    5ch
  536. ;
  537. ; Check return code.  Print error indication if NETBIOS does not
  538. ; accept NCB.
  539. ;
  540.         mov    al,[bx].ncb_retcode   ; JS added return code
  541.         cmp     al,0ffh
  542.         jz      nbint_pending_ok1
  543.         mov     al,'?'
  544.         call    tty
  545.         add     ax,32
  546.         call    tty
  547.         mov     al,'.'
  548.         call    tty
  549.  
  550. nbint_pending_ok1:
  551.         jmp     short nbint_done
  552.  
  553. bad_nbint:
  554.         add     ax,32
  555.         call    tty
  556.         mov     al,'R'
  557.         call    tty
  558.     jmp    skip_copy
  559.  
  560. nbint_done:
  561.         pop ds
  562.         iret
  563. nbint   endp
  564.  
  565. ;
  566. ; Set destination and source addressess and packet type in an
  567. ; Ethernet header.
  568. ;
  569. fix_header:
  570. ;
  571. ; Set destination address.
  572. ;
  573.     push    cx
  574.     mov    ax,0000h
  575.     stosw
  576.     mov    ax,ip_adress.offs    ;was 0c3c4h
  577.     stosw
  578.     mov    ax,ip_adress.segm    ;was 0c2cch
  579.     stosw
  580. ;
  581. ; Set source address.  NCB callname contains the string "TCPIP" +
  582. ; source host IP address.  Extract host IP address and copy into
  583. ; Ethernet header as the source address.
  584. ;
  585.     mov    ax,0000h
  586.     stosw
  587.     mov    ax,word ptr [bx].ncb_callname+5
  588.     stosw
  589.     mov    ax,word ptr [bx].ncb_callname+7
  590.     stosw
  591. ;
  592. ; Set packet type to IP.
  593. ;
  594.     mov    ax, 0008h
  595.     stosw    
  596.  
  597.     pop    cx
  598.     ret
  599.  
  600.  
  601.  
  602.         public  nb_stop
  603. nb_stop:
  604.         ;                   unregister name
  605.         push    cs
  606.         pop     es
  607.         lea      bx,nbrcv1
  608.         mov     [bx].ncb_command,NCB_DELNAME
  609. ;        mov     al,lana_num
  610. ;        mov     [bx].ncb_lana_num,al
  611.         int     5ch
  612.         cmp     al,0
  613.         jz      good_delete
  614.         add     ax,32
  615.         call    tty
  616.         mov     al,'I'
  617.         call    tty
  618. good_delete:
  619.         ret
  620.  
  621.  
  622.     public tty
  623. tty:
  624.         push    bx
  625.         mov     ah,14
  626.         int     10h
  627.         pop     bx
  628.         ret
  629.  
  630. ip_to_nbname:
  631.         ;      call with es:di = *ncb_name
  632.         ;            bx and dx = ip_address
  633.  
  634.         mov     cx,5
  635.         mov     si,offset prefix
  636.         rep     movsb
  637.  
  638.         mov     [di],bx
  639.         mov     [di+2],dx
  640.         ret
  641.  
  642.     public    timer_isr
  643. timer_isr:
  644. ;if the first instruction is an iret, then the timer is not hooked
  645.     iret
  646.  
  647. ;any code after this will not be kept.  Buffers used by the program, if any,
  648. ;are allocated from the memory between end_resident and end_free_mem.
  649.     public end_resident,end_free_mem
  650. end_resident    label    byte
  651. end_free_mem    label    byte
  652.  
  653.         public  usage_msg
  654. usage_msg       db      "usage: nb [options] <packet_int_no> <ip.ad.dr.ess> [receive queue size]",CR,LF,'$'
  655.  
  656.         public  copyright_msg
  657. copyright_msg   db      "Packet driver for a netbios device, version ",'0'+version,CR,LF,'$'
  658.                 db      "Portions Copyright 1990, Michael Haberler",CR,LF,'$'
  659.  
  660. ip_adress_name  db      "IP Adress ",'$'
  661. rq_size_name    db      "Receive Queue ",'$'
  662. bad_name_msg    db      " bad returncode from nb add_name",CR,LF,'$'
  663. bad_rcv_msg     db      " bad returncode from nb receive dg",CR,LF,'$'
  664. good_name_msg   db      " good returncode from nb add_name",CR,LF,'$'
  665. good_rcv_msg    db      " good returncode from nb receive dg",CR,LF,'$'
  666. temp_dw         dw      ?
  667.         extrn   set_recv_isr: near
  668.  
  669. ;enter with si -> argument string, di -> word to store.
  670. ;if there is no number, don't change the number.
  671.         extrn   get_number: near
  672.     extrn    skip_blanks: near
  673.  
  674. ;-> the assigned Ethernet address of the card.
  675.     extrn    rom_address: byte
  676.  
  677.         public  parse_args
  678. parse_args:
  679. ;exit with nc if all went well, cy otherwise.
  680.     call    skip_blanks
  681.     cmp    al,'-'            ;did they specify a switch?
  682.     jne    not_switch
  683.     cmp    byte ptr [si+1],'g'    ;did they specify '-g'?
  684.     je    got_gw_switch
  685.     stc                ;no, must be an error.
  686.     ret
  687. got_gw_switch:
  688.     mov    gw_switch,1
  689.     add    si,2            ;skip past the switch's characters.
  690.     jmp    parse_args        ;go parse more arguments.
  691. not_switch:
  692.  
  693.         mov     di, offset temp_dw
  694.         mov     bx, offset ip_adress_name
  695.         call    get_number
  696.         mov     ax,temp_dw
  697.         mov     byte ptr ip_adress+0,al
  698.         inc     si
  699.         mov     di, offset temp_dw
  700.         mov     bx, offset ip_adress_name
  701.         call    get_number
  702.         mov     ax,temp_dw
  703.         mov     byte ptr ip_adress+1,al
  704.         inc     si
  705.         mov     di, offset temp_dw
  706.         mov     bx, offset ip_adress_name
  707.         call    get_number
  708.         mov     ax,temp_dw
  709.         mov     byte ptr ip_adress+2,al
  710.         inc     si
  711.         mov     di, offset temp_dw
  712.         mov     bx, offset ip_adress_name
  713.         call    get_number
  714.         mov     ax,temp_dw
  715.         mov     byte ptr ip_adress+3,al
  716.  
  717.         ret
  718.  
  719.  
  720.  
  721.         public  etopen
  722. etopen:
  723. ;if all is okay,
  724. ;        mov     bx,offset nbsend
  725.         lea     bx,nbsend
  726.         mov     [bx].ncb_command,NCB_ADDNAME
  727.         mov     al,lana_num
  728.         mov     [bx].ncb_lana_num,al
  729.  
  730.         push    ds
  731.         push    cs
  732.         push    cs
  733.         pop     ds
  734.         pop     es
  735.  
  736.         push    bx
  737.         lea     di,nbsend.ncb_name
  738.         mov     bx,ip_adress
  739.         mov     dx,ip_adress+2
  740.         call    ip_to_nbname
  741.         pop     bx
  742.  
  743. ;fake up an Ethernet address.
  744.     mov    word ptr rom_address[0],word ptr 0000h
  745.         mov     bx,cs:ip_adress
  746.     mov    word ptr rom_address[4],bx
  747.     mov    bx,cs:ip_adress+2
  748.     mov    word ptr rom_address[2],bx
  749.  
  750. ;    mov    di, offset nbsend.ncb_name
  751. ;    mov    cx,16
  752. ;mike:
  753. ;    mov    al, [di]
  754. ;    call    tty
  755. ;    inc    di
  756. ;    dec    cx
  757. ;    jnz    mike
  758.  
  759.  
  760.         mov     cx,16
  761.         mov     di,offset nbrcv1.ncb_name
  762.         mov     si,offset nbsend.ncb_name
  763.         rep     movsb
  764.         mov     cx,16
  765.         mov     di,offset nbrcv2.ncb_name
  766.         mov     si,offset nbsend.ncb_name
  767.         rep     movsb
  768.  
  769.         int     5ch     ; add_name, -> returns rc in al
  770.         cmp     al,0
  771.         jz      good_name
  772.         mov     dx,0
  773.         mov     ah,0
  774.         call    dwordout
  775.         mov     dx,offset bad_name_msg
  776.         pop     ds
  777.     stc
  778.     ret
  779.  
  780. good_name:
  781. ;        mov     dx,offset good_name_msg
  782. ;        call    say
  783.  
  784.         mov     al,[bx].ncb_num
  785.         mov     local_ncb_num,al
  786.         mov     [bx].ncb_command,NCB_SDATAGRAM  ;set send command code
  787.  
  788.         ;       start receive operations
  789. ;        mov     bx,offset nbrcv1
  790.         lea     bx,nbrcv1
  791.         mov     al,NCB_RDATAGRAM+NCB_NOWAIT  ;set rcv command
  792.         mov     [bx].ncb_command,al
  793.  
  794.         mov     al,local_ncb_num
  795.         mov     [bx].ncb_num,al
  796.  
  797.         mov     ax,MAX_DG
  798.         mov     [bx].ncb_length,ax
  799.  
  800.         mov     ax,ds
  801.         mov     [bx].ncb_buffer.segm,ax
  802.         mov     [bx].ncb_buffer.offs,offset rcv_buffer1
  803.  
  804.         mov     [bx].ncb_post.segm,ax
  805.         mov     [bx].ncb_post.offs,offset nbint
  806.  
  807.         mov     al,lana_num
  808.         mov     [bx].ncb_lana_num,al
  809.         int     5ch
  810.  
  811.         cmp     al,0ffh
  812.         jz      pending_ok1
  813.         cmp     al,00h
  814.         jnz     bad_init
  815.  
  816. pending_ok1:
  817.         mov     dx,offset good_rcv_msg
  818.     mov    ah,9
  819.     int    21h
  820.  
  821.         pop     ds
  822.         clc
  823.         ret
  824. ;if we got an error,
  825. bad_init:
  826.         mov     ah,0
  827.         mov     dx,0
  828.         call    dwordout
  829.         call    nb_stop
  830.         pop     ds
  831.         mov     dx,offset bad_rcv_msg
  832.         stc
  833.         ret
  834.  
  835.     public    print_parameters
  836. print_parameters:
  837.     ret
  838.  
  839. say:
  840.         mov     ah,9
  841.         int     21h
  842.         ret
  843.  
  844.  
  845. code    ends
  846.  
  847.     end
  848.  
  849.