interrupt.c 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237
  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. #include "includes.h"
  18. #include "hardware.h"
  19. #include "message.h"
  20. #include "card.h"
  21. #include <linux/interrupt.h>
  22. /*
  23. *
  24. */
  25. irqreturn_t interrupt_handler(int dummy, void *card_inst)
  26. {
  27. RspMessage rcvmsg;
  28. int channel;
  29. int card = (int)(unsigned long) card_inst;
  30. if(!IS_VALID_CARD(card)) {
  31. pr_debug("Invalid param: %d is not a valid card id\n", card);
  32. return IRQ_NONE;
  33. }
  34. pr_debug("%s: Entered Interrupt handler\n",
  35. sc_adapter[card]->devicename);
  36. /*
  37. * Pull all of the waiting messages off the response queue
  38. */
  39. while (!receivemessage(card, &rcvmsg)) {
  40. /*
  41. * Push the message to the adapter structure for
  42. * send_and_receive to snoop
  43. */
  44. if(sc_adapter[card]->want_async_messages)
  45. memcpy(&(sc_adapter[card]->async_msg),
  46. &rcvmsg, sizeof(RspMessage));
  47. channel = (unsigned int) rcvmsg.phy_link_no;
  48. /*
  49. * Trap Invalid request messages
  50. */
  51. if(IS_CM_MESSAGE(rcvmsg, 0, 0, Invalid)) {
  52. pr_debug("%s: Invalid request Message, rsp_status = %d\n",
  53. sc_adapter[card]->devicename,
  54. rcvmsg.rsp_status);
  55. break;
  56. }
  57. /*
  58. * Check for a linkRead message
  59. */
  60. if (IS_CE_MESSAGE(rcvmsg, Lnk, 1, Read))
  61. {
  62. pr_debug("%s: Received packet 0x%x bytes long at 0x%lx\n",
  63. sc_adapter[card]->devicename,
  64. rcvmsg.msg_data.response.msg_len,
  65. rcvmsg.msg_data.response.buff_offset);
  66. rcvpkt(card, &rcvmsg);
  67. continue;
  68. }
  69. /*
  70. * Handle a write acknoledgement
  71. */
  72. if(IS_CE_MESSAGE(rcvmsg, Lnk, 1, Write)) {
  73. pr_debug("%s: Packet Send ACK on channel %d\n",
  74. sc_adapter[card]->devicename,
  75. rcvmsg.phy_link_no);
  76. sc_adapter[card]->channel[rcvmsg.phy_link_no-1].free_sendbufs++;
  77. continue;
  78. }
  79. /*
  80. * Handle a connection message
  81. */
  82. if (IS_CE_MESSAGE(rcvmsg, Phy, 1, Connect))
  83. {
  84. unsigned int callid;
  85. setup_parm setup;
  86. pr_debug("%s: Connect message: line %d: status %d: cause 0x%x\n",
  87. sc_adapter[card]->devicename,
  88. rcvmsg.phy_link_no,
  89. rcvmsg.rsp_status,
  90. rcvmsg.msg_data.byte_array[2]);
  91. memcpy(&callid,rcvmsg.msg_data.byte_array,sizeof(int));
  92. if(callid>=0x8000 && callid<=0xFFFF)
  93. {
  94. pr_debug("%s: Got Dial-Out Rsp\n",
  95. sc_adapter[card]->devicename);
  96. indicate_status(card, ISDN_STAT_DCONN,
  97. (unsigned long)rcvmsg.phy_link_no-1,NULL);
  98. }
  99. else if(callid>=0x0000 && callid<=0x7FFF)
  100. {
  101. pr_debug("%s: Got Incoming Call\n",
  102. sc_adapter[card]->devicename);
  103. strcpy(setup.phone,&(rcvmsg.msg_data.byte_array[4]));
  104. strcpy(setup.eazmsn,
  105. sc_adapter[card]->channel[rcvmsg.phy_link_no-1].dn);
  106. setup.si1 = 7;
  107. setup.si2 = 0;
  108. setup.plan = 0;
  109. setup.screen = 0;
  110. indicate_status(card, ISDN_STAT_ICALL,(unsigned long)rcvmsg.phy_link_no-1,(char *)&setup);
  111. indicate_status(card, ISDN_STAT_DCONN,(unsigned long)rcvmsg.phy_link_no-1,NULL);
  112. }
  113. continue;
  114. }
  115. /*
  116. * Handle a disconnection message
  117. */
  118. if (IS_CE_MESSAGE(rcvmsg, Phy, 1, Disconnect))
  119. {
  120. pr_debug("%s: disconnect message: line %d: status %d: cause 0x%x\n",
  121. sc_adapter[card]->devicename,
  122. rcvmsg.phy_link_no,
  123. rcvmsg.rsp_status,
  124. rcvmsg.msg_data.byte_array[2]);
  125. indicate_status(card, ISDN_STAT_BHUP,(unsigned long)rcvmsg.phy_link_no-1,NULL);
  126. indicate_status(card, ISDN_STAT_DHUP,(unsigned long)rcvmsg.phy_link_no-1,NULL);
  127. continue;
  128. }
  129. /*
  130. * Handle a startProc engine up message
  131. */
  132. if (IS_CM_MESSAGE(rcvmsg, 5, 0, MiscEngineUp)) {
  133. pr_debug("%s: Received EngineUp message\n",
  134. sc_adapter[card]->devicename);
  135. sc_adapter[card]->EngineUp = 1;
  136. sendmessage(card, CEPID,ceReqTypeCall,ceReqClass0,ceReqCallGetMyNumber,1,0,NULL);
  137. sendmessage(card, CEPID,ceReqTypeCall,ceReqClass0,ceReqCallGetMyNumber,2,0,NULL);
  138. init_timer(&sc_adapter[card]->stat_timer);
  139. sc_adapter[card]->stat_timer.function = check_phystat;
  140. sc_adapter[card]->stat_timer.data = card;
  141. sc_adapter[card]->stat_timer.expires = jiffies + CHECKSTAT_TIME;
  142. add_timer(&sc_adapter[card]->stat_timer);
  143. continue;
  144. }
  145. /*
  146. * Start proc response
  147. */
  148. if (IS_CM_MESSAGE(rcvmsg, 2, 0, StartProc)) {
  149. pr_debug("%s: StartProc Response Status %d\n",
  150. sc_adapter[card]->devicename,
  151. rcvmsg.rsp_status);
  152. continue;
  153. }
  154. /*
  155. * Handle a GetMyNumber Rsp
  156. */
  157. if (IS_CE_MESSAGE(rcvmsg,Call,0,GetMyNumber)){
  158. strcpy(sc_adapter[card]->channel[rcvmsg.phy_link_no-1].dn,rcvmsg.msg_data.byte_array);
  159. continue;
  160. }
  161. /*
  162. * PhyStatus response
  163. */
  164. if(IS_CE_MESSAGE(rcvmsg, Phy, 2, Status)) {
  165. unsigned int b1stat, b2stat;
  166. /*
  167. * Covert the message data to the adapter->phystat code
  168. */
  169. b1stat = (unsigned int) rcvmsg.msg_data.byte_array[0];
  170. b2stat = (unsigned int) rcvmsg.msg_data.byte_array[1];
  171. sc_adapter[card]->nphystat = (b2stat >> 8) | b1stat; /* endian?? */
  172. pr_debug("%s: PhyStat is 0x%2x\n",
  173. sc_adapter[card]->devicename,
  174. sc_adapter[card]->nphystat);
  175. continue;
  176. }
  177. /*
  178. * Handle a GetFramFormat
  179. */
  180. if(IS_CE_MESSAGE(rcvmsg, Call, 0, GetFrameFormat)) {
  181. if(rcvmsg.msg_data.byte_array[0] != HDLC_PROTO) {
  182. unsigned int proto = HDLC_PROTO;
  183. /*
  184. * Set board format to HDLC if it wasn't already
  185. */
  186. pr_debug("%s: current frame format: 0x%x, will change to HDLC\n",
  187. sc_adapter[card]->devicename,
  188. rcvmsg.msg_data.byte_array[0]);
  189. sendmessage(card, CEPID, ceReqTypeCall,
  190. ceReqClass0,
  191. ceReqCallSetFrameFormat,
  192. (unsigned char) channel +1,
  193. 1,&proto);
  194. }
  195. continue;
  196. }
  197. /*
  198. * Hmm...
  199. */
  200. pr_debug("%s: Received unhandled message (%d,%d,%d) link %d\n",
  201. sc_adapter[card]->devicename,
  202. rcvmsg.type, rcvmsg.class, rcvmsg.code,
  203. rcvmsg.phy_link_no);
  204. } /* while */
  205. pr_debug("%s: Exiting Interrupt Handler\n",
  206. sc_adapter[card]->devicename);
  207. return IRQ_HANDLED;
  208. }