int ni_tio_arm(struct ni_gpct *counter, int arm, unsigned start_trigger) { struct ni_gpct_device *counter_dev = counter->counter_dev; unsigned command_transient_bits = 0; if (arm) { switch (start_trigger) { case NI_GPCT_ARM_IMMEDIATE: command_transient_bits |= Gi_Arm_Bit; break; case NI_GPCT_ARM_PAIRED_IMMEDIATE: command_transient_bits |= Gi_Arm_Bit | Gi_Arm_Copy_Bit; break; default: break; } if (ni_tio_counting_mode_registers_present(counter_dev)) { unsigned counting_mode_bits = 0; switch (start_trigger) { case NI_GPCT_ARM_IMMEDIATE: case NI_GPCT_ARM_PAIRED_IMMEDIATE: break; default: if (start_trigger & NI_GPCT_ARM_UNKNOWN) { /* pass-through the least significant bits so we can figure out what select later */ unsigned hw_arm_select_bits = (start_trigger << Gi_HW_Arm_Select_Shift) & Gi_HW_Arm_Select_Mask (counter_dev->variant); counting_mode_bits |= Gi_HW_Arm_Enable_Bit | hw_arm_select_bits; } else { return -EINVAL; } break; } ni_tio_set_bits(counter, NITIO_Gi_Counting_Mode_Reg (counter->counter_index), Gi_HW_Arm_Select_Mask (counter_dev->variant) | Gi_HW_Arm_Enable_Bit, counting_mode_bits); } } else { command_transient_bits |= Gi_Disarm_Bit; } ni_tio_set_bits_transient(counter, NITIO_Gi_Command_Reg(counter->counter_index), 0, 0, command_transient_bits); return 0; }
int ni_tio_winsn(struct ni_gpct *counter, struct comedi_insn *insn, unsigned int *data) { struct ni_gpct_device *counter_dev = counter->counter_dev; const unsigned channel = CR_CHAN(insn->chanspec); unsigned load_reg; if (insn->n < 1) return 0; switch (channel) { case 0: /* Unsafe if counter is armed. Should probably check status and return -EBUSY if armed. */ /* Don't disturb load source select, just use whichever load register is already selected. */ load_reg = ni_tio_next_load_register(counter); write_register(counter, data[0], load_reg); ni_tio_set_bits_transient(counter, NITIO_Gi_Command_Reg(counter-> counter_index), 0, 0, Gi_Load_Bit); /* restore state of load reg to whatever the user set last set it to */ write_register(counter, counter_dev->regs[load_reg], load_reg); break; case 1: counter_dev->regs[NITIO_Gi_LoadA_Reg(counter->counter_index)] = data[0]; write_register(counter, data[0], NITIO_Gi_LoadA_Reg(counter->counter_index)); break; case 2: counter_dev->regs[NITIO_Gi_LoadB_Reg(counter->counter_index)] = data[0]; write_register(counter, data[0], NITIO_Gi_LoadB_Reg(counter->counter_index)); break; default: return -EINVAL; break; } return 0; }
int ni_tio_winsn(struct ni_gpct *counter, struct comedi_insn *insn, unsigned int *data) { struct ni_gpct_device *counter_dev = counter->counter_dev; const unsigned channel = CR_CHAN(insn->chanspec); unsigned load_reg; if (insn->n < 1) return 0; switch (channel) { case 0: load_reg = ni_tio_next_load_register(counter); write_register(counter, data[0], load_reg); ni_tio_set_bits_transient(counter, NITIO_Gi_Command_Reg(counter-> counter_index), 0, 0, Gi_Load_Bit); write_register(counter, counter_dev->regs[load_reg], load_reg); break; case 1: counter_dev->regs[NITIO_Gi_LoadA_Reg(counter->counter_index)] = data[0]; write_register(counter, data[0], NITIO_Gi_LoadA_Reg(counter->counter_index)); break; case 2: counter_dev->regs[NITIO_Gi_LoadB_Reg(counter->counter_index)] = data[0]; write_register(counter, data[0], NITIO_Gi_LoadB_Reg(counter->counter_index)); break; default: return -EINVAL; break; } return 0; }