interrupt.c 6.3 KB

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