interrupt.c 6.7 KB

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