home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / PROGRAMS / UTILS / NOVELL / PKTDRV7.ZIP / LOCALTLK.ASM < prev    next >
Encoding:
Assembly Source File  |  1990-07-27  |  29.2 KB  |  1,134 lines

  1. version    equ    0
  2.  
  3.     include    defs.asm
  4.  
  5. ; PC/FTP Packet Driver source, conforming to version 1.09 of the spec
  6. ; Katie Stevens (dkstevens@ucdavis.edu)
  7. ; Computing Services, University of California, Davis
  8. ; Portions (C) Copyright 1988 Regents of the University of California
  9.  
  10. ; This program is free software; you can redistribute it and/or modify
  11. ; it under the terms of the GNU General Public LIcense as published by
  12. ; the Free Software Foundation, version 1.
  13. ;
  14. ; This program is distributed in the hope that it will be useful,
  15. ; but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. ; GNU General Public License for more details.
  18.  
  19. code    segment    word public
  20.     assume    cs:code, ds:code
  21.  
  22. ; Definitions specific to the PC LocalTalk cards: these include Apple
  23. ; LocalTalk PC Card, TOPS FlashCard
  24. ; For a complete description of the LocalTalk commands, structures and
  25. ; methods used in this driver, please refer to Apple APDA document #M7055,
  26. ; LocalTalk PC Card and Driver Preliminary Notes.
  27.  
  28. driverstring    db    'AppleTalk', 0        ; ATALK.SYS signature string
  29. dot_char    db    '.', 0            ; for IP address display
  30.  
  31. AT_INT        equ    5CH            ; Software int# for ATALK.SYS
  32.  
  33. ; General ATALK.SYS driver commands
  34. AT_INIT            equ    01H        ; Initialize driver software
  35. AT_GETNETINFO        equ    03H        ; Get driver info
  36.  
  37. ; Datagram Delivery Protocol commands for ATALK.SYS driver
  38. DDP_OPENSOCKET        equ    20H
  39. DDP_CLOSESOCKET        equ    21H
  40. DDP_WRITE        equ    22H
  41. DDP_READ        equ    23H
  42. DDP_CANCEL        equ    24H
  43.  
  44. ; Name Binding Protocol commands for ATALK.SYS driver
  45. NBP_REGISTER        equ    30H
  46. NBP_REMOVE        equ    31H
  47. NBP_LOOKUP        equ    32H
  48. NBP_CONFIRM        equ    33H
  49. NBP_CANCEL        equ    34H
  50.  
  51. ; AppleTalk Transaction Protocol commands for ATALK.SYS driver
  52. ATP_SEND_REQUEST    equ    42H
  53.  
  54. ; ATALK.SYS command qualifiers
  55. ASYNC_MASK    equ    8000H        ; Start command, then return
  56. INTR_MASK    equ    4000H        ; Wait for intr service to complete
  57.  
  58. XO_BIT        equ    20H        ; ATP - exactly once transaction
  59.  
  60. ; Structure for AppleTalk node addressing
  61. AddrBlk struc
  62.     ablk_network    dw    0
  63.     ablk_nodeid    db    0
  64.     ablk_socket    db    0
  65. AddrBlk ends
  66.  
  67. ; Structure for general calls to AppleTalk driver (ATALK.SYS)
  68. InfoParams struc
  69.     atd_command    dw        AT_GETNETINFO
  70.     atd_status    dw        0
  71.     atd_compfun    segmoffs    <>
  72.     inf_network    dw        0
  73.     inf_nodeid    db        0
  74.     inf_abridge    db        0
  75.     inf_config    dw        0
  76.     inf_buffptr    segmoffs    <>
  77.     inf_buffsize    dw        0
  78. InfoParams ends
  79. ; Parameter block for general calls to AppleTalk driver (ATALK.SYS)
  80. MyInfo    InfoParams    <>
  81.  
  82. ; Address block for our gateway
  83. MyGateway    AddrBlk        <>
  84.  
  85. ; Structure for calls to AppleTalk driver (ATALK.SYS) for Datagram
  86. ; Delivery Protocol (DDP) service
  87. DDPParams struc
  88.     ddp_command    dw        0
  89.     ddp_status    dw        0
  90.     ddp_compfun    segmoffs    <>
  91.     ddp_addr    AddrBlk        <>
  92.     ddp_socket    db        0
  93.     ddp_type    db        0
  94.     ddp_buffptr    segmoffs    <>
  95.     ddp_buffsize    dw        0
  96.     ddp_chksum    db        0
  97. DDPParams ends
  98. ; Parameter blocks for AppleTalk DDP access
  99. DDPio        DDPParams    <>        ; Write on DDP socket
  100. ; 2 buffers for packet receive from ATALK.SYS
  101. DDP1inuse    db    0            ; Buffer occupied flag
  102. DDP1buffsize    dw    0            ; Buffer length during reads
  103. DDP1buffer    db    1024 dup (0)        ; Buffer for DDP read
  104. DDP2inuse    db    0            ; 2nd Buffer occupied flag
  105. DDP2buffsize    dw    0            ; 2nd Buffer length during reads
  106. DDP2buffer    db    1024 dup (0)        ; 2nd Buffer for DDP read
  107.  
  108. ; Structure for calls to AppleTalk driver (ATALK.SYS) for Name
  109. ; Binding Protocol (NBP) service
  110. NBPParams struc
  111.     nbp_command    dw        0
  112.     nbp_status    dw        0
  113.     nbp_compfun    segmoffs    <>
  114.     nbp_addr    AddrBlk        <>
  115.     nbp_toget    dw        0
  116.     nbp_buffptr    segmoffs    <>
  117.     nbp_buffsize    dw        0
  118.     nbp_interval    db        0
  119.     nbp_retry    db        0
  120.     nbp_entptr    segmoffs    <>
  121. NBPParams ends
  122. ; Parameter block for AppleTalk NBP access
  123. NBP        NBPParams    <>
  124.  
  125. ; Structure for name-to-address bind entries
  126. NBPTuple struc
  127.     tup_address    AddrBlk        <>
  128.     tup_enum    db        0
  129.     tup_name    db        99 dup(0)
  130. NBPTuple ends
  131. ; Name Binding Tuple for our IP gateway
  132. NBPt        NBPTuple    <>
  133.  
  134. ; Structure for name-to-address table
  135. NBPEntry struc
  136.     tab_next    segmoffs    <>
  137.     tab_entry    NBPTuple    <>
  138. NBPEntry ends
  139. NBPtable    NBPEntry    <>
  140.  
  141. ; Structure for calls to AppleTalk driver (ATALK.SYS) for AppleTalk
  142. ; Transaction Protocol (ATP) service
  143. ATPParams struc
  144.     atp_command    dw        0
  145.     atp_status    dw        0
  146.     atp_compfun    segmoffs    <>
  147.     atp_addrblk    AddrBlk        <>
  148.     atp_socket    db        0
  149.     atp_fill    db        0
  150.     atp_buffptr    segmoffs    <>
  151.     atp_buffsize    dw        0
  152.     atp_interval    db        0
  153.     atp_retry    db        0
  154.     atp_flags    db        0
  155.     atp_seqbit    db        0
  156.     atp_tranid    dw        0
  157.     atp_userbytes    db        4 dup(0)
  158.     atp_bdsbuffs    db        0
  159.     atp_bdsresps    db        0
  160.     atp_bdsptr    segmoffs    <>
  161. ATPParams ends
  162. ; Parameter block for AppleTalk ATP access
  163. ATP        ATPParams    <>
  164.  
  165. ; Structure for BDS elements
  166. BDSElement struc
  167.     bds_buffptr    segmoffs    <>
  168.     bds_buffsize    dw        0
  169.     bds_datasize    dw        0
  170.     bds_userbytes    db        4 dup(0)
  171. BDSElement ends
  172. ; Parameter block for our BDS element
  173. BDS        BDSElement    <>
  174.  
  175. ; Struct for IP gateway information
  176. IPGInfo struc
  177.     ipg_opcode    db        0,0,0,1    ; IPGP_ASSIGN
  178.     ipg_ipaddress    dd        0    ; our IP address
  179.     ipg_ipname    dd        0    ; nameserver IP address
  180.     ipg_ipbroad    dd        0    ; broadcast IP address
  181.     ipg_ipfile    dd        0    ; file server IP address
  182.     ipg_ipother    dd        4 dup (0)
  183.     ipg_string    db        128 dup (0), '$'
  184. IPGInfo ends
  185. ; Parameter block for info about our IP gateway
  186. IPG        IPGInfo        <>
  187.  
  188. IPG_ERROR    equ    -1
  189.  
  190. ; End of Appletalk parameter definitions
  191.  
  192. ; The following values may be overridden from the command line.
  193. ; If they are omitted from the command line, these defaults are used.
  194.  
  195.     public    int_no
  196. int_no    db    0,0,0,0            ;must be four bytes long for get_number.
  197.  
  198.     public    driver_class, driver_type, driver_name, driver_function, parameter_list
  199. driver_class    db    17        ;from the packet spec
  200. driver_type    db    0        ;from the packet spec
  201. driver_name    db    'LocalTalk',0    ;name of the driver.
  202. driver_function    db    2
  203. parameter_list    label    byte
  204.     db    1    ;major rev of packet driver
  205.     db    9    ;minor rev of packet driver
  206.     db    14    ;length of parameter list
  207.     db    EADDR_LEN    ;length of MAC-layer address
  208.     dw    GIANT    ;MTU, including MAC headers
  209.     dw    MAX_MULTICAST * EADDR_LEN    ;buffer size of multicast addrs
  210.     dw    0    ;(# of back-to-back MTU rcvs) - 1
  211.     dw    0    ;(# of successive xmits) - 1
  212. int_num    dw    0    ;Interrupt # to hook for post-EOI
  213.             ;processing, 0 == none,
  214.  
  215.     public    rcv_modes
  216. rcv_modes    dw    4        ;number of receive modes in our table.
  217.         dw    0,0,0,rcv_mode_3
  218.  
  219.     public    as_send_pkt
  220. ; The Asynchronous Transmit Packet routine.
  221. ; Enter with es:di -> i/o control block, ds:si -> packet, cx = packet length,
  222. ;   interrupts possibly enabled.
  223. ; Exit with nc if ok, or else cy if error, dh set to error number.
  224. ;   es:di and interrupt enable flag preserved on exit.
  225. as_send_pkt:
  226.     ret
  227.  
  228.     public    drop_pkt
  229. ; Drop a packet from the queue.
  230. ; Enter with es:di -> iocb.
  231. drop_pkt:
  232.     assume    ds:nothing
  233.     ret
  234.  
  235.     public    xmit
  236. ; Process a transmit interrupt with the least possible latency to achieve
  237. ;   back-to-back packet transmissions.
  238. ; May only use ax and dx.
  239. xmit:
  240.     assume    ds:nothing
  241.     ret
  242.  
  243.  
  244.     public    send_pkt
  245. send_pkt:
  246. ;enter with es:di->upcall routine, (0:0) if no upcall is desired.
  247. ;  (only if the high-performance bit is set in driver_function)
  248. ;enter with ds:si -> packet, cx = packet length.
  249. ;if we're a high-performance driver, es:di -> upcall.
  250. ;exit with nc if ok, or else cy if error, dh set to error number.
  251.     assume    ds:nothing
  252. ; send packet to AppleTalk/DDP/IP gateway
  253.     ; load info about the packet we are sending
  254.     mov    DDPio.ddp_buffptr.offs, si
  255.     mov    DDPio.ddp_buffptr.segm, ds    ; DDPio.buffptr -> IP packet
  256.     mov    DDPio.ddp_buffsize, cx        ; DDPio.buffsize = packet len
  257.  
  258.     ; send all packets to the IP gateway
  259.     mov    cx, (size AddrBlk)        ; DDPio.ddp_addr = MyGateway
  260.     mov    ax, cs
  261.     mov    ds, ax
  262.     mov    es, ax
  263.     mov    si, offset MyGateway
  264.     mov    di, offset DDPio.ddp_addr
  265.     rep    movsb
  266.  
  267.     mov    bx, offset DDPio
  268.     call    doATint                ; Ask ATALK.SYS to send packet
  269.  
  270.     cmp    DDPio.ddp_status, 00H        ; Packet sent okay?
  271.     je    send_ret            ; Yes, status is good
  272.                         ; No, status gives error
  273. send_err:
  274.     call    count_out_err
  275.     mov    dh, CANT_SEND            ; set error flag
  276.     stc
  277.     ret
  278.  
  279. send_ret:
  280.     clc                    ; packet sent successfully
  281.     ret
  282.  
  283.     public    get_address
  284. get_address:
  285. ;get the address of the interface.
  286. ;enter with es:di -> place to get the address, cx = size of address buffer.
  287. ;exit with nc, cx = actual size of address, or cy if buffer not big enough.
  288.     assume    ds:code
  289.     ret
  290.  
  291.  
  292.     public    set_address
  293. set_address:
  294. ;enter with ds:si -> Ethernet address, CX = length of address.
  295. ;exit with nc if okay, or cy, dh=error if any errors.
  296.     assume    ds:nothing
  297.     mov    dh, BAD_COMMAND
  298.     stc
  299.     ret
  300.  
  301.  
  302. rcv_mode_3:
  303. ;receive mode 3 is the only one we support, so we don't have to do anything.
  304.     ret
  305.  
  306.  
  307.     public    set_multicast_list
  308. set_multicast_list:
  309. ;enter with ds:si ->list of multicast addresses, cx = number of addresses.
  310. ;return nc if we set all of them, or cy,dh=error if we didn't.
  311.     mov    dh,NO_MULTICAST
  312.     stc
  313.     ret
  314.  
  315.  
  316.     public    terminate
  317. terminate:
  318.     push    ds
  319.     push    cs
  320.     pop    ds
  321.  
  322. terminate_write:
  323.     ; close the DDP socket
  324.     mov    DDPio.ddp_command, DDP_CLOSESOCKET
  325.     mov    bx, offset DDPio
  326.     call    doATint
  327.  
  328.     mov    NBP.nbp_command, NBP_REMOVE
  329.     mov    NBP.nbp_entptr.offs, offset NBPtable.tab_entry.tup_name
  330.     mov    NBP.nbp_entptr.segm, ds
  331.     mov    bx, offset NBP
  332.     call    doATint
  333.  
  334.     pop    ds
  335.     ret
  336.  
  337.     public    reset_interface
  338. reset_interface:
  339. ;reset the interface.
  340.     assume    ds:code
  341.     ret
  342.  
  343.  
  344. ;called when we want to determine what to do with a received packet.
  345. ;enter with cx = packet length, es:di -> packet type.
  346.     extrn    recv_find: near
  347.  
  348. ;called after we have copied the packet into the buffer.
  349. ;enter with ds:si ->the packet, cx = length of the packet.
  350.     extrn    recv_copy: near
  351.  
  352.     extrn    count_in_err: near
  353.     extrn    count_out_err: near
  354.  
  355.     public    recv
  356. recv:
  357. ;called from the recv isr.  All registers have been saved, and ds=cs.
  358. ;Upon exit, the interrupt will be acknowledged.
  359. ;NOTE: this packet driver merely makes calls to another hardware
  360. ;driver, ATALK.SYS. ATALK.SYS handles the hardware interrupt service;
  361. ;ATALK.SYS then calls this packet driver with FAR subroutine calls.
  362. ;the ATALK.SYS FAR subroutine is recv_at_upcall
  363.     assume    ds:nothing
  364.     ret
  365.  
  366.     public    recv_exiting
  367. recv_exiting:
  368. ;called from the recv isr after interrupts have been acknowledged.
  369. ;Only ds and ax have been saved.
  370.     assume    ds:nothing
  371.     ret
  372.  
  373. ;*******************************************
  374.  
  375. ; NULL completion routine for ATALK.SYS drivers calls
  376. noop_upcall proc far
  377.     ret
  378. noop_upcall endp
  379.  
  380. ;First half routine for DDP socket.
  381. ;ATALK.SYS calls this routine when a packet is received.
  382. ;ATALK.SYS assumes we are a far procedure.
  383. ;    CX = size of data packet
  384. preview_upcall proc far
  385.     assume    ds:nothing
  386.  
  387. ;    maximum packet we can receive is 1024 bytes
  388.     cmp    cx, 1024
  389.     ja    preview_drop
  390.  
  391. preview_buff1:
  392.     cmp    DDP1inuse, 00H
  393.     jne    preview_buff2
  394.     mov    DDP1inuse, 01H
  395.  
  396. ;    repeat buffer size back to ATALK.SYS in CX
  397. ;    ask ATALK.SYS driver to pass us the buffer at DS:BX
  398. ;    tell ATALK.SYS address of 2nd half routine in ES:DX
  399.     push    cs
  400.     pop    ds
  401.     mov    bx, offset DDP1buffer        ; ds:bx->buffer
  402.     push    cs
  403.     pop    es
  404.     mov    dx, offset recv_at_upcall    ; es:dx->2nd half routine
  405.     jmp    preview_ret
  406.  
  407. preview_buff2:
  408.     cmp    DDP2inuse, 00H
  409.     jne    preview_drop
  410.     mov    DDP2inuse, 01H
  411.  
  412. ;    repeat buffer size back to ATALK.SYS in CX
  413. ;    ask ATALK.SYS driver to pass us the buffer at DS:BX
  414. ;    tell ATALK.SYS address of 2nd half routine in ES:DX
  415.     push    cs
  416.     pop    ds
  417.     mov    bx, offset DDP2buffer        ; ds:bx->buffer
  418.     push    cs
  419.     pop    es
  420.     mov    dx, offset recv_at_upcall    ; es:dx->2nd half routine
  421.     jmp    preview_ret
  422.  
  423.  
  424. preview_drop:
  425. ;    ask ATALK.SYS to drop the packet
  426.     call    count_in_err
  427.     mov    cx, 00h
  428.  
  429. preview_ret:
  430.     ret
  431. preview_upcall endp
  432.  
  433. ;Second half routine for DDP socket.
  434. ;ATALK.SYS calls this routine when the packet has been copied to our buffer.
  435. ;ATALK.SYS assumes we are a far procedure.
  436. ;    CX = size of data packet
  437. ;    DS:BX = address of buffer
  438. recv_at_upcall proc far
  439.     assume    ds:nothing
  440.  
  441. recv_buff1:
  442.     cmp    bx, offset DDP1buffer
  443.     jne    recv_buff2
  444.  
  445. ;    check if we have a client waiting for packets
  446. ;    pass to recv_find    es:di->driver_type, cx=#bytes in packet
  447.     mov    DDP1buffsize, cx
  448.     mov    di, offset driver_type
  449.     push    cs
  450.     pop    es
  451.     call    recv_find
  452.  
  453. ;    es:di->client buffer, or es:di=0 means drop the packet
  454.     mov    ax, es
  455.     or    ax, di
  456.     je    recv_pass1
  457.  
  458. ;    copy ds:si->es:di for cx bytes
  459.     push    cs
  460.     pop    ds
  461.     mov    si, offset DDP1buffer
  462.     mov    cx, DDP1buffsize
  463.     rep    movsb
  464.  
  465. ;    tell receiver copy has been made; ds:si->the packet, cx=length
  466.     push    es
  467.     pop    ds
  468.     mov    si, offset DDP1buffer
  469.     mov    cx, DDP1buffsize
  470.     call    recv_copy
  471.  
  472. recv_pass1:
  473. ;    first buffer is free for use again
  474.     mov    DDP1inuse, 00H
  475.     jmp    recv_ret
  476.  
  477.  
  478. recv_buff2:
  479.     cmp    bx, offset DDP2buffer
  480.     jne    recv_ret
  481.  
  482. ;    check if we have a client waiting for packets
  483. ;    pass to recv_find    es:di->driver_type, cx=#bytes in packet
  484.     mov    DDP2buffsize, cx
  485.     mov    di, offset driver_type
  486.     push    cs
  487.     pop    es
  488.     call    recv_find
  489.  
  490. ;    es:di->client buffer, or es:di=0 means drop the packet
  491.     mov    ax, es
  492.     or    ax, di
  493.     je    recv_pass2
  494.  
  495. ;    copy ds:si->es:di for cx bytes
  496.     push    cs
  497.     pop    ds
  498.     mov    si, offset DDP2buffer
  499.     mov    cx, DDP2buffsize
  500.     rep    movsb
  501.  
  502. ;    tell receiver copy has been made; ds:si->the packet, cx=length
  503.     push    es
  504.     pop    ds
  505.     mov    si, offset DDP2buffer
  506.     mov    cx, DDP2buffsize
  507.     call    recv_copy
  508. recv_pass2:
  509. ;    second buffer is now free for use
  510.     mov    DDP2inuse, 00H
  511.  
  512. recv_ret:
  513.     ret
  514. recv_at_upcall endp
  515.  
  516. ;*******************************************
  517.  
  518. ; Call DOS software interrupt for AppleTalk
  519. ; caller must set ds:bx -> parameter block for ATALK.SYS
  520. doATint:
  521.     int    AT_INT                ; Interrupt ATALK.SYS driver
  522.     ret
  523.  
  524.  
  525.  
  526. ;any code after this will not be kept after initialization.
  527. end_resident    label    byte
  528. ;****************************************************************************
  529.  
  530.     public    usage_msg
  531. usage_msg    db    "usage: localtlk [-n] [-d] [-w] <packet_int_no>",CR,LF,'$'
  532.  
  533.     public    copyright_msg
  534. copyright_msg    db    "Packet driver for Apple LocalTalk PC Card, version ",'0'+majver,".",'0'+version,CR,LF
  535.         db    "Portions Copyright 1990, Regents of the University of California",CR,LF,'$'
  536.  
  537. no_atalk_sys_msg:
  538.     db    "Couldn't locate ATALK.SYS -- packet driver not installed",CR,LF,'$'
  539. atalk_sys_found_msg:
  540.     db    "ATALK.SYS driver located at software interrupt ",'$'
  541. inf_nodeid_name:
  542.     db    "Attaching to AppleTalk network as node ",'$'
  543. inf_abridge_name:
  544.     db    "AppleTalk network bridge is node ",'$'
  545. ddp_failed_msg:
  546.     db    "Datagram Delivery Protocol socket open failed; return status: ",'$'
  547. ddp_wrong_socket_msg:
  548.     db    "Datagram Delivery Protocol failed; unable to aquire requested socket",CR,LF,'$'
  549. ddp_open_msg:
  550.     db    "Datagram Delivery Protocol open on socket ",'$'
  551. atalk_open_msg:
  552.     db    "Attached to AppleTalk network as (net:node:sock): ",'$'
  553. nbp_no_gateway_msg:
  554.     db    "NBP: IPGATEWAY lookup failed; return status: ",'$'
  555. nbp_ipg_addr_msg:
  556.     db    "IPGATEWAY located on AppleTalk network as (net:node:sock): ",'$'
  557. atp_no_gateway_msg:
  558.     db    "ATP: IPGATEWAY transport setup failed; return status: ",'$'
  559. ipg_gateway_err_msg:
  560.     db    "IP Gateway error: ",'$'
  561. myip_addr_msg:
  562.     db    "My IP address: ",'$'
  563. ns_ip_addr_msg:
  564.     db    "Name Server IP address: ",'$'
  565. bd_ip_addr_msg:
  566.     db    "Broadcast IP address: ",'$'
  567. fs_ip_addr_msg:
  568.     db    "File Server IP address: ",'$'
  569. opcode_msg:
  570.     db    "IPG opcode: ",'$'
  571. nbp_no_register_msg:
  572.     db    "NBP: failed, couldn't register our name; return status: ",'$'
  573. ddp_cant_recv:
  574.     db    "DDP: couldn't initiate read on socket; return status: ",'$'
  575.  
  576.  
  577. ipgateway_name:
  578.     db    01H, '=', 09H, "IPGATEWAY", 01H, '*', '0'
  579. myip_name:
  580.     db    09H, "IPADDRESS", 01H, '*', '0'
  581. myip_name_len    equ    12
  582.  
  583. ; Temporary storage for calls to print_number
  584. dtemp    dw    ?
  585.     dw    0
  586.  
  587.  
  588.     extrn    set_recv_isr: near
  589.  
  590. ;enter with si -> argument string, di -> wword to store.
  591. ;if there is no number, don't change the number.
  592.     extrn    get_number: near
  593.  
  594. ;enter with ds:dx -> argument string, ds:di -> dword to print.
  595.     extrn    print_number: near
  596.  
  597. ;enter with al = char to display
  598.     extrn    chrout: near
  599. ;enter with ax,dx holding 32 bits to display in decimal (ax holds low word)
  600.     extrn    decout: near
  601.     extrn    byteout: near
  602.     extrn    wordout: near
  603.  
  604.     public    parse_args
  605. parse_args:
  606. ;exit with nc if all went well, cy otherwise.
  607.     clc
  608.     ret
  609.  
  610.  
  611. ; Initialize our interface to the ATALK.SYS driver.
  612. ; NOTE: this initialization code is modeled after the PC/IP LocalTalk
  613. ; driver written by Dan Lanciani (ddl@harvard.harvard.edu); the PCIP
  614. ; software package can found at husc6.harvard.edu:pub/pcip/pcip.tar.Z
  615.     public    etopen
  616. etopen:
  617.     assume    ds:code
  618.  
  619. ; ATALK.SYS driver may be loaded at a software interrupt somewhere
  620. ; between 5CH and 70H. Locate ATALK.SYS driver by scanning for signature.
  621. isATLoaded:                    ; Look for ATALK.SYS driver
  622.     cld
  623.     call    ATGetInt            ; Load start of intr range
  624.     mov    dx, ax                ; Save start value in DX
  625. chkloop:
  626.     cmp    dx, 70H                ; Scanned all possible vectors?
  627.     jne    checkstring            ; No, check this vector
  628.     xor    ax, ax                ; Yes, driver not found
  629.     jmp    chksplit            ; Skip ahead to return
  630. checkstring:
  631.     mov    bx, dx                ; Load intr# for scan
  632.     shl    bx, 1                ; Multiply by 2 (for seg bytes)
  633.     shl    bx, 1                ; Multiply by 2 (for off bytes)
  634.     xor    ax, ax
  635.     mov    es, ax                ; Lowest page of memory
  636.     lds    si, es:[bx]            ; Load vector for scan intr#
  637.     mov    ax, ds                ; Load segment this scan intr#
  638.     or    ax, si                ; OR with off this scan intr#
  639.     jz    keepchecking            ; Keep checking if no bits
  640.     sub    si, 16                ; Signature is just before code
  641.     mov    di, offset driverstring        ; Load compare string
  642.     mov    cx, 9                ; Load length of compare string
  643.     push    cs
  644.     pop    es
  645.     repe    cmpsb                ; Compare ds:si to es:di
  646.     jne    keepchecking            ; Keep checking if not matched
  647.     call    ATGetInt            ; Matched, get INT# again
  648.     cmp    ax, dx                ; INT# already set properly?
  649.     jz    chksplit            ; Yes, use this INT#
  650.                         ; No, we found INT# by scanning
  651.     call    ATPatch                ; Modify code to match scan
  652.     call    ATGetInt            ; Retrieve final INT#
  653.     jmp    chksplit            ; Skip ahead to return
  654.  
  655. keepchecking:                    ; Havent found ATALK.SYS driver
  656.     inc    dx                ; Check next possible INT#
  657.     jmp    chkloop                ; Loop back to check next INT#
  658.  
  659. chksplit:                    ; Done with scan for ATALK.SYS
  660.     cmp    ax, 00H                ; ATALK.SYS driver found?
  661.     jne    atalk_sys_found            ; Yes, skip ahead to continue
  662.  
  663.     mov    dx, offset no_atalk_sys_msg    ; No, ATALK.SYS not loaded
  664.     jmp    error_wrt            ; Skip ahead to report error
  665.  
  666. atalk_sys_found:                ; ATALK.SYS driver found
  667.     push    cs                ; Used DS for another purpose
  668.     pop    ds                ; Reset DS to our data
  669.     mov    dtemp, dx            ; Report intr# of ATALK.SYS
  670.     mov    di, offset dtemp
  671.     mov    dx, offset atalk_sys_found_msg
  672.     call    print_number
  673.  
  674. ; We need to establish our Appletalk node
  675. get_our_info:                    ; Get info params from ATALK
  676.     mov    MyInfo.atd_command, AT_GETNETINFO
  677.     mov    MyInfo.atd_compfun.offs, offset noop_upcall
  678.     mov    MyInfo.atd_compfun.segm, cs
  679.     mov    bx, offset MyInfo
  680.     call    doATint
  681.  
  682.     cmp    MyInfo.atd_status, 00H        ; Already initialized?
  683.     je    get_ddp_socket            ; Yes, skip ahead
  684.  
  685.     mov    MyInfo.atd_command, AT_INIT    ; No, initialize our node
  686.     mov    MyInfo.atd_compfun.offs, offset noop_upcall
  687.     mov    MyInfo.atd_compfun.segm, cs
  688.     mov    bx, offset MyInfo
  689.     call    doATint
  690.  
  691. ; We need to establish our AppleTalk/DDP socket
  692. get_ddp_socket:                    ; Open a DDP socket
  693.     mov    DDPio.ddp_command, DDP_OPENSOCKET
  694.     mov    DDPio.ddp_compfun.offs, offset noop_upcall
  695.     mov    DDPio.ddp_compfun.segm, cs
  696.     mov    DDPio.ddp_buffptr.offs, offset preview_upcall
  697.     mov    DDPio.ddp_buffptr.segm, cs
  698.     mov    DDPio.ddp_socket, 72        ; ask for experimental sock#
  699.     mov    DDPio.ddp_type, 22        ; ask for IP socket type
  700.     mov    bx, offset DDPio            ; ds:bx-> DDP param block
  701.     call    doATint                ; ask ATALK.SYS for a socket
  702.  
  703.     cmp    DDPio.ddp_status, 00H        ; error return from ATALK.SYS?
  704.     je    chk_ddp_socket            ; no, skip ahead to continue
  705.                         ; yes, no socket for us
  706.     mov    ax, DDPio.ddp_status
  707.     mov    dtemp, ax
  708.     mov    di, offset dtemp
  709.     mov    dx, offset ddp_failed_msg
  710.     call    print_number            ; report error and stat return
  711.     jmp    error_ret
  712.  
  713. ;**** do we really require socket 72?
  714. chk_ddp_socket:                    ; check the socket we opened
  715.     cmp    DDPio.ddp_socket, 72        ; did we get the one requested?
  716.     je    ddp_ready            ; yes, socket is as expected
  717.                         ; no, but must have socket 72
  718.     mov    DDPio.ddp_command, DDP_CLOSESOCKET
  719.     mov    bx, offset DDPio
  720.     call    doATint                ; close the assigned socket
  721.  
  722.     mov    dx, offset ddp_wrong_socket_msg    ; load error msg
  723.     jmp    error_wrt            ; skip ahead to display and ret
  724.  
  725. ddp_ready:                    ; DDP socket 72 is ready
  726.     mov    DDPio.ddp_command, DDP_WRITE    ; Use param block for WRITE now
  727.  
  728. ; AppleTalk node and DDP socket have been established
  729.     mov    ax, MyInfo.inf_network
  730.     mov    word ptr dtemp, ax
  731.     mov    al, MyInfo.inf_nodeid
  732.     mov    ah, DDPio.ddp_socket
  733.     mov    byte ptr dtemp+2, al
  734.     mov    byte ptr dtemp+3, ah
  735.     mov    di, offset dtemp
  736.     mov    dx, offset atalk_open_msg
  737.     call    print_at_addr            ; display AppleTalk node info
  738.     mov    ax, 00H
  739.     mov    dtemp+2, ax
  740.  
  741. ; We need an IP gateway node
  742. nbp_ipgateway:                    ; Locate our IP gateway node
  743.     push    cs
  744.     pop    ds
  745.     mov    NBP.nbp_command, NBP_LOOKUP
  746.     mov    NBP.nbp_compfun.offs, offset noop_upcall
  747.     mov    NBP.nbp_compfun.segm, cs
  748.     mov    NBP.nbp_toget, 01H
  749.     mov    NBP.nbp_buffptr.offs, offset NBPt
  750.     mov    NBP.nbp_buffptr.segm, ds
  751.     mov    NBP.nbp_buffsize, (size NBPTuple)
  752.     mov    NBP.nbp_interval, 5
  753.     mov    NBP.nbp_retry, 12
  754.     mov    NBP.nbp_entptr.offs, offset ipgateway_name
  755.     mov    NBP.nbp_entptr.segm, ds
  756.     mov    bx, offset NBP
  757.     call    doATint                ; do name-bind lookup
  758.  
  759.     cmp    NBP.nbp_status, 00H        ; status return=error?
  760.     jne    nbp_no_gateway            ; yes, report error and exit
  761.  
  762.     cmp    NBP.nbp_toget, 01H
  763.     je    atp_setup
  764.  
  765. nbp_no_gateway:                    ; NBP lookup failed
  766.     mov    ax, NBP.nbp_status
  767.     mov    dtemp, ax
  768.     mov    di, offset dtemp
  769.     mov    dx, offset nbp_no_gateway_msg    ; display error msg
  770.     call    print_number
  771.  
  772.     mov    DDPio.ddp_command, DDP_CLOSESOCKET
  773.     mov    bx, offset DDPio
  774.     call    doATint                ; close the assigned socket
  775.  
  776.     jmp    error_ret            ; skip ahead to return
  777.  
  778. ; We need a transport layer to the IP gateway
  779. atp_setup:
  780.     mov    cx, (size AddrBlk)        ; MyGateway = NBPt.tup_addr
  781.     push    cs
  782.     pop    es
  783.     mov    si, offset NBPt.tup_address
  784.     mov    di, offset MyGateway
  785.     rep    movsb
  786.  
  787.     mov    di, offset NBPt.tup_address    ; Display our gateway node
  788.     mov    dx, offset nbp_ipg_addr_msg
  789.     call    print_at_addr
  790.  
  791.     mov    BDS.bds_buffptr.offs, offset IPG
  792.     mov    BDS.bds_buffptr.segm, ds
  793.     mov    BDS.bds_buffsize, (size IPGInfo)
  794.  
  795.     mov    ATP.atp_command, ATP_SEND_REQUEST
  796.     mov    ATP.atp_compfun.offs, offset noop_upcall
  797.     mov    ATP.atp_compfun.segm, cs
  798.     mov    cx, (size AddrBlk)        ; ATP.atp_addr = NBPt.tup_addr
  799.     push    cs
  800.     pop    es
  801.     mov    si, offset NBPt.tup_address
  802.     mov    di, offset ATP.atp_addrblk
  803.     rep    movsb
  804.     mov    ATP.atp_buffptr.offs, offset IPG
  805.     mov    ATP.atp_buffptr.segm, ds
  806.     mov    ATP.atp_buffsize, (size IPGInfo)
  807.     mov    ATP.atp_interval, 05H
  808.     mov    ATP.atp_retry, 05H
  809.     mov    ATP.atp_flags, XO_BIT
  810.     mov    ATP.atp_bdsbuffs, 01H
  811.     mov    ATP.atp_bdsptr.offs, offset BDS
  812.     mov    ATP.atp_bdsptr.segm, ds
  813.     mov    bx, offset ATP
  814.     call    doATint
  815.  
  816.     cmp    ATP.atp_status, 00H        ; status return=error?
  817.     jne    atp_no_gateway            ; yes, report error and exit
  818.  
  819.     cmp    ATP.atp_bdsbuffs, 01H
  820.     je    chk_ip_opcode
  821.  
  822. atp_no_gateway:                    ; ATP setup failed
  823.     mov    ax, ATP.atp_status
  824.     mov    dtemp, ax
  825.     mov    di, offset dtemp
  826.     mov    dx, offset atp_no_gateway_msg    ; display error msg
  827.     call    print_number
  828.  
  829.     mov    DDPio.ddp_command, DDP_CLOSESOCKET
  830.     mov    bx, offset DDPio
  831.     call    doATint                ; close the assigned socket
  832.  
  833.     jmp    error_ret            ; skip ahead to return
  834.  
  835. chk_ip_opcode:
  836.     cmp    IPG.ipg_opcode.offs, IPG_ERROR    ; opcode is 32 bit
  837.     jne    save_ipaddr            ; check one word at a time
  838.     cmp    IPG.ipg_opcode.segm, IPG_ERROR    ; error from IP gateway?
  839.     jne    save_ipaddr            ; no, transport established
  840.                         ; yes, ATP setup failed
  841.     mov    dx, offset ipg_gateway_err_msg    ; display IPG error msg
  842.     mov    ah, 9
  843.     int    21H
  844.     mov    dx, offset IPG.ipg_string
  845.     mov    ah, 9
  846.     int    21H
  847.     mov    al, 13                ; display CR-LF
  848.     call    chrout
  849.     mov    al, 10
  850.     call    chrout
  851.  
  852.     mov    DDPio.ddp_command, DDP_CLOSESOCKET
  853.     mov    bx, offset DDPio
  854.     call    doATint                ; close the assigned socket
  855.  
  856.     jmp    error_ret
  857.  
  858. ; AppleTalk/IP transport layer established
  859. save_ipaddr:
  860.     mov    dx, offset myip_addr_msg
  861.     mov    di, offset IPG.ipg_ipaddress
  862.     call    print_ip_addr
  863.  
  864.     mov    dx, offset ns_ip_addr_msg
  865.     mov    di, offset IPG.ipg_ipname
  866.     call    print_ip_addr
  867.  
  868.     mov    dx, offset bd_ip_addr_msg
  869.     mov    di, offset IPG.ipg_ipbroad
  870.     call    print_ip_addr
  871.  
  872.     mov    dx, offset fs_ip_addr_msg
  873.     mov    di, offset IPG.ipg_ipfile
  874.     call    print_ip_addr
  875.  
  876. ; We need to register ourself with the AppleTalk Name Binding Agent
  877. nbp_register_ourself:
  878.     mov    al, MyInfo.inf_nodeid
  879.     mov    NBPtable.tab_entry.tup_address.ablk_nodeid, al
  880.     mov    al, DDPio.ddp_socket
  881.     mov    NBPtable.tab_entry.tup_address.ablk_socket, al
  882.  
  883.     ; print our IP address in our NBP table entry
  884.     mov    bx, offset NBPtable.tab_entry.tup_name
  885.     inc    bx
  886.     xor    dx, dx
  887.     mov    dl, byte ptr IPG.ipg_ipaddress
  888.     call    decstr
  889.     mov    al, dot_char
  890.     mov    byte ptr ds:[bx], al
  891.     inc    bx
  892.     mov    dl, byte ptr IPG.ipg_ipaddress+1
  893.     call    decstr
  894.     mov    al, dot_char
  895.     mov    ds:[bx], al
  896.     inc    bx
  897.     mov    dl, byte ptr IPG.ipg_ipaddress+2
  898.     call    decstr
  899.     mov    al, dot_char
  900.     mov    ds:[bx], al
  901.     inc    bx
  902.     mov    dl, byte ptr IPG.ipg_ipaddress+3
  903.     call    decstr
  904.  
  905.     mov    ax, bx
  906.     sub    ax, offset NBPtable.tab_entry.tup_name
  907.     sub    ax, 1
  908.     mov    NBPtable.tab_entry.tup_name, al
  909.  
  910.     mov    cx, myip_name_len    ; append IPADDR command to our IP
  911.     push    cs
  912.     pop    es
  913.     mov    si, offset myip_name    ; ds:si -> source
  914.     mov    di, bx            ; es:di -> dest
  915.     rep    movsb
  916.  
  917.     ; Register our name with NBP agent
  918.     mov    NBP.nbp_command, NBP_REGISTER
  919.     mov    NBP.nbp_compfun.offs, offset noop_upcall
  920.     mov    NBP.nbp_compfun.segm, cs
  921.     mov    NBP.nbp_buffptr.offs, offset NBPtable
  922.     mov    NBP.nbp_buffptr.segm, ds
  923.     mov    NBP.nbp_interval, 01H
  924.     mov    NBP.nbp_retry, 03H
  925.     mov    bx, offset NBP
  926.     call    doATint
  927.  
  928.     cmp    NBP.nbp_status, 00H
  929.     je    atinit_done
  930.  
  931. nbp_no_register:
  932.     mov    ax, NBP.nbp_status
  933.     mov    dtemp, ax
  934.     mov    di, offset dtemp
  935.     mov    dx, offset nbp_no_register_msg    ; display error msg
  936.     call    print_number
  937.  
  938.     mov    DDPio.ddp_command, DDP_CLOSESOCKET
  939.     mov    bx, offset DDPio
  940.     call    doATint                ; close the assigned socket
  941.  
  942.     jmp    error_ret            ; skip ahead to return
  943.  
  944. ;**** LocalTalk PC Card initialized, ready to TSR
  945. atinit_done:
  946.     push    cs
  947.     pop    ds
  948.     mov    dx, offset end_resident
  949.     clc
  950.     ret
  951.  
  952. ;**** Got an error while initializing LocalTalk PC Card
  953. error_wrt:                    ; Display an error message
  954.     push    cs                ; Get our data segment back
  955.     pop    ds
  956.     mov    ah, 9
  957.     int    21H
  958.  
  959. error_ret:                    ; Board not initialized
  960.     stc
  961.     ret
  962.  
  963.     public    print_parameters
  964. print_parameters:
  965. ;echo our command-line parameters
  966.     ret
  967.  
  968. ;*******************************************
  969.  
  970. ; Modify ATALK.SYS interrupt number in doATint code (self-modifying code!)
  971. ATPatch:
  972.     mov    al, dl                ; Load new interrupt number
  973.     push    cs
  974.     pop    es
  975.     lea    bx, doATint            ; es:bx=offset of doATint code
  976.     inc    bx                ; skip to operator for INT
  977.     mov    es:[bx], al            ; modify the code
  978.     ret
  979.  
  980. ; Get ATALK.SYS interrupt number
  981. ATGetInt:
  982.     push    cs
  983.     pop    es
  984.     lea    bx, doATint            ; es:bx=offset of doATint code
  985.     inc    bx                ; skip to operator for INT
  986.     mov    al, es:[bx]            ; load operator for INT
  987.     xor    ah, ah                ; zero high byte
  988.     ret                    ; return INT# to caller
  989.  
  990. ;*******************************************
  991.  
  992. ;*******************************************
  993.  
  994. ; caller must set ds:si -> dest for string, dx 16-bit value to sprint
  995. decstr:
  996.     mov    di,dx
  997.     cmp    dx, 0
  998.     jne    decstr_nonzero
  999.     mov    al,'0'            ;yes - easier to just print it, than
  1000.     jmp    chrstr            ;  to eliminate all but the last zero.
  1001. decstr_nonzero:
  1002.  
  1003.     xor    ax,ax            ;start with all zeroes in al,bx,bp
  1004.     mov    bp,ax
  1005.  
  1006.     mov    cx,16            ;16 bits in one 16 bit registers.
  1007. decstr_1:
  1008.     rcl    di,1
  1009.     xchg    bp,ax
  1010.     call    addbit
  1011.     xchg    bp,ax
  1012.     adc    al,al
  1013.     daa
  1014.     loop    decstr_1
  1015.  
  1016.     mov    cl,'0'            ;prepare to eliminate leading zeroes.
  1017.     call    bytestr            ;output the first two.
  1018.     mov    ax,bp
  1019.     jmp    wordstr            ;output the next four.
  1020.  
  1021. addbit:    adc    al,al
  1022.     daa
  1023.     xchg    al,ah
  1024.     adc    al,al
  1025.     daa
  1026.     xchg    al,ah
  1027.     ret
  1028.  
  1029. ;print the char in al at ds:bx
  1030. chrstr:
  1031.     mov    byte ptr [bx], al
  1032.     inc    bx
  1033.     ret
  1034.  
  1035. wordstr:
  1036.     push    ax
  1037.     mov    al,ah
  1038.     call    bytestr
  1039.     pop    ax
  1040. bytestr:
  1041.     mov    ah,al
  1042.     shr    al,1
  1043.     shr    al,1
  1044.     shr    al,1
  1045.     shr    al,1
  1046.     call    digstr
  1047.     mov    al,ah
  1048. digstr:
  1049.     and    al,0fh
  1050.     add    al,90h    ;binary digit to ascii hex digit.
  1051.     daa
  1052.     adc    al,40h
  1053.     daa
  1054.     cmp    al,cl            ;leading zero?
  1055.     je    digstr_1
  1056.     mov    cl,-1            ;no more leading zeros.
  1057.     jmp    chrstr
  1058. digstr_1:
  1059.     ret
  1060.  
  1061. ; caller must set ds:dx -> argument string, ds:di -> AddrBlk struct
  1062. print_at_addr:
  1063. ;enter with dx -> dollar terminated name of number, di ->dword.
  1064. ;exit with the number printed and the cursor advanced to the next line.
  1065.     mov    ah,9            ;print the name of the number.
  1066.     int    21h
  1067.     mov    ax, [di].ablk_network    ;print the network number
  1068.     mov    dx, 00H
  1069.     push    di
  1070.     call    decout
  1071.     pop    di
  1072.     mov    al, ':'
  1073.     call    chrout
  1074.     xor    ax, ax
  1075.     mov    al, [di].ablk_nodeid    ; print the nodeid number
  1076.     push    di
  1077.     call    decout
  1078.     pop    di
  1079.     mov    al, ':'
  1080.     call    chrout
  1081.     xor    ax, ax
  1082.     mov    al, [di].ablk_socket    ; print the socket number
  1083.     call    decout
  1084.     mov    al,CR
  1085.     call    chrout
  1086.     mov    al,LF
  1087.     call    chrout
  1088.     ret
  1089.  
  1090. ; caller must set ds:dx -> argument string, ds:di -> 32 bit ip address
  1091. print_ip_addr:
  1092. ;enter with dx -> dollar terminated name of number, di ->dword.
  1093. ;exit with the number printed and the cursor advanced to the next line.
  1094.     mov    ah,9            ;print the name of the number.
  1095.     int    21h
  1096.     mov    al, '['
  1097.     call    chrout
  1098.     xor    ax, ax
  1099.     mov    al, [di]        ;print first byte in decimal.
  1100.     mov    dx, 00H
  1101.     push    di
  1102.     call    decout
  1103.     pop    di
  1104.     mov    al, '.'
  1105.     call    chrout
  1106.     xor    ax, ax
  1107.     mov    al, [di+1]        ; print second byte in decimal
  1108.     push    di
  1109.     call    decout
  1110.     pop    di
  1111.     mov    al, '.'
  1112.     call    chrout
  1113.     xor    ax, ax
  1114.     mov    al, [di+2]        ; print third byte in decimal
  1115.     push    di
  1116.     call    decout
  1117.     pop    di
  1118.     mov    al, '.'
  1119.     call    chrout
  1120.     xor    ax, ax
  1121.     mov    al, [di+3]        ; print fourth byte in decimal
  1122.     call    decout
  1123.     mov    al, ']'
  1124.     call    chrout
  1125.     mov    al,CR
  1126.     call    chrout
  1127.     mov    al,LF
  1128.     call    chrout
  1129.     ret
  1130.  
  1131. code    ends
  1132.  
  1133.     end
  1134.