Skip to content

Commit

Permalink
staging: comedi: addi-data: Don't overwrite read-only data
Browse files Browse the repository at this point in the history
The drivers for ADDI-DATA cards can override some static parameters for
the board type using information read from EEPROM.  Unfortunately, they
currently write the parameters from the EEPROM back to the shared,
read-only board data!  The problem has been masked during compilation by
type-casting away the const-ness of the data.

This patch changes the code to use an area in the private data for the
board instance to hold the parameters read from EEPROM (after
initializing the parameters from the static board data).  It also
changes the type-casts to the read-only data to preserve the const
qualifier.

Signed-off-by: Ian Abbott <abbotti@mev.co.uk>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
  • Loading branch information
Ian Abbott authored and Greg Kroah-Hartman committed May 17, 2011
1 parent cfe3cff commit 5751787
Show file tree
Hide file tree
Showing 5 changed files with 102 additions and 52 deletions.
55 changes: 37 additions & 18 deletions drivers/staging/comedi/drivers/addi-data/addi_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ You should also find the complete GPL in the COPYING file accompanying this sour
/* Update-0.7.57->0.7.68MODULE_LICENSE("GPL"); */

#define devpriv ((struct addi_private *)dev->private)
#define this_board ((struct addi_board *)dev->board_ptr)
#define this_board ((const struct addi_board *)dev->board_ptr)

#if defined(CONFIG_APCI_1710) || defined(CONFIG_APCI_3200) || defined(CONFIG_APCI_3300)
/* BYTE b_SaveFPUReg [94]; */
Expand Down Expand Up @@ -2680,6 +2680,21 @@ static int i_ADDI_Attach(struct comedi_device *dev, struct comedi_devconfig *it)
printk("\nioremap end");
}

/* Initialize parameters that can be overridden in EEPROM */
devpriv->s_EeParameters.i_NbrAiChannel = this_board->i_NbrAiChannel;
devpriv->s_EeParameters.i_NbrAoChannel = this_board->i_NbrAoChannel;
devpriv->s_EeParameters.i_AiMaxdata = this_board->i_AiMaxdata;
devpriv->s_EeParameters.i_AoMaxdata = this_board->i_AoMaxdata;
devpriv->s_EeParameters.i_NbrDiChannel = this_board->i_NbrDiChannel;
devpriv->s_EeParameters.i_NbrDoChannel = this_board->i_NbrDoChannel;
devpriv->s_EeParameters.i_DoMaxdata = this_board->i_DoMaxdata;
devpriv->s_EeParameters.i_Dma = this_board->i_Dma;
devpriv->s_EeParameters.i_Timer = this_board->i_Timer;
devpriv->s_EeParameters.ui_MinAcquisitiontimeNs =
this_board->ui_MinAcquisitiontimeNs;
devpriv->s_EeParameters.ui_MinDelaytimeNs =
this_board->ui_MinDelaytimeNs;

/* ## */

if (irq > 0) {
Expand Down Expand Up @@ -2728,7 +2743,7 @@ static int i_ADDI_Attach(struct comedi_device *dev, struct comedi_devconfig *it)
devpriv->us_UseDma = ADDI_ENABLE;
}

if (this_board->i_Dma) {
if (devpriv->s_EeParameters.i_Dma) {
printk("\nDMA used");
if (devpriv->us_UseDma == ADDI_ENABLE) {
/* alloc DMA buffers */
Expand Down Expand Up @@ -2787,21 +2802,22 @@ static int i_ADDI_Attach(struct comedi_device *dev, struct comedi_devconfig *it)

/* Allocate and Initialise AI Subdevice Structures */
s = dev->subdevices + 0;
if ((this_board->i_NbrAiChannel)
if ((devpriv->s_EeParameters.i_NbrAiChannel)
|| (this_board->i_NbrAiChannelDiff)) {
dev->read_subdev = s;
s->type = COMEDI_SUBD_AI;
s->subdev_flags =
SDF_READABLE | SDF_COMMON | SDF_GROUND
| SDF_DIFF;
if (this_board->i_NbrAiChannel) {
s->n_chan = this_board->i_NbrAiChannel;
if (devpriv->s_EeParameters.i_NbrAiChannel) {
s->n_chan =
devpriv->s_EeParameters.i_NbrAiChannel;
devpriv->b_SingelDiff = 0;
} else {
s->n_chan = this_board->i_NbrAiChannelDiff;
devpriv->b_SingelDiff = 1;
}
s->maxdata = this_board->i_AiMaxdata;
s->maxdata = devpriv->s_EeParameters.i_AiMaxdata;
s->len_chanlist = this_board->i_AiChannelList;
s->range_table = this_board->pr_AiRangelist;

Expand All @@ -2825,12 +2841,13 @@ static int i_ADDI_Attach(struct comedi_device *dev, struct comedi_devconfig *it)

/* Allocate and Initialise AO Subdevice Structures */
s = dev->subdevices + 1;
if (this_board->i_NbrAoChannel) {
if (devpriv->s_EeParameters.i_NbrAoChannel) {
s->type = COMEDI_SUBD_AO;
s->subdev_flags = SDF_WRITEABLE | SDF_GROUND | SDF_COMMON;
s->n_chan = this_board->i_NbrAoChannel;
s->maxdata = this_board->i_AoMaxdata;
s->len_chanlist = this_board->i_NbrAoChannel;
s->n_chan = devpriv->s_EeParameters.i_NbrAoChannel;
s->maxdata = devpriv->s_EeParameters.i_AoMaxdata;
s->len_chanlist =
devpriv->s_EeParameters.i_NbrAoChannel;
s->range_table = this_board->pr_AoRangelist;
s->insn_config =
this_board->i_hwdrv_InsnConfigAnalogOutput;
Expand All @@ -2841,12 +2858,13 @@ static int i_ADDI_Attach(struct comedi_device *dev, struct comedi_devconfig *it)
}
/* Allocate and Initialise DI Subdevice Structures */
s = dev->subdevices + 2;
if (this_board->i_NbrDiChannel) {
if (devpriv->s_EeParameters.i_NbrDiChannel) {
s->type = COMEDI_SUBD_DI;
s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_COMMON;
s->n_chan = this_board->i_NbrDiChannel;
s->n_chan = devpriv->s_EeParameters.i_NbrDiChannel;
s->maxdata = 1;
s->len_chanlist = this_board->i_NbrDiChannel;
s->len_chanlist =
devpriv->s_EeParameters.i_NbrDiChannel;
s->range_table = &range_digital;
s->io_bits = 0; /* all bits input */
s->insn_config =
Expand All @@ -2860,13 +2878,14 @@ static int i_ADDI_Attach(struct comedi_device *dev, struct comedi_devconfig *it)
}
/* Allocate and Initialise DO Subdevice Structures */
s = dev->subdevices + 3;
if (this_board->i_NbrDoChannel) {
if (devpriv->s_EeParameters.i_NbrDoChannel) {
s->type = COMEDI_SUBD_DO;
s->subdev_flags =
SDF_READABLE | SDF_WRITEABLE | SDF_GROUND | SDF_COMMON;
s->n_chan = this_board->i_NbrDoChannel;
s->maxdata = this_board->i_DoMaxdata;
s->len_chanlist = this_board->i_NbrDoChannel;
s->n_chan = devpriv->s_EeParameters.i_NbrDoChannel;
s->maxdata = devpriv->s_EeParameters.i_DoMaxdata;
s->len_chanlist =
devpriv->s_EeParameters.i_NbrDoChannel;
s->range_table = &range_digital;
s->io_bits = 0xf; /* all bits output */

Expand All @@ -2883,7 +2902,7 @@ static int i_ADDI_Attach(struct comedi_device *dev, struct comedi_devconfig *it)

/* Allocate and Initialise Timer Subdevice Structures */
s = dev->subdevices + 4;
if (this_board->i_Timer) {
if (devpriv->s_EeParameters.i_Timer) {
s->type = COMEDI_SUBD_TIMER;
s->subdev_flags = SDF_WRITEABLE | SDF_GROUND | SDF_COMMON;
s->n_chan = 1;
Expand Down
18 changes: 17 additions & 1 deletion drivers/staging/comedi/drivers/addi-data/addi_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -406,7 +406,7 @@ struct addi_private {

/* Pointer to the current process */
struct task_struct *tsk_Current;
struct addi_board *ps_BoardInfo;
const struct addi_board *ps_BoardInfo;

/* Hardware board infos for 1710 */
struct {
Expand Down Expand Up @@ -434,6 +434,22 @@ struct addi_private {
union str_ModuleInfo s_ModuleInfo[4];
unsigned int ul_TTLPortConfiguration[10];

/* Parameters read from EEPROM overriding static board info */
struct {
int i_NbrAiChannel; /* num of A/D chans */
int i_NbrAoChannel; /* num of D/A chans */
int i_AiMaxdata; /* resolution of A/D */
int i_AoMaxdata; /* resolution of D/A */
int i_NbrDiChannel; /* Number of DI channels */
int i_NbrDoChannel; /* Number of DO channels */
int i_DoMaxdata; /* data to set all channels high */
int i_Dma; /* dma present or not */
int i_Timer; /* timer subdevice present or not */
unsigned int ui_MinAcquisitiontimeNs;
/* Minimum Acquisition in Nano secs */
unsigned int ui_MinDelaytimeNs;
/* Minimum Delay in Nano secs */
} s_EeParameters;
};

static unsigned short pci_list_builded; /* set to 1 when list of card is known */
Expand Down
36 changes: 21 additions & 15 deletions drivers/staging/comedi/drivers/addi-data/addi_eeprom.c
Original file line number Diff line number Diff line change
Expand Up @@ -847,7 +847,7 @@ int i_EepromReadMainHeader(unsigned short w_PCIBoardEepromAddress,
pc_PCIChipInformation,
s_MainHeader.s_Functions[i].w_Address,
&s_DigitalInputHeader);
this_board->i_NbrDiChannel =
devpriv->s_EeParameters.i_NbrDiChannel =
s_DigitalInputHeader.w_Nchannel;
break;

Expand All @@ -856,11 +856,12 @@ int i_EepromReadMainHeader(unsigned short w_PCIBoardEepromAddress,
pc_PCIChipInformation,
s_MainHeader.s_Functions[i].w_Address,
&s_DigitalOutputHeader);
this_board->i_NbrDoChannel =
devpriv->s_EeParameters.i_NbrDoChannel =
s_DigitalOutputHeader.w_Nchannel;
ui_Temp = 0xffffffff;
this_board->i_DoMaxdata =
ui_Temp >> (32 - this_board->i_NbrDoChannel);
devpriv->s_EeParameters.i_DoMaxdata =
ui_Temp >> (32 -
devpriv->s_EeParameters.i_NbrDoChannel);
break;

case EEPROM_ANALOGINPUT:
Expand All @@ -869,20 +870,21 @@ int i_EepromReadMainHeader(unsigned short w_PCIBoardEepromAddress,
s_MainHeader.s_Functions[i].w_Address,
&s_AnalogInputHeader);
if (!(strcmp(this_board->pc_DriverName, "apci3200")))
this_board->i_NbrAiChannel =
devpriv->s_EeParameters.i_NbrAiChannel =
s_AnalogInputHeader.w_Nchannel * 4;
else
this_board->i_NbrAiChannel =
devpriv->s_EeParameters.i_NbrAiChannel =
s_AnalogInputHeader.w_Nchannel;
this_board->i_Dma = s_AnalogInputHeader.b_HasDma;
this_board->ui_MinAcquisitiontimeNs =
devpriv->s_EeParameters.i_Dma =
s_AnalogInputHeader.b_HasDma;
devpriv->s_EeParameters.ui_MinAcquisitiontimeNs =
(unsigned int) s_AnalogInputHeader.w_MinConvertTiming *
1000;
this_board->ui_MinDelaytimeNs =
devpriv->s_EeParameters.ui_MinDelaytimeNs =
(unsigned int) s_AnalogInputHeader.w_MinDelayTiming *
1000;
ui_Temp = 0xffff;
this_board->i_AiMaxdata =
devpriv->s_EeParameters.i_AiMaxdata =
ui_Temp >> (16 -
s_AnalogInputHeader.b_Resolution);
break;
Expand All @@ -892,24 +894,28 @@ int i_EepromReadMainHeader(unsigned short w_PCIBoardEepromAddress,
pc_PCIChipInformation,
s_MainHeader.s_Functions[i].w_Address,
&s_AnalogOutputHeader);
this_board->i_NbrAoChannel =
devpriv->s_EeParameters.i_NbrAoChannel =
s_AnalogOutputHeader.w_Nchannel;
ui_Temp = 0xffff;
this_board->i_AoMaxdata =
devpriv->s_EeParameters.i_AoMaxdata =
ui_Temp >> (16 -
s_AnalogOutputHeader.b_Resolution);
break;

case EEPROM_TIMER:
this_board->i_Timer = 1; /* Timer subdevice present */
/* Timer subdevice present */
devpriv->s_EeParameters.i_Timer = 1;
break;

case EEPROM_WATCHDOG:
this_board->i_Timer = 1; /* Timer subdevice present */
/* Timer subdevice present */
devpriv->s_EeParameters.i_Timer = 1;
break;

case EEPROM_TIMER_WATCHDOG_COUNTER:
this_board->i_Timer = 1; /* Timer subdevice present */
/* Timer subdevice present */
devpriv->s_EeParameters.i_Timer = 1;
break;
}
}

Expand Down
27 changes: 16 additions & 11 deletions drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,8 @@ int i_APCI3120_InsnConfigAnalogInput(struct comedi_device *dev, struct comedi_su
/* Test the number of the channel */
for (i = 0; i < data[3]; i++) {

if (CR_CHAN(data[4 + i]) >= this_board->i_NbrAiChannel) {
if (CR_CHAN(data[4 + i]) >=
devpriv->s_EeParameters.i_NbrAiChannel) {
printk("bad channel list\n");
return -2;
}
Expand Down Expand Up @@ -541,8 +542,10 @@ int i_APCI3120_CommandTestAnalogInput(struct comedi_device *dev, struct comedi_s
}

if (cmd->scan_begin_src == TRIG_TIMER) { /* Test Delay timing */
if (cmd->scan_begin_arg < this_board->ui_MinDelaytimeNs) {
cmd->scan_begin_arg = this_board->ui_MinDelaytimeNs;
if (cmd->scan_begin_arg <
devpriv->s_EeParameters.ui_MinDelaytimeNs) {
cmd->scan_begin_arg =
devpriv->s_EeParameters.ui_MinDelaytimeNs;
err++;
}
}
Expand All @@ -551,16 +554,18 @@ int i_APCI3120_CommandTestAnalogInput(struct comedi_device *dev, struct comedi_s
if (cmd->scan_begin_src == TRIG_TIMER) {
if ((cmd->convert_arg)
&& (cmd->convert_arg <
this_board->ui_MinAcquisitiontimeNs)) {
cmd->convert_arg =
this_board->ui_MinAcquisitiontimeNs;
devpriv->s_EeParameters.
ui_MinAcquisitiontimeNs)) {
cmd->convert_arg = devpriv->s_EeParameters.
ui_MinAcquisitiontimeNs;
err++;
}
} else {
if (cmd->convert_arg <
this_board->ui_MinAcquisitiontimeNs) {
cmd->convert_arg =
this_board->ui_MinAcquisitiontimeNs;
devpriv->s_EeParameters.ui_MinAcquisitiontimeNs
) {
cmd->convert_arg = devpriv->s_EeParameters.
ui_MinAcquisitiontimeNs;
err++;

}
Expand Down Expand Up @@ -2452,7 +2457,7 @@ int i_APCI3120_InsnBitsDigitalOutput(struct comedi_device *dev,
struct comedi_insn *insn,
unsigned int *data)
{
if ((data[0] > this_board->i_DoMaxdata) || (data[0] < 0)) {
if ((data[0] > devpriv->s_EeParameters.i_DoMaxdata) || (data[0] < 0)) {

comedi_error(dev, "Data is not valid !!! \n");
return -EINVAL;
Expand Down Expand Up @@ -2515,7 +2520,7 @@ int i_APCI3120_InsnWriteDigitalOutput(struct comedi_device *dev,
"Not a valid Data !!! ,Data should be 1 or 0\n");
return -EINVAL;
}
if (ui_NoOfChannel > this_board->i_NbrDoChannel - 1) {
if (ui_NoOfChannel > devpriv->s_EeParameters.i_NbrDoChannel - 1) {
comedi_error(dev,
"This board doesn't have specified channel !!! \n");
return -EINVAL;
Expand Down
18 changes: 11 additions & 7 deletions drivers/staging/comedi/drivers/addi-data/hwdrv_apci3xxx.c
Original file line number Diff line number Diff line change
Expand Up @@ -165,12 +165,16 @@ static int i_APCI3XXX_AnalogInputConfigOperatingMode(struct comedi_device *dev,
/*******************************/

if (dw_TestReloadValue >=
devpriv->ps_BoardInfo->
devpriv->s_EeParameters.
ui_MinAcquisitiontimeNs) {
if ((b_SingleDiff == APCI3XXX_SINGLE)
|| (b_SingleDiff ==
APCI3XXX_DIFF)) {
if (((b_SingleDiff == APCI3XXX_SINGLE) && (devpriv->ps_BoardInfo->i_NbrAiChannel == 0)) || ((b_SingleDiff == APCI3XXX_DIFF) && (devpriv->ps_BoardInfo->i_NbrAiChannelDiff == 0))) {
if (((b_SingleDiff == APCI3XXX_SINGLE)
&& (devpriv->s_EeParameters.i_NbrAiChannel == 0))
|| ((b_SingleDiff == APCI3XXX_DIFF)
&& (devpriv->ps_BoardInfo->i_NbrAiChannelDiff == 0))
) {
/*******************************/
/* Single/Diff selection error */
/*******************************/
Expand Down Expand Up @@ -372,7 +376,7 @@ static int i_APCI3XXX_InsnReadAnalogInput(struct comedi_device *dev,
/* Test the channel number */
/***************************/

if (((b_Channel < devpriv->ps_BoardInfo->i_NbrAiChannel)
if (((b_Channel < devpriv->s_EeParameters.i_NbrAiChannel)
&& (devpriv->b_SingelDiff == APCI3XXX_SINGLE))
|| ((b_Channel < devpriv->ps_BoardInfo->
i_NbrAiChannelDiff)
Expand Down Expand Up @@ -663,7 +667,7 @@ static int i_APCI3XXX_InsnWriteAnalogOutput(struct comedi_device *dev,
/* Test the channel number */
/***************************/

if (b_Channel < devpriv->ps_BoardInfo->i_NbrAoChannel) {
if (b_Channel < devpriv->s_EeParameters.i_NbrAoChannel) {
/**********************************/
/* Test the channel configuration */
/**********************************/
Expand Down Expand Up @@ -1273,7 +1277,7 @@ static int i_APCI3XXX_InsnReadDigitalInput(struct comedi_device *dev,
/* Test the channel number */
/***************************/

if (b_Channel <= devpriv->ps_BoardInfo->i_NbrDiChannel) {
if (b_Channel <= devpriv->s_EeParameters.i_NbrDiChannel) {
/************************/
/* Test the buffer size */
/************************/
Expand Down Expand Up @@ -1492,7 +1496,7 @@ static int i_APCI3XXX_InsnWriteDigitalOutput(struct comedi_device *dev,
/* Test the channel number */
/***************************/

if (b_Channel < devpriv->ps_BoardInfo->i_NbrDoChannel) {
if (b_Channel < devpriv->s_EeParameters.i_NbrDoChannel) {
/*******************/
/* Get the command */
/*******************/
Expand Down Expand Up @@ -1568,7 +1572,7 @@ static int i_APCI3XXX_InsnReadDigitalOutput(struct comedi_device *dev,
/* Test the channel number */
/***************************/

if (b_Channel < devpriv->ps_BoardInfo->i_NbrDoChannel) {
if (b_Channel < devpriv->s_EeParameters.i_NbrDoChannel) {
/********************************/
/* Read the digital output port */
/********************************/
Expand Down

0 comments on commit 5751787

Please sign in to comment.