Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d22418b0 authored by H Hartley Sweeten's avatar H Hartley Sweeten Committed by Greg Kroah-Hartman
Browse files

staging: comedi: refactor unioxx5 driver to remove forward declarations



Refactor of the unioxx5 comedi driver to remove all the forward
declarations.

Signed-off-by: default avatarH Hartley Sweeten <hsweeten@visionengravers.com>
Cc: Ian Abbott <abbotti@mev.co.uk>
Cc: Mori Hess <fmhess@users.sourceforge.net>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 247e9cff
Loading
Loading
Loading
Loading
+181 −209
Original line number Diff line number Diff line
@@ -83,26 +83,189 @@ struct unioxx5_subd_priv {
	unsigned char usp_prev_cn_val[3];	/* previous channel value */
};

static int unioxx5_subdev_write(struct comedi_device *dev,
				struct comedi_subdevice *subdev,
				struct comedi_insn *insn, unsigned int *data);
static int unioxx5_subdev_read(struct comedi_device *dev,
			       struct comedi_subdevice *subdev,
			       struct comedi_insn *insn, unsigned int *data);
static int unioxx5_insn_config(struct comedi_device *dev,
			       struct comedi_subdevice *subdev,
			       struct comedi_insn *insn, unsigned int *data);
static int __unioxx5_digital_write(struct unioxx5_subd_priv *usp,
				   unsigned int *data, int channel, int minor);
static int __unioxx5_define_chan_offset(int chan_num)
{

	if (chan_num < 0 || chan_num > 23)
		return -1;

	return (chan_num >> 3) + 1;
}

#if 0				/* not used? */
static void __unioxx5_digital_config(struct unioxx5_subd_priv *usp, int mode)
{
	int i, mask;

	mask = (mode == ALL_2_OUTPUT) ? 0xFF : 0x00;
	printk("COMEDI: mode = %d\n", mask);

	outb(1, usp->usp_iobase + 0);

	for (i = 0; i < 3; i++)
		outb(mask, usp->usp_iobase + i);

	outb(0, usp->usp_iobase + 0);
}
#endif

/* configure channels for analog i/o (even to output, odd to input) */
static void __unioxx5_analog_config(struct unioxx5_subd_priv *usp, int channel)
{
	int chan_a, chan_b, conf, channel_offset;

	channel_offset = __unioxx5_define_chan_offset(channel);
	conf = usp->usp_prev_cn_val[channel_offset - 1];
	chan_a = chan_b = 1;

	/* setting channel A and channel B mask */
	if (channel % 2 == 0) {
		chan_a <<= channel & 0x07;
		chan_b <<= (channel + 1) & 0x07;
	} else {
		chan_a <<= (channel - 1) & 0x07;
		chan_b <<= channel & 0x07;
	}

	conf |= chan_a;		/* even channel ot output */
	conf &= ~chan_b;	/* odd channel to input */

	outb(1, usp->usp_iobase + 0);
	outb(conf, usp->usp_iobase + channel_offset);
	outb(0, usp->usp_iobase + 0);

	usp->usp_prev_cn_val[channel_offset - 1] = conf;
}

static int __unioxx5_digital_read(struct unioxx5_subd_priv *usp,
				  unsigned int *data, int channel, int minor);
/* static void __unioxx5_digital_config(struct unioxx5_subd_priv* usp, int mode); */
static int __unioxx5_analog_write(struct unioxx5_subd_priv *usp,
				  unsigned int *data, int channel, int minor);
				  unsigned int *data, int channel, int minor)
{
	int channel_offset, mask = 1 << (channel & 0x07);

	channel_offset = __unioxx5_define_chan_offset(channel);
	if (channel_offset < 0) {
		printk(KERN_ERR
		       "comedi%d: undefined channel %d. channel range is 0 .. 23\n",
		       minor, channel);
		return 0;
	}

	*data = inb(usp->usp_iobase + channel_offset);
	*data &= mask;

	/* correct the read value to 0 or 1 */
	if (channel_offset > 1)
		channel -= 2 << channel_offset;
	*data >>= channel;
	return 1;
}

static int __unioxx5_analog_read(struct unioxx5_subd_priv *usp,
				 unsigned int *data, int channel, int minor);
static int __unioxx5_define_chan_offset(int chan_num);
static void __unioxx5_analog_config(struct unioxx5_subd_priv *usp, int channel);
				 unsigned int *data, int channel, int minor)
{
	int module_no, read_ch;
	char control;

	module_no = channel / 2;
	read_ch = channel % 2;	/* depend on type of channel (A or B) */

	/* defining if given module can work on input */
	if (usp->usp_module_type[module_no] & MODULE_OUTPUT_MASK) {
		printk(KERN_ERR
		       "comedi%d: module in position %d with id 0x%02x is for output only",
		       minor, module_no, usp->usp_module_type[module_no]);
		return 0;
	}

	__unioxx5_analog_config(usp, channel);
	/* sends module number to card(1 .. 12) */
	outb(module_no + 1, usp->usp_iobase + 5);
	outb('V', usp->usp_iobase + 6);	/* sends to module (V)erify command */
	control = inb(usp->usp_iobase);	/* get control register byte */

	/* waits while reading four bytes will be allowed */
	while (!((control = inb(usp->usp_iobase + 0)) & Rx4CA))
		;

	/* if four bytes readding error occurs - return 0(false) */
	if ((control & Rx4CA_ERR_MASK)) {
		printk("COMEDI: 4 bytes error\n");
		return 0;
	}

	if (read_ch)
		*data = inw(usp->usp_iobase + 6);	/* channel B */
	else
		*data = inw(usp->usp_iobase + 4);	/* channel A */

	return 1;
}

static int __unioxx5_digital_write(struct unioxx5_subd_priv *usp,
				   unsigned int *data, int channel, int minor)
{
	int channel_offset, val;
	int mask = 1 << (channel & 0x07);

	channel_offset = __unioxx5_define_chan_offset(channel);
	if (channel_offset < 0) {
		printk(KERN_ERR
		       "comedi%d: undefined channel %d. channel range is 0 .. 23\n",
		       minor, channel);
		return 0;
	}

	/* getting previous written value */
	val = usp->usp_prev_wr_val[channel_offset - 1];

	if (*data)
		val |= mask;
	else
		val &= ~mask;

	outb(val, usp->usp_iobase + channel_offset);
	/* saving new written value */
	usp->usp_prev_wr_val[channel_offset - 1] = val;

	return 1;
}

static int __unioxx5_analog_write(struct unioxx5_subd_priv *usp,
				  unsigned int *data, int channel, int minor)
{
	int module, i;

	module = channel / 2;	/* definig module number(0 .. 11) */
	i = (channel % 2) << 1;	/* depends on type of channel (A or B) */

	/* defining if given module can work on output */
	if (!(usp->usp_module_type[module] & MODULE_OUTPUT_MASK)) {
		printk(KERN_ERR
		       "comedi%d: module in position %d with id 0x%0x is for input only!\n",
		       minor, module, usp->usp_module_type[module]);
		return 0;
	}

	__unioxx5_analog_config(usp, channel);
	/* saving minor byte */
	usp->usp_extra_data[module][i++] = (unsigned char)(*data & 0x00FF);
	/* saving major byte */
	usp->usp_extra_data[module][i] = (unsigned char)((*data & 0xFF00) >> 8);

	/* while(!((inb(usp->usp_iobase + 0)) & TxBE)); */
	/* sending module number to card(1 .. 12) */
	outb(module + 1, usp->usp_iobase + 5);
	outb('W', usp->usp_iobase + 6);	/* sends (W)rite command to module */

	/* sending for bytes to module(one byte per cycle iteration) */
	for (i = 0; i < 4; i++) {
		while (!((inb(usp->usp_iobase + 0)) & TxBE))
			;	/* waits while writting will be allowed */
		outb(usp->usp_extra_data[module][i], usp->usp_iobase + 6);
	}

	return 1;
}

static int unioxx5_subdev_read(struct comedi_device *dev,
			       struct comedi_subdevice *subdev,
@@ -275,197 +438,6 @@ static int __unioxx5_subdev_init(struct comedi_subdevice *subdev,
	return 0;
}

static int __unioxx5_digital_write(struct unioxx5_subd_priv *usp,
				   unsigned int *data, int channel, int minor)
{
	int channel_offset, val;
	int mask = 1 << (channel & 0x07);

	channel_offset = __unioxx5_define_chan_offset(channel);
	if (channel_offset < 0) {
		printk(KERN_ERR
		       "comedi%d: undefined channel %d. channel range is 0 .. 23\n",
		       minor, channel);
		return 0;
	}

	/* getting previous written value */
	val = usp->usp_prev_wr_val[channel_offset - 1];

	if (*data)
		val |= mask;
	else
		val &= ~mask;

	outb(val, usp->usp_iobase + channel_offset);
	/* saving new written value */
	usp->usp_prev_wr_val[channel_offset - 1] = val;

	return 1;
}

/* function for digital reading */
static int __unioxx5_digital_read(struct unioxx5_subd_priv *usp,
				  unsigned int *data, int channel, int minor)
{
	int channel_offset, mask = 1 << (channel & 0x07);

	channel_offset = __unioxx5_define_chan_offset(channel);
	if (channel_offset < 0) {
		printk(KERN_ERR
		       "comedi%d: undefined channel %d. channel range is 0 .. 23\n",
		       minor, channel);
		return 0;
	}

	*data = inb(usp->usp_iobase + channel_offset);
	*data &= mask;

	if (channel_offset > 1)
		channel -= 2 << channel_offset;	/* this operation is created for correct readed value to 0 or 1 */
	*data >>= channel;
	return 1;
}

#if 0				/* not used? */
static void __unioxx5_digital_config(struct unioxx5_subd_priv *usp, int mode)
{
	int i, mask;

	mask = (mode == ALL_2_OUTPUT) ? 0xFF : 0x00;
	printk("COMEDI: mode = %d\n", mask);

	outb(1, usp->usp_iobase + 0);

	for (i = 0; i < 3; i++)
		outb(mask, usp->usp_iobase + i);

	outb(0, usp->usp_iobase + 0);
}
#endif

static int __unioxx5_analog_write(struct unioxx5_subd_priv *usp,
				  unsigned int *data, int channel, int minor)
{
	int module, i;

	module = channel / 2;	/* definig module number(0 .. 11) */
	i = (channel % 2) << 1;	/* depends on type of channel (A or B) */

	/* defining if given module can work on output */
	if (!(usp->usp_module_type[module] & MODULE_OUTPUT_MASK)) {
		printk(KERN_ERR
		       "comedi%d: module in position %d with id 0x%0x is for input only!\n",
		       minor, module, usp->usp_module_type[module]);
		return 0;
	}

	__unioxx5_analog_config(usp, channel);
	/* saving minor byte */
	usp->usp_extra_data[module][i++] = (unsigned char)(*data & 0x00FF);
	/* saving major byte */
	usp->usp_extra_data[module][i] = (unsigned char)((*data & 0xFF00) >> 8);

	/* while(!((inb(usp->usp_iobase + 0)) & TxBE)); */
	/* sending module number to card(1 .. 12) */
	outb(module + 1, usp->usp_iobase + 5);
	outb('W', usp->usp_iobase + 6);	/* sends (W)rite command to module */

	/* sending for bytes to module(one byte per cycle iteration) */
	for (i = 0; i < 4; i++) {
		while (!((inb(usp->usp_iobase + 0)) & TxBE))
			;	/* waits while writting will be allowed */
		outb(usp->usp_extra_data[module][i], usp->usp_iobase + 6);
	}

	return 1;
}

static int __unioxx5_analog_read(struct unioxx5_subd_priv *usp,
				 unsigned int *data, int channel, int minor)
{
	int module_no, read_ch;
	char control;

	module_no = channel / 2;
	read_ch = channel % 2;	/* depend on type of channel (A or B) */

	/* defining if given module can work on input */
	if (usp->usp_module_type[module_no] & MODULE_OUTPUT_MASK) {
		printk(KERN_ERR
		       "comedi%d: module in position %d with id 0x%02x is for output only",
		       minor, module_no, usp->usp_module_type[module_no]);
		return 0;
	}

	__unioxx5_analog_config(usp, channel);
	/* sends module number to card(1 .. 12) */
	outb(module_no + 1, usp->usp_iobase + 5);
	outb('V', usp->usp_iobase + 6);	/* sends to module (V)erify command */
	control = inb(usp->usp_iobase);	/* get control register byte */

	/* waits while reading four bytes will be allowed */
	while (!((control = inb(usp->usp_iobase + 0)) & Rx4CA))
		;

	/* if four bytes readding error occurs - return 0(false) */
	if ((control & Rx4CA_ERR_MASK)) {
		printk("COMEDI: 4 bytes error\n");
		return 0;
	}

	if (read_ch)
		*data = inw(usp->usp_iobase + 6);	/* channel B */
	else
		*data = inw(usp->usp_iobase + 4);	/* channel A */

	return 1;
}

/* configure channels for analog i/o (even to output, odd to input) */
static void __unioxx5_analog_config(struct unioxx5_subd_priv *usp, int channel)
{
	int chan_a, chan_b, conf, channel_offset;

	channel_offset = __unioxx5_define_chan_offset(channel);
	conf = usp->usp_prev_cn_val[channel_offset - 1];
	chan_a = chan_b = 1;

	/* setting channel A and channel B mask */
	if (channel % 2 == 0) {
		chan_a <<= channel & 0x07;
		chan_b <<= (channel + 1) & 0x07;
	} else {
		chan_a <<= (channel - 1) & 0x07;
		chan_b <<= channel & 0x07;
	}

	conf |= chan_a;		/* even channel ot output */
	conf &= ~chan_b;	/* odd channel to input */

	outb(1, usp->usp_iobase + 0);
	outb(conf, usp->usp_iobase + channel_offset);
	outb(0, usp->usp_iobase + 0);

	usp->usp_prev_cn_val[channel_offset - 1] = conf;
}

/*                                                    *\
 * this function defines if the given channel number  *
 * enters in default numeric interspace(from 0 to 23) *
 * and it returns address offset for usage needed     *
 * channel.                                           *
\*                                                    */

static int __unioxx5_define_chan_offset(int chan_num)
{

	if (chan_num < 0 || chan_num > 23)
		return -1;

	return (chan_num >> 3) + 1;
}

static int unioxx5_attach(struct comedi_device *dev,
			  struct comedi_devconfig *it)
{