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