From: David Schleef Date: Sun, 10 Feb 2002 03:26:49 +0000 (+0000) Subject: Added cpu_to_le32() for big-endian machines. Removed unused functions. X-Git-Tag: r0_7_64~137 X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=f16d81cd43e20e724a2f75a558c281f36e9487fb;p=comedi.git Added cpu_to_le32() for big-endian machines. Removed unused functions. Cleanups. Converted most to use mite->chan. Added functions for ni_pcidio. Added chsr dump function. --- diff --git a/comedi/drivers/mite.c b/comedi/drivers/mite.c index f581b800..25f5fdc8 100644 --- a/comedi/drivers/mite.c +++ b/comedi/drivers/mite.c @@ -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 + Copyright (C) 1997-2002 David A. Schleef 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;iring[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;iasync->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_lenComedi 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_farComedi Error: MITE_RING_SIZE is too small to hold the needed buffer\n"); } - #if 0 //#ifdef DEBUG_MITE +#ifdef DEBUG_MITE for(i=0; iring[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_farComedi 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; iring[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;iring[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< 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);