static int ia_cbr_setup()

in iphase.c [462:576]


static int ia_cbr_setup (IADEV *dev, struct atm_vcc *vcc) {
   u32 rateLow=0, rateHigh, rate;
   int entries;
   struct ia_vcc *ia_vcc;

   int   idealSlot =0, testSlot, toBeAssigned, inc;
   u32   spacing;
   u16  *SchedTbl, *TstSchedTbl;
   u16  cbrVC, vcIndex;
   u32   fracSlot    = 0;
   u32   sp_mod      = 0;
   u32   sp_mod2     = 0;

   /* IpAdjustTrafficParams */
   if (vcc->qos.txtp.max_pcr <= 0) {
      IF_ERR(printk("PCR for CBR not defined\n");)
      return -1;
   }
   rate = vcc->qos.txtp.max_pcr;
   entries = rate / dev->Granularity;
   IF_CBR(printk("CBR: CBR entries=0x%x for rate=0x%x & Gran=0x%x\n",
                                entries, rate, dev->Granularity);)
   if (entries < 1)
      IF_CBR(printk("CBR: Bandwidth smaller than granularity of CBR table\n");) 
   rateLow  =  entries * dev->Granularity;
   rateHigh = (entries + 1) * dev->Granularity;
   if (3*(rate - rateLow) > (rateHigh - rate))
      entries++;
   if (entries > dev->CbrRemEntries) {
      IF_CBR(printk("CBR: Not enough bandwidth to support this PCR.\n");)
      IF_CBR(printk("Entries = 0x%x, CbrRemEntries = 0x%x.\n",
                                       entries, dev->CbrRemEntries);)
      return -EBUSY;
   }   

   ia_vcc = INPH_IA_VCC(vcc);
   ia_vcc->NumCbrEntry = entries; 
   dev->sum_mcr += entries * dev->Granularity; 
   /* IaFFrednInsertCbrSched */
   // Starting at an arbitrary location, place the entries into the table
   // as smoothly as possible
   cbrVC   = 0;
   spacing = dev->CbrTotEntries / entries;
   sp_mod  = dev->CbrTotEntries % entries; // get modulo
   toBeAssigned = entries;
   fracSlot = 0;
   vcIndex  = vcc->vci;
   IF_CBR(printk("Vci=0x%x,Spacing=0x%x,Sp_mod=0x%x\n",vcIndex,spacing,sp_mod);)
   while (toBeAssigned)
   {
      // If this is the first time, start the table loading for this connection
      // as close to entryPoint as possible.
      if (toBeAssigned == entries)
      {
         idealSlot = dev->CbrEntryPt;
         dev->CbrEntryPt += 2;    // Adding 2 helps to prevent clumping
         if (dev->CbrEntryPt >= dev->CbrTotEntries) 
            dev->CbrEntryPt -= dev->CbrTotEntries;// Wrap if necessary
      } else {
         idealSlot += (u32)(spacing + fracSlot); // Point to the next location
         // in the table that would be  smoothest
         fracSlot = ((sp_mod + sp_mod2) / entries);  // get new integer part
         sp_mod2  = ((sp_mod + sp_mod2) % entries);  // calc new fractional part
      }
      if (idealSlot >= (int)dev->CbrTotEntries) 
         idealSlot -= dev->CbrTotEntries;  
      // Continuously check around this ideal value until a null
      // location is encountered.
      SchedTbl = (u16*)(dev->seg_ram+CBR_SCHED_TABLE*dev->memSize); 
      inc = 0;
      testSlot = idealSlot;
      TstSchedTbl = (u16*)(SchedTbl+testSlot);  //set index and read in value
      IF_CBR(printk("CBR Testslot 0x%x AT Location 0x%p, NumToAssign=%d\n",
                                testSlot, TstSchedTbl,toBeAssigned);)
      memcpy((caddr_t)&cbrVC,(caddr_t)TstSchedTbl,sizeof(cbrVC));
      while (cbrVC)  // If another VC at this location, we have to keep looking
      {
          inc++;
          testSlot = idealSlot - inc;
          if (testSlot < 0) { // Wrap if necessary
             testSlot += dev->CbrTotEntries;
             IF_CBR(printk("Testslot Wrap. STable Start=0x%p,Testslot=%d\n",
                                                       SchedTbl,testSlot);)
          }
          TstSchedTbl = (u16 *)(SchedTbl + testSlot);  // set table index
          memcpy((caddr_t)&cbrVC,(caddr_t)TstSchedTbl,sizeof(cbrVC)); 
          if (!cbrVC)
             break;
          testSlot = idealSlot + inc;
          if (testSlot >= (int)dev->CbrTotEntries) { // Wrap if necessary
             testSlot -= dev->CbrTotEntries;
             IF_CBR(printk("TotCbrEntries=%d",dev->CbrTotEntries);)
             IF_CBR(printk(" Testslot=0x%x ToBeAssgned=%d\n", 
                                            testSlot, toBeAssigned);)
          } 
          // set table index and read in value
          TstSchedTbl = (u16*)(SchedTbl + testSlot);
          IF_CBR(printk("Reading CBR Tbl from 0x%p, CbrVal=0x%x Iteration %d\n",
                          TstSchedTbl,cbrVC,inc);)
          memcpy((caddr_t)&cbrVC,(caddr_t)TstSchedTbl,sizeof(cbrVC));
       } /* while */
       // Move this VCI number into this location of the CBR Sched table.
       memcpy((caddr_t)TstSchedTbl, (caddr_t)&vcIndex, sizeof(*TstSchedTbl));
       dev->CbrRemEntries--;
       toBeAssigned--;
   } /* while */ 

   /* IaFFrednCbrEnable */
   dev->NumEnabledCBR++;
   if (dev->NumEnabledCBR == 1) {
       writew((CBR_EN | UBR_EN | ABR_EN | (0x23 << 2)), dev->seg_reg+STPARMS);
       IF_CBR(printk("CBR is enabled\n");)
   }
   return 0;
}