Added cpu_to_le32() for big-endian machines. Removed unused functions.
authorDavid Schleef <ds@schleef.org>
Sun, 10 Feb 2002 03:26:49 +0000 (03:26 +0000)
committerDavid Schleef <ds@schleef.org>
Sun, 10 Feb 2002 03:26:49 +0000 (03:26 +0000)
Cleanups.  Converted most to use mite->chan.  Added functions for
ni_pcidio.  Added chsr dump function.

comedi/drivers/mite.c

index f581b8007f352e6db3ee2f7499cd724260070105..25f5fdc873f871e19a1ed958ac88f01ba00303b6 100644 (file)
@@ -3,7 +3,7 @@
     Hardware driver for NI Mite PCI interface chip
 
     COMEDI - Linux Control and Measurement Device Interface
-    Copyright (C) 1997-8 David A. Schleef <ds@stm.lbl.gov>
+    Copyright (C) 1997-2002 David A. Schleef <ds@schleef.org>
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
@@ -69,7 +69,7 @@
 
 
 struct mite_struct *mite_devices = NULL;
-       
+
 #define TOP_OF_PAGE(x) ((x)|(~(PAGE_MASK)))
 
 #ifdef PCI_SUPPORT_VER1
@@ -199,12 +199,14 @@ int mite_setup(struct mite_struct *mite)
        }
 #endif
 
+#ifdef PCIMIO_COMPAT
        /* DMA setup */
        for(i=0;i<MITE_RING_SIZE-1;i++){
-               mite->ring[i].next=virt_to_bus(mite->ring+i+1);
+               mite->ring[i].next=cpu_to_le32(virt_to_bus(mite->ring+i+1));
 
        }
        mite->ring[i].next=0;
+#endif
 
        mite->used = 1;
 
@@ -271,67 +273,27 @@ int mite_kvmem_segment_load(struct mite_struct *mite,int i,char *kvmem,unsigned
 
        offset=((int)kvmem)&(PAGE_SIZE-1);
 
-       mite->ring[i].addr = kvirt_to_bus((int)kvmem);
+       mite->ring[i].addr = cpu_to_le32(kvirt_to_bus((int)kvmem));
+       //mite->ring[i].dar = cpu_to_le32(0x1c);
 
        count=PAGE_SIZE-offset;
        if(count>len)count=len;
-       mite->ring[i].count = count;
+       mite->ring[i].count = cpu_to_le32(count);
 
        return count;
 }
 
-void mite_dma_prep(struct mite_struct *mite,comedi_subdevice *s)
-{
-       int i,n;
-       int chor,chcr,mcr,dcr,lkcr;
-
-       for(i=0;i<MITE_RING_SIZE;i++){
-               n=s->async->prealloc_bufsz-s->async->buf_int_ptr;
-               n=mite_kvmem_segment_load(mite,i,s->async->data+s->async->buf_int_ptr,n);
-               s->async->buf_int_ptr+=n;
-               if(s->async->buf_int_ptr>=s->async->prealloc_bufsz)
-                       s->async->buf_int_ptr=0;
-       }
-
-       chor = CHOR_DMARESET | CHOR_FRESET;
-       writel(chor,mite->mite_io_addr+MITE_CHOR+CHAN_OFFSET(0));
-
-       // Should this be LINKLONG for 32HS?
-       chcr = CHCR_LINKSHORT | CHCR_DEV_TO_MEM;
-       writel(chcr,mite->mite_io_addr+MITE_CHCR+CHAN_OFFSET(0));
-
-       mcr = CR_RL64 | CR_ASEQxP1 | CR_PSIZEHALF;
-       writel(mcr,mite->mite_io_addr+MITE_MCR+CHAN_OFFSET(0));
-
-       dcr = CR_RL64 | CR_PSIZEHALF | CR_PORTIO | CR_AMDEVICE;
-       dcr |= CR_REQSDRQ0;
-       writel(dcr,mite->mite_io_addr+MITE_DCR+CHAN_OFFSET(0));
-
-       lkcr = CR_RL64 | CR_ASEQUP | CR_PSIZEWORD;
-       writel(lkcr,mite->mite_io_addr+MITE_LKCR+CHAN_OFFSET(0));
-
-       writel(virt_to_bus(mite->ring),mite->mite_io_addr+MITE_LKAR+CHAN_OFFSET(0));
-}
-
-
 
 /*
  * Create the short linkchaining MITE linked list using kernel memory
- * a drop in replacement for mite_ll_from_user( ) 
  */
 unsigned long mite_ll_from_kvmem(struct mite_struct *mite,comedi_async *async,int reqlen)
 {
        int i,size_so_far, continuous_aq, len;
        unsigned long nup;
        unsigned long prealloc_buf,prealloc_bufsz; 
-       //comedi_subdevice *s;
-       //struct mite_struct *mite=NULL;
-       //comedi_async *async=NULL;
-       //int len;
                
        MDPRINTK("mite_ll_from_kvmem\n");
-       //s=dev->subdevices+cmd->subdev;
-       //mite=devpriv->mite;
        prealloc_buf=(unsigned long)async->prealloc_buf;
        prealloc_bufsz=async->prealloc_bufsz;
        
@@ -342,10 +304,6 @@ unsigned long mite_ll_from_kvmem(struct mite_struct *mite,comedi_async *async,in
                len = (reqlen>prealloc_bufsz?prealloc_bufsz:reqlen);
        }
        
-       //if(async->data_len<len) {
-       //      printk("<1>Comedi Error: preallocated DMA buffer is too small to hold the samples.");
-       //}
-       
        //find the kernel's memory pages.
        nup = (unsigned long)async->data;
        i=0;
@@ -357,25 +315,26 @@ unsigned long mite_ll_from_kvmem(struct mite_struct *mite,comedi_async *async,in
                int count;
                count = 1+TOP_OF_PAGE(nup)-nup;
                if(count>len-size_so_far) count = len-size_so_far;
-               mite->ring[i].addr =kvirt_to_bus(nup);// it's already a kernel address :-)
-               mite->ring[i].count=count;
-               mite->ring[i].next=virt_to_bus(mite->ring+i+1);
-               size_so_far += mite->ring[i].count;
-               nup += mite->ring[i].count;
+               mite->ring[i].addr = cpu_to_le32(kvirt_to_bus((void *)nup));// it's already a kernel address :-)
+               mite->ring[i].count = cpu_to_le32(count);
+               //mite->ring[i].dar = cpu_to_le32(0x1c);
+               mite->ring[i].next = cpu_to_le32(virt_to_bus(mite->ring+i+1));
+               size_so_far += count;
+               nup += count;
                i++;
        }
        
        /*End the mite->ring by setting the last element's count to 0.
        To make a looping ring for continuous acquisition, 
-       mite->ring[i-1].next = virt_to_bus(mite->ring);
+       mite->ring[i-1].next = cpu_to_le32(virt_to_bus(mite->ring));
        */
        //mite->ring[i].count=0;
        
        if (continuous_aq&&(i>0)) {
-               mite->ring[i-1].next = virt_to_bus(mite->ring+0);
+               mite->ring[i-1].next = cpu_to_le32(virt_to_bus(mite->ring+0));
                mite->DMA_CheckNearEnd = 0;
        }else if (prealloc_bufsz < reqlen) {
-               mite->ring[i-1].next = virt_to_bus(mite->ring+0);
+               mite->ring[i-1].next = cpu_to_le32(virt_to_bus(mite->ring+0));
                mite->DMA_CheckNearEnd = 1;
        }       
        else {
@@ -388,61 +347,16 @@ unsigned long mite_ll_from_kvmem(struct mite_struct *mite,comedi_async *async,in
        if(size_so_far<len) {
                printk("<1>Comedi Error: MITE_RING_SIZE is too small to hold the needed buffer\n");
        }
-       #if 0 //#ifdef DEBUG_MITE
+#ifdef DEBUG_MITE
        for(i=0; i<MITE_RING_SIZE;i++){
-               printk("i=%3d, addr=0x%08x, next=0x%08x, count=0x%08x\n",i,mite->ring[i].addr,
-                       mite->ring[i].next, mite->ring[i].count);
+               printk("i=%3d, addr=0x%08x, next=0x%08x, count=0x%08x dar=%08x\n",i,mite->ring[i].addr,
+                       mite->ring[i].next, mite->ring[i].count, mite->ring[i].dar);
        }
-       #endif
+#endif
        MDPRINTK("exit mite_ll_from_kvmem\n");
        return virt_to_bus(&(mite->ring[0]));
 }
 
-/* This function would be used to DMA directly into user memory.
-Since Comedi won't support that for a while, this should probably be removed. --Tim Ousley
-unsigned long mite_ll_from_user(comedi_device *dev, comedi_cmd *cmd)
-{
-       int i,size_so_far,len;
-       unsigned long nup;
-               
-       comedi_subdevice *s;
-       struct mite_struct *mite;
-               
-       MDPRINTK("mite_ll_from_user\n");
-       s=dev->subdevices+cmd->subdev;
-       //mite=devpriv->mite;
-       len = cmd->data_len;
-       
-       //find the users memory pages.
-       nup = (unsigned long)cmd->data; i=0; size_so_far=0;
-       MDPRINTK("buf=0x%08lx bufsz=0x%08x\n",
-               (unsigned long)cmd->data,cmd->data_len);
-       while(((void*)nup < ((void*)cmd->data+len))&&(i<(MITE_RING_SIZE-1))) {
-               mite->ring[i].addr =uvirt_to_bus(nup);
-               mite->ring[i].count=min(1+TOP_OF_PAGE(nup)-nup,len-size_so_far);
-               mite->ring[i].next=virt_to_bus(mite->ring+i+1);
-               size_so_far += mite->ring[i].count;
-               nup += mite->ring[i].count;
-               i++;
-       }
-       mite->ring[i].count=0;
-       MDPRINTK("i was %d, size_so_far was %d\n",i,size_so_far);
-       if(size_so_far<len) {
-               printk("<1>Comedi Error: MITE_RING_SIZE is too small to hold the needed buffer\n");
-               printk("<1>Comedi Error: MITE_RING_SIZE is %d, buffer is %d bytes\n",
-                       MITE_RING_SIZE, len);
-       }
-       
-       #if 0 //#ifdef DEBUG_MITE
-       for(i=0; i<MITE_RING_SIZE;i++){
-               printk("i=%3d, addr=0x%08x, next=0x%08x, count=0x%08x\n",i,mite->ring[i].addr,
-                       mite->ring[i].next, mite->ring[i].count);
-       }
-       #endif
-       MDPRINTK("exit mite_ll_from_user\n");
-       return virt_to_bus(&(mite->ring[0]));
-}
-*/
 
 void mite_dma_arm(struct mite_struct *mite)
 {
@@ -450,7 +364,7 @@ void mite_dma_arm(struct mite_struct *mite)
 
        /* arm */
        chor = CHOR_START;
-       writel(chor,mite->mite_io_addr+CHAN_OFFSET(0)+MITE_CHOR);
+       writel(chor,mite->mite_io_addr+CHAN_OFFSET(mite->chan)+MITE_CHOR);
 
        mite_dma_tcr(mite);
 }
@@ -507,6 +421,133 @@ void mite_setregs(struct mite_struct *mite,unsigned long ll_start,int chan,int d
        MDPRINTK("exit mite_setregs\n");
 }
 
+
+/**************************************/
+
+int mite_load_buffer(struct mite_struct *mite, comedi_async *async)
+{
+       unsigned int n_links;
+       int i;
+
+       MDPRINTK("mite_load_buffer\n");
+
+       if(mite->ring){
+               kfree(mite->ring);
+       }
+
+       if(async->prealloc_bufsz==0){
+               return 0;
+       }
+
+       n_links = async->prealloc_bufsz >> PAGE_SHIFT;
+
+       MDPRINTK("buf=%p bufsz=0x%08x n_links=0x%04x\n",
+               async->prealloc_buf, async->prealloc_bufsz, n_links);
+
+       mite->ring = kmalloc(n_links*sizeof(struct mite_dma_chain),GFP_KERNEL);
+       if(!mite->ring){
+               printk("mite: ring buffer allocation failed\n");
+               return -ENOMEM;
+       }
+       mite->n_links = n_links;
+       mite->current_link = 0;
+
+       for(i=0;i<n_links;i++){
+               mite->ring[i].count = cpu_to_le32(PAGE_SIZE);
+               mite->ring[i].addr = cpu_to_le32(
+                       virt_to_bus(async->prealloc_buf + i*PAGE_SIZE));
+               mite->ring[i].next = cpu_to_le32(virt_to_bus(mite->ring+i+1));
+               mite->ring[i].dar = 0x1c;
+       }
+
+       mite->ring[n_links-1].next = cpu_to_le32(virt_to_bus(mite->ring));
+
+       return 0;
+}
+
+int mite_buf_alloc(struct mite_struct *mite, comedi_async *async,
+       unsigned long new_size)
+{
+       MDPRINTK("mite_buf_alloc\n");
+
+       if(async->prealloc_buf && async->prealloc_bufsz == new_size){
+               return 0;
+       }
+
+       if(async->prealloc_bufsz){
+               kfree(async->prealloc_buf);
+               async->prealloc_buf = NULL;
+               async->prealloc_bufsz = 0;
+       }
+
+       if(new_size){
+               async->prealloc_buf = kmalloc(new_size, GFP_KERNEL);
+               if(async->prealloc_buf == NULL){
+                       async->prealloc_bufsz = 0;
+                       return -ENOMEM;
+               }
+       }
+       async->prealloc_bufsz = new_size;
+
+       mite_load_buffer(mite,async);
+
+       return 0;
+}
+
+void mite_prep_dma(struct mite_struct *mite)
+{
+       unsigned int chor,chcr,mcr,dcr,lkcr;
+       int chan = mite->chan;
+       
+       MDPRINTK("mite_prep_dma\n");
+       
+       /* reset DMA and FIFO */
+       chor = CHOR_DMARESET | CHOR_FRESET;
+       writel(chor,mite->mite_io_addr+MITE_CHOR+CHAN_OFFSET(chan));
+       
+       /* short link chaining mode */
+       chcr = CHCR_SET_DMA_IE| CHCR_LINKSHORT | CHCR_SET_DONE_IE;
+       /*
+        * Link Complete Interrupt: interrupt every time a link
+        * in MITE_RING is completed. This can generate a lot of
+        * extra interrupts, but right now we update the values
+        * of buf_int_ptr and buf_int_count at each interrupt.  A
+        * better method is to poll the MITE before each user
+        * "read()" to calculate the number of bytes available.
+        * mite_bytes_transferred() is provided to get the number
+        * of bytes transferred to system memory so far.
+        */
+       chcr |= CHCR_SET_LC_IE; 
+       
+       if(mite->dir == COMEDI_INPUT){
+               chcr |= CHCR_DEV_TO_MEM;
+       }
+       writel(chcr,mite->mite_io_addr+MITE_CHCR+CHAN_OFFSET(chan));
+       
+       /* 16 bits, to memory */
+       mcr = CR_RL64 | CR_ASEQxP1 | CR_PSIZEHALF; 
+       writel(mcr,mite->mite_io_addr+MITE_MCR+CHAN_OFFSET(chan));
+
+       /* 16 bits, from device */
+       dcr = CR_RL64 |  CR_ASEQx(1) | CR_PSIZEHALF;
+       dcr |= CR_PORTIO | CR_AMDEVICE | CR_REQS(0x4+chan);
+       writel(dcr,mite->mite_io_addr+MITE_DCR+CHAN_OFFSET(chan));
+       
+       /* reset the DAR */
+       writel(0,mite->mite_io_addr+MITE_DAR+CHAN_OFFSET(chan));
+       
+       /* the link is 32bits */
+       lkcr = CR_RL64 | CR_ASEQUP | CR_PSIZEWORD;
+       writel(lkcr,mite->mite_io_addr+MITE_LKCR+CHAN_OFFSET(chan));
+
+       /* starting address for link chaining */
+       writel(virt_to_bus(mite->ring),
+               mite->mite_io_addr+MITE_LKAR+CHAN_OFFSET(chan));
+       
+       MDPRINTK("exit mite_prep_dma\n");
+}
+
+
 int mite_bytes_transferred(struct mite_struct *mite, int chan)
 {
        int dar, fcr;
@@ -521,8 +562,8 @@ int mite_dma_tcr(struct mite_struct *mite)
        int tcr;
        int lkar;
 
-       lkar=readl(mite->mite_io_addr+CHAN_OFFSET(0)+MITE_LKAR);
-       tcr=readl(mite->mite_io_addr+CHAN_OFFSET(0)+MITE_TCR);
+       lkar=readl(mite->mite_io_addr+CHAN_OFFSET(mite->chan)+MITE_LKAR);
+       tcr=readl(mite->mite_io_addr+CHAN_OFFSET(mite->chan)+MITE_TCR);
        MDPRINTK("lkar=0x%08x tcr=%d\n",lkar,tcr);
 
        return tcr;
@@ -534,7 +575,7 @@ void mite_dma_disarm(struct mite_struct *mite)
 
        /* disarm */
        chor = CHOR_ABORT;
-       writel(chor,mite->mite_io_addr+CHAN_OFFSET(0)+MITE_CHOR);
+       writel(chor,mite->mite_io_addr+CHAN_OFFSET(mite->chan)+MITE_CHOR);
 }
 
 void mite_dump_regs(struct mite_struct *mite)
@@ -572,12 +613,37 @@ void mite_dump_regs(struct mite_struct *mite)
 
        addr = mite_io_addr+MITE_CHSR+CHAN_OFFSET(0);
        printk("mite status[CHSR]at 0x%08lx =0x%08lx\n",addr, temp=readl(addr));
+       mite_print_chsr(temp);
        //mite_decode(mite_CHSR_strings,temp);
        addr = mite_io_addr+MITE_FCR+CHAN_OFFSET(0);
        printk("mite status[FCR] at 0x%08lx =0x%08x\n\n",addr, readl(addr));
 }
 
 
+#ifdef DEBUG_MITE
+static char *chsr_strings[] = {
+       "d.err0", "d.err1", "m.err0", "m.err1",
+       "l.err0", "l.err1", "drq0", "drq1",
+       "end", "xferr", "operr0", "operr1",
+       "stops", "habort", "sabort", "error",
+       "16", "conts_rb", "18", "linkc",
+       "20", "drdy", "22", "mrdy",
+       "24", "done", "26", "sars",
+       "28", "lpauses", "30", "int",
+};
+void mite_print_chsr(unsigned int bits)
+{
+       int i;
+
+       printk("chsr:");
+       for(i=31;i>=0;i--){
+               if(bits&(1<<i)){
+                       printk(" %s",chsr_strings[i]);
+               }
+       }
+       printk("\n");
+}
+#endif
 
 
 #ifdef MODULE
@@ -600,7 +666,6 @@ struct symbol_table mite_syms = {
 #include <linux/symtab_begin.h>
        X(mite_dma_arm),
        X(mite_dma_disarm),
-       X(mite_dma_prep),
        X(mite_setup),
        X(mite_unsetup),
        X(mite_kvmem_segment_load),
@@ -614,16 +679,17 @@ struct symbol_table mite_syms = {
 EXPORT_SYMBOL(mite_dma_tcr);
 EXPORT_SYMBOL(mite_dma_arm);
 EXPORT_SYMBOL(mite_dma_disarm);
-EXPORT_SYMBOL(mite_dma_prep);
 EXPORT_SYMBOL(mite_setup);
 EXPORT_SYMBOL(mite_unsetup);
 EXPORT_SYMBOL(mite_kvmem_segment_load);
 EXPORT_SYMBOL(mite_devices);
 EXPORT_SYMBOL(mite_list_devices);
+EXPORT_SYMBOL(mite_print_chsr);
+EXPORT_SYMBOL(mite_prep_dma);
+EXPORT_SYMBOL(mite_buf_alloc);
 
 //Tim's debugging function
 EXPORT_SYMBOL(mite_dump_regs);
-//EXPORT_SYMBOL(mite_ll_from_user); //obsolete
 EXPORT_SYMBOL(mite_ll_from_kvmem);
 EXPORT_SYMBOL(mite_setregs);
 EXPORT_SYMBOL(mite_bytes_transferred);