mailbox.c

Go to the documentation of this file.
00001 /******************************************************************************
00002  *
00003  *  $Id: mailbox.c 490 2006-08-02 12:25:25Z fp $
00004  *
00005  *  Copyright (C) 2006  Florian Pose, Ingenieurgemeinschaft IgH
00006  *
00007  *  This file is part of the IgH EtherCAT Master.
00008  *
00009  *  The IgH EtherCAT Master is free software; you can redistribute it
00010  *  and/or modify it under the terms of the GNU General Public License
00011  *  as published by the Free Software Foundation; either version 2 of the
00012  *  License, or (at your option) any later version.
00013  *
00014  *  The IgH EtherCAT Master is distributed in the hope that it will be
00015  *  useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017  *  GNU General Public License for more details.
00018  *
00019  *  You should have received a copy of the GNU General Public License
00020  *  along with the IgH EtherCAT Master; if not, write to the Free Software
00021  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00022  *
00023  *  The right to use EtherCAT Technology is granted and comes free of
00024  *  charge under condition of compatibility of product made by
00025  *  Licensee. People intending to distribute/sell products based on the
00026  *  code, have to sign an agreement to guarantee that products using
00027  *  software based on IgH EtherCAT master stay compatible with the actual
00028  *  EtherCAT specification (which are released themselves as an open
00029  *  standard) as the (only) precondition to have the right to use EtherCAT
00030  *  Technology, IP and trade marks.
00031  *
00032  *****************************************************************************/
00033 
00039 /*****************************************************************************/
00040 
00041 #include <linux/slab.h>
00042 #include <linux/delay.h>
00043 
00044 #include "mailbox.h"
00045 #include "datagram.h"
00046 #include "master.h"
00047 
00048 /*****************************************************************************/
00049 
00055 uint8_t *ec_slave_mbox_prepare_send(const ec_slave_t *slave, 
00056                                     ec_datagram_t *datagram, 
00057                                     uint8_t type, 
00058                                     size_t size 
00059                                     )
00060 {
00061     size_t total_size;
00062 
00063     if (unlikely(!slave->sii_mailbox_protocols)) {
00064         EC_ERR("Slave %i does not support mailbox communication!\n",
00065                slave->ring_position);
00066         return NULL;
00067     }
00068 
00069     total_size = size + 6;
00070     if (unlikely(total_size > slave->sii_rx_mailbox_size)) {
00071         EC_ERR("Data size does not fit in mailbox!\n");
00072         return NULL;
00073     }
00074 
00075     if (ec_datagram_npwr(datagram, slave->station_address,
00076                          slave->sii_rx_mailbox_offset,
00077                          slave->sii_rx_mailbox_size))
00078         return NULL;
00079 
00080     EC_WRITE_U16(datagram->data,     size); // mailbox service data length
00081     EC_WRITE_U16(datagram->data + 2, slave->station_address); // station addr.
00082     EC_WRITE_U8 (datagram->data + 4, 0x00); // channel & priority
00083     EC_WRITE_U8 (datagram->data + 5, type); // underlying protocol type
00084 
00085     return datagram->data + 6;
00086 }
00087 
00088 /*****************************************************************************/
00089 
00095 int ec_slave_mbox_prepare_check(const ec_slave_t *slave, 
00096                                 ec_datagram_t *datagram 
00097                                 )
00098 {
00099     // FIXME: second sync manager?
00100     if (ec_datagram_nprd(datagram, slave->station_address, 0x808, 8))
00101         return -1;
00102 
00103     return 0;
00104 }
00105 
00106 /*****************************************************************************/
00107 
00113 int ec_slave_mbox_check(const ec_datagram_t *datagram )
00114 {
00115     return EC_READ_U8(datagram->data + 5) & 8 ? 1 : 0;
00116 }
00117 
00118 /*****************************************************************************/
00119 
00125 int ec_slave_mbox_prepare_fetch(const ec_slave_t *slave, 
00126                                 ec_datagram_t *datagram 
00127                                 )
00128 {
00129     if (ec_datagram_nprd(datagram, slave->station_address,
00130                          slave->sii_tx_mailbox_offset,
00131                          slave->sii_tx_mailbox_size)) return -1;
00132     return 0;
00133 }
00134 
00135 /*****************************************************************************/
00136 
00142 uint8_t *ec_slave_mbox_fetch(const ec_slave_t *slave, 
00143                              ec_datagram_t *datagram, 
00144                              uint8_t type, 
00145                              size_t *size 
00146                              )
00147 {
00148     size_t data_size;
00149 
00150     if ((EC_READ_U8(datagram->data + 5) & 0x0F) != type) {
00151         EC_ERR("Unexpected mailbox protocol 0x%02X (exp.: 0x%02X) at"
00152                " slave %i!\n", EC_READ_U8(datagram->data + 5), type,
00153                slave->ring_position);
00154         return NULL;
00155     }
00156 
00157     if ((data_size = EC_READ_U16(datagram->data)) >
00158         slave->sii_tx_mailbox_size - 6) {
00159         EC_ERR("Currupt mailbox response detected!\n");
00160         return NULL;
00161     }
00162 
00163     *size = data_size;
00164     return datagram->data + 6;
00165 }
00166 
00167 /*****************************************************************************/
00168 
00174 uint8_t *ec_slave_mbox_simple_io(const ec_slave_t *slave, 
00175                                  ec_datagram_t *datagram, 
00176                                  size_t *size 
00177                                  )
00178 {
00179     uint8_t type;
00180 
00181     type = EC_READ_U8(datagram->data + 5);
00182 
00183     if (unlikely(ec_master_simple_io(slave->master, datagram))) {
00184         EC_ERR("Mailbox checking failed on slave %i!\n",
00185                slave->ring_position);
00186         return NULL;
00187     }
00188 
00189     return ec_slave_mbox_simple_receive(slave, datagram, type, size);
00190 }
00191 
00192 /*****************************************************************************/
00193 
00199 uint8_t *ec_slave_mbox_simple_receive(const ec_slave_t *slave, 
00200                                       ec_datagram_t *datagram, 
00201                                       uint8_t type, 
00202                                       size_t *size 
00203                                       )
00204 {
00205     cycles_t start, end, timeout;
00206 
00207     start = get_cycles();
00208     timeout = (cycles_t) 100 * cpu_khz; // 100ms
00209 
00210     while (1)
00211     {
00212         if (ec_slave_mbox_prepare_check(slave, datagram)) return NULL;
00213         if (unlikely(ec_master_simple_io(slave->master, datagram))) {
00214             EC_ERR("Mailbox checking failed on slave %i!\n",
00215                    slave->ring_position);
00216             return NULL;
00217         }
00218 
00219         end = get_cycles();
00220 
00221         if (ec_slave_mbox_check(datagram))
00222             break; // proceed with receiving data
00223 
00224         if ((end - start) >= timeout) {
00225             EC_ERR("Mailbox check - Slave %i timed out.\n",
00226                    slave->ring_position);
00227             return NULL;
00228         }
00229 
00230         udelay(100);
00231     }
00232 
00233     if (ec_slave_mbox_prepare_fetch(slave, datagram)) return NULL;
00234     if (unlikely(ec_master_simple_io(slave->master, datagram))) {
00235         EC_ERR("Mailbox receiving failed on slave %i!\n",
00236                slave->ring_position);
00237         return NULL;
00238     }
00239 
00240     if (unlikely(slave->master->debug_level) > 1)
00241         EC_DBG("Mailbox receive took %ius.\n",
00242                ((unsigned int) (end - start) * 1000 / cpu_khz));
00243 
00244     return ec_slave_mbox_fetch(slave, datagram, type, size);
00245 }
00246 
00247 /*****************************************************************************/

Generated on Wed Aug 2 18:41:43 2006 for IgH EtherCAT master by  doxygen 1.4.6