Linux 2.6.26-rc5
[linux-2.6/openmoko-kernel/knife-kernel.git] / drivers / isdn / sc / message.c
blob0b4c4f15abdd59496129f9103417c7ae55fc187a
1 /* $Id: message.c,v 1.5.8.2 2001/09/23 22:24:59 kai Exp $
3 * functions for sending and receiving control messages
5 * Copyright (C) 1996 SpellCaster Telecommunications Inc.
7 * This software may be used and distributed according to the terms
8 * of the GNU General Public License, incorporated herein by reference.
10 * For more information, please contact gpl-info@spellcast.com or write:
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
19 #include <linux/sched.h>
20 #include "includes.h"
21 #include "hardware.h"
22 #include "message.h"
23 #include "card.h"
26 * receive a message from the board
28 int receivemessage(int card, RspMessage *rspmsg)
30 DualPortMemory *dpm;
31 unsigned long flags;
33 if (!IS_VALID_CARD(card)) {
34 pr_debug("Invalid param: %d is not a valid card id\n", card);
35 return -EINVAL;
38 pr_debug("%s: Entered receivemessage\n",
39 sc_adapter[card]->devicename);
42 * See if there are messages waiting
44 if (inb(sc_adapter[card]->ioport[FIFO_STATUS]) & RF_HAS_DATA) {
46 * Map in the DPM to the base page and copy the message
48 spin_lock_irqsave(&sc_adapter[card]->lock, flags);
49 outb((sc_adapter[card]->shmem_magic >> 14) | 0x80,
50 sc_adapter[card]->ioport[sc_adapter[card]->shmem_pgport]);
51 dpm = (DualPortMemory *) sc_adapter[card]->rambase;
52 memcpy_fromio(rspmsg, &(dpm->rsp_queue[dpm->rsp_tail]),
53 MSG_LEN);
54 dpm->rsp_tail = (dpm->rsp_tail+1) % MAX_MESSAGES;
55 inb(sc_adapter[card]->ioport[FIFO_READ]);
56 spin_unlock_irqrestore(&sc_adapter[card]->lock, flags);
58 * Tell the board that the message is received
60 pr_debug("%s: Received Message seq:%d pid:%d time:%d cmd:%d "
61 "cnt:%d (type,class,code):(%d,%d,%d) "
62 "link:%d stat:0x%x\n",
63 sc_adapter[card]->devicename,
64 rspmsg->sequence_no,
65 rspmsg->process_id,
66 rspmsg->time_stamp,
67 rspmsg->cmd_sequence_no,
68 rspmsg->msg_byte_cnt,
69 rspmsg->type,
70 rspmsg->class,
71 rspmsg->code,
72 rspmsg->phy_link_no,
73 rspmsg->rsp_status);
75 return 0;
77 return -ENOMSG;
81 * send a message to the board
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)
92 DualPortMemory *dpm;
93 ReqMessage sndmsg;
94 unsigned long flags;
96 if (!IS_VALID_CARD(card)) {
97 pr_debug("Invalid param: %d is not a valid card id\n", card);
98 return -EINVAL;
102 * Make sure we only send CEPID messages when the engine is up
103 * and CMPID messages when it is down
105 if(sc_adapter[card]->EngineUp && procid == CMPID) {
106 pr_debug("%s: Attempt to send CM message with engine up\n",
107 sc_adapter[card]->devicename);
108 return -ESRCH;
111 if(!sc_adapter[card]->EngineUp && procid == CEPID) {
112 pr_debug("%s: Attempt to send CE message with engine down\n",
113 sc_adapter[card]->devicename);
114 return -ESRCH;
117 memset(&sndmsg, 0, MSG_LEN);
118 sndmsg.msg_byte_cnt = 4;
119 sndmsg.type = type;
120 sndmsg.class = class;
121 sndmsg.code = code;
122 sndmsg.phy_link_no = link;
124 if (data_len > 0) {
125 if (data_len > MSG_DATA_LEN)
126 data_len = MSG_DATA_LEN;
127 memcpy(&(sndmsg.msg_data), data, data_len);
128 sndmsg.msg_byte_cnt = data_len + 8;
131 sndmsg.process_id = procid;
132 sndmsg.sequence_no = sc_adapter[card]->seq_no++ % 256;
135 * wait for an empty slot in the queue
137 while (!(inb(sc_adapter[card]->ioport[FIFO_STATUS]) & WF_NOT_FULL))
138 udelay(1);
141 * Disable interrupts and map in shared memory
143 spin_lock_irqsave(&sc_adapter[card]->lock, flags);
144 outb((sc_adapter[card]->shmem_magic >> 14) | 0x80,
145 sc_adapter[card]->ioport[sc_adapter[card]->shmem_pgport]);
146 dpm = (DualPortMemory *) sc_adapter[card]->rambase; /* Fix me */
147 memcpy_toio(&(dpm->req_queue[dpm->req_head]),&sndmsg,MSG_LEN);
148 dpm->req_head = (dpm->req_head+1) % MAX_MESSAGES;
149 outb(sndmsg.sequence_no, sc_adapter[card]->ioport[FIFO_WRITE]);
150 spin_unlock_irqrestore(&sc_adapter[card]->lock, flags);
152 pr_debug("%s: Sent Message seq:%d pid:%d time:%d "
153 "cnt:%d (type,class,code):(%d,%d,%d) "
154 "link:%d\n ",
155 sc_adapter[card]->devicename,
156 sndmsg.sequence_no,
157 sndmsg.process_id,
158 sndmsg.time_stamp,
159 sndmsg.msg_byte_cnt,
160 sndmsg.type,
161 sndmsg.class,
162 sndmsg.code,
163 sndmsg.phy_link_no);
165 return 0;
168 int send_and_receive(int card,
169 unsigned int procid,
170 unsigned char type,
171 unsigned char class,
172 unsigned char code,
173 unsigned char link,
174 unsigned char data_len,
175 unsigned char *data,
176 RspMessage *mesgdata,
177 int timeout)
179 int retval;
180 int tries;
182 if (!IS_VALID_CARD(card)) {
183 pr_debug("Invalid param: %d is not a valid card id\n", card);
184 return -EINVAL;
187 sc_adapter[card]->want_async_messages = 1;
188 retval = sendmessage(card, procid, type, class, code, link,
189 data_len, (unsigned int *) data);
191 if (retval) {
192 pr_debug("%s: SendMessage failed in SAR\n",
193 sc_adapter[card]->devicename);
194 sc_adapter[card]->want_async_messages = 0;
195 return -EIO;
198 tries = 0;
199 /* wait for the response */
200 while (tries < timeout) {
201 schedule_timeout_interruptible(1);
203 pr_debug("SAR waiting..\n");
206 * See if we got our message back
208 if ((sc_adapter[card]->async_msg.type == type) &&
209 (sc_adapter[card]->async_msg.class == class) &&
210 (sc_adapter[card]->async_msg.code == code) &&
211 (sc_adapter[card]->async_msg.phy_link_no == link)) {
214 * Got it!
216 pr_debug("%s: Got ASYNC message\n",
217 sc_adapter[card]->devicename);
218 memcpy(mesgdata, &(sc_adapter[card]->async_msg),
219 sizeof(RspMessage));
220 sc_adapter[card]->want_async_messages = 0;
221 return 0;
224 tries++;
227 pr_debug("%s: SAR message timeout\n", sc_adapter[card]->devicename);
228 sc_adapter[card]->want_async_messages = 0;
229 return -ETIME;