1 /* $Id: tpam_queues.c,v 1.1.2.1 2001/11/20 14:19:37 kai Exp $
2 *
3 * Turbo PAM ISDN driver for Linux. (Kernel Driver)
4 *
5 * Copyright 2001 Stelian Pop <stelian.pop@fr.alcove.com>, Alc�ve
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 all support questions please contact: <support@auvertech.fr>
11 *
12 */
13
14 #include <linux/pci.h>
15 #include <linux/sched.h>
16 #include <linux/tqueue.h>
17 #include <linux/interrupt.h>
18 #include <asm/io.h>
19
20 #include "tpam.h"
21
22 /* Local function prototype */
23 static int tpam_sendpacket(tpam_card *card, tpam_channel *channel);
24
25 /*
26 * Queue a message to be send to the card when possible.
27 *
28 * card: the board
29 * skb: the sk_buff containing the message.
30 */
tpam_enqueue(tpam_card * card,struct sk_buff * skb)31 void tpam_enqueue(tpam_card *card, struct sk_buff *skb) {
32
33 dprintk("TurboPAM(tpam_enqueue): card=%d\n", card->id);
34
35 /* queue the sk_buff on the board's send queue */
36 skb_queue_tail(&card->sendq, skb);
37
38 /* queue the board's send task struct for immediate treatment */
39 queue_task(&card->send_tq, &tq_immediate);
40 mark_bh(IMMEDIATE_BH);
41 }
42
43 /*
44 * Queue a data message to be send to the card when possible.
45 *
46 * card: the board
47 * skb: the sk_buff containing the message and the data. This parameter
48 * can be NULL if we want just to trigger the send of queued
49 * messages.
50 */
tpam_enqueue_data(tpam_channel * channel,struct sk_buff * skb)51 void tpam_enqueue_data(tpam_channel *channel, struct sk_buff *skb) {
52
53 dprintk("TurboPAM(tpam_enqueue_data): card=%d, channel=%d\n",
54 channel->card->id, channel->num);
55
56 /* if existant, queue the sk_buff on the channel's send queue */
57 if (skb)
58 skb_queue_tail(&channel->sendq, skb);
59
60 /* queue the channel's send task struct for immediate treatment */
61 queue_task(&channel->card->send_tq, &tq_immediate);
62 mark_bh(IMMEDIATE_BH);
63 }
64
65 /*
66 * IRQ handler.
67 *
68 * If a message comes from the board we read it, construct a sk_buff containing
69 * the message and we queue the sk_buff on the board's receive queue, and we
70 * trigger the execution of the board's receive task queue.
71 *
72 * If a message ack comes from the board we can go on and send a new message,
73 * so we trigger the execution of the board's send task queue.
74 *
75 * irq: the irq number
76 * dev_id: the registered board to the irq
77 * regs: not used.
78 */
tpam_irq(int irq,void * dev_id,struct pt_regs * regs)79 void tpam_irq(int irq, void *dev_id, struct pt_regs *regs) {
80 tpam_card *card = (tpam_card *)dev_id;
81 u32 ackupload, uploadptr;
82 u32 waiting_too_long;
83 u32 hpic;
84 struct sk_buff *skb;
85 pci_mpb mpb;
86 skb_header *skbh;
87
88 dprintk("TurboPAM(tpam_irq): IRQ received, card=%d\n", card->id);
89
90 /* grab the board lock */
91 spin_lock(&card->lock);
92
93 /* get the message type */
94 ackupload = copy_from_pam_dword(card, (void *)TPAM_ACKUPLOAD_REGISTER);
95
96 /* acknowledge the interrupt */
97 copy_to_pam_dword(card, (void *)TPAM_INTERRUPTACK_REGISTER, 0);
98 readl(card->bar0 + TPAM_HINTACK_REGISTER);
99
100 if (!ackupload) {
101 /* it is a new message from the board */
102
103 dprintk("TurboPAM(tpam_irq): message received, card=%d\n",
104 card->id);
105
106 /* get the upload pointer */
107 uploadptr = copy_from_pam_dword(card,
108 (void *)TPAM_UPLOADPTR_REGISTER);
109
110 /* get the beginning of the message (pci_mpb part) */
111 copy_from_pam(card, &mpb, (void *)uploadptr, sizeof(pci_mpb));
112
113 /* allocate the sk_buff */
114 if (!(skb = alloc_skb(sizeof(skb_header) + sizeof(pci_mpb) +
115 mpb.actualBlockTLVSize +
116 mpb.actualDataSize, GFP_ATOMIC))) {
117 printk(KERN_ERR "TurboPAM(tpam_irq): "
118 "alloc_skb failed\n");
119 spin_unlock(&card->lock);
120 return;
121 }
122
123 /* build the skb_header */
124 skbh = (skb_header *)skb_put(skb, sizeof(skb_header));
125 skbh->size = sizeof(pci_mpb) + mpb.actualBlockTLVSize;
126 skbh->data_size = mpb.actualDataSize;
127 skbh->ack = 0;
128 skbh->ack_size = 0;
129
130 /* copy the pci_mpb into the sk_buff */
131 memcpy(skb_put(skb, sizeof(pci_mpb)), &mpb, sizeof(pci_mpb));
132
133 /* copy the TLV block into the sk_buff */
134 copy_from_pam(card, skb_put(skb, mpb.actualBlockTLVSize),
135 (void *)uploadptr + sizeof(pci_mpb),
136 mpb.actualBlockTLVSize);
137
138 /* if existent, copy the data block into the sk_buff */
139 if (mpb.actualDataSize)
140 copy_from_pam(card, skb_put(skb, mpb.actualDataSize),
141 (void *)uploadptr + sizeof(pci_mpb) + 4096,
142 mpb.actualDataSize);
143
144 /* wait for the board to become ready */
145 waiting_too_long = 0;
146 do {
147 hpic = readl(card->bar0 + TPAM_HPIC_REGISTER);
148 if (waiting_too_long++ > 0xfffffff) {
149 kfree_skb(skb);
150 spin_unlock(&card->lock);
151 printk(KERN_ERR "TurboPAM(tpam_irq): "
152 "waiting too long...\n");
153 return;
154 }
155 } while (hpic & 0x00000002);
156
157 /* acknowledge the message */
158 copy_to_pam_dword(card, (void *)TPAM_ACKDOWNLOAD_REGISTER,
159 0xffffffff);
160 readl(card->bar0 + TPAM_DSPINT_REGISTER);
161
162 /* release the board lock */
163 spin_unlock(&card->lock);
164
165 if (mpb.messageID == ID_U3ReadyToReceiveInd) {
166 /* this message needs immediate treatment */
167 tpam_recv_U3ReadyToReceiveInd(card, skb);
168 kfree_skb(skb);
169 }
170 else {
171 /* put the message in the receive queue */
172 skb_queue_tail(&card->recvq, skb);
173 queue_task(&card->recv_tq, &tq_immediate);
174 mark_bh(IMMEDIATE_BH);
175 }
176 return;
177 }
178 else {
179 /* it is a ack from the board */
180
181 dprintk("TurboPAM(tpam_irq): message acknowledged, card=%d\n",
182 card->id);
183
184 /* board is not busy anymore */
185 card->busy = 0;
186
187 /* release the lock */
188 spin_unlock(&card->lock);
189
190 /* schedule the send queue for execution */
191 queue_task(&card->send_tq, &tq_immediate);
192 mark_bh(IMMEDIATE_BH);
193 return;
194 }
195
196 /* not reached */
197 }
198
199 /*
200 * Run the board's receive task queue, dispatching each message on the queue,
201 * to its treatment function.
202 *
203 * card: the board.
204 */
tpam_recv_tq(tpam_card * card)205 void tpam_recv_tq(tpam_card *card) {
206 pci_mpb *p;
207 struct sk_buff *skb;
208
209 /* for each message on the receive queue... */
210 while ((skb = skb_dequeue(&card->recvq))) {
211
212 /* point to the pci_mpb block */
213 p = (pci_mpb *)(skb->data + sizeof(skb_header));
214
215 /* dispatch the message */
216 switch (p->messageID) {
217 case ID_ACreateNCOCnf:
218 tpam_recv_ACreateNCOCnf(card, skb);
219 break;
220 case ID_ADestroyNCOCnf:
221 tpam_recv_ADestroyNCOCnf(card, skb);
222 break;
223 case ID_CConnectCnf:
224 tpam_recv_CConnectCnf(card, skb);
225 break;
226 case ID_CConnectInd:
227 tpam_recv_CConnectInd(card, skb);
228 break;
229 case ID_CDisconnectInd:
230 tpam_recv_CDisconnectInd(card, skb);
231 break;
232 case ID_CDisconnectCnf:
233 tpam_recv_CDisconnectCnf(card, skb);
234 break;
235 case ID_U3DataInd:
236 tpam_recv_U3DataInd(card, skb);
237 break;
238 default:
239 dprintk("TurboPAM(tpam_recv_tq): "
240 "unknown messageID %d, card=%d\n",
241 p->messageID, card->id);
242 break;
243 }
244 /* free the sk_buff */
245 kfree_skb(skb);
246 }
247 }
248
249 /*
250 * Run the board's send task queue. If there is a message in the board's send
251 * queue, it gets sended. If not, it examines each channel (one at the time,
252 * using a round robin algorithm). For each channel, if there is a message
253 * in the channel's send queue, it gets sended. This function sends only one
254 * message, it does not consume all the queue.
255 */
tpam_send_tq(tpam_card * card)256 void tpam_send_tq(tpam_card *card) {
257 int i;
258
259 /* first, try to send a packet from the board's send queue */
260 if (tpam_sendpacket(card, NULL))
261 return;
262
263 /* then, try each channel, in a round-robin manner */
264 for (i=card->roundrobin; i<card->roundrobin+card->channels_used; i++) {
265 if (tpam_sendpacket(card,
266 &card->channels[i % card->channels_used])) {
267 card->roundrobin = (i + 1) % card->channels_used;
268 return;
269 }
270 }
271 }
272
273 /*
274 * Try to send a packet from the board's send queue or from the channel's
275 * send queue.
276 *
277 * card: the board.
278 * channel: the channel (if NULL, the packet will be taken from the
279 * board's send queue. If not, it will be taken from the
280 * channel's send queue.
281 *
282 * Return: 0 if tpam_send_tq must try another card/channel combination
283 * (meaning that no packet has been send), 1 if no more packets
284 * can be send at that time (a packet has been send or the card is
285 * still busy from a previous send).
286 */
tpam_sendpacket(tpam_card * card,tpam_channel * channel)287 static int tpam_sendpacket(tpam_card *card, tpam_channel *channel) {
288 struct sk_buff *skb;
289 u32 hpic;
290 u32 downloadptr;
291 skb_header *skbh;
292 u32 waiting_too_long;
293
294 dprintk("TurboPAM(tpam_sendpacket), card=%d, channel=%d\n",
295 card->id, channel ? channel->num : -1);
296
297 if (channel) {
298 /* dequeue a packet from the channel's send queue */
299 if (!(skb = skb_dequeue(&channel->sendq))) {
300 dprintk("TurboPAM(tpam_sendpacket): "
301 "card=%d, channel=%d, no packet\n",
302 card->id, channel->num);
303 return 0;
304 }
305
306 /* if the channel is not ready to receive, requeue the packet
307 * and return 0 to give a chance to another channel */
308 if (!channel->readytoreceive) {
309 dprintk("TurboPAM(tpam_sendpacket): "
310 "card=%d, channel=%d, channel not ready\n",
311 card->id, channel->num);
312 skb_queue_head(&channel->sendq, skb);
313 return 0;
314 }
315
316 /* grab the board lock */
317 spin_lock_irq(&card->lock);
318
319 /* if the board is busy, requeue the packet and return 1 since
320 * there is no need to try another channel */
321 if (card->busy) {
322 dprintk("TurboPAM(tpam_sendpacket): "
323 "card=%d, channel=%d, card busy\n",
324 card->id, channel->num);
325 skb_queue_head(&channel->sendq, skb);
326 spin_unlock_irq(&card->lock);
327 return 1;
328 }
329 }
330 else {
331 /* dequeue a packet from the board's send queue */
332 if (!(skb = skb_dequeue(&card->sendq))) {
333 dprintk("TurboPAM(tpam_sendpacket): "
334 "card=%d, no packet\n", card->id);
335 return 0;
336 }
337
338 /* grab the board lock */
339 spin_lock_irq(&card->lock);
340
341 /* if the board is busy, requeue the packet and return 1 since
342 * there is no need to try another channel */
343 if (card->busy) {
344 dprintk("TurboPAM(tpam_sendpacket): "
345 "card=%d, card busy\n", card->id);
346 skb_queue_head(&card->sendq, skb);
347 spin_unlock_irq(&card->lock);
348 return 1;
349 }
350 }
351
352 /* wait for the board to become ready */
353 waiting_too_long = 0;
354 do {
355 hpic = readl(card->bar0 + TPAM_HPIC_REGISTER);
356 if (waiting_too_long++ > 0xfffffff) {
357 spin_unlock_irq(&card->lock);
358 printk(KERN_ERR "TurboPAM(tpam_sendpacket): "
359 "waiting too long...\n");
360 return 1;
361 }
362 } while (hpic & 0x00000002);
363
364 skbh = (skb_header *)skb->data;
365 dprintk("TurboPAM(tpam_sendpacket): "
366 "card=%d, card ready, sending %d/%d bytes\n",
367 card->id, skbh->size, skbh->data_size);
368
369 /* get the board's download pointer */
370 downloadptr = copy_from_pam_dword(card,
371 (void *)TPAM_DOWNLOADPTR_REGISTER);
372
373 /* copy the packet to the board at the downloadptr location */
374 copy_to_pam(card, (void *)downloadptr, skb->data + sizeof(skb_header),
375 skbh->size);
376 if (skbh->data_size)
377 /* if there is some data in the packet, copy it too */
378 copy_to_pam(card, (void *)downloadptr + sizeof(pci_mpb) + 4096,
379 skb->data + sizeof(skb_header) + skbh->size,
380 skbh->data_size);
381
382 /* card will become busy right now */
383 card->busy = 1;
384
385 /* interrupt the board */
386 copy_to_pam_dword(card, (void *)TPAM_ACKDOWNLOAD_REGISTER, 0);
387 readl(card->bar0 + TPAM_DSPINT_REGISTER);
388
389 /* release the lock */
390 spin_unlock_irq(&card->lock);
391
392 /* if a data ack was requested by the ISDN link layer, send it now */
393 if (skbh->ack) {
394 isdn_ctrl ctrl;
395 ctrl.driver = card->id;
396 ctrl.command = ISDN_STAT_BSENT;
397 ctrl.arg = channel->num;
398 ctrl.parm.length = skbh->ack_size;
399 (* card->interface.statcallb)(&ctrl);
400 }
401
402 /* free the sk_buff */
403 kfree_skb(skb);
404
405 return 1;
406 }
407
408