Merge tag 'sound-3.10' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / drivers / isdn / sc / message.c
CommitLineData
1da177e4
LT
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 */
e8edc6e0 19#include <linux/sched.h>
1da177e4
LT
20#include "includes.h"
21#include "hardware.h"
22#include "message.h"
23#include "card.h"
24
1da177e4
LT
25/*
26 * receive a message from the board
27 */
475be4d8 28int receivemessage(int card, RspMessage *rspmsg)
1da177e4
LT
29{
30 DualPortMemory *dpm;
31 unsigned long flags;
32
33 if (!IS_VALID_CARD(card)) {
34 pr_debug("Invalid param: %d is not a valid card id\n", card);
35 return -EINVAL;
36 }
475be4d8 37
1da177e4 38 pr_debug("%s: Entered receivemessage\n",
475be4d8 39 sc_adapter[card]->devicename);
1da177e4
LT
40
41 /*
42 * See if there are messages waiting
43 */
44 if (inb(sc_adapter[card]->ioport[FIFO_STATUS]) & RF_HAS_DATA) {
45 /*
46 * Map in the DPM to the base page and copy the message
47 */
48 spin_lock_irqsave(&sc_adapter[card]->lock, flags);
49 outb((sc_adapter[card]->shmem_magic >> 14) | 0x80,
475be4d8 50 sc_adapter[card]->ioport[sc_adapter[card]->shmem_pgport]);
1da177e4 51 dpm = (DualPortMemory *) sc_adapter[card]->rambase;
475be4d8
JP
52 memcpy_fromio(rspmsg, &(dpm->rsp_queue[dpm->rsp_tail]),
53 MSG_LEN);
54 dpm->rsp_tail = (dpm->rsp_tail + 1) % MAX_MESSAGES;
1da177e4
LT
55 inb(sc_adapter[card]->ioport[FIFO_READ]);
56 spin_unlock_irqrestore(&sc_adapter[card]->lock, flags);
57 /*
58 * Tell the board that the message is received
59 */
60 pr_debug("%s: Received Message seq:%d pid:%d time:%d cmd:%d "
475be4d8
JP
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);
1da177e4
LT
74
75 return 0;
76 }
77 return -ENOMSG;
78}
475be4d8 79
1da177e4
LT
80/*
81 * send a message to the board
82 */
83int sendmessage(int card,
84 unsigned int procid,
475be4d8
JP
85 unsigned int type,
86 unsigned int class,
1da177e4 87 unsigned int code,
475be4d8
JP
88 unsigned int link,
89 unsigned int data_len,
90 unsigned int *data)
1da177e4
LT
91{
92 DualPortMemory *dpm;
93 ReqMessage sndmsg;
94 unsigned long flags;
95
96 if (!IS_VALID_CARD(card)) {
97 pr_debug("Invalid param: %d is not a valid card id\n", card);
98 return -EINVAL;
99 }
100
101 /*
102 * Make sure we only send CEPID messages when the engine is up
103 * and CMPID messages when it is down
104 */
475be4d8 105 if (sc_adapter[card]->EngineUp && procid == CMPID) {
1da177e4 106 pr_debug("%s: Attempt to send CM message with engine up\n",
475be4d8 107 sc_adapter[card]->devicename);
1da177e4
LT
108 return -ESRCH;
109 }
110
475be4d8 111 if (!sc_adapter[card]->EngineUp && procid == CEPID) {
1da177e4 112 pr_debug("%s: Attempt to send CE message with engine down\n",
475be4d8 113 sc_adapter[card]->devicename);
1da177e4
LT
114 return -ESRCH;
115 }
116
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;
123
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;
129 }
130
131 sndmsg.process_id = procid;
132 sndmsg.sequence_no = sc_adapter[card]->seq_no++ % 256;
133
134 /*
135 * wait for an empty slot in the queue
136 */
137 while (!(inb(sc_adapter[card]->ioport[FIFO_STATUS]) & WF_NOT_FULL))
138 udelay(1);
139
140 /*
141 * Disable interrupts and map in shared memory
142 */
143 spin_lock_irqsave(&sc_adapter[card]->lock, flags);
144 outb((sc_adapter[card]->shmem_magic >> 14) | 0x80,
475be4d8 145 sc_adapter[card]->ioport[sc_adapter[card]->shmem_pgport]);
1da177e4 146 dpm = (DualPortMemory *) sc_adapter[card]->rambase; /* Fix me */
475be4d8
JP
147 memcpy_toio(&(dpm->req_queue[dpm->req_head]), &sndmsg, MSG_LEN);
148 dpm->req_head = (dpm->req_head + 1) % MAX_MESSAGES;
1da177e4
LT
149 outb(sndmsg.sequence_no, sc_adapter[card]->ioport[FIFO_WRITE]);
150 spin_unlock_irqrestore(&sc_adapter[card]->lock, flags);
475be4d8 151
1da177e4 152 pr_debug("%s: Sent Message seq:%d pid:%d time:%d "
475be4d8
JP
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);
164
1da177e4
LT
165 return 0;
166}
167
168int send_and_receive(int card,
475be4d8
JP
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)
1da177e4
LT
178{
179 int retval;
180 int tries;
181
182 if (!IS_VALID_CARD(card)) {
183 pr_debug("Invalid param: %d is not a valid card id\n", card);
184 return -EINVAL;
185 }
186
187 sc_adapter[card]->want_async_messages = 1;
475be4d8
JP
188 retval = sendmessage(card, procid, type, class, code, link,
189 data_len, (unsigned int *) data);
190
1da177e4
LT
191 if (retval) {
192 pr_debug("%s: SendMessage failed in SAR\n",
475be4d8 193 sc_adapter[card]->devicename);
1da177e4
LT
194 sc_adapter[card]->want_async_messages = 0;
195 return -EIO;
196 }
197
198 tries = 0;
199 /* wait for the response */
200 while (tries < timeout) {
24763c48 201 schedule_timeout_interruptible(1);
475be4d8 202
1da177e4
LT
203 pr_debug("SAR waiting..\n");
204
205 /*
206 * See if we got our message back
207 */
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)) {
212
213 /*
214 * Got it!
215 */
216 pr_debug("%s: Got ASYNC message\n",
475be4d8 217 sc_adapter[card]->devicename);
1da177e4 218 memcpy(mesgdata, &(sc_adapter[card]->async_msg),
475be4d8 219 sizeof(RspMessage));
1da177e4
LT
220 sc_adapter[card]->want_async_messages = 0;
221 return 0;
222 }
223
475be4d8 224 tries++;
1da177e4
LT
225 }
226
227 pr_debug("%s: SAR message timeout\n", sc_adapter[card]->devicename);
228 sc_adapter[card]->want_async_messages = 0;
229 return -ETIME;
230}