for(pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL); pcidev != NULL ;
pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pcidev)) {
if(pcidev->vendor==PCI_VENDOR_ID_NATINST){
+ unsigned i;
+
mite=kmalloc(sizeof(*mite),GFP_KERNEL);
if(!mite){
printk("mite: allocation failed\n");
memset(mite,0,sizeof(*mite));
spin_lock_init(&mite->lock);
mite->pcidev=pci_dev_get(pcidev);
-
+ for(i = 0; i < MAX_MITE_DMA_CHANNELS; ++i)
+ {
+ mite->channels[i].mite = mite;
+ mite->channels[i].channel = i;
+ }
mite->next=mite_devices;
mite_devices=mite;
}
if(!mite)return;
+ pci_disable_device(mite->pcidev);
if(mite->mite_io_addr){
iounmap(mite->mite_io_addr);
mite->mite_io_addr=NULL;
}
-int mite_alloc_channel(struct mite_struct *mite)
+struct mite_channel* mite_offset_request_channel(struct mite_struct *mite, struct mite_dma_descriptor_ring *ring,
+ unsigned first_channel_to_try)
{
int i;
unsigned long flags;
- int retval = -1;
+ struct mite_channel *channel = NULL;
- // spin lock so mite_free_channel can be called safely from interrupts
+ // spin lock so mite_release_channel can be called safely from interrupts
comedi_spin_lock_irqsave(&mite->lock, flags);
- for(i = 0; i < mite->num_channels; ++i)
+ for(i = first_channel_to_try; i < mite->num_channels; ++i)
{
if(mite->channel_allocated[i] == 0)
{
mite->channel_allocated[i] = 1;
- retval = i;
+ channel = &mite->channels[i];
+ channel->ring = ring;
break;
}
}
comedi_spin_unlock_irqrestore(&mite->lock, flags);
- return retval;
+ return channel;
}
-void mite_free_channel(struct mite_struct *mite, unsigned channel)
+void mite_release_channel(struct mite_channel *mite_chan)
{
+ struct mite_struct *mite = mite_chan->mite;
unsigned long flags;
- BUG_ON(channel >= mite->num_channels);
- // spin lock to prevent races with mite_alloc_channel
+ // spin lock to prevent races with mite_request_channel
comedi_spin_lock_irqsave(&mite->lock, flags);
- mite->channel_allocated[channel] = 0;
+ mite->channel_allocated[mite_chan->channel] = 0;
+ mite_chan->ring = NULL;
comedi_spin_unlock_irqrestore(&mite->lock, flags);
}
-void mite_dma_arm( struct mite_struct *mite, unsigned int channel )
+void mite_dma_arm(struct mite_channel *mite_chan)
{
+ struct mite_struct *mite = mite_chan->mite;
int chor;
MDPRINTK("mite_dma_arm ch%i\n", channel);
/* arm */
chor = CHOR_START;
- writel(chor, mite->mite_io_addr + MITE_CHOR(channel));
+ writel(chor, mite->mite_io_addr + MITE_CHOR(mite_chan->channel));
// mite_dma_tcr(mite, channel);
}
/**************************************/
-int mite_load_buffer(struct mite_struct *mite, unsigned int channel, comedi_async *async)
+int mite_buf_change(struct mite_dma_descriptor_ring *ring, comedi_async *async)
{
unsigned int n_links;
int i;
- struct mite_channel *mite_chan = &mite->channels[ channel ];
-
- MDPRINTK("mite_load_buffer ch%i\n", channel);
- if(mite_chan->ring){
- kfree(mite_chan->ring);
- mite_chan->ring = NULL;
+ if(ring->descriptors){
+ kfree(ring->descriptors);
}
+ ring->descriptors = NULL;
+ ring->n_links = 0;
if(async->prealloc_bufsz==0){
return 0;
MDPRINTK("buf=%p buf(bus)=%08lx bufsz=0x%08x n_links=0x%04x\n",
async->prealloc_buf, virt_to_bus(async->prealloc_buf), async->prealloc_bufsz, n_links);
- mite_chan->ring = kmalloc(n_links * sizeof(struct mite_dma_chain), GFP_KERNEL);
- if(!mite_chan->ring){
+ ring->descriptors = kmalloc(n_links * sizeof(struct mite_dma_descriptor), GFP_KERNEL);
+ if(!ring->descriptors){
printk("mite: ring buffer allocation failed\n");
return -ENOMEM;
}
- mite_chan->n_links = n_links;
- mite_chan->current_link = 0;
-
- for(i=0;i<n_links;i++){
- mite_chan->ring[i].count = cpu_to_le32(PAGE_SIZE);
- mite_chan->ring[i].addr = cpu_to_le32(virt_to_bus(
- (void *)async->buf_page_list[i]));
- mite_chan->ring[i].next = cpu_to_le32(virt_to_bus(
- mite_chan->ring+i+1));
+ ring->n_links = n_links;
+
+ for(i = 0; i < n_links; i++){
+ ring->descriptors[i].count = cpu_to_le32(PAGE_SIZE);
+ ring->descriptors[i].addr = cpu_to_le32(virt_to_bus(
+ (void *)async->buf_page_list[i]));
+ ring->descriptors[i].next = cpu_to_le32(virt_to_bus(
+ ring->descriptors + i + 1));
}
-
- mite_chan->ring[n_links-1].next = cpu_to_le32(virt_to_bus(
- mite_chan->ring));
-
+ ring->descriptors[n_links - 1].next = cpu_to_le32(virt_to_bus(
+ ring->descriptors));
+ /* barrier is meant to insure that all the writes to the dma descriptors
+ have completed before the dma controller is commanded to read them */
+ smp_wmb();
return 0;
}
-int mite_buf_change(struct mite_struct *mite, unsigned int channel,
- comedi_async *async, unsigned long new_size)
-{
- MDPRINTK("mite_buf_change ch%i\n", channel);
-
- mite_load_buffer(mite, channel, async);
-
- return 0;
-}
-
-void mite_prep_dma( struct mite_struct *mite, unsigned int channel,
+void mite_prep_dma(struct mite_channel *mite_chan,
unsigned int num_device_bits, unsigned int num_memory_bits )
{
unsigned int chor,chcr,mcr,dcr,lkcr;
- struct mite_channel *mite_chan = &mite->channels[ channel ];
+ struct mite_struct *mite = mite_chan->mite;
- MDPRINTK("mite_prep_dma ch%i\n", channel );
+ MDPRINTK("mite_prep_dma ch%i\n", mite_chan->channel);
/* reset DMA and FIFO */
chor = CHOR_DMARESET | CHOR_FRESET;
- writel(chor, mite->mite_io_addr + MITE_CHOR(channel));
+ writel(chor, mite->mite_io_addr + MITE_CHOR(mite_chan->channel));
/* short link chaining mode */
chcr = CHCR_SET_DMA_IE | CHCR_LINKSHORT | CHCR_SET_DONE_IE | CHCR_BURSTEN;
if(mite_chan->dir == COMEDI_INPUT){
chcr |= CHCR_DEV_TO_MEM;
}
- writel(chcr, mite->mite_io_addr + MITE_CHCR(channel));
+ writel(chcr, mite->mite_io_addr + MITE_CHCR(mite_chan->channel));
/* to/from memory */
mcr = CR_RL(64) | CR_ASEQUP;
rt_printk( "mite: bug! invalid mem bit width for dma transfer\n" );
break;
}
- writel(mcr, mite->mite_io_addr + MITE_MCR(channel));
+ writel(mcr, mite->mite_io_addr + MITE_MCR(mite_chan->channel));
/* from/to device */
dcr = CR_RL(64) | CR_ASEQUP;
- dcr |= CR_PORTIO | CR_AMDEVICE | CR_REQSDRQ(channel);
+ dcr |= CR_PORTIO | CR_AMDEVICE | CR_REQSDRQ(mite_chan->channel);
switch( num_device_bits ){
case 8:
dcr |= CR_PSIZE8;
rt_printk( "mite: bug! invalid dev bit width for dma transfer\n" );
break;
}
- writel(dcr, mite->mite_io_addr + MITE_DCR(channel));
+ writel(dcr, mite->mite_io_addr + MITE_DCR(mite_chan->channel));
/* reset the DAR */
- writel(0, mite->mite_io_addr + MITE_DAR(channel));
+ writel(0, mite->mite_io_addr + MITE_DAR(mite_chan->channel));
/* the link is 32bits */
lkcr = CR_RL(64) | CR_ASEQUP | CR_PSIZE32;
- writel(lkcr, mite->mite_io_addr + MITE_LKCR(channel));
+ writel(lkcr, mite->mite_io_addr + MITE_LKCR(mite_chan->channel));
/* starting address for link chaining */
- writel(virt_to_bus(mite_chan->ring),
- mite->mite_io_addr + MITE_LKAR(channel));
+ writel(virt_to_bus(mite_chan->ring->descriptors),
+ mite->mite_io_addr + MITE_LKAR(mite_chan->channel));
MDPRINTK("exit mite_prep_dma\n");
}
-u32 mite_device_bytes_transferred(struct mite_struct *mite, unsigned int chan)
+u32 mite_device_bytes_transferred(struct mite_channel *mite_chan)
{
- return readl(mite->mite_io_addr + MITE_DAR(chan));
+ struct mite_struct *mite = mite_chan->mite;
+ return readl(mite->mite_io_addr + MITE_DAR(mite_chan->channel));
}
-u32 mite_bytes_in_transit(struct mite_struct *mite, unsigned int chan)
+u32 mite_bytes_in_transit(struct mite_channel *mite_chan)
{
- return readl(mite->mite_io_addr + MITE_FCR(chan)) & 0x000000FF;
+ struct mite_struct *mite = mite_chan->mite;
+ return readl(mite->mite_io_addr + MITE_FCR(mite_chan->channel)) & 0x000000FF;
}
// returns lower bound for number of bytes transferred from device to memory
-u32 mite_bytes_written_to_memory_lb(struct mite_struct *mite, unsigned int chan)
+u32 mite_bytes_written_to_memory_lb(struct mite_channel *mite_chan)
{
u32 device_byte_count;
- device_byte_count = mite_device_bytes_transferred(mite, chan);
- return device_byte_count - mite_bytes_in_transit(mite, chan);
+ device_byte_count = mite_device_bytes_transferred(mite_chan);
+ return device_byte_count - mite_bytes_in_transit(mite_chan);
}
// returns upper bound for number of bytes transferred from device to memory
-u32 mite_bytes_written_to_memory_ub(struct mite_struct *mite, unsigned int chan)
+u32 mite_bytes_written_to_memory_ub(struct mite_channel *mite_chan)
{
u32 in_transit_count;
- in_transit_count = mite_bytes_in_transit(mite, chan);
- return mite_device_bytes_transferred(mite, chan) - in_transit_count;
+ in_transit_count = mite_bytes_in_transit(mite_chan);
+ return mite_device_bytes_transferred(mite_chan) - in_transit_count;
}
// returns lower bound for number of bytes read from memory for transfer to device
-u32 mite_bytes_read_from_memory_lb(struct mite_struct *mite, unsigned int chan)
+u32 mite_bytes_read_from_memory_lb(struct mite_channel *mite_chan)
{
u32 device_byte_count;
- device_byte_count = mite_device_bytes_transferred(mite, chan);
- return device_byte_count + mite_bytes_in_transit(mite, chan);
+ device_byte_count = mite_device_bytes_transferred(mite_chan);
+ return device_byte_count + mite_bytes_in_transit(mite_chan);
}
// returns upper bound for number of bytes read from memory for transfer to device
-u32 mite_bytes_read_from_memory_ub(struct mite_struct *mite, unsigned int chan)
+u32 mite_bytes_read_from_memory_ub(struct mite_channel *mite_chan)
{
u32 in_transit_count;
- in_transit_count = mite_bytes_in_transit(mite, chan);
- return mite_device_bytes_transferred(mite, chan) + in_transit_count;
+ in_transit_count = mite_bytes_in_transit(mite_chan);
+ return mite_device_bytes_transferred(mite_chan) + in_transit_count;
}
-int mite_dma_tcr(struct mite_struct *mite, unsigned int channel)
+unsigned mite_dma_tcr(struct mite_channel *mite_chan)
{
+ struct mite_struct *mite = mite_chan->mite;
int tcr;
int lkar;
- lkar = readl(mite->mite_io_addr + MITE_LKAR(channel));
- tcr = readl(mite->mite_io_addr + MITE_TCR(channel));
- MDPRINTK("mite_dma_tcr ch%i, lkar=0x%08x tcr=%d\n", channel, lkar, tcr);
+ lkar = readl(mite->mite_io_addr + MITE_LKAR(mite_chan->channel));
+ tcr = readl(mite->mite_io_addr + MITE_TCR(mite_chan->channel));
+ MDPRINTK("mite_dma_tcr ch%i, lkar=0x%08x tcr=%d\n", mite_chan->channel, lkar, tcr);
return tcr;
}
-void mite_dma_disarm(struct mite_struct *mite, unsigned int channel)
+void mite_dma_disarm(struct mite_channel *mite_chan)
{
- int chor;
+ struct mite_struct *mite = mite_chan->mite;
+ unsigned chor;
/* disarm */
chor = CHOR_ABORT;
- writel(chor, mite->mite_io_addr + MITE_CHOR(channel));
+ writel(chor, mite->mite_io_addr + MITE_CHOR(mite_chan->channel));
}
-int mite_sync_input_dma(struct mite_struct *mite, unsigned mite_channel, comedi_async *async)
+int mite_sync_input_dma(struct mite_channel *mite_chan, comedi_async *async)
{
int count;
unsigned int nbytes, old_alloc_count;
// write alloc as much as we can
comedi_buf_write_alloc(async, async->prealloc_bufsz);
- nbytes = mite_bytes_written_to_memory_lb(mite, mite_channel);
- if((int)(mite_bytes_written_to_memory_ub(mite, mite_channel) - old_alloc_count) > 0)
+ nbytes = mite_bytes_written_to_memory_lb(mite_chan);
+ if((int)(mite_bytes_written_to_memory_ub(mite_chan) - old_alloc_count) > 0)
{
rt_printk("mite: DMA overwrite of free area\n");
async->events |= COMEDI_CB_OVERFLOW;
return 0;
}
-int mite_sync_output_dma(struct mite_struct *mite, unsigned mite_channel, comedi_async *async)
+int mite_sync_output_dma(struct mite_channel *mite_chan, comedi_async *async)
{
int count;
u32 nbytes_ub, nbytes_lb;
old_alloc_count = async->buf_read_alloc_count;
// read alloc as much as we can
comedi_buf_read_alloc(async, async->prealloc_bufsz);
- nbytes_lb = mite_bytes_read_from_memory_lb(mite, mite_channel);
+ nbytes_lb = mite_bytes_read_from_memory_lb(mite_chan);
if(async->cmd.stop_src == TRIG_COUNT &&
(int) (nbytes_lb - stop_count) > 0)
nbytes_lb = stop_count;
- nbytes_ub = mite_bytes_read_from_memory_ub(mite, mite_channel);
+ nbytes_ub = mite_bytes_read_from_memory_ub(mite_chan);
if(async->cmd.stop_src == TRIG_COUNT &&
(int) (nbytes_ub - stop_count) > 0)
nbytes_ub = stop_count;
"28", "lpauses", "30", "int",
};
-void mite_dump_regs(struct mite_struct *mite, int channel)
+void mite_dump_regs(struct mite_channel *mite_chan)
{
- unsigned long mite_io_addr = (unsigned long) mite->mite_io_addr;
+ unsigned long mite_io_addr = (unsigned long) mite_chan->mite->mite_io_addr;
unsigned long addr=0;
unsigned long temp=0;
- printk("mite_dump_regs ch%i\n", channel);
- printk("mite address is =0x%08lx\n",mite_io_addr);
+ printk("mite_dump_regs ch%i\n", mite_chan->channel);
+ printk("mite address is =0x%08lx\n", mite_io_addr);
addr = mite_io_addr+MITE_CHOR(channel);
printk("mite status[CHOR]at 0x%08lx =0x%08lx\n",addr, temp=readl(addr));
#endif
EXPORT_SYMBOL(mite_devices);
EXPORT_SYMBOL(mite_list_devices);
-EXPORT_SYMBOL(mite_alloc_channel);
-EXPORT_SYMBOL(mite_free_channel);
+EXPORT_SYMBOL(mite_offset_request_channel);
+EXPORT_SYMBOL(mite_release_channel);
EXPORT_SYMBOL(mite_prep_dma);
EXPORT_SYMBOL(mite_buf_change);
EXPORT_SYMBOL(mite_bytes_written_to_memory_lb);
#define MAX_MITE_DMA_CHANNELS 8
-struct mite_dma_chain{
+struct mite_dma_descriptor{
u32 count;
u32 addr;
u32 next;
u32 dar;
};
-struct mite_channel{
- int DMA_CheckNearEnd;
-
- int dir;
- unsigned int current_link;
+struct mite_dma_descriptor_ring
+{
unsigned int n_links;
+ struct mite_dma_descriptor *descriptors;
+};
+
+static inline struct mite_dma_descriptor_ring* mite_alloc_ring(void)
+{
+ struct mite_dma_descriptor_ring *ring = kmalloc(sizeof(struct mite_dma_descriptor_ring), GFP_KERNEL);
+ if(ring == NULL) return ring;
+ ring->n_links = 0;
+ ring->descriptors = NULL;
+ return ring;
+};
+
+static inline void mite_free_ring(struct mite_dma_descriptor_ring *ring)
+{
+ if(ring)
+ {
+ if(ring->descriptors) kfree(ring->descriptors);
+ kfree(ring);
+ }
+};
- struct mite_dma_chain *ring;
+struct mite_channel{
+ struct mite_struct *mite;
+ unsigned channel;
+ int dir;
+ struct mite_dma_descriptor_ring *ring;
};
struct mite_struct{
int mite_setup(struct mite_struct *mite);
void mite_unsetup(struct mite_struct *mite);
void mite_list_devices(void);
-int mite_alloc_channel(struct mite_struct *mite);
-void mite_free_channel(struct mite_struct *mite, unsigned channel);
-
-int mite_dma_tcr(struct mite_struct *mite, unsigned int channel );
-void mite_dma_arm(struct mite_struct *mite, unsigned int channel );
-void mite_dma_disarm(struct mite_struct *mite, unsigned int channel );
-int mite_sync_input_dma(struct mite_struct *mite, unsigned mite_channel, comedi_async *async);
-int mite_sync_output_dma(struct mite_struct *mite, unsigned mite_channel, comedi_async *async);
-u32 mite_bytes_written_to_memory_lb(struct mite_struct *mite, unsigned int chan);
-u32 mite_bytes_written_to_memory_ub(struct mite_struct *mite, unsigned int chan);
-u32 mite_bytes_read_from_memory_lb(struct mite_struct *mite, unsigned int chan);
-u32 mite_bytes_read_from_memory_ub(struct mite_struct *mite, unsigned int chan);
-u32 mite_bytes_in_transit(struct mite_struct *mite, unsigned int chan);
+struct mite_channel* mite_offset_request_channel(struct mite_struct *mite, struct mite_dma_descriptor_ring *ring,
+ unsigned first_channel_to_try);
+static inline struct mite_channel* mite_request_channel(
+ struct mite_struct *mite, struct mite_dma_descriptor_ring *ring)
+{
+ return mite_offset_request_channel(mite, ring, 0);
+}
+void mite_release_channel(struct mite_channel *mite_chan);
+
+unsigned mite_dma_tcr(struct mite_channel *mite_chan );
+void mite_dma_arm(struct mite_channel *mite_chan );
+void mite_dma_disarm(struct mite_channel *mite_chan );
+int mite_sync_input_dma(struct mite_channel *mite_chan, comedi_async *async);
+int mite_sync_output_dma(struct mite_channel *mite_chan, comedi_async *async);
+u32 mite_bytes_written_to_memory_lb(struct mite_channel *mite_chan);
+u32 mite_bytes_written_to_memory_ub(struct mite_channel *mite_chan);
+u32 mite_bytes_read_from_memory_lb(struct mite_channel *mite_chan);
+u32 mite_bytes_read_from_memory_ub(struct mite_channel *mite_chan);
+u32 mite_bytes_in_transit(struct mite_channel *mite_chan);
#if 0
unsigned long mite_ll_from_kvmem(struct mite_struct *mite,comedi_async *async,int len);
void mite_setregs(struct mite_struct *mite,unsigned long ll_start,int chan, int dir);
#endif
-void mite_prep_dma(struct mite_struct *mite, unsigned int channel,
+void mite_prep_dma(struct mite_channel *mite_chan,
unsigned int num_device_bits, unsigned int num_memory_bits );
-int mite_buf_change(struct mite_struct *mite, unsigned int channel,
- comedi_async *async, unsigned long new_size);
+int mite_buf_change(struct mite_dma_descriptor_ring *ring, comedi_async *async);
#ifdef DEBUG_MITE
void mite_print_chsr(unsigned int chsr);
-void mite_dump_regs(struct mite_struct *mite, int channel);
+void mite_dump_regs(struct mite_channel *mite_chan);
#endif
static inline int CHAN_OFFSET(int channel)
CHSR_DOERR = (3<<0),
};
+static inline void mite_dma_reset(struct mite_channel *mite_chan)
+{
+ writel(CHOR_DMARESET | CHOR_FRESET, mite_chan->mite->mite_io_addr + MITE_CHOR(mite_chan->channel));
+};
+
#endif
devpriv->counters[i].read_register = ni_gpct_read_register;
devpriv->counters[i].variant = ni_gpct_variant_660x;
devpriv->counters[i].clock_period_ps = 0;
- devpriv->counters[i].mite = devpriv->mite;
- devpriv->counters[i].mite_channel = -1;
+ devpriv->counters[i].mite_chan = NULL;
}else
{
s->type = COMEDI_SUBD_UNUSED;
#ifdef PCIDMA
//static void mite_handle_interrupt(comedi_device *dev,unsigned int status);
static int ni_ai_drain_dma(comedi_device *dev );
-#endif
+
+/* DMA channel setup */
+static inline void ni_set_ai_dma_channel(comedi_device *dev, int channel)
+{
+ unsigned long flags;
+
+ comedi_spin_lock_irqsave(&devpriv->soft_reg_copy_lock, flags);
+ devpriv->ai_ao_select_reg &= ~AI_DMA_Select_Mask;
+ /*FIXME this only works for channels 0,1,2. Need to reverse
+ engineer proper bits for higher mite channels with m-series */
+ if(channel >= 0)
+ {
+ devpriv->ai_ao_select_reg |= (1 << (channel + AI_DMA_Select_Shift)) & AI_DMA_Select_Mask;
+ }
+ ni_writeb(devpriv->ai_ao_select_reg, AI_AO_Select);
+ mmiowb();
+ comedi_spin_unlock_irqrestore(&devpriv->soft_reg_copy_lock, flags);
+}
+
+static inline void ni_set_ao_dma_channel(comedi_device *dev, int channel)
+{
+ unsigned long flags;
+
+ comedi_spin_lock_irqsave(&devpriv->soft_reg_copy_lock, flags);
+ devpriv->ai_ao_select_reg &= ~AO_DMA_Select_Mask;
+ /*FIXME this only works for channels 0,1,2. Need to reverse
+ engineer proper bits for higher mite channels with m-series */
+ if(channel >= 0)
+ {
+ devpriv->ai_ao_select_reg |= (1 << (channel + AO_DMA_Select_Shift)) & AO_DMA_Select_Mask;
+ }
+ ni_writeb(devpriv->ai_ao_select_reg, AI_AO_Select);
+ mmiowb();
+ comedi_spin_unlock_irqrestore(&devpriv->soft_reg_copy_lock, flags);
+}
+
+static int ni_request_ai_mite_channel(comedi_device *dev)
+{
+ unsigned long flags;
+
+ comedi_spin_lock_irqsave(&devpriv->mite_channel_lock, flags);
+ BUG_ON(devpriv->ai_mite_chan);
+ devpriv->ai_mite_chan = mite_request_channel(devpriv->mite, devpriv->ai_mite_ring);
+ if(devpriv->ai_mite_chan == NULL)
+ {
+ comedi_spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags);
+ comedi_error(dev, "failed to reserve mite dma channel for analog input.");
+ return -EBUSY;
+ }
+ ni_set_ai_dma_channel(dev, devpriv->ai_mite_chan->channel);
+ comedi_spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags);
+ return 0;
+}
+
+static int ni_request_ao_mite_channel(comedi_device *dev)
+{
+ unsigned long flags;
+
+ comedi_spin_lock_irqsave(&devpriv->mite_channel_lock, flags);
+ BUG_ON(devpriv->ao_mite_chan);
+ devpriv->ao_mite_chan = mite_request_channel(devpriv->mite, devpriv->ao_mite_ring);
+ if(devpriv->ao_mite_chan == NULL)
+ {
+ comedi_spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags);
+ comedi_error(dev, "failed to reserve mite dma channel for analog outut.");
+ return -EBUSY;
+ }
+ ni_set_ao_dma_channel(dev, devpriv->ao_mite_chan->channel);
+ comedi_spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags);
+ return 0;
+}
+
+#endif // PCIDMA
+
+static void ni_release_ai_mite_channel(comedi_device *dev)
+{
+#ifdef PCIDMA
+ unsigned long flags;
+
+ comedi_spin_lock_irqsave(&devpriv->mite_channel_lock, flags);
+ if(devpriv->ai_mite_chan)
+ {
+ mite_release_channel(devpriv->ai_mite_chan);
+ devpriv->ai_mite_chan = NULL;
+ ni_set_ai_dma_channel(dev, -1);
+ }
+ comedi_spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags);
+#endif // PCIDMA
+}
+
+static void ni_release_ao_mite_channel(comedi_device *dev)
+{
+#ifdef PCIDMA
+ unsigned long flags;
+
+ comedi_spin_lock_irqsave(&devpriv->mite_channel_lock, flags);
+ if(devpriv->ao_mite_chan)
+ {
+ mite_release_channel(devpriv->ao_mite_chan);
+ devpriv->ao_mite_chan = NULL;
+ ni_set_ao_dma_channel(dev, -1);
+ }
+ comedi_spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags);
+#endif // PCIDMA
+}
static void ni_flush_ai_fifo(comedi_device *dev){
if(boardtype.reg_type == ni_reg_6143){
{
unsigned long flags;
- comedi_spin_lock_irqsave( &devpriv->window_lock, flags );
+ comedi_spin_lock_irqsave(&devpriv->soft_reg_copy_lock, flags);
switch (reg){
case Interrupt_A_Enable_Register:
if(value)
devpriv->int_a_enable_reg |= bits;
else
devpriv->int_a_enable_reg &= ~bits;
- comedi_spin_unlock_irqrestore( &devpriv->window_lock, flags );
devpriv->stc_writew(dev, devpriv->int_a_enable_reg,Interrupt_A_Enable_Register);
break;
case Interrupt_B_Enable_Register:
devpriv->int_b_enable_reg |= bits;
else
devpriv->int_b_enable_reg &= ~bits;
- comedi_spin_unlock_irqrestore( &devpriv->window_lock, flags );
devpriv->stc_writew(dev, devpriv->int_b_enable_reg,Interrupt_B_Enable_Register);
break;
case IO_Bidirection_Pin_Register:
devpriv->io_bidirection_pin_reg |= bits;
else
devpriv->io_bidirection_pin_reg &= ~bits;
- comedi_spin_unlock_irqrestore( &devpriv->window_lock, flags );
devpriv->stc_writew(dev, devpriv->io_bidirection_pin_reg,IO_Bidirection_Pin_Register);
break;
default:
rt_printk("Warning ni_set_bits() called with invalid arguments\n");
rt_printk("reg is %d\n",reg);
- comedi_spin_unlock_irqrestore( &devpriv->window_lock, flags );
break;
}
+ comedi_spin_unlock_irqrestore(&devpriv->soft_reg_copy_lock, flags );
}
comedi_device *dev=d;
unsigned short a_status;
unsigned short b_status;
- unsigned int m0_status;
- unsigned int m1_status;
+ unsigned int ai_mite_status = 0;
+ unsigned int ao_mite_status = 0;
unsigned long flags;
#ifdef PCIDMA
struct mite_struct *mite = devpriv->mite;
a_status=devpriv->stc_readw(dev, AI_Status_1_Register);
b_status=devpriv->stc_readw(dev, AO_Status_1_Register);
#ifdef PCIDMA
- m0_status=readl(mite->mite_io_addr + MITE_CHSR(AI_DMA_CHAN));
- m1_status=readl(mite->mite_io_addr + MITE_CHSR(AO_DMA_CHAN));
-#else
- m0_status = 0;
- m1_status = 0;
+ if(devpriv->ai_mite_chan)
+ ai_mite_status = readl(mite->mite_io_addr + MITE_CHSR(devpriv->ai_mite_chan->channel));
+ if(devpriv->ao_mite_chan)
+ ao_mite_status = readl(mite->mite_io_addr + MITE_CHSR(devpriv->ao_mite_chan->channel));
#endif
- if(a_status&Interrupt_A_St || m0_status & CHSR_INT )
- handle_a_interrupt(dev, a_status, m0_status);
- if(b_status&Interrupt_B_St || m1_status & CHSR_INT )
- handle_b_interrupt(dev, b_status, m1_status);
+ if(a_status & Interrupt_A_St || ai_mite_status & CHSR_INT )
+ handle_a_interrupt(dev, a_status, ai_mite_status);
+ if(b_status & Interrupt_B_St || ao_mite_status & CHSR_INT )
+ handle_b_interrupt(dev, b_status, ao_mite_status);
comedi_spin_unlock_irqrestore(&dev->spinlock, flags);
return IRQ_HANDLED;
}
#ifdef PCIDMA
-static void ni_sync_ai_dma(struct mite_struct *mite, comedi_device *dev)
+static void ni_sync_ai_dma(comedi_device *dev)
{
comedi_subdevice *s = dev->subdevices + 0;
- int retval = mite_sync_input_dma(mite, AI_DMA_CHAN, s->async);
+ int retval;
+
+ if(devpriv->ai_mite_chan == NULL) return;
+ retval = mite_sync_input_dma(devpriv->ai_mite_chan, s->async);
if(retval < 0)
{
ni_ai_reset(dev,s);
{
comedi_subdevice *s = dev->subdevices + 1;
- writel(CHOR_CLRLC, mite->mite_io_addr + MITE_CHOR(AO_DMA_CHAN));
+ if(devpriv->ao_mite_chan == NULL) return;
+ writel(CHOR_CLRLC, mite->mite_io_addr + MITE_CHOR(devpriv->ao_mite_chan->channel));
- if(mite_sync_output_dma(mite, AO_DMA_CHAN, s->async) < 0)
+ if(mite_sync_output_dma(devpriv->ao_mite_chan, s->async) < 0)
{
- ni_ao_reset(dev,s);
+ ni_ao_reset(dev, s);
return;
}
}
for(i = 0; i < timeout; i++)
{
- ni_sync_ai_dma(devpriv->mite, dev);
+ ni_sync_ai_dma(dev);
if((s->async->events & COMEDI_CB_EOS)) break;
comedi_udelay(1);
}
#ifdef PCIDMA
ni_ai_drain_dma( dev );
- mite_dma_disarm(devpriv->mite, AI_DMA_CHAN);
+ if(devpriv->ai_mite_chan)
+ {
+ mite_dma_disarm(devpriv->ai_mite_chan);
+ }
#endif
ni_handle_fifo_dregs(dev);
get_last_sample_611x(dev);
#ifdef PCIDMA
/* Currently, mite.c requires us to handle LINKC and DONE */
if(m_status & CHSR_LINKC){
- writel(CHOR_CLRLC, devpriv->mite->mite_io_addr + MITE_CHOR(AI_DMA_CHAN));
- ni_sync_ai_dma(devpriv->mite, dev);
+ writel(CHOR_CLRLC, devpriv->mite->mite_io_addr + MITE_CHOR(devpriv->ai_mite_chan->channel));
+ ni_sync_ai_dma(dev);
}
if(m_status & CHSR_DONE){
- writel(CHOR_CLRDONE, devpriv->mite->mite_io_addr + MITE_CHOR(AI_DMA_CHAN));
+ writel(CHOR_CLRDONE, devpriv->mite->mite_io_addr + MITE_CHOR(devpriv->ai_mite_chan->channel));
}
if(m_status & ~(CHSR_INT | CHSR_LINKC | CHSR_DONE | CHSR_MRDY | CHSR_DRDY | CHSR_DRQ1 | CHSR_DRQ0 | CHSR_ERROR | CHSR_SABORT | CHSR_XFERR | CHSR_LxERR_mask)){
rt_printk("unknown mite interrupt, ack! (m_status=%08x)\n", m_status);
//mite_print_chsr(m_status);
- mite_dma_disarm(devpriv->mite, AI_DMA_CHAN );
- writel(CHOR_DMARESET, devpriv->mite->mite_io_addr + MITE_CHOR(AI_DMA_CHAN));
+ mite_dma_disarm(devpriv->ai_mite_chan);
+ mite_dma_reset(devpriv->ai_mite_chan);
//disable_irq(dev->irq);
}
#endif
* so it's a good idea to be careful. */
if(s->subdev_flags&SDF_RUNNING){
s->async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
- //comedi_event(dev,s,s->async->events);
+ comedi_event(dev,s,s->async->events);
}
return;
}
}
#endif
if(ack) devpriv->stc_writew(dev, ack,Interrupt_A_Ack_Register);
-
comedi_event(dev,s,s->async->events);
#ifdef DEBUG_INTERRUPT
}
if(m_status & CHSR_DONE){
- writel(CHOR_CLRDONE, devpriv->mite->mite_io_addr + MITE_CHOR(AO_DMA_CHAN));
+ writel(CHOR_CLRDONE, devpriv->mite->mite_io_addr + MITE_CHOR(devpriv->ao_mite_chan->channel));
}
if(m_status & ~(CHSR_INT | CHSR_LINKC | CHSR_DONE | CHSR_MRDY | CHSR_DRDY | CHSR_DRQ1 | CHSR_DRQ0 | CHSR_ERROR | CHSR_SABORT | CHSR_XFERR | CHSR_LxERR_mask)){
rt_printk("unknown mite interrupt, ack! (m_status=%08x)\n", m_status);
//mite_print_chsr(m_status);
- mite_dma_disarm(devpriv->mite, AO_DMA_CHAN );
- writel(CHOR_DMARESET, devpriv->mite->mite_io_addr + MITE_CHOR(AO_DMA_CHAN));
- }
+ mite_dma_disarm(devpriv->ao_mite_chan);
+ mite_dma_reset(devpriv->ao_mite_chan);
+ }
#endif
if(b_status==0xffff)return;
#ifdef PCIDMA
static int ni_ai_drain_dma(comedi_device *dev )
{
- struct mite_struct *mite = devpriv->mite;
int i;
static const int timeout = 10000;
+ if(devpriv->ai_mite_chan == NULL) return 0;
for( i = 0; i < timeout; i++ )
{
if((devpriv->stc_readw(dev, AI_Status_1_Register) & AI_FIFO_Empty_St) &&
- mite_bytes_in_transit(mite, AI_DMA_CHAN) == 0)
+ mite_bytes_in_transit(devpriv->ai_mite_chan) == 0)
break;
comedi_udelay(2);
}
{
rt_printk("ni_mio_common: wait for dma drain timed out\n");
rt_printk("mite_bytes_in_transit=%i, AI_Status1_Register=0x%x\n",
- mite_bytes_in_transit(mite, AI_DMA_CHAN), devpriv->stc_readw(dev, AI_Status_1_Register));
+ mite_bytes_in_transit(devpriv->ai_mite_chan), devpriv->stc_readw(dev, AI_Status_1_Register));
return -1;
}
- ni_sync_ai_dma( mite, dev );
+ ni_sync_ai_dma(dev);
return 0;
}
#ifdef PCIDMA
-static void ni_ai_setup_MITE_dma(comedi_device *dev,comedi_cmd *cmd)
+static int ni_ai_setup_MITE_dma(comedi_device *dev,comedi_cmd *cmd)
{
- struct mite_struct *mite = devpriv->mite;
- struct mite_channel *mite_chan = &mite->channels[ AI_DMA_CHAN ];
comedi_subdevice *s = dev->subdevices + 0;
+ int retval;
+
+ retval = ni_request_ai_mite_channel(dev);
+ if(retval) return retval;
+ //rt_printk("comedi_debug: using mite channel %i for ai.\n", devpriv->ai_mite_chan->channel);
/* write alloc the entire buffer */
comedi_buf_write_alloc(s->async, s->async->prealloc_bufsz);
- mite_chan->current_link = 0;
- mite_chan->dir = COMEDI_INPUT;
+ devpriv->ai_mite_chan->dir = COMEDI_INPUT;
switch(boardtype.reg_type)
{
case ni_reg_611x:
case ni_reg_6143:
- mite_prep_dma(mite, AI_DMA_CHAN, 32, 16);
+ mite_prep_dma(devpriv->ai_mite_chan, 32, 16);
break;
case ni_reg_628x:
- mite_prep_dma(mite, AI_DMA_CHAN, 32, 32);
+ mite_prep_dma(devpriv->ai_mite_chan, 32, 32);
break;
default:
- mite_prep_dma(mite, AI_DMA_CHAN, 16, 16);
+ mite_prep_dma(devpriv->ai_mite_chan, 16, 16);
break;
};
/*start the MITE*/
- mite_dma_arm(mite, AI_DMA_CHAN);
+ mite_dma_arm(devpriv->ai_mite_chan);
+ return 0;
}
-static void ni_ao_setup_MITE_dma(comedi_device *dev, comedi_cmd *cmd)
+static int ni_ao_setup_MITE_dma(comedi_device *dev, comedi_cmd *cmd)
{
- struct mite_struct *mite = devpriv->mite;
- struct mite_channel *mite_chan = &mite->channels[ AO_DMA_CHAN ];
comedi_subdevice *s = dev->subdevices + 1;
+ int retval;
+
+ retval = ni_request_ao_mite_channel(dev);
+ if(retval) return retval;
+ //rt_printk("comedi_debug: using mite channel %i for ao.\n", devpriv->ao_mite_chan->channel);
/* read alloc the entire buffer */
comedi_buf_read_alloc(s->async, s->async->prealloc_bufsz);
to the mite's registers and arm it. */
smp_wmb();
- mite_chan->current_link = 0;
- mite_chan->dir = COMEDI_OUTPUT;
+ devpriv->ao_mite_chan->dir = COMEDI_OUTPUT;
if(boardtype.reg_type & (ni_reg_611x | ni_reg_6713))
{
- mite_prep_dma(mite, AO_DMA_CHAN, 32, 32);
+ mite_prep_dma(devpriv->ao_mite_chan, 32, 32);
}else
{
/* doing 32 instead of 16 bit wide transfers from memory
makes the mite do 32 bit pci transfers, doubling pci bandwidth. */
- mite_prep_dma(mite, AO_DMA_CHAN, 16, 32);
+ mite_prep_dma(devpriv->ao_mite_chan, 16, 32);
}
/*start the MITE*/
- mite_dma_arm(mite, AO_DMA_CHAN);
+ mite_dma_arm(devpriv->ao_mite_chan);
+ return 0;
}
#endif // PCIDMA
static int ni_ai_reset(comedi_device *dev,comedi_subdevice *s)
{
#ifdef PCIDMA
- mite_dma_disarm(devpriv->mite, AI_DMA_CHAN);
+ if(devpriv->ai_mite_chan)
+ {
+ mite_dma_disarm(devpriv->ai_mite_chan);
+ }
#endif
/* ai configuration */
devpriv->stc_writew(dev, AI_Configuration_Start | AI_Reset, Joint_Reset_Register);
#ifndef PCIDMA
ni_handle_fifo_dregs(dev);
#else
- ni_sync_ai_dma(devpriv->mite, dev);
+ ni_sync_ai_dma(dev);
#endif
count = s->async->buf_write_count - s->async->buf_read_count;
if(in_interrupt() == 0)
return 0;
}
+static void ni_ai_cmd_cleanup(comedi_device *dev, comedi_subdevice *s)
+{
+ ni_release_ai_mite_channel(dev);
+}
+
static int ni_ai_cmd(comedi_device *dev,comedi_subdevice *s)
{
comedi_cmd *cmd=&s->async->cmd;
}
#ifdef PCIDMA
- ni_ai_setup_MITE_dma(dev,cmd);
+ {
+ int retval = ni_ai_setup_MITE_dma(dev,cmd);
+ if(retval) return retval;
+ }
//mite_dump_regs(devpriv->mite);
#endif
int i;
static const int timeout = 1000;
- if(trignum!=0)return -EINVAL;
+ if(trignum!=0) return -EINVAL;
ni_set_bits(dev, Interrupt_B_Enable_Register, AO_FIFO_Interrupt_Enable | AO_Error_Interrupt_Enable, 0);
interrupt_b_bits = AO_Error_Interrupt_Enable;
devpriv->stc_writew(dev, 1, DAC_FIFO_Clear);
if(boardtype.reg_type & ni_reg_6xxx_mask)
ni_ao_win_outl(dev, 0x6, AO_FIFO_Offset_Load_611x);
- ni_ao_setup_MITE_dma(dev, &s->async->cmd);
+ ret = ni_ao_setup_MITE_dma(dev, &s->async->cmd);
+ if(ret) return ret;
ret = ni_ao_wait_for_dma_load(dev);
if(ret < 0) return ret;
return 0;
}
+static void ni_ao_cmd_cleanup(comedi_device *dev,comedi_subdevice *s)
+{
+ ni_release_ao_mite_channel(dev);
+}
+
static int ni_ao_cmd(comedi_device *dev,comedi_subdevice *s)
{
comedi_cmd *cmd = &s->async->cmd;
//ni_writew(devpriv->ao1p,AO_Configuration);
#ifdef PCIDMA
- mite_dma_disarm(devpriv->mite, AO_DMA_CHAN);
- writel(CHOR_DMARESET | CHOR_FRESET, devpriv->mite->mite_io_addr + MITE_CHOR(AO_DMA_CHAN));
+ if(devpriv->ao_mite_chan)
+ {
+ mite_dma_disarm(devpriv->ao_mite_chan);
+ mite_dma_reset(devpriv->ao_mite_chan);
+ }
#endif
devpriv->stc_writew(dev, AO_Configuration_Start,Joint_Reset_Register);
if(ret < 0) return ret;
spin_lock_init(&devpriv->window_lock);
+ spin_lock_init(&devpriv->soft_reg_copy_lock);
+ spin_lock_init(&devpriv->mite_channel_lock);
return 0;
};
static int ni_E_init(comedi_device *dev,comedi_devconfig *it)
{
comedi_subdevice *s;
- int bits;
unsigned j;
if(boardtype.n_aochan > MAX_N_AO_CHAN)
s->len_chanlist=512;
s->maxdata=(1<<boardtype.adbits)-1;
s->range_table=ni_range_lkup[boardtype.gainlkup];
- s->insn_read=ni_ai_insn_read;
- s->insn_config=ni_ai_insn_config;
- s->do_cmdtest=ni_ai_cmdtest;
- s->do_cmd=ni_ai_cmd;
- s->cancel=ni_ai_reset;
- s->poll=ni_ai_poll;
- s->munge=ni_ai_munge;
+ s->insn_read = &ni_ai_insn_read;
+ s->insn_config = &ni_ai_insn_config;
+ s->do_cmdtest = &ni_ai_cmdtest;
+ s->do_cmd = &ni_ai_cmd;
+ s->cmd_cleanup = &ni_ai_cmd_cleanup;
+ s->cancel = &ni_ai_reset;
+ s->poll = &ni_ai_poll;
+ s->munge = &ni_ai_munge;
}else{
s->type=COMEDI_SUBD_UNUSED;
}
#endif
dev->write_subdev=s;
s->subdev_flags |= SDF_CMD_WRITE;
- s->do_cmd=ni_ao_cmd;
- s->do_cmdtest=ni_ao_cmdtest;
+ s->do_cmd = &ni_ao_cmd;
+ s->cmd_cleanup = &ni_ao_cmd_cleanup;
+ s->do_cmdtest = &ni_ao_cmdtest;
s->len_chanlist = boardtype.n_aochan;
if((boardtype.reg_type & ni_reg_m_series_mask) == 0)
s->munge=ni_ao_munge;
devpriv->counters[j].variant = ni_gpct_variant_e_series;
}
devpriv->counters[j].clock_period_ps = 0;
-#ifdef PCIDMA
- devpriv->counters[j].mite = devpriv->mite;
-#endif
- devpriv->counters[j].mite_channel = -1;
+ devpriv->counters[j].mite_chan = NULL;
ni_tio_init_counter(&devpriv->counters[j]);
}
}
/* DMA setup */
- /* tell the STC which dma channels to use for AI and AO */
- bits = 1 << ( AI_DMA_CHAN );
- bits |= 1 << ( AO_DMA_CHAN + 4 );
- ni_writeb( bits, AI_AO_Select);
- /* tell the STC which dma channels to use for
- * General purpose counters 0 and 1 */
- bits = 1 << ( GPC0_DMA_CHAN );
- bits |= 1 << ( GPC1_DMA_CHAN + 4 );
- ni_writeb( bits, G0_G1_Select);
+ ni_writeb(devpriv->ai_ao_select_reg, AI_AO_Select);
+ ni_writeb(devpriv->g0_g1_select_reg, G0_G1_Select);
if(boardtype.reg_type & ni_reg_6xxx_mask)
{
#define Interrupt_Control 75
/* bits same as flags */
-#define DMA_Line_Control 76
- #define DMAChannel(x) ((x)&0xf)
+#define DMA_Line_Control_Group1 76
+#define DMA_Line_Control_Group2 108
+// channel zero is none
+static inline unsigned primary_DMAChannel_bits(unsigned channel)
+{
+ return channel & 0x3;
+}
+static inline unsigned secondary_DMAChannel_bits(unsigned channel)
+{
+ return (channel << 2) & 0xc;
+}
#define Transfer_Size_Control 77
#define TransferWidth(x) ((x)&3)
#define IntEn (TransferReady|CountExpired|Waited|PrimaryTC|SecondaryTC)
#endif
-enum mite_dma_channels
-{
- DI_DMA_CHAN = 1,
-};
-
static int nidio_attach(comedi_device *dev,comedi_devconfig *it);
static int nidio_detach(comedi_device *dev);
static comedi_driver driver_pcidio={
int boardtype;
int dio;
unsigned short OpModeBits;
+ struct mite_channel *di_mite_chan;
+ struct mite_dma_descriptor_ring *di_mite_ring;
+ spinlock_t mite_channel_lock;
}nidio96_private;
#define devpriv ((nidio96_private *)dev->private)
unsigned int trignum);
static int nidio_find_device(comedi_device *dev,int bus,int slot);
static int ni_pcidio_ns_to_timer(int *nanosec, int round_mode);
-static void setup_mite_dma(comedi_device *dev,comedi_subdevice *s);
+static int setup_mite_dma(comedi_device *dev,comedi_subdevice *s);
#ifdef DEBUG_FLAGS
static void ni_pcidio_print_flags(unsigned int flags);
#define ni_pcidio_print_status(x)
#endif
+static int ni_pcidio_request_di_mite_channel(comedi_device *dev)
+{
+ unsigned long flags;
+
+ comedi_spin_lock_irqsave(&devpriv->mite_channel_lock, flags);
+ BUG_ON(devpriv->di_mite_chan);
+ devpriv->di_mite_chan = mite_offset_request_channel(devpriv->mite, devpriv->di_mite_ring, 1);
+ if(devpriv->di_mite_chan == NULL)
+ {
+ comedi_spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags);
+ comedi_error(dev, "failed to reserve mite dma channel.");
+ return -EBUSY;
+ }
+ writeb(primary_DMAChannel_bits(devpriv->di_mite_chan->channel) |
+ secondary_DMAChannel_bits(devpriv->di_mite_chan->channel),
+ devpriv->mite->daq_io_addr + DMA_Line_Control_Group1);
+ mmiowb();
+ comedi_spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags);
+ return 0;
+}
+
+static void ni_pcidio_release_di_mite_channel(comedi_device *dev)
+{
+ unsigned long flags;
+
+ comedi_spin_lock_irqsave(&devpriv->mite_channel_lock, flags);
+ if(devpriv->di_mite_chan)
+ {
+ mite_release_channel(devpriv->di_mite_chan);
+ writeb(primary_DMAChannel_bits(0) |
+ secondary_DMAChannel_bits(0),
+ devpriv->mite->daq_io_addr + DMA_Line_Control_Group1);
+ mmiowb();
+ }
+ comedi_spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags);
+}
+
static int nidio96_8255_cb(int dir,int port,int data,unsigned long iobase)
{
if(dir){
}
}
+static void nidio_disarm_and_reset_di_mite_channel(comedi_device *dev)
+{
+#ifdef USE_DMA
+ unsigned long flags;
+
+ comedi_spin_lock_irqsave(&devpriv->mite_channel_lock, flags);
+ if(devpriv->di_mite_chan)
+ {
+ mite_dma_disarm(devpriv->di_mite_chan);
+ mite_dma_reset(devpriv->di_mite_chan);
+ }
+ comedi_spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags);
+#endif // USE_DMA
+}
+
static irqreturn_t nidio_interrupt(int irq, void *d PT_REGS_ARG)
{
comedi_device *dev=d;
comedi_subdevice *s = dev->subdevices;
comedi_async *async = s->async;
struct mite_struct *mite = devpriv->mite;
- struct mite_channel *mite_chan = &mite->channels[ DI_DMA_CHAN ];
+
//int i, j;
long int AuxData = 0;
sampl_t data1 = 0;
int flags;
int status;
int work = 0;
- unsigned int m_status;
+ unsigned int m_status = 0;
+ unsigned long irq_flags;
status = readb(devpriv->mite->daq_io_addr+Interrupt_And_Window_Status);
flags = readb(devpriv->mite->daq_io_addr+Group_1_Flags);
- m_status = readl(mite->mite_io_addr + MITE_CHSR(DI_DMA_CHAN));
//interrupcions parasites
if(dev->attached == 0){
async->events |= COMEDI_CB_ERROR|COMEDI_CB_EOA;
}
- DPRINTK("ni_pcidio_interrupt: status=0x%02x,flags=0x%02x,m_status=0x%08x\n",
- status,flags,m_status);
+ DPRINTK("ni_pcidio_interrupt: status=0x%02x,flags=0x%02x\n",
+ status,flags);
ni_pcidio_print_flags(flags);
ni_pcidio_print_status(status);
+
+ //printk("buf[0]=%08x\n",*(unsigned int *)async->prealloc_buf);
+ //printk("buf[4096]=%08x\n",*(unsigned int *)(async->prealloc_buf+4096));
+
+ comedi_spin_lock_irqsave(&devpriv->mite_channel_lock, irq_flags);
+ if(devpriv->di_mite_chan)
+ m_status = readl(mite->mite_io_addr + MITE_CHSR(devpriv->di_mite_chan->channel));
#ifdef MITE_DEBUG
mite_print_chsr(m_status);
#endif
//printk("mite_bytes_transferred: %d\n",mite_bytes_transferred(mite,DI_DMA_CHAN));
//mite_dump_regs(mite);
-
- //printk("buf[0]=%08x\n",*(unsigned int *)async->prealloc_buf);
- //printk("buf[4096]=%08x\n",*(unsigned int *)(async->prealloc_buf+4096));
-
if(m_status & CHSR_INT){
if(m_status & CHSR_LINKC){
- unsigned int count;
-
- writel(CHOR_CLRLC, mite->mite_io_addr + MITE_CHOR(DI_DMA_CHAN));
- count = le32_to_cpu(mite_chan->ring[mite_chan->current_link].count);
-
- /* XXX need to byteswap */
-
- async->buf_write_count += count;
- async->buf_write_ptr += count;
- if(async->buf_write_ptr >= async->prealloc_bufsz){
- async->buf_write_ptr -= async->prealloc_bufsz;
- }
- mite_chan->current_link++;
- if(mite_chan->current_link >= mite_chan->n_links){
- mite_chan->current_link=0;
+ int retval;
+
+ writel(CHOR_CLRLC, mite->mite_io_addr + MITE_CHOR(devpriv->di_mite_chan->channel));
+ retval = mite_sync_input_dma(devpriv->di_mite_chan, s->async);
+ if(retval)
+ {
+ mite_dma_disarm(devpriv->di_mite_chan);
+ mite_dma_reset(devpriv->di_mite_chan);
}
+ /* XXX need to byteswap */
}
if(m_status & CHSR_DONE){
- writel(CHOR_CLRDONE, mite->mite_io_addr + MITE_CHOR(DI_DMA_CHAN));
+ writel(CHOR_CLRDONE, mite->mite_io_addr + MITE_CHOR(devpriv->di_mite_chan->channel));
}
if(m_status & ~(CHSR_INT | CHSR_LINKC | CHSR_DONE | CHSR_DRDY | CHSR_DRQ1 | CHSR_MRDY)){
DPRINTK("unknown mite interrupt, disabling IRQ\n");
- writel(CHOR_DMARESET, mite->mite_io_addr + MITE_CHOR(DI_DMA_CHAN));
+ mite_dma_disarm(devpriv->di_mite_chan);
+ mite_dma_reset(devpriv->di_mite_chan);
disable_irq(dev->irq);
}
- async->events |= COMEDI_CB_BLOCK;
}
+ comedi_spin_unlock_irqrestore(&devpriv->mite_channel_lock, irq_flags);
while(status&DataLeft){
work++;
writeb(0x00,devpriv->mite->daq_io_addr+OpMode);
writeb(0x00,devpriv->mite->daq_io_addr+Master_DMA_And_Interrupt_Control);
-#ifdef USE_DMA
- mite_dma_disarm(mite, DI_DMA_CHAN);
- writel(CHOR_DMARESET, mite->mite_io_addr + MITE_CHOR(DI_DMA_CHAN));
-#endif
+ nidio_disarm_and_reset_di_mite_channel(dev);
break;
}else if(flags & Waited){
DPRINTK("Waited\n");
writeb(ClearWaited,devpriv->mite->daq_io_addr+Group_1_First_Clear);
writeb(0x00,devpriv->mite->daq_io_addr+Master_DMA_And_Interrupt_Control);
async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR;
-#ifdef USE_DMA
- mite_dma_disarm(mite, DI_DMA_CHAN);
- writel(CHOR_DMARESET, mite->mite_io_addr + MITE_CHOR(DI_DMA_CHAN));
-#endif
+ nidio_disarm_and_reset_di_mite_channel(dev);
break;
}else if(flags & PrimaryTC){
DPRINTK("PrimaryTC\n");
out:
comedi_event(dev,s,async->events);
-
#if 0
if(!tag){
writeb(0x03,devpriv->mite->daq_io_addr+Master_DMA_And_Interrupt_Control);
return divider;
}
+static void ni_pcidio_cmd_cleanup(comedi_device *dev,comedi_subdevice *s)
+{
+ ni_pcidio_release_di_mite_channel(dev);
+}
static int ni_pcidio_cmd(comedi_device *dev,comedi_subdevice *s)
{
}
#ifdef USE_DMA
- writeb(0x05,devpriv->mite->daq_io_addr+DMA_Line_Control);
- writeb(0x30,devpriv->mite->daq_io_addr+Group_1_First_Clear);
+ writeb(ClearPrimaryTC | ClearSecondaryTC,
+ devpriv->mite->daq_io_addr + Group_1_First_Clear);
- setup_mite_dma(dev,s);
+ {
+ int retval = setup_mite_dma(dev,s);
+ if(retval) return retval;
+ }
#else
- writeb(0x00,devpriv->mite->daq_io_addr+DMA_Line_Control);
+ 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);
return 0;
}
-
-static void setup_mite_dma(comedi_device *dev,comedi_subdevice *s)
+static int setup_mite_dma(comedi_device *dev,comedi_subdevice *s)
{
- struct mite_struct *mite = devpriv->mite;
- struct mite_channel *mite_chan = &mite->channels[ DI_DMA_CHAN ];
+ int retval;
- mite_chan->current_link = 0;
+ retval = ni_pcidio_request_di_mite_channel(dev);
+ if(retval) return retval;
- mite_chan->dir = COMEDI_INPUT;
+ devpriv->di_mite_chan->dir = COMEDI_INPUT;
- mite_prep_dma(mite, DI_DMA_CHAN, 32, 32);
+ mite_prep_dma(devpriv->di_mite_chan, 32, 32);
- mite_dma_arm(mite, DI_DMA_CHAN);
+ mite_dma_arm(devpriv->di_mite_chan);
+ return 0;
}
{
int ret;
- ret = mite_buf_change(devpriv->mite, DI_DMA_CHAN, s->async, new_size);
+ ret = mite_buf_change(devpriv->di_mite_ring, s->async);
if(ret<0)return ret;
memset(s->async->prealloc_buf, 0xaa, s->async->prealloc_bufsz);
if((ret=alloc_private(dev,sizeof(nidio96_private)))<0)
return ret;
+ devpriv->di_mite_ring = mite_alloc_ring();
+ if(devpriv->di_mite_ring == NULL) return -ENOMEM;
+ spin_lock_init(&devpriv->mite_channel_lock);
ret=nidio_find_device(dev,it->options[0],it->options[1]);
if(ret<0)return ret;
s->insn_config = ni_pcidio_insn_config;
s->insn_bits = ni_pcidio_insn_bits;
s->do_cmd = ni_pcidio_cmd;
+ s->cmd_cleanup = ni_pcidio_cmd_cleanup;
s->do_cmdtest = ni_pcidio_cmdtest;
s->cancel = ni_pcidio_cancel;
s->len_chanlist=32; /* XXX */
if(dev->irq)
comedi_free_irq(dev->irq,dev);
- if(devpriv && devpriv->mite)
- mite_unsetup(devpriv->mite);
-
+ if(devpriv)
+ {
+ if(devpriv->di_mite_ring)
+ {
+ mite_free_ring(devpriv->di_mite_ring);
+ devpriv->di_mite_ring = NULL;
+ }
+ if(devpriv->mite)
+ mite_unsetup(devpriv->mite);
+ }
return 0;
}
typedef struct{
struct mite_struct *mite;
+ struct mite_channel *ai_mite_chan;
+ struct mite_channel *ao_mite_chan;
+ struct mite_channel *gpct_mite_chan[2];
+ struct mite_dma_descriptor_ring *ai_mite_ring;
+ struct mite_dma_descriptor_ring *ao_mite_ring;
+ struct mite_dma_descriptor_ring *gpct_mite_ring[2];
NI_PRIVATE_COMMON
}ni_private;
static int pcimio_detach(comedi_device *dev)
{
mio_common_detach(dev);
-
- if(dev->private && devpriv->mite)
- mite_unsetup(devpriv->mite);
-
if(dev->irq){
- comedi_free_irq(dev->irq,dev);
+ comedi_free_irq(dev->irq, dev);
+ }
+ if(dev->private)
+ {
+ mite_free_ring(devpriv->ai_mite_ring);
+ mite_free_ring(devpriv->ao_mite_ring);
+ mite_free_ring(devpriv->gpct_mite_ring[0]);
+ mite_free_ring(devpriv->gpct_mite_ring[1]);
+ if(devpriv->mite)
+ mite_unsetup(devpriv->mite);
}
return 0;
ret=ni_alloc_private(dev);
if(ret<0)return ret;
+ devpriv->ai_mite_ring = mite_alloc_ring();
+ if(devpriv->ai_mite_ring == NULL) return -ENOMEM;
+ devpriv->ao_mite_ring = mite_alloc_ring();
+ if(devpriv->ao_mite_ring == NULL) return -ENOMEM;
+ devpriv->gpct_mite_ring[0] = mite_alloc_ring();
+ if(devpriv->gpct_mite_ring[0] == NULL) return -ENOMEM;
+ devpriv->gpct_mite_ring[1] = mite_alloc_ring();
+ if(devpriv->gpct_mite_ring[1] == NULL) return -ENOMEM;
ret=pcimio_find_device(dev,it->options[0],it->options[1]);
if(ret<0)return ret;
{
int ret;
- ret = mite_buf_change(devpriv->mite, AI_DMA_CHAN, s->async, new_size);
- if(ret<0)return ret;
+ ret = mite_buf_change(devpriv->ai_mite_ring, s->async);
+ if(ret < 0) return ret;
return 0;
}
{
int ret;
- ret = mite_buf_change(devpriv->mite, AO_DMA_CHAN, s->async, new_size);
- if(ret<0)return ret;
+ ret = mite_buf_change(devpriv->ao_mite_ring, s->async);
+ if(ret < 0) return ret;
return 0;
}
#define Channel_B_Mode 0x05
#define Channel_C_Mode 0x07
#define AI_AO_Select 0x09
+enum AI_AO_Select_Bits
+{
+ AI_DMA_Select_Shift = 0,
+ AI_DMA_Select_Mask = 0xf,
+ AO_DMA_Select_Shift = 4,
+ AO_DMA_Select_Mask = 0xf << AO_DMA_Select_Shift
+};
#define G0_G1_Select 0x0b
/* 16 bit registers */
but I thought I'd put it here anyway.
*/
-/* our default usage of mite channels */
-enum mite_dma_channel{
- AI_DMA_CHAN = 0,
- AO_DMA_CHAN = 1,
- GPC0_DMA_CHAN = 2,
- GPC1_DMA_CHAN = 3,
-};
-
enum{ ai_gain_16=0, ai_gain_8, ai_gain_14, ai_gain_4, ai_gain_611x, ai_gain_622x, ai_gain_628x, ai_gain_6143};
enum caldac_enum { caldac_none=0, mb88341, dac8800, dac8043, ad8522,
ad8804, ad8842, ad8804_debug };
unsigned int ai_calib_source; \
unsigned int ai_calib_source_enabled; \
spinlock_t window_lock; \
+ spinlock_t soft_reg_copy_lock; \
+ spinlock_t mite_channel_lock; \
\
int changain_state; \
unsigned int changain_spec; \
unsigned short ao[MAX_N_AO_CHAN]; \
unsigned short caldacs[MAX_N_CALDACS]; \
\
- volatile unsigned short ai_cmd2; \
+ unsigned short ai_cmd2; \
\
unsigned short ao_conf[MAX_N_AO_CHAN]; \
unsigned short ao_mode1; \
unsigned short clock_and_fout; \
unsigned short clock_and_fout2; \
\
- volatile unsigned short int_a_enable_reg; \
- volatile unsigned short int_b_enable_reg; \
+ unsigned short int_a_enable_reg; \
+ unsigned short int_b_enable_reg; \
unsigned short io_bidirection_pin_reg; \
unsigned short rtsi_trig_direction_reg; \
unsigned short rtsi_trig_a_output_reg; \
unsigned short rtsi_trig_b_output_reg; \
unsigned short pfi_output_select_reg[NUM_PFI_OUTPUT_SELECT_REGS]; \
+ unsigned short ai_ao_select_reg; \
+ unsigned short g0_g1_select_reg; \
\
unsigned clock_ns; \
unsigned clock_source; \
static int ni_tio_input_cmd(struct ni_gpct *counter, comedi_async *async)
{
comedi_cmd *cmd = &async->cmd;
- struct mite_channel *mite_chan = &counter->mite->channels[counter->mite_channel];
/* write alloc the entire buffer */
comedi_buf_write_alloc(async, async->prealloc_bufsz);
- mite_chan->current_link = 0;
- mite_chan->dir = COMEDI_INPUT;
- mite_prep_dma(counter->mite, counter->mite_channel, 32, 32);
+ counter->mite_chan->dir = COMEDI_INPUT;
+ mite_prep_dma(counter->mite_chan, 32, 32);
if(counter->variant == ni_gpct_variant_m_series ||
counter->variant == ni_gpct_variant_660x)
{
counter->write_register(counter, Gi_DMA_Enable_Bit, NITIO_Gi_DMA_Config_Reg(counter->counter_index));
}
/*start the MITE*/
- mite_dma_arm(counter->mite, counter->mite_channel);
+ mite_dma_arm(counter->mite_chan);
return ni_tio_arm(counter, 1, NI_GPCT_ARM_IMMEDIATE);
}
{
comedi_cmd *cmd = &async->cmd;
- if(counter->mite == NULL || counter->mite_channel < 0)
+ if(counter->mite_chan == NULL)
{
rt_printk("ni_tio: commands only supported with DMA. Interrupt-driven commands not yet implemented.\n");
return -EIO;
int ni_tio_cancel(struct ni_gpct *counter)
{
- if(counter->mite == NULL || counter->mite_channel < 0) return 0;
- mite_dma_disarm(counter->mite, counter->mite_channel);
+ if(counter->mite_chan == NULL) return 0;
+ mite_dma_disarm(counter->mite_chan);
return 0;
}
unsigned (*read_register)(struct ni_gpct *this, enum ni_gpct_register reg);
enum ni_gpct_variant variant;
uint64_t clock_period_ps; /* clock period in picoseconds */
- struct mite_struct *mite;
- int mite_channel; /* -1 when no channel is allocated to the counter */
+ struct mite_channel *mite_chan;
unsigned regs[MAX_NUM_NITIO_REGS];
};