	name pkglue

	.286p

	INCLUDE	struct.inc

X	equ	4		; for near calls
;X	equ	6		; for far calls

_TEXT	SEGMENT  para PUBLIC 'CODE'
_TEXT	ENDS
_DATA	SEGMENT  PARA PUBLIC 'DATA'
_DATA	ENDS
_BSS	SEGMENT PARA PUBLIC 'BSS'
_BSS	ENDS

DGROUP	GROUP	_DATA,_BSS

	ASSUME cs:_TEXT, ds:DGROUP, es:nothing

	extrn	_slip_mode:byte
	extrn	_mbfree:word, _mbnext:word, _eb:byte

_BSS	SEGMENT
	PUBLIC	_innet
_innet	db	?
_BSS	ENDS

_TEXT	segment

	ASSUME	ds:nothing
comment	*
return_err proc far
	mov	dh,11		; bad command error
	push	bp
	mov	bp,sp
	or	word ptr [bp+6],1	; point to PSW, and set carry flag
	pop	bp
	iret
return_err endp
	*

	ASSUME	ds:nothing, es:nothing
	even
do_int	proc near
	int	60h
	ret

comment	*
	pushf
	cli
	db	9ah		; call far ptr
packet_vector	dd	return_err
	ret
	*
do_int	endp

	ASSUME	ds:nothing, es: nothing

        public	_pkt_receiver
	even
_pkt_receiver   proc    far
	push	ds
	push	bx
	push	dx
	mov	bx,DGROUP
	mov	ds,bx
	mov	es,bx
	ASSUME	ds:DGROUP, es:DGROUP

	or	ax,ax
	jz	$B0

	mov	_innet,0
	jmp	$B99
$B23:
	mov	bx,_mbfree		; restore mbuf onto free list
	mov	[di].next,bx
	mov	_mbfree,di
$B1:
	sti
	mov	ah,2
	mov	dl,'!'
	int	21h

	sub	ax,ax			; drop packet
	mov	_innet,al
	mov	di,ax
	mov	es,ax
	jmp	$B99
$B0:
	mov	_innet,1		; while innet is 1, netsleep can't
					; mess with ebuf
	mov	di,_mbfree
	or	di,di
	jz	$B1			; drop packet
	mov	bx,[di].next
	mov	_mbfree,bx
	mov	[di].next,ax		; on entry ax = 0

	test	_slip_mode,0ffh
	jz	$B7
	add	cx,size ether		; add fake Ethernet header
$B7:
	mov	ax,cx			; ax = length of packet in bytes
	add	ax,007fh		; len += 127
	and	ax,0ff80h
	mov	si,offset DGROUP:_eb	; find a free buffer to put data into
$B5:
	mov	cx,[si].count
	jcxz	$B23			; display dropped packet
	sub	cx,ax
	jae	$B4			; if cx >= ax then branch
	add	si,size ebuf		; else look at next buffer

	jmp	short $B5
;	cmp	si,offset DGROUP:_eb + NEBUFS * size ebuf
;					; NEBUFS * sizeof(struct ebuf)
;	jb	$B5
;	jmp short $B23			; drop packet, no non-fragged storage

$B4:
	mov	[si].count,cx
	mov	dx,[si].start_addr
	mov	[di].dptr,dx		; [di].next has been zeroed
	mov	[di].len,ax
	add	ax,dx
	mov	[si].start_addr,ax
					; put in mbprocess queue
	mov	bx,_mbnext	; *mbnext = di
	mov	[bx],di
	add	di,offset mbuf.next	; di -> &[di].next
	mov	_mbnext,di	; mbnext = &[di].next
	jcxz	$B91		; if eb length is 0, merge ebufs
	jmp	short $B98
$B91:
	mov	di,si
	add	si,size ebuf		; si -> next entry
	cld				; make sure it's forward
$B90:
	movsw
	lodsw
	stosw				; last word is length
	or	ax,ax
	jnz	$B90
$B98:
	mov	di,dx			; set up buffer for packet
	test	_slip_mode,0ffh
	jz	$B99
	add	di,size ether
$B99:
	pop	dx
	pop	bx
	pop	ds
	ASSUME	ds: nothing, es: nothing
        ret
_pkt_receiver endp

; void _fastcall patch_vec(u_char intno)
; unsigned char intno;
	public	@patch_vec
	even
@patch_vec proc near
	mov	byte ptr cs:do_int+1,al
	ret
@patch_vec endp

	public	_driver_info
	even
_driver_info proc near
	ASSUME	ds:DGROUP
	push	bp
	mov	bp,sp
	push	ds
	push	si
	push	di
	mov	ax,ds
	mov	es,ax
	ASSUME	es:DGROUP

	mov	ax,01ffh
	sub	bx,bx
	call	do_int
	ASSUME	ds:nothing
	mov	ah,0
	jc	$C0
	cmp	al,0ffh
	jne	$C1
$C0:
	sub	ax,ax
	not	ax
	jmp short $C99
$C1:
	mov	di,[bp+X]
	mov	es:[di].version,bx
	mov	es:[di].pktype,dx
	cmp	al,2
	je	$C2
	mov	al,1
$C2:
	mov	es:[di].extend,ax
	mov	al,ch
	mov	es:[di].class,ax
	mov	al,cl
	mov	es:[di].ifnum,ax
	mov	word ptr es:[di].pkname,si
	mov	word ptr es:[di].pkname+2,ds
	sub	ax,ax
$C99:
	pop	di
	pop	si
	pop	ds
	ASSUME	ds:DGROUP
	pop	bp
	ret
_driver_info endp

	ASSUME	es:nothing

	public	_access_type
	even
_access_type proc near
	push	bp
	mov	bp,sp
	push	si
	push	di

	; For near text, set ES to the same as CS
	mov	ax,cs
	mov	es,ax
	mov	ax,[bp+X]
	mov	bx,[bp+X+2]
	mov	dl,[bp+X+4]
;	lds	si,[bp+X+6]
	mov	si,[bp+X+6]
	mov	cx,[bp+X+8]
;	les	di,[bp+X+10]
	mov	di,[bp+X+10]
	mov	ah,2
	call	do_int
	jnc	$D99
	mov	ah,0
	mov	al,dh
	neg	ax
$D99:
	pop	di
	pop	si
	pop	bp
	ret
_access_type endp

	public	_release_type
	even
_release_type proc near
	push	bp
	mov	bp,sp

	mov	bx,[bp+X]
	mov	ah,3
	call	do_int
	mov	ax,0
	jnc	$E99
	mov	al,dh
	neg	ax
$E99:
	pop	bp
	ret
_release_type endp

	public	@pkxmit
;	int _fastcall pkxmit(void _far *buffer, unsigned length);
	even
@pkxmit proc near
	push	bp
	mov	bp,sp
	push	si
	push	ds

	mov	cx,ax		; length
	mov	al,_slip_mode

	; Change ds AFTER we grab slip_mode.
	lds	si,[bp+X]	; buffer
	ASSUME	ds:nothing

	or	al,al
	jnz	slip
	cmp	cx,60		; minimum packet size is 60 bytes
	jge	no_slip
	mov	cx,60
	jmp	short no_slip
slip:
	sub	cx,size ether
	add	si,size ether
no_slip:
	mov	ah,4
	call	do_int
	mov	ax,0
	jnc	$F99
	mov	al,dh
	neg	ax
$F99:
	pop	ds
	ASSUME	ds:DGROUP
	pop	si
	pop	bp
	ret	4
@pkxmit endp

	public	_get_address
	even
_get_address proc near
	push	bp
	mov	bp,sp
	push	di

	mov	bx,[bp+X]
;	les	di,[bp+X+2]
	mov	di,[bp+X+2]
	mov	ax,ds
	mov	es,ax
	mov	cx,[bp+X+4]
	mov	ah,6
	call	do_int
	mov	ax,cx
	jnc	$I99
	mov	al,dh
	neg	al
	cbw
$I99:
	pop	di
	pop	bp
	ret
_get_address endp

	public	_set_rcv_mode
	even
_set_rcv_mode proc near
	push	bp
	mov	bp,sp

	mov	ah,20h
	mov	bx,[bp+X]
	mov	cx,[bp+X+2]
	call	do_int
	mov	ax,0
	jnc	$J99
	mov	al,dh
	neg	ax
$J99:
	pop	bp
	ret
_set_rcv_mode endp

_TEXT	ends
        end
