message.c 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. /* $Id: message.c,v 1.5.8.2 2001/09/23 22:24:59 kai Exp $
  2. *
  3. * functions for sending and receiving control messages
  4. *
  5. * Copyright (C) 1996 SpellCaster Telecommunications Inc.
  6. *
  7. * This software may be used and distributed according to the terms
  8. * of the GNU General Public License, incorporated herein by reference.
  9. *
  10. * For more information, please contact gpl-info@spellcast.com or write:
  11. *
  12. * SpellCaster Telecommunications Inc.
  13. * 5621 Finch Avenue East, Unit #3
  14. * Scarborough, Ontario Canada
  15. * M1B 2T9
  16. * +1 (416) 297-8565
  17. * +1 (416) 297-6433 Facsimile
  18. */
  19. #include "includes.h"
  20. #include "hardware.h"
  21. #include "message.h"
  22. #include "card.h"
  23. extern board *sc_adapter[];
  24. extern unsigned int cinst;
  25. /*
  26. * Obligatory function prototypes
  27. */
  28. extern int indicate_status(int,ulong,char*);
  29. extern int scm_command(isdn_ctrl *);
  30. /*
  31. * receive a message from the board
  32. */
  33. int receivemessage(int card, RspMessage *rspmsg)
  34. {
  35. DualPortMemory *dpm;
  36. unsigned long flags;
  37. if (!IS_VALID_CARD(card)) {
  38. pr_debug("Invalid param: %d is not a valid card id\n", card);
  39. return -EINVAL;
  40. }
  41. pr_debug("%s: Entered receivemessage\n",
  42. sc_adapter[card]->devicename);
  43. /*
  44. * See if there are messages waiting
  45. */
  46. if (inb(sc_adapter[card]->ioport[FIFO_STATUS]) & RF_HAS_DATA) {
  47. /*
  48. * Map in the DPM to the base page and copy the message
  49. */
  50. spin_lock_irqsave(&sc_adapter[card]->lock, flags);
  51. outb((sc_adapter[card]->shmem_magic >> 14) | 0x80,
  52. sc_adapter[card]->ioport[sc_adapter[card]->shmem_pgport]);
  53. dpm = (DualPortMemory *) sc_adapter[card]->rambase;
  54. memcpy_fromio(rspmsg, &(dpm->rsp_queue[dpm->rsp_tail]),
  55. MSG_LEN);
  56. dpm->rsp_tail = (dpm->rsp_tail+1) % MAX_MESSAGES;
  57. inb(sc_adapter[card]->ioport[FIFO_READ]);
  58. spin_unlock_irqrestore(&sc_adapter[card]->lock, flags);
  59. /*
  60. * Tell the board that the message is received
  61. */
  62. pr_debug("%s: Received Message seq:%d pid:%d time:%d cmd:%d "
  63. "cnt:%d (type,class,code):(%d,%d,%d) "
  64. "link:%d stat:0x%x\n",
  65. sc_adapter[card]->devicename,
  66. rspmsg->sequence_no,
  67. rspmsg->process_id,
  68. rspmsg->time_stamp,
  69. rspmsg->cmd_sequence_no,
  70. rspmsg->msg_byte_cnt,
  71. rspmsg->type,
  72. rspmsg->class,
  73. rspmsg->code,
  74. rspmsg->phy_link_no,
  75. rspmsg->rsp_status);
  76. return 0;
  77. }
  78. return -ENOMSG;
  79. }
  80. /*
  81. * send a message to the board
  82. */
  83. int sendmessage(int card,
  84. unsigned int procid,
  85. unsigned int type,
  86. unsigned int class,
  87. unsigned int code,
  88. unsigned int link,
  89. unsigned int data_len,
  90. unsigned int *data)
  91. {
  92. DualPortMemory *dpm;
  93. ReqMessage sndmsg;
  94. unsigned long flags;
  95. if (!IS_VALID_CARD(card)) {
  96. pr_debug("Invalid param: %d is not a valid card id\n", card);
  97. return -EINVAL;
  98. }
  99. /*
  100. * Make sure we only send CEPID messages when the engine is up
  101. * and CMPID messages when it is down
  102. */
  103. if(sc_adapter[card]->EngineUp && procid == CMPID) {
  104. pr_debug("%s: Attempt to send CM message with engine up\n",
  105. sc_adapter[card]->devicename);
  106. return -ESRCH;
  107. }
  108. if(!sc_adapter[card]->EngineUp && procid == CEPID) {
  109. pr_debug("%s: Attempt to send CE message with engine down\n",
  110. sc_adapter[card]->devicename);
  111. return -ESRCH;
  112. }
  113. memset(&sndmsg, 0, MSG_LEN);
  114. sndmsg.msg_byte_cnt = 4;
  115. sndmsg.type = type;
  116. sndmsg.class = class;
  117. sndmsg.code = code;
  118. sndmsg.phy_link_no = link;
  119. if (data_len > 0) {
  120. if (data_len > MSG_DATA_LEN)
  121. data_len = MSG_DATA_LEN;
  122. memcpy(&(sndmsg.msg_data), data, data_len);
  123. sndmsg.msg_byte_cnt = data_len + 8;
  124. }
  125. sndmsg.process_id = procid;
  126. sndmsg.sequence_no = sc_adapter[card]->seq_no++ % 256;
  127. /*
  128. * wait for an empty slot in the queue
  129. */
  130. while (!(inb(sc_adapter[card]->ioport[FIFO_STATUS]) & WF_NOT_FULL))
  131. udelay(1);
  132. /*
  133. * Disable interrupts and map in shared memory
  134. */
  135. spin_lock_irqsave(&sc_adapter[card]->lock, flags);
  136. outb((sc_adapter[card]->shmem_magic >> 14) | 0x80,
  137. sc_adapter[card]->ioport[sc_adapter[card]->shmem_pgport]);
  138. dpm = (DualPortMemory *) sc_adapter[card]->rambase; /* Fix me */
  139. memcpy_toio(&(dpm->req_queue[dpm->req_head]),&sndmsg,MSG_LEN);
  140. dpm->req_head = (dpm->req_head+1) % MAX_MESSAGES;
  141. outb(sndmsg.sequence_no, sc_adapter[card]->ioport[FIFO_WRITE]);
  142. spin_unlock_irqrestore(&sc_adapter[card]->lock, flags);
  143. pr_debug("%s: Sent Message seq:%d pid:%d time:%d "
  144. "cnt:%d (type,class,code):(%d,%d,%d) "
  145. "link:%d\n ",
  146. sc_adapter[card]->devicename,
  147. sndmsg.sequence_no,
  148. sndmsg.process_id,
  149. sndmsg.time_stamp,
  150. sndmsg.msg_byte_cnt,
  151. sndmsg.type,
  152. sndmsg.class,
  153. sndmsg.code,
  154. sndmsg.phy_link_no);
  155. return 0;
  156. }
  157. int send_and_receive(int card,
  158. unsigned int procid,
  159. unsigned char type,
  160. unsigned char class,
  161. unsigned char code,
  162. unsigned char link,
  163. unsigned char data_len,
  164. unsigned char *data,
  165. RspMessage *mesgdata,
  166. int timeout)
  167. {
  168. int retval;
  169. int tries;
  170. if (!IS_VALID_CARD(card)) {
  171. pr_debug("Invalid param: %d is not a valid card id\n", card);
  172. return -EINVAL;
  173. }
  174. sc_adapter[card]->want_async_messages = 1;
  175. retval = sendmessage(card, procid, type, class, code, link,
  176. data_len, (unsigned int *) data);
  177. if (retval) {
  178. pr_debug("%s: SendMessage failed in SAR\n",
  179. sc_adapter[card]->devicename);
  180. sc_adapter[card]->want_async_messages = 0;
  181. return -EIO;
  182. }
  183. tries = 0;
  184. /* wait for the response */
  185. while (tries < timeout) {
  186. schedule_timeout_interruptible(1);
  187. pr_debug("SAR waiting..\n");
  188. /*
  189. * See if we got our message back
  190. */
  191. if ((sc_adapter[card]->async_msg.type == type) &&
  192. (sc_adapter[card]->async_msg.class == class) &&
  193. (sc_adapter[card]->async_msg.code == code) &&
  194. (sc_adapter[card]->async_msg.phy_link_no == link)) {
  195. /*
  196. * Got it!
  197. */
  198. pr_debug("%s: Got ASYNC message\n",
  199. sc_adapter[card]->devicename);
  200. memcpy(mesgdata, &(sc_adapter[card]->async_msg),
  201. sizeof(RspMessage));
  202. sc_adapter[card]->want_async_messages = 0;
  203. return 0;
  204. }
  205. tries++;
  206. }
  207. pr_debug("%s: SAR message timeout\n", sc_adapter[card]->devicename);
  208. sc_adapter[card]->want_async_messages = 0;
  209. return -ETIME;
  210. }