/* $Id: interrupt.c,v 1.4.8.3 2001/09/23 22:24:59 kai Exp $
 *
 * Copyright (C) 1996  SpellCaster Telecommunications Inc.
 *
 * This software may be used and distributed according to the terms
 * of the GNU General Public License, incorporated herein by reference.
 *
 * For more information, please contact gpl-info@spellcast.com or write:
 *
 *     SpellCaster Telecommunications Inc.
 *     5621 Finch Avenue East, Unit #3
 *     Scarborough, Ontario  Canada
 *     M1B 2T9
 *     +1 (416) 297-8565
 *     +1 (416) 297-6433 Facsimile
 */

#include "includes.h"
#include "hardware.h"
#include "message.h"
#include "card.h"
#include <linux/interrupt.h>

extern int indicate_status(int, int, ulong, char *);
extern void check_phystat(unsigned long);
extern int receivemessage(int, RspMessage *);
extern int sendmessage(int, unsigned int, unsigned int, unsigned int,
        unsigned int, unsigned int, unsigned int, unsigned int *);
extern void rcvpkt(int, RspMessage *);

extern int cinst;
extern board *sc_adapter[];

int get_card_from_irq(int irq)
{
	int i;

	for(i = 0 ; i < cinst ; i++) {
		if(sc_adapter[i]->interrupt == irq)
			return i;
	}
	return -1;
}

/*
 * 
 */
irqreturn_t interrupt_handler(int interrupt, void *cardptr, struct pt_regs *regs)
{

	RspMessage rcvmsg;
	int channel;
	int card;

	card = get_card_from_irq(interrupt);

	if(!IS_VALID_CARD(card)) {
		pr_debug("Invalid param: %d is not a valid card id\n", card);
		return IRQ_NONE;
	}

	pr_debug("%s: Entered Interrupt handler\n",
			sc_adapter[card]->devicename);
	
 	/*
	 * Pull all of the waiting messages off the response queue
	 */
	while (!receivemessage(card, &rcvmsg)) {
		/*
		 * Push the message to the adapter structure for
		 * send_and_receive to snoop
		 */
		if(sc_adapter[card]->want_async_messages)
			memcpy(&(sc_adapter[card]->async_msg),
					&rcvmsg, sizeof(RspMessage));

		channel = (unsigned int) rcvmsg.phy_link_no;
		
		/*
		 * Trap Invalid request messages
		 */
		if(IS_CM_MESSAGE(rcvmsg, 0, 0, Invalid)) {
			pr_debug("%s: Invalid request Message, rsp_status = %d\n", 
				sc_adapter[card]->devicename,
				rcvmsg.rsp_status);
			break;	
		}
		
		/*
		 * Check for a linkRead message
		 */
		if (IS_CE_MESSAGE(rcvmsg, Lnk, 1, Read))
		{
			pr_debug("%s: Received packet 0x%x bytes long at 0x%x\n",
						sc_adapter[card]->devicename,
						rcvmsg.msg_data.response.msg_len,
						rcvmsg.msg_data.response.buff_offset);
			rcvpkt(card, &rcvmsg);
			continue;

		}

		/*
		 * Handle a write acknoledgement
		 */
		if(IS_CE_MESSAGE(rcvmsg, Lnk, 1, Write)) {
			pr_debug("%s: Packet Send ACK on channel %d\n",
				sc_adapter[card]->devicename,
				rcvmsg.phy_link_no);
			sc_adapter[card]->channel[rcvmsg.phy_link_no-1].free_sendbufs++;
			continue;
		}

		/*
		 * Handle a connection message
		 */
		if (IS_CE_MESSAGE(rcvmsg, Phy, 1, Connect)) 
		{
			unsigned int callid;
			setup_parm setup;	
			pr_debug("%s: Connect message: line %d: status %d: cause 0x%x\n",
						sc_adapter[card]->devicename,
						rcvmsg.phy_link_no,
						rcvmsg.rsp_status,
						rcvmsg.msg_data.byte_array[2]);
			
			memcpy(&callid,rcvmsg.msg_data.byte_array,sizeof(int));
			if(callid>=0x8000 && callid<=0xFFFF)
			{		
				pr_debug("%s: Got Dial-Out Rsp\n",
					sc_adapter[card]->devicename);
				indicate_status(card, ISDN_STAT_DCONN,
						(unsigned long)rcvmsg.phy_link_no-1,NULL);
				
			}
			else if(callid>=0x0000 && callid<=0x7FFF)
			{
				pr_debug("%s: Got Incoming Call\n",
						sc_adapter[card]->devicename);
				strcpy(setup.phone,&(rcvmsg.msg_data.byte_array[4]));
				strcpy(setup.eazmsn,
					sc_adapter[card]->channel[rcvmsg.phy_link_no-1].dn);
				setup.si1 = 7;
				setup.si2 = 0;
				setup.plan = 0;
				setup.screen = 0;

				indicate_status(card, ISDN_STAT_ICALL,(unsigned long)rcvmsg.phy_link_no-1,(char *)&setup);
				indicate_status(card, ISDN_STAT_DCONN,(unsigned long)rcvmsg.phy_link_no-1,NULL);
			}
			continue;
		}

		/*
		 * Handle a disconnection message
		 */
		if (IS_CE_MESSAGE(rcvmsg, Phy, 1, Disconnect)) 
		{
			pr_debug("%s: disconnect message: line %d: status %d: cause 0x%x\n",
						sc_adapter[card]->devicename,
						rcvmsg.phy_link_no,
						rcvmsg.rsp_status,
					 	rcvmsg.msg_data.byte_array[2]);

			indicate_status(card, ISDN_STAT_BHUP,(unsigned long)rcvmsg.phy_link_no-1,NULL);
			indicate_status(card, ISDN_STAT_DHUP,(unsigned long)rcvmsg.phy_link_no-1,NULL);
			continue;

		}

		/*
		 * Handle a startProc engine up message
		 */
		if (IS_CM_MESSAGE(rcvmsg, 5, 0, MiscEngineUp)) {
			pr_debug("%s: Received EngineUp message\n",
				sc_adapter[card]->devicename);
			sc_adapter[card]->EngineUp = 1;
			sendmessage(card, CEPID,ceReqTypeCall,ceReqClass0,ceReqCallGetMyNumber,1,0,NULL);
			sendmessage(card, CEPID,ceReqTypeCall,ceReqClass0,ceReqCallGetMyNumber,2,0,NULL);
			init_timer(&sc_adapter[card]->stat_timer);
			sc_adapter[card]->stat_timer.function = check_phystat;
			sc_adapter[card]->stat_timer.data = card;
			sc_adapter[card]->stat_timer.expires = jiffies + CHECKSTAT_TIME;
			add_timer(&sc_adapter[card]->stat_timer);
			continue;
		}

		/*
		 * Start proc response
		 */
		if (IS_CM_MESSAGE(rcvmsg, 2, 0, StartProc)) {
			pr_debug("%s: StartProc Response Status %d\n",
				sc_adapter[card]->devicename,
				rcvmsg.rsp_status);
			continue;
		}

		/*
		 * Handle a GetMyNumber Rsp
		 */
		if (IS_CE_MESSAGE(rcvmsg,Call,0,GetMyNumber)){
			strcpy(sc_adapter[card]->channel[rcvmsg.phy_link_no-1].dn,rcvmsg.msg_data.byte_array);
			continue;
		}
			
		/*
		 * PhyStatus response
		 */
		if(IS_CE_MESSAGE(rcvmsg, Phy, 2, Status)) {
			unsigned int b1stat, b2stat;

			/*
			 * Covert the message data to the adapter->phystat code
			 */
			b1stat = (unsigned int) rcvmsg.msg_data.byte_array[0];
			b2stat = (unsigned int) rcvmsg.msg_data.byte_array[1];

			sc_adapter[card]->nphystat = (b2stat >> 8) | b1stat; /* endian?? */
			pr_debug("%s: PhyStat is 0x%2x\n",
				sc_adapter[card]->devicename,
				sc_adapter[card]->nphystat);
			continue;
		}


		/* 
		 * Handle a GetFramFormat
		 */
		if(IS_CE_MESSAGE(rcvmsg, Call, 0, GetFrameFormat)) {
			if(rcvmsg.msg_data.byte_array[0] != HDLC_PROTO) {
				unsigned int proto = HDLC_PROTO;
				/*
				 * Set board format to HDLC if it wasn't already
				 */
				pr_debug("%s: current frame format: 0x%x, will change to HDLC\n",
						sc_adapter[card]->devicename,
					rcvmsg.msg_data.byte_array[0]);
				sendmessage(card, CEPID, ceReqTypeCall,
						ceReqClass0,
						ceReqCallSetFrameFormat,
						(unsigned char) channel +1,
						1,&proto);
				}
			continue;
		}

		/*
		 * Hmm...
		 */
		pr_debug("%s: Received unhandled message (%d,%d,%d) link %d\n",
			sc_adapter[card]->devicename,
			rcvmsg.type, rcvmsg.class, rcvmsg.code,
			rcvmsg.phy_link_no);

	}	/* while */

	pr_debug("%s: Exiting Interrupt Handler\n",
			sc_adapter[card]->devicename);
	return IRQ_HANDLED;
}
