Changed request/release of mite channels to use mite_channel struct
authorFrank Mori Hess <fmhess@speakeasy.net>
Thu, 26 Apr 2007 17:43:44 +0000 (17:43 +0000)
committerFrank Mori Hess <fmhess@speakeasy.net>
Thu, 26 Apr 2007 17:43:44 +0000 (17:43 +0000)
pointers, instead of channel indices.  Changed many mite functions
to take mite_channel argument instead of a mite_struct and a
channel index.  Added mite_dma_descriptor_ring, since drivers
need to maintain the descriptors seperatly from a channel, since
the channel is reserved/released with each use but the
descriptor ring only changes when comedi's buffer is resized.  Made
ni_mio_common.c dynamically allocate mite channels for ai/ao
when needed, instead of permanently assigning mite channels to
subdevices.

comedi/drivers/mite.c
comedi/drivers/mite.h
comedi/drivers/ni_660x.c
comedi/drivers/ni_mio_common.c
comedi/drivers/ni_pcidio.c
comedi/drivers/ni_pcimio.c
comedi/drivers/ni_stc.h
comedi/drivers/ni_tio.c
comedi/drivers/ni_tio.h

index 076c8e57c0084688ce88a1aa6084f98c55f5a994..35df00dcf4dc7044d56b3512bb1419a8a8ebaabe 100644 (file)
@@ -76,6 +76,8 @@ void mite_init(void)
        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");
@@ -85,7 +87,11 @@ void mite_init(void)
                        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;
                }
@@ -190,6 +196,7 @@ void mite_unsetup(struct mite_struct *mite)
 
        if(!mite)return;
 
+       pci_disable_device(mite->pcidev);
        if(mite->mite_io_addr){
                iounmap(mite->mite_io_addr);
                mite->mite_io_addr=NULL;
@@ -222,64 +229,66 @@ void mite_list_devices(void)
 
 }
 
-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;
@@ -290,49 +299,39 @@ int mite_load_buffer(struct mite_struct *mite, unsigned int channel, comedi_asyn
        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;
@@ -355,7 +354,7 @@ void mite_prep_dma( struct mite_struct *mite, unsigned int channel,
        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;
@@ -373,11 +372,11 @@ void mite_prep_dma( struct mite_struct *mite, unsigned int channel,
                        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;
@@ -392,90 +391,94 @@ void mite_prep_dma( struct mite_struct *mite, unsigned int channel,
                        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(mitechan);
-       return device_byte_count - mite_bytes_in_transit(mitechan);
+       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(mitechan);
-       return mite_device_bytes_transferred(mitechan) - 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(mitechan);
-       return device_byte_count + mite_bytes_in_transit(mitechan);
+       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(mitechan);
-       return mite_device_bytes_transferred(mitechan) + 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;
@@ -485,8 +488,8 @@ int mite_sync_input_dma(struct mite_struct *mite, unsigned mite_channel, comedi_
        // 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;
@@ -512,7 +515,7 @@ int mite_sync_input_dma(struct mite_struct *mite, unsigned mite_channel, comedi_
        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;
@@ -522,11 +525,11 @@ int mite_sync_output_dma(struct mite_struct *mite, unsigned mite_channel, comedi
        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;
@@ -621,14 +624,14 @@ static char *mite_CHSR_strings[] = {
        "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));
@@ -704,8 +707,8 @@ EXPORT_SYMBOL(mite_setregs);
 #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);
index 387376b1925ca83f1395726f8a673f2d0a068c1e..089fffcff4633227edf008f02678040d44dab20c 100644 (file)
 
 #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{
@@ -90,33 +111,38 @@ void mite_cleanup(void);
 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)
@@ -378,5 +404,10 @@ enum CHSR_bits
        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
 
index 959ac3f11d7435d5dada4c395ac0b7165c01dd0b..af257ece1c9d21b57fc9c0440f1c08546f5493fa 100644 (file)
@@ -677,8 +677,7 @@ static int ni_660x_attach(comedi_device *dev,comedi_devconfig *it)
                        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;
index c5e81d1eef4382de3036a8a92208cd005ab7d5df..98e2b86be16e0b5930c5341e0a6f3313e9f4cb38 100644 (file)
@@ -309,7 +309,111 @@ static void get_last_sample_6143( comedi_device *dev );
 #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){
@@ -391,14 +495,13 @@ static inline void ni_set_bits(comedi_device *dev, int reg, int bits, int value)
 {
        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:
@@ -406,7 +509,6 @@ static inline void ni_set_bits(comedi_device *dev, int reg, int bits, int value)
                                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:
@@ -414,15 +516,14 @@ static inline void ni_set_bits(comedi_device *dev, int reg, int bits, int value)
                                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 );
 }
 
 
@@ -431,8 +532,8 @@ static irqreturn_t ni_E_interrupt(int irq, void *d PT_REGS_ARG)
        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;
@@ -444,26 +545,28 @@ static irqreturn_t ni_E_interrupt(int irq, void *d PT_REGS_ARG)
        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);
@@ -475,11 +578,12 @@ static void mite_handle_b_linkc(struct mite_struct *mite, comedi_device *dev)
 {
        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;
        }
 }
@@ -540,7 +644,7 @@ static void ni_handle_eos(comedi_device *dev, comedi_subdevice *s)
 
                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);
                }
@@ -562,7 +666,10 @@ static void shutdown_ai_command( comedi_device *dev )
 
 #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);
@@ -595,19 +702,19 @@ static void handle_a_interrupt(comedi_device *dev,unsigned short status,
 #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
@@ -620,7 +727,7 @@ static void handle_a_interrupt(comedi_device *dev,unsigned short status,
                         * 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;
                }
@@ -683,7 +790,6 @@ static void handle_a_interrupt(comedi_device *dev,unsigned short status,
        }
 #endif
        if(ack) devpriv->stc_writew(dev, ack,Interrupt_A_Ack_Register);
-
        comedi_event(dev,s,s->async->events);
 
 #ifdef DEBUG_INTERRUPT
@@ -712,15 +818,15 @@ static void handle_b_interrupt(comedi_device *dev,unsigned short b_status, unsig
        }
 
        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;
@@ -983,14 +1089,14 @@ static void ni_handle_fifo_half_full(comedi_device *dev)
 #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);
        }
@@ -998,11 +1104,11 @@ static int ni_ai_drain_dma(comedi_device *dev )
        {
                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;
 }
@@ -1124,39 +1230,45 @@ static void ni_ai_munge(comedi_device *dev, comedi_subdevice *s,
 
 #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);
@@ -1165,19 +1277,19 @@ static void ni_ao_setup_MITE_dma(comedi_device *dev, comedi_cmd *cmd)
        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
@@ -1191,7 +1303,10 @@ static void ni_ao_setup_MITE_dma(comedi_device *dev, comedi_cmd *cmd)
 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);
@@ -1276,7 +1391,7 @@ static int ni_ai_poll(comedi_device *dev,comedi_subdevice *s)
 #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)
@@ -1795,6 +1910,11 @@ static int ni_ai_cmdtest(comedi_device *dev,comedi_subdevice *s,comedi_cmd *cmd)
        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;
@@ -2053,7 +2173,10 @@ static int ni_ai_cmd(comedi_device *dev,comedi_subdevice *s)
        }
 
 #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
 
@@ -2428,7 +2551,7 @@ static int ni_ao_inttrig(comedi_device *dev,comedi_subdevice *s,
        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;
@@ -2436,7 +2559,8 @@ static int ni_ao_inttrig(comedi_device *dev,comedi_subdevice *s,
        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;
 
@@ -2476,6 +2600,11 @@ static int ni_ao_inttrig(comedi_device *dev,comedi_subdevice *s,
        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;
@@ -2726,8 +2855,11 @@ static int ni_ao_reset(comedi_device *dev,comedi_subdevice *s)
        //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);
@@ -3213,6 +3345,8 @@ static int ni_alloc_private(comedi_device *dev)
        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;
 };
@@ -3220,7 +3354,6 @@ static int ni_alloc_private(comedi_device *dev)
 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)
@@ -3249,13 +3382,14 @@ static int ni_E_init(comedi_device *dev,comedi_devconfig *it)
                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;
        }
@@ -3284,8 +3418,9 @@ static int ni_E_init(comedi_device *dev,comedi_devconfig *it)
 #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;
@@ -3464,10 +3599,7 @@ static int ni_E_init(comedi_device *dev,comedi_devconfig *it)
                        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]);
        }
 
@@ -3506,15 +3638,8 @@ static int ni_E_init(comedi_device *dev,comedi_devconfig *it)
        }
 
        /* 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)
        {
index 93bbf8402df6f6bd09227b11834cfd895326d6b1..f713afba72b13af357bf3d5a9e639ecdf83b3ab7 100644 (file)
@@ -205,8 +205,17 @@ comedi_nonfree_firmware tarball available from http://www.comedi.org
 #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)
@@ -282,11 +291,6 @@ enum FPGA_Control_Bits
 #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={
@@ -390,6 +394,9 @@ typedef struct{
        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)
 
@@ -400,7 +407,7 @@ static int ni_pcidio_inttrig(comedi_device *dev, comedi_subdevice *s,
        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);
@@ -410,6 +417,43 @@ static void ni_pcidio_print_status(unsigned int status);
 #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){
@@ -420,13 +464,28 @@ static int nidio96_8255_cb(int dir,int port,int data,unsigned long iobase)
        }
 }
 
+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;
@@ -434,11 +493,11 @@ static irqreturn_t nidio_interrupt(int irq, void *d PT_REGS_ARG)
        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){
@@ -446,48 +505,46 @@ static irqreturn_t nidio_interrupt(int irq, void *d PT_REGS_ARG)
                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++;
@@ -530,20 +587,14 @@ static irqreturn_t nidio_interrupt(int irq, void *d PT_REGS_ARG)
 
                        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");
@@ -573,7 +624,6 @@ static irqreturn_t nidio_interrupt(int irq, void *d PT_REGS_ARG)
 
 out:
        comedi_event(dev,s,async->events);
-
 #if 0
        if(!tag){
                writeb(0x03,devpriv->mite->daq_io_addr+Master_DMA_And_Interrupt_Control);
@@ -807,6 +857,10 @@ static int ni_pcidio_ns_to_timer(int *nanosec, int round_mode)
        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)
 {
@@ -876,13 +930,17 @@ 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);
@@ -909,19 +967,19 @@ static int ni_pcidio_cmd(comedi_device *dev,comedi_subdevice *s)
        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;
 }
 
 
@@ -950,7 +1008,7 @@ static int ni_pcidio_change(comedi_device *dev, comedi_subdevice *s,
 {
        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);
@@ -1070,6 +1128,9 @@ static int nidio_attach(comedi_device *dev,comedi_devconfig *it)
 
        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;
@@ -1118,6 +1179,7 @@ static int nidio_attach(comedi_device *dev,comedi_devconfig *it)
                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 */
@@ -1155,9 +1217,16 @@ static int nidio_detach(comedi_device *dev)
        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;
 }
 
index 361843dab05aa861cbd7a608e9c1d107d0201616..3e87320475ddd58e78fe878ee490e117f38838fa 100644 (file)
@@ -1041,6 +1041,12 @@ COMEDI_INITCLEANUP(driver_pcimio);
 
 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;
@@ -1407,12 +1413,17 @@ static void init_6143(comedi_device *dev)
 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;
@@ -1426,6 +1437,14 @@ static int pcimio_attach(comedi_device *dev,comedi_devconfig *it)
 
        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;
@@ -1513,8 +1532,8 @@ static int pcimio_ai_change(comedi_device *dev, comedi_subdevice *s,
 {
        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;
 }
@@ -1524,8 +1543,8 @@ static int pcimio_ao_change(comedi_device *dev, comedi_subdevice *s,
 {
        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;
 }
index 04b1eb13c9695d32c4859b9208d8571431907cc0..6390c384c2d5217a78b989a459718a37494908eb 100644 (file)
@@ -691,6 +691,13 @@ enum XXX_Status_Bits
 #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 */
@@ -855,14 +862,6 @@ enum cs5529_status_bits
        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 };
@@ -1292,6 +1291,8 @@ static ni_board ni_boards[];
        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;                             \
@@ -1300,7 +1301,7 @@ static ni_board ni_boards[];
        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;                                \
@@ -1321,13 +1322,15 @@ static ni_board ni_boards[];
        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; \
index 3c9f851fa8865225df9e65f3305061c0a84f8bd3..326322379178e204a25740553104019aa583db9c 100644 (file)
@@ -1978,21 +1978,19 @@ int ni_tio_winsn(struct ni_gpct *counter,
 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);
 }
 
@@ -2005,7 +2003,7 @@ int ni_tio_cmd(struct ni_gpct *counter, comedi_async *async)
 {
        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;
@@ -2027,8 +2025,8 @@ int ni_tio_cmdtest(struct ni_gpct *counter)
 
 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;
 }
 
index 2bb503127f4ef654af5e506d05d06c678d520863..e561088a9eb1adfad09be496b2fb51683dffcf0d 100644 (file)
@@ -106,8 +106,7 @@ struct ni_gpct
        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];
 };