📄 c4.c
字号:
if (CAPICMD(cmd, subcmd) == CAPI_DATA_B3_REQ) { u16 dlen = CAPIMSG_DATALEN(skb->data); _put_byte(&p, SEND_DATA_B3_REQ); _put_slice(&p, skb->data, len); _put_slice(&p, skb->data + len, dlen); } else { _put_byte(&p, SEND_MESSAGE); _put_slice(&p, skb->data, len); } txlen = (u8 *)p - (u8 *)dma->sendbuf.dmabuf;#ifdef CONFIG_C4_DEBUG printk(KERN_DEBUG "%s: tx put msg len=%d\n", card->name, txlen);#endif } else { txlen = skb->len-2;#ifdef CONFIG_C4_POLLDEBUG if (skb->data[2] == SEND_POLLACK) printk(KERN_INFO "%s: ack to c4\n", card->name);#endif#ifdef CONFIG_C4_DEBUG printk(KERN_DEBUG "%s: tx put 0x%x len=%d\n", card->name, skb->data[2], txlen);#endif memcpy(dma->sendbuf.dmabuf, skb->data+2, skb->len-2); } txlen = (txlen + 3) & ~3; c4outmeml(card->mbase+MBOX_DOWN_ADDR, dma->sendbuf.dmaaddr); c4outmeml(card->mbase+MBOX_DOWN_LEN, txlen); card->csr |= DBELL_DOWN_ARM; c4outmeml(card->mbase+DOORBELL, DBELL_DOWN_ARM); dev_kfree_skb_any(skb);}/* ------------------------------------------------------------- */static void queue_pollack(avmcard *card){ struct sk_buff *skb; void *p; skb = alloc_skb(3, GFP_ATOMIC); if (!skb) { printk(KERN_CRIT "%s: no memory, lost poll ack\n", card->name); return; } p = skb->data; _put_byte(&p, 0); _put_byte(&p, 0); _put_byte(&p, SEND_POLLACK); skb_put(skb, (u8 *)p - (u8 *)skb->data); skb_queue_tail(&card->dma->send_queue, skb); c4_dispatch_tx(card);}/* ------------------------------------------------------------- */static void c4_handle_rx(avmcard *card){ avmcard_dmainfo *dma = card->dma; struct capi_ctr *ctrl; avmctrl_info *cinfo; struct sk_buff *skb; void *p = dma->recvbuf.dmabuf; u32 ApplId, MsgLen, DataB3Len, NCCI, WindowSize; u8 b1cmd = _get_byte(&p); u32 cidx;#ifdef CONFIG_C4_DEBUG printk(KERN_DEBUG "%s: rx 0x%x len=%lu\n", card->name, b1cmd, (unsigned long)dma->recvlen);#endif switch (b1cmd) { case RECEIVE_DATA_B3_IND: ApplId = (unsigned) _get_word(&p); MsgLen = _get_slice(&p, card->msgbuf); DataB3Len = _get_slice(&p, card->databuf); cidx = CAPIMSG_CONTROLLER(card->msgbuf)-card->cardnr; if (cidx >= card->nlogcontr) cidx = 0; ctrl = &card->ctrlinfo[cidx].capi_ctrl; if (MsgLen < 30) { /* not CAPI 64Bit */ memset(card->msgbuf+MsgLen, 0, 30-MsgLen); MsgLen = 30; CAPIMSG_SETLEN(card->msgbuf, 30); } if (!(skb = alloc_skb(DataB3Len+MsgLen, GFP_ATOMIC))) { printk(KERN_ERR "%s: incoming packet dropped\n", card->name); } else { memcpy(skb_put(skb, MsgLen), card->msgbuf, MsgLen); memcpy(skb_put(skb, DataB3Len), card->databuf, DataB3Len); capi_ctr_handle_message(ctrl, ApplId, skb); } break; case RECEIVE_MESSAGE: ApplId = (unsigned) _get_word(&p); MsgLen = _get_slice(&p, card->msgbuf); cidx = CAPIMSG_CONTROLLER(card->msgbuf)-card->cardnr; if (cidx >= card->nlogcontr) cidx = 0; cinfo = &card->ctrlinfo[cidx]; ctrl = &card->ctrlinfo[cidx].capi_ctrl; if (!(skb = alloc_skb(MsgLen, GFP_ATOMIC))) { printk(KERN_ERR "%s: incoming packet dropped\n", card->name); } else { memcpy(skb_put(skb, MsgLen), card->msgbuf, MsgLen); if (CAPIMSG_CMD(skb->data) == CAPI_DATA_B3_CONF) capilib_data_b3_conf(&cinfo->ncci_head, ApplId, CAPIMSG_NCCI(skb->data), CAPIMSG_MSGID(skb->data)); capi_ctr_handle_message(ctrl, ApplId, skb); } break; case RECEIVE_NEW_NCCI: ApplId = _get_word(&p); NCCI = _get_word(&p); WindowSize = _get_word(&p); cidx = (NCCI&0x7f) - card->cardnr; if (cidx >= card->nlogcontr) cidx = 0; capilib_new_ncci(&card->ctrlinfo[cidx].ncci_head, ApplId, NCCI, WindowSize); break; case RECEIVE_FREE_NCCI: ApplId = _get_word(&p); NCCI = _get_word(&p); if (NCCI != 0xffffffff) { cidx = (NCCI&0x7f) - card->cardnr; if (cidx >= card->nlogcontr) cidx = 0; capilib_free_ncci(&card->ctrlinfo[cidx].ncci_head, ApplId, NCCI); } break; case RECEIVE_START:#ifdef CONFIG_C4_POLLDEBUG printk(KERN_INFO "%s: poll from c4\n", card->name);#endif if (!suppress_pollack) queue_pollack(card); for (cidx=0; cidx < card->nr_controllers; cidx++) { ctrl = &card->ctrlinfo[cidx].capi_ctrl; capi_ctr_resume_output(ctrl); } break; case RECEIVE_STOP: for (cidx=0; cidx < card->nr_controllers; cidx++) { ctrl = &card->ctrlinfo[cidx].capi_ctrl; capi_ctr_suspend_output(ctrl); } break; case RECEIVE_INIT: cidx = card->nlogcontr; if (cidx >= card->nr_controllers) { printk(KERN_ERR "%s: card with %d controllers ??\n", card->name, cidx+1); break; } card->nlogcontr++; cinfo = &card->ctrlinfo[cidx]; ctrl = &cinfo->capi_ctrl; cinfo->versionlen = _get_slice(&p, cinfo->versionbuf); b1_parse_version(cinfo); printk(KERN_INFO "%s: %s-card (%s) now active\n", card->name, cinfo->version[VER_CARDTYPE], cinfo->version[VER_DRIVER]); capi_ctr_ready(&cinfo->capi_ctrl); break; case RECEIVE_TASK_READY: ApplId = (unsigned) _get_word(&p); MsgLen = _get_slice(&p, card->msgbuf); card->msgbuf[MsgLen] = 0; while ( MsgLen > 0 && ( card->msgbuf[MsgLen-1] == '\n' || card->msgbuf[MsgLen-1] == '\r')) { card->msgbuf[MsgLen-1] = 0; MsgLen--; } printk(KERN_INFO "%s: task %d \"%s\" ready.\n", card->name, ApplId, card->msgbuf); break; case RECEIVE_DEBUGMSG: MsgLen = _get_slice(&p, card->msgbuf); card->msgbuf[MsgLen] = 0; while ( MsgLen > 0 && ( card->msgbuf[MsgLen-1] == '\n' || card->msgbuf[MsgLen-1] == '\r')) { card->msgbuf[MsgLen-1] = 0; MsgLen--; } printk(KERN_INFO "%s: DEBUG: %s\n", card->name, card->msgbuf); break; default: printk(KERN_ERR "%s: c4_interrupt: 0x%x ???\n", card->name, b1cmd); return; }}/* ------------------------------------------------------------- */static irqreturn_t c4_handle_interrupt(avmcard *card){ unsigned long flags; u32 status; spin_lock_irqsave(&card->lock, flags); status = c4inmeml(card->mbase+DOORBELL); if (status & DBELL_RESET_HOST) { u_int i; c4outmeml(card->mbase+PCI_OUT_INT_MASK, 0x0c); spin_unlock_irqrestore(&card->lock, flags); if (card->nlogcontr == 0) return IRQ_HANDLED; printk(KERN_ERR "%s: unexpected reset\n", card->name); for (i=0; i < card->nr_controllers; i++) { avmctrl_info *cinfo = &card->ctrlinfo[i]; memset(cinfo->version, 0, sizeof(cinfo->version)); capilib_release(&cinfo->ncci_head); capi_ctr_reseted(&cinfo->capi_ctrl); } card->nlogcontr = 0; return IRQ_HANDLED; } status &= (DBELL_UP_HOST | DBELL_DOWN_HOST); if (!status) { spin_unlock_irqrestore(&card->lock, flags); return IRQ_HANDLED; } c4outmeml(card->mbase+DOORBELL, status); if ((status & DBELL_UP_HOST) != 0) { card->dma->recvlen = c4inmeml(card->mbase+MBOX_UP_LEN); c4outmeml(card->mbase+MBOX_UP_LEN, 0); c4_handle_rx(card); card->dma->recvlen = 0; c4outmeml(card->mbase+MBOX_UP_LEN, card->dma->recvbuf.size); c4outmeml(card->mbase+DOORBELL, DBELL_UP_ARM); } if ((status & DBELL_DOWN_HOST) != 0) { card->csr &= ~DBELL_DOWN_ARM; c4_dispatch_tx(card); } else if (card->csr & DBELL_DOWN_HOST) { if (c4inmeml(card->mbase+MBOX_DOWN_LEN) == 0) { card->csr &= ~DBELL_DOWN_ARM; c4_dispatch_tx(card); } } spin_unlock_irqrestore(&card->lock, flags); return IRQ_HANDLED;}static irqreturn_t c4_interrupt(int interrupt, void *devptr, struct pt_regs *regs){ avmcard *card = devptr; return c4_handle_interrupt(card);}/* ------------------------------------------------------------- */static void c4_send_init(avmcard *card){ struct sk_buff *skb; void *p; skb = alloc_skb(15, GFP_ATOMIC); if (!skb) { printk(KERN_CRIT "%s: no memory, lost register appl.\n", card->name); return; } p = skb->data; _put_byte(&p, 0); _put_byte(&p, 0); _put_byte(&p, SEND_INIT); _put_word(&p, CAPI_MAXAPPL); _put_word(&p, AVM_NCCI_PER_CHANNEL*30); _put_word(&p, card->cardnr - 1); skb_put(skb, (u8 *)p - (u8 *)skb->data); skb_queue_tail(&card->dma->send_queue, skb); c4_dispatch_tx(card);}static int queue_sendconfigword(avmcard *card, u32 val){ struct sk_buff *skb; void *p; skb = alloc_skb(3+4, GFP_ATOMIC); if (!skb) { printk(KERN_CRIT "%s: no memory, send config\n", card->name); return -ENOMEM; } p = skb->data; _put_byte(&p, 0); _put_byte(&p, 0); _put_byte(&p, SEND_CONFIG); _put_word(&p, val); skb_put(skb, (u8 *)p - (u8 *)skb->data); skb_queue_tail(&card->dma->send_queue, skb); c4_dispatch_tx(card); return 0;}static int queue_sendconfig(avmcard *card, char cval[4]){ struct sk_buff *skb; unsigned long flags; void *p; skb = alloc_skb(3+4, GFP_ATOMIC); if (!skb) { printk(KERN_CRIT "%s: no memory, send config\n", card->name); return -ENOMEM; } p = skb->data; _put_byte(&p, 0); _put_byte(&p, 0); _put_byte(&p, SEND_CONFIG); _put_byte(&p, cval[0]); _put_byte(&p, cval[1]); _put_byte(&p, cval[2]); _put_byte(&p, cval[3]); skb_put(skb, (u8 *)p - (u8 *)skb->data); skb_queue_tail(&card->dma->send_queue, skb); spin_lock_irqsave(&card->lock, flags); c4_dispatch_tx(card); spin_unlock_irqrestore(&card->lock, flags); return 0;}static int c4_send_config(avmcard *card, capiloaddatapart * config){ u8 val[4]; unsigned char *dp; u_int left; int retval; if ((retval = queue_sendconfigword(card, 1)) != 0) return retval; if ((retval = queue_sendconfigword(card, config->len)) != 0) return retval; dp = config->data; left = config->len; while (left >= sizeof(u32)) { if (config->user) { if (copy_from_user(val, dp, sizeof(val))) return -EFAULT; } else { memcpy(val, dp, sizeof(val)); } if ((retval = queue_sendconfig(card, val)) != 0) return retval; left -= sizeof(val); dp += sizeof(val); } if (left) { memset(val, 0, sizeof(val)); if (config->user) { if (copy_from_user(&val, dp, left)) return -EFAULT; } else { memcpy(&val, dp, left); } if ((retval = queue_sendconfig(card, val)) != 0) return retval; } return 0;}static int c4_load_firmware(struct capi_ctr *ctrl, capiloaddata *data){ avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); avmcard *card = cinfo->card; int retval; if ((retval = c4_load_t4file(card, &data->firmware))) { printk(KERN_ERR "%s: failed to load t4file!!\n", card->name); c4_reset(card); return retval; } card->csr = 0; c4outmeml(card->mbase+MBOX_UP_LEN, 0); c4outmeml(card->mbase+MBOX_DOWN_LEN, 0); c4outmeml(card->mbase+DOORBELL, DBELL_INIT); mdelay(1); c4outmeml(card->mbase+DOORBELL, DBELL_UP_HOST | DBELL_DOWN_HOST | DBELL_RESET_HOST); c4outmeml(card->mbase+PCI_OUT_INT_MASK, 0x08); card->dma->recvlen = 0; c4outmeml(card->mbase+MBOX_UP_ADDR, card->dma->recvbuf.dmaaddr); c4outmeml(card->mbase+MBOX_UP_LEN, card->dma->recvbuf.size); c4outmeml(card->mbase+DOORBELL, DBELL_UP_ARM); if (data->configuration.len > 0 && data->configuration.data) { retval = c4_send_config(card, &data->configuration); if (retval) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -