From: H Hartley Sweeten Date: Tue, 6 Nov 2012 17:03:23 +0000 (-0700) Subject: staging: comedi: addi_apci_3200: fix digital output 'insn_bits' function X-Git-Url: https://git.karo-electronics.de/?a=commitdiff_plain;h=2e7be560b7d42413b94d46a5ada25fb0a8f732fc;p=linux-beck.git staging: comedi: addi_apci_3200: 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_apci3200.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c index 2f23ec9cef84..1c2f26d66b4d 100644 --- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c +++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c @@ -648,156 +648,25 @@ static int i_APCI3200_ConfigDigitalOutput(struct comedi_device *dev, return insn->n; } -/* - * Writes To the digital Output Subdevice - * - * data[0] = Value to output - * data[1] = 0 o/p single channel - * = 1 o/p port - * data[2] = port no - * data[3] = 0 set the digital o/p on - * = 1 set the digital o/p off - */ -static int i_APCI3200_WriteDigitalOutput(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, - unsigned int *data) +static int apci3200_do_insn_bits(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data) { struct addi_private *devpriv = dev->private; - unsigned int ui_Temp = 0, ui_Temp1 = 0; - unsigned int ui_NoOfChannel = CR_CHAN(insn->chanspec); /* get the channel */ + unsigned int mask = data[0]; + unsigned int bits = data[1]; - if (devpriv->b_OutputMemoryStatus) { - ui_Temp = inl(devpriv->i_IobaseAddon); - - } /* if(devpriv->b_OutputMemoryStatus ) */ - else { - ui_Temp = 0; - } /* if(devpriv->b_OutputMemoryStatus ) */ - if (data[3] == 0) { - if (data[1] == 0) { - data[0] = (data[0] << ui_NoOfChannel) | ui_Temp; - outl(data[0], devpriv->i_IobaseAddon); - } /* if(data[1]==0) */ - else { - if (data[1] == 1) { - switch (ui_NoOfChannel) { - - case 2: - data[0] = - (data[0] << (2 * - data[2])) | ui_Temp; - break; - case 3: - data[0] = (data[0] | ui_Temp); - break; - } /* switch(ui_NoOfChannels) */ - - outl(data[0], devpriv->i_IobaseAddon); - } /* if(data[1]==1) */ - else { - printk("\nSpecified channel not supported\n"); - } /* else if(data[1]==1) */ - } /* elseif(data[1]==0) */ - } /* if(data[3]==0) */ - else { - if (data[3] == 1) { - if (data[1] == 0) { - data[0] = ~data[0] & 0x1; - ui_Temp1 = 1; - ui_Temp1 = ui_Temp1 << ui_NoOfChannel; - ui_Temp = ui_Temp | ui_Temp1; - data[0] = (data[0] << ui_NoOfChannel) ^ 0xf; - data[0] = data[0] & ui_Temp; - outl(data[0], devpriv->i_IobaseAddon); - } /* if(data[1]==0) */ - else { - if (data[1] == 1) { - switch (ui_NoOfChannel) { - - case 2: - data[0] = ~data[0] & 0x3; - ui_Temp1 = 3; - ui_Temp1 = - ui_Temp1 << 2 * data[2]; - ui_Temp = ui_Temp | ui_Temp1; - data[0] = - ((data[0] << (2 * - data - [2])) ^ - 0xf) & ui_Temp; - - break; - case 3: - break; - - default: - comedi_error(dev, - " chan spec wrong"); - return -EINVAL; /* "sorry channel spec wrong " */ - } /* switch(ui_NoOfChannels) */ - - outl(data[0], devpriv->i_IobaseAddon); - } /* if(data[1]==1) */ - else { - printk("\nSpecified channel not supported\n"); - } /* else if(data[1]==1) */ - } /* elseif(data[1]==0) */ - } /* if(data[3]==1); */ - else { - printk("\nSpecified functionality does not exist\n"); - return -EINVAL; - } /* if else data[3]==1) */ - } /* if else data[3]==0) */ - return insn->n; -} + s->state = inl(devpriv->i_IobaseAddon) & 0xf; + if (mask) { + s->state &= ~mask; + s->state |= (bits & mask) -/* - * Read value of the selected channel or port - * - * data[0] = 0 read single channel - * = 1 read port value - * data[1] = port no - */ -static int i_APCI3200_ReadDigitalOutput(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, - unsigned int *data) -{ - struct addi_private *devpriv = dev->private; - unsigned int ui_Temp; - unsigned int ui_NoOfChannel; - - ui_NoOfChannel = CR_CHAN(insn->chanspec); - ui_Temp = data[0]; - *data = inl(devpriv->i_IobaseAddon); - if (ui_Temp == 0) { - *data = (*data >> ui_NoOfChannel) & 0x1; - } /* if (ui_Temp==0) */ - else { - if (ui_Temp == 1) { - if (data[1] < 0 || data[1] > 1) { - printk("\nThe port selection is in error\n"); - return -EINVAL; - } /* if(data[1] <0 ||data[1] >1) */ - switch (ui_NoOfChannel) { - case 2: - *data = (*data >> (2 * data[1])) & 3; - break; + outl(s->state, devpriv->i_IobaseAddon); + } - case 3: - break; + data[1] = s->state; - default: - comedi_error(dev, " chan spec wrong"); - return -EINVAL; /* "sorry channel spec wrong " */ - break; - } /* switch(ui_NoOfChannels) */ - } /* if (ui_Temp==1) */ - else { - printk("\nSpecified channel not supported \n"); - } /* else if (ui_Temp==1) */ - } /* else if (ui_Temp==0) */ return insn->n; } diff --git a/drivers/staging/comedi/drivers/addi_apci_3200.c b/drivers/staging/comedi/drivers/addi_apci_3200.c index 432caccdd325..890877febaca 100644 --- a/drivers/staging/comedi/drivers/addi_apci_3200.c +++ b/drivers/staging/comedi/drivers/addi_apci_3200.c @@ -51,8 +51,7 @@ static const struct addi_board apci3200_boardtypes[] = { .ai_cancel = i_APCI3200_StopCyclicAcquisition, .di_bits = apci3200_di_insn_bits, .do_config = i_APCI3200_ConfigDigitalOutput, - .do_write = i_APCI3200_WriteDigitalOutput, - .do_bits = i_APCI3200_ReadDigitalOutput, + .do_bits = apci3200_do_insn_bits, }, { .pc_DriverName = "apci3300", .i_VendorId = PCI_VENDOR_ID_ADDIDATA, @@ -82,8 +81,7 @@ static const struct addi_board apci3200_boardtypes[] = { .ai_cancel = i_APCI3200_StopCyclicAcquisition, .di_bits = apci3200_di_insn_bits, .do_config = i_APCI3200_ConfigDigitalOutput, - .do_write = i_APCI3200_WriteDigitalOutput, - .do_bits = i_APCI3200_ReadDigitalOutput, + .do_bits = apci3200_do_insn_bits, }, };