#include "pcdefs.h"
#include "mbuf.h"
#include "protocol.h"
#include "data.h"
#include "funcdef.h"

static int	ip_handle = 0;
static int	arp_handle = 0;
static int	rarp_handle = 0;

#define IC_ETHERNET	1
#define IC_SLIP		6
#define	IT_ANY		0xFFFF

struct packet_info {
	u_int	packet_version;
	u_int	packet_class;
	u_int	packet_type;
	u_int	packet_ifnumber;
	u_char	_far *packet_name;
	u_int	packet_extended;
};

#define set_rcv_mode(a,b)

static u_int _near
locate_pkt_vector(vec)             /* search for the packet driver */
u_int	vec;
{
	u_char _far *vptr;
	u_int vector;

	if (vec == 0)
		vec = 0x60;
	else if (vec < 0x60 || vec > 0x7f)
		return 0;

	for (vector = vec; vector < 0x80; vector++) {
		vptr = *(u_char _far * _far *)(unsigned long)(vector << 2);
		if (!memcmp(vptr + 3, (u_char _far *)"PKT DRVR", 8)) {
			(void) patch_vec(vptr);
			return(vector);
		}
	}
	return 0;
}

static char _near iptype[] = {8, 0};
static char _near arptype[] = {8, 6};
static u_char _near rarptype[] = {0x80, 0x35};
/*
 *	pkopen()
 *	try and locate the packet driver,
 *	open ARP and IP handles.
 */
int _near
pkopen(s, address, ioaddr, flags)
u_char	_near *s;	/* ethernet address */
u_int	address;	/* address is packet class */
u_int	ioaddr;		/* packet int, or 0 */
u_char	flags;		/* for RARP */
{
	struct packet_info p;
	int	i;

	if (ip_handle)
		return 0;

	if (locate_pkt_vector(ioaddr) == 0)
		return -1;

	if (driver_info(&p))
		return -2;

	if (address && address != p.packet_class)
		return -3;
	else
		address = p.packet_class;

	if (p.packet_class != IC_ETHERNET && p.packet_class != IC_SLIP)
		return -4;

	slip_mode = address == IC_SLIP;

	ip_handle = access_type(address, IT_ANY, 0, (u_char _far *)iptype,
		slip_mode ? 0 : sizeof(iptype), pkt_receiver);
	if (ip_handle < 0) {
		ip_handle = 0;
		return -5;
	}
	set_rcv_mode(ip_handle, 3);
	if (!slip_mode) {
		arp_handle = access_type(address, IT_ANY, 0,
			(u_char _far *)arptype, sizeof(arptype), arp_receiver);
		if (arp_handle < 0) {
			(void) release_type(ip_handle);
			ip_handle = 0;
			arp_handle = 0;
			return -6;
		}
		set_rcv_mode(arp_handle, 3);
		if ((i = get_address(ip_handle, (u_char _far *)s, 6)) < 0) {
			(void) release_type(ip_handle);
			ip_handle = 0;
			(void) release_type(arp_handle);
			arp_handle = 0;
			return -7;
		}
		if (flags & H_RARP) {
		    rarp_handle = access_type(address, IT_ANY, 0,
		      (u_char _far *)rarptype, sizeof(rarptype), arp_receiver);
		    if (rarp_handle < 0) {
			(void) release_type(ip_handle);
			(void) release_type(arp_handle);
			ip_handle = 0;
			arp_handle = 0;
			rarp_handle = 0;
			return -8;
		    }
		    set_rcv_mode(rarp_handle, 3);
		}
	}
	return 0;
}

void _near
pkclose()                     /* throw away our handles */
{

	if (!slip_mode) {
		set_rcv_mode(arp_handle, 1);
		(void) release_type(arp_handle);
		if (rarp_handle) {
			set_rcv_mode(rarp_handle, 1);
			(void) release_type(rarp_handle);
		}
	}
	set_rcv_mode(ip_handle, 1);
	(void) release_type(ip_handle);
}

int _near
pkxmit(packet, len)		/* transmit a packet */
u_char _far *packet;
u_int len;
{

	if (slip_mode) {
		packet += sizeof (struct ether);
		len -= sizeof (struct ether);
	} else if (len < 60)
		len = 60;

	if (send_pkt(packet, len) < 0)
/*		if (send_pkt(packet, len) < 0) */
			return -1;
	return 0;
}
