openMMC
Open Source Modular MMC for AMCs
Loading...
Searching...
No Matches
ipmb.c File Reference
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "semphr.h"
#include "string.h"
#include "utils.h"
#include "ipmb.h"
#include "ipmi.h"
#include "led.h"
#include "port.h"
#include "task_priorities.h"
Include dependency graph for ipmb.c:

Functions

ipmb_error ipmb_encode (uint8_t *buffer, ipmi_msg *msg)
 Encode IPMI msg struct to a byte formatted buffer.
 
ipmb_error ipmb_decode (ipmi_msg *msg, uint8_t *buffer, uint8_t len)
 Decodes a buffer and copies to its specific fields in a ipmi_msg struct.
 
ipmb_error ipmb_notify_client (ipmi_msg_cfg *msg_cfg)
 Notifies the client that a new request has arrived and copies the message to its queue. This function receives a message wrapped in a ipmi_msg_cfg struct and copies only the ipmi_msg field to the client queue. Also, if a task has registered its handle in the caller_task field, notify it.
 
void IPMB_TXTask (void *pvParameters)
 IPMB Transmitter Task.
 
void IPMB_RXTask (void *pvParameters)
 IPMB Receiver Task.
 
void ipmb_init (void)
 Initializes the IPMB Layer.
 
ipmb_error ipmb_send_request (ipmi_msg *req)
 Format and send a request via IPMB channel.
 
ipmb_error ipmb_send_response (ipmi_msg *req, ipmi_msg *resp)
 Format and send a response via IPMB channel.
 
ipmb_error ipmb_register_rxqueue (QueueHandle_t *queue)
 Creates and returns a queue in which the client can block to receive the incoming requests.
 
ipmb_error ipmb_assert_chksum (uint8_t *buffer, uint8_t buffer_len)
 Asserts the input message checksums by comparing them with our calculated ones.
 

Variables

uint8_t ipmb_addr = 0xFF
 AMC IPMB Address.
 
QueueHandle_t ipmb_txqueue = NULL
 
QueueHandle_t client_queue = NULL
 

Function Documentation

◆ ipmb_assert_chksum()

ipmb_error ipmb_assert_chksum ( uint8_t * buffer,
uint8_t buffer_len )

Asserts the input message checksums by comparing them with our calculated ones.

Parameters
bufferPointer to the message bytes.
buffer_lenSize of the message.
Return values
ipmb_error_successThe message's checksum bytes are correct, therefore the message is valid.
ipmb_error_hdr_chksumThe header checksum byte is invalid.
ipmb_error_hdr_chksumThe final checksum byte is invalid.

◆ ipmb_decode()

ipmb_error ipmb_decode ( ipmi_msg * msg,
uint8_t * buffer,
uint8_t len )

Decodes a buffer and copies to its specific fields in a ipmi_msg struct.

Parameters
[out]msgPointer to a ipmi_msg struct which will hold the decoded message
[in]bufferPointer to a byte array that will be decoded
[in]lenLength of buffer
Return values
ipmb_error_successThe message was successfully decoded

◆ ipmb_encode()

ipmb_error ipmb_encode ( uint8_t * buffer,
ipmi_msg * msg )

Encode IPMI msg struct to a byte formatted buffer.

This function formats the ipmi_msg struct fields into a byte array, following the specification:

IPMB Messages
REQUEST RESPONSE Bit Len Byte #
Connection rsSA rqSA 8 1
Header NetFN NetFN 6 2
rsLUN rqLUN 2 2
Header Chksum Chksum Chksum 8 3
rqSA rsSA 8 4
Callback Info rqSeq rqSeq 6 5
rqLUN rsLUN 2 5
Command CMD CMD 8 6
Data CC 8 7
Data Data 8*N 7+N
Message Chksum Chksum Checksum 8 7+N+1
Parameters
[out]bufferByte buffer which will hold the formatted message
[in]msgThe message struct to be formatted
Return values
ipmb_error_successThe message was successfully formatted

◆ ipmb_init()

void ipmb_init ( void )

Initializes the IPMB Layer.

Configures the I2C Driver, creates the TX queue for the IPMB Task and both IPMB RX and IPMB TX tasks

◆ ipmb_notify_client()

ipmb_error ipmb_notify_client ( ipmi_msg_cfg * msg_cfg)

Notifies the client that a new request has arrived and copies the message to its queue. This function receives a message wrapped in a ipmi_msg_cfg struct and copies only the ipmi_msg field to the client queue. Also, if a task has registered its handle in the caller_task field, notify it.

Parameters
[in]msg_cfgThe message that arrived, wrapped in the configuration struct ipmi_msg_cfg.
Return values
ipmb_error_successThe message was successfully copied.
ipmb_error_timeoutThe client_queue was full.

◆ ipmb_register_rxqueue()

ipmb_error ipmb_register_rxqueue ( QueueHandle_t * queue)

Creates and returns a queue in which the client can block to receive the incoming requests.

The queue is created and its handler is written at the given pointer (queue). Also keeps a copy of the handler to know where to write the incoming messages.

Parameters
queuePointer to a QueueHandle_t variable which will be written by this function.
Return values
ipmb_error_successThe queue was successfully created.
ipmb_error_queue_creationQueue creation failed due to lack of Heap space.

◆ IPMB_RXTask()

void IPMB_RXTask ( void * pvParameters)

IPMB Receiver Task.

Similarly to IPMB_TXTask, this task remains blocked until a new message is received by the I2C driver. The message passes through checksum checking to assure its integrity.
If the message is a request, we have to check if it's a new one or just a retransmission of the last. In order to do this, the sequential number is tested, since every request has a different one.
Right after that, the arrival time and the message body are stored for future checking and the specified client is notified using ipmb_notify_client.

If we have received a response instead, we match it with the last stored request and also check if the awating request hasn't timed-out yet.

Note
When a malformed message, a response without a request or a repeated request are received, they are just ignored, following the IPMB specifications.
Parameters
pvParametersDefault parameter to FreeRTOS tasks, not used here.
See also
IPMB_TXTask
ipmb_notify_client

◆ ipmb_send_request()

ipmb_error ipmb_send_request ( ipmi_msg * req)

Format and send a request via IPMB channel.

◆ ipmb_send_response()

ipmb_error ipmb_send_response ( ipmi_msg * req,
ipmi_msg * resp )

Format and send a response via IPMB channel.

◆ IPMB_TXTask()

void IPMB_TXTask ( void * pvParameters)

IPMB Transmitter Task.

When ipmb_send_request or ipmb_send_response put a message in ipmb_txqueue, this task unblocks. First step to send a message is differentiating requests from responses. It does this analyzing the parity of NetFN (even for requests, odd for responses).

When sending a response, this task has to check if it matches with the sequence number from the last known request and the amount of time it took to be built (timeout checking). Last step is checking if it has already tried to send this message more than IPMB_MAX_RETRIES value.
After passing all checking, the message is formatted as the IPMB protocol demands and passed down to the I2C driver, using the function xI2CWrite().
If an error comes out of the I2C driver when sending the message, it increases the retry counter in the ipmi_msg_cfg struct and send the message to the front of ipmb_txqueue.
If no errors occurs, the task that put the message in the queue is notified with a success flag.

The proccess is analog when sending a request, but the only check that is made is the retry number. The task skip all checking because, when sending a request, the message is formatted using it's own functions ipmb_send_request or ipmb_send_response and they are guaranteed to put only valid messages in queue.

Parameters
pvParametersDefault parameter to FreeRTOS tasks, not used here.
See also
IPMB_RXTask
ipmb_send_request
ipmb_send_response

Variable Documentation

◆ client_queue

QueueHandle_t client_queue = NULL

◆ ipmb_addr

uint8_t ipmb_addr = 0xFF

AMC IPMB Address.

This variable saves this module's IPMB address read through the Geographical Address pins

See also
get_ipmb_addr

◆ ipmb_txqueue

QueueHandle_t ipmb_txqueue = NULL