static int ni_pcidio_cmd()

in drivers/ni_pcidio.c [617:729]


static int ni_pcidio_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
{
	struct nidio96_private *devpriv = dev->private;
	struct comedi_cmd *cmd = &s->async->cmd;

	/* XXX configure ports for input */
	writel(0x0000, dev->mmio + PORT_PIN_DIRECTIONS(0));

	if (1) {
		/* enable fifos A B C D */
		writeb(0x0f, dev->mmio + DATA_PATH);

		/* set transfer width a 32 bits */
		writeb(TRANSFER_WIDTH(0) | TRANSFER_LENGTH(0),
		       dev->mmio + TRANSFER_SIZE_CONTROL);
	} else {
		writeb(0x03, dev->mmio + DATA_PATH);
		writeb(TRANSFER_WIDTH(3) | TRANSFER_LENGTH(0),
		       dev->mmio + TRANSFER_SIZE_CONTROL);
	}

	/* protocol configuration */
	if (cmd->scan_begin_src == TRIG_TIMER) {
		/* page 4-5, "input with internal REQs" */
		writeb(0, dev->mmio + OP_MODE);
		writeb(0x00, dev->mmio + CLOCK_REG);
		writeb(1, dev->mmio + SEQUENCE);
		writeb(0x04, dev->mmio + REQ_REG);
		writeb(4, dev->mmio + BLOCK_MODE);
		writeb(3, dev->mmio + LINE_POLARITIES);
		writeb(0xc0, dev->mmio + ACK_SER);
		writel(ni_pcidio_ns_to_timer(&cmd->scan_begin_arg,
					     CMDF_ROUND_NEAREST),
		       dev->mmio + START_DELAY);
		writeb(1, dev->mmio + REQ_DELAY);
		writeb(1, dev->mmio + REQ_NOT_DELAY);
		writeb(1, dev->mmio + ACK_DELAY);
		writeb(0x0b, dev->mmio + ACK_NOT_DELAY);
		writeb(0x01, dev->mmio + DATA_1_DELAY);
		/*
		 * manual, page 4-5:
		 * CLOCK_SPEED comment is incorrectly listed on DAQ_OPTIONS
		 */
		writew(0, dev->mmio + CLOCK_SPEED);
		writeb(0, dev->mmio + DAQ_OPTIONS);
	} else {
		/* TRIG_EXT */
		/* page 4-5, "input with external REQs" */
		writeb(0, dev->mmio + OP_MODE);
		writeb(0x00, dev->mmio + CLOCK_REG);
		writeb(0, dev->mmio + SEQUENCE);
		writeb(0x00, dev->mmio + REQ_REG);
		writeb(4, dev->mmio + BLOCK_MODE);
		if (!(cmd->scan_begin_arg & CR_INVERT))	/* Leading Edge */
			writeb(0, dev->mmio + LINE_POLARITIES);
		else					/* Trailing Edge */
			writeb(2, dev->mmio + LINE_POLARITIES);
		writeb(0x00, dev->mmio + ACK_SER);
		writel(1, dev->mmio + START_DELAY);
		writeb(1, dev->mmio + REQ_DELAY);
		writeb(1, dev->mmio + REQ_NOT_DELAY);
		writeb(1, dev->mmio + ACK_DELAY);
		writeb(0x0C, dev->mmio + ACK_NOT_DELAY);
		writeb(0x10, dev->mmio + DATA_1_DELAY);
		writew(0, dev->mmio + CLOCK_SPEED);
		writeb(0x60, dev->mmio + DAQ_OPTIONS);
	}

	if (cmd->stop_src == TRIG_COUNT) {
		writel(cmd->stop_arg,
		       dev->mmio + TRANSFER_COUNT);
	} else {
		/* XXX */
	}

#ifdef USE_DMA
	writeb(CLEAR_PRIMARY_TC | CLEAR_SECONDARY_TC,
	       dev->mmio + GROUP_1_FIRST_CLEAR);

	{
		int retval = setup_mite_dma(dev, s);

		if (retval)
			return retval;
	}
#else
	writeb(0x00, dev->mmio + DMA_LINE_CONTROL_GROUP1);
#endif
	writeb(0x00, dev->mmio + DMA_LINE_CONTROL_GROUP2);

	/* clear and enable interrupts */
	writeb(0xff, dev->mmio + GROUP_1_FIRST_CLEAR);
	/* writeb(CLEAR_EXPIRED, dev->mmio+GROUP_1_SECOND_CLEAR); */

	writeb(INT_EN, dev->mmio + INTERRUPT_CONTROL);
	writeb(0x03, dev->mmio + MASTER_DMA_AND_INTERRUPT_CONTROL);

	if (cmd->stop_src == TRIG_NONE) {
		devpriv->OP_MODEBits = DATA_LATCHING(0) | RUN_MODE(7);
	} else {		/* TRIG_TIMER */
		devpriv->OP_MODEBits = NUMBERED | RUN_MODE(7);
	}
	if (cmd->start_src == TRIG_NOW) {
		/* start */
		writeb(devpriv->OP_MODEBits, dev->mmio + OP_MODE);
		s->async->inttrig = NULL;
	} else {
		/* TRIG_INT */
		s->async->inttrig = ni_pcidio_inttrig;
	}

	return 0;
}