Mite additions from Tim Ousley
authorDavid Schleef <ds@schleef.org>
Fri, 6 Apr 2001 22:55:53 +0000 (22:55 +0000)
committerDavid Schleef <ds@schleef.org>
Fri, 6 Apr 2001 22:55:53 +0000 (22:55 +0000)
comedi/drivers/mite.c
comedi/drivers/mite.h

index 76fd59b4fb92bd014936962a384b845ac06cbab9..00a1145e1da25332d6234ffec0013cbe4e5c09c3 100644 (file)
@@ -69,9 +69,9 @@
 
 
 struct mite_struct *mite_devices = NULL;
-
-
-
+       
+#define TOP_OF_PAGE(x) ((x)|(~(PAGE_MASK)))
+#define min(a,b) (((a)<(b))?(a):(b))
 
 #ifdef PCI_SUPPORT_VER1
 /* routines for the old PCI code (before 2.1.55) */
@@ -92,6 +92,10 @@ void mite_init(void)
                pcibios_read_config_word(pci_bus,pci_device_fn,PCI_VENDOR_ID,&vendor);
                if(vendor==PCI_VENDOR_ID_NATINST){
                        mite=kmalloc(sizeof(*mite),GFP_KERNEL);
+                       if(!mite){
+                               printk("mite: allocation failed\n");
+                               return;
+                       }
                        memset(mite,0,sizeof(*mite));
 
                        mite->pci_bus=pci_bus;
@@ -118,6 +122,10 @@ void mite_init(void)
        pci_for_each_dev(pcidev){
                if(pcidev->vendor==PCI_VENDOR_ID_NATINST){
                        mite=kmalloc(sizeof(*mite),GFP_KERNEL);
+                       if(!mite){
+                               printk("mite: allocation failed\n");
+                               return;
+                       }
                        memset(mite,0,sizeof(*mite));
 
                        mite->pcidev=pcidev;
@@ -165,8 +173,9 @@ int mite_setup(struct mite_struct *mite)
        printk("DAQ:0x%08lx mapped to %p, ",mite->daq_phys_addr,mite->daq_io_addr);
 
        /* XXX don't know what the 0xc0 and 0x80 mean */
+       /* It must be here for the driver to work though */
        writel(mite->daq_phys_addr | 0x80 , mite->mite_io_addr + 0xc0 );
-       
+
 #ifdef PCI_SUPPORT_VER1
        {
                unsigned char irq;
@@ -178,10 +187,9 @@ int mite_setup(struct mite_struct *mite)
        /* 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].unused=0x1c; /* eh? */
+
        }
        mite->ring[i].next=0;
-       mite->ring[i].unused=0x1c; /* eh? */
 
        mite->used = 1;
 
@@ -261,8 +269,8 @@ void mite_dma_prep(struct mite_struct *mite,comedi_subdevice *s)
        chor = CHOR_DMARESET | CHOR_FRESET;
        writel(chor,mite->mite_io_addr+MITE_CHOR+CHAN_OFFSET(0));
 
-       chcr = CHCR_LINKLONG | CHCR_DEV_TO_MEM;
-       //chcr = CHCR_LINKLONG | CHCR_MEM_TO_DEV;
+       // 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;
@@ -276,7 +284,105 @@ void mite_dma_prep(struct mite_struct *mite,comedi_subdevice *s)
        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 len)
+{
+       int i,size_so_far;
+       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)s->async->prealloc_buf;
+       //prealloc_bufsz=s->async->prealloc_bufsz;
+       
+       //len = min(cmd->scan_end_arg*cmd->stop_arg*sizeof(sampl_t), async->data_len);
+       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;
+       size_so_far=0;
+       MDPRINTK("buf=0x%08lx bufsz=0x%08x\n",
+               (unsigned long)prealloc_buf,prealloc_bufsz);
+       
+       while(((void*)nup < (async->data+len))&&(i<(MITE_RING_SIZE-1))) {
+               mite->ring[i].addr =kvirt_to_bus(nup);// it's already a kernel address :-)
+               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");
+       }
+       #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_kvmem\n");
+       return virt_to_bus(&(mite->ring[0]));
+}
+
+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)
@@ -290,6 +396,67 @@ void mite_dma_arm(struct mite_struct *mite)
        mite_dma_tcr(mite);
 }
 
+
+void mite_setregs(struct mite_struct *mite,unsigned long ll_start,int chan,int dir)
+{
+       //*mite is the mite to work with
+       //ll_start is the beginning of the linkshort mite linked list
+       //chan is the DMA channel to use on the MITE (0,1,2,3)
+       //dir is the direction of the transfer COMEDI_INPUT or COMEDI_OUTPUT
+       int chor,chcr,mcr,dcr,lkcr;
+       
+       MDPRINTK("mite_setregs\n");
+       
+       chor = CHOR_DMARESET | CHOR_FRESET; //reset DMA and FIFO
+       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(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 STC
+       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(ll_start,mite->mite_io_addr+MITE_LKAR+CHAN_OFFSET(chan));
+       
+       MDPRINTK("exit mite_setregs\n");
+}
+
+int mite_bytes_transferred(struct mite_struct *mite, int chan)
+{
+       int bytes;
+       
+       bytes = readl(mite->mite_io_addr+MITE_DAR+CHAN_OFFSET(chan));
+       bytes -= readl(mite->mite_io_addr+MITE_FCR+CHAN_OFFSET(chan)) & 0x000000FF;
+       return bytes;
+}
+
 int mite_dma_tcr(struct mite_struct *mite)
 {
        int tcr;
@@ -297,7 +464,7 @@ int mite_dma_tcr(struct mite_struct *mite)
 
        lkar=readl(mite->mite_io_addr+CHAN_OFFSET(0)+MITE_LKAR);
        tcr=readl(mite->mite_io_addr+CHAN_OFFSET(0)+MITE_TCR);
-       printk("lkar=0x%08x tcr=%d\n",lkar,tcr);
+       MDPRINTK("lkar=0x%08x tcr=%d\n",lkar,tcr);
 
        return tcr;
 }
@@ -311,6 +478,49 @@ void mite_dma_disarm(struct mite_struct *mite)
        writel(chor,mite->mite_io_addr+CHAN_OFFSET(0)+MITE_CHOR);
 }
 
+void mite_dump_regs(struct mite_struct *mite)
+{
+       unsigned long mite_io_addr = mite->mite_io_addr;
+       unsigned long addr=0;
+       unsigned long temp=0;
+
+       printk("mite address is  =0x%08lx\n",mite_io_addr);
+               
+       addr = mite_io_addr+MITE_CHOR+CHAN_OFFSET(0);
+       printk("mite status[CHOR]at 0x%08lx =0x%08lx\n",addr, temp=readl(addr));
+       //mite_decode(mite_CHOR_strings,temp);
+       addr = mite_io_addr+MITE_CHCR+CHAN_OFFSET(0);
+       printk("mite status[CHCR]at 0x%08lx =0x%08lx\n",addr, temp=readl(addr));
+       //mite_decode(mite_CHCR_strings,temp);
+       addr = mite_io_addr+MITE_TCR+CHAN_OFFSET(0);
+       printk("mite status[TCR] at 0x%08lx =0x%08x\n",addr, readl(addr));
+       addr = mite_io_addr+MITE_MCR+CHAN_OFFSET(0);
+       printk("mite status[MCR] at 0x%08lx =0x%08lx\n",addr, temp=readl(addr));
+       //mite_decode(mite_MCR_strings,temp);
+       
+       addr = mite_io_addr+MITE_MAR+CHAN_OFFSET(0);
+       printk("mite status[MAR] at 0x%08lx =0x%08x\n",addr, readl(addr));
+       addr = mite_io_addr+MITE_DCR+CHAN_OFFSET(0);
+       printk("mite status[DCR] at 0x%08lx =0x%08lx\n",addr, temp=readl(addr));
+       //mite_decode(mite_CR_strings,temp);
+       addr = mite_io_addr+MITE_DAR+CHAN_OFFSET(0);
+       printk("mite status[DAR] at 0x%08lx =0x%08x\n",addr, readl(addr));
+       addr = mite_io_addr+MITE_LKCR+CHAN_OFFSET(0);
+       printk("mite status[LKCR]at 0x%08lx =0x%08lx\n",addr, temp=readl(addr));
+       //mite_decode(mite_CR_strings,temp);
+       addr = mite_io_addr+MITE_LKAR+CHAN_OFFSET(0);
+       printk("mite status[LKAR]at 0x%08lx =0x%08x\n",addr, readl(addr));
+
+       addr = mite_io_addr+MITE_CHSR+CHAN_OFFSET(0);
+       printk("mite status[CHSR]at 0x%08lx =0x%08lx\n",addr, temp=readl(addr));
+       //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 MODULE
 int init_module(void)
 {
@@ -354,6 +564,13 @@ EXPORT_SYMBOL(mite_kvmem_segment_load);
 EXPORT_SYMBOL(mite_devices);
 EXPORT_SYMBOL(mite_list_devices);
 
+//Tim's debugging function
+EXPORT_SYMBOL(mite_dump_regs);
+EXPORT_SYMBOL(mite_ll_from_user);
+EXPORT_SYMBOL(mite_ll_from_kvmem);
+EXPORT_SYMBOL(mite_setregs);
+EXPORT_SYMBOL(mite_bytes_transferred);
+
 #endif
 
 #endif
index e183056092034c3f762c566457ddf97ba4f9288f..5383638ab2738ac75aaab31f2db6f2573c2da892 100644 (file)
 
 #define PCI_VENDOR_ID_NATINST          0x1093
 
+//#define DEBUG_MITE
 
-#define MITE_RING_SIZE 32
+#ifdef DEBUG_MITE
+#define MDPRINTK(format,args...)       printk(format , ## args )
+#else
+#define MDPRINTK(format,args...)
+#endif
+
+#define MITE_RING_SIZE 3000 
 
 struct mite_dma_chain{
        u32 count;
        u32 addr;
-       u32 unused;
        u32 next;
 };
 
@@ -88,7 +94,12 @@ int mite_dma_tcr(struct mite_struct *mite);
 
 void mite_dma_arm(struct mite_struct *mite);
 void mite_dma_disarm(struct mite_struct *mite);
-
+       
+unsigned long mite_ll_from_user(comedi_device *dev, comedi_cmd *cmd);
+unsigned long mite_ll_from_kvmem(struct mite_struct *mite,comedi_async *async,int len);
+void mite_dump_regs(struct mite_struct *mite);
+void mite_setregs(struct mite_struct *mite,unsigned long ll_start,int chan, int dir);
+int mite_bytes_transferred(struct mite_struct *mite, int chan);
 
 #define CHAN_OFFSET(x)                 (0x100*(x))
 
@@ -206,6 +217,10 @@ void mite_dma_disarm(struct mite_struct *mite);
 #define CR_PORTMXI                     (3<<6)
 #define CR_AMDEVICE                    (1<<0)
 
+#define CHSR_INT                       0x80000000
+#define CHSR_DONE                      0x02000000
+#define CHSR_LINKC                     0x00080000
+
 #define MITE_MCR               0x50c
 #define        MCRPON                          0
 
@@ -241,7 +256,5 @@ void mite_dma_disarm(struct mite_struct *mite);
 #define MITE_AMHOST_A32D64_BLOCK       0x08
 #define MITE_AMHOST_A24_BLOCK  0x3b
 
-
-
 #endif