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
17 * +1 (416) 297-6433 Facsimile
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
)
43 if (!IS_VALID_CARD(card
)) {
44 pr_debug("Invalid param: %d is not a valid card id\n", card
);
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
]),
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
,
77 rspmsg
->cmd_sequence_no
,
91 * send a message to the board
93 int sendmessage(int card
,
99 unsigned int data_len
,
106 if (!IS_VALID_CARD(card
)) {
107 pr_debug("Invalid param: %d is not a valid card id\n", card
);
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
);
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
);
127 memset(&sndmsg
, 0, MSG_LEN
);
128 sndmsg
.msg_byte_cnt
= 4;
130 sndmsg
.class = class;
132 sndmsg
.phy_link_no
= link
;
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
))
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) "
165 sc_adapter
[card
]->devicename
,
178 int send_and_receive(int card
,
184 unsigned char data_len
,
186 RspMessage
*mesgdata
,
192 if (!IS_VALID_CARD(card
)) {
193 pr_debug("Invalid param: %d is not a valid card id\n", card
);
197 sc_adapter
[card
]->want_async_messages
= 1;
198 retval
= sendmessage(card
, procid
, type
, class, code
, link
,
199 data_len
, (unsigned int *) data
);
202 pr_debug("%s: SendMessage failed in SAR\n",
203 sc_adapter
[card
]->devicename
);
204 sc_adapter
[card
]->want_async_messages
= 0;
209 /* wait for the response */
210 while (tries
< timeout
) {
211 set_current_state(TASK_INTERRUPTIBLE
);
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
)) {
227 pr_debug("%s: Got ASYNC message\n",
228 sc_adapter
[card
]->devicename
);
229 memcpy(mesgdata
, &(sc_adapter
[card
]->async_msg
),
231 sc_adapter
[card
]->want_async_messages
= 0;
238 pr_debug("%s: SAR message timeout\n", sc_adapter
[card
]->devicename
);
239 sc_adapter
[card
]->want_async_messages
= 0;