提交 57517878 编写于 作者: I Ian Abbott 提交者: Greg Kroah-Hartman

staging: comedi: addi-data: Don't overwrite read-only data

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: NIan Abbott <abbotti@mev.co.uk>
Signed-off-by: NGreg Kroah-Hartman <gregkh@suse.de>
上级 cfe3cffd
......@@ -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]; */
......@@ -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) {
......@@ -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 */
......@@ -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;
......@@ -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;
......@@ -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 =
......@@ -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 */
......@@ -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;
......
......@@ -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 {
......@@ -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 */
......
......@@ -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;
......@@ -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:
......@@ -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;
......@@ -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;
}
}
......
......@@ -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;
}
......@@ -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++;
}
}
......@@ -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++;
}
......@@ -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;
......@@ -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;
......
......@@ -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 */
/*******************************/
......@@ -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)
......@@ -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 */
/**********************************/
......@@ -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 */
/************************/
......@@ -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 */
/*******************/
......@@ -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 */
/********************************/
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册