Exemplo n.º 1
0
static void conn_autocommit_event(int fd, short event, void *_userdata) {
  struct maria_status *ms = (struct maria_status *)_userdata;
  MYSQL *conn = (MYSQL *)ms->data;
  lua_State *L = ms->L;

  int errorcode = mysql_errno(conn);
  if (errorcode) {
    FAN_RESUME(L, NULL, luamariadb_push_errno(L, ms->conn_data));
    UNREF_CO(ms->conn_data);
  } else {
    my_bool ret = 0;
    int status = mysql_autocommit_cont(&ret, conn, ms->status);
    if (status) {
      wait_for_status(L, ms->conn_data, conn, status, conn_autocommit_event,
                      ms->extra);
    } else if (ret == 0) {
      lua_pushboolean(L, true);
      FAN_RESUME(L, NULL, 1);
      UNREF_CO(ms->conn_data);
    } else {
      FAN_RESUME(L, NULL, luamariadb_push_errno(L, ms->conn_data));
      UNREF_CO(ms->conn_data);
    }
  }
  event_free(ms->event);
  free(ms);
}
Exemplo n.º 2
0
static void stmt_send_long_data_event(int fd, short event, void *_userdata) {
  struct maria_status *ms = (struct maria_status *)_userdata;
  st_data *st = (st_data *)ms->data;
  lua_State *L = ms->L;

  int errorcode = mysql_stmt_errno(st->my_stmt);
  if (errorcode) {
    FAN_RESUME(L, NULL, luamariadb_push_stmt_error(L, st));
    UNREF_CO(st);
  } else {
    my_bool ret = 0;
    int status = mysql_stmt_send_long_data_cont(&ret, st->my_stmt, ms->status);
    if (status) {
      wait_for_status(L, st->conn_data, st, status, stmt_send_long_data_event,
                      ms->extra);
    } else if (ret == 0) {
      int count = stmt_send_long_data_result(L, st);
      FAN_RESUME(L, NULL, count);
      UNREF_CO(st);
    } else {
      FAN_RESUME(L, NULL, luamariadb_push_stmt_error(L, st));
      UNREF_CO(st);
    }
  }

  event_free(ms->event);
  free(ms);
}
/*******************************************************************************
* Function Name: nack_detected 
* Description  : Check if a '0' was not issued in ack bit time slot. This is
*                called a "NACK".
* Arguments    : channel -
*                    Which RIIC channel to use
* Return Value : RIIC_OK -
*                    No NACK detected.
*                RIIC_BUSY_TMO -
*                    Channel is busy. Timeout occurred.
*                RIIC_STOP_TMO - 
*                    Timeout waiting for detection of stop condition.
*                RIIC_NACK_ERR -
*                    NACK detected.
*******************************************************************************/
static riic_ret_t nack_detected(uint8_t channel)
{
    volatile uint8_t tmp;    
     
    /* If NACK error, request a stop. */
    if (1 == (*g_riic_channels[channel]).ICSR2.BIT.NACKF)
    {
        /* NACK detected. */
        (*g_riic_channels[channel]).ICSR2.BIT.NACKF = 0;
        (*g_riic_channels[channel]).ICSR2.BIT.STOP = 0;

        /* Issue stop. */
        (*g_riic_channels[channel]).ICCR2.BIT.SP = 1;

        /* Do a dummy read. (See Master Reception flowchart.) */
        tmp = (*g_riic_channels[channel]).ICDRR;

        /* Wait for a detected stop condition. */
        if(RIIC_OK != wait_for_status(channel, RIIC_STOP_TMO))
        {
            return RIIC_STOP_TMO;            
        }  

        if(RIIC_OK != wait_for_status(channel, RIIC_BUSY_TMO))
        {
            return RIIC_BUSY_TMO;            
        }
          
        (*g_riic_channels[channel]).ICSR2.BIT.STOP = 0;

        return RIIC_NACK_ERR;
    }    
    else
    {
        /* No NACK detected. */
        return RIIC_OK;
    }
} /* End of function nack_detected() */
Exemplo n.º 4
0
LUA_API int conn_autocommit_start(lua_State *L) {
  conn_data *conn = getconnection(L);
  my_bool auto_mode = lua_toboolean(L, 2);

  my_bool ret = 0;
  int status = mysql_autocommit_start(&ret, &conn->my_conn, auto_mode);
  if (status) {
    REF_CO(conn);
    wait_for_status(L, conn, &conn->my_conn, status, conn_autocommit_event, 0);
    return lua_yield(L, 0);
  } else if (ret == 0) {
    lua_pushboolean(L, true);
    return 1;
  } else {
    return luamariadb_push_errno(L, conn);
  }
}
Exemplo n.º 5
0
LUA_API int set_character_set_start(lua_State *L) {
  conn_data *conn = getconnection(L);
  const char *charset = luaL_checkstring(L, 2);

  int ret = 0;
  int status = mysql_set_character_set_start(&ret, &conn->my_conn, charset);
  if (status) {
    REF_CO(conn);
    wait_for_status(L, conn, &conn->my_conn, status, set_character_set_cont, 0);
    return lua_yield(L, 0);
  } else if (ret == 0) {
    lua_pushboolean(L, 1);
    return 1;
  } else {
    return luamariadb_push_errno(L, conn);
  }
}
/*******************************************************************************
* Function Name: riic_tx_byte 
* Description  : Transmits one byte in master mode over RIIC channel
* Arguments    : channel -
*                    Which RIIC channel to use
*                tx_data -
*                    Byte to transmit
* Return Value : RIIC_OK -
*                    Byte transmitted successfully.
*                RIIC_TDRE_TMO -
*                    Timeout occured waiting for last transfer to finish.
*                RIIC_NACK_ERR -
*                    NACK detected.
*******************************************************************************/
static riic_ret_t riic_master_tx_byte(uint8_t channel, uint8_t tx_data)
{
    riic_ret_t result = RIIC_OK;
   
    /* Wait for TDRE status. */
    result = wait_for_status(channel, RIIC_TDRE_TMO);

    /* Proceed with write. */
    if (RIIC_OK == result)
    {
        /* Copying data to the TX register starts transmission. */
        (*g_riic_channels[channel]).ICDRT = (uint8_t)(tx_data); 

        /* Check for NACK. */
        result = nack_detected(channel);
    }
         
    return result;
} /* End of function riic_tx_byte() */
Exemplo n.º 7
0
LUA_API int stmt_close_start(lua_State *L, st_data *st) {
  st->closed = 1;

  my_bool ret = 0;
  int status = mysql_stmt_close_start(&ret, st->my_stmt);
  if (status) {
    REF_CO(st);
    wait_for_status(L, st->conn_data, st, status, stmt_close_cont, 0);
    return lua_yield(L, 0);
  } else if (ret == 0) {
    luaL_unref(L, LUA_REGISTRYINDEX, st->table);
    lua_pushboolean(L, 1);
    return 1;
  } else {
    return luamariadb_push_errno(L, st->conn_data);
  }

  return 0;
}
Exemplo n.º 8
0
LUA_API int st_send_long_data(lua_State *L) {
  st_data *st = getstatement(L);

  size_t size = 0;
  int num = luaL_checkinteger(L, 2);
  const char *data = luaL_checklstring(L, 3, &size);

  my_bool ret = 0;
  int status =
      mysql_stmt_send_long_data_start(&ret, st->my_stmt, num, data, size);
  if (status) {
    REF_CO(st);
    wait_for_status(L, st->conn_data, st, status, stmt_send_long_data_event, 0);
    return lua_yield(L, 0);
  } else if (ret == 0) {
    return stmt_send_long_data_result(L, st);
  } else {
    return luamariadb_push_stmt_error(L, st);
  }
}
Exemplo n.º 9
0
static void stmt_close_cont(int fd, short event, void *_userdata) {
  struct maria_status *ms = (struct maria_status *)_userdata;
  lua_State *L = ms->L;
  st_data *st = (st_data *)ms->data;

  my_bool ret = 0;
  int status = mysql_stmt_close_cont(&ret, st->my_stmt, ms->status);
  if (status) {
    wait_for_status(L, st->conn_data, st, status, stmt_close_cont, ms->extra);
  } else if (ret == 0) {
    luaL_unref(L, LUA_REGISTRYINDEX, st->table);

    lua_pushboolean(L, 1);
    FAN_RESUME(L, NULL, 1);
    UNREF_CO(st);
  } else {
    luaL_unref(L, LUA_REGISTRYINDEX, st->table);
    FAN_RESUME(L, NULL, luamariadb_push_errno(L, ms->conn_data));
    UNREF_CO(st);
  }
}
Exemplo n.º 10
0
static void set_character_set_cont(int fd, short event, void *_userdata) {
  struct maria_status *ms = (struct maria_status *)_userdata;
  MYSQL *conn = (MYSQL *)ms->data;
  lua_State *L = ms->L;

  int ret = 0;
  int status = mysql_set_character_set_cont(&ret, conn, ms->status);
  if (status) {
    wait_for_status(L, ms->conn_data, conn, status, set_character_set_cont,
                    ms->extra);
  } else if (ret == 0) {
    lua_pushboolean(L, 1);
    FAN_RESUME(L, NULL, 1);
    UNREF_CO(ms->conn_data);
  } else {
    FAN_RESUME(L, NULL, luamariadb_push_errno(L, ms->conn_data));
    UNREF_CO(ms->conn_data);
  }

  event_free(ms->event);
  free(ms);
}
Exemplo n.º 11
0
/*******************************************************************************
* Function Name: R_RIIC_MasterReceive 
* Description  : Receive data over RIIC. 
*              : Supports entry on start or restart conditions.
*              : For entry on restart condition, R_RIIC_MasterTransmitHead() should 
*              : already have been called before this. 
* Arguments    : channel -
*                    Which RIIC channel to use
*                slave_addr -
*                    Slave address
*                p_data_buff -
*                    Pointer to data buffer
*                num_bytes -
*                    Number of bytes to read
* Return Value : RIIC_OK -
*                    Operation completed successfully.
*                RIIC_LOCKED -
*                    This task has not locked this RIIC channel yet.
*                RIIC_BUSY_TMO -
*                    Channel is busy. Timeout occurred.
*                RIIC_TDRE_TMO -
*                    Timeout occured waiting for last transfer to finish.
*                RIIC_TEND_TMO -
*                    Timeout occurred waiting for data to finish transmitting.
*                RIIC_STOP_TMO - 
*                    Timeout waiting for detection of stop condition.
*                RIIC_START_TMO -
*                    Timeout waiting for detection of start condition
*                RIIC_RDRF_TMO -
*                    Timeout waiting for receive data
*                RIIC_NACK_ERR - 
*                    NACK received.
*                RIIC_LOCKED -
*                    RIIC channel was already locked for another operation.
*                RIIC_NO_CHANNEL -
*                    Channel requested is not a valid RIIC channel.
*******************************************************************************/
riic_ret_t R_RIIC_MasterReceive(uint8_t         channel,
                                uint8_t         slave_addr,
                                uint8_t *       p_data_buff,
                                const uint32_t  num_bytes)
{
    /* Return value */
    riic_ret_t ret = RIIC_OK;
    /* Loop variable */
    uint32_t   count = 1; 

    if(RIIC_IDLE_MODE == g_riic_mode[channel])
    {            
        if(RIIC_OK != wait_for_status(channel, RIIC_BUSY_TMO))
        {
            return RIIC_BUSY_TMO;            
        } 
        
        (*g_riic_channels[channel]).ICSR2.BIT.START = 0;
            
        /* Issue start condition. */
        (*g_riic_channels[channel]).ICCR2.BIT.ST = 1;            
    }
    else if (MASTER_TRANSMIT_MODE == g_riic_mode[channel])        
    {
        /* Test to see if this channel is already locked. It should be since
           the mode is not IDLE. R_RIIC_MasterTransmitHead() must have been 
           called before this function and it should already have locked the 
           channel. If this returns that the lock was obtained then a function 
           called this one out-of-turn. */
        if ( RIIC_OK == riic_lock(channel))
        {
            /* This function was called out-of-turn. */
            /* Give up lock */
            riic_unlock(channel);

            return RIIC_LOCKED;
        }  
                
        /* Issue re-start condition. */
        (*g_riic_channels[channel]).ICSR2.BIT.START = 0;
        (*g_riic_channels[channel]).ICCR2.BIT.RS = 1;
    }
    else
    {
        riic_unlock(channel);            
        return RIIC_MODE_ERR; 
    }     


    if(RIIC_OK != wait_for_status(channel, RIIC_START_TMO))
    {
        /* Give up lock */
        riic_unlock(channel);

        return RIIC_START_TMO;            
    }

    /* Wait for TDRE status. */
    if(RIIC_OK != wait_for_status(channel, RIIC_TDRE_TMO))
    {
        /* Give up lock */
        riic_unlock(channel);

        return RIIC_TDRE_TMO;            
    }  
  
    /*** Send slave address + READ-bit (b7). ***/
    (*g_riic_channels[channel]).ICDRT = slave_addr | 0x01;

    /* Wait for receive data ready status. */
    if(RIIC_OK != wait_for_status(channel, RIIC_RDRF_TMO))
    {
        /* Give up lock */
        riic_unlock(channel);

        return RIIC_RDRF_TMO;            
    }      

    /* Check for NACK */
    ret = nack_detected(channel);

    if (RIIC_OK != ret)
    {
        /* Give up lock */
        riic_unlock(channel);

        return ret;
    }

    /* Dummy read ICDRR. Starts outputting clocks to perform real read. */
    (*g_riic_channels[channel]).ICDRR;
     
    while (count < (num_bytes))
    {
        /* Wait for receive data ready status. */
        if(RIIC_OK != wait_for_status(channel, RIIC_RDRF_TMO))
        {
            /* Give up lock */
            riic_unlock(channel);

            return RIIC_RDRF_TMO;            
        }

        /* Set the WAIT bit - (The period between ninth clock cycle and 
           first clock cycle is held low.) Low-hold is released by 
           reading ICDRR.*/
        if(count == (num_bytes - 2))
        {
            (*g_riic_channels[channel]).ICMR3.BIT.WAIT = 1;
        }
        /* Set bit to send NACK */ 
        else if (count == (num_bytes - 1))
        {            
            (*g_riic_channels[channel]).ICMR3.BIT.ACKBT = 1;                  
        }
        else
        {
            /* Do nothing. */
        }
        
        /* Copy data to application read buffer, and increment its pointer. */
        *p_data_buff = (*g_riic_channels[channel]).ICDRR;
        p_data_buff++;
        count++;
    }              

    /* If num_bytes is 1 then the while loop above will be skipped. The
       ACKBT bit still needs to be set. */
    if (num_bytes <= 1)
    {
        /* Set bit to send NACK */ 
        (*g_riic_channels[channel]).ICMR3.BIT.ACKBT = 1;
    }

    if(RIIC_OK != wait_for_status(channel, RIIC_RDRF_TMO)) 
    {
        /* Give up lock */
        riic_unlock(channel);

        return RIIC_RDRF_TMO;            
    }
      
    /* Issue Stop. */
    (*g_riic_channels[channel]).ICSR2.BIT.STOP = 0;
    (*g_riic_channels[channel]).ICCR2.BIT.SP = 1;
    
    /* Read final byte. */       
    *p_data_buff = (*g_riic_channels[channel]).ICDRR;

    (*g_riic_channels[channel]).ICMR3.BIT.WAIT = 0;

    /* Wait for a detected stop condition. */
    if(RIIC_OK != wait_for_status(channel, RIIC_STOP_TMO))
    {
        /* Give up lock */
        riic_unlock(channel);
        ret = RIIC_STOP_TMO;            
    } 
 
    (*g_riic_channels[channel]).ICSR2.BIT.NACKF = 0;
    (*g_riic_channels[channel]).ICSR2.BIT.STOP = 0;     

    /* Give up lock */
    riic_unlock(channel);

    g_riic_mode[channel] = RIIC_IDLE_MODE;

    return ret;
} /* End of function R_RIIC_MasterReceive() */
Exemplo n.º 12
0
/*******************************************************************************
* Function Name: R_RIIC_MasterTransmit 
* Description  : Transmits data over RIIC. R_RIIC_MasterTransmitHead() should 
*                already have been called before this
* Arguments    : channel -
*                    Which RIIC channel to use
*                p_data_buff -
*                    Pointer to data buffer
*                num_bytes -
*                    Number of bytes to transmit
*					 If num_bytes = 0, then only the stop is processed.
* Return Value : RIIC_OK -
*                    Operation completed successfully.
*                RIIC_BUSY_TMO -
*                    Channel is busy. Timeout occurred.
*                RIIC_TDRE_TMO -
*                    Timeout occured waiting for last transfer to finish.
*                RIIC_TEND_TMO -
*                    Timeout occurred waiting for data to finish transmitting.
*                RIIC_STOP_TMO - 
*                    Timeout waiting for detection of stop condition.
*                RIIC_LOCKED -
*                    RIIC channel was already locked for another operation.
*                RIIC_NO_CHANNEL -
*                    Channel requested is not a valid RIIC channel.
*******************************************************************************/
riic_ret_t R_RIIC_MasterTransmit(uint8_t        channel,
                                 uint8_t *      p_data_buff, 
                                 const uint32_t num_bytes)
{
    uint32_t count; /* Local loop counter variable. */ 
    riic_ret_t ret = RIIC_OK;/* Return value */

    /* Test to see if this channel is already locked. It should be since
       R_RIIC_MasterTransmitHead() must be called before this function and
       it should already have locked the channel. If this returns that the lock
       was obtained then a function called this one out-of-turn. */
    if (RIIC_OK == riic_lock(channel))
    {
        /* This function was called out-of-turn. */
        /* Give up lock */
        riic_unlock(channel);

        return RIIC_LOCKED;
    }

	if(num_bytes > 0) /* Skip ahead and just do the Stop otherwise */
	{
		/* Transmit data. */
		for (count = 0; count < num_bytes; count++)
		{
			/* Send 1 byte at a time */
			ret = riic_master_tx_byte(channel, p_data_buff[count]);

			/* Check result. */
			if (RIIC_OK != ret)
			{
				/* Give up lock */
				riic_unlock(channel);

				return ret;
			}
		}

		/* Wait for transmission completed status. */
		if(RIIC_OK != wait_for_status(channel, RIIC_TEND_TMO))
		{
			/* Give up lock */
			riic_unlock(channel);

			return RIIC_TEND_TMO;
		}       

		/* Check for NACK */
		ret = nack_detected(channel);

		if (RIIC_OK != ret)
		{
			/* Give up lock */
			riic_unlock(channel);

			return ret;
		}

	}
    /* Request to issue a stop condition. */
    (*g_riic_channels[channel]).ICSR2.BIT.STOP = 0;
    (*g_riic_channels[channel]).ICCR2.BIT.SP = 1;

    /* Wait for a detected stop condition. */
    ret = wait_for_status(channel, RIIC_STOP_TMO);
    
    if (RIIC_OK != ret)
    {
        /* Give up lock */
        riic_unlock(channel);

        return ret;
    }
          
    /* Clear status before exit. */
    (*g_riic_channels[channel]).ICSR2.BIT.NACKF = 0;     
    (*g_riic_channels[channel]).ICSR2.BIT.STOP = 0;
    
    /* Give up lock */
    riic_unlock(channel);

    g_riic_mode[channel] = RIIC_IDLE_MODE;

    return RIIC_OK;
} /* End of function R_RIIC_MasterTransmit() */
Exemplo n.º 13
0
/*******************************************************************************
* Function Name: R_RIIC_MasterTransmitHead
* Description  : Transmits header information on I2C bus to precede other write
*                or read operations. Starts out a transmission with a start 
*                condition but does not end with a stop. Leaves bus state ready
*                for continuing operations.		
* Parameters   : source_buf -
*                    Pointer to the buffer holding the data to be transmitted.         
*                nr_bytes -
*                    The number of bytes to transmit.
* Return Value : RIIC_OK -
*                    Operation completed successfully.
*                RIIC_BUSY_TMO -
*                    Channel is busy. Timeout occurred.
*                RIIC_TDRE_TMO -
*                    Timeout occured waiting for last transfer to finish.
*                RIIC_TEND_TMO -
*                    Timeout occurred waiting for data to finish transmitting.
*                RIIC_STOP_TMO - 
*                    Timeout waiting for detection of stop condition.
*                RIIC_LOCKED -
*                    RIIC channel was already locked for another operation.
*                RIIC_NO_CHANNEL -
*                    Channel requested is not a valid RIIC channel.
*                RIIC_NACK_ERR -
*                    Got a NACK when an ACK was expected.
*******************************************************************************/
riic_ret_t R_RIIC_MasterTransmitHead(uint8_t          channel,                                      
                                     uint8_t *        p_data_buff, 
                                     const uint32_t   num_bytes)
{
    uint32_t count; /* Local loop counter variable. */
    
    /* Return value */
    riic_ret_t ret = RIIC_OK;

    /* Try to lock this channel. */
    ret = riic_lock(channel); 

    /* Check result */
    if ( RIIC_OK != ret )
    {
        /* Either already locked or invalid channel. */
        return ret;
    }

    /* Wait for RIIC bus free. */
    if(RIIC_OK != wait_for_status(channel, RIIC_BUSY_TMO))
    {
        /* Give up lock */
        riic_unlock(channel);

        return RIIC_BUSY_TMO;            
    } 

    /* Generate start condition. */
    (*g_riic_channels[channel]).ICCR2.BIT.ST = 1;

    /* Check for NACK */
    ret = nack_detected(channel);

    if (RIIC_OK != ret)
    {
        /* Give up lock */
        riic_unlock(channel);

        return ret;
    }

    
    /* Transmit header. */
    for (count = 0; count < num_bytes; count++)
    {
    	/* Aspetto il bus libero prima di trasmettere il dato successivo? */
    	//wait_for_status(channel, RIIC_BUSY_TMO);
    	/* Aspetto lo stato alto della sola linea dati
    	 * Provare con e senza
    	 **/
    	wait_for_status(channel, RIIC_DATA_HIGH);

    	/* Send 1 byte at a time */
        ret = riic_master_tx_byte(channel, p_data_buff[count]);

        /* Check result. */
        if (RIIC_OK != ret)
        {
            /* Give up lock */
            riic_unlock(channel);

            return ret;
        }

        /* AAA Wait for complete end of transmission status.
         * intra bytes transmission
         * Provare con e senza...
         * */
        if(num_bytes >= 2 && count < (num_bytes - 1))
        	wait_for_status(channel, RIIC_TEND_TMO);

    }

    /* Wait for complete end of transmission status. */
    ret = wait_for_status(channel, RIIC_TEND_TMO);
    if(RIIC_OK != ret)
    {
        ret |= RIIC_TEND_TMO;
        
        /* If NACK detected, it issues stop to complete the transmission. */   
        ret |= nack_detected(channel);

        /* Give up lock */
        riic_unlock(channel);             
        return ret;            
    }
    
    /* Check for NACK */
    ret = nack_detected(channel);

    if (RIIC_OK != ret)
    {
        /* Give up lock */
        riic_unlock(channel);
    }

    /* Since this is just sending the header, riic_unlock() will be called
       later from R_RIIC_MasterReceive() or R_RIIC_MasterTransmit(). */

    g_riic_mode[channel] = MASTER_TRANSMIT_MODE;

    return ret;   
} /* End of function R_RIIC_MasterTransmitHead() */
Exemplo n.º 14
0
int state_config( int fd, int itf, Msgs *msgs ){
	Message *tmp;
	int newstate = S1;

	diag( COMPONENT, DIAG_INFO, "State S4: config" );
	ilmi_state = down;

	if( config->atmfAtmLayerUniVersion == 0 ){
		diag( COMPONENT, DIAG_ERROR, "remote IME did not negotiate "
			"a UNI version -- using configured uni version." );
	} else
	if( config->atmfAtmLayerUniVersion < atmfAtmLayerUniVersionValue ){
		diag( COMPONENT, DIAG_ERROR, "remote IME does not support"
			" the locally configured uni version" );
		atmfAtmLayerUniVersionValue = config->atmfAtmLayerUniVersion;
	}

	if( config->atmfAtmLayerDeviceType == 2 /* NODE */ ){
		action_A6( fd, msgs );	/* stop timer */
		action_A10( fd, msgs );	/* Start signalling */
		action_A14( fd, msgs );	/* request address status */
		action_A7( fd, msgs );	/* retries = 0 */
		action_A5( fd, msgs );	/* start timer */
		newstate = S5;	/* retrieve network prefixes */
	} else if( config->atmfAtmLayerDeviceType == 1 /* USER */ ){
		diag( COMPONENT, DIAG_ERROR, "Remote device is also a host" );
		action_A10( fd, msgs );	/* start signalling */
		action_A14( fd, msgs );	/* get next prefix */
		action_A7( fd, msgs );	/* retries = 0 */
		action_A5( fd, msgs );	/* start timer */
		newstate = S6;
	} else if( config->atmfAtmLayerDeviceType == 0 /* ??? */ ){
		diag( COMPONENT, DIAG_ERROR, "Remote IME does not know "
			"what type of device it is -- assume NODE" );
		action_A6( fd, msgs );	/* stop timer */
		action_A10( fd, msgs );	/* Start signalling */
		action_A14( fd, msgs );	/* request address status */
		action_A7( fd, msgs );	/* retries = 0 */
		action_A5( fd, msgs );	/* start timer */
		newstate = S5;	/* retrieve network prefixes */
	}

	while(( tmp = wait_for_status( fd, itf, msgs )) == NULL ){
		if( ilmi_errno == ETIMEOUT ){
			action_A14( fd, msgs );	/* request address status */
			action_A8( fd, msgs );	/* retries++ */
			action_A5( fd, msgs );	/* start timer */
		} else if( ilmi_errno == ECOLDSTART ){
			return S1;
		}
	}

	action_get_sysgroup( fd, msgs );
	while(( tmp = wait_for_sysgroup( fd, itf, msgs )) == NULL ){
		if( ilmi_errno == ETIMEOUT ){
			action_get_sysgroup( fd, msgs );
			action_A8( fd, msgs );	/* retries++ */
			action_A5( fd, msgs );	/* start timer */
		} else if( ilmi_errno == ECOLDSTART ){
			return S1;
		}
	}

	return newstate;
}
Exemplo n.º 15
0
size_t tpm2_process_command(const void *tpm2_command, size_t command_size,
			    void *tpm2_response, size_t max_response)
{
	uint32_t status;
	uint32_t expected_status_bits;
	size_t payload_size;
	size_t bytes_to_go;
	const uint8_t *cmd_body = tpm2_command;
	uint8_t *rsp_body = tpm2_response;
	union fifo_transfer_buffer fifo_buffer;
	const int HEADER_SIZE = 6;
	struct tpm2_info *tpm_info = car_get_var_ptr(&g_tpm_info);

	/* Do not try using an uninitialized TPM. */
	if (!tpm_info->vendor_id)
		return 0;

	/* Skip the two byte tag, read the size field. */
	payload_size = read_be32(cmd_body + 2);

	/* Sanity check. */
	if (payload_size != command_size) {
		printk(BIOS_ERR,
		       "Command size mismatch: encoded %zd != requested %zd\n",
		       payload_size, command_size);
		trace_dump("W", TPM_DATA_FIFO_REG, command_size, cmd_body, 1);
		printk(BIOS_DEBUG, "\n");
		return 0;
	}

	/* Let the TPM know that the command is coming. */
	write_tpm_sts(TPM_STS_COMMAND_READY);

	/*
	 * TPM commands and responses written to and read from the FIFO
	 * register (0x24) are datagrams of variable size, prepended by a 6
	 * byte header.
	 *
	 * The specification description of the state machine is a bit vague,
	 * but from experience it looks like there is no need to wait for the
	 * sts.expect bit to be set, at least with the 9670 and cr50 devices.
	 * Just write the command into FIFO, making sure not to exceed the
	 * burst count or the maximum PDU size, whatever is smaller.
	 */
	fifo_buffer.tx_buffer = cmd_body;
	fifo_transfer(command_size, fifo_buffer, fifo_transmit);

	/* Now tell the TPM it can start processing the command. */
	write_tpm_sts(TPM_STS_GO);

	/* Now wait for it to report that the response is ready. */
	expected_status_bits = TPM_STS_VALID | TPM_STS_DATA_AVAIL;
	if (!wait_for_status(expected_status_bits, expected_status_bits)) {
		/*
		 * If timed out, which should never happen, let's at least
		 * print out the offending command.
		 */
		trace_dump("W", TPM_DATA_FIFO_REG, command_size, cmd_body, 1);
		printk(BIOS_DEBUG, "\n");
		return 0;
	}

	/*
	 * The response is ready, let's read it. First we read the FIFO
	 * payload header, to see how much data to expect. The response header
	 * size is fixed to six bytes, the total payload size is stored in
	 * network order in the last four bytes.
	 */
	tpm2_read_reg(TPM_DATA_FIFO_REG, rsp_body, HEADER_SIZE);

	/* Find out the total payload size, skipping the two byte tag. */
	payload_size = read_be32(rsp_body + 2);

	if (payload_size > max_response) {
		/*
		 * TODO(vbendeb): at least drain the FIFO here or somehow let
		 * the TPM know that the response can be dropped.
		 */
		printk(BIOS_ERR, " TPM response too long (%zd bytes)",
		       payload_size);
		return 0;
	}

	/*
	 * Now let's read all but the last byte in the FIFO to make sure the
	 * status register is showing correct flow control bits: 'more data'
	 * until the last byte and then 'no more data' once the last byte is
	 * read.
	 */
	bytes_to_go = payload_size - 1 - HEADER_SIZE;
	fifo_buffer.rx_buffer = rsp_body + HEADER_SIZE;
	fifo_transfer(bytes_to_go, fifo_buffer, fifo_receive);

	/* Verify that there is still data to read. */
	read_tpm_sts(&status);
	if ((status & expected_status_bits) != expected_status_bits) {
		printk(BIOS_ERR, "unexpected intermediate status %#x\n",
		       status);
		return 0;
	}

	/* Read the last byte of the PDU. */
	tpm2_read_reg(TPM_DATA_FIFO_REG, rsp_body + payload_size - 1, 1);

	/* Terminate the dump, if enabled. */
	if (debug_level_)
		printk(BIOS_DEBUG, "\n");

	/* Verify that 'data available' is not asseretd any more. */
	read_tpm_sts(&status);
	if ((status & expected_status_bits) != TPM_STS_VALID) {
		printk(BIOS_ERR, "unexpected final status %#x\n", status);
		return 0;
	}

	/* Move the TPM back to idle state. */
	write_tpm_sts(TPM_STS_COMMAND_READY);

	return payload_size;
}