interrupt.c 6.4 KB

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