?? pc300_drv.c
字號:
(uclong) cpc_readl(scabase + DTX_REG(CDAL, ch)), (uclong) cpc_readl(scabase + DTX_REG(EDAL, ch))); for (i = 0; i < N_DMA_TX_BUF; i++) { ptdescr = (pcsca_bd_t *) (card->hw.rambase + TX_BD_ADDR(ch, i)); printk("\n CH%d TX%d: next=0x%lx, ptbuf=0x%lx, ST=0x%x, len=%d", ch, i, (uclong) cpc_readl(&ptdescr->next), (uclong) cpc_readl(&ptdescr->ptbuf), cpc_readb(&ptdescr->status), cpc_readw(&ptdescr->len)); } printk("\n");}#endif static void rx_dma_buf_check(pc300_t * card, int ch){ volatile pcsca_bd_t *ptdescr; int i; ucshort first_bd = card->chan[ch].rx_first_bd; ucshort last_bd = card->chan[ch].rx_last_bd; int ch_factor; ch_factor = ch * N_DMA_RX_BUF; printk("#CH%d: f_bd = %d, l_bd = %d\n", ch, first_bd, last_bd); for (i = 0, ptdescr = (pcsca_bd_t *) (card->hw.rambase + DMA_RX_BD_BASE + ch_factor * sizeof(pcsca_bd_t)); i < N_DMA_RX_BUF; i++, ptdescr++) { if (cpc_readb(&ptdescr->status) & DST_OSB) printk ("\n CH%d RX%d: next=0x%lx, ptbuf=0x%lx, ST=0x%x, len=%d", ch, i, (uclong) cpc_readl(&ptdescr->next), (uclong) cpc_readl(&ptdescr->ptbuf), cpc_readb(&ptdescr->status), cpc_readw(&ptdescr->len)); } printk("\n");}int dma_get_rx_frame_size(pc300_t * card, int ch){ volatile pcsca_bd_t *ptdescr; ucshort first_bd = card->chan[ch].rx_first_bd; int rcvd = 0; volatile ucchar status; ptdescr = (pcsca_bd_t *)(card->hw.rambase + RX_BD_ADDR(ch, first_bd)); while ((status = cpc_readb(&ptdescr->status)) & DST_OSB) { rcvd += cpc_readw(&ptdescr->len); first_bd = (first_bd + 1) & (N_DMA_RX_BUF - 1); if ((status & DST_EOM) || (first_bd == card->chan[ch].rx_last_bd)) { /* Return the size of a good frame or incomplete bad frame * (dma_buf_read will clean the buffer descriptors in this case). */ return (rcvd); } ptdescr = (pcsca_bd_t *)(card->hw.rambase + cpc_readl(&ptdescr->next)); } return (-1);}/* * dma_buf_write: writes a frame to the Tx DMA buffers * NOTE: this function writes one frame at a time. */int dma_buf_write(pc300_t * card, int ch, ucchar * ptdata, int len){ int i, nchar; volatile pcsca_bd_t *ptdescr; int tosend = len; ucchar nbuf = ((len - 1) / BD_DEF_LEN) + 1; if (nbuf >= card->chan[ch].nfree_tx_bd) { return -ENOMEM; } for (i = 0; i < nbuf; i++) { ptdescr = (pcsca_bd_t *) (card->hw.rambase + TX_BD_ADDR(ch, card->chan[ch].tx_next_bd)); nchar = cpc_min(BD_DEF_LEN, tosend); if (cpc_readb(&ptdescr->status) & DST_OSB) { memcpy_toio((void *)(card->hw.rambase + cpc_readl(&ptdescr->ptbuf)), &ptdata[len - tosend], nchar); cpc_writew(&ptdescr->len, nchar); card->chan[ch].nfree_tx_bd--; if ((i + 1) == nbuf) { /* This must be the last BD to be used */ cpc_writeb(&ptdescr->status, DST_EOM); } else { cpc_writeb(&ptdescr->status, 0); } } else { return -ENOMEM; } tosend -= nchar; card->chan[ch].tx_next_bd = (card->chan[ch].tx_next_bd + 1) & (N_DMA_TX_BUF - 1); } /* If it gets to here, it means we have sent the whole frame */ return 0;}/* * dma_buf_read: reads a frame from the Rx DMA buffers * NOTE: this function reads one frame at a time. */int dma_buf_read(pc300_t * card, int ch, struct sk_buff *skb){ int nchar; pc300ch_t *chan = (pc300ch_t *) & card->chan[ch]; volatile pcsca_bd_t *ptdescr; int rcvd = 0; volatile ucchar status; ptdescr = (pcsca_bd_t *) (card->hw.rambase + RX_BD_ADDR(ch, chan->rx_first_bd)); while ((status = cpc_readb(&ptdescr->status)) & DST_OSB) { nchar = cpc_readw(&ptdescr->len); if ((status & (DST_OVR | DST_CRC | DST_RBIT | DST_SHRT | DST_ABT)) || (nchar > BD_DEF_LEN)) { if (nchar > BD_DEF_LEN) status |= DST_RBIT; rcvd = -status; /* Discard remaining descriptors used by the bad frame */ while (chan->rx_first_bd != chan->rx_last_bd) { cpc_writeb(&ptdescr->status, 0); chan->rx_first_bd = (chan->rx_first_bd+1) & (N_DMA_RX_BUF-1); if (status & DST_EOM) break; ptdescr = (pcsca_bd_t *) (card->hw.rambase + cpc_readl(&ptdescr->next)); status = cpc_readb(&ptdescr->status); } break; } if (nchar != 0) { if (skb) { memcpy_fromio(skb_put(skb, nchar), (void *)(card->hw.rambase+cpc_readl(&ptdescr->ptbuf)),nchar); } rcvd += nchar; } cpc_writeb(&ptdescr->status, 0); cpc_writeb(&ptdescr->len, 0); chan->rx_first_bd = (chan->rx_first_bd + 1) & (N_DMA_RX_BUF - 1); if (status & DST_EOM) break; ptdescr = (pcsca_bd_t *) (card->hw.rambase + cpc_readl(&ptdescr->next)); } if (rcvd != 0) { /* Update pointer */ chan->rx_last_bd = (chan->rx_first_bd - 1) & (N_DMA_RX_BUF - 1); /* Update EDA */ cpc_writel(card->hw.scabase + DRX_REG(EDAL, ch), RX_BD_ADDR(ch, chan->rx_last_bd)); } return (rcvd);}void tx_dma_stop(pc300_t * card, int ch){ uclong scabase = card->hw.scabase; ucchar drr_ena_bit = 1 << (5 + 2 * ch); ucchar drr_rst_bit = 1 << (1 + 2 * ch); /* Disable DMA */ cpc_writeb(scabase + DRR, drr_ena_bit); cpc_writeb(scabase + DRR, drr_rst_bit & ~drr_ena_bit);}void rx_dma_stop(pc300_t * card, int ch){ uclong scabase = card->hw.scabase; ucchar drr_ena_bit = 1 << (4 + 2 * ch); ucchar drr_rst_bit = 1 << (2 * ch); /* Disable DMA */ cpc_writeb(scabase + DRR, drr_ena_bit); cpc_writeb(scabase + DRR, drr_rst_bit & ~drr_ena_bit);}void rx_dma_start(pc300_t * card, int ch){ uclong scabase = card->hw.scabase; pc300ch_t *chan = (pc300ch_t *) & card->chan[ch]; /* Start DMA */ cpc_writel(scabase + DRX_REG(CDAL, ch), RX_BD_ADDR(ch, chan->rx_first_bd)); if (cpc_readl(scabase + DRX_REG(CDAL,ch)) != RX_BD_ADDR(ch, chan->rx_first_bd)) { cpc_writel(scabase + DRX_REG(CDAL, ch), RX_BD_ADDR(ch, chan->rx_first_bd)); } cpc_writel(scabase + DRX_REG(EDAL, ch), RX_BD_ADDR(ch, chan->rx_last_bd)); cpc_writew(scabase + DRX_REG(BFLL, ch), BD_DEF_LEN); cpc_writeb(scabase + DSR_RX(ch), DSR_DE); if (!(cpc_readb(scabase + DSR_RX(ch)) & DSR_DE)) { cpc_writeb(scabase + DSR_RX(ch), DSR_DE); }}/*************************//*** FALC Routines ***//*************************/void falc_issue_cmd(pc300_t * card, int ch, ucchar cmd){ uclong falcbase = card->hw.falcbase; unsigned long i = 0; while (cpc_readb(falcbase + F_REG(SIS, ch)) & SIS_CEC) { if (i++ >= PC300_FALC_MAXLOOP) { printk("%s: FALC command locked(cmd=0x%x).\n", card->chan[ch].d.name, cmd); break; } } cpc_writeb(falcbase + F_REG(CMDR, ch), cmd);}void falc_intr_enable(pc300_t * card, int ch){ pc300ch_t *chan = (pc300ch_t *) & card->chan[ch]; pc300chconf_t *conf = (pc300chconf_t *) & chan->conf; falc_t *pfalc = (falc_t *) & chan->falc; uclong falcbase = card->hw.falcbase; /* Interrupt pins are open-drain */ cpc_writeb(falcbase + F_REG(IPC, ch), cpc_readb(falcbase + F_REG(IPC, ch)) & ~IPC_IC0); /* Conters updated each second */ cpc_writeb(falcbase + F_REG(FMR1, ch), cpc_readb(falcbase + F_REG(FMR1, ch)) | FMR1_ECM); /* Enable SEC and ES interrupts */ cpc_writeb(falcbase + F_REG(IMR3, ch), cpc_readb(falcbase + F_REG(IMR3, ch)) & ~(IMR3_SEC | IMR3_ES)); if (conf->fr_mode == PC300_FR_UNFRAMED) { cpc_writeb(falcbase + F_REG(IMR4, ch), cpc_readb(falcbase + F_REG(IMR4, ch)) & ~(IMR4_LOS)); } else { cpc_writeb(falcbase + F_REG(IMR4, ch), cpc_readb(falcbase + F_REG(IMR4, ch)) & ~(IMR4_LFA | IMR4_AIS | IMR4_LOS | IMR4_SLIP)); } if (conf->media == IF_IFACE_T1) { cpc_writeb(falcbase + F_REG(IMR3, ch), cpc_readb(falcbase + F_REG(IMR3, ch)) & ~IMR3_LLBSC); } else { cpc_writeb(falcbase + F_REG(IPC, ch), cpc_readb(falcbase + F_REG(IPC, ch)) | IPC_SCI); if (conf->fr_mode == PC300_FR_UNFRAMED) { cpc_writeb(falcbase + F_REG(IMR2, ch), cpc_readb(falcbase + F_REG(IMR2, ch)) & ~(IMR2_LOS)); } else { cpc_writeb(falcbase + F_REG(IMR2, ch), cpc_readb(falcbase + F_REG(IMR2, ch)) & ~(IMR2_FAR | IMR2_LFA | IMR2_AIS | IMR2_LOS)); if (pfalc->multiframe_mode) { cpc_writeb(falcbase + F_REG(IMR2, ch), cpc_readb(falcbase + F_REG(IMR2, ch)) & ~(IMR2_T400MS | IMR2_MFAR)); } else { cpc_writeb(falcbase + F_REG(IMR2, ch), cpc_readb(falcbase + F_REG(IMR2, ch)) | IMR2_T400MS | IMR2_MFAR); } } }}void falc_open_timeslot(pc300_t * card, int ch, int timeslot){ uclong falcbase = card->hw.falcbase; ucchar tshf = card->chan[ch].falc.offset; cpc_writeb(falcbase + F_REG((ICB1 + (timeslot - tshf) / 8), ch), cpc_readb(falcbase + F_REG((ICB1 + (timeslot - tshf) / 8), ch)) & ~(0x80 >> ((timeslot - tshf) & 0x07))); cpc_writeb(falcbase + F_REG((TTR1 + timeslot / 8), ch), cpc_readb(falcbase + F_REG((TTR1 + timeslot / 8), ch)) | (0x80 >> (timeslot & 0x07))); cpc_writeb(falcbase + F_REG((RTR1 + timeslot / 8), ch), cpc_readb(falcbase + F_REG((RTR1 + timeslot / 8), ch)) | (0x80 >> (timeslot & 0x07)));}void falc_close_timeslot(pc300_t * card, int ch, int timeslot){ uclong falcbase = card->hw.falcbase; ucchar tshf = card->chan[ch].falc.offset; cpc_writeb(falcbase + F_REG((ICB1 + (timeslot - tshf) / 8), ch), cpc_readb(falcbase + F_REG((ICB1 + (timeslot - tshf) / 8), ch)) | (0x80 >> ((timeslot - tshf) & 0x07))); cpc_writeb(falcbase + F_REG((TTR1 + timeslot / 8), ch), cpc_readb(falcbase + F_REG((TTR1 + timeslot / 8), ch)) & ~(0x80 >> (timeslot & 0x07))); cpc_writeb(falcbase + F_REG((RTR1 + timeslot / 8), ch), cpc_readb(falcbase + F_REG((RTR1 + timeslot / 8), ch)) & ~(0x80 >> (timeslot & 0x07)));}void falc_close_all_timeslots(pc300_t * card, int ch){ pc300ch_t *chan = (pc300ch_t *) & card->chan[ch]; pc300chconf_t *conf = (pc300chconf_t *) & chan->conf; uclong falcbase = card->hw.falcbase; cpc_writeb(falcbase + F_REG(ICB1, ch), 0xff); cpc_writeb(falcbase + F_REG(TTR1, ch), 0); cpc_writeb(falcbase + F_REG(RTR1, ch), 0); cpc_writeb(falcbase + F_REG(ICB2, ch), 0xff); cpc_writeb(falcbase + F_REG(TTR2, ch), 0); cpc_writeb(falcbase + F_REG(RTR2, ch), 0); cpc_writeb(falcbase + F_REG(ICB3, ch), 0xff); cpc_writeb(falcbase + F_REG(TTR3, ch), 0); cpc_writeb(falcbase + F_REG(RTR3, ch), 0); if (conf->media == IF_IFACE_E1) { cpc_writeb(falcbase + F_REG(ICB4, ch), 0xff); cpc_writeb(falcbase + F_REG(TTR4, ch), 0); cpc_writeb(falcbase + F_REG(RTR4, ch), 0); }}void falc_open_all_timeslots(pc300_t * card, int ch){ pc300ch_t *chan = (pc300ch_t *) & card->chan[ch]; pc300chconf_t *conf = (pc300chconf_t *) & chan->conf; uclong falcbase = card->hw.falcbase; cpc_writeb(falcbase + F_REG(ICB1, ch), 0); if (conf->fr_mode == PC300_FR_UNFRAMED) { cpc_writeb(falcbase + F_REG(TTR1, ch), 0xff); cpc_writeb(falcbase + F_REG(RTR1, ch), 0xff); } else { /* Timeslot 0 is never enabled */ cpc_writeb(falcbase + F_REG(TTR1, ch), 0x7f); cpc_writeb(falcbase + F_REG(RTR1, ch), 0x7f); } cpc_writeb(falcbase + F_REG(ICB2, ch), 0); cpc_writeb(falcbase + F_REG(TTR2, ch), 0xff); cpc_writeb(falcbase + F_REG(RTR2, ch), 0xff); cpc_writeb(falcbase + F_REG(ICB3, ch), 0); cpc_writeb(falcbase + F_REG(TTR3, ch), 0xff); cpc_writeb(falcbase + F_REG(RTR3, ch), 0xff); if (conf->media == IF_IFACE_E1) { cpc_writeb(falcbase + F_REG(ICB4, ch), 0); cpc_writeb(falcbase + F_REG(TTR4, ch), 0xff); cpc_writeb(falcbase + F_REG(RTR4, ch), 0xff); } else { cpc_writeb(falcbase + F_REG(ICB4, ch), 0xff); cpc_writeb(falcbase + F_REG(TTR4, ch), 0x80); cpc_writeb(falcbase + F_REG(RTR4, ch), 0x80); }}void falc_init_timeslot(pc300_t * card, int ch){ pc300ch_t *chan = (pc300ch_t *) & card->chan[ch]; pc300chconf_t *conf = (pc300chconf_t *) & chan->conf; falc_t *pfalc = (falc_t *) & chan->falc; int tslot; for (tslot = 0; tslot < pfalc->num_channels; tslot++) { if (conf->tslot_bitmap & (1 << tslot)) { // Channel enabled falc_open_timeslot(card, ch, tslot + 1); } else { // Channel disabled falc_close_timeslot(card, ch, tslot + 1); } }}void falc_enable_comm(pc300_t * card, int ch){ pc300ch_t *chan = (pc300ch_t *) & card->chan[ch]; falc_t *pfalc = (falc_t *) & chan->falc; if (pfalc->full_bandwidth) { falc_open_all_timeslots(card, ch); } else { falc_init_timeslot(card, ch); } // CTS/DCD ON cpc_writeb(card->hw.falcbase + card->hw.cpld_reg1, cpc_readb(card->hw.falcbase + card->hw.cpld_reg1) & ~((CPLD_REG1_FALC_DCD | CPLD_REG1_FALC_CTS) << (2 * ch)));}void falc_disable_comm(pc300_t * card, int ch){ pc300ch_t *chan = (pc300ch_t *) & card->chan[ch]; falc_t *pfalc = (falc_t *) & chan->falc; if (pfalc->loop_active != 2) { falc_close_all_timeslots(card, ch); } // CTS/DCD OFF cpc_writeb(card->hw.falcbase + card->hw.cpld_reg1, cpc_readb(card->hw.falcbase + card->hw.cpld_reg1) | ((CPLD_REG1_FALC_DCD | CPLD_REG1_FALC_CTS) << (2 * ch)));
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -