Linux-2.6.12-rc2
[linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git] / drivers / isdn / sc / message.c
blobca204da3257d3918ae150c30d8b08a2e92bd35db
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
20 #include "includes.h"
21 #include "hardware.h"
22 #include "message.h"
23 #include "card.h"
25 extern board *sc_adapter[];
26 extern unsigned int cinst;
29 * Obligatory function prototypes
31 extern int indicate_status(int,ulong,char*);
32 extern int scm_command(isdn_ctrl *);
36 * receive a message from the board
38 int receivemessage(int card, RspMessage *rspmsg)
40 DualPortMemory *dpm;
41 unsigned long flags;
43 if (!IS_VALID_CARD(card)) {
44 pr_debug("Invalid param: %d is not a valid card id\n", card);
45 return -EINVAL;
48 pr_debug("%s: Entered receivemessage\n",
49 sc_adapter[card]->devicename);
52 * See if there are messages waiting
54 if (inb(sc_adapter[card]->ioport[FIFO_STATUS]) & RF_HAS_DATA) {
56 * Map in the DPM to the base page and copy the message
58 spin_lock_irqsave(&sc_adapter[card]->lock, flags);
59 outb((sc_adapter[card]->shmem_magic >> 14) | 0x80,
60 sc_adapter[card]->ioport[sc_adapter[card]->shmem_pgport]);
61 dpm = (DualPortMemory *) sc_adapter[card]->rambase;
62 memcpy_fromio(rspmsg, &(dpm->rsp_queue[dpm->rsp_tail]),
63 MSG_LEN);
64 dpm->rsp_tail = (dpm->rsp_tail+1) % MAX_MESSAGES;
65 inb(sc_adapter[card]->ioport[FIFO_READ]);
66 spin_unlock_irqrestore(&sc_adapter[card]->lock, flags);
68 * Tell the board that the message is received
70 pr_debug("%s: Received Message seq:%d pid:%d time:%d cmd:%d "
71 "cnt:%d (type,class,code):(%d,%d,%d) "
72 "link:%d stat:0x%x\n",
73 sc_adapter[card]->devicename,
74 rspmsg->sequence_no,
75 rspmsg->process_id,
76 rspmsg->time_stamp,
77 rspmsg->cmd_sequence_no,
78 rspmsg->msg_byte_cnt,
79 rspmsg->type,
80 rspmsg->class,
81 rspmsg->code,
82 rspmsg->phy_link_no,
83 rspmsg->rsp_status);
85 return 0;
87 return -ENOMSG;
91 * send a message to the board
93 int sendmessage(int card,
94 unsigned int procid,
95 unsigned int type,
96 unsigned int class,
97 unsigned int code,
98 unsigned int link,
99 unsigned int data_len,
100 unsigned int *data)
102 DualPortMemory *dpm;
103 ReqMessage sndmsg;
104 unsigned long flags;
106 if (!IS_VALID_CARD(card)) {
107 pr_debug("Invalid param: %d is not a valid card id\n", card);
108 return -EINVAL;
112 * Make sure we only send CEPID messages when the engine is up
113 * and CMPID messages when it is down
115 if(sc_adapter[card]->EngineUp && procid == CMPID) {
116 pr_debug("%s: Attempt to send CM message with engine up\n",
117 sc_adapter[card]->devicename);
118 return -ESRCH;
121 if(!sc_adapter[card]->EngineUp && procid == CEPID) {
122 pr_debug("%s: Attempt to send CE message with engine down\n",
123 sc_adapter[card]->devicename);
124 return -ESRCH;
127 memset(&sndmsg, 0, MSG_LEN);
128 sndmsg.msg_byte_cnt = 4;
129 sndmsg.type = type;
130 sndmsg.class = class;
131 sndmsg.code = code;
132 sndmsg.phy_link_no = link;
134 if (data_len > 0) {
135 if (data_len > MSG_DATA_LEN)
136 data_len = MSG_DATA_LEN;
137 memcpy(&(sndmsg.msg_data), data, data_len);
138 sndmsg.msg_byte_cnt = data_len + 8;
141 sndmsg.process_id = procid;
142 sndmsg.sequence_no = sc_adapter[card]->seq_no++ % 256;
145 * wait for an empty slot in the queue
147 while (!(inb(sc_adapter[card]->ioport[FIFO_STATUS]) & WF_NOT_FULL))
148 udelay(1);
151 * Disable interrupts and map in shared memory
153 spin_lock_irqsave(&sc_adapter[card]->lock, flags);
154 outb((sc_adapter[card]->shmem_magic >> 14) | 0x80,
155 sc_adapter[card]->ioport[sc_adapter[card]->shmem_pgport]);
156 dpm = (DualPortMemory *) sc_adapter[card]->rambase; /* Fix me */
157 memcpy_toio(&(dpm->req_queue[dpm->req_head]),&sndmsg,MSG_LEN);
158 dpm->req_head = (dpm->req_head+1) % MAX_MESSAGES;
159 outb(sndmsg.sequence_no, sc_adapter[card]->ioport[FIFO_WRITE]);
160 spin_unlock_irqrestore(&sc_adapter[card]->lock, flags);
162 pr_debug("%s: Sent Message seq:%d pid:%d time:%d "
163 "cnt:%d (type,class,code):(%d,%d,%d) "
164 "link:%d\n ",
165 sc_adapter[card]->devicename,
166 sndmsg.sequence_no,
167 sndmsg.process_id,
168 sndmsg.time_stamp,
169 sndmsg.msg_byte_cnt,
170 sndmsg.type,
171 sndmsg.class,
172 sndmsg.code,
173 sndmsg.phy_link_no);
175 return 0;
178 int send_and_receive(int card,
179 unsigned int procid,
180 unsigned char type,
181 unsigned char class,
182 unsigned char code,
183 unsigned char link,
184 unsigned char data_len,
185 unsigned char *data,
186 RspMessage *mesgdata,
187 int timeout)
189 int retval;
190 int tries;
192 if (!IS_VALID_CARD(card)) {
193 pr_debug("Invalid param: %d is not a valid card id\n", card);
194 return -EINVAL;
197 sc_adapter[card]->want_async_messages = 1;
198 retval = sendmessage(card, procid, type, class, code, link,
199 data_len, (unsigned int *) data);
201 if (retval) {
202 pr_debug("%s: SendMessage failed in SAR\n",
203 sc_adapter[card]->devicename);
204 sc_adapter[card]->want_async_messages = 0;
205 return -EIO;
208 tries = 0;
209 /* wait for the response */
210 while (tries < timeout) {
211 set_current_state(TASK_INTERRUPTIBLE);
212 schedule_timeout(1);
214 pr_debug("SAR waiting..\n");
217 * See if we got our message back
219 if ((sc_adapter[card]->async_msg.type == type) &&
220 (sc_adapter[card]->async_msg.class == class) &&
221 (sc_adapter[card]->async_msg.code == code) &&
222 (sc_adapter[card]->async_msg.phy_link_no == link)) {
225 * Got it!
227 pr_debug("%s: Got ASYNC message\n",
228 sc_adapter[card]->devicename);
229 memcpy(mesgdata, &(sc_adapter[card]->async_msg),
230 sizeof(RspMessage));
231 sc_adapter[card]->want_async_messages = 0;
232 return 0;
235 tries++;
238 pr_debug("%s: SAR message timeout\n", sc_adapter[card]->devicename);
239 sc_adapter[card]->want_async_messages = 0;
240 return -ETIME;