/* * IPMB driver to receive a request and send a response * * Copyright (C) 2019 Mellanox Techologies, Ltd. * * This was inspired by Brendan Higgins' ipmi-bmc-bt-i2c driver.
*/
/* Check i2c block transfer vs smbus */ if (ipmb_dev->is_i2c_protocol) {
ret = ipmb_i2c_write(ipmb_dev->client, msg, rq_sa); return (ret == 1) ? count : ret;
}
/* * subtract rq_sa and netf_rq_lun from the length of the msg. Fill the * temporary client. Note that its use is an exception for IPMI.
*/
msg_len = msg[IPMB_MSG_LEN_IDX] - SMBUS_MSG_HEADER_LENGTH;
temp_client = kmemdup(ipmb_dev->client, sizeof(*temp_client), GFP_KERNEL); if (!temp_client) return -ENOMEM;
temp_client->addr = rq_sa;
ret = i2c_smbus_write_block_data(temp_client, netf_rq_lun, msg_len,
msg + SMBUS_MSG_IDX_OFFSET);
kfree(temp_client);
static u8 ipmb_verify_checksum1(struct ipmb_dev *ipmb_dev, u8 rs_sa)
{ /* The 8 lsb of the sum is 0 when the checksum is valid */ return (rs_sa + ipmb_dev->request.netfn_rs_lun +
ipmb_dev->request.checksum1);
}
/* * Verify if message has proper ipmb header with minimum length * and correct checksum byte.
*/ staticbool is_ipmb_msg(struct ipmb_dev *ipmb_dev, u8 rs_sa)
{ if ((ipmb_dev->msg_idx >= IPMB_REQUEST_LEN_MIN) &&
(!ipmb_verify_checksum1(ipmb_dev, rs_sa))) returntrue;
returnfalse;
}
/* * The IPMB protocol only supports I2C Writes so there is no need * to support I2C_SLAVE_READ* events. * This i2c callback function only monitors IPMB request messages * and adds them in a queue, so that they can be handled by * receive_ipmb_request.
*/ staticint ipmb_slave_cb(struct i2c_client *client, enum i2c_slave_event event, u8 *val)
{ struct ipmb_dev *ipmb_dev = i2c_get_clientdata(client);
u8 *buf = (u8 *)&ipmb_dev->request; unsignedlong flags;
/* * At index 0, ipmb_msg stores the length of msg, * skip it for now. * The len will be populated once the whole * buf is populated. * * The I2C bus driver's responsibility is to pass the * data bytes to the backend driver; it does not * forward the i2c slave address. * Since the first byte in the IPMB message is the * address of the responder, it is the responsibility * of the IPMB driver to format the message properly. * So this driver prepends the address of the responder * to the received i2c data before the request message * is handled in userland.
*/
buf[++ipmb_dev->msg_idx] = GET_8BIT_ADDR(client->addr); break;
case I2C_SLAVE_WRITE_RECEIVED: if (ipmb_dev->msg_idx >= sizeof(struct ipmb_msg) - 1) break;
buf[++ipmb_dev->msg_idx] = *val; break;
case I2C_SLAVE_STOP:
ipmb_dev->request.len = ipmb_dev->msg_idx; if (is_ipmb_msg(ipmb_dev, GET_8BIT_ADDR(client->addr)))
ipmb_handle_request(ipmb_dev); break;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.