home *** CD-ROM | disk | FTP | other *** search
- Title pclana -- IBM PC LAN or SYTEK 6120 Packet Driver Interface
- Page ,132
- version equ 5
-
- ;
- ; COPYRIGHT (c) 1989, Kevin J. Rowett -- N6RCE
- ; Cupertino, CA
- ;
-
- ;
- ; implements the body of a packet driver supporting the
- ; IBM PC network LAN adapter (LANA), also known as a SYTEK 6120
- ; card.
- ;
- ; These cards have an on-board (now known as version 1) NETBIOS
- ; interface, accessed via INT 5C.
- ;
- ; The cards implement networking with their own OSI style session
- ; and transport protocols. The MAC layer is almost raw 802.3
- ;
- ; While the card has a connected mode session protocol available,
- ; our implementation uses the DATAGRAM mode. Packets are sent and
- ; received as datagrams using the PROM supplied MAC address.
- ; Broadcast packets are send/received using the DATAGRAM BROADCAST
- ; mode.
- ;
- ; The card is not nice enough to interrupt us when a frame has
- ; arrived. We must supply it a buffer to put the frame into
- ; as it arrives. Therefore, we have one DATAGRAM and DATAGRAM
- ; BROADCAST buffer defined here. Of course, if we don't empty
- ; it fast enough, the next arriving frame will go into the bit
- ; bucket :-). Some might view this as a performance problem.
- ; So does the author :-(.
- ;
- ; We reserve another NCB for control.
- ;
- ; Why bother you ask? So, N3EUA can demo N6GN's uwv talents.
- ;
-
- Page
- include defs.asm ;SEE ENCLOSED COPYRIGHT MESSAGE
-
- Page
- code segment byte public
- assume cs:code, ds:code
-
- public int_no
- int_no db 3,0,0,0 ;we don't use it, but tail.asm wants to
- ;fix it if this is an AT
-
- public lana_num
- lana_num db 0,0,0,0
-
- public mac_addr
- mac_addr db 6 dup (0)
- ether_broadcast db 6 dup (0FFh)
-
- public driver_class, driver_type, driver_name
- driver_class db 1 ;from the packet spec
- driver_type db 16 ;from the packet spec
- driver_name db 'pclana',0 ;name of the driver.
-
- savess Dw ?
- savesp Dw ?
-
- ;
- ; Struct defining a std NCB layout
- ;
- NCB Struc
-
-
- NCB_COMMAND Db ? ;NCB command field
- NCB_RETCODE Db ?
- NCB_LSN Db ? ;local session number
- NCB_NUM Db ? ;NCB number of your name
- NCB_BUFFER Dd ? ;FAR ptr to buffer
- NCB_LENGTH Dw ? ;bufer length
- NCB_CALLNAME Db 16 dup (?) ;name on local or remote adapter
- NCB_NAME Db 16 dup (?) ;name on local adapter
- NCB_RTO Db ? ;receive timeout value
- NCB_STO Db ? ;send timeout value
- NCB_POST Dd ? ;far ptr to post completion rtn
- NCB_LANA_NUM Db ? ;adapter number 0 or 1
- NCB_CMD_CPLT Db ? ;cmd status flag
- NCB_RESERVE Db 14 dup (?) ;reserved work area
-
- previous_error Db ?
- immediate_error Db ?
- active_flag Db ? ;have we done an INT on this NCB?
- NCB_link Dw ? ;offset to next NCB
-
- NCB_data_buffer Db 512 dup (0)
-
- NCB ends
-
- NETBIOS Equ 5CH
-
- MAX_LANA_BUF_LEN Equ 512
- ncb_count Equ 5
- NCB_in_use Equ 0FFH
- NCB_unused Equ 00H
-
- CTL_NCB Db (size NCB) dup (0)
-
- RCV_NCB Db ncb_count*(size NCB) dup (0)
-
- RCV_BDCST_NCB Db ncb_count*(size NCB) dup (0)
-
- SEND_NCB Db (size NCB) dup (0)
-
- SEND_BDCST_NCB Db (size NCB) dup (0)
-
- send_in_use Db 00H
- recv_in_use Db 00H
-
- stack Dw 100 dup (?)
-
- ;
- ; cmd codes for the LANA
- ;
- LANA_RESET Equ 32H ;RESET, waited mode
- LANA_ADPTS Equ 33H ;Adapter status, waited mode
- LANA_SENDDG Equ 0A0H ;SEND DATAGRAM, nowait mode
- LANA_SENDDG_BDCST Equ 0A2H ;SEND BROADCAST DATAGRAM, nowait
- LANA_RCVDG equ 0A1H ;RCV DATAGRAM, nowait
- LANA_RCVDG_BDCST Equ 0A3H ;RCV BROADCAST DATAGRAM, nowait
- LANA_TEST_PRES Equ 7FH ;TEST IF LANA Present (inv cmd)
-
- Subttl send_pkt
- Page
- public send_pkt
- send_pkt:
- ;enter with ds:si -> packet, cx = packet length.
- ;exit with nc if ok, or else cy if error, dh set to error number.
-
-
- assume ds:nothing
- ; better protect our selves
- Pushf
- Cli
- Nop ;03H
- Cmp CS:send_in_use,NCB_in_use
- Jne not_reentered_s
- Int 03H
-
- not_reentered_s:
- Mov send_in_use,NCB_in_use
-
- ; check to see if the recv routine is active
- Cmp CS:recv_in_use,NCB_in_use
- Jne not_reentered_r_wins
- Int 03H
-
- not_reentered_r_wins:
-
- Popf
- Pushf
-
- ; check the length
- Cmp CX,MAX_LANA_BUF_LEN
- Jb ok_send_len
- Mov CX,MAX_LANA_BUF_LEN
- ok_send_len:
-
- ;
- ; Determine if the destination is broadcast
- ; real ethernet uses the DMAC of all FFh for broadcast
- ; The LANA does as well, but it wants us to use a different
- ; NCB type.
- ;
- Push SI ;save ptr to start of buffer
- Push CX ;and original length of packet
- Mov CX,6
- Mov DI,offset ether_broadcast
- Push CS
- Pop ES
- Cld
- Repe Cmpsb
- Pop CX
- Pop SI
- Jz send_bdcst
- Jmp send_dgram
- ;
- send_bdcst:
- ;
- ; send in broadcast mode
- ;
- Mov BX,offset SEND_BDCST_NCB
- Jmp send_ncb_prep
-
- send_dgram:
- ;
- ; send in datagram mode
- ;
- Mov BX,offset SEND_NCB
- Jmp send_ncb_prep
-
-
- send_ncb_prep:
-
- ; check previous send operation completed. Note, we prime the value of
- ; this field during etopen ( retcode = 00H, cmd_cplt = 00H )
- sendb_cplt_loop:
- Cmp [BX].NCB_CMD_CPLT,0FFh
- Je sendb_cplt_loop
- Jne sendb_cplt
- Int 03H
- Popf
- Stc
- Ret
-
- sendb_cplt:
- ;
- Push CS
- Pop ES
- Mov AL,ES:[BX].NCB_RETCODE
- Mov ES:[BX].previous_error,AL
- ; the NCB is ours. Initialize it.
- Call init_ncb
- ;
- ; setup the length field
- ;
- Mov ES:[BX].NCB_LENGTH,CX
- ;
- ; Move the destination address into CALLNAME
- ;
- Lea DI,ES:[BX].NCB_CALLNAME+10
- Push CX
- Mov CX,6
- Push SI
- Rep Movsb
- Pop SI
- Pop CX
- ;
- ; Move the data to the buffer
- ;
- Lea DI, ES:[BX].NCB_data_buffer
- Rep Movsb
- ;
- ; NCB is prepared and ready to go
- ;
- ; note, we don't load the cmd field, since init will do this
- ; for us, and the LANA never alters it
- ;
- Int NETBIOS
- Mov ES:[BX].immediate_error,AL
- Cmp AL,00H
- Je okay_send_ret
- Mov DH,CANT_SEND
- Mov CS:send_in_use,NCB_unused
- Int 03H
- Popf
- Stc
- Ret
-
- okay_send_ret:
- Mov DH,00H
- Mov CS:send_in_use,NCB_unused
- Popf
- Clc
- Ret
-
-
-
- Subttl get_address
- Page
- public get_address
- get_address:
- ;get the address of the interface.
- ;enter with es:di -> place to get the address, cx = size of address buffer.
- ;exit with nc, cx = actual size of address, or cy if buffer not big enough.
-
- assume ds:code
- Cmp CX,6
- Jb get_address_2
- Mov CX,6 ;count of bytes to copy
- Cld ;increment addr index
- Mov si,OFFSET mac_addr
- ; dest is a callng parameter
- Rep Movsb
- Mov CX,6
- Clc
- Ret
- get_address_2:
- Stc
- Ret
-
- Subttl set_address
- Page
- ;Set Ethernet address on controller
- public set_address
- set_address:
- assume ds:nothing
- ;enter with ds:si -> Ethernet address, CX = length of address.
- ;exit with nc if okay, or cy, dh=error if any errors.
- ;
- stc
- set_address_done:
- push cs
- pop ds
- assume ds:code
- ret
-
-
- Subttl reset_interface
- Page
- public reset_interface
- reset_interface:
- ;reset the interface.
- ; RESET the LANA
- ;
- Mov BX,offset CTL_NCB
- Call init_ncb
- Mov [BX].NCB_COMMAND,LANA_RESET
- Mov [BX].NCB_LSN,01H ;number of sessions to support
- Mov [BX].NCB_NUM,06H ;number of commands to support
- Int NETBIOS
- ;
- Ret
-
-
- Subttl
- Page
- ;called when we want to determine what to do with a received packet.
- ;enter with cx = packet length, es:di -> packet type.
- 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
-
- extrn count_in_err: near
- extrn count_out_err: near
-
- Subttl recv
- Page
- public recv
- recv:
- ;called from the recv isr. All registers have been saved, and ds=cs.
- ;Upon exit, the interrupt will be acknowledged.
- assume ds:code
-
- Mov AL,ES:[BX].NCB_RETCODE
- Mov ES:[BX].previous_error,AL
- Les DI,ES:[BX].NCB_BUFFER
- ;
- ; Check if it is from ourselves ( we hear our own broadcasts), if
- ; so, then ignore it.
- ;
- Add DI,6 ;point to SMAC
- Mov CX,6
- Mov SI,offset mac_addr
- Cld
- Repe Cmpsb
- Jz drop_frame ;it's from ourselves
-
- ; after the above, we have no idea where DI is pointing
-
- Les DI,ES:[BX].NCB_BUFFER
- Add DI,12 ;point to frame type field
- Mov CX,ES:[BX].NCB_LENGTH
- Push BX
- Nop ;03H
- Call recv_find
- ; returns with buffer ptr in ES:DI, or null if not buffer allocated
-
- Pop BX
- Mov AX,ES ;did we get a buffer ptr back?
- Or AX,DI
- Je drop_frame
-
- Push ES ;remember ptr to appl's buffer
- Push DI
-
- Mov CX,DS:[BX].NCB_LENGTH
- Lds SI,DS:[BX].NCB_BUFFER
-
- Cld
- Rep Movsb
-
- Mov CX,DS:[BX].NCB_LENGTH
- Pop SI
- Pop DS
- Call recv_copy
-
- drop_frame:
-
- ;
- ; to keep receiving of frames, we need to put another NCB
- ; to the LANA. The NCB's are chained in a single forward linked
- ; list. We loop thru it looking for one to use.
-
- Push CS
- Pop DS
- Push BX ;we'll need to get back to the one
- ;we started with
- Mov CX,ncb_count ;loop counter
- Dec CX ;since at least one is in use!
- src_free_recv_NCB:
- Mov BX,[BX].NCB_link ;link to the next NCB
- Cmp [BX].active_flag,NCB_unused ;this guy free?
- Je fnd_free_recv_NCB ;yea! use him
- Loop src_free_recv_NCB ;no, keep looking
- Pop BX ;didn't find a free NCB
- Jmp no_free_recv_NCB ;but that is okay
-
- fnd_free_recv_NCB:
-
- Push CS
- Pop ES
- Call init_ncb
- Mov AX,offset lana_post_recv
- Mov word ptr ES:[BX].NCB_POST,AX
- Mov AX,ES
- Mov word ptr ES:[BX].NCB_POST+2,AX
- Mov [BX].NCB_LENGTH,MAX_LANA_BUF_LEN
- Mov [BX].active_flag,NCB_in_use
-
- Int NETBIOS
- Mov [BX].immediate_error,AL
- Pop BX
-
- no_free_recv_NCB:
- Mov [BX].active_flag,NCB_unused
-
- Ret
-
- Subttl lana_post_recv
- Page
- lana_post_recv:
- ;
- ; come here when the LANA posts open of the RECV NCB's as complete
- ;
- ; AL = RetCode
- ; CS = set to this code segment
- ; ES = of the NCB
- ; BX = offset of the NCB
- ; we don't need to preserve any of the registers, since the LANA
- ; BIOS has already done that.
-
-
- ; check to see if this is a recursive reenter
- Cmp CS:recv_in_use,NCB_in_use
- Jne not_reentered_r
- Int 03H
-
- not_reentered_r:
- Mov recv_in_use,NCB_in_use
-
- ; check to see if the send routine is active
- Cmp CS:send_in_use,NCB_in_use
- Jne not_reentered_s_winr
- Int 03H
-
- not_reentered_s_winr:
-
- Mov AX,CS
- Mov DS,AX
-
- Mov savesp,SP
- Mov savess,SS
-
- Mov SS,AX
- Mov SP,offset stack
-
- Call Recv
-
- Mov recv_in_use,NCB_unused
- Push CS
- Pop DS
- Mov SS,savess
- Mov SP,savesp
-
- Iret
-
- Subttl init_ncb
- Page
- init_ncb:
- ; bx -> NCB to clear and init
-
- ; Mov [BX].NCB_COMMAND,00H
- ; note, we don't init NCB_COMMAND Field, as it's value, once set is
- ; never changed
- ;
- Mov ES:[BX].NCB_RETCODE,00H
- Mov ES:[BX].NCB_LSN,00H
- Mov ES:[BX].NCB_NUM,01H ;01H says use the PROM MAC address
- Mov AX,0000H
- Mov word ptr ES:[BX].NCB_LENGTH,AX
- Lea AX, ES:[BX].NCB_data_buffer
- Mov word ptr ES:[BX].NCB_BUFFER,AX
- Mov AX,ES
- Mov word ptr ES:[BX].NCB_BUFFER+2,AX
- ;
- Push SI
- ;
- Mov SI,0000H
- init_ncb_1:
- Mov AX,0000H
- Mov word ptr ES:[BX][SI].NCB_CALLNAME,AX
- Inc SI
- Inc SI
- Cmp SI,8
- Jl init_ncb_1
- ;
- Mov SI,0000H
- Mov AX,0000H
- init_ncb_2:
- Mov word ptr ES:[BX][SI].NCB_NAME,AX
- Inc SI
- Inc SI
- Cmp SI,5 ;this sets first ten bytes to zero
- Jl init_ncb_2
- Mov AX,word ptr CS:mac_addr
- Mov word ptr ES:[BX].NCB_NAME+10,AX
- Mov AX,word ptr CS:mac_addr+2
- Mov word ptr ES:[BX].NCB_NAME+12,AX
- Mov AX,word ptr CS:mac_addr+4
- Mov word ptr ES:[BX].NCB_NAME+14,AX
- ;
- Mov ES:[BX].NCB_RTO,00H
- Mov ES:[BX].NCB_STO,00H
- Mov AX,0000H
- Mov word ptr ES:[BX].NCB_POST,AX
- Mov word ptr ES:[BX].NCB_POST+2,AX
- Mov AL,ES:lana_num
- Mov ES:[BX].NCB_LANA_NUM,AL
- Mov ES:[BX].NCB_CMD_CPLT,00H
- ;
- Mov SI,0000H
- Mov AX,0000H
- init_ncb_3:
- Mov word ptr ES:[BX][SI].NCB_RESERVE,AX
- Inc SI
- Inc SI
- Cmp SI,7
- Jl init_ncb_3
- ;
- Pop SI
- Ret
-
-
-
- ;any code after this will not be kept after initialization.
- end_resident label byte
-
-
- Subttl
- Page
- public usage_msg
- usage_msg db "usage: pclana <packet_int_no> <LANA # -- 1 | 2>",CR,LF,'$'
-
- public copyright_msg
- copyright_msg db "Packet driver for IBM PC LAN card or SYTEK 6120, version ",'0'+majver,".",'0'+version,CR,LF
- db "Portions Copyright 1989, Kevin J. Rowett - N6RCE",CR,LF,'$'
-
- no_lana_msg db "NETBIOS (LANA) not present",CR,LF,'$'
-
- inv_lana_num_msg db "No LANA with that number found",CR,LF,'$'
-
- lana_err_msg db "LANA returned error",CR,LF,'$'
-
- lana_num_name db "LANA number = ",'$'
-
- extrn set_recv_isr: near
-
- Subttl parse_args
- Page
- ;enter with si -> argument string, di -> word to store.
- ;if there is no number, don't change the number.
- extrn get_number: near
-
- public parse_args
- parse_args:
-
- Mov di,offset lana_num ;save the LANA or NCB
- Mov bx,offset lana_num_name ;and name for get num to print
- Call get_number
- Dec lana_num ;user supplies 1 or 2, card want
- ; 0 or 1
-
- Ret
-
-
- lana_not_present:
-
- Mov dx,offset no_lana_msg
- Mov ah,9
- Int 21H ;DOS FN Call
- Stc
- Ret
-
-
- invalid_lana_num:
-
- Mov dx,offset inv_lana_num_msg
- Mov ah,9
- Int 21H ;DOS FN Call
- Stc
- Ret
-
-
- lana_error_rpt:
-
- Mov dx,offset lana_err_msg
- Mov ah,9
- Int 21H ;DOS FN Call
- Stc
- Ret
-
-
- Subttl etopen
- Page
- public etopen
- etopen:
- ;if all is okay,
-
- ;
- ; check to see if the LANA is present. Right out of book, page 2-88.
- ;
- ; version two learned something. Also must check the vector is not pointing
- ; into ROM above 0D000h.
- ;
- ;
- ; 1. check that INT 5C is not zero's
- ;
- ; 1A check segment < 0D000h
- ;
- ; 2. issue a cmd 7fH
- ;
- ; 3. see that the cmd comes back 03H (invalid cmd)
- ;
- ; if so, we have an adapter present
- ;
-
- Mov send_in_use,NCB_unused
- Mov recv_in_use,NCB_unused
- Mov ah,35H ;DOS FN get vector
- Mov al,NETBIOS
- Int 21H ;Hello DOS
- Cmp bx,0000H ;vector other than zero?
- Jne lana_pres_test2
- Jmp lana_not_present
- lana_pres_test2:
- Mov BX,ES
- ; get our ES back
- Push DS
- Pop ES
- Cmp BX,0000H
- Jne lana_pres_test3
- Jmp lana_not_present
- lana_pres_test3:
- Cmp BX,0D000H
- Jb lana_present
- Jmp lana_not_present
- lana_present:
-
- ; vector not zero
-
-
- Mov BX,offset CTL_NCB
- ;
- Call init_ncb
- Mov [BX].NCB_COMMAND,LANA_TEST_PRES
- Int NETBIOS
- Cmp [BX].NCB_RETCODE,03H
- Je lana_test_ret_ok
- Cmp [BX].NCB_RETCODE,23H
- Je invalid_lana_num_s
- Jmp lana_not_present
- invalid_lana_num_s:
- Jmp invalid_lana_num
-
-
- lana_test_ret_ok:
-
- ; good chance we have a LANA present
- ;
- ; Now, RESET the bastard, and get the MAC address
- ;
- Call init_ncb
- Mov [BX].NCB_COMMAND,LANA_RESET
- Mov [BX].NCB_LSN,01H ;number of sessions to support
- Mov [BX].NCB_NUM,0cH ;number of commands to support
- Int NETBIOS
- Cmp [BX].NCB_RETCODE,00H
- Je lana_reset_okay
- Jmp lana_error_rpt
- lana_reset_okay:
- ;
- ; adapter status please
- ;
- Call init_ncb
- Mov [BX].NCB_COMMAND,LANA_ADPTS
- Mov [BX].NCB_CALLNAME,'*' ;get status of local adapter
- Mov [BX].NCB_LENGTH,MAX_LANA_BUF_LEN
- Int NETBIOS
- Cmp [BX].NCB_RETCODE,00H
- Je lana_adpts_okay
- Jmp lana_error_rpt
- lana_adpts_okay:
- ;
- ; save the mac address
- ;
- Mov AX,word ptr [BX].NCB_data_buffer
- Mov word ptr mac_addr,AX
- Mov AX,word ptr [BX].NCB_data_buffer+2
- Mov word ptr mac_addr+2,AX
- Mov AX,word ptr [BX].NCB_data_buffer+4
- Mov word ptr mac_addr+4,AX
-
- ;
- ; set the NCB_COMMAND fields for the various static NCB's
- ;
- Mov BX,offset SEND_NCB
- Mov [BX].NCB_COMMAND,LANA_SENDDG
-
- Mov BX,offset SEND_BDCST_NCB
- Mov [BX].NCB_COMMAND,LANA_SENDDG_BDCST
-
- ;
- ; loop thru the string of receive style NCB's
- ;
- Mov BX,offset RCV_NCB
- Mov CX,ncb_count
-
- recv_ncb_loop:
- Call init_ncb
- Mov AX,offset lana_post_recv
- Mov word ptr ES:[BX].NCB_POST,AX
- Mov AX,ES
- Mov word ptr ES:[BX].NCB_POST+2,AX
- Mov [BX].NCB_COMMAND,LANA_RCVDG
- Mov [BX].NCB_LENGTH,MAX_LANA_BUF_LEN
- Mov [BX].active_flag,NCB_in_use
-
- Mov DX,BX
- Add DX,size NCB
- Mov [BX].NCB_link,DX
- Mov BX,DX
-
- Loop recv_ncb_loop
- ;
- ; fix up the last one
- ;
- Sub BX,size NCB
- Mov Dx,offset RCV_NCB
- Mov [BX].NCB_link,DX
-
- ;
- ; post a chain of rcv datagram NCBs
- ;
- Mov BX,offset RCV_NCB
- Mov CX,ncb_count
-
- rcv_ncb_post_loop:
- Int NETBIOS
- Mov [BX].immediate_error,AL
- Cmp AL,00H
- Je ok_post_rcvdg
- Jmp lana_error_rpt
- ok_post_rcvdg:
- Add BX,size NCB
- Loop rcv_ncb_post_loop
-
-
- ;
- ; now the same for rcv broadcast ncb's
- ;
- Mov BX,offset RCV_BDCST_NCB
- Mov CX,ncb_count
-
- recv_bdcst_ncb_loop:
- Call init_ncb
- Mov AX,offset lana_post_recv
- Mov word ptr ES:[BX].NCB_POST,AX
- Mov AX,ES
- Mov word ptr ES:[BX].NCB_POST+2,AX
- Mov [BX].NCB_COMMAND,LANA_RCVDG_BDCST
- Mov [BX].NCB_LENGTH,MAX_LANA_BUF_LEN
- Mov [BX].active_flag,NCB_unused
- ; We marked the BDCST as unused initially, since we only
- ; post one of them
-
- Mov DX,BX
- Add DX,size NCB
- Mov [BX].NCB_link,DX
- Mov BX,DX
-
- Loop recv_bdcst_ncb_loop
- ;
- ; fix up the last one
- ;
- Sub BX,size NCB
- Mov Dx,offset RCV_BDCST_NCB
- Mov [BX].NCB_link,DX
-
- ;
- ; post only one RECV BDCST DATAGRAM NCB, as they all complete
- ; at once.
- ;
- Mov BX,offset RCV_BDCST_NCB
- Mov [BX].active_flag,NCB_in_use ;mark as in_use
- Int NETBIOS
- Mov [BX].immediate_error,AL
- Cmp AL,00H
- Je ok_post_rcvdg_bdcst
- ; Jmp ok_post_rcvdg_bdcst
- Jmp lana_error_rpt
- ok_post_rcvdg_bdcst:
-
-
- mov dx,offset end_resident
- clc
- ret
- ;if we got an error,
- stc
- ret
-
- code ends
-
- end
-