drivers/char/ipmi/ipmi_smic_sm.c

Source file repositories/reference/linux-study-clean/drivers/char/ipmi/ipmi_smic_sm.c

File Facts

System
Linux kernel
Corpus path
drivers/char/ipmi/ipmi_smic_sm.c
Extension
.c
Size
15934 bytes
Lines
586
Domain
Driver Families
Bucket
drivers/char
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

struct si_sm_data {
	enum smic_states state;
	struct si_sm_io *io;
	unsigned char	 write_data[MAX_SMIC_WRITE_SIZE];
	int		 write_pos;
	int		 write_count;
	int		 orig_write_count;
	unsigned char	 read_data[MAX_SMIC_READ_SIZE];
	int		 read_pos;
	int		 truncated;
	unsigned int	 error_retries;
	long		 smic_timeout;
};

static unsigned int init_smic_data(struct si_sm_data *smic,
				   struct si_sm_io *io)
{
	smic->state = SMIC_IDLE;
	smic->io = io;
	smic->write_pos = 0;
	smic->write_count = 0;
	smic->orig_write_count = 0;
	smic->read_pos = 0;
	smic->error_retries = 0;
	smic->truncated = 0;
	smic->smic_timeout = SMIC_RETRY_TIMEOUT;

	/* We use 3 bytes of I/O. */
	return 3;
}

static int start_smic_transaction(struct si_sm_data *smic,
				  unsigned char *data, unsigned int size)
{
	unsigned int i;

	if (size < 2)
		return IPMI_REQ_LEN_INVALID_ERR;
	if (size > MAX_SMIC_WRITE_SIZE)
		return IPMI_REQ_LEN_EXCEEDED_ERR;

	if ((smic->state != SMIC_IDLE) && (smic->state != SMIC_HOSED)) {
		dev_warn(smic->io->dev,
			 "SMIC in invalid state %d\n", smic->state);
		return IPMI_NOT_IN_MY_STATE_ERR;
	}

	if (smic_debug & SMIC_DEBUG_MSG) {
		dev_dbg(smic->io->dev, "%s -", __func__);
		for (i = 0; i < size; i++)
			pr_cont(" %02x", data[i]);
		pr_cont("\n");
	}
	smic->error_retries = 0;
	memcpy(smic->write_data, data, size);
	smic->write_count = size;
	smic->orig_write_count = size;
	smic->write_pos = 0;
	smic->read_pos = 0;
	smic->state = SMIC_START_OP;
	smic->smic_timeout = SMIC_RETRY_TIMEOUT;
	return 0;
}

static int smic_get_result(struct si_sm_data *smic,
			   unsigned char *data, unsigned int length)
{
	int i;

	if (smic_debug & SMIC_DEBUG_MSG) {
		dev_dbg(smic->io->dev, "smic_get result -");
		for (i = 0; i < smic->read_pos; i++)
			pr_cont(" %02x", smic->read_data[i]);
		pr_cont("\n");
	}
	if (length < smic->read_pos) {
		smic->read_pos = length;
		smic->truncated = 1;
	}
	memcpy(data, smic->read_data, smic->read_pos);

	if ((length >= 3) && (smic->read_pos < 3)) {
		data[2] = IPMI_ERR_UNSPECIFIED;
		smic->read_pos = 3;
	}
	if (smic->truncated) {
		data[2] = IPMI_ERR_MSG_TRUNCATED;
		smic->truncated = 0;
	}
	return smic->read_pos;

Annotation

Implementation Notes