diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
commit | 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch) | |
tree | 0bba044c4ce775e45a88a51686b5d9f90697ea9d /drivers/isdn/sc/message.c |
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.
Let it rip!
Diffstat (limited to 'drivers/isdn/sc/message.c')
-rw-r--r-- | drivers/isdn/sc/message.c | 241 |
1 files changed, 241 insertions, 0 deletions
diff --git a/drivers/isdn/sc/message.c b/drivers/isdn/sc/message.c new file mode 100644 index 000000000000..ca204da3257d --- /dev/null +++ b/drivers/isdn/sc/message.c | |||
@@ -0,0 +1,241 @@ | |||
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 | |||
20 | #include "includes.h" | ||
21 | #include "hardware.h" | ||
22 | #include "message.h" | ||
23 | #include "card.h" | ||
24 | |||
25 | extern board *sc_adapter[]; | ||
26 | extern unsigned int cinst; | ||
27 | |||
28 | /* | ||
29 | * Obligatory function prototypes | ||
30 | */ | ||
31 | extern int indicate_status(int,ulong,char*); | ||
32 | extern int scm_command(isdn_ctrl *); | ||
33 | |||
34 | |||
35 | /* | ||
36 | * receive a message from the board | ||
37 | */ | ||
38 | int receivemessage(int card, RspMessage *rspmsg) | ||
39 | { | ||
40 | DualPortMemory *dpm; | ||
41 | unsigned long flags; | ||
42 | |||
43 | if (!IS_VALID_CARD(card)) { | ||
44 | pr_debug("Invalid param: %d is not a valid card id\n", card); | ||
45 | return -EINVAL; | ||
46 | } | ||
47 | |||
48 | pr_debug("%s: Entered receivemessage\n", | ||
49 | sc_adapter[card]->devicename); | ||
50 | |||
51 | /* | ||
52 | * See if there are messages waiting | ||
53 | */ | ||
54 | if (inb(sc_adapter[card]->ioport[FIFO_STATUS]) & RF_HAS_DATA) { | ||
55 | /* | ||
56 | * Map in the DPM to the base page and copy the message | ||
57 | */ | ||
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); | ||
67 | /* | ||
68 | * Tell the board that the message is received | ||
69 | */ | ||
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); | ||
84 | |||
85 | return 0; | ||
86 | } | ||
87 | return -ENOMSG; | ||
88 | } | ||
89 | |||
90 | /* | ||
91 | * send a message to the board | ||
92 | */ | ||
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) | ||
101 | { | ||
102 | DualPortMemory *dpm; | ||
103 | ReqMessage sndmsg; | ||
104 | unsigned long flags; | ||
105 | |||
106 | if (!IS_VALID_CARD(card)) { | ||
107 | pr_debug("Invalid param: %d is not a valid card id\n", card); | ||
108 | return -EINVAL; | ||
109 | } | ||
110 | |||
111 | /* | ||
112 | * Make sure we only send CEPID messages when the engine is up | ||
113 | * and CMPID messages when it is down | ||
114 | */ | ||
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; | ||
119 | } | ||
120 | |||
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; | ||
125 | } | ||
126 | |||
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; | ||
133 | |||
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; | ||
139 | } | ||
140 | |||
141 | sndmsg.process_id = procid; | ||
142 | sndmsg.sequence_no = sc_adapter[card]->seq_no++ % 256; | ||
143 | |||
144 | /* | ||
145 | * wait for an empty slot in the queue | ||
146 | */ | ||
147 | while (!(inb(sc_adapter[card]->ioport[FIFO_STATUS]) & WF_NOT_FULL)) | ||
148 | udelay(1); | ||
149 | |||
150 | /* | ||
151 | * Disable interrupts and map in shared memory | ||
152 | */ | ||
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); | ||
161 | |||
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); | ||
174 | |||
175 | return 0; | ||
176 | } | ||
177 | |||
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) | ||
188 | { | ||
189 | int retval; | ||
190 | int tries; | ||
191 | |||
192 | if (!IS_VALID_CARD(card)) { | ||
193 | pr_debug("Invalid param: %d is not a valid card id\n", card); | ||
194 | return -EINVAL; | ||
195 | } | ||
196 | |||
197 | sc_adapter[card]->want_async_messages = 1; | ||
198 | retval = sendmessage(card, procid, type, class, code, link, | ||
199 | data_len, (unsigned int *) data); | ||
200 | |||
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; | ||
206 | } | ||
207 | |||
208 | tries = 0; | ||
209 | /* wait for the response */ | ||
210 | while (tries < timeout) { | ||
211 | set_current_state(TASK_INTERRUPTIBLE); | ||
212 | schedule_timeout(1); | ||
213 | |||
214 | pr_debug("SAR waiting..\n"); | ||
215 | |||
216 | /* | ||
217 | * See if we got our message back | ||
218 | */ | ||
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)) { | ||
223 | |||
224 | /* | ||
225 | * Got it! | ||
226 | */ | ||
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; | ||
233 | } | ||
234 | |||
235 | tries++; | ||
236 | } | ||
237 | |||
238 | pr_debug("%s: SAR message timeout\n", sc_adapter[card]->devicename); | ||
239 | sc_adapter[card]->want_async_messages = 0; | ||
240 | return -ETIME; | ||
241 | } | ||