message.c 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  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. /*
  24. * receive a message from the board
  25. */
  26. int receivemessage(int card, RspMessage *rspmsg)
  27. {
  28. DualPortMemory *dpm;
  29. unsigned long flags;
  30. if (!IS_VALID_CARD(card)) {
  31. pr_debug("Invalid param: %d is not a valid card id\n", card);
  32. return -EINVAL;
  33. }
  34. pr_debug("%s: Entered receivemessage\n",
  35. sc_adapter[card]->devicename);
  36. /*
  37. * See if there are messages waiting
  38. */
  39. if (inb(sc_adapter[card]->ioport[FIFO_STATUS]) & RF_HAS_DATA) {
  40. /*
  41. * Map in the DPM to the base page and copy the message
  42. */
  43. spin_lock_irqsave(&sc_adapter[card]->lock, flags);
  44. outb((sc_adapter[card]->shmem_magic >> 14) | 0x80,
  45. sc_adapter[card]->ioport[sc_adapter[card]->shmem_pgport]);
  46. dpm = (DualPortMemory *) sc_adapter[card]->rambase;
  47. memcpy_fromio(rspmsg, &(dpm->rsp_queue[dpm->rsp_tail]),
  48. MSG_LEN);
  49. dpm->rsp_tail = (dpm->rsp_tail+1) % MAX_MESSAGES;
  50. inb(sc_adapter[card]->ioport[FIFO_READ]);
  51. spin_unlock_irqrestore(&sc_adapter[card]->lock, flags);
  52. /*
  53. * Tell the board that the message is received
  54. */
  55. pr_debug("%s: Received Message seq:%d pid:%d time:%d cmd:%d "
  56. "cnt:%d (type,class,code):(%d,%d,%d) "
  57. "link:%d stat:0x%x\n",
  58. sc_adapter[card]->devicename,
  59. rspmsg->sequence_no,
  60. rspmsg->process_id,
  61. rspmsg->time_stamp,
  62. rspmsg->cmd_sequence_no,
  63. rspmsg->msg_byte_cnt,
  64. rspmsg->type,
  65. rspmsg->class,
  66. rspmsg->code,
  67. rspmsg->phy_link_no,
  68. rspmsg->rsp_status);
  69. return 0;
  70. }
  71. return -ENOMSG;
  72. }
  73. /*
  74. * send a message to the board
  75. */
  76. int sendmessage(int card,
  77. unsigned int procid,
  78. unsigned int type,
  79. unsigned int class,
  80. unsigned int code,
  81. unsigned int link,
  82. unsigned int data_len,
  83. unsigned int *data)
  84. {
  85. DualPortMemory *dpm;
  86. ReqMessage sndmsg;
  87. unsigned long flags;
  88. if (!IS_VALID_CARD(card)) {
  89. pr_debug("Invalid param: %d is not a valid card id\n", card);
  90. return -EINVAL;
  91. }
  92. /*
  93. * Make sure we only send CEPID messages when the engine is up
  94. * and CMPID messages when it is down
  95. */
  96. if(sc_adapter[card]->EngineUp && procid == CMPID) {
  97. pr_debug("%s: Attempt to send CM message with engine up\n",
  98. sc_adapter[card]->devicename);
  99. return -ESRCH;
  100. }
  101. if(!sc_adapter[card]->EngineUp && procid == CEPID) {
  102. pr_debug("%s: Attempt to send CE message with engine down\n",
  103. sc_adapter[card]->devicename);
  104. return -ESRCH;
  105. }
  106. memset(&sndmsg, 0, MSG_LEN);
  107. sndmsg.msg_byte_cnt = 4;
  108. sndmsg.type = type;
  109. sndmsg.class = class;
  110. sndmsg.code = code;
  111. sndmsg.phy_link_no = link;
  112. if (data_len > 0) {
  113. if (data_len > MSG_DATA_LEN)
  114. data_len = MSG_DATA_LEN;
  115. memcpy(&(sndmsg.msg_data), data, data_len);
  116. sndmsg.msg_byte_cnt = data_len + 8;
  117. }
  118. sndmsg.process_id = procid;
  119. sndmsg.sequence_no = sc_adapter[card]->seq_no++ % 256;
  120. /*
  121. * wait for an empty slot in the queue
  122. */
  123. while (!(inb(sc_adapter[card]->ioport[FIFO_STATUS]) & WF_NOT_FULL))
  124. udelay(1);
  125. /*
  126. * Disable interrupts and map in shared memory
  127. */
  128. spin_lock_irqsave(&sc_adapter[card]->lock, flags);
  129. outb((sc_adapter[card]->shmem_magic >> 14) | 0x80,
  130. sc_adapter[card]->ioport[sc_adapter[card]->shmem_pgport]);
  131. dpm = (DualPortMemory *) sc_adapter[card]->rambase; /* Fix me */
  132. memcpy_toio(&(dpm->req_queue[dpm->req_head]),&sndmsg,MSG_LEN);
  133. dpm->req_head = (dpm->req_head+1) % MAX_MESSAGES;
  134. outb(sndmsg.sequence_no, sc_adapter[card]->ioport[FIFO_WRITE]);
  135. spin_unlock_irqrestore(&sc_adapter[card]->lock, flags);
  136. pr_debug("%s: Sent Message seq:%d pid:%d time:%d "
  137. "cnt:%d (type,class,code):(%d,%d,%d) "
  138. "link:%d\n ",
  139. sc_adapter[card]->devicename,
  140. sndmsg.sequence_no,
  141. sndmsg.process_id,
  142. sndmsg.time_stamp,
  143. sndmsg.msg_byte_cnt,
  144. sndmsg.type,
  145. sndmsg.class,
  146. sndmsg.code,
  147. sndmsg.phy_link_no);
  148. return 0;
  149. }
  150. int send_and_receive(int card,
  151. unsigned int procid,
  152. unsigned char type,
  153. unsigned char class,
  154. unsigned char code,
  155. unsigned char link,
  156. unsigned char data_len,
  157. unsigned char *data,
  158. RspMessage *mesgdata,
  159. int timeout)
  160. {
  161. int retval;
  162. int tries;
  163. if (!IS_VALID_CARD(card)) {
  164. pr_debug("Invalid param: %d is not a valid card id\n", card);
  165. return -EINVAL;
  166. }
  167. sc_adapter[card]->want_async_messages = 1;
  168. retval = sendmessage(card, procid, type, class, code, link,
  169. data_len, (unsigned int *) data);
  170. if (retval) {
  171. pr_debug("%s: SendMessage failed in SAR\n",
  172. sc_adapter[card]->devicename);
  173. sc_adapter[card]->want_async_messages = 0;
  174. return -EIO;
  175. }
  176. tries = 0;
  177. /* wait for the response */
  178. while (tries < timeout) {
  179. schedule_timeout_interruptible(1);
  180. pr_debug("SAR waiting..\n");
  181. /*
  182. * See if we got our message back
  183. */
  184. if ((sc_adapter[card]->async_msg.type == type) &&
  185. (sc_adapter[card]->async_msg.class == class) &&
  186. (sc_adapter[card]->async_msg.code == code) &&
  187. (sc_adapter[card]->async_msg.phy_link_no == link)) {
  188. /*
  189. * Got it!
  190. */
  191. pr_debug("%s: Got ASYNC message\n",
  192. sc_adapter[card]->devicename);
  193. memcpy(mesgdata, &(sc_adapter[card]->async_msg),
  194. sizeof(RspMessage));
  195. sc_adapter[card]->want_async_messages = 0;
  196. return 0;
  197. }
  198. tries++;
  199. }
  200. pr_debug("%s: SAR message timeout\n", sc_adapter[card]->devicename);
  201. sc_adapter[card]->want_async_messages = 0;
  202. return -ETIME;
  203. }