1 /* $Id: tpam_queues.c,v 1.1.2.2 2001/09/23 22:25:03 kai Exp $
3 * Turbo PAM ISDN driver for Linux. (Kernel Driver)
5 * Copyright 2001 Stelian Pop <stelian.pop@fr.alcove.com>, AlcĂ´ve
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 all support questions please contact: <support@auvertech.fr>
14 #include <linux/pci.h>
15 #include <linux/sched.h>
16 #include <linux/workqueue.h>
17 #include <linux/interrupt.h>
22 /* Local function prototype */
23 static int tpam_sendpacket(tpam_card *card, tpam_channel *channel);
26 * Queue a message to be send to the card when possible.
29 * skb: the sk_buff containing the message.
31 void tpam_enqueue(tpam_card *card, struct sk_buff *skb) {
33 dprintk("TurboPAM(tpam_enqueue): card=%d\n", card->id);
35 /* queue the sk_buff on the board's send queue */
36 skb_queue_tail(&card->sendq, skb);
38 /* queue the board's send task struct for immediate treatment */
39 schedule_work(&card->send_tq);
43 * Queue a data message to be send to the card when possible.
46 * skb: the sk_buff containing the message and the data. This parameter
47 * can be NULL if we want just to trigger the send of queued
50 void tpam_enqueue_data(tpam_channel *channel, struct sk_buff *skb) {
52 dprintk("TurboPAM(tpam_enqueue_data): card=%d, channel=%d\n",
53 channel->card->id, channel->num);
55 /* if existant, queue the sk_buff on the channel's send queue */
57 skb_queue_tail(&channel->sendq, skb);
59 /* queue the channel's send task struct for immediate treatment */
60 schedule_work(&channel->card->send_tq);
66 * If a message comes from the board we read it, construct a sk_buff containing
67 * the message and we queue the sk_buff on the board's receive queue, and we
68 * trigger the execution of the board's receive task queue.
70 * If a message ack comes from the board we can go on and send a new message,
71 * so we trigger the execution of the board's send task queue.
74 * dev_id: the registered board to the irq
77 irqreturn_t tpam_irq(int irq, void *dev_id, struct pt_regs *regs)
79 tpam_card *card = (tpam_card *)dev_id;
80 u32 ackupload, uploadptr;
87 dprintk("TurboPAM(tpam_irq): IRQ received, card=%d\n", card->id);
89 /* grab the board lock */
90 spin_lock(&card->lock);
92 /* get the message type */
93 ackupload = copy_from_pam_dword(card, (void *)TPAM_ACKUPLOAD_REGISTER);
95 /* acknowledge the interrupt */
96 copy_to_pam_dword(card, (void *)TPAM_INTERRUPTACK_REGISTER, 0);
97 readl(card->bar0 + TPAM_HINTACK_REGISTER);
100 /* it is a new message from the board */
102 dprintk("TurboPAM(tpam_irq): message received, card=%d\n",
105 /* get the upload pointer */
106 uploadptr = copy_from_pam_dword(card,
107 (void *)TPAM_UPLOADPTR_REGISTER);
109 /* get the beginning of the message (pci_mpb part) */
110 copy_from_pam(card, &mpb, (void *)uploadptr, sizeof(pci_mpb));
112 /* allocate the sk_buff */
113 if (!(skb = alloc_skb(sizeof(skb_header) + sizeof(pci_mpb) +
114 mpb.actualBlockTLVSize +
115 mpb.actualDataSize, GFP_ATOMIC))) {
116 printk(KERN_ERR "TurboPAM(tpam_irq): "
117 "alloc_skb failed\n");
118 spin_unlock(&card->lock);
122 /* build the skb_header */
123 skbh = (skb_header *)skb_put(skb, sizeof(skb_header));
124 skbh->size = sizeof(pci_mpb) + mpb.actualBlockTLVSize;
125 skbh->data_size = mpb.actualDataSize;
129 /* copy the pci_mpb into the sk_buff */
130 memcpy(skb_put(skb, sizeof(pci_mpb)), &mpb, sizeof(pci_mpb));
132 /* copy the TLV block into the sk_buff */
133 copy_from_pam(card, skb_put(skb, mpb.actualBlockTLVSize),
134 (void *)uploadptr + sizeof(pci_mpb),
135 mpb.actualBlockTLVSize);
137 /* if existent, copy the data block into the sk_buff */
138 if (mpb.actualDataSize)
139 copy_from_pam(card, skb_put(skb, mpb.actualDataSize),
140 (void *)uploadptr + sizeof(pci_mpb) + 4096,
143 /* wait for the board to become ready */
144 waiting_too_long = 0;
146 hpic = readl(card->bar0 + TPAM_HPIC_REGISTER);
147 if (waiting_too_long++ > 0xfffffff) {
149 spin_unlock(&card->lock);
150 printk(KERN_ERR "TurboPAM(tpam_irq): "
151 "waiting too long...\n");
154 } while (hpic & 0x00000002);
156 /* acknowledge the message */
157 copy_to_pam_dword(card, (void *)TPAM_ACKDOWNLOAD_REGISTER,
159 readl(card->bar0 + TPAM_DSPINT_REGISTER);
161 /* release the board lock */
162 spin_unlock(&card->lock);
164 if (mpb.messageID == ID_U3ReadyToReceiveInd) {
165 /* this message needs immediate treatment */
166 tpam_recv_U3ReadyToReceiveInd(card, skb);
170 /* put the message in the receive queue */
171 skb_queue_tail(&card->recvq, skb);
172 schedule_work(&card->recv_tq);
177 /* it is a ack from the board */
179 dprintk("TurboPAM(tpam_irq): message acknowledged, card=%d\n",
182 /* board is not busy anymore */
185 /* release the lock */
186 spin_unlock(&card->lock);
188 /* schedule the send queue for execution */
189 schedule_work(&card->send_tq);
195 * Run the board's receive task queue, dispatching each message on the queue,
196 * to its treatment function.
200 void tpam_recv_tq(tpam_card *card) {
204 /* for each message on the receive queue... */
205 while ((skb = skb_dequeue(&card->recvq))) {
207 /* point to the pci_mpb block */
208 p = (pci_mpb *)(skb->data + sizeof(skb_header));
210 /* dispatch the message */
211 switch (p->messageID) {
212 case ID_ACreateNCOCnf:
213 tpam_recv_ACreateNCOCnf(card, skb);
215 case ID_ADestroyNCOCnf:
216 tpam_recv_ADestroyNCOCnf(card, skb);
219 tpam_recv_CConnectCnf(card, skb);
222 tpam_recv_CConnectInd(card, skb);
224 case ID_CDisconnectInd:
225 tpam_recv_CDisconnectInd(card, skb);
227 case ID_CDisconnectCnf:
228 tpam_recv_CDisconnectCnf(card, skb);
231 tpam_recv_U3DataInd(card, skb);
234 dprintk("TurboPAM(tpam_recv_tq): "
235 "unknown messageID %d, card=%d\n",
236 p->messageID, card->id);
239 /* free the sk_buff */
245 * Run the board's send task queue. If there is a message in the board's send
246 * queue, it gets sended. If not, it examines each channel (one at the time,
247 * using a round robin algorithm). For each channel, if there is a message
248 * in the channel's send queue, it gets sended. This function sends only one
249 * message, it does not consume all the queue.
251 void tpam_send_tq(tpam_card *card) {
254 /* first, try to send a packet from the board's send queue */
255 if (tpam_sendpacket(card, NULL))
258 /* then, try each channel, in a round-robin manner */
259 for (i=card->roundrobin; i<card->roundrobin+card->channels_used; i++) {
260 if (tpam_sendpacket(card,
261 &card->channels[i % card->channels_used])) {
262 card->roundrobin = (i + 1) % card->channels_used;
269 * Try to send a packet from the board's send queue or from the channel's
273 * channel: the channel (if NULL, the packet will be taken from the
274 * board's send queue. If not, it will be taken from the
275 * channel's send queue.
277 * Return: 0 if tpam_send_tq must try another card/channel combination
278 * (meaning that no packet has been send), 1 if no more packets
279 * can be send at that time (a packet has been send or the card is
280 * still busy from a previous send).
282 static int tpam_sendpacket(tpam_card *card, tpam_channel *channel) {
287 u32 waiting_too_long;
289 dprintk("TurboPAM(tpam_sendpacket), card=%d, channel=%d\n",
290 card->id, channel ? channel->num : -1);
293 /* dequeue a packet from the channel's send queue */
294 if (!(skb = skb_dequeue(&channel->sendq))) {
295 dprintk("TurboPAM(tpam_sendpacket): "
296 "card=%d, channel=%d, no packet\n",
297 card->id, channel->num);
301 /* if the channel is not ready to receive, requeue the packet
302 * and return 0 to give a chance to another channel */
303 if (!channel->readytoreceive) {
304 dprintk("TurboPAM(tpam_sendpacket): "
305 "card=%d, channel=%d, channel not ready\n",
306 card->id, channel->num);
307 skb_queue_head(&channel->sendq, skb);
311 /* grab the board lock */
312 spin_lock_irq(&card->lock);
314 /* if the board is busy, requeue the packet and return 1 since
315 * there is no need to try another channel */
317 dprintk("TurboPAM(tpam_sendpacket): "
318 "card=%d, channel=%d, card busy\n",
319 card->id, channel->num);
320 skb_queue_head(&channel->sendq, skb);
321 spin_unlock_irq(&card->lock);
326 /* dequeue a packet from the board's send queue */
327 if (!(skb = skb_dequeue(&card->sendq))) {
328 dprintk("TurboPAM(tpam_sendpacket): "
329 "card=%d, no packet\n", card->id);
333 /* grab the board lock */
334 spin_lock_irq(&card->lock);
336 /* if the board is busy, requeue the packet and return 1 since
337 * there is no need to try another channel */
339 dprintk("TurboPAM(tpam_sendpacket): "
340 "card=%d, card busy\n", card->id);
341 skb_queue_head(&card->sendq, skb);
342 spin_unlock_irq(&card->lock);
347 /* wait for the board to become ready */
348 waiting_too_long = 0;
350 hpic = readl(card->bar0 + TPAM_HPIC_REGISTER);
351 if (waiting_too_long++ > 0xfffffff) {
352 spin_unlock_irq(&card->lock);
353 printk(KERN_ERR "TurboPAM(tpam_sendpacket): "
354 "waiting too long...\n");
357 } while (hpic & 0x00000002);
359 skbh = (skb_header *)skb->data;
360 dprintk("TurboPAM(tpam_sendpacket): "
361 "card=%d, card ready, sending %d/%d bytes\n",
362 card->id, skbh->size, skbh->data_size);
364 /* get the board's download pointer */
365 downloadptr = copy_from_pam_dword(card,
366 (void *)TPAM_DOWNLOADPTR_REGISTER);
368 /* copy the packet to the board at the downloadptr location */
369 copy_to_pam(card, (void *)downloadptr, skb->data + sizeof(skb_header),
372 /* if there is some data in the packet, copy it too */
373 copy_to_pam(card, (void *)downloadptr + sizeof(pci_mpb) + 4096,
374 skb->data + sizeof(skb_header) + skbh->size,
377 /* card will become busy right now */
380 /* interrupt the board */
381 copy_to_pam_dword(card, (void *)TPAM_ACKDOWNLOAD_REGISTER, 0);
382 readl(card->bar0 + TPAM_DSPINT_REGISTER);
384 /* release the lock */
385 spin_unlock_irq(&card->lock);
387 /* if a data ack was requested by the ISDN link layer, send it now */
390 ctrl.driver = card->id;
391 ctrl.command = ISDN_STAT_BSENT;
392 ctrl.arg = channel->num;
393 ctrl.parm.length = skbh->ack_size;
394 (* card->interface.statcallb)(&ctrl);
397 /* free the sk_buff */