コード例 #1
0
/** Map all PDOs from slaves to IOmap.
 *
 * @param[out] pIOmap	  = pointer to IOmap	
 * @return IOmap size
 */
int ec_config_map(void *pIOmap)
{
    uint16 slave, configadr;
	int Isize, Osize, BitCount, ByteCount, FMMUsize, FMMUdone;
	uint16 SMlength;
    uint8 BitPos, EndAddr;
	uint8 SMc, FMMUc;
	uint32 LogAddr = 0;
	int nSM, rval;
	ec_eepromPDOt eepPDO;

	if (ec_slavecount > 0)
	{	
		LogAddr = 0;
		BitPos = 0;

		/* find output mapping of slave and program FMMU0 */
		for (slave = 1; slave <= ec_slavecount; slave++)
        {
            configadr = ec_slave[slave].configadr;

			ec_statecheck(slave, EC_STATE_PRE_OP,  EC_TIMEOUTSTATE); //* check state change pre-op */
			
			/* if slave not found in configlist find IO mapping in slave self */
			if (!ec_slave[slave].configindex)
			{
				Isize = 0;
				Osize = 0;
				if (ec_slave[slave].mbx_proto & ECT_MBXPROT_COE) /* has CoE */
				{
					if (ec_slave[slave].CoEdetails & ECT_COEDET_SDOCA) /* has Complete Access */
					{
						/* read PDO mapping via CoE and use Complete Access */
						rval = ec_readPDOmapCA(slave, &Osize, &Isize);
					}
					else
					{
						/* read PDO mapping via CoE */
						rval = ec_readPDOmap(slave, &Osize, &Isize);
					}	
					ec_slave[slave].SM[2].SMlength = htoes((Osize + 7) / 8);
					ec_slave[slave].SM[3].SMlength = htoes((Isize + 7) / 8);
				}
				if ((!Isize && !Osize) && (ec_slave[slave].mbx_proto & ECT_MBXPROT_SOE)) /* has SoE */
				{
					/* read AT / MDT mapping via SoE */
					rval = ec_readIDNmap(slave, &Osize, &Isize);
					ec_slave[slave].SM[2].SMlength = htoes((Osize + 7) / 8);
					ec_slave[slave].SM[3].SMlength = htoes((Isize + 7) / 8);
				}
				if (!Isize && !Osize) /* find PDO mapping by SII */
				{
					Isize = ec_siiPDO (slave, &eepPDO, 0);
					for( nSM=0 ; nSM < EC_MAXSM ; nSM++ )
					{	
						if (eepPDO.SMbitsize[nSM] > 0)
						{	
							ec_slave[slave].SM[nSM].SMlength =  htoes((eepPDO.SMbitsize[nSM] + 7) / 8);
							ec_slave[slave].SMtype[nSM] = 3;
						}	
					}	
					Osize = ec_siiPDO (slave, &eepPDO, 1);
					for( nSM=0 ; nSM < EC_MAXSM ; nSM++ )
					{	
						if (eepPDO.SMbitsize[nSM] > 0)
						{	
							ec_slave[slave].SM[nSM].SMlength =  htoes((eepPDO.SMbitsize[nSM] + 7) / 8);
							ec_slave[slave].SMtype[nSM] = 2;
						}	
					}	
				}
				ec_slave[slave].Obits = Osize;
				ec_slave[slave].Ibits = Isize;
				
			}

			if (!ec_slave[slave].mbx_l && ec_slave[slave].SM[0].StartAddr)
			{
				ec_FPWR (configadr, ECT_REG_SM0, sizeof(ec_smt), &ec_slave[slave].SM[0], EC_TIMEOUTRET);
			}	
			if (!ec_slave[slave].mbx_l && ec_slave[slave].SM[1].StartAddr)
			{
				ec_FPWR (configadr, ECT_REG_SM1, sizeof(ec_smt), &ec_slave[slave].SM[1], EC_TIMEOUTRET);
			}	
			if (ec_slave[slave].SM[2].StartAddr)
			{
				/* check if SM length is zero -> clear enable flag */
				if( ec_slave[slave].SM[2].SMlength == 0) 
					ec_slave[slave].SM[2].SMflags = htoel( etohl(ec_slave[slave].SM[2].SMflags) & EC_SMENABLEMASK);
				ec_FPWR (configadr, ECT_REG_SM2, sizeof(ec_smt), &ec_slave[slave].SM[2], EC_TIMEOUTRET);
			}	
			// usleep(1000); // was needed for NETX (needs internal time after SM update)
			if (ec_slave[slave].SM[3].StartAddr)
			{
				/* check if SM length is zero -> clear enable flag */
				if( ec_slave[slave].SM[3].SMlength == 0)
					ec_slave[slave].SM[3].SMflags = htoel( etohl(ec_slave[slave].SM[3].SMflags) & EC_SMENABLEMASK);
				ec_FPWR (configadr, ECT_REG_SM3, sizeof(ec_smt), &ec_slave[slave].SM[3], EC_TIMEOUTRET);
			}	
			if (ec_slave[slave].Ibits > 7)
				ec_slave[slave].Ibytes = (ec_slave[slave].Ibits + 7) / 8;
			if (ec_slave[slave].Obits > 7)
				ec_slave[slave].Obytes = (ec_slave[slave].Obits + 7) / 8;

			FMMUc = 0;
			SMc = 0;
			BitCount = 0;
			ByteCount = 0;
			EndAddr = 0;
			FMMUsize = 0;
			FMMUdone = 0;
			/* create output mapping */
			if (ec_slave[slave].Obits)
			{
				/* search for SM that contribute to the output mapping */
				while ( (SMc < (EC_MAXSM - 1)) && (FMMUdone < ((ec_slave[slave].Obits + 7) / 8)))
				{	
					while ( (SMc < (EC_MAXSM - 1)) && (ec_slave[slave].SMtype[SMc] != 2)) SMc++;
					ec_slave[slave].FMMU[FMMUc].PhysStart = ec_slave[slave].SM[SMc].StartAddr;
					SMlength = etohs(ec_slave[slave].SM[SMc].SMlength);
					ByteCount += SMlength;
					BitCount += SMlength * 8;
					EndAddr = etohs(ec_slave[slave].SM[SMc].StartAddr) + SMlength;
					while ( (BitCount < ec_slave[slave].Obits) && (SMc < (EC_MAXSM - 1)) ) /* more SM for output */
					{
						SMc++;
						while ( (SMc < (EC_MAXSM - 1)) && (ec_slave[slave].SMtype[SMc] != 2)) SMc++;
						/* if addresses from more SM connect use one FMMU otherwise break up in mutiple FMMU */
						if ( etohs(ec_slave[slave].SM[SMc].StartAddr) > EndAddr ) break;
						SMlength = etohs(ec_slave[slave].SM[SMc].SMlength);
						ByteCount += SMlength;
						BitCount += SMlength * 8;
						EndAddr = etohs(ec_slave[slave].SM[SMc].StartAddr) + SMlength;					
					}	

					/* bit oriented slave */
					if (!ec_slave[slave].Obytes)
					{	
						ec_slave[slave].FMMU[FMMUc].LogStart = htoel(LogAddr);
						ec_slave[slave].FMMU[FMMUc].LogStartbit = BitPos;
						BitPos += ec_slave[slave].Obits - 1;
						if (BitPos > 7)
						{
							LogAddr++;
							BitPos -= 8;
						}	
						FMMUsize = LogAddr - etohl(ec_slave[slave].FMMU[FMMUc].LogStart) + 1;
						ec_slave[slave].FMMU[FMMUc].LogLength = htoes(FMMUsize);
						ec_slave[slave].FMMU[FMMUc].LogEndbit = BitPos;
						BitPos ++;
						if (BitPos > 7)
						{
							LogAddr++;
							BitPos -= 8;
						}	
					}
					/* byte oriented slave */
					else
					{
						if (BitPos)
						{
							LogAddr++;
							BitPos = 0;
						}	
						ec_slave[slave].FMMU[FMMUc].LogStart = htoel(LogAddr);
						ec_slave[slave].FMMU[FMMUc].LogStartbit = BitPos;
						BitPos = 7;
						FMMUsize = ByteCount;
						if ((FMMUsize + FMMUdone)> ec_slave[slave].Obytes)
							FMMUsize = ec_slave[slave].Obytes - FMMUdone;
						LogAddr += FMMUsize;
						ec_slave[slave].FMMU[FMMUc].LogLength = htoes(FMMUsize);
						ec_slave[slave].FMMU[FMMUc].LogEndbit = BitPos;
						BitPos = 0;
					}
					FMMUdone += FMMUsize;
					ec_slave[slave].FMMU[FMMUc].PhysStartBit = 0;
					ec_slave[slave].FMMU[FMMUc].FMMUtype = 2;
					ec_slave[slave].FMMU[FMMUc].FMMUactive = 1;
					/* program FMMU for output */
					ec_FPWR (configadr, ECT_REG_FMMU0 + (sizeof(ec_fmmut) * FMMUc), sizeof(ec_fmmut), 
					         &ec_slave[slave].FMMU[FMMUc], EC_TIMEOUTRET);
					if (!ec_slave[slave].outputs)
					{	
						ec_slave[slave].outputs = pIOmap + etohl(ec_slave[slave].FMMU[FMMUc].LogStart);
						ec_slave[slave].Ostartbit = ec_slave[slave].FMMU[FMMUc].LogStartbit;
					}
					FMMUc++;
				}	
			}
        }
		ec_slave[0].outputs = pIOmap;
		if (BitPos)
		{
			LogAddr++;
			BitPos = 0;
		}	
		ec_slave[0].Obytes = LogAddr; /* store output bytes in master record */
		
		/* do input mapping of slave and program FMMUs */
		for (slave = 1; slave <= ec_slavecount; slave++)
        {
            configadr = ec_slave[slave].configadr;
			FMMUc = 1;
			if (ec_slave[slave].Obits) /* find free FMMU */
			{	
				while ( ec_slave[slave].FMMU[FMMUc].LogStart ) FMMUc++;
			}
			SMc = 0;
			BitCount = 0;
			ByteCount = 0;
			EndAddr = 0;
			FMMUsize = 0;
			FMMUdone = 0;
			/* create input mapping */
			if (ec_slave[slave].Ibits)
			{
				/* search for SM that contribute to the input mapping */
				while ( (SMc < (EC_MAXSM - 1)) && (FMMUdone < ((ec_slave[slave].Ibits + 7) / 8)))
				{	
					while ( (SMc < (EC_MAXSM - 1)) && (ec_slave[slave].SMtype[SMc] != 3)) SMc++;
					ec_slave[slave].FMMU[FMMUc].PhysStart = ec_slave[slave].SM[SMc].StartAddr;
					SMlength = etohs(ec_slave[slave].SM[SMc].SMlength);
					ByteCount += SMlength;
					BitCount += SMlength * 8;
					EndAddr = etohs(ec_slave[slave].SM[SMc].StartAddr) + SMlength;
					while ( (BitCount < ec_slave[slave].Obits) && (SMc < (EC_MAXSM - 1)) ) /* more SM for input */
					{
						SMc++;
						while ( (SMc < (EC_MAXSM - 1)) && (ec_slave[slave].SMtype[SMc] != 3)) SMc++;
						/* if addresses from more SM connect use one FMMU otherwise break up in mutiple FMMU */
						if ( etohs(ec_slave[slave].SM[SMc].StartAddr) > EndAddr ) break;
						SMlength = etohs(ec_slave[slave].SM[SMc].SMlength);
						ByteCount += SMlength;
						BitCount += SMlength * 8;
						EndAddr = etohs(ec_slave[slave].SM[SMc].StartAddr) + SMlength;					
					}	

					/* bit oriented slave */
					if (!ec_slave[slave].Ibytes)
					{	
						ec_slave[slave].FMMU[FMMUc].LogStart = htoel(LogAddr);
						ec_slave[slave].FMMU[FMMUc].LogStartbit = BitPos;
						BitPos += ec_slave[slave].Ibits - 1;
						if (BitPos > 7)
						{
							LogAddr++;
							BitPos -= 8;
						}	
						FMMUsize = LogAddr - etohl(ec_slave[slave].FMMU[FMMUc].LogStart) + 1;
						ec_slave[slave].FMMU[FMMUc].LogLength = htoes(FMMUsize);
						ec_slave[slave].FMMU[FMMUc].LogEndbit = BitPos;
						BitPos ++;
						if (BitPos > 7)
						{
							LogAddr++;
							BitPos -= 8;
						}	
					}
					/* byte oriented slave */
					else
					{
						if (BitPos)
						{
							LogAddr++;
							BitPos = 0;
						}	
						ec_slave[slave].FMMU[FMMUc].LogStart = htoel(LogAddr);
						ec_slave[slave].FMMU[FMMUc].LogStartbit = BitPos;
						BitPos = 7;
						FMMUsize = ByteCount;
						if ((FMMUsize + FMMUdone)> ec_slave[slave].Ibytes)
							FMMUsize = ec_slave[slave].Ibytes - FMMUdone;
						LogAddr += FMMUsize;
						ec_slave[slave].FMMU[FMMUc].LogLength = htoes(FMMUsize);
						ec_slave[slave].FMMU[FMMUc].LogEndbit = BitPos;
						BitPos = 0;
					}
					FMMUdone += FMMUsize;
					if (ec_slave[slave].FMMU[FMMUc].LogLength)
					{	
						ec_slave[slave].FMMU[FMMUc].PhysStartBit = 0;
						ec_slave[slave].FMMU[FMMUc].FMMUtype = 1;
						ec_slave[slave].FMMU[FMMUc].FMMUactive = 1;
						/* program FMMU for input */
						ec_FPWR (configadr, ECT_REG_FMMU0 + (sizeof(ec_fmmut) * FMMUc), sizeof(ec_fmmut), 
						         &ec_slave[slave].FMMU[FMMUc], EC_TIMEOUTRET);
					}	
					if (!ec_slave[slave].inputs)
					{	
						ec_slave[slave].inputs = pIOmap + etohl(ec_slave[slave].FMMU[FMMUc].LogStart);
						ec_slave[slave].Istartbit = ec_slave[slave].FMMU[FMMUc].LogStartbit;
					}
					FMMUc++;
				}	
			}

			ec_eeprom2pdi(slave); /* set Eeprom control to PDI */			
			ec_FPWRw(configadr, ECT_REG_ALCTL, htoes(EC_STATE_SAFE_OP) , EC_TIMEOUTRET); /* set safeop status */
						
		}
		ec_slave[0].inputs = pIOmap + ec_slave[0].Obytes;
		if (BitPos)
		{
			LogAddr++;
			BitPos = 0;
		}	
		ec_slave[0].Ibytes = LogAddr - ec_slave[0].Obytes; /* store input bytes in master record */
		
	}
	return LogAddr;
}	
コード例 #2
0
/** Map all PDOs in one group of slaves to IOmap.
 *
 * @param[out] pIOmap	  = pointer to IOmap	
 * @param[in]  group	  = group to map, 0 = all groups	
 * @return IOmap size
 */
int ec_config_map_group(void *pIOmap, uint8 group)
{
  uint16 slave, configadr;
  int Isize, Osize, BitCount, ByteCount, FMMUsize, FMMUdone;
  uint16 SMlength;
  uint8 BitPos, EndAddr;
  uint8 SMc, FMMUc;
  uint32 LogAddr = 0;
  uint32 oLogAddr = 0;
  uint32 diff;
  int nSM; //, rval;
  ec_eepromPDOt eepPDO;
  uint16 currentsegment = 0;
  uint32 segmentsize = 0;

  if ((ec_slavecount > 0) && (group < EC_MAXGROUP))
  {
    EC_PRINT("ec_config_map_group IOmap:%p group:%d\n", pIOmap, group);
    LogAddr = ec_group[group].logstartaddr;
    oLogAddr = LogAddr;
    BitPos = 0;
    ec_group[group].nsegments = 0;
    ec_group[group].expectedWKC = 0;

    /* find output mapping of slave and program FMMU */
    for (slave = 1; slave <= ec_slavecount; slave++)
    {
      configadr = ec_slave[slave].configadr;

      ec_statecheck(slave, EC_STATE_PRE_OP, EC_TIMEOUTSTATE); /* check state change pre-op */

      EC_PRINT(" >Slave %d, configadr %x, state %2.2x\n", slave, ec_slave[slave].configadr, ec_slave[slave].state);

      if (!group || (group == ec_slave[slave].group))
      {

        /* if slave not found in configlist find IO mapping in slave self */
        if (!ec_slave[slave].configindex)
        {
          Isize = 0;
          Osize = 0;
          if (ec_slave[slave].mbx_proto & ECT_MBXPROT_COE) /* has CoE */
          {
            if (ec_slave[slave].CoEdetails & ECT_COEDET_SDOCA) /* has Complete Access */
              /* read PDO mapping via CoE and use Complete Access */
              /*rval =*/ec_readPDOmapCA(slave, &Osize, &Isize);
            else
              /* read PDO mapping via CoE */
              /*rval =*/ec_readPDOmap(slave, &Osize, &Isize);
            EC_PRINT("  CoE Osize:%d Isize:%d\n", Osize, Isize);
          }
          if ((!Isize && !Osize) && (ec_slave[slave].mbx_proto & ECT_MBXPROT_SOE)) /* has SoE */
          {
            /* read AT / MDT mapping via SoE */
            /*rval =*/ec_readIDNmap(slave, &Osize, &Isize);
            ec_slave[slave].SM[2].SMlength = htoes((Osize + 7) / 8);
            ec_slave[slave].SM[3].SMlength = htoes((Isize + 7) / 8);
            EC_PRINT("  SoE Osize:%d Isize:%d\n", Osize, Isize);
          }
          if (!Isize && !Osize) /* find PDO mapping by SII */
          {
            memset(&eepPDO, 0, sizeof(eepPDO));
            Isize = (int)ec_siiPDO(slave, &eepPDO, 0);
            EC_PRINT("  SII Isize:%d\n", Isize);
            for (nSM = 0; nSM < EC_MAXSM; nSM++)
            {
              if (eepPDO.SMbitsize[nSM] > 0)
              {
                ec_slave[slave].SM[nSM].SMlength = htoes((eepPDO.SMbitsize[nSM] + 7) / 8);
                ec_slave[slave].SMtype[nSM] = 4;
                EC_PRINT("    SM%d length %d\n", nSM, eepPDO.SMbitsize[nSM]);
              }
            }
            Osize = (int)ec_siiPDO(slave, &eepPDO, 1);
            EC_PRINT("  SII Osize:%d\n", Osize);
            for (nSM = 0; nSM < EC_MAXSM; nSM++)
            {
              if (eepPDO.SMbitsize[nSM] > 0)
              {
                ec_slave[slave].SM[nSM].SMlength = htoes((eepPDO.SMbitsize[nSM] + 7) / 8);
                ec_slave[slave].SMtype[nSM] = 3;
                EC_PRINT("    SM%d length %d\n", nSM, eepPDO.SMbitsize[nSM]);
              }
            }
          }
          ec_slave[slave].Obits = Osize;
          ec_slave[slave].Ibits = Isize;
          EC_PRINT("     ISIZE:%d %d OSIZE:%d\n", ec_slave[slave].Ibits, Isize, ec_slave[slave].Obits);

        }

        EC_PRINT("  SM programming\n");
        if (!ec_slave[slave].mbx_l && ec_slave[slave].SM[0].StartAddr)
        {
          ec_FPWR(configadr, ECT_REG_SM0, sizeof(ec_smt), &ec_slave[slave].SM[0], EC_TIMEOUTRET);
          EC_PRINT("    SM0 Type:%d StartAddr:%4.4x Flags:%8.8x\n", ec_slave[slave].SMtype[0],
                   ec_slave[slave].SM[0].StartAddr, ec_slave[slave].SM[0].SMflags);
        }
        if (!ec_slave[slave].mbx_l && ec_slave[slave].SM[1].StartAddr)
        {
          ec_FPWR(configadr, ECT_REG_SM1, sizeof(ec_smt), &ec_slave[slave].SM[1], EC_TIMEOUTRET);
          EC_PRINT("    SM1 Type:%d StartAddr:%4.4x Flags:%8.8x\n", ec_slave[slave].SMtype[1],
                   ec_slave[slave].SM[1].StartAddr, ec_slave[slave].SM[1].SMflags);
        }
        /* program SM2 to SMx */
        for (nSM = 2; nSM < EC_MAXSM; nSM++)
        {
          if (ec_slave[slave].SM[nSM].StartAddr)
          {
            /* check if SM length is zero -> clear enable flag */
            if (ec_slave[slave].SM[nSM].SMlength == 0)
              ec_slave[slave].SM[nSM].SMflags = htoel( etohl(ec_slave[slave].SM[nSM].SMflags) & EC_SMENABLEMASK);
            ec_FPWR(configadr, ECT_REG_SM0 + (nSM * sizeof(ec_smt)), sizeof(ec_smt), &ec_slave[slave].SM[nSM],
                    EC_TIMEOUTRET);
            EC_PRINT("    SM%d Type:%d StartAddr:%4.4x Flags:%8.8x\n", nSM, ec_slave[slave].SMtype[nSM],
                     ec_slave[slave].SM[nSM].StartAddr, ec_slave[slave].SM[nSM].SMflags);
          }
        }
        if (ec_slave[slave].Ibits > 7)
          ec_slave[slave].Ibytes = (ec_slave[slave].Ibits + 7) / 8;
        if (ec_slave[slave].Obits > 7)
          ec_slave[slave].Obytes = (ec_slave[slave].Obits + 7) / 8;

        FMMUc = ec_slave[slave].FMMUunused;
        SMc = 0;
        BitCount = 0;
        ByteCount = 0;
        EndAddr = 0;
        FMMUsize = 0;
        FMMUdone = 0;
        /* create output mapping */
        if (ec_slave[slave].Obits)
        {
          EC_PRINT("  OUTPUT MAPPING\n");
          /* search for SM that contribute to the output mapping */
          while ((SMc < (EC_MAXSM - 1)) && (FMMUdone < ((ec_slave[slave].Obits + 7) / 8)))
          {
            EC_PRINT("    FMMU %d\n", FMMUc);
            while ((SMc < (EC_MAXSM - 1)) && (ec_slave[slave].SMtype[SMc] != 3))
              SMc++;
            EC_PRINT("      SM%d\n", SMc);
            ec_slave[slave].FMMU[FMMUc].PhysStart = ec_slave[slave].SM[SMc].StartAddr;
            SMlength = etohs(ec_slave[slave].SM[SMc].SMlength);
            ByteCount += SMlength;
            BitCount += SMlength * 8;
            EndAddr = etohs(ec_slave[slave].SM[SMc].StartAddr)+ SMlength;
            while ((BitCount < ec_slave[slave].Obits) && (SMc < (EC_MAXSM - 1))) /* more SM for output */
            {
              SMc++;
              while ((SMc < (EC_MAXSM - 1)) && (ec_slave[slave].SMtype[SMc] != 3))
                SMc++;
              /* if addresses from more SM connect use one FMMU otherwise break up in mutiple FMMU */
              if (etohs(ec_slave[slave].SM[SMc].StartAddr)> EndAddr ) break;
              EC_PRINT("      SM%d\n", SMc);
              SMlength = etohs(ec_slave[slave].SM[SMc].SMlength);
              ByteCount += SMlength;
              BitCount += SMlength * 8;
              EndAddr = etohs(ec_slave[slave].SM[SMc].StartAddr)+ SMlength;
            }

              /* bit oriented slave */
            if (!ec_slave[slave].Obytes)
            {
              ec_slave[slave].FMMU[FMMUc].LogStart = htoel(LogAddr);
              ec_slave[slave].FMMU[FMMUc].LogStartbit = BitPos;
              BitPos += ec_slave[slave].Obits - 1;
              if (BitPos > 7)
              {
                LogAddr++;
                BitPos -= 8;
              }
              FMMUsize = LogAddr - etohl(ec_slave[slave].FMMU[FMMUc].LogStart)+ 1;
              ec_slave[slave].FMMU[FMMUc].LogLength = htoes(FMMUsize);
              ec_slave[slave].FMMU[FMMUc].LogEndbit = BitPos;
              BitPos++;
              if (BitPos > 7)
              {
                LogAddr++;
                BitPos -= 8;
              }
            }
            /* byte oriented slave */
            else
            {
              if (BitPos)
              {
                LogAddr++;
                BitPos = 0;
              }
              ec_slave[slave].FMMU[FMMUc].LogStart = htoel(LogAddr);
              ec_slave[slave].FMMU[FMMUc].LogStartbit = BitPos;
              BitPos = 7;
              FMMUsize = ByteCount;
              if ((FMMUsize + FMMUdone) > ec_slave[slave].Obytes)
                FMMUsize = ec_slave[slave].Obytes - FMMUdone;
              LogAddr += FMMUsize;
              ec_slave[slave].FMMU[FMMUc].LogLength = htoes(FMMUsize);
              ec_slave[slave].FMMU[FMMUc].LogEndbit = BitPos;
              BitPos = 0;
            }
            FMMUdone += FMMUsize;
            ec_slave[slave].FMMU[FMMUc].PhysStartBit = 0;
            ec_slave[slave].FMMU[FMMUc].FMMUtype = 2;
            ec_slave[slave].FMMU[FMMUc].FMMUactive = 1;
            /* program FMMU for output */
            ec_FPWR(configadr, ECT_REG_FMMU0 + (sizeof(ec_fmmut) * FMMUc), sizeof(ec_fmmut),
                    &ec_slave[slave].FMMU[FMMUc], EC_TIMEOUTRET);
            /* add two for an output FMMU */
            ec_group[group].expectedWKC += 2;
            if (!ec_slave[slave].outputs)
            {
              ec_slave[slave].outputs = pIOmap + etohl(ec_slave[slave].FMMU[FMMUc].LogStart);
              ec_slave[slave].Ostartbit = ec_slave[slave].FMMU[FMMUc].LogStartbit;
              EC_PRINT("    slave %d Outputs %p startbit %d\n", slave, ec_slave[slave].outputs, ec_slave[slave].Ostartbit);
					}
            FMMUc++;
          }
          ec_slave[slave].FMMUunused = FMMUc;
          diff = LogAddr - oLogAddr;
          oLogAddr = LogAddr;
          if ((segmentsize + diff) > (EC_MAXLRWDATA - EC_FIRSTDCDATAGRAM))
          {
            ec_group[group].IOsegment[currentsegment] = segmentsize;
            if (currentsegment < (EC_MAXIOSEGMENTS - 1))
            {
              currentsegment++;
              segmentsize = diff;
            }
          }
          else
            segmentsize += diff;
        }
      }
    }
    if (BitPos)
    {
      LogAddr++;
      oLogAddr = LogAddr;
      BitPos = 0;
      if ((segmentsize + 1) > (EC_MAXLRWDATA - EC_FIRSTDCDATAGRAM))
      {
        ec_group[group].IOsegment[currentsegment] = segmentsize;
        if (currentsegment < (EC_MAXIOSEGMENTS - 1))
        {
          currentsegment++;
          segmentsize = 1;
        }
      }
      else
        segmentsize += 1;
    }
    ec_group[group].outputs = pIOmap;
    ec_group[group].Obytes = LogAddr;
    ec_group[group].nsegments = currentsegment + 1;
    ec_group[group].Isegment = currentsegment;
    ec_group[group].Ioffset = segmentsize;
    if (!group)
    {
      ec_slave[0].outputs = pIOmap;
      ec_slave[0].Obytes = LogAddr; /* store output bytes in master record */
    }

    /* do input mapping of slave and program FMMUs */
    for (slave = 1; slave <= ec_slavecount; slave++)
    {
      configadr = ec_slave[slave].configadr;
      FMMUc = ec_slave[slave].FMMUunused;
      if (ec_slave[slave].Obits) /* find free FMMU */
        while (ec_slave[slave].FMMU[FMMUc].LogStart)
          FMMUc++;
      SMc = 0;
      BitCount = 0;
      ByteCount = 0;
      EndAddr = 0;
      FMMUsize = 0;
      FMMUdone = 0;
      /* create input mapping */
      if (ec_slave[slave].Ibits)
      {
        EC_PRINT(" =Slave %d, INPUT MAPPING\n", slave);
        /* search for SM that contribute to the input mapping */
        while ((SMc < (EC_MAXSM - 1)) && (FMMUdone < ((ec_slave[slave].Ibits + 7) / 8)))
        {
          EC_PRINT("    FMMU %d\n", FMMUc);
          while ((SMc < (EC_MAXSM - 1)) && (ec_slave[slave].SMtype[SMc] != 4))
            SMc++;
          EC_PRINT("      SM%d\n", SMc);
          ec_slave[slave].FMMU[FMMUc].PhysStart = ec_slave[slave].SM[SMc].StartAddr;
          SMlength = etohs(ec_slave[slave].SM[SMc].SMlength);
          ByteCount += SMlength;
          BitCount += SMlength * 8;
          EndAddr = etohs(ec_slave[slave].SM[SMc].StartAddr)+ SMlength;
          while ((BitCount < ec_slave[slave].Ibits) && (SMc < (EC_MAXSM - 1))) /* more SM for input */
          {
            SMc++;
            while ((SMc < (EC_MAXSM - 1)) && (ec_slave[slave].SMtype[SMc] != 4))
              SMc++;
            /* if addresses from more SM connect use one FMMU otherwise break up in mutiple FMMU */
            if (etohs(ec_slave[slave].SM[SMc].StartAddr)> EndAddr ) break;
            EC_PRINT("      SM%d\n", SMc);
            SMlength = etohs(ec_slave[slave].SM[SMc].SMlength);
            ByteCount += SMlength;
            BitCount += SMlength * 8;
            EndAddr = etohs(ec_slave[slave].SM[SMc].StartAddr)+ SMlength;
          }

          /* bit oriented slave */
          if (!ec_slave[slave].Ibytes)
          {
            ec_slave[slave].FMMU[FMMUc].LogStart = htoel(LogAddr);
            ec_slave[slave].FMMU[FMMUc].LogStartbit = BitPos;
            BitPos += ec_slave[slave].Ibits - 1;
            if (BitPos > 7)
            {
              LogAddr++;
              BitPos -= 8;
            }
            FMMUsize = LogAddr - etohl(ec_slave[slave].FMMU[FMMUc].LogStart)+ 1;
            ec_slave[slave].FMMU[FMMUc].LogLength = htoes(FMMUsize);
            ec_slave[slave].FMMU[FMMUc].LogEndbit = BitPos;
            BitPos++;
            if (BitPos > 7)
            {
              LogAddr++;
              BitPos -= 8;
            }
          }
          /* byte oriented slave */
          else
          {
            if (BitPos)
            {
              LogAddr++;
              BitPos = 0;
            }
            ec_slave[slave].FMMU[FMMUc].LogStart = htoel(LogAddr);
            ec_slave[slave].FMMU[FMMUc].LogStartbit = BitPos;
            BitPos = 7;
            FMMUsize = ByteCount;
            if ((FMMUsize + FMMUdone) > ec_slave[slave].Ibytes)
              FMMUsize = ec_slave[slave].Ibytes - FMMUdone;
            LogAddr += FMMUsize;
            ec_slave[slave].FMMU[FMMUc].LogLength = htoes(FMMUsize);
            ec_slave[slave].FMMU[FMMUc].LogEndbit = BitPos;
            BitPos = 0;
          }
          FMMUdone += FMMUsize;
          if (ec_slave[slave].FMMU[FMMUc].LogLength)
          {
            ec_slave[slave].FMMU[FMMUc].PhysStartBit = 0;
            ec_slave[slave].FMMU[FMMUc].FMMUtype = 1;
            ec_slave[slave].FMMU[FMMUc].FMMUactive = 1;
            /* program FMMU for input */
            ec_FPWR(configadr, ECT_REG_FMMU0 + (sizeof(ec_fmmut) * FMMUc), sizeof(ec_fmmut),
                    &ec_slave[slave].FMMU[FMMUc], EC_TIMEOUTRET);
            /* add one for an input FMMU */
            ec_group[group].expectedWKC += 1;
          }
          if (!ec_slave[slave].inputs)
          {
            ec_slave[slave].inputs = pIOmap + etohl(ec_slave[slave].FMMU[FMMUc].LogStart);
            ec_slave[slave].Istartbit = ec_slave[slave].FMMU[FMMUc].LogStartbit;
            EC_PRINT("    Inputs %p startbit %d\n", ec_slave[slave].inputs, ec_slave[slave].Istartbit);
          }
          FMMUc++;
        }
        ec_slave[slave].FMMUunused = FMMUc;
        diff = LogAddr - oLogAddr;
        oLogAddr = LogAddr;
        if ((segmentsize + diff) > (EC_MAXLRWDATA - EC_FIRSTDCDATAGRAM))
        {
          ec_group[group].IOsegment[currentsegment] = segmentsize;
          if (currentsegment < (EC_MAXIOSEGMENTS - 1))
          {
            currentsegment++;
            segmentsize = diff;
          }
        }
        else
          segmentsize += diff;
      }

      ec_eeprom2pdi(slave); /* set Eeprom control to PDI */
      ec_FPWRw(configadr, ECT_REG_ALCTL, htoes(EC_STATE_SAFE_OP), EC_TIMEOUTRET); /* set safeop status */

    }
    if (BitPos)
    {
      LogAddr++;
      oLogAddr = LogAddr;
      BitPos = 0;
      if ((segmentsize + 1) > (EC_MAXLRWDATA - EC_FIRSTDCDATAGRAM))
      {
        ec_group[group].IOsegment[currentsegment] = segmentsize;
        if (currentsegment < (EC_MAXIOSEGMENTS - 1))
        {
          currentsegment++;
          segmentsize = 1;
        }
      }
      else
        segmentsize += 1;
    }
    ec_group[group].IOsegment[currentsegment] = segmentsize;
    ec_group[group].nsegments = currentsegment + 1;
    ec_group[group].inputs = pIOmap + ec_group[group].Obytes;
    ec_group[group].Ibytes = LogAddr - ec_group[group].Obytes;
    if (ec_slave[slave].blockLRW)
      ec_group[group].blockLRW++;
    ec_group[group].Ebuscurrent += ec_slave[slave].Ebuscurrent;
    if (!group)
    {
      ec_slave[0].inputs = pIOmap + ec_slave[0].Obytes;
      ec_slave[0].Ibytes = LogAddr - ec_slave[0].Obytes; /* store input bytes in master record */
    }

    EC_PRINT("IOmapSize %d\n", LogAddr - ec_group[group].logstartaddr);
    return (LogAddr - ec_group[group].logstartaddr);
  }
  return 0;
}