From: H Hartley Sweeten Date: Tue, 6 Nov 2012 17:04:56 +0000 (-0700) Subject: staging: comedi: addi_apci_3120: fix digital output 'insn_bits' function X-Git-Url: http://drtracing.org/?a=commitdiff_plain;h=66511843c55b1124a8527b041cdde4bd1ae75422;p=deliverable%2Flinux.git staging: comedi: addi_apci_3120: fix digital output 'insn_bits' function This driver does not follow the comedi API. The digital output 'insn_bits' function is passed a mask value in data[0] indicating which output bits in data[1] are changing. The function is then supposed to update the outputs accordingly and then return the current state of the outputs in data[1]. Currently this driver uses the 'insn_write' function to update either a single or all the output channels. And it uses the 'insn_bits' function to read either a single or all the output channel states. Fix the 'insn_bits' function so it works like the comedi core expects. The core can then use the function to emulate the 'insn_read' and 'insn_write' functions for individual channels. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c index d5dea349f102..106b286724f9 100644 --- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c +++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c @@ -2230,106 +2230,29 @@ static int i_APCI3120_InsnConfigDigitalOutput(struct comedi_device *dev, return insn->n; } -/* - * Write diatal output port - * - * data[0] = Value to be written - * data[1] = 1 Set digital o/p ON - * = 2 Set digital o/p OFF with memory ON - */ -static int i_APCI3120_InsnBitsDigitalOutput(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, - unsigned int *data) +static int apci3120_do_insn_bits(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data) { - const struct addi_board *this_board = comedi_board(dev); struct addi_private *devpriv = dev->private; + unsigned int mask = data[0]; + unsigned int bits = data[1]; + unsigned int val; - if ((data[0] > this_board->i_DoMaxdata) || (data[0] < 0)) { - - comedi_error(dev, "Data is not valid !!! \n"); - return -EINVAL; - } - - switch (data[1]) { - case 1: - data[0] = (data[0] << 4) | devpriv->b_DigitalOutputRegister; - break; - - case 2: - data[0] = data[0]; - break; - default: - printk("\nThe parameter passed is in error \n"); - return -EINVAL; - } /* switch(data[1]) */ - outb(data[0], devpriv->iobase + APCI3120_DIGITAL_OUTPUT); - - devpriv->b_DigitalOutputRegister = data[0] & 0xF0; - - return insn->n; - -} + /* The do channels are bits 7:4 of the do register */ + val = devpriv->b_DigitalOutputRegister >> 4; + if (mask) { + val &= ~mask; + val |= (bits & mask); + devpriv->b_DigitalOutputRegister = val << 4; -/* - * Write digital output - * - * data[0] = Value to be written - * data[1] = 1 Set digital o/p ON - * = 2 Set digital o/p OFF with memory ON - */ -static int i_APCI3120_InsnWriteDigitalOutput(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, - unsigned int *data) -{ - const struct addi_board *this_board = comedi_board(dev); - struct addi_private *devpriv = dev->private; - unsigned int ui_Temp1; - unsigned int ui_NoOfChannel = CR_CHAN(insn->chanspec); /* get the channel */ - - if ((data[0] != 0) && (data[0] != 1)) { - comedi_error(dev, - "Not a valid Data !!! ,Data should be 1 or 0\n"); - return -EINVAL; - } - if (ui_NoOfChannel > this_board->i_NbrDoChannel - 1) { - comedi_error(dev, - "This board doesn't have specified channel !!! \n"); - return -EINVAL; + outb(val << 4, devpriv->iobase + APCI3120_DIGITAL_OUTPUT); } - switch (data[1]) { - case 1: - data[0] = (data[0] << ui_NoOfChannel); -/* ES05 data[0]=(data[0]<<4)|ui_Temp; */ - data[0] = (data[0] << 4) | devpriv->b_DigitalOutputRegister; - break; - - case 2: - data[0] = ~data[0] & 0x1; - ui_Temp1 = 1; - ui_Temp1 = ui_Temp1 << ui_NoOfChannel; - ui_Temp1 = ui_Temp1 << 4; -/* ES05 ui_Temp=ui_Temp|ui_Temp1; */ - devpriv->b_DigitalOutputRegister = - devpriv->b_DigitalOutputRegister | ui_Temp1; - - data[0] = (data[0] << ui_NoOfChannel) ^ 0xf; - data[0] = data[0] << 4; -/* ES05 data[0]=data[0]& ui_Temp; */ - data[0] = data[0] & devpriv->b_DigitalOutputRegister; - break; - default: - printk("\nThe parameter passed is in error \n"); - return -EINVAL; - } /* switch(data[1]) */ - outb(data[0], devpriv->iobase + APCI3120_DIGITAL_OUTPUT); + data[1] = val; -/* ES05 ui_Temp=data[0] & 0xf0; */ - devpriv->b_DigitalOutputRegister = data[0] & 0xf0; return insn->n; - } static int i_APCI3120_InsnWriteAnalogOutput(struct comedi_device *dev, diff --git a/drivers/staging/comedi/drivers/addi_apci_3120.c b/drivers/staging/comedi/drivers/addi_apci_3120.c index bd53a0cb61c7..1326a2ec42b5 100644 --- a/drivers/staging/comedi/drivers/addi_apci_3120.c +++ b/drivers/staging/comedi/drivers/addi_apci_3120.c @@ -194,8 +194,7 @@ static int apci3120_attach_pci(struct comedi_device *dev, /* insn_config - for digital output memory */ s->insn_config = i_APCI3120_InsnConfigDigitalOutput; - s->insn_write = i_APCI3120_InsnWriteDigitalOutput; - s->insn_bits = i_APCI3120_InsnBitsDigitalOutput; + s->insn_bits = apci3120_do_insn_bits; /* Allocate and Initialise Timer Subdevice Structures */ s = &dev->subdevices[4];