📄 iphase.c
字号:
buf_desc_ptr->buf_start_hi = rx_pkt_start >> 16; buf_desc_ptr->buf_start_lo = rx_pkt_start & 0x0000ffff; buf_desc_ptr++; rx_pkt_start += iadev->rx_buf_sz; } IF_INIT(printk("Rx Buffer desc ptr: 0x%0x\n", (u32)(buf_desc_ptr));) i = FREE_BUF_DESC_Q*iadev->memSize; writew(i >> 16, iadev->reass_reg+REASS_QUEUE_BASE); writew(i, iadev->reass_reg+FREEQ_ST_ADR); writew(i+iadev->num_rx_desc*sizeof(u_short), iadev->reass_reg+FREEQ_ED_ADR); writew(i, iadev->reass_reg+FREEQ_RD_PTR); writew(i+iadev->num_rx_desc*sizeof(u_short), iadev->reass_reg+FREEQ_WR_PTR); /* Fill the FREEQ with all the free descriptors. */ freeq_st_adr = readw(iadev->reass_reg+FREEQ_ST_ADR); freeq_start = (u_short *)(iadev->reass_ram+freeq_st_adr); for(i=1; i<=iadev->num_rx_desc; i++) { *freeq_start = (u_short)i; freeq_start++; } IF_INIT(printk("freeq_start: 0x%0x\n", (u32)freeq_start);) /* Packet Complete Queue */ i = (PKT_COMP_Q * iadev->memSize) & 0xffff; writew(i, iadev->reass_reg+PCQ_ST_ADR); writew(i+iadev->num_vc*sizeof(u_short), iadev->reass_reg+PCQ_ED_ADR); writew(i, iadev->reass_reg+PCQ_RD_PTR); writew(i, iadev->reass_reg+PCQ_WR_PTR); /* Exception Queue */ i = (EXCEPTION_Q * iadev->memSize) & 0xffff; writew(i, iadev->reass_reg+EXCP_Q_ST_ADR); writew(i + NUM_RX_EXCP * sizeof(RX_ERROR_Q), iadev->reass_reg+EXCP_Q_ED_ADR); writew(i, iadev->reass_reg+EXCP_Q_RD_PTR); writew(i, iadev->reass_reg+EXCP_Q_WR_PTR); /* Load local copy of FREEQ and PCQ ptrs */ iadev->rfL.fdq_st = readw(iadev->reass_reg+FREEQ_ST_ADR) & 0xffff; iadev->rfL.fdq_ed = readw(iadev->reass_reg+FREEQ_ED_ADR) & 0xffff ; iadev->rfL.fdq_rd = readw(iadev->reass_reg+FREEQ_RD_PTR) & 0xffff; iadev->rfL.fdq_wr = readw(iadev->reass_reg+FREEQ_WR_PTR) & 0xffff; iadev->rfL.pcq_st = readw(iadev->reass_reg+PCQ_ST_ADR) & 0xffff; iadev->rfL.pcq_ed = readw(iadev->reass_reg+PCQ_ED_ADR) & 0xffff; iadev->rfL.pcq_rd = readw(iadev->reass_reg+PCQ_RD_PTR) & 0xffff; iadev->rfL.pcq_wr = readw(iadev->reass_reg+PCQ_WR_PTR) & 0xffff; IF_INIT(printk("INIT:pcq_st:0x%x pcq_ed:0x%x pcq_rd:0x%x pcq_wr:0x%x", iadev->rfL.pcq_st, iadev->rfL.pcq_ed, iadev->rfL.pcq_rd, iadev->rfL.pcq_wr);) /* just for check - no VP TBL */ /* VP Table */ /* writew(0x0b80, iadev->reass_reg+VP_LKUP_BASE); */ /* initialize VP Table for invalid VPIs - I guess we can write all 1s or 0x000f in the entire memory space or something similar. */ /* This seems to work and looks right to me too !!! */ i = REASS_TABLE * iadev->memSize; writew((i >> 3), iadev->reass_reg+REASS_TABLE_BASE); /* initialize Reassembly table to I don't know what ???? */ reass_table = (u16 *)(iadev->reass_ram+i); j = REASS_TABLE_SZ * iadev->memSize; for(i=0; i < j; i++) *reass_table++ = NO_AAL5_PKT; i = 8*1024; vcsize_sel = 0; while (i != iadev->num_vc) { i /= 2; vcsize_sel++; } i = RX_VC_TABLE * iadev->memSize; writew(((i>>3) & 0xfff8) | vcsize_sel, iadev->reass_reg+VC_LKUP_BASE); vc_table = (u16 *)(iadev->reass_ram+RX_VC_TABLE*iadev->memSize); j = RX_VC_TABLE_SZ * iadev->memSize; for(i = 0; i < j; i++) { /* shift the reassembly pointer by 3 + lower 3 bits of vc_lkup_base register (=3 for 1K VCs) and the last byte is those low 3 bits. Shall program this later. */ *vc_table = (i << 6) | 15; /* for invalid VCI */ vc_table++; } /* ABR VC table */ i = ABR_VC_TABLE * iadev->memSize; writew(i >> 3, iadev->reass_reg+ABR_LKUP_BASE); i = ABR_VC_TABLE * iadev->memSize; abr_vc_table = (struct abr_vc_table *)(iadev->reass_ram+i); j = REASS_TABLE_SZ * iadev->memSize; memset ((char*)abr_vc_table, 0, j * sizeof(struct abr_vc_table ) ); for(i = 0; i < j; i++) { abr_vc_table->rdf = 0x0003; abr_vc_table->air = 0x5eb1; abr_vc_table++; } /* Initialize other registers */ /* VP Filter Register set for VC Reassembly only */ writew(0xff00, iadev->reass_reg+VP_FILTER); writew(0, iadev->reass_reg+XTRA_RM_OFFSET); writew(0x1, iadev->reass_reg+PROTOCOL_ID); /* Packet Timeout Count related Registers : Set packet timeout to occur in about 3 seconds Set Packet Aging Interval count register to overflow in about 4 us */ writew(0xF6F8, iadev->reass_reg+PKT_TM_CNT ); ptr16 = (u16*)j; i = ((u32)ptr16 >> 6) & 0xff; ptr16 += j - 1; i |=(((u32)ptr16 << 2) & 0xff00); writew(i, iadev->reass_reg+TMOUT_RANGE); /* initiate the desc_tble */ for(i=0; i<iadev->num_tx_desc;i++) iadev->desc_tbl[i].timestamp = 0; /* to clear the interrupt status register - read it */ readw(iadev->reass_reg+REASS_INTR_STATUS_REG); /* Mask Register - clear it */ writew(~(RX_FREEQ_EMPT|RX_PKT_RCVD), iadev->reass_reg+REASS_MASK_REG); skb_queue_head_init(&iadev->rx_dma_q); iadev->rx_free_desc_qhead = NULL; iadev->rx_open =(struct atm_vcc **)kmalloc(4*iadev->num_vc,GFP_KERNEL); if (!iadev->rx_open) { printk(KERN_ERR DEV_LABEL "itf %d couldn't get free page\n", dev->number); return -ENOMEM; } memset(iadev->rx_open, 0, 4*iadev->num_vc); iadev->rxing = 1; iadev->rx_pkt_cnt = 0; /* Mode Register */ writew(R_ONLINE, iadev->reass_reg+MODE_REG); return 0; } /* The memory map suggested in appendix A and the coding for it. Keeping it around just in case we change our mind later. Buffer descr 0x0000 (128 - 4K) UBR sched 0x1000 (1K - 4K) UBR Wait q 0x2000 (1K - 4K) Commn queues 0x3000 Packet Ready, Trasmit comp(0x3100) (128 - 256) each extended VC 0x4000 (1K - 8K) ABR sched 0x6000 and ABR wait queue (1K - 2K) each CBR sched 0x7000 (as needed) VC table 0x8000 (1K - 32K) */ static void tx_intr(struct atm_dev *dev) { IADEV *iadev; unsigned short status; unsigned long flags; iadev = INPH_IA_DEV(dev); status = readl(iadev->seg_reg+SEG_INTR_STATUS_REG); if (status & TRANSMIT_DONE){ IF_EVENT(printk("Tansmit Done Intr logic run\n");) spin_lock_irqsave(&iadev->tx_lock, flags); ia_tx_poll(iadev); spin_unlock_irqrestore(&iadev->tx_lock, flags); writew(TRANSMIT_DONE, iadev->seg_reg+SEG_INTR_STATUS_REG); if (iadev->close_pending) wake_up(&iadev->close_wait); } if (status & TCQ_NOT_EMPTY) { IF_EVENT(printk("TCQ_NOT_EMPTY int received\n");) } } static void tx_dle_intr(struct atm_dev *dev){ IADEV *iadev; struct dle *dle, *cur_dle; struct sk_buff *skb; struct atm_vcc *vcc; struct ia_vcc *iavcc; u_int dle_lp; unsigned long flags; iadev = INPH_IA_DEV(dev); spin_lock_irqsave(&iadev->tx_lock, flags); dle = iadev->tx_dle_q.read; dle_lp = readl(iadev->dma+IPHASE5575_TX_LIST_ADDR) & (sizeof(struct dle)*DLE_ENTRIES - 1); cur_dle = (struct dle*)(iadev->tx_dle_q.start + (dle_lp >> 4)); while (dle != cur_dle) { /* free the DMAed skb */ skb = skb_dequeue(&iadev->tx_dma_q); if (!skb) break; vcc = ATM_SKB(skb)->vcc; if (!vcc) { printk("tx_dle_intr: vcc is null\n"); spin_unlock_irqrestore(&iadev->tx_lock, flags); dev_kfree_skb_any(skb); return; } iavcc = INPH_IA_VCC(vcc); if (!iavcc) { printk("tx_dle_intr: iavcc is null\n"); spin_unlock_irqrestore(&iadev->tx_lock, flags); dev_kfree_skb_any(skb); return; } if (vcc->qos.txtp.pcr >= iadev->rate_limit) { if ((vcc->pop) && (skb->len != 0)) { vcc->pop(vcc, skb); } else { dev_kfree_skb_any(skb); } } else { /* Hold the rate-limited skb for flow control */ IA_SKB_STATE(skb) |= IA_DLED; skb_queue_tail(&iavcc->txing_skb, skb); } IF_EVENT(printk("tx_dle_intr: enque skb = 0x%x \n", (u32)skb);) if (++dle == iadev->tx_dle_q.end) dle = iadev->tx_dle_q.start; } iadev->tx_dle_q.read = dle; spin_unlock_irqrestore(&iadev->tx_lock, flags);} static int open_tx(struct atm_vcc *vcc) { struct ia_vcc *ia_vcc; IADEV *iadev; struct main_vc *vc; struct ext_vc *evc; int ret; IF_EVENT(printk("iadev: open_tx entered vcc->vci = %d\n", vcc->vci);) if (vcc->qos.txtp.traffic_class == ATM_NONE) return 0; iadev = INPH_IA_DEV(vcc->dev); if (iadev->phy_type & FE_25MBIT_PHY) { if (vcc->qos.txtp.traffic_class == ATM_ABR) { printk("IA: ABR not support\n"); return -EINVAL; } if (vcc->qos.txtp.traffic_class == ATM_CBR) { printk("IA: CBR not support\n"); return -EINVAL; } } ia_vcc = INPH_IA_VCC(vcc); memset((caddr_t)ia_vcc, 0, sizeof(struct ia_vcc)); if (vcc->qos.txtp.max_sdu > (iadev->tx_buf_sz - sizeof(struct cpcs_trailer))){ printk("IA: SDU size over the configured SDU size %d\n", iadev->tx_buf_sz); kfree(ia_vcc); return -EINVAL; } ia_vcc->vc_desc_cnt = 0; ia_vcc->txing = 1; /* find pcr */ if (vcc->qos.txtp.max_pcr == ATM_MAX_PCR) vcc->qos.txtp.pcr = iadev->LineRate; else if ((vcc->qos.txtp.max_pcr == 0)&&( vcc->qos.txtp.pcr <= 0)) vcc->qos.txtp.pcr = iadev->LineRate; else if ((vcc->qos.txtp.max_pcr > vcc->qos.txtp.pcr) && (vcc->qos.txtp.max_pcr> 0)) vcc->qos.txtp.pcr = vcc->qos.txtp.max_pcr; if (vcc->qos.txtp.pcr > iadev->LineRate) vcc->qos.txtp.pcr = iadev->LineRate; ia_vcc->pcr = vcc->qos.txtp.pcr; if (ia_vcc->pcr > (iadev->LineRate / 6) ) ia_vcc->ltimeout = HZ / 10; else if (ia_vcc->pcr > (iadev->LineRate / 130)) ia_vcc->ltimeout = HZ; else if (ia_vcc->pcr <= 170) ia_vcc->ltimeout = 16 * HZ; else ia_vcc->ltimeout = 2700 * HZ / ia_vcc->pcr; if (ia_vcc->pcr < iadev->rate_limit) skb_queue_head_init (&ia_vcc->txing_skb); if (ia_vcc->pcr < iadev->rate_limit) { if (vcc->qos.txtp.max_sdu != 0) { if (ia_vcc->pcr > 60000) vcc->sk->sndbuf = vcc->qos.txtp.max_sdu * 5; else if (ia_vcc->pcr > 2000) vcc->sk->sndbuf = vcc->qos.txtp.max_sdu * 4; else vcc->sk->sndbuf = 3*vcc->qos.txtp.max_sdu; } else vcc->sk->sndbuf = 24576; } vc = (struct main_vc *)iadev->MAIN_VC_TABLE_ADDR; evc = (struct ext_vc *)iadev->EXT_VC_TABLE_ADDR; vc += vcc->vci; evc += vcc->vci; memset((caddr_t)vc, 0, sizeof(struct main_vc)); memset((caddr_t)evc, 0, sizeof(struct ext_vc)); /* store the most significant 4 bits of vci as the last 4 bits of first part of atm header. store the last 12 bits of vci as first 12 bits of the second part of the atm header. */ evc->atm_hdr1 = (vcc->vci >> 12) & 0x000f; evc->atm_hdr2 = (vcc->vci & 0x0fff) << 4; /* check the following for different traffic classes */ if (vcc->qos.txtp.traffic_class == ATM_UBR) { vc->type = UBR; vc->status = CRC_APPEND; vc->acr = cellrate_to_float(iadev->LineRate); if (vcc->qos.txtp.pcr > 0) vc->acr = cellrate_to_float(vcc->qos.txtp.pcr); IF_UBR(printk("UBR: txtp.pcr = 0x%x f_rate = 0x%x\n", vcc->qos.txtp.max_pcr,vc->acr);) } else if (vcc->qos.txtp.traffic_class == ATM_ABR) { srv_cls_param_t srv_p; IF_ABR(printk("Tx ABR VCC\n");) init_abr_vc(iadev, &srv_p); if (vcc->qos.txtp.pcr > 0) srv_p.pcr = vcc->qos.txtp.pcr; if (vcc->qos.txtp.min_pcr > 0) { int tmpsum = iadev->sum_mcr+iadev->sum_cbr+vcc->qos.txtp.min_pcr; if (tmpsum > iadev->LineRate) return -EBUSY; srv_p.mcr = vcc->qos.txtp.min_pcr; iadev->sum_mcr += vcc->qos.txtp.min_pcr; } else srv_p.mcr = 0; if (vcc->qos.txtp.icr) srv_p.icr = vcc->qos.txtp.icr; if (vcc->qos.txtp.tbe) srv_p.tbe = vcc->qos.txtp.tbe; if (vcc->qos.txtp.frtt) srv_p.frtt = vcc->qos.txtp.frtt; if (vcc->qos.txtp.rif) srv_p.rif = vcc->qos.txtp.rif; if (vcc->qos.txtp.rdf) srv_p.rdf = vcc->qos.txtp.rdf; if (vcc->qos.txtp.nrm_pres) srv_p.nrm = vcc->qos.txtp.nrm; if (vcc->qos.txtp.trm_pres) srv_p.trm = vcc->qos.txtp.trm; if (vcc->qos.txtp.adtf_pres) srv_p.adtf = vcc->qos.txtp.adtf; if (vcc->qos.txtp.cdf_pres) srv_p.cdf = vcc->qos.txtp.cdf; if (srv_p.icr > srv_p.pcr) srv_p.icr = srv_p.pcr; IF_ABR(printk("ABR:vcc->qos.txtp.max_pcr = %d mcr = %d\n", srv_p.pcr, srv_p.mcr);) ia_open_abr_vc(iadev, &srv_p, vcc, 1); } else if (vcc->qos.txtp.traffic_class == ATM_CBR) { if (iadev->phy_type & FE_25MBIT_PHY) { printk("IA: CBR not support\n"); return -EINVAL; } if (vcc->qos.txtp.max_pcr > iadev->LineRate) { IF_CBR(printk("PCR is
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -