/*
 * (lan_hdrs.c)- Access to MAC headers
 *
 * Copyright (c) 1997 by Procom Technology,Inc.
 *
 * This program can be redistributed or modified under the terms of the 
 * GNU General Public License as published by the Free Software Foundation.
 * This program is distributed without any warranty or implied warranty
 * of merchantability or fitness for a particular purpose.
 *
 * See the GNU General Public License for more details.
 *
 */


#define LAN_HDRS_C


#include <asm/byteorder.h>
#include <linux/skbuff.h>
#include <linux/netdevice.h>
#include <linux/trdevice.h>
#include <linux/if_arp.h>
#include <linux/if_tr.h>
#include <net/cm_types.h>
#include <net/cm_mm.h>
#include <net/cm_dll.h>
#include <net/cm_frame.h>
#include <net/lan_hdrs.h>
#include <net/llc_mac.h>
#include <net/llc_dbg.h>
#include <net/decode.h>



#ifdef LAN_HDRS_DBG
  #define  DBG_MSG(body) { printk body; }
#else
  #define  DBG_MSG(body)  ;
#endif

/* 
 * Function: lan_hdrs_init
 *
 * Description: 
 *  Fills MAC header fields, depending on MAC type.
 *
 * Parameters:
 *  pdu_frame : Address of the frame to initialize its MAC header
 *  mac_type : The MAC type (Ethernet or Token ring)
 *  sa :i The MAC source address
 *  da : The MAC destination address
 *
 * Returns:
 *  0, If MAC type is a valid type and initialization completes correctly
 *  1, Otherwise
 */
 
us16
lan_hdrs_init (frame_t * pdu_frame, us8 mac_type, us8 * sa, us8 * da)
{
	us8 *	src_addr;
	us8 *	dest_addr;
	us16	rc = 1;
	us16	lpdu_len;
	
	/* 
		ARPHRD_ETHER : ethernet device
		ARPHRD_LOOPBACK : loopback
		ARPHRD_IEEE802 : token-ring device
	*/ 
	
	switch (((struct device *)pdu_frame->dev)->type) {

#ifdef CONFIG_TR
		case ARPHRD_IEEE802 :		
			{	
			struct sk_buff *skb=(struct sk_buff *)pdu_frame->skb;
			token_ring_mac_hdr_t *trh=(token_ring_mac_hdr_t *)skb_push(skb,
						sizeof(token_ring_mac_hdr_t));
			struct device *dev=(struct device *)pdu_frame->dev;

			trh->ac=AC;
			trh->fc=LLC_FRAME;
			if(sa)
				memcpy(trh->sa,(void *)sa,dev->addr_len);
			else
				memset(trh->sa,0,dev->addr_len); 
			if(da) {
				memcpy(trh->da,(void *)da,dev->addr_len);
				tr_source_route((struct trh_hdr *)trh,dev);
			}
			pdu_frame->mac_hdr = (void *)skb->data;
			}
			rc = 0;
#ifdef TR_DBG
        		decode_trframe_t(pdu_frame);	
#endif
			break;
#endif
		case ARPHRD_ETHER :
		case ARPHRD_LOOPBACK :
			lpdu_len = ((struct sk_buff *) pdu_frame->skb)->len;
			pdu_frame->mac_hdr =
				skb_push ((struct sk_buff *) pdu_frame->skb, 
				sizeof(ieee_802_3_mac_hdr_t));
			memset (pdu_frame->mac_hdr, 0, sizeof(ieee_802_3_mac_hdr_t));
			((ieee_802_3_mac_hdr_t *) pdu_frame->mac_hdr)->lpdu_len =
						htons (lpdu_len);
			dest_addr = ((ieee_802_3_mac_hdr_t *) pdu_frame->mac_hdr)->da;
			src_addr = ((ieee_802_3_mac_hdr_t *) pdu_frame->mac_hdr)->sa;
			memcpy (dest_addr, da, MAC_ADDR_LEN);
			memcpy (src_addr, sa, MAC_ADDR_LEN);
			rc = 0;
			break;
		default:
			printk("Unknown DEVICE type : %d\n", 
					((struct device *)pdu_frame->dev)->type);
#ifdef TR_DBG
        		decode_trframe_t(pdu_frame);	
#endif
			rc = 1;
	}
	return (rc);
}			

