drivers/sbus/char/uctrl.c

Source file repositories/reference/linux-study-clean/drivers/sbus/char/uctrl.c

File Facts

System
Linux kernel
Corpus path
drivers/sbus/char/uctrl.c
Extension
.c
Size
10888 bytes
Lines
435
Domain
Driver Families
Bucket
drivers/sbus
Inferred role
Driver Families: operation-table or driver-model contract
Status
pattern 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

static const struct file_operations uctrl_fops = {
	.owner =	THIS_MODULE,
	.unlocked_ioctl =	uctrl_ioctl,
	.open =		uctrl_open,
};

static struct miscdevice uctrl_dev = {
	UCTRL_MINOR,
	"uctrl",
	&uctrl_fops
};

/* Wait for space to write, then write to it */
#define WRITEUCTLDATA(value) \
{ \
  unsigned int i; \
  for (i = 0; i < 10000; i++) { \
      if (UCTRL_STAT_TXNF_STA & sbus_readl(&driver->regs->uctrl_stat)) \
      break; \
  } \
  dprintk(("write data 0x%02x\n", value)); \
  sbus_writel(value, &driver->regs->uctrl_data); \
}

/* Wait for something to read, read it, then clear the bit */
#define READUCTLDATA(value) \
{ \
  unsigned int i; \
  value = 0; \
  for (i = 0; i < 10000; i++) { \
      if ((UCTRL_STAT_RXNE_STA & sbus_readl(&driver->regs->uctrl_stat)) == 0) \
      break; \
    udelay(1); \
  } \
  value = sbus_readl(&driver->regs->uctrl_data); \
  dprintk(("read data 0x%02x\n", value)); \
  sbus_writel(UCTRL_STAT_RXNE_STA, &driver->regs->uctrl_stat); \
}

static void uctrl_do_txn(struct uctrl_driver *driver, struct uctrl_txn *txn)
{
	int stat, incnt, outcnt, bytecnt, intr;
	u32 byte;

	stat = sbus_readl(&driver->regs->uctrl_stat);
	intr = sbus_readl(&driver->regs->uctrl_intr);
	sbus_writel(stat, &driver->regs->uctrl_stat);

	dprintk(("interrupt stat 0x%x int 0x%x\n", stat, intr));

	incnt = txn->inbits;
	outcnt = txn->outbits;
	byte = (txn->opcode << 8);
	WRITEUCTLDATA(byte);

	bytecnt = 0;
	while (incnt > 0) {
		byte = (txn->inbuf[bytecnt] << 8);
		WRITEUCTLDATA(byte);
		incnt--;
		bytecnt++;
	}

	/* Get the ack */
	READUCTLDATA(byte);
	dprintk(("ack was %x\n", (byte >> 8)));

	bytecnt = 0;
	while (outcnt > 0) {
		READUCTLDATA(byte);
		txn->outbuf[bytecnt] = (byte >> 8);
		dprintk(("set byte to %02x\n", byte));
		outcnt--;
		bytecnt++;
	}
}

static void uctrl_get_event_status(struct uctrl_driver *driver)
{
	struct uctrl_txn txn;
	u8 outbits[2];

	txn.opcode = READ_EVENT_STATUS;
	txn.inbits = 0;
	txn.outbits = 2;
	txn.inbuf = NULL;
	txn.outbuf = outbits;

	uctrl_do_txn(driver, &txn);

Annotation

Implementation Notes