static int open_tx()

in iphase.c [1749:1899]


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(*ia_vcc));
        if (vcc->qos.txtp.max_sdu > 
                         (iadev->tx_buf_sz - sizeof(struct cpcs_trailer))){
           printk("IA:  SDU size over (%d) the configured SDU size %d\n",
		  vcc->qos.txtp.max_sdu,iadev->tx_buf_sz);
	   vcc->dev_data = NULL;
           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) {
	   struct sock *sk = sk_atm(vcc);

	   if (vcc->qos.txtp.max_sdu != 0) {
               if (ia_vcc->pcr > 60000)
                  sk->sk_sndbuf = vcc->qos.txtp.max_sdu * 5;
               else if (ia_vcc->pcr > 2000)
                  sk->sk_sndbuf = vcc->qos.txtp.max_sdu * 4;
               else
                 sk->sk_sndbuf = vcc->qos.txtp.max_sdu * 3;
           }
           else
             sk->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(*vc));  
	memset((caddr_t)evc, 0, sizeof(*evc));  
	  
	/* 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 not available\n");)
                   return -1;
                }
                vc->type = CBR;
                vc->status = CRC_APPEND;
                if ((ret = ia_cbr_setup (iadev, vcc)) < 0) {     
                    return ret;
                }
	} else {
		printk("iadev:  Non UBR, ABR and CBR traffic not supported\n");
	}
        
        iadev->testTable[vcc->vci]->vc_status |= VC_ACTIVE;
	IF_EVENT(printk("ia open_tx returning \n");)  
	return 0;  
}