Exemplo n.º 1
0
static int
wbcir_tx(struct rc_dev *dev, unsigned *b, unsigned count)
{
	struct wbcir_data *data = dev->priv;
	unsigned *buf;
	unsigned i;
	unsigned long flags;

	buf = kmalloc_array(count, sizeof(*b), GFP_KERNEL);
	if (!buf)
		return -ENOMEM;

	/* Convert values to multiples of 10us */
	for (i = 0; i < count; i++)
		buf[i] = DIV_ROUND_CLOSEST(b[i], 10);

	/* Not sure if this is possible, but better safe than sorry */
	spin_lock_irqsave(&data->spinlock, flags);
	if (data->txstate != WBCIR_TXSTATE_INACTIVE) {
		spin_unlock_irqrestore(&data->spinlock, flags);
		kfree(buf);
		return -EBUSY;
	}

	/* Fill the TX fifo once, the irq handler will do the rest */
	data->txbuf = buf;
	data->txlen = count;
	data->txoff = 0;
	wbcir_irq_tx(data);

	/* We're done */
	spin_unlock_irqrestore(&data->spinlock, flags);
	return count;
}
Exemplo n.º 2
0
static int
wbcir_tx(struct rc_dev *dev, int *buf, u32 bufsize)
{
	struct wbcir_data *data = dev->priv;
	u32 count;
	unsigned i;
	unsigned long flags;

	/* bufsize has been sanity checked by the caller */
	count = bufsize / sizeof(int);

	/* Not sure if this is possible, but better safe than sorry */
	spin_lock_irqsave(&data->spinlock, flags);
	if (data->txstate != WBCIR_TXSTATE_INACTIVE) {
		spin_unlock_irqrestore(&data->spinlock, flags);
		return -EBUSY;
	}

	/* Convert values to multiples of 10us */
	for (i = 0; i < count; i++)
		buf[i] = DIV_ROUND_CLOSEST(buf[i], 10);

	/* Fill the TX fifo once, the irq handler will do the rest */
	data->txbuf = buf;
	data->txlen = count;
	data->txoff = 0;
	wbcir_irq_tx(data);

	/* Wait for the TX to complete */
	while (data->txstate == WBCIR_TXSTATE_ACTIVE) {
		spin_unlock_irqrestore(&data->spinlock, flags);
		wait_event(data->txwaitq, data->txstate != WBCIR_TXSTATE_ACTIVE);
		spin_lock_irqsave(&data->spinlock, flags);
	}

	/* We're done */
	if (data->txstate == WBCIR_TXSTATE_ERROR)
		count = -EAGAIN;
	data->txstate = WBCIR_TXSTATE_INACTIVE;
	data->txbuf = NULL;
	spin_unlock_irqrestore(&data->spinlock, flags);

	return count;
}
static int
wbcir_tx(struct rc_dev *dev, unsigned *buf, unsigned count)
{
	struct wbcir_data *data = dev->priv;
	unsigned i;
	unsigned long flags;

	
	spin_lock_irqsave(&data->spinlock, flags);
	if (data->txstate != WBCIR_TXSTATE_INACTIVE) {
		spin_unlock_irqrestore(&data->spinlock, flags);
		return -EBUSY;
	}

	
	for (i = 0; i < count; i++)
		buf[i] = DIV_ROUND_CLOSEST(buf[i], 10);

	
	data->txbuf = buf;
	data->txlen = count;
	data->txoff = 0;
	wbcir_irq_tx(data);

	
	while (data->txstate == WBCIR_TXSTATE_ACTIVE) {
		spin_unlock_irqrestore(&data->spinlock, flags);
		wait_event(data->txwaitq, data->txstate != WBCIR_TXSTATE_ACTIVE);
		spin_lock_irqsave(&data->spinlock, flags);
	}

	
	if (data->txstate == WBCIR_TXSTATE_ERROR)
		count = -EAGAIN;
	data->txstate = WBCIR_TXSTATE_INACTIVE;
	data->txbuf = NULL;
	spin_unlock_irqrestore(&data->spinlock, flags);

	return count;
}
Exemplo n.º 4
0
static irqreturn_t
wbcir_irq_handler(int irqno, void *cookie)
{
	struct pnp_dev *device = cookie;
	struct wbcir_data *data = pnp_get_drvdata(device);
	unsigned long flags;
	u8 status;

	spin_lock_irqsave(&data->spinlock, flags);
	wbcir_select_bank(data, WBCIR_BANK_0);
	status = inb(data->sbase + WBCIR_REG_SP3_EIR);
	status &= data->irqmask;

	if (!status) {
		spin_unlock_irqrestore(&data->spinlock, flags);
		return IRQ_NONE;
	}

	if (status & WBCIR_IRQ_ERR) {
		/* RX overflow? (read clears bit) */
		if (inb(data->sbase + WBCIR_REG_SP3_LSR) & WBCIR_RX_OVERRUN) {
			data->rxstate = WBCIR_RXSTATE_ERROR;
			ir_raw_event_reset(data->dev);
		}

		/* TX underflow? */
		if (inb(data->sbase + WBCIR_REG_SP3_ASCR) & WBCIR_TX_UNDERRUN)
			data->txstate = WBCIR_TXSTATE_ERROR;
	}

	if (status & WBCIR_IRQ_RX)
		wbcir_irq_rx(data, device);

	if (status & (WBCIR_IRQ_TX_LOW | WBCIR_IRQ_TX_EMPTY))
		wbcir_irq_tx(data);

	spin_unlock_irqrestore(&data->spinlock, flags);
	return IRQ_HANDLED;
}