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) */
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;
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;
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;
/* 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;
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;
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)
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;
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;
}
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)
{
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