/*
 * 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.
 *
 */
 
#include <linux/kernel.h>
#include <linux/skbuff.h>
#include <linux/netdevice.h>
#include <net/cm_types.h>
#include <net/cm_mm.h>
#include <net/cm_frame.h>
#include <net/cm_dll.h>
#include <net/llc_if.h>
#include <net/llc_sap.h>
#include <net/llc_conn.h>
#include <net/llc_main.h>
#include <net/llc_evnt.h>
#include <net/llc_c_ev.h>
#include <net/lan_hdrs.h>
#include <net/llc_pdu.h>
#include <asm/byteorder.h>

#include <net/decode.h>

/*---------------------------------------------------------------------*/

void decode_trframe_t(frame_t * f)
{
	unsigned char *p;	
	int i;
	struct sk_buff *skb=(struct sk_buff *)f->skb;

	printk("\n++++++++++ DECODE_TR_FRAME_T ++++++++++");

	printk("\nmac_type: %u", f->mac_type);
	p = (unsigned char *)f->mac_hdr;
	printk("\nAC: %2X", *p );
	printk(", FC: %2X", *(p+1));
	printk("\nmac_hdr: da: %2X%2X%2X%2X%2X%2X, sa: %2X%2X%2X%2X%2X%2X", 
		(((token_ring_mac_hdr_t *)f->mac_hdr)->da)[0],
		(((token_ring_mac_hdr_t *)f->mac_hdr)->da)[1],
		(((token_ring_mac_hdr_t *)f->mac_hdr)->da)[2],
                (((token_ring_mac_hdr_t *)f->mac_hdr)->da)[3],
                (((token_ring_mac_hdr_t *)f->mac_hdr)->da)[4],
                (((token_ring_mac_hdr_t *)f->mac_hdr)->da)[5],

                (((token_ring_mac_hdr_t *)f->mac_hdr)->sa)[0],
                (((token_ring_mac_hdr_t *)f->mac_hdr)->sa)[1],
                (((token_ring_mac_hdr_t *)f->mac_hdr)->sa)[2],
                (((token_ring_mac_hdr_t *)f->mac_hdr)->sa)[3],
                (((token_ring_mac_hdr_t *)f->mac_hdr)->sa)[4],
                (((token_ring_mac_hdr_t *)f->mac_hdr)->sa)[5]
	      );	
	printk(" , RCF : %4X", 
				((token_ring_mac_hdr_t *)f->mac_hdr)->rcf);


	printk("\nllc_hdr: ssap: %X, dsap: %X, ctrl_1: %X, ctrl_2: %X",
                ((pdu_sn_t *)f->llc_hdr)->ssap, 
                ((pdu_sn_t *)f->llc_hdr)->dsap,
                ((pdu_sn_t *)f->llc_hdr)->ctrl_1,
                ((pdu_sn_t *)f->llc_hdr)->ctrl_2);

   
	printk("\ntail-data:%u,len:%lu, dev_type: %d", (char *)skb->tail - (char *)skb->data, 
				skb->len, ((struct device *)f->dev)->type);
   
	printk("\n++++++++++++ RAW DATA ++++++++++++++++++++++++");
	printk("\nMAC :\n");
	for ( i=0,p = (unsigned char *)f->mac_hdr; p < (unsigned char *)f->llc_hdr && i < 32 ; 
					p++,i++ ){
		printk("%2X ", *p);
	}
	printk("\nLLC :\n");
	for ( i = 0,p=(unsigned char *)f->llc_hdr ; i < 20 ; p++,i++ ){
		printk("%2X ", *p);
	}

	printk("\n--------------- END OF FRAME  ----------------\n");
}


/*---------------------------------------------------------------------*/

void decode_frame_t(frame_t * f)
{
	printk(KERN_ERR "\n++++++++++ DECODE_FRAME_T ++++++++++");

	printk(KERN_ERR "\nData size: %u", f->data_size);
	printk(KERN_ERR "\nmac_type: %u", f->mac_type);
	printk(KERN_ERR "\nmac_hdr: da: %2X%2X%2X%2X%2X%2X, sa: %2X%2X%2X%2X%2X%2X, lpdu_len: %d",
		(((ieee_802_3_mac_hdr_t *)f->mac_hdr)->da)[0],
		(((ieee_802_3_mac_hdr_t *)f->mac_hdr)->da)[1],
		(((ieee_802_3_mac_hdr_t *)f->mac_hdr)->da)[2],
                (((ieee_802_3_mac_hdr_t *)f->mac_hdr)->da)[3],
                (((ieee_802_3_mac_hdr_t *)f->mac_hdr)->da)[4],
                (((ieee_802_3_mac_hdr_t *)f->mac_hdr)->da)[5],

                (((ieee_802_3_mac_hdr_t *)f->mac_hdr)->sa)[0],
                (((ieee_802_3_mac_hdr_t *)f->mac_hdr)->sa)[1],
                (((ieee_802_3_mac_hdr_t *)f->mac_hdr)->sa)[2],
                (((ieee_802_3_mac_hdr_t *)f->mac_hdr)->sa)[3],
                (((ieee_802_3_mac_hdr_t *)f->mac_hdr)->sa)[4],
                (((ieee_802_3_mac_hdr_t *)f->mac_hdr)->sa)[5],

                ntohs(((ieee_802_3_mac_hdr_t *)f->mac_hdr)->lpdu_len));

	printk(KERN_ERR "\nllc_hdr: ssap: %X, dsap: %X, ctrl_1: %X, ctrl_2: %X",
                ((pdu_sn_t *)f->llc_hdr)->ssap, 
                ((pdu_sn_t *)f->llc_hdr)->dsap,
                ((pdu_sn_t *)f->llc_hdr)->ctrl_1,
                ((pdu_sn_t *)f->llc_hdr)->ctrl_2);

   
	/*decode_ncb_frame_t(f->nb_hdr);*/

   
	printk(KERN_ERR "\nfree_frame_flag: %u", f->free_frame_flag);
	printk(KERN_ERR "\nskb: %p, dev: %p, pt: %p", f->skb, f->dev, f->pt);
   
	printk(KERN_ERR "\n++++++++++++++++++++++++++++++++++++");
}

/*---------------------------------------------------------------------*/

char * prim_types[] = { "", "REQUEST", "INDICATE", "RESPONSE", "CONFIRM" };

char * primitives[] =
      {
         "DATAUNIT",
         "CONNECT",
         "DATA",
         "DISCONNECT",
         "RESET",
         "FLOWCONTROL", 
         "DISABLE",
         "XID",
         "TEST"
      };

void decode_stat_event_if_t (stat_event_if_t * data, us8 type )
{
   switch (type)
   {
      case 1:
         printk(KERN_ERR "\nEvent: %u", data->a.event);
         break;
      case 2:
         printk(KERN_ERR "\nCondition");
         break;
      case 3:
         printk(KERN_ERR "\nprim: %u (%s)", data->prim.prim, primitives[data->prim.prim]);
         printk(KERN_ERR "\ntype: %u (%s)", data->prim.type, prim_types[data->prim.type]);
         break;
      case 4:
         printk(KERN_ERR "\nreason: %u", data->pdu.reason);
         decode_frame_t(data->pdu.frame);
         break;
      case 5:
         printk(KERN_ERR "\ntimer_specific: %p", data->tmr.timer_specific);
         break;
      case 6:
         printk(KERN_ERR "\nstatus: %u", data->rsts.status);
         break;
   }
}

void decode_station_event_t (station_state_event_t * ev)
{
   char * ev_types[] = { "", "SIMPLE", "CONDITION", "PRIM", "PDU",
                "ACK_TIMER", "RPT_STATUS" };

   printk(KERN_ERR "\n++++++++ DECODE_STATION_EVENT_T ++++");
   printk(KERN_ERR "\nType: %u (%s)", ev->type, ev_types[ev->type]);
   decode_stat_event_if_t(&ev->data, ev->type);
   printk(KERN_ERR "\n++++++++++++++++++++++++++++++++++++");
}

/*---------------------------------------------------------------------*/

void decode_address_t(address_t addr)
{
   printk(KERN_ERR "lsap: %i, mac: %X%X%X%X%X%X", addr.lsap,
		addr.mac[0],
		addr.mac[1],
		addr.mac[2],
		addr.mac[3],
		addr.mac[4],
		addr.mac[5]);
}

/*---------------------------------------------------------------------*/

void decode_prim_unit_data_t(prim_unit_data_t * ud)
{
   printk(KERN_ERR "\nsourse_addr: ");
   decode_address_t(ud->source_addr);

   printk(KERN_ERR "\ndest_addr: ");
   decode_address_t(ud->dest_addr);

   decode_frame_t ((frame_t *)ud->unit);
}

void decode_prim_connect_t(prim_connect_t * conn)
{
   printk(KERN_ERR "\nsourse_addr: ");
   decode_address_t(conn->source_addr);

   printk(KERN_ERR "\ndest_addr: ");
   decode_address_t(conn->dest_addr);

   printk(KERN_ERR "\ndevice: %p", conn->device);
   printk(KERN_ERR "\npriority: %i,  connect_handle: %li", conn->priority, conn->connect_handle);
}

void decode_prim_data_t(prim_data_t * data)
{
   printk(KERN_ERR "\npriority: %i,  connect_handle: %li", data->priority, data->connect_handle);
   decode_frame_t ((frame_t *)data->unit);
}

void decode_prim_disconnect_t(prim_disconnect_t * disc)
{
   printk(KERN_ERR "\nconnect_handle: %li", disc->connect_handle);

   printk(KERN_ERR "\nreason: %i ", disc->reason);

   switch (disc->reason)
   {
      case 0:
         printk(KERN_ERR "(RX_DM_RSP_PDU)");
         break;
      case 1:
         printk(KERN_ERR "(RX_DISC_CMD_PDU)");
         break;
      case 2:
         printk(KERN_ERR "(ACK_TIMER_EXPIRED)");
         break;
   }
}

void decode_prim_reset_t(prim_reset_t * res)
{
   printk(KERN_ERR "\nconnect_handle: %li", res->connect_handle);

   printk(KERN_ERR "\nreason: %i ", res->reason);

   switch (res->reason)
   {
      case 1:
         printk(KERN_ERR "(REMOTE)");
         break;
      case 2:
         printk(KERN_ERR "(LOCAL)");
         break;
   }
}

void decode_prim_flow_control_t(prim_flow_control_t * fc)
{
   printk(KERN_ERR "\nconnect_handle: %li, amount: %li", fc->connect_handle, fc->amount);
}

void decode_prim_xid_t(prim_xid_t * xid)
{
   printk(KERN_ERR "\nsourse_addr: ");
   decode_address_t(xid->source_addr);

   printk(KERN_ERR "\ndest_addr: ");
   decode_address_t(xid->dest_addr);

   printk(KERN_ERR "\npriority: %i", xid->priority);
}

void decode_prim_test_t(prim_test_t * test)
{
   printk(KERN_ERR "\nsourse_addr: ");
   decode_address_t(test->source_addr);

   printk(KERN_ERR "\ndest_addr: ");
   decode_address_t(test->dest_addr);

   printk(KERN_ERR "\npriority: %i", test->priority);

   decode_frame_t((frame_t *)test->unit);
}

/*---------------------------------------------------------------------*/

void decode_prim_data_u (prim_data_u * data, int primitive)
{
   switch (primitive)
   {
       case 0:
          decode_prim_unit_data_t (&data->udata);
          break;
       case 1:
          decode_prim_connect_t(&data->conn); 
          break;
       case 2:
          decode_prim_data_t(&data->data); 
          break;
       case 3:
          decode_prim_disconnect_t(&data->disc); 
          break;
       case 4:
          decode_prim_reset_t(&data->res); 
          break;
       case 5:
          decode_prim_flow_control_t(&data->fc); 
          break;
       case 6:
          printk(KERN_ERR "\nDisable primitve !");
          break;
       case 7:
          decode_prim_xid_t(&data->xid); 
          break;
       case 8:
          decode_prim_test_t(&data->test); 
          break;
       default:
          printk(KERN_ERR "\nUnknown primitive");
   } 
}

/*---------------------------------------------------------------------*/

void decode_prim_if_block_t (prim_if_block_t * p)
{
   printk(KERN_ERR "\n+++++++ DECODE_PRIM_IF_BLOCK_T +++++");
   printk(KERN_ERR "\nSap number: %lu", p->sap);
   printk(KERN_ERR "\nPrimitive type: %s", primitives[p->primitive]);
   decode_prim_data_u (p->data, p->primitive);
   printk(KERN_ERR "\n++++++++++++++++++++++++++++++++++++");
}

/*---------------------------------------------------------------------*/

void decode_conn_event_if_t (conn_event_if_t * data, us8 type )
{
   switch (type)
   {
      case 1:
         printk(KERN_ERR "\nEvent: %u", data->a.event);
         break;
      case 2:
         printk(KERN_ERR "\nCondition");
         break;
      case 3:
         printk(KERN_ERR "\nprim: %u (%s)", data->prim.prim, primitives[data->prim.prim]);
         printk(KERN_ERR "\ntype: %u (%s)", data->prim.type, prim_types[data->prim.type]);
         decode_prim_if_block_t(data->prim.data);
         break;
      case 4:
         printk(KERN_ERR "\nEvent: %u", data->pdu.event);
         printk(KERN_ERR "\nreason: %u", data->pdu.reason);
         decode_frame_t(data->pdu.frame);
         break;
      case 5:  /* ACK_TIMER */
      case 6:  /* P_TIMER */
      case 7:  /* REJ_TIMER */
      case 8:  /* BUSY_TIMER */
         printk(KERN_ERR "\nconn: %p, component_handle: %lu", data->tmr.conn, 
                           data->tmr.component_handle);
         printk(KERN_ERR "\ntimer_specific: %p", data->tmr.timer_specific);
         break;
      case 9:
         printk(KERN_ERR "\nstatus: %u", data->rsts.status);
         break;
   }
}

void decode_connect_event_t (conn_state_event_t * ev)
{   
   char * ev_types[] = { "", "SIMPLE", "CONDITION", "PRIM", "PDU",
     "ACK_TIMER", "P_TIMER", "REJ_TIMER", "BUSY_TIMER", "RPT_STATUS" };

   printk(KERN_ERR "\n++++++++ DECODE_CONNECT_EVENT_T ++++");
   printk(KERN_ERR "\nType: %u (%s)", ev->type, ev_types[ev->type]);
   decode_conn_event_if_t(&ev->data, ev->type);
   printk(KERN_ERR "\n++++++++++++++++++++++++++++++++++++");
}


