home *** CD-ROM | disk | FTP | other *** search
- version equ 3
-
- include defs.asm
-
- ; PC/FTP Packet Driver source, conforming to version 1.09 of the spec
- ; Katie Stevens (dkstevens@ucdavis.edu)
- ; Computing Services, University of California, Davis
- ; Portions (C) Copyright 1988 Regents of the University of California
-
- ; This program is free software; you can redistribute it and/or modify
- ; it under the terms of the GNU General Public License as published by
- ; the Free Software Foundation, version 1.
- ;
- ; This program is distributed in the hope that it will be useful,
- ; but WITHOUT ANY WARRANTY; without even the implied warranty of
- ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- ; GNU General Public License for more details.
-
- ; Change History
- ;
- ; 05-90 ks Katie Stevens (dkstevens@ucdavis.edu):
- ; - Created
- ; 07-19-91 jgn Jim Noble (noble_jim@po.gis.prc.com):
- ; - Added Change History and documented changes
- ; - Fixed a bug that caused AppleTalk network numbers to
- ; be byte-swapped when printed
- ; - Fixed a bug that caused the wrong buffer address to
- ; be passed to the packet receiver upcall routine
- ; - Made changes in the driver information structure to
- ; match LocalTalk: size of MAC-layer address, MTU,
- ; and multicast buffer size
- ; - Changed the packet buffer sizes from 1024 to 586,
- ; the maximum amount of data in a DDP packet
- ; - Commented-out the noop_upcall completion routine and
- ; changed the completion routine address passed to
- ; the AppleTalk driver to 0000:0000 for all driver
- ; calls
- ; - Set the status field to -1 prior to the GetNetInfo
- ; AppleTalk driver call as per the recommendation of
- ; the driver interface spec.
- ; - Added structure definitions for short and long
- ; format DDP packets and used them when adding a
- ; check to ensure that received packets are IP packets
- ; 07-22-91 jgn Jim Noble (noble_jim@po.gis.prc.com):
- ; - Fixed a bug that would prevent the packet driver
- ; from initializing with a static address if there
- ; were no dynamic addresses available
- ; 07-23-91 jgn Jim Noble (noble_jim@po.gis.prc.com):
- ; - Added the optional IP address to the usage message
- ; - Incremented version to 3
- ;
-
- code segment word public
- assume cs:code, ds:code
-
- ; Definitions specific to the ATALK.SYS driver for PC LocalTalk cards:
- ; these include Apple LocalTalk PC Card, Sun/TOPS FlashCard
- ; For a complete description of the LocalTalk commands, structures and
- ; methods used in this driver, please refer to Apple APDA document #M7055,
- ; LocalTalk PC Card and Driver Preliminary Notes.
-
- driverstring db 'AppleTalk', 0 ; ATALK.SYS signature string
- dot_char db '.', 0 ; for IP address display
-
- AT_INT equ 5CH ; Software int# for ATALK.SYS
-
- ; General ATALK.SYS driver commands
- AT_INIT equ 01H ; Initialize driver software
- AT_GETNETINFO equ 03H ; Get driver info
-
- ; Datagram Delivery Protocol commands for ATALK.SYS driver
- DDP_OPENSOCKET equ 20H
- DDP_CLOSESOCKET equ 21H
- DDP_WRITE equ 22H
- DDP_READ equ 23H
- DDP_CANCEL equ 24H
-
- ; Name Binding Protocol commands for ATALK.SYS driver
- NBP_REGISTER equ 30H
- NBP_REMOVE equ 31H
- NBP_LOOKUP equ 32H
- NBP_CONFIRM equ 33H
- NBP_CANCEL equ 34H
-
- ; AppleTalk Transaction Protocol commands for ATALK.SYS driver
- ATP_SEND_REQUEST equ 42H
-
- ; ATALK.SYS command qualifiers
- ASYNC_MASK equ 8000H ; Start command, then return
- INTR_MASK equ 4000H ; Wait for intr service to complete
-
- XO_BIT equ 20H ; ATP - exactly once transaction
-
- ; Structure for short format DDP packet [jgn]
- DDPshort struc
- lap_dst db ? ; destination node
- lap_src db ? ; source node
- lap_type db ? ; 1 for short format DDP packet
- ddps_len dw ? ; packet length
- ddps_dskt db ? ; destination socket
- ddps_sskt db ? ; source socket
- ddps_type db ? ; 22 for IP packets
- DDPshort ends
-
- ; Structure for long format DDP packet [jgn]
- DDPlong struc
- lap_dst db ? ; destination node
- lap_src db ? ; source node
- lap_type db ? ; 2 for long format DDP packets
- ddpl_len dw ? ; packet length
- ddpl_chksum dw ? ; checksum
- ddpl_dnet dw ? ; destination network
- ddpl_snet dw ? ; source network
- ddpl_dnode db ? ; destination node
- ddpl_snode db ? ; source node
- ddpl_dskt db ? ; destination socket
- ddpl_sskt db ? ; source socket
- ddpl_type db ? ; 22 for IP packets
- DDPlong ends
-
- ; Structure for AppleTalk node addressing
- AddrBlk struc
- ablk_network dw 0
- ablk_nodeid db 0
- ablk_socket db 0
- AddrBlk ends
-
- ; Structure for general calls to AppleTalk driver (ATALK.SYS)
- InfoParams struc
- atd_command dw AT_GETNETINFO
- atd_status dw 0
- atd_compfun segmoffs <>
- inf_network dw 0
- inf_nodeid db 0
- inf_abridge db 0
- inf_config dw 0
- inf_buffptr segmoffs <>
- inf_buffsize dw 0
- InfoParams ends
- ; Parameter block for general calls to AppleTalk driver (ATALK.SYS)
- MyInfo InfoParams <>
-
- ; Address block for our gateway
- MyGateway AddrBlk <>
-
- ; Structure for calls to AppleTalk driver (ATALK.SYS) for Datagram
- ; Delivery Protocol (DDP) service
- DDPParams struc
- ddp_command dw 0
- ddp_status dw 0
- ddp_compfun segmoffs <>
- ddp_addr AddrBlk <>
- ddp_socket db 0
- ddp_type db 0
- ddp_buffptr segmoffs <>
- ddp_buffsize dw 0
- ddp_chksum db 0
- DDPParams ends
- ; Parameter blocks for AppleTalk DDP access
- DDPio DDPParams <> ; Write on DDP socket
- ; 2 buffers for packet receive from ATALK.SYS
- DDP1inuse db 0 ; Buffer occupied flag
- DDP1buffsize dw 0 ; Buffer length during reads
- DDP1buffer db 586 dup (0) ; Buffer for DDP read [jgn]
- DDP2inuse db 0 ; 2nd Buffer occupied flag
- DDP2buffsize dw 0 ; 2nd Buffer length during reads
- DDP2buffer db 586 dup (0) ; 2nd Buffer for DDP read [jgn]
-
- ; Structure for calls to AppleTalk driver (ATALK.SYS) for Name
- ; Binding Protocol (NBP) service
- NBPParams struc
- nbp_command dw 0
- nbp_status dw 0
- nbp_compfun segmoffs <>
- nbp_addr AddrBlk <>
- nbp_toget dw 0
- nbp_buffptr segmoffs <>
- nbp_buffsize dw 0
- nbp_interval db 0
- nbp_retry db 0
- nbp_entptr segmoffs <>
- NBPParams ends
- ; Parameter block for AppleTalk NBP access
- NBP NBPParams <>
-
- ; Structure for name-to-address bind entries
- NBPTuple struc
- tup_address AddrBlk <>
- tup_enum db 0
- tup_name db 99 dup(0)
- NBPTuple ends
- ; Name Binding Tuple for our IP gateway
- NBPt NBPTuple <>
-
- ; Structure for name-to-address table
- NBPEntry struc
- tab_next segmoffs <>
- tab_entry NBPTuple <>
- NBPEntry ends
- NBPtable NBPEntry <>
-
- ; Structure for calls to AppleTalk driver (ATALK.SYS) for AppleTalk
- ; Transaction Protocol (ATP) service
- ATPParams struc
- atp_command dw 0
- atp_status dw 0
- atp_compfun segmoffs <>
- atp_addrblk AddrBlk <>
- atp_socket db 0
- atp_fill db 0
- atp_buffptr segmoffs <>
- atp_buffsize dw 0
- atp_interval db 0
- atp_retry db 0
- atp_flags db 0
- atp_seqbit db 0
- atp_tranid dw 0
- atp_userbytes db 4 dup(0)
- atp_bdsbuffs db 0
- atp_bdsresps db 0
- atp_bdsptr segmoffs <>
- ATPParams ends
- ; Parameter block for AppleTalk ATP access
- ATP ATPParams <>
-
- ; Structure for BDS elements
- BDSElement struc
- bds_buffptr segmoffs <>
- bds_buffsize dw 0
- bds_datasize dw 0
- bds_userbytes db 4 dup(0)
- BDSElement ends
- ; Parameter block for our BDS element
- BDS BDSElement <>
-
- ; Struct for IP gateway information
- IPGInfo struc
- ipg_opcode db 0,0,0,1 ; IPGP_ASSIGN
- ipg_ipaddress dd 0 ; our IP address
- ipg_ipname dd 0 ; nameserver IP address
- ipg_ipbroad dd 0 ; broadcast IP address
- ipg_ipfile dd 0 ; file server IP address
- ipg_ipother dd 4 dup (0)
- ipg_string db 128 dup (0), '$'
- IPGInfo ends
- ; Parameter block for info about our IP gateway
- IPG IPGInfo <>
-
- IPG_ERROR equ -1
-
- static_address db 0, 0, 0, 0
- use_static db 0
- test_address db 0, 0, 0, 0
- temp_4bytes db 0, 0, 0, 0
-
- ; End of Appletalk parameter definitions
-
- ; The following values may be overridden from the command line.
- ; If they are omitted from the command line, these defaults are used.
-
- public int_no
- int_no db 0,0,0,0 ;must be four bytes long for get_number.
-
- public driver_class, driver_type, driver_name, driver_function, parameter_list
- driver_class db 5,0 ;from the packet spec
- driver_type db 1 ;from the packet spec
- driver_name db 'LocalTalk',0 ;name of the driver.
- driver_function db 2
- parameter_list label byte
- db 1 ;major rev of packet driver
- db 9 ;minor rev of packet driver
- db 14 ;length of parameter list
- db 4 ;length of MAC-layer address [jgn]
- dw 586 ;MTU, including MAC headers [jgn]
- dw 0 ;buffer size of multicast addrs [jgn]
- dw 0 ;(# of back-to-back MTU rcvs) - 1
- dw 0 ;(# of successive xmits) - 1
- int_num dw 0 ;Interrupt # to hook for post-EOI
- ;processing, 0 == none,
-
- public rcv_modes
- rcv_modes dw 4 ;number of receive modes in our table.
- dw 0,0,0,rcv_mode_3
-
- public bad_command_intercept
- bad_command_intercept:
- ;called with ah=command, unknown to the skeleton.
- ;exit with nc if okay, cy, dh=error if not.
- mov dh,BAD_COMMAND
- stc
- ret
-
- public as_send_pkt
- ; The Asynchronous Transmit Packet routine.
- ; Enter with es:di -> i/o control block, ds:si -> packet, cx = packet length,
- ; interrupts possibly enabled.
- ; Exit with nc if ok, or else cy if error, dh set to error number.
- ; es:di and interrupt enable flag preserved on exit.
- as_send_pkt:
- ret
-
- public drop_pkt
- ; Drop a packet from the queue.
- ; Enter with es:di -> iocb.
- drop_pkt:
- assume ds:nothing
- ret
-
- public xmit
- ; Process a transmit interrupt with the least possible latency to achieve
- ; back-to-back packet transmissions.
- ; May only use ax and dx.
- xmit:
- assume ds:nothing
- ret
-
- public send_pkt
- send_pkt:
- ;enter with es:di->upcall routine, (0:0) if no upcall is desired.
- ; (only if the high-performance bit is set in driver_function)
- ;enter with ds:si -> packet, cx = packet length.
- ;if we're a high-performance driver, es:di -> upcall.
- ;exit with nc if ok, or else cy if error, dh set to error number.
- assume ds:nothing
- ; send packet to AppleTalk/DDP/IP gateway
- ; load info about the packet we are sending
- mov DDPio.ddp_buffptr.offs, si
- mov DDPio.ddp_buffptr.segm, ds ; DDPio.buffptr -> IP packet
- mov DDPio.ddp_buffsize, cx ; DDPio.buffsize = packet len
-
- ; send all packets to the IP gateway
- mov cx, (size AddrBlk) ; DDPio.ddp_addr = MyGateway
- mov ax, cs
- mov ds, ax
- mov es, ax
- mov si, offset MyGateway
- mov di, offset DDPio.ddp_addr
- rep movsb
-
- mov bx, offset DDPio
- call doATint ; Ask ATALK.SYS to send packet
-
- cmp DDPio.ddp_status, 00H ; Packet sent okay?
- je send_ret ; Yes, status is good
- ; No, status gives error
- send_err:
- call count_out_err
- mov dh, CANT_SEND ; set error flag
- stc
- ret
-
- send_ret:
- clc ; packet sent successfully
- ret
-
- public set_address
- set_address:
- ;enter with ds:si -> Ethernet address, CX = length of address.
- ;exit with nc if okay, or cy, dh=error if any errors.
- assume ds:nothing
- mov dh, BAD_COMMAND
- stc
- ret
-
-
- rcv_mode_3:
- ;receive mode 3 is the only one we support, so we don't have to do anything.
- ret
-
-
- public set_multicast_list
- set_multicast_list:
- ;enter with ds:si ->list of multicast addresses, ax = number of addresses,
- ; cx = number of bytes.
- ;return nc if we set all of them, or cy,dh=error if we didn't.
- mov dh,NO_MULTICAST
- stc
- ret
-
-
- public terminate
- terminate:
- push ds
- push cs
- pop ds
-
- terminate_write:
- ; close the DDP socket
- mov DDPio.ddp_command, DDP_CLOSESOCKET
- mov bx, offset DDPio
- call doATint
-
- mov NBP.nbp_command, NBP_REMOVE
- mov NBP.nbp_entptr.offs, offset NBPtable.tab_entry.tup_name
- mov NBP.nbp_entptr.segm, ds
- mov bx, offset NBP
- call doATint
-
- pop ds
- ret
-
- public reset_interface
- reset_interface:
- ;reset the interface.
- assume ds:code
- ret
-
-
- ;called when we want to determine what to do with a received packet.
- ;enter with cx = packet length, es:di -> packet type, dl = packet class.
- extrn recv_find: near
-
- ;called after we have copied the packet into the buffer.
- ;enter with ds:si ->the packet, cx = length of the packet.
- extrn recv_copy: near
-
- ;call this routine to schedule a subroutine that gets run after the
- ;recv_isr. This is done by stuffing routine's address in place
- ;of the recv_isr iret's address. This routine should push the flags when it
- ;is entered, and should jump to recv_exiting_exit to leave.
- ;enter with ax = address of routine to run.
- extrn schedule_exiting: near
-
- ;recv_exiting jumps here to exit, after pushing the flags.
- extrn recv_exiting_exit: near
-
- extrn count_in_err: near
- extrn count_out_err: near
-
- public recv
- recv:
- ;called from the recv isr. All registers have been saved, and ds=cs.
- ;Upon exit, the interrupt will be acknowledged.
- ;NOTE: this packet driver merely makes calls to another hardware
- ;driver, ATALK.SYS. ATALK.SYS handles the hardware interrupt service;
- ;ATALK.SYS then calls this packet driver with FAR subroutine calls.
- ;the ATALK.SYS FAR subroutine is recv_at_upcall
- assume ds:nothing
- ret
-
- ;*******************************************
-
- ; [jgn] Null completion routine is not needed. Just specify 0000:0000 as the
- ; address of the completion routine for no call.
- ;
- ; NULL completion routine for ATALK.SYS drivers calls
- ;noop_upcall proc far
- ; ret
- ;noop_upcall endp
-
- ;First half routine for DDP socket.
- ;ATALK.SYS calls this routine when a packet is received.
- ;ATALK.SYS assumes we are a far procedure.
- ; AH = socket
- ; CX = size of data packet
- ; DS:BX = address of buffer
- preview_upcall proc far
- assume ds:nothing
-
- ; maximum packet we can receive is 586 bytes [jgn]
- cmp cx, 586 ; Max size of DDP data field [jgn]
- ja preview_drop
-
- ; Is it an IP packet? DDP type should be 22 [jgn]
- cmp byte ptr ds:[bx].lap_type, 1 ; Is it a short DDP packet?
- jne ddp_long ; No, must be long DDP
- cmp byte ptr ds:[bx].ddps_type, 22 ; Is it an IP packet?
- jne preview_drop ; No, refuse packet
- jmp preview_buff1
- ddp_long:
- cmp byte ptr ds:[bx].ddpl_type, 22 ; Is it an IP packet?
- jne preview_drop ; No, refuse packet
-
- preview_buff1:
- cmp DDP1inuse, 00H
- jne preview_buff2
- mov DDP1inuse, 01H
-
- ; repeat buffer size back to ATALK.SYS in CX
- ; ask ATALK.SYS driver to pass us the buffer at DS:BX
- ; tell ATALK.SYS address of 2nd half routine in ES:DX
- movseg ds,cs
- mov bx, offset DDP1buffer ; ds:bx->buffer
- movseg es,cs
- mov dx, offset recv_at_upcall ; es:dx->2nd half routine
- jmp preview_ret
-
- preview_buff2:
- cmp DDP2inuse, 00H
- jne preview_drop
- mov DDP2inuse, 01H
-
- ; repeat buffer size back to ATALK.SYS in CX
- ; ask ATALK.SYS driver to pass us the buffer at DS:BX
- ; tell ATALK.SYS address of 2nd half routine in ES:DX
- movseg ds,cs
- mov bx, offset DDP2buffer ; ds:bx->buffer
- movseg es,cs
- mov dx, offset recv_at_upcall ; es:dx->2nd half routine
- jmp preview_ret
-
-
- preview_drop:
- ; ask ATALK.SYS to drop the packet
- call count_in_err
- mov cx, 00h
-
- preview_ret:
- ret
- preview_upcall endp
-
- ;Second half routine for DDP socket.
- ;ATALK.SYS calls this routine when the packet has been copied to our buffer.
- ;ATALK.SYS assumes we are a far procedure.
- ; CX = size of data packet
- ; DS:BX = address of buffer
- recv_at_upcall proc far
- assume ds:nothing
-
- recv_buff1:
- cmp bx, offset DDP1buffer
- jne recv_buff2
-
- ; check if we have a client waiting for packets
- ; pass to recv_find es:di->driver_type, cx=#bytes in packet
- mov DDP1buffsize, cx
- mov di, offset driver_type
- movseg es,cs
- mov dl,cs:driver_class
- call recv_find
-
- ; es:di->client buffer, or es:di=0 means drop the packet
- mov ax, es
- or ax, di
- je recv_pass1
-
- ; copy ds:si->es:di for cx bytes
- push es ; save the client buffer
- push di ; address (es:di) [jgn]
- movseg ds,cs
- mov si, offset DDP1buffer
- mov cx, DDP1buffsize
- rep movsb
-
- ; tell receiver copy has been made; ds:si->the packet, cx=length
- pop si ; restore the client buffer
- pop ds ; address into ds:si [jgn]
- mov cx, DDP1buffsize
- call recv_copy
-
- recv_pass1:
- ; first buffer is free for use again
- mov DDP1inuse, 00H
- jmp recv_ret
-
-
- recv_buff2:
- cmp bx, offset DDP2buffer
- jne recv_ret
-
- ; check if we have a client waiting for packets
- ; pass to recv_find es:di->driver_type, cx=#bytes in packet
- mov DDP2buffsize, cx
- mov di, offset driver_type
- movseg es,cs
- call recv_find
-
- ; es:di->client buffer, or es:di=0 means drop the packet
- mov ax, es
- or ax, di
- je recv_pass2
-
- ; copy ds:si->es:di for cx bytes
- push es ; save the client buffer
- push di ; address (es:di) [jgn]
- movseg ds,cs
- mov si, offset DDP2buffer
- mov cx, DDP2buffsize
- rep movsb
-
- ; tell receiver copy has been made; ds:si->the packet, cx=length
- ; push es
- pop si ; restore the client buffer
- pop ds ; address into ds:si [jgn]
- ; mov si, offset DDP2buffer
- mov cx, DDP2buffsize
- call recv_copy
- recv_pass2:
- ; second buffer is now free for use
- mov DDP2inuse, 00H
-
- recv_ret:
- ret
- recv_at_upcall endp
-
- ;*******************************************
-
- ; Call DOS software interrupt for AppleTalk
- ; caller must set ds:bx -> parameter block for ATALK.SYS
- doATint:
- int AT_INT ; Interrupt ATALK.SYS driver
- ret
-
-
-
- public timer_isr
- timer_isr:
- ;if the first instruction is an iret, then the timer is not hooked
- iret
-
- ;any code after this will not be kept after initialization. Buffers
- ;used by the program, if any, are allocated from the memory between
- ;end_resident and end_free_mem.
- public end_resident,end_free_mem
- end_resident label byte
- end_free_mem label byte
- ;****************************************************************************
-
- public usage_msg
- usage_msg db "usage: localtlk [options] <packet_int_no> [ <IP address> ]",CR,LF,'$' ; [jgn]
-
- public copyright_msg
- copyright_msg db "Packet driver for Apple LocalTalk PC Card, version ",'0'+(majver / 10),'0'+(majver mod 10),".",'0'+version,CR,LF
- db "Portions Copyright 1990, Regents of the University of California",CR,LF,'$'
-
- no_atalk_sys_msg:
- db "Couldn't locate ATALK.SYS -- packet driver not installed",CR,LF,'$'
- atalk_sys_found_msg:
- db "ATALK.SYS driver located at software interrupt ",'$'
- inf_nodeid_name:
- db "Attaching to AppleTalk network as node ",'$'
- inf_abridge_name:
- db "AppleTalk network bridge is node ",'$'
- ddp_failed_msg:
- db "Datagram Delivery Protocol socket open failed; return status: ",'$'
- ddp_wrong_socket_msg:
- db "Datagram Delivery Protocol failed; unable to aquire requested socket",CR,LF,'$'
- ddp_open_msg:
- db "Datagram Delivery Protocol open on socket ",'$'
- atalk_open_msg:
- db "Attached to AppleTalk network as (net:node:sock): ",'$'
- nbp_no_gateway_msg:
- db "NBP: IPGATEWAY lookup failed; return status: ",'$'
- nbp_ipg_addr_msg:
- db "IPGATEWAY located on AppleTalk network as (net:node:sock): ",'$'
- atp_no_gateway_msg:
- db "ATP: IPGATEWAY transport setup failed; return status: ",'$'
- ipg_gateway_err_msg:
- db "IP Gateway error: ",'$'
- myip_addr_msg:
- db "My IP address: ",'$'
- ns_ip_addr_msg:
- db "Name Server IP address: ",'$'
- bd_ip_addr_msg:
- db "Broadcast IP address: ",'$'
- fs_ip_addr_msg:
- db "File Server IP address: ",'$'
- opcode_msg:
- db "IPG opcode: ",'$'
- nbp_no_register_msg:
- db "NBP: failed, couldn't register our name; return status: ",'$'
- ddp_cant_recv:
- db "DDP: couldn't initiate read on socket; return status: ",'$'
- test_arg_msg:
- db "Test IP arg parsing: ",'$'
- null_msg db '$'
-
- ipgateway_name:
- db 01H, '=', 09H, "IPGATEWAY", 01H, '*', '0'
- myip_name:
- db 09H, "IPADDRESS", 01H, '*', '0'
- myip_name_len equ 12
-
- ; Temporary storage for calls to print_number
- dtemp dw ?,0
-
- extrn set_recv_isr: near
-
- ;enter with si -> argument string, di -> wword to store.
- ;if there is no number, don't change the number.
- extrn get_number: near
-
- ;enter with ds:dx -> argument string, ds:di -> dword to print.
- extrn print_number: near
-
- ;enter with al = char to display
- extrn chrout: near
- ;enter with ax,dx holding 32 bits to display in decimal (ax holds low word)
- extrn decout: near
- extrn byteout: near
- extrn wordout: near
-
- extrn skip_blanks: near
-
- ;enter with si -> argument string, di -> word to store.
- ;if there is no number, don't change the number.
- extrn get_number: near
-
- ;called with ds:si -> immediately after the entry_point
- public parse_args
- parse_args:
- call skip_blanks
- lodsb
- cmp al, CR
- je no_more_args
- cmp al, '[' ; check for square brackets
- je past_brackets
- dec si ; not a bracket, back up
- past_brackets:
- mov di, offset temp_4bytes ; get first IP address byte
- call get_number
- mov byte ptr test_address, cl
- lodsb
- cmp al, '.'
- jne no_more_args
-
- mov di, offset temp_4bytes ; get second IP address byte
- call get_number
- mov byte ptr test_address+1, cl
- lodsb
- cmp al, '.'
- jne no_more_args
-
- mov di, offset temp_4bytes ; get third IP address byte
- call get_number
- mov byte ptr test_address+2, cl
- lodsb
- cmp al, '.'
- jne no_more_args
-
- mov di, offset temp_4bytes ; get first IP address byte
- call get_number
- mov byte ptr test_address+3, cl
-
- ; mov dx, offset test_arg_msg
- ; mov di, offset test_address
- ;push si
- ; call print_ip_addr
- ;pop si
-
- mov ax, word ptr test_address
- mov word ptr static_address, ax
- mov ax, word ptr test_address+2
- mov word ptr static_address+2, ax
- mov use_static, 01H
-
- lodsb
- cmp al, ']'
- je arg_return
-
- ;exit with nc if all went well, cy otherwise.
- no_more_args:
- dec si
- arg_return:
- clc
- ret
-
-
- ; Initialize our interface to the ATALK.SYS driver.
- ; NOTE: this initialization code is modeled after the PC/IP LocalTalk
- ; driver written by Dan Lanciani (ddl@harvard.harvard.edu); the PCIP
- ; software package can found at husc6.harvard.edu:pub/pcip/pcip.tar.Z
- public etopen
- etopen:
- assume ds:code
-
- ; ATALK.SYS driver may be loaded at a software interrupt somewhere
- ; between 5CH and 70H. Locate ATALK.SYS driver by scanning for signature.
- isATLoaded: ; Look for ATALK.SYS driver
- cld
- call ATGetInt ; Load start of intr range
- mov dx, ax ; Save start value in DX
- chkloop:
- cmp dx, 70H ; Scanned all possible vectors?
- jne checkstring ; No, check this vector
- xor ax, ax ; Yes, driver not found
- jmp chksplit ; Skip ahead to return
- checkstring:
- mov bx, dx ; Load intr# for scan
- shl bx, 1 ; Multiply by 2 (for seg bytes)
- shl bx, 1 ; Multiply by 2 (for off bytes)
- xor ax, ax
- mov es, ax ; Lowest page of memory
- lds si, es:[bx] ; Load vector for scan intr#
- mov ax, ds ; Load segment this scan intr#
- or ax, si ; OR with off this scan intr#
- jz keepchecking ; Keep checking if no bits
- sub si, 16 ; Signature is just before code
- mov di, offset driverstring ; Load compare string
- mov cx, 9 ; Load length of compare string
- movseg es,cs
- repe cmpsb ; Compare ds:si to es:di
- jne keepchecking ; Keep checking if not matched
- call ATGetInt ; Matched, get INT# again
- cmp ax, dx ; INT# already set properly?
- jz chksplit ; Yes, use this INT#
- ; No, we found INT# by scanning
- call ATPatch ; Modify code to match scan
- call ATGetInt ; Retrieve final INT#
- jmp chksplit ; Skip ahead to return
-
- keepchecking: ; Havent found ATALK.SYS driver
- inc dx ; Check next possible INT#
- jmp chkloop ; Loop back to check next INT#
-
- chksplit: ; Done with scan for ATALK.SYS
- cmp ax, 00H ; ATALK.SYS driver found?
- jne atalk_sys_found ; Yes, skip ahead to continue
-
- mov dx, offset no_atalk_sys_msg ; No, ATALK.SYS not loaded
- jmp error_wrt ; Skip ahead to report error
-
- atalk_sys_found: ; ATALK.SYS driver found
- movseg ds,cs
- mov dtemp, dx ; Report intr# of ATALK.SYS
- mov di, offset dtemp
- mov dx, offset atalk_sys_found_msg
- call print_number
-
- ; We need to establish our Appletalk node
- get_our_info: ; Get info params from ATALK
- mov MyInfo.atd_command, AT_GETNETINFO
- mov MyInfo.atd_status, -1 ; As per PC LocalTalk spec. [jgn]
- mov MyInfo.atd_compfun.offs, 0 ; No completion routine [jgn]
- mov MyInfo.atd_compfun.segm, 0
- mov bx, offset MyInfo
- call doATint
-
- cmp MyInfo.atd_status, 00H ; Already initialized?
- je get_ddp_socket ; Yes, skip ahead
-
- mov MyInfo.atd_command, AT_INIT ; No, initialize our node
- mov MyInfo.atd_compfun.offs, 0 ; No completion routine [jgn]
- mov MyInfo.atd_compfun.segm, 0
- mov bx, offset MyInfo
- call doATint
-
- ; We need to establish our AppleTalk/DDP socket
- get_ddp_socket: ; Open a DDP socket
- mov DDPio.ddp_command, DDP_OPENSOCKET
- mov DDPio.ddp_compfun.offs, 0 ; No completion routine [jgn]
- mov DDPio.ddp_compfun.segm, 0
- mov DDPio.ddp_buffptr.offs, offset preview_upcall
- mov DDPio.ddp_buffptr.segm, cs
- mov DDPio.ddp_socket, 72 ; ask for experimental sock#
- mov DDPio.ddp_type, 22 ; ask for IP socket type
- mov bx, offset DDPio ; ds:bx-> DDP param block
- call doATint ; ask ATALK.SYS for a socket
-
- cmp DDPio.ddp_status, 00H ; error return from ATALK.SYS?
- je chk_ddp_socket ; no, skip ahead to continue
- ; yes, no socket for us
- mov ax, DDPio.ddp_status
- mov dtemp, ax
- mov di, offset dtemp
- mov dx, offset ddp_failed_msg
- call print_number ; report error and stat return
- jmp error_ret
-
- ;**** do we really require socket 72?
- chk_ddp_socket: ; check the socket we opened
- cmp DDPio.ddp_socket, 72 ; did we get the one requested?
- je ddp_ready ; yes, socket is as expected
- ; no, but must have socket 72
- mov DDPio.ddp_command, DDP_CLOSESOCKET
- mov bx, offset DDPio
- call doATint ; close the assigned socket
-
- mov dx, offset ddp_wrong_socket_msg ; load error msg
- jmp error_wrt ; skip ahead to display and ret
-
- ddp_ready: ; DDP socket 72 is ready
- mov DDPio.ddp_command, DDP_WRITE ; Use param block for WRITE now
-
- ; AppleTalk node and DDP socket have been established
- mov ax, MyInfo.inf_network
- mov word ptr dtemp, ax
- mov al, MyInfo.inf_nodeid
- mov ah, DDPio.ddp_socket
- mov byte ptr dtemp+2, al
- mov byte ptr dtemp+3, ah
- mov di, offset dtemp
- mov dx, offset atalk_open_msg
- call print_at_addr ; display AppleTalk node info
- mov ax, 00H
- mov dtemp+2, ax
-
- ; We need an IP gateway node
- nbp_ipgateway: ; Locate our IP gateway node
- movseg ds,cs
- mov NBP.nbp_command, NBP_LOOKUP
- mov NBP.nbp_compfun.offs, 0 ; No completion routine [jgn]
- mov NBP.nbp_compfun.segm, 0
- mov NBP.nbp_toget, 01H
- mov NBP.nbp_buffptr.offs, offset NBPt
- mov NBP.nbp_buffptr.segm, ds
- mov NBP.nbp_buffsize, (size NBPTuple)
- mov NBP.nbp_interval, 5
- mov NBP.nbp_retry, 12
- mov NBP.nbp_entptr.offs, offset ipgateway_name
- mov NBP.nbp_entptr.segm, ds
- mov bx, offset NBP
- call doATint ; do name-bind lookup
-
- cmp NBP.nbp_status, 00H ; status return=error?
- jne nbp_no_gateway ; yes, report error and exit
-
- cmp NBP.nbp_toget, 01H
- je atp_setup
-
- nbp_no_gateway: ; NBP lookup failed
- mov ax, NBP.nbp_status
- mov dtemp, ax
- mov di, offset dtemp
- mov dx, offset nbp_no_gateway_msg ; display error msg
- call print_number
-
- mov DDPio.ddp_command, DDP_CLOSESOCKET
- mov bx, offset DDPio
- call doATint ; close the assigned socket
-
- jmp error_ret ; skip ahead to return
-
- ; We need a transport layer to the IP gateway
- atp_setup:
- mov cx, (size AddrBlk) ; MyGateway = NBPt.tup_addr
- movseg es,cs
- mov si, offset NBPt.tup_address
- mov di, offset MyGateway
- rep movsb
-
- mov di, offset NBPt.tup_address ; Display our gateway node
- mov dx, offset nbp_ipg_addr_msg
- call print_at_addr
-
- cmp use_static, 00H ; Do we have a static address? [jgn]
- je bds_setup ; No, don't change anything
- mov IPG.ipg_opcode+3, 3 ; Yes, change to IPG_SERVER
-
- bds_setup:
- mov BDS.bds_buffptr.offs, offset IPG
- mov BDS.bds_buffptr.segm, ds
- mov BDS.bds_buffsize, (size IPGInfo)
-
- mov ATP.atp_command, ATP_SEND_REQUEST
- mov ATP.atp_compfun.offs, 0 ; No completion routine [jgn]
- mov ATP.atp_compfun.segm, 0
- mov cx, (size AddrBlk) ; ATP.atp_addr = NBPt.tup_addr
- movseg es,cs
- mov si, offset NBPt.tup_address
- mov di, offset ATP.atp_addrblk
- rep movsb
- mov ATP.atp_buffptr.offs, offset IPG
- mov ATP.atp_buffptr.segm, ds
- mov ATP.atp_buffsize, (size IPGInfo)
- mov ATP.atp_interval, 05H
- mov ATP.atp_retry, 05H
- mov ATP.atp_flags, XO_BIT
- mov ATP.atp_bdsbuffs, 01H
- mov ATP.atp_bdsptr.offs, offset BDS
- mov ATP.atp_bdsptr.segm, ds
- mov bx, offset ATP
- call doATint
-
- cmp ATP.atp_status, 00H ; status return=error?
- jne atp_no_gateway ; yes, report error and exit
-
- cmp ATP.atp_bdsbuffs, 01H
- je chk_ip_opcode
-
- atp_no_gateway: ; ATP setup failed
- mov ax, ATP.atp_status
- mov dtemp, ax
- mov di, offset dtemp
- mov dx, offset atp_no_gateway_msg ; display error msg
- call print_number
-
- mov DDPio.ddp_command, DDP_CLOSESOCKET
- mov bx, offset DDPio
- call doATint ; close the assigned socket
-
- jmp error_ret ; skip ahead to return
-
- chk_ip_opcode:
- cmp IPG.ipg_opcode.offs, IPG_ERROR ; opcode is 32 bit
- jne save_ipaddr ; check one word at a time
- cmp IPG.ipg_opcode.segm, IPG_ERROR ; error from IP gateway?
- jne save_ipaddr ; no, transport established
- ; yes, ATP setup failed
- mov dx, offset ipg_gateway_err_msg ; display IPG error msg
- mov ah, 9
- int 21H
- mov dx, offset IPG.ipg_string
- mov ah, 9
- int 21H
- mov al, 13 ; display CR-LF
- call chrout
- mov al, 10
- call chrout
-
- mov DDPio.ddp_command, DDP_CLOSESOCKET
- mov bx, offset DDPio
- call doATint ; close the assigned socket
-
- jmp error_ret
-
- ; AppleTalk/IP transport layer established
- save_ipaddr:
- mov dx, offset myip_addr_msg
- cmp use_static, 00H
- jne show_static
- show_dynamic:
- mov di, offset IPG.ipg_ipaddress
- jmp show_ipaddr
- show_static:
- mov di, offset static_address
- show_ipaddr:
- call print_ip_addr
-
- mov dx, offset ns_ip_addr_msg
- mov di, offset IPG.ipg_ipname
- call print_ip_addr
-
- mov dx, offset bd_ip_addr_msg
- mov di, offset IPG.ipg_ipbroad
- call print_ip_addr
-
- mov dx, offset fs_ip_addr_msg
- mov di, offset IPG.ipg_ipfile
- call print_ip_addr
-
- ; We need to register ourself with the AppleTalk Name Binding Agent
- nbp_register_ourself:
- mov al, MyInfo.inf_nodeid
- mov NBPtable.tab_entry.tup_address.ablk_nodeid, al
- mov al, DDPio.ddp_socket
- mov NBPtable.tab_entry.tup_address.ablk_socket, al
-
- ; print our IP address in our NBP table entry
- mov bx, offset NBPtable.tab_entry.tup_name
- inc bx
- xor dx, dx
- cmp use_static, 00H
- jne reg_static1
- reg_dynamic1:
- mov dl, byte ptr IPG.ipg_ipaddress
- jmp reg_format1
- reg_static1:
- mov dl, byte ptr static_address
- reg_format1:
- call decstr
- mov al, dot_char
- mov byte ptr ds:[bx], al
- inc bx
- cmp use_static, 00H
- jne reg_static2
- reg_dynamic2:
- mov dl, byte ptr IPG.ipg_ipaddress+1
- jmp reg_format2
- reg_static2:
- mov dl, byte ptr static_address+1
- reg_format2:
- call decstr
- mov al, dot_char
- mov ds:[bx], al
- inc bx
- cmp use_static, 00H
- jne reg_static3
- reg_dynamic3:
- mov dl, byte ptr IPG.ipg_ipaddress+2
- jmp reg_format3
- reg_static3:
- mov dl, byte ptr static_address+2
- reg_format3:
- call decstr
- mov al, dot_char
- mov ds:[bx], al
- inc bx
- cmp use_static, 00H
- jne reg_static4
- reg_dynamic4:
- mov dl, byte ptr IPG.ipg_ipaddress+3
- jmp reg_format4
- reg_static4:
- mov dl, byte ptr static_address+3
- reg_format4:
- call decstr
-
- mov ax, bx
- sub ax, offset NBPtable.tab_entry.tup_name
- sub ax, 1
- mov NBPtable.tab_entry.tup_name, al
-
- mov cx, myip_name_len ; append IPADDR command to our IP
- movseg es,cs
- mov si, offset myip_name ; ds:si -> source
- mov di, bx ; es:di -> dest
- rep movsb
-
- ; Register our name with NBP agent
- mov NBP.nbp_command, NBP_REGISTER
- mov NBP.nbp_compfun.offs, 0 ; No completion routine [jgn]
- mov NBP.nbp_compfun.segm, 0
- mov NBP.nbp_buffptr.offs, offset NBPtable
- mov NBP.nbp_buffptr.segm, ds
- mov NBP.nbp_interval, 01H
- mov NBP.nbp_retry, 03H
- mov bx, offset NBP
- call doATint
-
- cmp NBP.nbp_status, 00H
- je atinit_done
-
- nbp_no_register:
- mov ax, NBP.nbp_status
- mov dtemp, ax
- mov di, offset dtemp
- mov dx, offset nbp_no_register_msg ; display error msg
- call print_number
-
- mov DDPio.ddp_command, DDP_CLOSESOCKET
- mov bx, offset DDPio
- call doATint ; close the assigned socket
-
- jmp error_ret ; skip ahead to return
-
- ;**** LocalTalk PC Card initialized, ready to TSR
- atinit_done:
- movseg ds,cs
- clc
- ret
-
- ;**** Got an error while initializing LocalTalk PC Card
- error_wrt: ; Display an error message
- movseg ds,cs
- stc
- ret
- error_ret: ; Board not initialized
- mov dx,offset null_msg ;error message already printed.
- stc
- ret
-
- public print_parameters
- print_parameters:
- ;echo our command-line parameters
- ret
-
- ;*******************************************
-
- ; Modify ATALK.SYS interrupt number in doATint code (self-modifying code!)
- ATPatch:
- mov al, dl ; Load new interrupt number
- movseg es,cs
- lea bx, doATint ; es:bx=offset of doATint code
- inc bx ; skip to operator for INT
- mov es:[bx], al ; modify the code
- ret
-
- ; Get ATALK.SYS interrupt number
- ATGetInt:
- movseg es,cs
- lea bx, doATint ; es:bx=offset of doATint code
- inc bx ; skip to operator for INT
- mov al, es:[bx] ; load operator for INT
- xor ah, ah ; zero high byte
- ret ; return INT# to caller
-
- ;*******************************************
-
- ;*******************************************
-
- ; caller must set ds:si -> dest for string, dx 16-bit value to sprint
- decstr:
- mov di,dx
- cmp dx, 0
- jne decstr_nonzero
- mov al,'0' ;yes - easier to just print it, than
- jmp chrstr ; to eliminate all but the last zero.
- decstr_nonzero:
-
- xor ax,ax ;start with all zeroes in al,bx,bp
- mov bp,ax
-
- mov cx,16 ;16 bits in one 16 bit registers.
- decstr_1:
- rcl di,1
- xchg bp,ax
- call addbit
- xchg bp,ax
- adc al,al
- daa
- loop decstr_1
-
- mov cl,'0' ;prepare to eliminate leading zeroes.
- call bytestr ;output the first two.
- mov ax,bp
- jmp wordstr ;output the next four.
-
- addbit: adc al,al
- daa
- xchg al,ah
- adc al,al
- daa
- xchg al,ah
- ret
-
- ;print the char in al at ds:bx
- chrstr:
- mov byte ptr [bx], al
- inc bx
- ret
-
- wordstr:
- push ax
- mov al,ah
- call bytestr
- pop ax
- bytestr:
- mov ah,al
- shr al,1
- shr al,1
- shr al,1
- shr al,1
- call digstr
- mov al,ah
- digstr:
- and al,0fh
- add al,90h ;binary digit to ascii hex digit.
- daa
- adc al,40h
- daa
- cmp al,cl ;leading zero?
- je digstr_1
- mov cl,-1 ;no more leading zeros.
- jmp chrstr
- digstr_1:
- ret
-
- ; caller must set ds:dx -> argument string, ds:di -> AddrBlk struct
- print_at_addr:
- ;enter with dx -> dollar terminated name of number, di ->dword.
- ;exit with the number printed and the cursor advanced to the next line.
- mov ah,9 ;print the name of the number.
- int 21h
- mov ax, [di].ablk_network ;print the network number
- xchg ah, al ; byte-swap network number [jgn]
- mov dx, 00H
- push di
- call decout
- pop di
- mov al, ':'
- call chrout
- xor ax, ax
- mov al, [di].ablk_nodeid ; print the nodeid number
- push di
- call decout
- pop di
- mov al, ':'
- call chrout
- xor ax, ax
- mov al, [di].ablk_socket ; print the socket number
- call decout
- mov al,CR
- call chrout
- mov al,LF
- call chrout
- ret
-
- ; caller must set ds:dx -> argument string, ds:di -> 32 bit ip address
- print_ip_addr:
- ;enter with dx -> dollar terminated name of number, di ->dword.
- ;exit with the number printed and the cursor advanced to the next line.
- mov ah,9 ;print the name of the number.
- int 21h
- mov al, '['
- call chrout
- xor ax, ax
- mov al, [di] ;print first byte in decimal.
- mov dx, 00H
- push di
- call decout
- pop di
- mov al, '.'
- call chrout
- xor ax, ax
- mov al, [di+1] ; print second byte in decimal
- push di
- call decout
- pop di
- mov al, '.'
- call chrout
- xor ax, ax
- mov al, [di+2] ; print third byte in decimal
- push di
- call decout
- pop di
- mov al, '.'
- call chrout
- xor ax, ax
- mov al, [di+3] ; print fourth byte in decimal
- call decout
- mov al, ']'
- call chrout
- mov al,CR
- call chrout
- mov al,LF
- call chrout
- ret
-
- code ends
-
- end
-
-