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