For M-Series boards (devpriv->is_m_series), the STC registers need to be
remapped. This is currently handled with some big switch statements to
convert the STC register offset to the M-Series offset. Some of the
registers also need special handling due to differences in the register
size on the M-Series boards.

Create some lookup tables to handle the remapping of the read and write
registers. These are easier to maintain and can contain the register size
so that a common function can be used instead of the separate helpers.

Signed-off-by: H Hartley Sweeten <hswee...@visionengravers.com>
Cc: Ian Abbott <abbo...@mev.co.uk>
Cc: Greg Kroah-Hartman <gre...@linuxfoundation.org>
---
 drivers/staging/comedi/drivers/ni_mio_common.c | 352 ++++++++-----------------
 1 file changed, 115 insertions(+), 237 deletions(-)

diff --git a/drivers/staging/comedi/drivers/ni_mio_common.c 
b/drivers/staging/comedi/drivers/ni_mio_common.c
index 69d71f3..ecfd097 100644
--- a/drivers/staging/comedi/drivers/ni_mio_common.c
+++ b/drivers/staging/comedi/drivers/ni_mio_common.c
@@ -308,262 +308,140 @@ static uint8_t ni_readb(struct comedi_device *dev, int 
reg)
  * windowed STC registers to the m series register offsets.
  */
 
-static void m_series_stc_writel(struct comedi_device *dev,
-                               uint32_t data, int reg)
+struct mio_regmap {
+       unsigned int mio_reg;
+       int size;
+};
+
+static const struct mio_regmap m_series_stc_write_regmap[] = {
+       [Interrupt_A_Ack_Register]      = { M_Offset_Interrupt_A_Ack, 2 },
+       [Interrupt_B_Ack_Register]      = { M_Offset_Interrupt_B_Ack, 2 },
+       [AI_Command_2_Register]         = { M_Offset_AI_Command_2, 2 },
+       [AO_Command_2_Register]         = { M_Offset_AO_Command_2, 2 },
+       [G_Command_Register(0)]         = { M_Offset_G0_Command, 2 },
+       [G_Command_Register(1)]         = { M_Offset_G1_Command, 2 },
+       [AI_Command_1_Register]         = { M_Offset_AI_Command_1, 2 },
+       [AO_Command_1_Register]         = { M_Offset_AO_Command_1, 2 },
+       [DIO_Output_Register]           = { 0, 0 }, /* DOES NOT MAP CLEANLY */
+                                       /*
+                                        * DIO_Output_Register maps to:
+                                        * { M_Offset_Static_Digital_Output, 4 }
+                                        * { M_Offset_SCXI_Serial_Data_Out, 1 }
+                                        */
+       [DIO_Control_Register]          = { 0, 0 }, /* DOES NOT MAP CLEANLY */
+       [AI_Mode_1_Register]            = { M_Offset_AI_Mode_1, 2 },
+       [AI_Mode_2_Register]            = { M_Offset_AI_Mode_2, 2 },
+       [AI_SI_Load_A_Registers]        = { M_Offset_AI_SI_Load_A, 4 },
+       [AI_SC_Load_A_Registers]        = { M_Offset_AI_SC_Load_A, 4 },
+       [AI_SI2_Load_A_Register]        = { M_Offset_AI_SI2_Load_A, 4 },
+       [AI_SI2_Load_B_Register]        = { M_Offset_AI_SI2_Load_B, 4 },
+       [G_Mode_Register(0)]            = { M_Offset_G0_Mode, 2 },
+       [G_Mode_Register(1)]            = { M_Offset_G1_Mode, 2 },
+       [G_Load_A_Register(0)]          = { M_Offset_G0_Load_A, 4 },
+       [G_Load_B_Register(0)]          = { M_Offset_G0_Load_B, 4 },
+       [G_Load_A_Register(1)]          = { M_Offset_G1_Load_A, 4 },
+       [G_Load_B_Register(1)]          = { M_Offset_G1_Load_B, 4 },
+       [G_Input_Select_Register(0)]    = { M_Offset_G0_Input_Select, 2 },
+       [G_Input_Select_Register(1)]    = { M_Offset_G1_Input_Select, 2 },
+       [AO_Mode_1_Register]            = { M_Offset_AO_Mode_1, 2 },
+       [AO_Mode_2_Register]            = { M_Offset_AO_Mode_2, 2 },
+       [AO_UI_Load_A_Register]         = { M_Offset_AO_UI_Load_A, 4 },
+       [AO_BC_Load_A_Register]         = { M_Offset_AO_BC_Load_A, 4 },
+       [AO_UC_Load_A_Register]         = { M_Offset_AO_UC_Load_A, 4 },
+       [Clock_and_FOUT_Register]       = { M_Offset_Clock_and_FOUT, 2 },
+       [IO_Bidirection_Pin_Register]   = { M_Offset_IO_Bidirection_Pin, 2 },
+       [RTSI_Trig_Direction_Register]  = { M_Offset_RTSI_Trig_Direction, 2 },
+       [Interrupt_Control_Register]    = { M_Offset_Interrupt_Control, 2 },
+       [AI_Output_Control_Register]    = { M_Offset_AI_Output_Control, 2 },
+       [Analog_Trigger_Etc_Register]   = { M_Offset_Analog_Trigger_Etc, 2 },
+       [AI_START_STOP_Select_Register] = { M_Offset_AI_START_STOP_Select, 2 },
+       [AI_Trigger_Select_Register]    = { M_Offset_AI_Trigger_Select, 2 },
+       [AO_Start_Select_Register]      = { M_Offset_AO_Start_Select, 2 },
+       [AO_Trigger_Select_Register]    = { M_Offset_AO_Trigger_Select, 2 },
+       [G_Autoincrement_Register(0)]   = { M_Offset_G0_Autoincrement, 2 },
+       [G_Autoincrement_Register(1)]   = { M_Offset_G1_Autoincrement, 2 },
+       [AO_Mode_3_Register]            = { M_Offset_AO_Mode_3, 2 },
+       [Joint_Reset_Register]          = { M_Offset_Joint_Reset, 2 },
+       [Interrupt_A_Enable_Register]   = { M_Offset_Interrupt_A_Enable, 2 },
+       [Interrupt_B_Enable_Register]   = { M_Offset_Interrupt_B_Enable, 2 },
+       [AI_Personal_Register]          = { M_Offset_AI_Personal, 2 },
+       [AO_Personal_Register]          = { M_Offset_AO_Personal, 2 },
+       [RTSI_Trig_A_Output_Register]   = { M_Offset_RTSI_Trig_A_Output, 2 },
+       [RTSI_Trig_B_Output_Register]   = { M_Offset_RTSI_Trig_B_Output, 2 },
+       [Configuration_Memory_Clear]    = { M_Offset_Configuration_Memory_Clear,
+                                           2 },
+       [ADC_FIFO_Clear]                = { M_Offset_AI_FIFO_Clear, 2 },
+       [DAC_FIFO_Clear]                = { M_Offset_AO_FIFO_Clear, 2 },
+       [AO_Output_Control_Register]    = { M_Offset_AO_Output_Control, 2 },
+       [AI_Mode_3_Register]            = { M_Offset_AI_Mode_3, 2 },
+};
+
+static void m_series_stc_write(struct comedi_device *dev,
+                              unsigned int data, unsigned int reg)
 {
-       unsigned offset;
+       const struct mio_regmap *regmap;
 
-       switch (reg) {
-       case AI_SC_Load_A_Registers:
-               offset = M_Offset_AI_SC_Load_A;
-               break;
-       case AI_SI_Load_A_Registers:
-               offset = M_Offset_AI_SI_Load_A;
-               break;
-       case AO_BC_Load_A_Register:
-               offset = M_Offset_AO_BC_Load_A;
-               break;
-       case AO_UC_Load_A_Register:
-               offset = M_Offset_AO_UC_Load_A;
-               break;
-       case AO_UI_Load_A_Register:
-               offset = M_Offset_AO_UI_Load_A;
-               break;
-       case G_Load_A_Register(0):
-               offset = M_Offset_G0_Load_A;
-               break;
-       case G_Load_A_Register(1):
-               offset = M_Offset_G1_Load_A;
-               break;
-       case G_Load_B_Register(0):
-               offset = M_Offset_G0_Load_B;
-               break;
-       case G_Load_B_Register(1):
-               offset = M_Offset_G1_Load_B;
-               break;
-       default:
-               dev_warn(dev->class_dev,
-                        "%s: bug! unhandled register=0x%x in switch\n",
+       if (reg < ARRAY_SIZE(m_series_stc_write_regmap)) {
+               regmap = &m_series_stc_write_regmap[reg];
+       } else {
+               dev_warn(dev->class_dev, "%s: unhandled register=0x%x\n",
                         __func__, reg);
                return;
        }
-       ni_writel(dev, data, offset);
-}
-
-static void m_series_stc_writew(struct comedi_device *dev,
-                               uint16_t data, int reg)
-{
-       unsigned offset;
 
-       switch (reg) {
-       case ADC_FIFO_Clear:
-               offset = M_Offset_AI_FIFO_Clear;
-               break;
-       case AI_Command_1_Register:
-               offset = M_Offset_AI_Command_1;
-               break;
-       case AI_Command_2_Register:
-               offset = M_Offset_AI_Command_2;
-               break;
-       case AI_Mode_1_Register:
-               offset = M_Offset_AI_Mode_1;
-               break;
-       case AI_Mode_2_Register:
-               offset = M_Offset_AI_Mode_2;
-               break;
-       case AI_Mode_3_Register:
-               offset = M_Offset_AI_Mode_3;
-               break;
-       case AI_Output_Control_Register:
-               offset = M_Offset_AI_Output_Control;
-               break;
-       case AI_Personal_Register:
-               offset = M_Offset_AI_Personal;
-               break;
-       case AI_SI2_Load_A_Register:
-               /* this is a 32 bit register on m series boards */
-               ni_writel(dev, data, M_Offset_AI_SI2_Load_A);
-               return;
-       case AI_SI2_Load_B_Register:
-               /* this is a 32 bit register on m series boards */
-               ni_writel(dev, data, M_Offset_AI_SI2_Load_B);
-               return;
-       case AI_START_STOP_Select_Register:
-               offset = M_Offset_AI_START_STOP_Select;
-               break;
-       case AI_Trigger_Select_Register:
-               offset = M_Offset_AI_Trigger_Select;
-               break;
-       case Analog_Trigger_Etc_Register:
-               offset = M_Offset_Analog_Trigger_Etc;
-               break;
-       case AO_Command_1_Register:
-               offset = M_Offset_AO_Command_1;
-               break;
-       case AO_Command_2_Register:
-               offset = M_Offset_AO_Command_2;
-               break;
-       case AO_Mode_1_Register:
-               offset = M_Offset_AO_Mode_1;
-               break;
-       case AO_Mode_2_Register:
-               offset = M_Offset_AO_Mode_2;
-               break;
-       case AO_Mode_3_Register:
-               offset = M_Offset_AO_Mode_3;
-               break;
-       case AO_Output_Control_Register:
-               offset = M_Offset_AO_Output_Control;
-               break;
-       case AO_Personal_Register:
-               offset = M_Offset_AO_Personal;
-               break;
-       case AO_Start_Select_Register:
-               offset = M_Offset_AO_Start_Select;
-               break;
-       case AO_Trigger_Select_Register:
-               offset = M_Offset_AO_Trigger_Select;
-               break;
-       case Clock_and_FOUT_Register:
-               offset = M_Offset_Clock_and_FOUT;
-               break;
-       case Configuration_Memory_Clear:
-               offset = M_Offset_Configuration_Memory_Clear;
-               break;
-       case DAC_FIFO_Clear:
-               offset = M_Offset_AO_FIFO_Clear;
-               break;
-       case DIO_Control_Register:
-               dev_dbg(dev->class_dev,
-                       "%s: FIXME: register 0x%x does not map cleanly on to 
m-series boards\n",
-                       __func__, reg);
-               return;
-       case G_Autoincrement_Register(0):
-               offset = M_Offset_G0_Autoincrement;
-               break;
-       case G_Autoincrement_Register(1):
-               offset = M_Offset_G1_Autoincrement;
-               break;
-       case G_Command_Register(0):
-               offset = M_Offset_G0_Command;
-               break;
-       case G_Command_Register(1):
-               offset = M_Offset_G1_Command;
-               break;
-       case G_Input_Select_Register(0):
-               offset = M_Offset_G0_Input_Select;
-               break;
-       case G_Input_Select_Register(1):
-               offset = M_Offset_G1_Input_Select;
-               break;
-       case G_Mode_Register(0):
-               offset = M_Offset_G0_Mode;
-               break;
-       case G_Mode_Register(1):
-               offset = M_Offset_G1_Mode;
-               break;
-       case Interrupt_A_Ack_Register:
-               offset = M_Offset_Interrupt_A_Ack;
-               break;
-       case Interrupt_A_Enable_Register:
-               offset = M_Offset_Interrupt_A_Enable;
-               break;
-       case Interrupt_B_Ack_Register:
-               offset = M_Offset_Interrupt_B_Ack;
-               break;
-       case Interrupt_B_Enable_Register:
-               offset = M_Offset_Interrupt_B_Enable;
-               break;
-       case Interrupt_Control_Register:
-               offset = M_Offset_Interrupt_Control;
-               break;
-       case IO_Bidirection_Pin_Register:
-               offset = M_Offset_IO_Bidirection_Pin;
-               break;
-       case Joint_Reset_Register:
-               offset = M_Offset_Joint_Reset;
-               break;
-       case RTSI_Trig_A_Output_Register:
-               offset = M_Offset_RTSI_Trig_A_Output;
-               break;
-       case RTSI_Trig_B_Output_Register:
-               offset = M_Offset_RTSI_Trig_B_Output;
+       switch (regmap->size) {
+       case 4:
+               ni_writel(dev, data, regmap->mio_reg);
                break;
-       case RTSI_Trig_Direction_Register:
-               offset = M_Offset_RTSI_Trig_Direction;
+       case 2:
+               ni_writew(dev, data, regmap->mio_reg);
                break;
-       /*
-        * FIXME: DIO_Output_Register (16 bit reg) is replaced by
-        * M_Offset_Static_Digital_Output (32 bit) and
-        * M_Offset_SCXI_Serial_Data_Out (8 bit)
-        */
        default:
-               dev_warn(dev->class_dev,
-                        "%s: bug! unhandled register=0x%x in switch\n",
+               dev_warn(dev->class_dev, "%s: unmapped register=0x%x\n",
                         __func__, reg);
-               return;
+               break;
        }
-       ni_writew(dev, data, offset);
 }
 
-static uint32_t m_series_stc_readl(struct comedi_device *dev, int reg)
+static const struct mio_regmap m_series_stc_read_regmap[] = {
+       [AI_Status_1_Register]          = { M_Offset_AI_Status_1, 2 },
+       [AO_Status_1_Register]          = { M_Offset_AO_Status_1, 2 },
+       [G_Status_Register]             = { M_Offset_G01_Status, 2 },
+       [AO_Status_2_Register]          = { M_Offset_AO_Status_2, 2 },
+       [G_HW_Save_Register(0)]         = { M_Offset_G0_HW_Save, 4 },
+       [G_HW_Save_Register(1)]         = { M_Offset_G1_HW_Save, 4 },
+       [G_Save_Register(0)]            = { M_Offset_G0_Save, 4 },
+       [G_Save_Register(1)]            = { M_Offset_G1_Save, 4 },
+       [Joint_Status_1_Register]       = { M_Offset_Joint_Status_1, 2 },
+       [DIO_Serial_Input_Register]     = { M_Offset_SCXI_Serial_Data_In, 1 },
+       [Joint_Status_2_Register]       = { M_Offset_Joint_Status_2, 2 },
+};
+
+static unsigned int m_series_stc_read(struct comedi_device *dev,
+                                     unsigned int reg)
 {
-       unsigned offset;
+       const struct mio_regmap *regmap;
 
-       switch (reg) {
-       case G_HW_Save_Register(0):
-               offset = M_Offset_G0_HW_Save;
-               break;
-       case G_HW_Save_Register(1):
-               offset = M_Offset_G1_HW_Save;
-               break;
-       case G_Save_Register(0):
-               offset = M_Offset_G0_Save;
-               break;
-       case G_Save_Register(1):
-               offset = M_Offset_G1_Save;
-               break;
-       default:
-               dev_warn(dev->class_dev,
-                        "%s: bug! unhandled register=0x%x in switch\n",
+       if (reg < ARRAY_SIZE(m_series_stc_read_regmap)) {
+               regmap = &m_series_stc_read_regmap[reg];
+       } else {
+               dev_warn(dev->class_dev, "%s: unhandled register=0x%x\n",
                         __func__, reg);
                return 0;
        }
-       return ni_readl(dev, offset);
-}
 
-static uint16_t m_series_stc_readw(struct comedi_device *dev, int reg)
-{
-       unsigned offset;
-
-       switch (reg) {
-       case AI_Status_1_Register:
-               offset = M_Offset_AI_Status_1;
-               break;
-       case AO_Status_1_Register:
-               offset = M_Offset_AO_Status_1;
-               break;
-       case AO_Status_2_Register:
-               offset = M_Offset_AO_Status_2;
-               break;
-       case DIO_Serial_Input_Register:
-               return ni_readb(dev, M_Offset_SCXI_Serial_Data_In);
-       case Joint_Status_1_Register:
-               offset = M_Offset_Joint_Status_1;
-               break;
-       case Joint_Status_2_Register:
-               offset = M_Offset_Joint_Status_2;
-               break;
-       case G_Status_Register:
-               offset = M_Offset_G01_Status;
-               break;
+       switch (regmap->size) {
+       case 4:
+               return ni_readl(dev, regmap->mio_reg);
+       case 2:
+               return ni_readw(dev, regmap->mio_reg);
+       case 1:
+               return ni_readb(dev, regmap->mio_reg);
        default:
-               dev_warn(dev->class_dev,
-                        "%s: bug! unhandled register=0x%x in switch\n",
+               dev_warn(dev->class_dev, "%s: unmapped register=0x%x\n",
                         __func__, reg);
                return 0;
        }
-       return ni_readw(dev, offset);
 }
 
 static void ni_stc_writew(struct comedi_device *dev, uint16_t data, int reg)
@@ -572,7 +450,7 @@ static void ni_stc_writew(struct comedi_device *dev, 
uint16_t data, int reg)
        unsigned long flags;
 
        if (devpriv->is_m_series) {
-               m_series_stc_writew(dev, data, reg);
+               m_series_stc_write(dev, data, reg);
        } else {
                spin_lock_irqsave(&devpriv->window_lock, flags);
                if (!devpriv->mite && reg < 8) {
@@ -590,7 +468,7 @@ static void ni_stc_writel(struct comedi_device *dev, 
uint32_t data, int reg)
        struct ni_private *devpriv = dev->private;
 
        if (devpriv->is_m_series) {
-               m_series_stc_writel(dev, data, reg);
+               m_series_stc_write(dev, data, reg);
        } else {
                ni_stc_writew(dev, data >> 16, reg);
                ni_stc_writew(dev, data & 0xffff, reg + 1);
@@ -604,7 +482,7 @@ static uint16_t ni_stc_readw(struct comedi_device *dev, int 
reg)
        uint16_t val;
 
        if (devpriv->is_m_series) {
-               val = m_series_stc_readw(dev, reg);
+               val = m_series_stc_read(dev, reg);
        } else {
                spin_lock_irqsave(&devpriv->window_lock, flags);
                if (!devpriv->mite && reg < 8) {
@@ -624,7 +502,7 @@ static uint32_t ni_stc_readl(struct comedi_device *dev, int 
reg)
        uint32_t val;
 
        if (devpriv->is_m_series) {
-               val = m_series_stc_readl(dev, reg);
+               val = m_series_stc_read(dev, reg);
        } else {
                val = ni_stc_readw(dev, reg) << 16;
                val |= ni_stc_readw(dev, reg + 1);
-- 
2.3.0

_______________________________________________
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel

Reply via email to