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                                int len;
 116
 117                                pr_debug("%s: Got Incoming Call\n",
 118                                         sc_adapter[card]->devicename);
 119                                len = strlcpy(setup.phone, &(rcvmsg.msg_data.byte_array[4]),
 120                                              sizeof(setup.phone));
 121                                if (len >= sizeof(setup.phone))
 122                                        continue;
 123                                len = strlcpy(setup.eazmsn,
 124                                              sc_adapter[card]->channel[rcvmsg.phy_link_no - 1].dn,
 125                                              sizeof(setup.eazmsn));
 126                                if (len >= sizeof(setup.eazmsn))
 127                                        continue;
 128                                setup.si1 = 7;
 129                                setup.si2 = 0;
 130                                setup.plan = 0;
 131                                setup.screen = 0;
 132
 133                                indicate_status(card, ISDN_STAT_ICALL, (unsigned long)rcvmsg.phy_link_no - 1, (char *)&setup);
 134                                indicate_status(card, ISDN_STAT_DCONN, (unsigned long)rcvmsg.phy_link_no - 1, NULL);
 135                        }
 136                        continue;
 137                }
 138
 139                /*
 140                 * Handle a disconnection message
 141                 */
 142                if (IS_CE_MESSAGE(rcvmsg, Phy, 1, Disconnect))
 143                {
 144                        pr_debug("%s: disconnect message: line %d: status %d: cause 0x%x\n",
 145                                 sc_adapter[card]->devicename,
 146                                 rcvmsg.phy_link_no,
 147                                 rcvmsg.rsp_status,
 148                                 rcvmsg.msg_data.byte_array[2]);
 149
 150                        indicate_status(card, ISDN_STAT_BHUP, (unsigned long)rcvmsg.phy_link_no - 1, NULL);
 151                        indicate_status(card, ISDN_STAT_DHUP, (unsigned long)rcvmsg.phy_link_no - 1, NULL);
 152                        continue;
 153
 154                }
 155
 156                /*
 157                 * Handle a startProc engine up message
 158                 */
 159                if (IS_CM_MESSAGE(rcvmsg, 5, 0, MiscEngineUp)) {
 160                        pr_debug("%s: Received EngineUp message\n",
 161                                 sc_adapter[card]->devicename);
 162                        sc_adapter[card]->EngineUp = 1;
 163                        sendmessage(card, CEPID, ceReqTypeCall, ceReqClass0, ceReqCallGetMyNumber, 1, 0, NULL);
 164                        sendmessage(card, CEPID, ceReqTypeCall, ceReqClass0, ceReqCallGetMyNumber, 2, 0, NULL);
 165                        init_timer(&sc_adapter[card]->stat_timer);
 166                        sc_adapter[card]->stat_timer.function = check_phystat;
 167                        sc_adapter[card]->stat_timer.data = card;
 168                        sc_adapter[card]->stat_timer.expires = jiffies + CHECKSTAT_TIME;
 169                        add_timer(&sc_adapter[card]->stat_timer);
 170                        continue;
 171                }
 172
 173                /*
 174                 * Start proc response
 175                 */
 176                if (IS_CM_MESSAGE(rcvmsg, 2, 0, StartProc)) {
 177                        pr_debug("%s: StartProc Response Status %d\n",
 178                                 sc_adapter[card]->devicename,
 179                                 rcvmsg.rsp_status);
 180                        continue;
 181                }
 182
 183                /*
 184                 * Handle a GetMyNumber Rsp
 185                 */
 186                if (IS_CE_MESSAGE(rcvmsg, Call, 0, GetMyNumber)) {
 187                        strlcpy(sc_adapter[card]->channel[rcvmsg.phy_link_no - 1].dn,
 188                                rcvmsg.msg_data.byte_array,
 189                                sizeof(rcvmsg.msg_data.byte_array));
 190                        continue;
 191                }
 192
 193                /*
 194                 * PhyStatus response
 195                 */
 196                if (IS_CE_MESSAGE(rcvmsg, Phy, 2, Status)) {
 197                        unsigned int b1stat, b2stat;
 198
 199                        /*
 200                         * Covert the message data to the adapter->phystat code
 201                         */
 202                        b1stat = (unsigned int) rcvmsg.msg_data.byte_array[0];
 203                        b2stat = (unsigned int) rcvmsg.msg_data.byte_array[1];
 204
 205                        sc_adapter[card]->nphystat = (b2stat >> 8) | b1stat; /* endian?? */
 206                        pr_debug("%s: PhyStat is 0x%2x\n",
 207                                 sc_adapter[card]->devicename,
 208                                 sc_adapter[card]->nphystat);
 209                        continue;
 210                }
 211
 212
 213                /*
 214                 * Handle a GetFramFormat
 215                 */
 216                if (IS_CE_MESSAGE(rcvmsg, Call, 0, GetFrameFormat)) {
 217                        if (rcvmsg.msg_data.byte_array[0] != HDLC_PROTO) {
 218                                unsigned int proto = HDLC_PROTO;
 219                                /*
 220                                 * Set board format to HDLC if it wasn't already
 221                                 */
 222                                pr_debug("%s: current frame format: 0x%x, will change to HDLC\n",
 223                                         sc_adapter[card]->devicename,
 224                                         rcvmsg.msg_data.byte_array[0]);
 225                                sendmessage(card, CEPID, ceReqTypeCall,
 226                                            ceReqClass0,
 227                                            ceReqCallSetFrameFormat,
 228                                            (unsigned char)channel + 1,
 229                                            1, &proto);
 230                        }
 231                        continue;
 232                }
 233
 234                /*
 235                 * Hmm...
 236                 */
 237                pr_debug("%s: Received unhandled message (%d,%d,%d) link %d\n",
 238                         sc_adapter[card]->devicename,
 239                         rcvmsg.type, rcvmsg.class, rcvmsg.code,
 240                         rcvmsg.phy_link_no);
 241
 242        }       /* while */
 243
 244        pr_debug("%s: Exiting Interrupt Handler\n",
 245                 sc_adapter[card]->devicename);
 246        return IRQ_HANDLED;
 247}
 248