linux/drivers/isdn/sc/interrupt.c
<<
>>
Prefs
   1/* $Id: interrupt.c,v 1.4.8.3 2001/09/23 22:24:59 kai Exp $
   2 *
   3 * Copyright (C) 1996  SpellCaster Telecommunications Inc.
   4 *
   5 * This software may be used and distributed according to the terms
   6 * of the GNU General Public License, incorporated herein by reference.
   7 *
   8 * For more information, please contact gpl-info@spellcast.com or write:
   9 *
  10 *     SpellCaster Telecommunications Inc.
  11 *     5621 Finch Avenue East, Unit #3
  12 *     Scarborough, Ontario  Canada
  13 *     M1B 2T9
  14 *     +1 (416) 297-8565
  15 *     +1 (416) 297-6433 Facsimile
  16 */
  17
  18#include "includes.h"
  19#include "hardware.h"
  20#include "message.h"
  21#include "card.h"
  22#include <linux/interrupt.h>
  23
  24/*
  25 * 
  26 */
  27irqreturn_t interrupt_handler(int dummy, void *card_inst)
  28{
  29
  30        RspMessage rcvmsg;
  31        int channel;
  32        int card = (int)(unsigned long) card_inst;
  33
  34        if(!IS_VALID_CARD(card)) {
  35                pr_debug("Invalid param: %d is not a valid card id\n", card);
  36                return IRQ_NONE;
  37        }
  38
  39        pr_debug("%s: Entered Interrupt handler\n",
  40                        sc_adapter[card]->devicename);
  41        
  42        /*
  43         * Pull all of the waiting messages off the response queue
  44         */
  45        while (!receivemessage(card, &rcvmsg)) {
  46                /*
  47                 * Push the message to the adapter structure for
  48                 * send_and_receive to snoop
  49                 */
  50                if(sc_adapter[card]->want_async_messages)
  51                        memcpy(&(sc_adapter[card]->async_msg),
  52                                        &rcvmsg, sizeof(RspMessage));
  53
  54                channel = (unsigned int) rcvmsg.phy_link_no;
  55                
  56                /*
  57                 * Trap Invalid request messages
  58                 */
  59                if(IS_CM_MESSAGE(rcvmsg, 0, 0, Invalid)) {
  60                        pr_debug("%s: Invalid request Message, rsp_status = %d\n", 
  61                                sc_adapter[card]->devicename,
  62                                rcvmsg.rsp_status);
  63                        break;  
  64                }
  65                
  66                /*
  67                 * Check for a linkRead message
  68                 */
  69                if (IS_CE_MESSAGE(rcvmsg, Lnk, 1, Read))
  70                {
  71                        pr_debug("%s: Received packet 0x%x bytes long at 0x%lx\n",
  72                                                sc_adapter[card]->devicename,
  73                                                rcvmsg.msg_data.response.msg_len,
  74                                                rcvmsg.msg_data.response.buff_offset);
  75                        rcvpkt(card, &rcvmsg);
  76                        continue;
  77
  78                }
  79
  80                /*
  81                 * Handle a write acknoledgement
  82                 */
  83                if(IS_CE_MESSAGE(rcvmsg, Lnk, 1, Write)) {
  84                        pr_debug("%s: Packet Send ACK on channel %d\n",
  85                                sc_adapter[card]->devicename,
  86                                rcvmsg.phy_link_no);
  87                        sc_adapter[card]->channel[rcvmsg.phy_link_no-1].free_sendbufs++;
  88                        continue;
  89                }
  90
  91                /*
  92                 * Handle a connection message
  93                 */
  94                if (IS_CE_MESSAGE(rcvmsg, Phy, 1, Connect)) 
  95                {
  96                        unsigned int callid;
  97                        setup_parm setup;       
  98                        pr_debug("%s: Connect message: line %d: status %d: cause 0x%x\n",
  99                                                sc_adapter[card]->devicename,
 100                                                rcvmsg.phy_link_no,
 101                                                rcvmsg.rsp_status,
 102                                                rcvmsg.msg_data.byte_array[2]);
 103                        
 104                        memcpy(&callid,rcvmsg.msg_data.byte_array,sizeof(int));
 105                        if(callid>=0x8000 && callid<=0xFFFF)
 106                        {               
 107                                pr_debug("%s: Got Dial-Out Rsp\n",
 108                                        sc_adapter[card]->devicename);
 109                                indicate_status(card, ISDN_STAT_DCONN,
 110                                                (unsigned long)rcvmsg.phy_link_no-1,NULL);
 111                                
 112                        }
 113                        else if(callid>=0x0000 && callid<=0x7FFF)
 114                        {
 115                                pr_debug("%s: Got Incoming Call\n",
 116                                                sc_adapter[card]->devicename);
 117                                strcpy(setup.phone,&(rcvmsg.msg_data.byte_array[4]));
 118                                strcpy(setup.eazmsn,
 119                                        sc_adapter[card]->channel[rcvmsg.phy_link_no-1].dn);
 120                                setup.si1 = 7;
 121                                setup.si2 = 0;
 122                                setup.plan = 0;
 123                                setup.screen = 0;
 124
 125                                indicate_status(card, ISDN_STAT_ICALL,(unsigned long)rcvmsg.phy_link_no-1,(char *)&setup);
 126                                indicate_status(card, ISDN_STAT_DCONN,(unsigned long)rcvmsg.phy_link_no-1,NULL);
 127                        }
 128                        continue;
 129                }
 130
 131                /*
 132                 * Handle a disconnection message
 133                 */
 134                if (IS_CE_MESSAGE(rcvmsg, Phy, 1, Disconnect)) 
 135                {
 136                        pr_debug("%s: disconnect message: line %d: status %d: cause 0x%x\n",
 137                                                sc_adapter[card]->devicename,
 138                                                rcvmsg.phy_link_no,
 139                                                rcvmsg.rsp_status,
 140                                                rcvmsg.msg_data.byte_array[2]);
 141
 142                        indicate_status(card, ISDN_STAT_BHUP,(unsigned long)rcvmsg.phy_link_no-1,NULL);
 143                        indicate_status(card, ISDN_STAT_DHUP,(unsigned long)rcvmsg.phy_link_no-1,NULL);
 144                        continue;
 145
 146                }
 147
 148                /*
 149                 * Handle a startProc engine up message
 150                 */
 151                if (IS_CM_MESSAGE(rcvmsg, 5, 0, MiscEngineUp)) {
 152                        pr_debug("%s: Received EngineUp message\n",
 153                                sc_adapter[card]->devicename);
 154                        sc_adapter[card]->EngineUp = 1;
 155                        sendmessage(card, CEPID,ceReqTypeCall,ceReqClass0,ceReqCallGetMyNumber,1,0,NULL);
 156                        sendmessage(card, CEPID,ceReqTypeCall,ceReqClass0,ceReqCallGetMyNumber,2,0,NULL);
 157                        init_timer(&sc_adapter[card]->stat_timer);
 158                        sc_adapter[card]->stat_timer.function = check_phystat;
 159                        sc_adapter[card]->stat_timer.data = card;
 160                        sc_adapter[card]->stat_timer.expires = jiffies + CHECKSTAT_TIME;
 161                        add_timer(&sc_adapter[card]->stat_timer);
 162                        continue;
 163                }
 164
 165                /*
 166                 * Start proc response
 167                 */
 168                if (IS_CM_MESSAGE(rcvmsg, 2, 0, StartProc)) {
 169                        pr_debug("%s: StartProc Response Status %d\n",
 170                                sc_adapter[card]->devicename,
 171                                rcvmsg.rsp_status);
 172                        continue;
 173                }
 174
 175                /*
 176                 * Handle a GetMyNumber Rsp
 177                 */
 178                if (IS_CE_MESSAGE(rcvmsg,Call,0,GetMyNumber)){
 179                        strcpy(sc_adapter[card]->channel[rcvmsg.phy_link_no-1].dn,rcvmsg.msg_data.byte_array);
 180                        continue;
 181                }
 182                        
 183                /*
 184                 * PhyStatus response
 185                 */
 186                if(IS_CE_MESSAGE(rcvmsg, Phy, 2, Status)) {
 187                        unsigned int b1stat, b2stat;
 188
 189                        /*
 190                         * Covert the message data to the adapter->phystat code
 191                         */
 192                        b1stat = (unsigned int) rcvmsg.msg_data.byte_array[0];
 193                        b2stat = (unsigned int) rcvmsg.msg_data.byte_array[1];
 194
 195                        sc_adapter[card]->nphystat = (b2stat >> 8) | b1stat; /* endian?? */
 196                        pr_debug("%s: PhyStat is 0x%2x\n",
 197                                sc_adapter[card]->devicename,
 198                                sc_adapter[card]->nphystat);
 199                        continue;
 200                }
 201
 202
 203                /* 
 204                 * Handle a GetFramFormat
 205                 */
 206                if(IS_CE_MESSAGE(rcvmsg, Call, 0, GetFrameFormat)) {
 207                        if(rcvmsg.msg_data.byte_array[0] != HDLC_PROTO) {
 208                                unsigned int proto = HDLC_PROTO;
 209                                /*
 210                                 * Set board format to HDLC if it wasn't already
 211                                 */
 212                                pr_debug("%s: current frame format: 0x%x, will change to HDLC\n",
 213                                                sc_adapter[card]->devicename,
 214                                        rcvmsg.msg_data.byte_array[0]);
 215                                sendmessage(card, CEPID, ceReqTypeCall,
 216                                                ceReqClass0,
 217                                                ceReqCallSetFrameFormat,
 218                                                (unsigned char) channel +1,
 219                                                1,&proto);
 220                                }
 221                        continue;
 222                }
 223
 224                /*
 225                 * Hmm...
 226                 */
 227                pr_debug("%s: Received unhandled message (%d,%d,%d) link %d\n",
 228                        sc_adapter[card]->devicename,
 229                        rcvmsg.type, rcvmsg.class, rcvmsg.code,
 230                        rcvmsg.phy_link_no);
 231
 232        }       /* while */
 233
 234        pr_debug("%s: Exiting Interrupt Handler\n",
 235                        sc_adapter[card]->devicename);
 236        return IRQ_HANDLED;
 237}
 238