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