1/* $Id: tpam_queues.c,v 1.1.1.1 2008/10/15 03:26:34 james26_jang 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 */
23static 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 */
31void 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 */
51void 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 */
79void 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				spin_unlock(&card->lock);
150				printk(KERN_ERR "TurboPAM(tpam_irq): "
151						"waiting too long...\n");
152				return;
153			}
154		} while (hpic & 0x00000002);
155
156		/* acknowledge the message */
157        	copy_to_pam_dword(card, (void *)TPAM_ACKDOWNLOAD_REGISTER,
158				  0xffffffff);
159        	readl(card->bar0 + TPAM_DSPINT_REGISTER);
160
161		/* release the board lock */
162		spin_unlock(&card->lock);
163
164		if (mpb.messageID == ID_U3ReadyToReceiveInd) {
165			/* this message needs immediate treatment */
166			tpam_recv_U3ReadyToReceiveInd(card, skb);
167			kfree_skb(skb);
168		}
169		else {
170			/* put the message in the receive queue */
171			skb_queue_tail(&card->recvq, skb);
172			queue_task(&card->recv_tq, &tq_immediate);
173			mark_bh(IMMEDIATE_BH);
174		}
175		return;
176	}
177	else {
178		/* it is a ack from the board */
179
180		dprintk("TurboPAM(tpam_irq): message acknowledged, card=%d\n",
181			card->id);
182
183		/* board is not busy anymore */
184		card->busy = 0;
185
186		/* release the lock */
187		spin_unlock(&card->lock);
188
189		/* schedule the send queue for execution */
190		queue_task(&card->send_tq, &tq_immediate);
191		mark_bh(IMMEDIATE_BH);
192		return;
193	}
194
195	/* not reached */
196}
197
198/*
199 * Run the board's receive task queue, dispatching each message on the queue,
200 * to its treatment function.
201 *
202 * 	card: the board.
203 */
204void tpam_recv_tq(tpam_card *card) {
205	pci_mpb *p;
206	struct sk_buff *skb;
207
208	/* for each message on the receive queue... */
209        while ((skb = skb_dequeue(&card->recvq))) {
210
211		/* point to the pci_mpb block */
212		p = (pci_mpb *)(skb->data + sizeof(skb_header));
213
214		/* dispatch the message */
215		switch (p->messageID) {
216			case ID_ACreateNCOCnf:
217				tpam_recv_ACreateNCOCnf(card, skb);
218				break;
219			case ID_ADestroyNCOCnf:
220				tpam_recv_ADestroyNCOCnf(card, skb);
221				break;
222			case ID_CConnectCnf:
223				tpam_recv_CConnectCnf(card, skb);
224				break;
225			case ID_CConnectInd:
226				tpam_recv_CConnectInd(card, skb);
227				break;
228			case ID_CDisconnectInd:
229				tpam_recv_CDisconnectInd(card, skb);
230				break;
231			case ID_CDisconnectCnf:
232				tpam_recv_CDisconnectCnf(card, skb);
233				break;
234			case ID_U3DataInd:
235				tpam_recv_U3DataInd(card, skb);
236				break;
237			default:
238				dprintk("TurboPAM(tpam_recv_tq): "
239					"unknown messageID %d, card=%d\n",
240					p->messageID, card->id);
241				break;
242		}
243		/* free the sk_buff */
244		kfree_skb(skb);
245	}
246}
247
248/*
249 * Run the board's send task queue. If there is a message in the board's send
250 * queue, it gets sended. If not, it examines each channel (one at the time,
251 * using a round robin algorithm). For each channel, if there is a message
252 * in the channel's send queue, it gets sended. This function sends only one
253 * message, it does not consume all the queue.
254 */
255void tpam_send_tq(tpam_card *card) {
256	int i;
257
258	/* first, try to send a packet from the board's send queue */
259	if (tpam_sendpacket(card, NULL))
260		return;
261
262	/* then, try each channel, in a round-robin manner */
263	for (i=card->roundrobin; i<card->roundrobin+card->channels_used; i++) {
264		if (tpam_sendpacket(card,
265				    &card->channels[i % card->channels_used])) {
266			card->roundrobin = (i + 1) % card->channels_used;
267			return;
268		}
269	}
270}
271
272/*
273 * Try to send a packet from the board's send queue or from the channel's
274 * send queue.
275 *
276 * 	card: the board.
277 * 	channel: the channel (if NULL, the packet will be taken from the
278 * 		board's send queue. If not, it will be taken from the
279 * 		channel's send queue.
280 *
281 * Return: 0 if tpam_send_tq must try another card/channel combination
282 * 	(meaning that no packet has been send), 1 if no more packets
283 * 	can be send at that time (a packet has been send or the card is
284 * 	still busy from a previous send).
285 */
286static int tpam_sendpacket(tpam_card *card, tpam_channel *channel) {
287        struct sk_buff *skb;
288	u32 hpic;
289        u32 downloadptr;
290	skb_header *skbh;
291	u32 waiting_too_long;
292
293	dprintk("TurboPAM(tpam_sendpacket), card=%d, channel=%d\n",
294		card->id, channel ? channel->num : -1);
295
296	if (channel) {
297		/* dequeue a packet from the channel's send queue */
298		if (!(skb = skb_dequeue(&channel->sendq))) {
299			dprintk("TurboPAM(tpam_sendpacket): "
300				"card=%d, channel=%d, no packet\n",
301				card->id, channel->num);
302			return 0;
303		}
304
305		/* if the channel is not ready to receive, requeue the packet
306		 * and return 0 to give a chance to another channel */
307		if (!channel->readytoreceive) {
308			dprintk("TurboPAM(tpam_sendpacket): "
309				"card=%d, channel=%d, channel not ready\n",
310				card->id, channel->num);
311			skb_queue_head(&channel->sendq, skb);
312			return 0;
313		}
314
315		/* grab the board lock */
316		spin_lock_irq(&card->lock);
317
318		/* if the board is busy, requeue the packet and return 1 since
319		 * there is no need to try another channel */
320		if (card->busy) {
321			dprintk("TurboPAM(tpam_sendpacket): "
322				"card=%d, channel=%d, card busy\n",
323				card->id, channel->num);
324			skb_queue_head(&channel->sendq, skb);
325			spin_unlock_irq(&card->lock);
326			return 1;
327		}
328	}
329	else {
330		/* dequeue a packet from the board's send queue */
331		if (!(skb = skb_dequeue(&card->sendq))) {
332			dprintk("TurboPAM(tpam_sendpacket): "
333				"card=%d, no packet\n", card->id);
334			return 0;
335		}
336
337		/* grab the board lock */
338		spin_lock_irq(&card->lock);
339
340		/* if the board is busy, requeue the packet and return 1 since
341		 * there is no need to try another channel */
342		if (card->busy) {
343			dprintk("TurboPAM(tpam_sendpacket): "
344				"card=%d, card busy\n", card->id);
345			skb_queue_head(&card->sendq, skb);
346			spin_unlock_irq(&card->lock);
347			return 1;
348		}
349	}
350
351	/* wait for the board to become ready */
352	waiting_too_long = 0;
353	do {
354		hpic = readl(card->bar0 + TPAM_HPIC_REGISTER);
355		if (waiting_too_long++ > 0xfffffff) {
356			spin_unlock_irq(&card->lock);
357			printk(KERN_ERR "TurboPAM(tpam_sendpacket): "
358					"waiting too long...\n");
359			return 1;
360		}
361	} while (hpic & 0x00000002);
362
363	skbh = (skb_header *)skb->data;
364	dprintk("TurboPAM(tpam_sendpacket): "
365		"card=%d, card ready, sending %d/%d bytes\n",
366		card->id, skbh->size, skbh->data_size);
367
368	/* get the board's download pointer */
369       	downloadptr = copy_from_pam_dword(card,
370					  (void *)TPAM_DOWNLOADPTR_REGISTER);
371
372	/* copy the packet to the board at the downloadptr location */
373       	copy_to_pam(card, (void *)downloadptr, skb->data + sizeof(skb_header),
374		    skbh->size);
375	if (skbh->data_size)
376		/* if there is some data in the packet, copy it too */
377		copy_to_pam(card, (void *)downloadptr + sizeof(pci_mpb) + 4096,
378			    skb->data + sizeof(skb_header) + skbh->size,
379			    skbh->data_size);
380
381	/* card will become busy right now */
382	card->busy = 1;
383
384	/* interrupt the board */
385	copy_to_pam_dword(card, (void *)TPAM_ACKDOWNLOAD_REGISTER, 0);
386	readl(card->bar0 + TPAM_DSPINT_REGISTER);
387
388	/* release the lock */
389	spin_unlock_irq(&card->lock);
390
391	/* if a data ack was requested by the ISDN link layer, send it now */
392	if (skbh->ack) {
393		isdn_ctrl ctrl;
394		ctrl.driver = card->id;
395		ctrl.command = ISDN_STAT_BSENT;
396		ctrl.arg = channel->num;
397		ctrl.parm.length = skbh->ack_size;
398		(* card->interface.statcallb)(&ctrl);
399	}
400
401	/* free the sk_buff */
402	kfree_skb(skb);
403
404	return 1;
405}
406
407