static int ni_pcidio_insn_config(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { if (insn->n != 1) return -EINVAL; switch (data[0]) { case INSN_CONFIG_DIO_OUTPUT: s->io_bits |= 1 << CR_CHAN(insn->chanspec); break; case INSN_CONFIG_DIO_INPUT: s->io_bits &= ~(1 << CR_CHAN(insn->chanspec)); break; case INSN_CONFIG_DIO_QUERY: data[1] = (s-> io_bits & (1 << CR_CHAN(insn->chanspec))) ? COMEDI_OUTPUT : COMEDI_INPUT; return insn->n; break; default: return -EINVAL; } writel(s->io_bits, devpriv->mite->daq_io_addr + Port_Pin_Directions(0)); return 1; }
static int ni_pcidio_cmd(struct comedi_device *dev, struct comedi_subdevice *s) { struct comedi_cmd *cmd = &s->async->cmd; writel(0x0000, devpriv->mite->daq_io_addr + Port_Pin_Directions(0)); if (1) { writeb(0x0f, devpriv->mite->daq_io_addr + Data_Path); writeb(TransferWidth(0) | TransferLength(0), devpriv->mite->daq_io_addr + Transfer_Size_Control); } else { writeb(0x03, devpriv->mite->daq_io_addr + Data_Path); writeb(TransferWidth(3) | TransferLength(0), devpriv->mite->daq_io_addr + Transfer_Size_Control); } if (cmd->scan_begin_src == TRIG_TIMER) { writeb(0, devpriv->mite->daq_io_addr + OpMode); writeb(0x00, devpriv->mite->daq_io_addr + ClockReg); writeb(1, devpriv->mite->daq_io_addr + Sequence); writeb(0x04, devpriv->mite->daq_io_addr + ReqReg); writeb(4, devpriv->mite->daq_io_addr + BlockMode); writeb(3, devpriv->mite->daq_io_addr + LinePolarities); writeb(0xc0, devpriv->mite->daq_io_addr + AckSer); writel(ni_pcidio_ns_to_timer(&cmd->scan_begin_arg, TRIG_ROUND_NEAREST), devpriv->mite->daq_io_addr + StartDelay); writeb(1, devpriv->mite->daq_io_addr + ReqDelay); writeb(1, devpriv->mite->daq_io_addr + ReqNotDelay); writeb(1, devpriv->mite->daq_io_addr + AckDelay); writeb(0x0b, devpriv->mite->daq_io_addr + AckNotDelay); writeb(0x01, devpriv->mite->daq_io_addr + Data1Delay); writew(0, devpriv->mite->daq_io_addr + ClockSpeed); writeb(0, devpriv->mite->daq_io_addr + DAQOptions); } else { writeb(0, devpriv->mite->daq_io_addr + OpMode); writeb(0x00, devpriv->mite->daq_io_addr + ClockReg); writeb(0, devpriv->mite->daq_io_addr + Sequence); writeb(0x00, devpriv->mite->daq_io_addr + ReqReg); writeb(4, devpriv->mite->daq_io_addr + BlockMode); writeb(0, devpriv->mite->daq_io_addr + LinePolarities); writeb(0x00, devpriv->mite->daq_io_addr + AckSer); writel(1, devpriv->mite->daq_io_addr + StartDelay); writeb(1, devpriv->mite->daq_io_addr + ReqDelay); writeb(1, devpriv->mite->daq_io_addr + ReqNotDelay); writeb(1, devpriv->mite->daq_io_addr + AckDelay); writeb(0x0C, devpriv->mite->daq_io_addr + AckNotDelay); writeb(0x10, devpriv->mite->daq_io_addr + Data1Delay); writew(0, devpriv->mite->daq_io_addr + ClockSpeed); writeb(0x60, devpriv->mite->daq_io_addr + DAQOptions); } if (cmd->stop_src == TRIG_COUNT) { writel(cmd->stop_arg, devpriv->mite->daq_io_addr + Transfer_Count); } else { } #ifdef USE_DMA writeb(ClearPrimaryTC | ClearSecondaryTC, devpriv->mite->daq_io_addr + Group_1_First_Clear); { int retval = setup_mite_dma(dev, s); if (retval) return retval; } #else writeb(0x00, devpriv->mite->daq_io_addr + DMA_Line_Control_Group1); #endif writeb(0x00, devpriv->mite->daq_io_addr + DMA_Line_Control_Group2); writeb(0xff, devpriv->mite->daq_io_addr + Group_1_First_Clear); writeb(IntEn, devpriv->mite->daq_io_addr + Interrupt_Control); writeb(0x03, devpriv->mite->daq_io_addr + Master_DMA_And_Interrupt_Control); if (cmd->stop_src == TRIG_NONE) { devpriv->OpModeBits = DataLatching(0) | RunMode(7); } else { devpriv->OpModeBits = Numbered | RunMode(7); } if (cmd->start_src == TRIG_NOW) { writeb(devpriv->OpModeBits, devpriv->mite->daq_io_addr + OpMode); s->async->inttrig = NULL; } else { s->async->inttrig = ni_pcidio_inttrig; } DPRINTK("ni_pcidio: command started\n"); return 0; }
static int nidio_attach(struct comedi_device *dev, struct comedi_devconfig *it) { struct comedi_subdevice *s; int i; int ret; int n_subdevices; unsigned int irq; printk("comedi%d: nidio:", dev->minor); if ((ret = alloc_private(dev, sizeof(struct nidio96_private))) < 0) return ret; spin_lock_init(&devpriv->mite_channel_lock); ret = nidio_find_device(dev, it->options[0], it->options[1]); if (ret < 0) return ret; ret = mite_setup(devpriv->mite); if (ret < 0) { printk("error setting up mite\n"); return ret; } comedi_set_hw_dev(dev, &devpriv->mite->pcidev->dev); devpriv->di_mite_ring = mite_alloc_ring(devpriv->mite); if (devpriv->di_mite_ring == NULL) return -ENOMEM; dev->board_name = this_board->name; irq = mite_irq(devpriv->mite); printk(" %s", dev->board_name); if (this_board->uses_firmware) { ret = pci_6534_upload_firmware(dev, it->options); if (ret < 0) return ret; } if (!this_board->is_diodaq) { n_subdevices = this_board->n_8255; } else { n_subdevices = 1; } if ((ret = alloc_subdevices(dev, n_subdevices)) < 0) return ret; if (!this_board->is_diodaq) { for (i = 0; i < this_board->n_8255; i++) { subdev_8255_init(dev, dev->subdevices + i, nidio96_8255_cb, (unsigned long)(devpriv->mite-> daq_io_addr + NIDIO_8255_BASE(i))); } } else { printk(" rev=%d", readb(devpriv->mite->daq_io_addr + Chip_Version)); s = dev->subdevices + 0; dev->read_subdev = s; s->type = COMEDI_SUBD_DIO; s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_LSAMPL | SDF_PACKED | SDF_CMD_READ; s->n_chan = 32; s->range_table = &range_digital; s->maxdata = 1; s->insn_config = &ni_pcidio_insn_config; s->insn_bits = &ni_pcidio_insn_bits; s->do_cmd = &ni_pcidio_cmd; s->do_cmdtest = &ni_pcidio_cmdtest; s->cancel = &ni_pcidio_cancel; s->len_chanlist = 32; s->buf_change = &ni_pcidio_change; s->async_dma_dir = DMA_BIDIRECTIONAL; writel(0, devpriv->mite->daq_io_addr + Port_IO(0)); writel(0, devpriv->mite->daq_io_addr + Port_Pin_Directions(0)); writel(0, devpriv->mite->daq_io_addr + Port_Pin_Mask(0)); writeb(0x00, devpriv->mite->daq_io_addr + Master_DMA_And_Interrupt_Control); ret = request_irq(irq, nidio_interrupt, IRQF_SHARED, "ni_pcidio", dev); if (ret < 0) { printk(" irq not available"); } dev->irq = irq; } printk("\n"); return 0; }
static int ni_pcidio_cmd(struct comedi_device *dev, struct comedi_subdevice *s) { struct comedi_cmd *cmd = &s->async->cmd; /* XXX configure ports for input */ writel(0x0000, devpriv->mite->daq_io_addr + Port_Pin_Directions(0)); if (1) { /* enable fifos A B C D */ writeb(0x0f, devpriv->mite->daq_io_addr + Data_Path); /* set transfer width a 32 bits */ writeb(TransferWidth(0) | TransferLength(0), devpriv->mite->daq_io_addr + Transfer_Size_Control); } else { writeb(0x03, devpriv->mite->daq_io_addr + Data_Path); writeb(TransferWidth(3) | TransferLength(0), devpriv->mite->daq_io_addr + Transfer_Size_Control); } /* protocol configuration */ if (cmd->scan_begin_src == TRIG_TIMER) { /* page 4-5, "input with internal REQs" */ writeb(0, devpriv->mite->daq_io_addr + OpMode); writeb(0x00, devpriv->mite->daq_io_addr + ClockReg); writeb(1, devpriv->mite->daq_io_addr + Sequence); writeb(0x04, devpriv->mite->daq_io_addr + ReqReg); writeb(4, devpriv->mite->daq_io_addr + BlockMode); writeb(3, devpriv->mite->daq_io_addr + LinePolarities); writeb(0xc0, devpriv->mite->daq_io_addr + AckSer); writel(ni_pcidio_ns_to_timer(&cmd->scan_begin_arg, TRIG_ROUND_NEAREST), devpriv->mite->daq_io_addr + StartDelay); writeb(1, devpriv->mite->daq_io_addr + ReqDelay); writeb(1, devpriv->mite->daq_io_addr + ReqNotDelay); writeb(1, devpriv->mite->daq_io_addr + AckDelay); writeb(0x0b, devpriv->mite->daq_io_addr + AckNotDelay); writeb(0x01, devpriv->mite->daq_io_addr + Data1Delay); /* manual, page 4-5: ClockSpeed comment is incorrectly listed * on DAQOptions */ writew(0, devpriv->mite->daq_io_addr + ClockSpeed); writeb(0, devpriv->mite->daq_io_addr + DAQOptions); } else { /* TRIG_EXT */ /* page 4-5, "input with external REQs" */ writeb(0, devpriv->mite->daq_io_addr + OpMode); writeb(0x00, devpriv->mite->daq_io_addr + ClockReg); writeb(0, devpriv->mite->daq_io_addr + Sequence); writeb(0x00, devpriv->mite->daq_io_addr + ReqReg); writeb(4, devpriv->mite->daq_io_addr + BlockMode); writeb(0, devpriv->mite->daq_io_addr + LinePolarities); writeb(0x00, devpriv->mite->daq_io_addr + AckSer); writel(1, devpriv->mite->daq_io_addr + StartDelay); writeb(1, devpriv->mite->daq_io_addr + ReqDelay); writeb(1, devpriv->mite->daq_io_addr + ReqNotDelay); writeb(1, devpriv->mite->daq_io_addr + AckDelay); writeb(0x0C, devpriv->mite->daq_io_addr + AckNotDelay); writeb(0x10, devpriv->mite->daq_io_addr + Data1Delay); writew(0, devpriv->mite->daq_io_addr + ClockSpeed); writeb(0x60, devpriv->mite->daq_io_addr + DAQOptions); } if (cmd->stop_src == TRIG_COUNT) { writel(cmd->stop_arg, devpriv->mite->daq_io_addr + Transfer_Count); } else { /* XXX */ } #ifdef USE_DMA writeb(ClearPrimaryTC | ClearSecondaryTC, devpriv->mite->daq_io_addr + Group_1_First_Clear); { int retval = setup_mite_dma(dev, s); if (retval) return retval; } #else writeb(0x00, devpriv->mite->daq_io_addr + DMA_Line_Control_Group1); #endif writeb(0x00, devpriv->mite->daq_io_addr + DMA_Line_Control_Group2); /* clear and enable interrupts */ writeb(0xff, devpriv->mite->daq_io_addr + Group_1_First_Clear); /* writeb(ClearExpired, devpriv->mite->daq_io_addr+Group_1_Second_Clear); */ writeb(IntEn, devpriv->mite->daq_io_addr + Interrupt_Control); writeb(0x03, devpriv->mite->daq_io_addr + Master_DMA_And_Interrupt_Control); if (cmd->stop_src == TRIG_NONE) { devpriv->OpModeBits = DataLatching(0) | RunMode(7); } else { /* TRIG_TIMER */ devpriv->OpModeBits = Numbered | RunMode(7); } if (cmd->start_src == TRIG_NOW) { /* start */ writeb(devpriv->OpModeBits, devpriv->mite->daq_io_addr + OpMode); s->async->inttrig = NULL; } else { /* TRIG_INT */ s->async->inttrig = ni_pcidio_inttrig; } DPRINTK("ni_pcidio: command started\n"); return 0; }