openMMC
Open Source Modular MMC for AMCs
|
#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"
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 |
ipmb_error ipmb_assert_chksum | ( | uint8_t * | buffer, |
uint8_t | buffer_len ) |
Asserts the input message checksums by comparing them with our calculated ones.
buffer | Pointer to the message bytes. |
buffer_len | Size of the message. |
ipmb_error_success | The message's checksum bytes are correct, therefore the message is valid. |
ipmb_error_hdr_chksum | The header checksum byte is invalid. |
ipmb_error_hdr_chksum | The final checksum byte is invalid. |
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.
[out] | msg | Pointer to a ipmi_msg struct which will hold the decoded message |
[in] | buffer | Pointer to a byte array that will be decoded |
[in] | len | Length of buffer |
ipmb_error_success | The message was successfully decoded |
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:
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 |
[out] | buffer | Byte buffer which will hold the formatted message |
[in] | msg | The message struct to be formatted |
ipmb_error_success | The message was successfully formatted |
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_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.
[in] | msg_cfg | The message that arrived, wrapped in the configuration struct ipmi_msg_cfg. |
ipmb_error_success | The message was successfully copied. |
ipmb_error_timeout | The client_queue was full. |
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.
queue | Pointer to a QueueHandle_t variable which will be written by this function. |
ipmb_error_success | The queue was successfully created. |
ipmb_error_queue_creation | Queue creation failed due to lack of Heap space. |
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.
pvParameters | Default parameter to FreeRTOS tasks, not used here. |
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.
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.
pvParameters | Default parameter to FreeRTOS tasks, not used here. |
QueueHandle_t client_queue = NULL |
uint8_t ipmb_addr = 0xFF |
AMC IPMB Address.
This variable saves this module's IPMB address read through the Geographical Address pins
QueueHandle_t ipmb_txqueue = NULL |