ethercatmain.c
Go to the documentation of this file.
00001 /*
00002  * Simple Open EtherCAT Master Library 
00003  *
00004  * File    : ethercatmain.c
00005  * Version : 1.2.5
00006  * Date    : 09-04-2011
00007  * Copyright (C) 2005-2011 Speciaal Machinefabriek Ketels v.o.f.
00008  * Copyright (C) 2005-2011 Arthur Ketels
00009  * Copyright (C) 2008-2009 TU/e Technische Universiteit Eindhoven 
00010  *
00011  * SOEM is free software; you can redistribute it and/or modify it under
00012  * the terms of the GNU General Public License version 2 as published by the Free
00013  * Software Foundation.
00014  *
00015  * SOEM is distributed in the hope that it will be useful, but WITHOUT ANY
00016  * WARRANTY; without even the implied warranty of MERCHANTABILITY or
00017  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
00018  * for more details.
00019  *
00020  * As a special exception, if other files instantiate templates or use macros
00021  * or inline functions from this file, or you compile this file and link it
00022  * with other works to produce a work based on this file, this file does not
00023  * by itself cause the resulting work to be covered by the GNU General Public
00024  * License. However the source code for this file must still be made available
00025  * in accordance with section (3) of the GNU General Public License.
00026  *
00027  * This exception does not invalidate any other reasons why a work based on
00028  * this file might be covered by the GNU General Public License.
00029  *
00030  * The EtherCAT Technology, the trade name and logo “EtherCAT” are the intellectual
00031  * property of, and protected by Beckhoff Automation GmbH. You can use SOEM for
00032  * the sole purpose of creating, using and/or selling or otherwise distributing
00033  * an EtherCAT network master provided that an EtherCAT Master License is obtained
00034  * from Beckhoff Automation GmbH.
00035  *
00036  * In case you did not receive a copy of the EtherCAT Master License along with
00037  * SOEM write to Beckhoff Automation GmbH, Eiserstraße 5, D-33415 Verl, Germany
00038  * (www.beckhoff.com).
00039  */
00040 
00053 #include <stdio.h>
00054 #include <string.h>
00055 #include <sys/time.h>
00056 #include <arpa/inet.h>
00057 #include <unistd.h>
00058 #include <youbot_driver/soem/ethercattype.h>
00059 #include <youbot_driver/soem/nicdrv.h>
00060 #include <youbot_driver/soem/ethercatbase.h>
00061 #include <youbot_driver/soem/ethercatmain.h>
00062 
00064 #define EC_LOCALDELAY   200
00065 
00067 typedef struct
00068 {
00069   uint8 pushed;
00070   uint8 pulled;
00071   uint8 idx[EC_MAXBUF];
00072   void *data[EC_MAXBUF];
00073   uint16 length[EC_MAXBUF];
00074 } ec_idxstackT;
00075 
00077 typedef struct
00078   PACKED
00079   {
00080     uint16 comm;
00081     uint16 addr;
00082     uint16 d2;
00083   } ec_eepromt;
00084 
00086   typedef struct
00087   {
00088     int16 head;
00089     int16 tail;
00090     ec_errort Error[EC_MAXELIST + 1];
00091   } ec_eringt;
00092 
00094   typedef struct
00095   {
00096     ec_mbxheadert MbxHeader;
00097     uint16 CANOpen;
00098     uint16 ErrorCode;
00099     uint8 ErrorReg;
00100     uint8 bData;
00101     uint16 w1, w2;
00102   } ec_emcyt;
00103 
00109   ec_slavet ec_slave[EC_MAXSLAVE];
00111   int ec_slavecount;
00113   ec_groupt ec_group[EC_MAXGROUP];
00114 
00116   static uint8 esibuf[EC_MAXEEPBUF];
00118   static uint32 esimap[EC_MAXEEPBITMAP];
00120   static uint16 esislave = 0;
00121   static ec_eringt ec_elist;
00122   static ec_idxstackT ec_idxstack;
00123 
00125   boolean EcatError = FALSE;
00126 
00127   uint16 ec_DCtO;
00128   static uint16 ec_DCl;
00129   int64 ec_DCtime;
00130 
00135   void ec_pusherror(const ec_errort *Ec)
00136   {
00137     ec_elist.Error[ec_elist.head] = *Ec;
00138     ec_elist.Error[ec_elist.head].Signal = TRUE;
00139     ec_elist.head++;
00140     if (ec_elist.head > EC_MAXELIST)
00141       ec_elist.head = 0;
00142     if (ec_elist.head == ec_elist.tail)
00143       ec_elist.tail++;
00144     if (ec_elist.tail > EC_MAXELIST)
00145       ec_elist.tail = 0;
00146     EcatError = TRUE;
00147   }
00148 
00154   boolean ec_poperror(ec_errort *Ec)
00155   {
00156     boolean notEmpty = (ec_elist.head != ec_elist.tail);
00157 
00158     *Ec = ec_elist.Error[ec_elist.tail];
00159     ec_elist.Error[ec_elist.tail].Signal = FALSE;
00160     if (notEmpty)
00161     {
00162       ec_elist.tail++;
00163       if (ec_elist.tail > EC_MAXELIST)
00164         ec_elist.tail = 0;
00165     }
00166     else
00167       EcatError = FALSE;
00168     return notEmpty;
00169   }
00170 
00175   boolean ec_iserror(void)
00176   {
00177     return (ec_elist.head != ec_elist.tail);
00178   }
00179 
00187   void ec_packeterror(uint16 Slave, uint16 Index, uint8 SubIdx, uint16 ErrorCode)
00188   {
00189     ec_errort Ec;
00190 
00191     gettimeofday(&Ec.Time, 0);
00192     Ec.Slave = Slave;
00193     Ec.Index = Index;
00194     Ec.SubIdx = SubIdx;
00195     EcatError = TRUE;
00196     Ec.Etype = EC_ERR_TYPE_PACKET_ERROR;
00197     Ec.ErrorCode = ErrorCode;
00198     ec_pusherror(&Ec);
00199   }
00200 
00210   static void ec_mbxemergencyerror(uint16 Slave, uint16 ErrorCode, uint16 ErrorReg, uint8 b1, uint16 w1, uint16 w2)
00211   {
00212     ec_errort Ec;
00213 
00214     gettimeofday(&Ec.Time, 0);
00215     Ec.Slave = Slave;
00216     Ec.Index = 0;
00217     Ec.SubIdx = 0;
00218     Ec.Etype = EC_ERR_TYPE_EMERGENCY;
00219     Ec.ErrorCode = ErrorCode;
00220     Ec.ErrorReg = (uint8)ErrorReg;
00221     Ec.b1 = b1;
00222     Ec.w1 = w1;
00223     Ec.w2 = w2;
00224     ec_pusherror(&Ec);
00225   }
00226 
00231   int ec_init(const char * ifname)
00232   {
00233     return ec_setupnic(ifname, FALSE);
00234   }
00235 
00241   int ec_init_redundant(const char *ifname, const char *if2name)
00242   {
00243     int rval, zbuf;
00244     ec_etherheadert *ehp;
00245 
00246     ec_setupnic(ifname, FALSE);
00247     rval = ec_setupnic(if2name, TRUE);
00248     /* prepare "dummy" BRD tx frame for redundant operation */
00249     ehp = (ec_etherheadert *)&ec_txbuf2;
00250     ehp->sa1 = htons(secMAC[0]);
00251     zbuf = 0;
00252     ec_setupdatagram(&ec_txbuf2, EC_CMD_BRD, 0, 0x0000, 0x0000, 2, &zbuf);
00253     ec_txbuflength2 = ETH_HEADERSIZE+ EC_HEADERSIZE + EC_WKCSIZE + 2;
00254 
00255     return rval;
00256   }
00257 
00260   void ec_close(void)
00261   {
00262     ec_closenic();
00263   }
00264   ;
00265 
00273   uint8 ec_siigetbyte(uint16 slave, uint16 address)
00274   {
00275     uint16 configadr, eadr;
00276     uint64 edat;
00277     uint16 mapw, mapb;
00278     int lp, cnt;
00279     uint8 retval;
00280 
00281     retval = 0xff;
00282     if (slave != esislave) /* not the same slave? */
00283     {
00284       memset(esimap, 0x00, EC_MAXEEPBITMAP); /* clear esibuf cache map */
00285       esislave = slave;
00286     }
00287     if (address < EC_MAXEEPBUF)
00288     {
00289       mapw = address >> 5;
00290       mapb = address - (mapw << 5);
00291       if (esimap[mapw] & (uint32)(1 << mapb))
00292       {
00293         /* byte is already in buffer */
00294         retval = esibuf[address];
00295       }
00296       else
00297       {
00298         /* byte is not in buffer, put it there */
00299         configadr = ec_slave[slave].configadr;
00300         ec_eeprom2master(slave); /* set eeprom control to master */
00301         eadr = address >> 1;
00302         edat = ec_readeepromFP(configadr, eadr, EC_TIMEOUTEEP);
00303         /* 8 byte response */
00304         if (ec_slave[slave].eep_8byte)
00305         {
00306           put_unaligned64(edat, &esibuf[eadr << 1]);
00307           cnt = 8;
00308         }
00309         /* 4 byte response */
00310         else
00311         {
00312           put_unaligned32(edat, &esibuf[eadr << 1]);
00313           cnt = 4;
00314         }
00315         /* find bitmap location */
00316         mapw = eadr >> 4;
00317         mapb = (eadr << 1) - (mapw << 5);
00318         for (lp = 0; lp < cnt; lp++)
00319         {
00320           /* set bitmap for each byte that is read */
00321           esimap[mapw] |= (1 << mapb);
00322           mapb++;
00323           if (mapb > 31)
00324           {
00325             mapb = 0;
00326             mapw++;
00327           }
00328         }
00329         retval = esibuf[address];
00330       }
00331     }
00332 
00333     return retval;
00334   }
00335 
00341   int16 ec_siifind(uint16 slave, uint16 cat)
00342   {
00343     int16 a;
00344     uint16 p;
00345     uint8 eectl = ec_slave[slave].eep_pdi;
00346 
00347     a = ECT_SII_START << 1;
00348     /* read first SII section category */
00349     p = ec_siigetbyte(slave, a++);
00350     p += (ec_siigetbyte(slave, a++) << 8);
00351     /* traverse SII while category is not found and not EOF */
00352     while ((p != cat) && (p != 0xffff))
00353     {
00354       /* read section length */
00355       p = ec_siigetbyte(slave, a++);
00356       p += (ec_siigetbyte(slave, a++) << 8);
00357       /* locate next section category */
00358       a += p << 1;
00359       /* read section category */
00360       p = ec_siigetbyte(slave, a++);
00361       p += (ec_siigetbyte(slave, a++) << 8);
00362     }
00363     if (p != cat)
00364       a = 0;
00365 
00366     if (eectl)
00367       ec_eeprom2pdi(slave); /* if eeprom control was previously pdi then restore */
00368 
00369     return a;
00370   }
00371 
00377   void ec_siistring(char *str, uint16 slave, uint16 Sn)
00378   {
00379     uint16 a, i, j, l, n, ba; //,p;
00380     char *ptr;
00381     uint8 eectl = ec_slave[slave].eep_pdi;
00382 
00383     ptr = str;
00384     //p = 0;
00385     a = ec_siifind(slave, ECT_SII_STRING); /* find string section */
00386     if (a > 0)
00387     {
00388       ba = a + 2; /* skip SII section header */
00389       n = ec_siigetbyte(slave, ba++); /* read number of strings in section */
00390       if (Sn <= n) /* is req string available? */
00391       {
00392         for (i = 1; i <= Sn; i++) /* walk through strings */
00393         {
00394           l = ec_siigetbyte(slave, ba++); /* length of this string */
00395           ptr = str;
00396           for (j = 1; j <= l; j++) /* copy one string */
00397           {
00398             *ptr = (char)ec_siigetbyte(slave, ba++);
00399             ptr++;
00400           }
00401         }
00402         *ptr = 0; /* add zero terminator */
00403       }
00404       else
00405       {
00406         ptr = str;
00407         *ptr = 0; /* empty string */
00408       }
00409     }
00410     if (eectl)
00411       ec_eeprom2pdi(slave); /* if eeprom control was previously pdi then restore */
00412   }
00413 
00419   uint16 ec_siiFMMU(uint16 slave, ec_eepromFMMUt* FMMU)
00420   {
00421     uint16 a;
00422     uint8 eectl = ec_slave[slave].eep_pdi;
00423 
00424     FMMU->nFMMU = 0;
00425     FMMU->FMMU0 = 0;
00426     FMMU->FMMU1 = 0;
00427     FMMU->FMMU2 = 0;
00428     FMMU->FMMU3 = 0;
00429     FMMU->Startpos = ec_siifind(slave, ECT_SII_FMMU);
00430 
00431     if (FMMU->Startpos > 0)
00432     {
00433       a = FMMU->Startpos;
00434       FMMU->nFMMU = ec_siigetbyte(slave, a++);
00435       FMMU->nFMMU += (ec_siigetbyte(slave, a++) << 8);
00436       FMMU->nFMMU *= 2;
00437       FMMU->FMMU0 = ec_siigetbyte(slave, a++);
00438       FMMU->FMMU1 = ec_siigetbyte(slave, a++);
00439       if (FMMU->nFMMU > 2)
00440       {
00441         FMMU->FMMU2 = ec_siigetbyte(slave, a++);
00442         FMMU->FMMU3 = ec_siigetbyte(slave, a++);
00443       }
00444     }
00445     if (eectl)
00446       ec_eeprom2pdi(slave); /* if eeprom control was previously pdi then restore */
00447     return FMMU->nFMMU;
00448   }
00449 
00455   uint16 ec_siiSM(uint16 slave, ec_eepromSMt* SM)
00456   {
00457     uint16 a, w; //,l;
00458     uint8 eectl = ec_slave[slave].eep_pdi;
00459 
00460     SM->nSM = 0;
00461     //l = 0;
00462     SM->Startpos = ec_siifind(slave, ECT_SII_SM);
00463     if (SM->Startpos > 0)
00464     {
00465       a = SM->Startpos;
00466       w = ec_siigetbyte(slave, a++);
00467       w += (ec_siigetbyte(slave, a++) << 8);
00468       SM->nSM = (w / 4);
00469       SM->PhStart = ec_siigetbyte(slave, a++);
00470       SM->PhStart += (ec_siigetbyte(slave, a++) << 8);
00471       SM->Plength = ec_siigetbyte(slave, a++);
00472       SM->Plength += (ec_siigetbyte(slave, a++) << 8);
00473       SM->Creg = ec_siigetbyte(slave, a++);
00474       SM->Sreg = ec_siigetbyte(slave, a++);
00475       SM->Activate = ec_siigetbyte(slave, a++);
00476       SM->PDIctrl = ec_siigetbyte(slave, a++);
00477     }
00478     if (eectl)
00479       ec_eeprom2pdi(slave); /* if eeprom control was previously pdi then restore */
00480     return SM->nSM;
00481   }
00482 
00489   uint16 ec_siiSMnext(uint16 slave, ec_eepromSMt* SM, uint16 n)
00490   {
00491     uint16 a;
00492     uint16 retVal = 0;
00493     uint8 eectl = ec_slave[slave].eep_pdi;
00494 
00495     if (n < SM->nSM)
00496     {
00497       a = SM->Startpos + 2 + (n * 8);
00498       SM->PhStart = ec_siigetbyte(slave, a++);
00499       SM->PhStart += (ec_siigetbyte(slave, a++) << 8);
00500       SM->Plength = ec_siigetbyte(slave, a++);
00501       SM->Plength += (ec_siigetbyte(slave, a++) << 8);
00502       SM->Creg = ec_siigetbyte(slave, a++);
00503       SM->Sreg = ec_siigetbyte(slave, a++);
00504       SM->Activate = ec_siigetbyte(slave, a++);
00505       SM->PDIctrl = ec_siigetbyte(slave, a++);
00506       retVal = 1;
00507     }
00508     if (eectl)
00509       ec_eeprom2pdi(slave); /* if eeprom control was previously pdi then restore */
00510     return retVal;
00511   }
00512 
00519   int ec_siiPDO(uint16 slave, ec_eepromPDOt* PDO, uint8 t)
00520   {
00521     uint16 a, w, c, e, er, Size;
00522     uint8 eectl = ec_slave[slave].eep_pdi;
00523 
00524     Size = 0;
00525     PDO->nPDO = 0;
00526     PDO->Length = 0;
00527     PDO->Index[1] = 0;
00528     for (c = 0; c < EC_MAXSM; c++)
00529       PDO->SMbitsize[c] = 0;
00530     if (t > 1)
00531       t = 1;
00532     PDO->Startpos = ec_siifind(slave, ECT_SII_PDO + t);
00533     if (PDO->Startpos > 0)
00534     {
00535       a = PDO->Startpos;
00536       w = ec_siigetbyte(slave, a++);
00537       w += (ec_siigetbyte(slave, a++) << 8);
00538       PDO->Length = w;
00539       c = 1;
00540       /* traverse through all PDOs */
00541       do
00542       {
00543         PDO->nPDO++;
00544         PDO->Index[PDO->nPDO] = ec_siigetbyte(slave, a++);
00545         PDO->Index[PDO->nPDO] += (ec_siigetbyte(slave, a++) << 8);
00546         PDO->BitSize[PDO->nPDO] = 0;
00547         c++;
00548         e = ec_siigetbyte(slave, a++);
00549         PDO->SyncM[PDO->nPDO] = ec_siigetbyte(slave, a++);
00550         a += 4;
00551         c += 2;
00552         if (PDO->SyncM[PDO->nPDO] < EC_MAXSM) /* active and in range SM? */
00553         {
00554           /* read all entries defined in PDO */
00555           for (er = 1; er <= e; er++)
00556           {
00557             c += 4;
00558             a += 5;
00559             PDO->BitSize[PDO->nPDO] += ec_siigetbyte(slave, a++);
00560             a += 2;
00561           }
00562           PDO->SMbitsize[PDO->SyncM[PDO->nPDO]] += PDO->BitSize[PDO->nPDO];
00563           Size += PDO->BitSize[PDO->nPDO];
00564           c++;
00565         }
00566         else /* PDO deactivated because SM is 0xff or > EC_MAXSM */
00567         {
00568           c += 4 * e;
00569           a += 8 * e;
00570           c++;
00571         }
00572         if (PDO->nPDO >= (EC_MAXEEPDO - 1))
00573           c = PDO->Length; /* limit number of PDO entries in buffer */
00574       } while (c < PDO->Length);
00575     }
00576     if (eectl)
00577       ec_eeprom2pdi(slave); /* if eeprom control was previously pdi then restore */
00578 
00579     return (Size);
00580   }
00581 
00585   int ec_readstate(void)
00586   {
00587     uint16 slave, configadr, lowest, rval;
00588     ec_alstatust slstat;
00589 
00590     lowest = 0xff;
00591     ec_slave[0].ALstatuscode = 0;
00592     for (slave = 1; slave <= ec_slavecount; slave++)
00593     {
00594       configadr = ec_slave[slave].configadr;
00595       slstat.alstatus = 0;
00596       slstat.alstatuscode = 0;
00597       ec_FPRD(configadr, ECT_REG_ALSTAT, sizeof(slstat), &slstat, EC_TIMEOUTRET);
00598       rval = etohs(slstat.alstatus);
00599       ec_slave[slave].ALstatuscode = etohs(slstat.alstatuscode);
00600       if (rval < lowest)
00601         lowest = rval;
00602       ec_slave[slave].state = rval;
00603       ec_slave[0].ALstatuscode |= ec_slave[slave].ALstatuscode;
00604     }
00605     ec_slave[0].state = lowest;
00606 
00607     return lowest;
00608   }
00609 
00615   int ec_writestate(uint16 slave)
00616   {
00617     uint16 configadr, slstate;
00618 
00619     if (slave == 0)
00620     {
00621       slstate = htoes(ec_slave[slave].state);
00622       ec_BWR(0, ECT_REG_ALCTL, sizeof(slstate), &slstate, EC_TIMEOUTRET); /* write slave status */
00623     }
00624     else
00625     {
00626       configadr = ec_slave[slave].configadr;
00627       ec_FPWRw(configadr, ECT_REG_ALCTL, htoes(ec_slave[slave].state), EC_TIMEOUTRET); /* write slave status */
00628     }
00629     return 0;
00630   }
00631 
00639   uint16 ec_statecheck(uint16 slave, uint16 reqstate, int timeout)
00640   {
00641     uint16 configadr, state, rval;
00642     struct timeval tv1, tv2, tve;
00643     ec_alstatust slstat;
00644 
00645     if (slave > ec_slavecount)
00646       return 0;
00647     gettimeofday(&tv1, 0);
00648     tv2.tv_sec = 0;
00649     tv2.tv_usec = timeout;
00650     timeradd(&tv1, &tv2, &tve);
00651     configadr = ec_slave[slave].configadr;
00652     do
00653     {
00654       if (slave < 1)
00655       {
00656         rval = 0;
00657         ec_BRD(0, ECT_REG_ALSTAT, sizeof(rval), &rval, EC_TIMEOUTRET);
00658         rval = etohs(rval);
00659       }
00660       else
00661       {
00662         slstat.alstatus = 0;
00663         slstat.alstatuscode = 0;
00664         ec_FPRD(configadr, ECT_REG_ALSTAT, sizeof(slstat), &slstat, EC_TIMEOUTRET);
00665         rval = etohs(slstat.alstatus);
00666         ec_slave[slave].ALstatuscode = etohs(slstat.alstatuscode);
00667       }
00668       state = rval & 0x000f; /* read slave status */
00669       if (state != reqstate)
00670         usleep(1000);
00671       gettimeofday(&tv2, 0);
00672     } while ((state != reqstate) && timercmp(&tv2, &tve, <));
00673     ec_slave[slave].state = rval;
00674 
00675     return state;
00676   }
00677 
00683   uint8 ec_nextmbxcnt(uint8 cnt)
00684   {
00685     cnt++;
00686     if (cnt > 7)
00687       cnt = 1; /* wrap around to 1, not 0 */
00688     return cnt;
00689   }
00690 
00694   void ec_clearmbx(ec_mbxbuft *Mbx)
00695   {
00696     memset(*Mbx, 0x00, EC_MAXMBX);
00697   }
00698 
00704   int ec_mbxempty(uint16 slave, int timeout)
00705   {
00706     uint16 configadr;
00707     uint8 SMstat;
00708     int wkc;
00709     struct timeval tv1, tv2, tve;
00710 
00711     gettimeofday(&tv1, 0);
00712     tv2.tv_sec = 0;
00713     tv2.tv_usec = timeout;
00714     timeradd(&tv1, &tv2, &tve);
00715     configadr = ec_slave[slave].configadr;
00716     do
00717     {
00718       wkc = ec_FPRD(configadr, ECT_REG_SM0STAT, sizeof(SMstat), &SMstat, EC_TIMEOUTRET);
00719       SMstat = etohs(SMstat);
00720       if (((SMstat & 0x08) != 0) && (timeout > EC_LOCALDELAY))
00721         usleep(EC_LOCALDELAY);
00722       gettimeofday(&tv2, 0);
00723     } while (((wkc <= 0) || ((SMstat & 0x08) != 0)) && timercmp(&tv2, &tve, <));
00724     if ((wkc > 0) && ((SMstat & 0x08) == 0))
00725       return 1;
00726     return 0;
00727   }
00728 
00735   int ec_mbxsend(uint16 slave, ec_mbxbuft *mbx, int timeout)
00736   {
00737     uint16 mbxwo, mbxl, configadr;
00738     int wkc;
00739 
00740     wkc = 0;
00741     configadr = ec_slave[slave].configadr;
00742     mbxl = ec_slave[slave].mbx_l;
00743     if (mbxl > 0)
00744     {
00745       if (ec_mbxempty(slave, timeout))
00746       {
00747         mbxwo = ec_slave[slave].mbx_wo;
00748         /* write slave in mailbox */
00749         wkc = ec_FPWR(configadr, mbxwo, mbxl, mbx, EC_TIMEOUTRET);
00750       }
00751       else
00752         wkc = 0;
00753     }
00754 
00755     return wkc;
00756   }
00757 
00765   int ec_mbxreceive(uint16 slave, ec_mbxbuft *mbx, int timeout)
00766   {
00767     uint16 mbxro, mbxl, configadr;
00768     int wkc = 0;
00769     int wkc2;
00770     uint16 SMstat;
00771     uint8 SMcontr;
00772     ec_mbxheadert *mbxh;
00773     ec_emcyt *EMp;
00774     struct timeval mtv1, mtv2, mtve;
00775 
00776     configadr = ec_slave[slave].configadr;
00777     mbxl = ec_slave[slave].mbx_rl;
00778     if (mbxl > 0)
00779     {
00780       gettimeofday(&mtv1, 0);
00781       mtv2.tv_sec = 0;
00782       mtv2.tv_usec = timeout;
00783       timeradd(&mtv1, &mtv2, &mtve);
00784       wkc = 0;
00785       do /* wait for read mailbox available */
00786       {
00787         wkc = ec_FPRD(configadr, ECT_REG_SM1STAT, sizeof(SMstat), &SMstat, EC_TIMEOUTRET);
00788         SMstat = etohs(SMstat);
00789         if (((SMstat & 0x08) == 0) && (timeout > EC_LOCALDELAY))
00790           usleep(EC_LOCALDELAY);
00791         gettimeofday(&mtv2, 0);
00792       } while (((wkc <= 0) || ((SMstat & 0x08) == 0)) && timercmp(&mtv2, &mtve, <));
00793 
00794       if ((wkc > 0) && ((SMstat & 0x08) > 0)) /* read mailbox available ? */
00795       {
00796         mbxro = ec_slave[slave].mbx_ro;
00797         mbxh = (ec_mbxheadert *)mbx;
00798         do
00799         {
00800           wkc = ec_FPRD(configadr, mbxro, mbxl, mbx, EC_TIMEOUTRET); /* get mailbox */
00801           /* TODO : check for mailbox error response */
00802           if ((wkc > 0) && ((mbxh->mbxtype & 0x0f) == 0x03)) /* CoE response? */
00803           {
00804             EMp = (ec_emcyt *)mbx;
00805             if ((etohs(EMp->CANOpen) >> 12) == 0x01) /* Emergency request? */
00806             {
00807               ec_mbxemergencyerror(slave, etohs(EMp->ErrorCode), EMp->ErrorReg, EMp->bData, etohs(EMp->w1),
00808                                    etohs(EMp->w2));
00809               wkc = 0; /* prevent emergency to cascade up, it is already handled. */
00810             }
00811           }
00812           else
00813           {
00814             if (wkc <= 0) /* read mailbox lost */
00815             {
00816               SMstat ^= 0x0200; /* toggle repeat request */
00817               SMstat = htoes(SMstat);
00818               wkc2 = ec_FPWR(configadr, ECT_REG_SM1STAT, sizeof(SMstat), &SMstat, EC_TIMEOUTRET);
00819               SMstat = etohs(SMstat);
00820               do /* wait for toggle ack */
00821               {
00822                 wkc2 = ec_FPRD(configadr, ECT_REG_SM1CONTR, sizeof(SMcontr), &SMcontr, EC_TIMEOUTRET);
00823                 gettimeofday(&mtv2, 0);
00824               } while (((wkc2 <= 0) || ((SMcontr & 0x02) != (HI_BYTE(SMstat) & 0x02))) && timercmp(&mtv2, &mtve, <));
00825               do /* wait for read mailbox available */
00826               {
00827                 wkc2 = ec_FPRD(configadr, ECT_REG_SM1STAT, sizeof(SMstat), &SMstat, EC_TIMEOUTRET);
00828                 SMstat = etohs(SMstat);
00829                 if (((SMstat & 0x08) == 0) && (timeout > EC_LOCALDELAY))
00830                 {
00831                   usleep(EC_LOCALDELAY);
00832                 }
00833                 gettimeofday(&mtv2, 0);
00834               } while (((wkc2 <= 0) || ((SMstat & 0x08) == 0)) && timercmp(&mtv2, &mtve, <));
00835             }
00836           }
00837         } while ((wkc <= 0) && timercmp(&mtv2, &mtve, <)); /* if WKC<=0 repeat */
00838       }
00839       else /* no read mailbox available */
00840       wkc = 0;
00841     }
00842 
00843     return wkc;
00844   }
00845 
00850   void ec_esidump(uint16 slave, uint8 *esibuf, uint8 test)
00851   {
00852     int address, incr;
00853     uint16 configadr;
00854     uint64 *p64;
00855     uint16 *p16;
00856     uint64 edat;
00857     uint8 eectl = ec_slave[slave].eep_pdi;
00858 
00859     ec_eeprom2master(slave); /* set eeprom control to master */
00860     configadr = ec_slave[slave].configadr;
00861     address = ECT_SII_START;
00862     p16 = (uint16*)esibuf;
00863     if (ec_slave[slave].eep_8byte)
00864       incr = 4;
00865     else
00866       incr = 2;
00867     do
00868     {
00869       edat = ec_readeepromFP(configadr, address, EC_TIMEOUTEEP);
00870       p64 = (uint64*)p16;
00871       *p64 = edat;
00872       p16 += incr;
00873       address += incr;
00874     } while ((address <= (EC_MAXEEPBUF >> 1)) && ((uint32)edat != 0xffffffff));
00875 
00876     if (eectl)
00877       ec_eeprom2pdi(slave); /* if eeprom control was previously pdi then restore */
00878   }
00879 
00886   uint32 ec_readeeprom(uint16 slave, uint16 eeproma, int timeout)
00887   {
00888     uint16 configadr;
00889 
00890     ec_eeprom2master(slave); /* set eeprom control to master */
00891     configadr = ec_slave[slave].configadr;
00892     return (ec_readeepromFP(configadr, eeproma, timeout));
00893   }
00894 
00902   int ec_writeeeprom(uint16 slave, uint16 eeproma, uint16 data, int timeout)
00903   {
00904     uint16 configadr;
00905 
00906     ec_eeprom2master(slave); /* set eeprom control to master */
00907     configadr = ec_slave[slave].configadr;
00908     return (ec_writeeepromFP(configadr, eeproma, data, timeout));
00909   }
00910 
00915   int ec_eeprom2master(uint16 slave)
00916   {
00917     int wkc = 1, cnt = 0;
00918     uint16 configadr;
00919     uint8 eepctl;
00920 
00921     if (ec_slave[slave].eep_pdi)
00922     {
00923       configadr = ec_slave[slave].configadr;
00924       eepctl = 2;
00925       do
00926       {
00927         wkc = ec_FPWR(configadr, ECT_REG_EEPCFG, sizeof(eepctl), &eepctl, EC_TIMEOUTRET); /* force Eeprom from PDI */
00928       } while ((wkc <= 0) && (cnt++ < EC_DEFAULTRETRIES));
00929       eepctl = 0;
00930       cnt = 0;
00931       do
00932       {
00933         wkc = ec_FPWR(configadr, ECT_REG_EEPCFG, sizeof(eepctl), &eepctl, EC_TIMEOUTRET); /* set Eeprom to master */
00934       } while ((wkc <= 0) && (cnt++ < EC_DEFAULTRETRIES));
00935       ec_slave[slave].eep_pdi = 0;
00936     }
00937 
00938     return wkc;
00939   }
00940 
00945   int ec_eeprom2pdi(uint16 slave)
00946   {
00947     int wkc = 1, cnt = 0;
00948     uint16 configadr;
00949     uint8 eepctl;
00950 
00951     if (!ec_slave[slave].eep_pdi)
00952     {
00953       configadr = ec_slave[slave].configadr;
00954       eepctl = 1;
00955       do
00956       {
00957         wkc = ec_FPWR(configadr, ECT_REG_EEPCFG, sizeof(eepctl), &eepctl, EC_TIMEOUTRET); /* set Eeprom to PDI */
00958       } while ((wkc <= 0) && (cnt++ < EC_DEFAULTRETRIES));
00959       ec_slave[slave].eep_pdi = 1;
00960     }
00961 
00962     return wkc;
00963   }
00964 
00965   uint16 ec_eeprom_waitnotbusyAP(uint16 aiadr, uint16 *estat, int timeout)
00966   {
00967     int wkc, cnt = 0, retval = 0;
00968     struct timeval tv1, tv2, tve;
00969 
00970     gettimeofday(&tv1, 0);
00971     tv2.tv_sec = 0;
00972     tv2.tv_usec = timeout;
00973     timeradd(&tv1, &tv2, &tve);
00974     do
00975     {
00976       if (cnt++)
00977         usleep(EC_LOCALDELAY);
00978       wkc = ec_APRD(aiadr, ECT_REG_EEPSTAT, sizeof(*estat), estat, EC_TIMEOUTRET);
00979       *estat = etohs(*estat);
00980       gettimeofday(&tv2, 0);
00981     } while (((wkc <= 0) || ((*estat & EC_ESTAT_BUSY) > 0)) && (timercmp(&tv2, &tve, <))); /* wait for eeprom ready */
00982     if ((*estat & EC_ESTAT_BUSY) == 0)
00983       retval = 1;
00984     return retval;
00985   }
00986 
00993   uint64 ec_readeepromAP(uint16 aiadr, uint16 eeproma, int timeout)
00994   {
00995     uint16 estat;
00996     uint32 edat32;
00997     uint64 edat64;
00998     ec_eepromt ed;
00999     int wkc, cnt, nackcnt = 0;
01000     struct timeval tv1, tv2, tve;
01001 
01002     gettimeofday(&tv1, 0);
01003     tv2.tv_sec = 0;
01004     tv2.tv_usec = timeout;
01005     timeradd(&tv1, &tv2, &tve);
01006     edat64 = 0;
01007     edat32 = 0;
01008     if (ec_eeprom_waitnotbusyAP(aiadr, &estat, timeout))
01009     {
01010       if (estat & EC_ESTAT_EMASK) /* error bits are set */
01011       {
01012         estat = htoes(EC_ECMD_NOP); /* clear error bits */
01013         wkc = ec_APWR(aiadr, ECT_REG_EEPCTL, sizeof(estat), &estat, EC_TIMEOUTRET);
01014       }
01015 
01016       do
01017       {
01018         ed.comm = htoes(EC_ECMD_READ);
01019         ed.addr = htoes(eeproma);
01020         ed.d2 = 0x0000;
01021         cnt = 0;
01022         do
01023           wkc = ec_APWR(aiadr, ECT_REG_EEPCTL, sizeof(ed), &ed, EC_TIMEOUTRET);
01024         while ((wkc <= 0) && (cnt++ < EC_DEFAULTRETRIES));
01025         if (wkc)
01026         {
01027           usleep(EC_LOCALDELAY);
01028           estat = 0x0000;
01029           if (ec_eeprom_waitnotbusyAP(aiadr, &estat, timeout))
01030           {
01031             if (estat & EC_ESTAT_NACK)
01032             {
01033               nackcnt++;
01034               usleep(EC_LOCALDELAY * 5);
01035             }
01036             else
01037             {
01038               nackcnt = 0;
01039               if (estat & EC_ESTAT_R64)
01040               {
01041                 cnt = 0;
01042                 do
01043                   wkc = ec_APRD(aiadr, ECT_REG_EEPDAT, sizeof(edat64), &edat64, EC_TIMEOUTRET);
01044                 while ((wkc <= 0) && (cnt++ < EC_DEFAULTRETRIES));
01045               }
01046               else
01047               {
01048                 cnt = 0;
01049                 do
01050                   wkc = ec_APRD(aiadr, ECT_REG_EEPDAT, sizeof(edat32), &edat32, EC_TIMEOUTRET);
01051                 while ((wkc <= 0) && (cnt++ < EC_DEFAULTRETRIES));
01052                 edat64 = (uint64)edat32;
01053               }
01054             }
01055           }
01056         }
01057       } while ((nackcnt > 0) && (nackcnt < 3));
01058     }
01059     return edat64;
01060   }
01061 
01069   int ec_writeeepromAP(uint16 aiadr, uint16 eeproma, uint16 data, int timeout)
01070   {
01071     uint16 estat;
01072     ec_eepromt ed;
01073     int wkc, rval = 0, cnt = 0, nackcnt = 0;
01074     struct timeval tv1, tv2, tve;
01075 
01076     gettimeofday(&tv1, 0);
01077     tv2.tv_sec = 0;
01078     tv2.tv_usec = timeout;
01079     timeradd(&tv1, &tv2, &tve);
01080     if (ec_eeprom_waitnotbusyAP(aiadr, &estat, timeout))
01081     {
01082       if (estat & EC_ESTAT_EMASK) /* error bits are set */
01083       {
01084         estat = htoes(EC_ECMD_NOP); /* clear error bits */
01085         wkc = ec_APWR(aiadr, ECT_REG_EEPCTL, sizeof(estat), &estat, EC_TIMEOUTRET);
01086       }
01087       do
01088       {
01089         cnt = 0;
01090         do
01091           wkc = ec_APWR(aiadr, ECT_REG_EEPDAT, sizeof(data), &data, EC_TIMEOUTRET);
01092         while ((wkc <= 0) && (cnt++ < EC_DEFAULTRETRIES));
01093 
01094         ed.comm = EC_ECMD_WRITE;
01095         ed.addr = eeproma;
01096         ed.d2 = 0x0000;
01097         cnt = 0;
01098         do
01099           wkc = ec_APWR(aiadr, ECT_REG_EEPCTL, sizeof(ed), &ed, EC_TIMEOUTRET);
01100         while ((wkc <= 0) && (cnt++ < EC_DEFAULTRETRIES));
01101         if (wkc)
01102         {
01103           usleep(EC_LOCALDELAY * 2);
01104           estat = 0x0000;
01105           if (ec_eeprom_waitnotbusyAP(aiadr, &estat, timeout))
01106           {
01107             if (estat & EC_ESTAT_NACK)
01108             {
01109               nackcnt++;
01110               usleep(EC_LOCALDELAY * 5);
01111             }
01112             else
01113             {
01114               nackcnt = 0;
01115               rval = 1;
01116             }
01117           }
01118         }
01119 
01120       } while ((nackcnt > 0) && (nackcnt < 3));
01121     }
01122     return rval;
01123   }
01124 
01125   uint16 ec_eeprom_waitnotbusyFP(uint16 configadr, uint16 *estat, int timeout)
01126   {
01127     int wkc, cnt = 0, retval = 0;
01128     struct timeval tv1, tv2, tve;
01129 
01130     gettimeofday(&tv1, 0);
01131     tv2.tv_sec = 0;
01132     tv2.tv_usec = timeout;
01133     timeradd(&tv1, &tv2, &tve);
01134     do
01135     {
01136       if (cnt++)
01137         usleep(EC_LOCALDELAY);
01138       wkc = ec_FPRD(configadr, ECT_REG_EEPSTAT, sizeof(*estat), estat, EC_TIMEOUTRET);
01139       *estat = etohs(*estat);
01140       gettimeofday(&tv2, 0);
01141     } while (((wkc <= 0) || ((*estat & EC_ESTAT_BUSY) > 0)) && (timercmp(&tv2, &tve, <))); /* wait for eeprom ready */
01142     if ((*estat & EC_ESTAT_BUSY) == 0)
01143       retval = 1;
01144     return retval;
01145   }
01146 
01153   uint64 ec_readeepromFP(uint16 configadr, uint16 eeproma, int timeout)
01154   {
01155     uint16 estat;
01156     uint32 edat32;
01157     uint64 edat64;
01158     ec_eepromt ed;
01159     int wkc, cnt, nackcnt = 0;
01160     struct timeval tv1, tv2, tve;
01161 
01162     gettimeofday(&tv1, 0);
01163     tv2.tv_sec = 0;
01164     tv2.tv_usec = timeout;
01165     timeradd(&tv1, &tv2, &tve);
01166     edat64 = 0;
01167     edat32 = 0;
01168     if (ec_eeprom_waitnotbusyFP(configadr, &estat, timeout))
01169     {
01170       if (estat & EC_ESTAT_EMASK) /* error bits are set */
01171       {
01172         estat = htoes(EC_ECMD_NOP); /* clear error bits */
01173         wkc = ec_FPWR(configadr, ECT_REG_EEPCTL, sizeof(estat), &estat, EC_TIMEOUTRET);
01174       }
01175 
01176       do
01177       {
01178         ed.comm = htoes(EC_ECMD_READ);
01179         ed.addr = htoes(eeproma);
01180         ed.d2 = 0x0000;
01181         cnt = 0;
01182         do
01183           wkc = ec_FPWR(configadr, ECT_REG_EEPCTL, sizeof(ed), &ed, EC_TIMEOUTRET);
01184         while ((wkc <= 0) && (cnt++ < EC_DEFAULTRETRIES));
01185         if (wkc)
01186         {
01187           usleep(EC_LOCALDELAY);
01188           estat = 0x0000;
01189           if (ec_eeprom_waitnotbusyFP(configadr, &estat, timeout))
01190           {
01191             if (estat & EC_ESTAT_NACK)
01192             {
01193               nackcnt++;
01194               usleep(EC_LOCALDELAY * 5);
01195             }
01196             else
01197             {
01198               nackcnt = 0;
01199               if (estat & EC_ESTAT_R64)
01200               {
01201                 cnt = 0;
01202                 do
01203                   wkc = ec_FPRD(configadr, ECT_REG_EEPDAT, sizeof(edat64), &edat64, EC_TIMEOUTRET);
01204                 while ((wkc <= 0) && (cnt++ < EC_DEFAULTRETRIES));
01205               }
01206               else
01207               {
01208                 cnt = 0;
01209                 do
01210                   wkc = ec_FPRD(configadr, ECT_REG_EEPDAT, sizeof(edat32), &edat32, EC_TIMEOUTRET);
01211                 while ((wkc <= 0) && (cnt++ < EC_DEFAULTRETRIES));
01212                 edat64 = (uint64)edat32;
01213               }
01214             }
01215           }
01216         }
01217       } while ((nackcnt > 0) && (nackcnt < 3));
01218     }
01219     return edat64;
01220   }
01221 
01229   int ec_writeeepromFP(uint16 configadr, uint16 eeproma, uint16 data, int timeout)
01230   {
01231     uint16 estat;
01232     ec_eepromt ed;
01233     int wkc, rval = 0, cnt = 0, nackcnt = 0;
01234     struct timeval tv1, tv2, tve;
01235 
01236     gettimeofday(&tv1, 0);
01237     tv2.tv_sec = 0;
01238     tv2.tv_usec = timeout;
01239     timeradd(&tv1, &tv2, &tve);
01240     if (ec_eeprom_waitnotbusyFP(configadr, &estat, timeout))
01241     {
01242       if (estat & EC_ESTAT_EMASK) /* error bits are set */
01243       {
01244         estat = htoes(EC_ECMD_NOP); /* clear error bits */
01245         wkc = ec_FPWR(configadr, ECT_REG_EEPCTL, sizeof(estat), &estat, EC_TIMEOUTRET);
01246       }
01247       do
01248       {
01249         cnt = 0;
01250         do
01251           wkc = ec_FPWR(configadr, ECT_REG_EEPDAT, sizeof(data), &data, EC_TIMEOUTRET);
01252         while ((wkc <= 0) && (cnt++ < EC_DEFAULTRETRIES));
01253         ed.comm = EC_ECMD_WRITE;
01254         ed.addr = eeproma;
01255         ed.d2 = 0x0000;
01256         cnt = 0;
01257         do
01258           wkc = ec_FPWR(configadr, ECT_REG_EEPCTL, sizeof(ed), &ed, EC_TIMEOUTRET);
01259         while ((wkc <= 0) && (cnt++ < EC_DEFAULTRETRIES));
01260         if (wkc)
01261         {
01262           usleep(EC_LOCALDELAY * 2);
01263           estat = 0x0000;
01264           if (ec_eeprom_waitnotbusyFP(configadr, &estat, timeout))
01265           {
01266             if (estat & EC_ESTAT_NACK)
01267             {
01268               nackcnt++;
01269               usleep(EC_LOCALDELAY * 5);
01270             }
01271             else
01272             {
01273               nackcnt = 0;
01274               rval = 1;
01275             }
01276           }
01277         }
01278       } while ((nackcnt > 0) && (nackcnt < 3));
01279     }
01280     return rval;
01281   }
01282 
01288   void ec_readeeprom1(uint16 slave, uint16 eeproma)
01289   {
01290     uint16 configadr, estat;
01291     ec_eepromt ed;
01292     int wkc, cnt = 0;
01293 
01294     ec_eeprom2master(slave); /* set eeprom control to master */
01295     configadr = ec_slave[slave].configadr;
01296     if (ec_eeprom_waitnotbusyFP(configadr, &estat, EC_TIMEOUTEEP))
01297     {
01298       if (estat & EC_ESTAT_EMASK) /* error bits are set */
01299       {
01300         estat = htoes(EC_ECMD_NOP); /* clear error bits */
01301         wkc = ec_FPWR(configadr, ECT_REG_EEPCTL, sizeof(estat), &estat, EC_TIMEOUTRET);
01302       }
01303       ed.comm = htoes(EC_ECMD_READ);
01304       ed.addr = htoes(eeproma);
01305       ed.d2 = 0x0000;
01306       do
01307         wkc = ec_FPWR(configadr, ECT_REG_EEPCTL, sizeof(ed), &ed, EC_TIMEOUTRET);
01308       while ((wkc <= 0) && (cnt++ < EC_DEFAULTRETRIES));
01309     }
01310   }
01311 
01318   uint32 ec_readeeprom2(uint16 slave, int timeout)
01319   {
01320     uint16 estat, configadr;
01321     uint32 edat;
01322     int wkc, cnt = 0;
01323     struct timeval tv1, tv2, tve;
01324 
01325     gettimeofday(&tv1, 0);
01326     tv2.tv_sec = 0;
01327     tv2.tv_usec = timeout;
01328     timeradd(&tv1, &tv2, &tve);
01329     configadr = ec_slave[slave].configadr;
01330     edat = 0;
01331     estat = 0x0000;
01332     if (ec_eeprom_waitnotbusyFP(configadr, &estat, timeout))
01333     {
01334       do
01335         wkc = ec_FPRD(configadr, ECT_REG_EEPDAT, sizeof(edat), &edat, EC_TIMEOUTRET);
01336       while ((wkc <= 0) && (cnt++ < EC_DEFAULTRETRIES));
01337     }
01338 
01339     return edat;
01340   }
01341 
01347   static void ec_pushindex(uint8 idx, void *data, uint16 length)
01348   {
01349     if (ec_idxstack.pushed < EC_MAXBUF)
01350     {
01351       ec_idxstack.idx[ec_idxstack.pushed] = idx;
01352       ec_idxstack.data[ec_idxstack.pushed] = data;
01353       ec_idxstack.length[ec_idxstack.pushed] = length;
01354       ec_idxstack.pushed++;
01355     }
01356   }
01357 
01361   static int ec_pullindex(void)
01362   {
01363     int rval = -1;
01364     if (ec_idxstack.pulled < ec_idxstack.pushed)
01365     {
01366       rval = ec_idxstack.pulled;
01367       ec_idxstack.pulled++;
01368     }
01369 
01370     return rval;
01371   }
01372 
01383   int ec_send_processdata_group(uint8 group)
01384   {
01385     uint32 LogAdr;
01386     uint16 w1, w2;
01387     int length, sublength;
01388     uint8 idx;
01389     int wkc;
01390     void* data;
01391     boolean first = FALSE;
01392     uint16 currentsegment = 0;
01393 
01394     wkc = 0;
01395     if (ec_group[group].hasdc)
01396       first = TRUE;
01397     length = ec_group[group].Obytes + ec_group[group].Ibytes;
01398     LogAdr = ec_group[group].logstartaddr;
01399     if (length)
01400     {
01401       if (!group)
01402       {
01403         ec_idxstack.pushed = 0;
01404         ec_idxstack.pulled = 0;
01405       }
01406       wkc = 1;
01407       /* LRW blocked by one or more slaves ? */
01408       if (ec_group[group].blockLRW)
01409       {
01410         /* if inputs available generate LRD */
01411         if (ec_group[group].Ibytes)
01412         {
01413           currentsegment = ec_group[group].Isegment;
01414           data = ec_group[group].inputs;
01415           length = ec_group[group].Ibytes;
01416           LogAdr += ec_group[group].Obytes;
01417           /* segment transfer if needed */
01418           do
01419           {
01420             if (currentsegment == ec_group[group].Isegment)
01421               sublength = ec_group[group].IOsegment[currentsegment++] - ec_group[group].Ioffset;
01422             else
01423               sublength = ec_group[group].IOsegment[currentsegment++];
01424             /* get new index */
01425             idx = ec_getindex();
01426             w1 = LO_WORD(LogAdr);
01427             w2 = HI_WORD(LogAdr);
01428             ec_setupdatagram(&ec_txbuf[idx], EC_CMD_LRD, idx, w1, w2, sublength, data);
01429             /* send frame */
01430             ec_outframe_red(idx);
01431             /* push index and data pointer on stack */
01432             ec_pushindex(idx, data, sublength);
01433             length -= sublength;
01434             LogAdr += sublength;
01435             data += sublength;
01436           } while (length && (currentsegment < ec_group[group].nsegments));
01437         }
01438         /* if outputs available generate LWR */
01439         if (ec_group[group].Obytes)
01440         {
01441           data = ec_group[group].outputs;
01442           length = ec_group[group].Obytes;
01443           LogAdr = ec_group[group].logstartaddr;
01444           currentsegment = 0;
01445           /* segment transfer if needed */
01446           do
01447           {
01448             sublength = ec_group[group].IOsegment[currentsegment++];
01449             if ((length - sublength) < 0)
01450               sublength = length;
01451             /* get new index */
01452             idx = ec_getindex();
01453             w1 = LO_WORD(LogAdr);
01454             w2 = HI_WORD(LogAdr);
01455             ec_setupdatagram(&ec_txbuf[idx], EC_CMD_LWR, idx, w1, w2, sublength, data);
01456             /* send frame */
01457             ec_outframe_red(idx);
01458             /* push index and data pointer on stack */
01459             ec_pushindex(idx, data, sublength);
01460             length -= sublength;
01461             LogAdr += sublength;
01462             data += sublength;
01463           } while (length && (currentsegment < ec_group[group].nsegments));
01464         }
01465       }
01466       /* LRW can be used */
01467       else
01468       {
01469         if (ec_group[group].Obytes)
01470           data = ec_group[group].outputs;
01471         else
01472           data = ec_group[group].inputs;
01473         /* segment transfer if needed */
01474         do
01475         {
01476           sublength = ec_group[group].IOsegment[currentsegment++];
01477           /* get new index */
01478           idx = ec_getindex();
01479           w1 = LO_WORD(LogAdr);
01480           w2 = HI_WORD(LogAdr);
01481           ec_setupdatagram(&ec_txbuf[idx], EC_CMD_LRW, idx, w1, w2, sublength, data);
01482           if (first)
01483           {
01484             ec_DCl = sublength;
01485             /* FPRMW in second datagram */
01486             ec_DCtO = ec_adddatagram(&ec_txbuf[idx], EC_CMD_FRMW, idx, FALSE,
01487                                      ec_slave[ec_group[group].DCnext].configadr, ECT_REG_DCSYSTIME, sizeof(ec_DCtime),
01488                                      &ec_DCtime);
01489             first = FALSE;
01490           }
01491           /* send frame */
01492           ec_outframe_red(idx);
01493           /* push index and data pointer on stack */
01494           ec_pushindex(idx, data, sublength);
01495           length -= sublength;
01496           LogAdr += sublength;
01497           data += sublength;
01498         } while (length && (currentsegment < ec_group[group].nsegments));
01499       }
01500     }
01501 
01502     return wkc;
01503   }
01504 
01512   int ec_receive_processdata_group(uint8 group, int timeout)
01513   {
01514     int pos, idx;
01515     int wkc = 0, wkc2;
01516     boolean first = FALSE;
01517 
01518     if (ec_group[group].hasdc)
01519       first = TRUE;
01520     /* get first index */
01521     pos = ec_pullindex();
01522     /* read the same number of frames as send */
01523     while (pos >= 0)
01524     {
01525       idx = ec_idxstack.idx[pos];
01526       wkc2 = ec_waitinframe(ec_idxstack.idx[pos], timeout);
01527       /* check if there is input data in frame */
01528       if ((wkc2 > EC_NOFRAME) && ((ec_rxbuf[idx][EC_CMDOFFSET]==EC_CMD_LRD) || (ec_rxbuf[idx][EC_CMDOFFSET]==EC_CMD_LRW)))
01529             {
01530                         if(first)
01531                         {       
01532                         memcpy(ec_idxstack.data[pos], &ec_rxbuf[idx][EC_HEADERSIZE], ec_DCl);
01533                                 memcpy(&wkc, &ec_rxbuf[idx][EC_HEADERSIZE + ec_DCl], EC_WKCSIZE);
01534                                 wkc = etohs(wkc);
01535                                 memcpy(&ec_DCtime, &ec_rxbuf[idx][ec_DCtO], sizeof(ec_DCtime));
01536                                 ec_DCtime = etohll(ec_DCtime);
01537                                 first = FALSE;
01538                         }
01539                         else
01540                         {       
01541                                 /* copy input data back to process data buffer */
01542                             memcpy(ec_idxstack.data[pos], &ec_rxbuf[idx][EC_HEADERSIZE], ec_idxstack.length[pos]);
01543                                 wkc += wkc2;
01544                         }       
01545             }
01546       /* release buffer */
01547       ec_setbufstat(idx, EC_BUF_EMPTY);
01548       /* get next index */
01549       pos = ec_pullindex();
01550     }
01551 
01552     return wkc;
01553   }
01554 
01555   int ec_send_processdata(void)
01556   {
01557     return ec_send_processdata_group(0);
01558   }
01559 
01560   int ec_receive_processdata(int timeout)
01561   {
01562     return ec_receive_processdata_group(0, timeout);
01563   }


youbot_driver
Author(s): Jan Paulus
autogenerated on Mon Oct 6 2014 09:08:01