/[VMELinux]/driver/ca91c042.c
ViewVC logotype

Contents of /driver/ca91c042.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.8 - (hide annotations)
Fri May 14 21:47:37 2004 UTC (15 years, 5 months ago) by jhuggins
Branch: MAIN
CVS Tags: License_change_back_to_GPL_May_2004, HEAD
Changes since 1.7: +30 -59 lines
File MIME type: text/plain
Changed license back to GPL.
Revised copyright year and contact information.
1 jhuggins 1.8 // ====================================================================
2     // These VMELinux tools provide Linux access to the VMEbus via the
3     // Tundra Universe PCI/VME bridge.
4     // Copyright (C) 1997-2004 John Huggins and Michael Wyrick
5     //
6     // This program is free software; you can redistribute it and/or modify
7     // it under the terms of the GNU General Public License as published by
8     // the Free Software Foundation; either version 2 of the License, or
9     // (at your option) any later version.
10     //
11     // This program is distributed in the hope that it will be useful,
12     // but WITHOUT ANY WARRANTY; without even the implied warranty of
13     // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14     // GNU General Public License for more details.
15     //
16     // You should have received a copy of the GNU General Public License
17     // along with this program; if not, write to the Free Software
18     // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19     //
20     // Contact the VMELinux project manager with questions at john@johnhuggins.com
21     // ====================================================================
22     //
23     // This software consists of voluntary contributions made by many
24     // individuals on behalf of the VMELinux Project. For more
25     // information on the VMELinux Project, please see
26     // <http://www.vmelinux.org/>.
27     //
28 jhuggins 1.7
29     //------------------------------------------------------------------------------
30     // Title: Tundra Universe PCI-VME Kernel Driver
31 jhuggins 1.8 // $Date: 2004/05/14 21:47:37 $
32     // $Author: jhuggins $
33     // $Revision: 1.8 $
34 jhuggins 1.7 // Initial programmer: Michael Wyrick
35     // language: GCC 2.95 and 3.0
36     //------------------------------------------------------------------------------
37     // Purpose: Provide a Kernel Driver to Linux for the Universe I and II
38 astro 1.1 // Universe model number ca91c042
39 jhuggins 1.7 // Docs:
40 wyrick 1.6 // This driver supports:
41     // Universe
42     // Universe II
43     // Universe II B
44 jhuggins 1.7 // Universe II D
45 astro 1.1 //-----------------------------------------------------------------------------
46     #define MODULE
47    
48 jhuggins 1.7 static char Version[] = "vmelinux-1.3-development";
49 astro 1.1
50     #include <linux/config.h>
51     #include <linux/version.h>
52    
53     #ifdef CONFIG_MODVERSIONS
54 jhuggins 1.4 #define MODVERSIONS
55     #include <linux/modversions.h>
56 astro 1.1 #endif
57    
58     #include <linux/module.h>
59     #include <linux/types.h>
60     #include <linux/errno.h>
61     #include <linux/proc_fs.h>
62     #include <linux/pci.h>
63     #include <linux/poll.h>
64     #include <asm/io.h>
65     #include <asm/uaccess.h>
66    
67     #include "ca91c042.h"
68    
69     //----------------------------------------------------------------------------
70     // Prototypes
71     //----------------------------------------------------------------------------
72     static int uni_open(struct inode *, struct file *);
73     static int uni_release(struct inode *, struct file *);
74     static ssize_t uni_read(struct file *,char *, size_t, loff_t *);
75     static ssize_t uni_write(struct file *,const char *, size_t, loff_t *);
76     static unsigned int uni_poll(struct file *, poll_table *);
77     static int uni_ioctl(struct inode *, struct file *, unsigned int, unsigned long);
78     static long long uni_llseek(struct file *,loff_t,int);
79     //static int uni_mmap(struct inode *inode,struct file *file,struct vm_area_struct *vma);
80     //static int uni_select(struct inode *inode,struct file *file,int mode, select_table *table);
81     static int uni_procinfo(char *, char **, off_t, int, int *,void *);
82    
83     //----------------------------------------------------------------------------
84     // Types
85     //----------------------------------------------------------------------------
86     static struct proc_dir_entry *uni_procdir;
87    
88 jhuggins 1.7 static struct file_operations uni_fops =
89 astro 1.1 {
90 jhuggins 1.4 llseek: uni_llseek,
91     read: uni_read,
92     write: uni_write,
93 jhuggins 1.7 poll: uni_poll, // uni_poll
94 jhuggins 1.4 ioctl: uni_ioctl,
95     open: uni_open,
96 jhuggins 1.7 release: uni_release
97 astro 1.1 };
98    
99 jhuggins 1.5 static int aCTL[] = {LSI0_CTL, LSI1_CTL, LSI2_CTL, LSI3_CTL,
100     LSI4_CTL, LSI5_CTL, LSI6_CTL, LSI7_CTL};
101 jhuggins 1.7
102 jhuggins 1.5 static int aBS[] = {LSI0_BS, LSI1_BS, LSI2_BS, LSI3_BS,
103 jhuggins 1.7 LSI4_BS, LSI5_BS, LSI6_BS, LSI7_BS};
104    
105 jhuggins 1.5 static int aBD[] = {LSI0_BD, LSI1_BD, LSI2_BD, LSI3_BD,
106 jhuggins 1.7 LSI4_BD, LSI5_BD, LSI6_BD, LSI7_BD};
107 jhuggins 1.5
108     static int aTO[] = {LSI0_TO, LSI1_TO, LSI2_TO, LSI3_TO,
109 jhuggins 1.7 LSI4_TO, LSI5_TO, LSI6_TO, LSI7_TO};
110 astro 1.1
111     //----------------------------------------------------------------------------
112     // Vars and Defines
113     //----------------------------------------------------------------------------
114 jhuggins 1.5 #define UNI_MAJOR 221
115 astro 1.1 #define MAX_MINOR 8
116     #define CONTROL_MINOR 8
117    
118     #define MODE_UNDEFINED 0
119     #define MODE_PROGRAMMED 1
120     #define MODE_DMA 2
121    
122     #define DMATYPE_SINGLE 1
123     #define DMATYPE_LLIST 2
124    
125 wyrick 1.6 #define UNIVERSEI 0
126     #define UNIVERSEII 1
127     #define UNIVERSEIIB 2
128     #define UNIVERSEUNK 5
129     #define UNIVERSEIIFUNC ((ChipType == UNIVERSEII) || (ChipType == UNIVERSEIIB))
130     static int ChipType = UNIVERSEUNK;
131    
132 astro 1.1 static int OkToWrite[MAX_MINOR + 1]; // Can I write to the Hardware
133    
134     static int opened[MAX_MINOR + 1];
135 jhuggins 1.4 static int mode[MAX_MINOR + 1]; // DMA or Programmed I/O
136 astro 1.1
137     static unsigned long DMA[MAX_MINOR + 1]; // DMA Control Reg
138    
139     static int status;
140     static int DMAType = 0;
141     static int irq = 0;
142     static char *baseaddr = 0;
143     static char *image_ba[MAX_MINOR+1]; // Base PCI Address
144    
145     static unsigned int image_ptr[MAX_MINOR+1];
146     static unsigned int image_va[MAX_MINOR+1];
147    
148     // Hold the VME Irq Handlers
149     static TirqHandler vmeirqs[7] = {NULL,NULL,NULL,NULL,NULL,NULL,NULL};
150     static short vmeirqbit[7] = {IRQ_VIRQ1, IRQ_VIRQ2, IRQ_VIRQ3, IRQ_VIRQ4,
151 jhuggins 1.7 IRQ_VIRQ5, IRQ_VIRQ6, IRQ_VIRQ7};
152 astro 1.1 static int vmevec[7] = {V1_STATID, V2_STATID, V3_STATID, V4_STATID,
153 jhuggins 1.4 V5_STATID, V6_STATID, V7_STATID};
154 astro 1.1
155     // Status Vars
156     static unsigned int reads = 0;
157     static unsigned int writes = 0;
158     static unsigned int ioctls = 0;
159    
160     static TDMAcallback DMACallBackFunc = NULL;
161     static void *debugptr = NULL;
162    
163     // Timers
164     struct timer_list DMA_timer; // This is a timer for returning status
165    
166     //----------------------------------------------------------------------------
167     // uni_procinfo()
168     //----------------------------------------------------------------------------
169     static int uni_procinfo(char *buf, char **start, off_t fpos, int lenght, int *eof, void *data)
170     {
171     char *p;
172     unsigned int temp1,temp2,x;
173    
174     p = buf;
175 wyrick 1.6 p += sprintf(p,"Universe driver %s, ChipType ",Version);
176     switch (ChipType) {
177     case UNIVERSEI : p+= sprintf(p,"Universe I\n"); break;
178     case UNIVERSEII : p+= sprintf(p,"Universe II\n"); break;
179     case UNIVERSEIIB : p+= sprintf(p,"Universe II B/D\n"); break;
180     default: p+= sprintf(p,"Unknown Universe\n"); break;
181 jhuggins 1.7 }
182 astro 1.1
183     p += sprintf(p," baseaddr = %08X\n",(int)baseaddr);
184     p += sprintf(p," Stats reads = %i writes = %i ioctls = %i\n",
185 jhuggins 1.4 reads,writes,ioctls);
186 astro 1.1
187 jhuggins 1.5 for (x=0;x<8;x+=2) {
188 astro 1.1 temp1 = readl(baseaddr+aCTL[x]);
189     temp2 = readl(baseaddr+aCTL[x+1]);
190     p += sprintf(p," LSI%i_CTL = %08X LSI%i_CTL = %08X\n",x,temp1,x+1,temp2);
191     temp1 = readl(baseaddr+aBS[x]);
192     temp2 = readl(baseaddr+aBS[x+1]);
193     p += sprintf(p," LSI%i_BS = %08X LSI%i_BS = %08X\n",x,temp1,x+1,temp2);
194     temp1 = readl(baseaddr+aBD[x]);
195     temp2 = readl(baseaddr+aBD[x+1]);
196     p += sprintf(p," LSI%i_BD = %08X LSI%i_BD = %08X\n",x,temp1,x+1,temp2);
197     temp1 = readl(baseaddr+aTO[x]);
198     temp2 = readl(baseaddr+aTO[x+1]);
199     p += sprintf(p," LSI%i_TO = %08X LSI%i_TO = %08X\n",x,temp1,x+1,temp2);
200 jhuggins 1.7 }
201 astro 1.1
202 jhuggins 1.5 for (x=0;x<8;x+=2)
203 astro 1.1 p += sprintf(p," image_va%i = %08X image_va%i = %08X\n",
204 jhuggins 1.7 x,image_va[x],x+1,image_va[x+1]);
205     p += sprintf(p,"\nDriver Program Status:\n");
206 astro 1.1
207 jhuggins 1.5 for (x=0;x<8;x+=2)
208 astro 1.1 p += sprintf(p," DMACTL %i = %08lX DMACTL %i = %08lX\n",
209 jhuggins 1.7 x,DMA[x],x+1,DMA[x+1]);
210 jhuggins 1.5 for (x=0;x<8;x+=2)
211 astro 1.1 p += sprintf(p," OkToWrite %i = %1X OkToWrite %i = %1X\n",
212 jhuggins 1.7 x,OkToWrite[x],x+1,OkToWrite[x+1]);
213 jhuggins 1.5 for (x=0;x<8;x+=2)
214 astro 1.1 p += sprintf(p," Mode %i = %1X Mode %i = %1X\n",
215 jhuggins 1.7 x,mode[x],x+1,mode[x+1]);
216 astro 1.1
217 jhuggins 1.7 p += sprintf(p,"\n");
218 astro 1.1
219     temp1 = 0;
220     p += sprintf(p, "VMEIrqs Assigned: ");
221 jhuggins 1.4 for (x=0;x<7;x++) {
222     if (vmeirqs[x] != NULL) {
223 astro 1.1 p += sprintf(p, "%i ",x+1);
224     temp1++;
225     }
226     }
227 jhuggins 1.4 if (temp1 == 0)
228 astro 1.1 p += sprintf(p, "none\n");
229     else
230 jhuggins 1.7 p += sprintf(p,"\n");
231 astro 1.1
232     *eof = 1;
233     return p - buf;
234     }
235    
236     //----------------------------------------------------------------------------
237     // register_proc()
238     //----------------------------------------------------------------------------
239     static void register_proc()
240     {
241     uni_procdir = create_proc_entry("ca91c042", S_IFREG | S_IRUGO, 0);
242     uni_procdir->read_proc = uni_procinfo;
243     }
244    
245     //----------------------------------------------------------------------------
246     // unregister_proc()
247     //----------------------------------------------------------------------------
248     static void unregister_proc()
249     {
250     remove_proc_entry("ca91c042",0);
251     }
252    
253     //----------------------------------------------------------------------------
254     //
255     // uni_poll()
256     //
257     //----------------------------------------------------------------------------
258     static unsigned int uni_poll(struct file* file, poll_table* wait)
259     {
260     return 0;
261     }
262    
263     //----------------------------------------------------------------------------
264     //
265     // uni_open()
266     //
267     //----------------------------------------------------------------------------
268     static int uni_open(struct inode *inode,struct file *file)
269     {
270     unsigned int minor = MINOR(inode->i_rdev);
271    
272 jhuggins 1.4 if (minor > MAX_MINOR) {
273 astro 1.1 return(-ENODEV);
274     }
275    
276 jhuggins 1.4 if (minor == CONTROL_MINOR) {
277 astro 1.1 opened[minor]++;
278     return(0);
279     }
280    
281 jhuggins 1.4 if (!opened[minor]) {
282 astro 1.1 opened[minor] = 1;
283     return(0);
284     } else
285     return(-EBUSY);
286     }
287    
288     //----------------------------------------------------------------------------
289     //
290     // uni_release()
291     //
292     //----------------------------------------------------------------------------
293     static int uni_release(struct inode *inode,struct file *file)
294     {
295     unsigned int minor = MINOR(inode->i_rdev);
296    
297     opened[minor]--;
298    
299     return 0;
300     }
301    
302     //----------------------------------------------------------------------------
303     //
304     // uni_lseek()
305     //
306     //----------------------------------------------------------------------------
307     static long long uni_llseek(struct file *file,loff_t offset,int whence)
308     {
309     unsigned int minor = MINOR(file->f_dentry->d_inode->i_rdev);
310     unsigned int toffset,base,paddr;
311    
312 jhuggins 1.4 if (whence == SEEK_SET) {
313     if (minor == CONTROL_MINOR) {
314 astro 1.1 image_ptr[minor] = offset;
315     } else {
316 jhuggins 1.7 toffset = readl(baseaddr+aTO[minor]);
317     base = readl(baseaddr+aBS[minor]);
318 astro 1.1 paddr = offset-toffset;
319     image_ptr[minor] = (int)(image_ba[minor]+(paddr-base));
320 jhuggins 1.7 }
321 astro 1.1 return 0;
322 jhuggins 1.4 } else if (whence == SEEK_CUR) {
323 astro 1.1 image_ptr[minor] += offset;
324     return 0;
325     } else
326 jhuggins 1.7 return -1;
327 astro 1.1 }
328    
329     //----------------------------------------------------------------------------
330     //
331     // uni_read()
332     //
333     //----------------------------------------------------------------------------
334     static ssize_t uni_read(struct file *file, char *buf, size_t count, loff_t *ppos)
335     {
336     int x = 0;
337     unsigned int v,numt,remain,tmp;
338     char *temp = buf;
339 jhuggins 1.7 unsigned int minor = MINOR(file->f_dentry->d_inode->i_rdev);
340     int p;
341 astro 1.1
342     unsigned char vc;
343     unsigned short vs;
344     unsigned int vl;
345    
346     char *DMA_Buffer;
347 jhuggins 1.7 unsigned int DMA_Buffer_Size = 0,
348 jhuggins 1.4 order = 0,
349     a_size = 0,
350     dma_align = 0,
351 jhuggins 1.7 timeout = 0;
352 jhuggins 1.4 int val = 0,
353     pci = 0,
354     vme = 0,
355     okcount = 0;
356 astro 1.1
357 jhuggins 1.4 if (minor == CONTROL_MINOR) {
358 astro 1.1 p = (int)image_ptr[minor];
359 jhuggins 1.7 v = readl(baseaddr+p);
360 astro 1.1 __copy_to_user(temp,&v,4);
361     } else {
362 jhuggins 1.7 reads++;
363 jhuggins 1.4 if (OkToWrite[minor]) {
364     if (mode[minor] == MODE_PROGRAMMED) {
365 astro 1.1 numt = count;
366     remain = count;
367    
368     // Calc the number of longs we need
369     numt = count / 4;
370     remain = count % 4;
371 jhuggins 1.4 for (x=0;x<numt;x++) {
372 jhuggins 1.7 vl = readl(image_ptr[minor]);
373 astro 1.1
374     // Lets Check for a Bus Error
375     tmp = readl(baseaddr+PCI_CSR);
376 jhuggins 1.4 if (tmp & 0x08000000) {
377 astro 1.1 writel(tmp,baseaddr+PCI_CSR);
378     return(okcount);
379     } else
380     okcount += 4;
381    
382     __copy_to_user(temp,&vl,4);
383     image_ptr[minor]+=4;
384     temp+=4;
385 jhuggins 1.7 }
386 astro 1.1
387     // Calc the number of Words we need
388     numt = remain / 2;
389     remain = remain % 2;
390 jhuggins 1.4 for (x=0;x<numt;x++) {
391 jhuggins 1.7 vs = readw(image_ptr[minor]);
392 astro 1.1
393     // Lets Check for a Bus Error
394     tmp = readl(baseaddr+PCI_CSR);
395 jhuggins 1.4 if (tmp & 0x08000000) {
396 astro 1.1 writel(tmp,baseaddr+PCI_CSR);
397     return(okcount);
398     } else
399     okcount += 2;
400    
401     __copy_to_user(temp,&vs,2);
402     image_ptr[minor]+=2;
403     temp+=2;
404 jhuggins 1.7 }
405 astro 1.1
406 jhuggins 1.4 for (x=0;x<remain;x++) {
407 jhuggins 1.7 vc = readb(image_ptr[minor]);
408 astro 1.1
409     // Lets Check for a Bus Error
410     tmp = readl(baseaddr+PCI_CSR);
411 jhuggins 1.4 if (tmp & 0x08000000) {
412 astro 1.1 writel(tmp,baseaddr+PCI_CSR);
413     return(okcount);
414     } else
415     okcount++;
416    
417     __copy_to_user(temp,&vc,1);
418     image_ptr[minor]+=1;
419     temp+=1;
420 jhuggins 1.7 }
421 astro 1.1
422 jhuggins 1.4 } else if (mode[minor] == MODE_DMA) {
423 astro 1.1 // ------------------------------------------------------------------
424     //
425 jhuggins 1.7 // ------------------------------------------------------------------
426 astro 1.1 // Wait for DMA to finish, This needs to be changed
427     val = readl(baseaddr+DGCS);
428 jhuggins 1.4 while ((val & 0x00008000) && (timeout++ < 1000000))
429 astro 1.1 val = readl(baseaddr+DGCS);
430    
431 jhuggins 1.7 // VME Address
432     vme = image_va[minor] + (image_ptr[minor] - (unsigned int)image_ba[minor]);
433     dma_align = vme % 8;
434 astro 1.1
435     // Setup DMA Buffer to read data into
436 jhuggins 1.7 DMA_Buffer_Size = count + ((int)image_ptr % 8) + dma_align;
437 astro 1.1 a_size = PAGE_SIZE;
438 jhuggins 1.4 while (a_size < DMA_Buffer_Size) {
439 astro 1.1 order++;
440     a_size <<= 1;
441     }
442 jhuggins 1.7 DMA_Buffer = (char *)__get_dma_pages(GFP_KERNEL,order);
443 astro 1.1
444     // PCI Address
445     pci = virt_to_bus(DMA_Buffer) + dma_align;
446    
447     // Setup DMA regs
448     writel(DMA[minor],baseaddr+DCTL); // Setup Control Reg
449 jhuggins 1.7 writel(count,baseaddr+DTBC); // Count
450 jhuggins 1.4 writel(pci,baseaddr+DLA); // PCI Address
451     writel(vme,baseaddr+DVA); // VME Address
452 astro 1.1
453     // Start DMA
454     writel(0x80006F00,baseaddr+DGCS); // GO
455    
456     // Wait for DMA to finish, This needs to be changed
457     val = readl(baseaddr+DGCS);
458 jhuggins 1.4 while ((val & 0x00008000) && (timeout++ < 100000))
459 astro 1.1 val = readl(baseaddr+DGCS);
460    
461 jhuggins 1.4 if (timeout == 100000)
462 astro 1.1 printk("<<ca91c042 DMA Timed out>>\n");
463    
464 jhuggins 1.4 if (! (val & 0x00000800)) { // An Error Happened
465 jhuggins 1.7 count -= readl(baseaddr+DTBC);
466 astro 1.1 }
467    
468     image_ptr[minor] += count;
469    
470     // Copy pages to User Memory
471     __copy_to_user(temp,DMA_Buffer+dma_align,count);
472    
473     free_pages((unsigned long)DMA_Buffer,order);
474     } // end of MODE_DMA
475     } // end of OKtoWrite
476 jhuggins 1.7 }
477 astro 1.1 *ppos += count;
478     return(count);
479     }
480    
481     //----------------------------------------------------------------------------
482     //
483     // uni_write()
484     //
485     //----------------------------------------------------------------------------
486     static ssize_t uni_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
487     {
488     int x,p;
489     unsigned int numt,remain,tmp;
490     char *temp = (char *)buf;
491     unsigned int minor = MINOR(file->f_dentry->d_inode->i_rdev);
492    
493     unsigned char vc;
494     unsigned short vs;
495     unsigned int vl;
496    
497     char *DMA_Buffer;
498 jhuggins 1.7 unsigned int DMA_Buffer_Size = 0,
499 jhuggins 1.4 order = 0,
500     a_size = 0,
501     dma_align = 0,
502 jhuggins 1.7 timeout = 0;
503 astro 1.1 int val,
504 jhuggins 1.4 pci = 0,
505     vme = 0,
506     okcount = 0;
507 astro 1.1
508     writes++;
509 jhuggins 1.4 if (minor == CONTROL_MINOR) {
510 astro 1.1 __copy_from_user(&vl,temp,4);
511     p = (int)image_ptr[minor];
512     writel(vl,baseaddr+p);
513     } else {
514 jhuggins 1.4 if (OkToWrite[minor]) {
515     if (mode[minor] == MODE_PROGRAMMED) {
516 astro 1.1 // Calc the number of longs we need
517     numt = count;
518     remain = count;
519    
520     numt = count / 4;
521     remain = count % 4;
522 jhuggins 1.4 for (x=0;x<numt;x++) {
523 astro 1.1 __copy_from_user(&vl,temp,4);
524     writel(vl,image_ptr[minor]);
525    
526     // Lets Check for a Bus Error
527     tmp = readl(baseaddr+PCI_CSR);
528 jhuggins 1.4 if (tmp & 0x08000000) {
529 astro 1.1 writel(tmp,baseaddr+PCI_CSR);
530     return(okcount);
531     } else
532     okcount += 4;
533    
534     image_ptr[minor]+=4;
535     temp+=4;
536 jhuggins 1.7 }
537 astro 1.1
538     // Calc the number of Words we need
539     numt = remain / 2;
540     remain = remain % 2;
541    
542 jhuggins 1.4 for (x=0;x<numt;x++) {
543 astro 1.1 __copy_from_user(&vs,temp,2);
544     writew(vs,image_ptr[minor]);
545    
546     // Lets Check for a Bus Error
547     tmp = readl(baseaddr+PCI_CSR);
548 jhuggins 1.4 if (tmp & 0x08000000) {
549 astro 1.1 writel(tmp,baseaddr+PCI_CSR);
550     return(okcount);
551     } else
552     okcount += 2;
553    
554     image_ptr[minor]+=2;
555     temp+=2;
556 jhuggins 1.7 }
557 astro 1.1
558 jhuggins 1.4 for (x=0;x<remain;x++) {
559 astro 1.1 __copy_from_user(&vc,temp,1);
560     writeb(vc,image_ptr[minor]);
561    
562     // Lets Check for a Bus Error
563     tmp = readl(baseaddr+PCI_CSR);
564 jhuggins 1.4 if (tmp & 0x08000000) {
565 astro 1.1 writel(tmp,baseaddr+PCI_CSR);
566     return(okcount);
567     } else
568     okcount += 2;
569    
570     image_ptr[minor]+=1;
571     temp+=1;
572 jhuggins 1.7 }
573 astro 1.1
574     // Lets Check for a Bus Error
575     tmp = readl(baseaddr+PCI_CSR);
576 jhuggins 1.4 if (tmp & 0x08000000) { // S_TA is Set
577 astro 1.1 writel(0x08000000,baseaddr+PCI_CSR);
578     count = 0;
579     }
580    
581 jhuggins 1.4 } else if (mode[minor] == MODE_DMA) {
582 astro 1.1 // ------------------------------------------------------------------
583     //
584 jhuggins 1.7 // ------------------------------------------------------------------
585 astro 1.1 // Wait for DMA to finish, This needs to be changed
586     val = readl(baseaddr+DGCS);
587 jhuggins 1.4 while ((val & 0x00008000) && (timeout++ < 100000))
588 astro 1.1 val = readl(baseaddr+DGCS);
589    
590     // Setup DMA Buffer to write data into
591 jhuggins 1.7 // VME Address
592     vme = image_va[minor] + (image_ptr[minor] - (unsigned int)image_ba[minor]);
593     dma_align = vme % 8;
594 astro 1.1
595 jhuggins 1.7 DMA_Buffer_Size = count + ((int)image_ptr % 8) + dma_align;
596 astro 1.1 a_size = PAGE_SIZE;
597 jhuggins 1.4 while (a_size < DMA_Buffer_Size) {
598 astro 1.1 order++;
599     a_size <<= 1;
600     }
601 jhuggins 1.7 DMA_Buffer = (char *)__get_dma_pages(GFP_KERNEL,order);
602 astro 1.1
603     // Copy User Memory into buffer
604     __copy_from_user(DMA_Buffer + dma_align,temp,count);
605    
606     // PCI Address
607     pci = virt_to_bus(DMA_Buffer) + dma_align;
608    
609     // Setup DMA regs
610 jhuggins 1.4 writel(DMA[minor]|0x80000000,baseaddr+DCTL); // Setup Control Reg
611 jhuggins 1.7 writel(count,baseaddr+DTBC); // Count
612 jhuggins 1.4 writel(pci,baseaddr+DLA); // PCI Address
613     writel(vme,baseaddr+DVA); // VME Address
614 astro 1.1
615     // Start DMA
616 jhuggins 1.4 writel(0x80006F00,baseaddr+DGCS); // GO
617 astro 1.1
618     // Wait for DMA to finish, This needs to be changed
619     val = readl(baseaddr+DGCS);
620 jhuggins 1.4 while ((val & 0x00008000) && (timeout++ < 100000))
621 astro 1.1 val = readl(baseaddr+DGCS);
622    
623 jhuggins 1.4 if (timeout == 100000)
624 astro 1.1 printk("<<ca91c042 DMA Timed out>>\n");
625    
626 jhuggins 1.4 if (! (val & 0x00000800)) { // An Error Happened
627 astro 1.1 // The Universe Seems to return an invalid value in DTBC on
628     // Bus Errors during DMA, so invalidate the count
629     count = 0;
630     }
631     image_ptr[minor] += count;
632    
633     free_pages((unsigned long)DMA_Buffer,order);
634     } // end of MODE_DMA
635     } //OKtoWrite
636 jhuggins 1.7 }
637 astro 1.1 *ppos += count;
638     return(count);
639     }
640    
641     //----------------------------------------------------------------------------
642     // uni_ioctl()
643     //----------------------------------------------------------------------------
644     static int uni_ioctl(struct inode *inode,struct file *file,unsigned int cmd, unsigned long arg)
645     {
646     unsigned int minor = MINOR(inode->i_rdev);
647     unsigned int sizetomap = 0, to = 0, bs = 0;
648    
649     ioctls++;
650 jhuggins 1.4 switch (cmd) {
651     case IOCTL_SET_CTL:
652     writel(arg,baseaddr+aCTL[minor]);
653    
654     // Lets compute and save the DMA CTL Register
655     DMA[minor] = arg & 0x00FFFF00;
656     break;
657    
658     case IOCTL_SET_MODE:
659     mode[minor] = arg;
660 jhuggins 1.7 break;
661 jhuggins 1.4
662     // Lets Map the VME Bus to the PCI Bus
663     //
664     // << NOTE >> BD Must already be set before you call this!!!!
665     //
666     //
667     case IOCTL_SET_BS:
668     writel(arg,baseaddr+aBS[minor]);
669     if (image_ba[minor])
670     iounmap(image_ba[minor]);
671    
672 jhuggins 1.7 // This uses the BD Register to Find the size of the Image Mapping
673 jhuggins 1.4 sizetomap = readl(baseaddr+aBD[minor]);
674     sizetomap -= arg;
675    
676     image_ba[minor] = (char *)ioremap(arg,sizetomap);
677     if (!image_ba[minor]) {
678 jhuggins 1.7 OkToWrite[minor] = 0;
679 jhuggins 1.4 return -1;
680     }
681     image_ptr[minor] = (int)image_ba[minor];
682     OkToWrite[minor] = 1;
683 astro 1.1
684 jhuggins 1.4 // Calculate the VME Address
685     bs = readl(baseaddr+aBS[minor]);
686     to = readl(baseaddr+aTO[minor]);
687     image_va[minor] = bs + to;
688     break;
689    
690     case IOCTL_SET_BD:
691     writel(arg,baseaddr+aBD[minor]);
692 jhuggins 1.7 break;
693 jhuggins 1.4 case IOCTL_SET_TO:
694     writel(arg,baseaddr+aTO[minor]);
695    
696     // Calculate the VME Address
697     bs = readl(baseaddr+aBS[minor]);
698     to = readl(baseaddr+aTO[minor]);
699     image_va[minor] = bs + to;
700 jhuggins 1.7 break;
701 jhuggins 1.4 default:
702     if (cmd < 0x1000) { // This is a Register value so write to it.
703     writel(arg,baseaddr+cmd);
704     }
705 jhuggins 1.7 break;
706 astro 1.1 }
707     return(0);
708     }
709    
710     //-----------------------------------------------------------------------------
711     // Function : PrintCmdPacketList
712     // Inputs : TDMA_Cmd_Packet* cpl (PCI Phys Address)
713     // Outputs : void
714 jhuggins 1.7 // Description:
715     // Remarks :
716     // History :
717 astro 1.1 //-----------------------------------------------------------------------------
718     void PrintCmdPacketList(TDMA_Cmd_Packet* cpl)
719     {
720     TDMA_Cmd_Packet *p = bus_to_virt((int)cpl);
721     char buff[100];
722     int x = 0;
723     int done = 0;
724    
725 jhuggins 1.4 while (!done && (x < 10)) {
726 astro 1.1 x++;
727     sprintf(buff,"<ca91c042> (%i) dctl=%08X, dtbc=%08X\n",x,p->dctl,p->dtbc);
728     printk(buff);
729     sprintf(buff,"<ca91c042> dlv=%08X, dva=%08X\n",p->dlv,p->dva);
730     printk(buff);
731     sprintf(buff,"<ca91c042> dcpp=%08X\n",p->dcpp);
732     printk(buff);
733     done = (p->dcpp & 0x00000001);
734     p = bus_to_virt((int)(TDMA_Cmd_Packet*)(p->dcpp & 0xFFFFFFF8)); // Next in Line Please
735     }
736     }
737    
738     //-----------------------------------------------------------------------------
739     // Function : void DMA_status
740     // Inputs : unsigned long __data
741     // Outputs : static
742 jhuggins 1.7 // Description:
743     // Remarks :
744     // History :
745 astro 1.1 //-----------------------------------------------------------------------------
746     static void DMA_status(unsigned long __data)
747     {
748     printk("<<ca91c042>> DMA Timed out\n");
749    
750 jhuggins 1.4 if (DMACallBackFunc)
751 astro 1.1 DMACallBackFunc(1);
752     DMACallBackFunc = NULL;
753     }
754    
755     //-----------------------------------------------------------------------------
756     // Function : DMA_irq_handler
757     // Inputs : void
758     // Outputs : void
759 jhuggins 1.7 // Description:
760     // Remarks :
761     // History :
762 astro 1.1 //-----------------------------------------------------------------------------
763     void DMA_irq_handler(void)
764     {
765     int val;
766     int cbv=0;
767     char buf[100];
768     TDMA_Cmd_Packet *cpl;
769    
770     del_timer(&DMA_timer); // Cancel DMA Time Out
771    
772     val = readl(baseaddr+DGCS);
773    
774 jhuggins 1.4 if (!(val & 0x00000800)) {
775 jhuggins 1.7 sprintf(buf,"<<ca91c042>> DMA Error in DMA_irq_handler DGCS=%08X\n",val);
776 astro 1.1 printk(buf);
777     val = readl(baseaddr+DCPP);
778 jhuggins 1.7 sprintf(buf,"<<ca91c042>> DCPP=%08X\n",val);
779 astro 1.1 printk(buf);
780     val = readl(baseaddr+DCTL);
781 jhuggins 1.7 sprintf(buf,"<<ca91c042>> DCTL=%08X\n",val);
782 astro 1.1 printk(buf);
783     val = readl(baseaddr+DTBC);
784 jhuggins 1.7 sprintf(buf,"<<ca91c042>> DTBC=%08X\n",val);
785 astro 1.1 printk(buf);
786     val = readl(baseaddr+DLA);
787 jhuggins 1.7 sprintf(buf,"<<ca91c042>> DLA=%08X\n",val);
788 astro 1.1 printk(buf);
789     val = readl(baseaddr+DVA);
790 jhuggins 1.7 sprintf(buf,"<<ca91c042>> DVA=%08X\n",val);
791 astro 1.1 printk(buf);
792    
793 jhuggins 1.4 if (DMAType == DMATYPE_LLIST) {
794 astro 1.1 printk("<<ca91c042>> CmdPacketList sent to DMARead\n");
795     PrintCmdPacketList(debugptr);
796    
797     printk("<<ca91c042>> CmdPacketList as seen by DCPP\n");
798     cpl = (TDMA_Cmd_Packet*)readl(baseaddr+DCPP); // Command Packet Pointer
799     cpl = (TDMA_Cmd_Packet*)((int)cpl & ~0x03);
800    
801     PrintCmdPacketList(cpl);
802     }
803     cbv = 1; // Call Back value is set to 1 to show error condition
804     }
805    
806 jhuggins 1.4 if (DMACallBackFunc)
807 astro 1.1 DMACallBackFunc(cbv);
808    
809     // We are done with the Call Back so clear it
810     DMACallBackFunc = NULL;
811     }
812    
813     //-----------------------------------------------------------------------------
814     // Function : LERR_irq_handler
815     // Inputs : void
816     // Outputs : void
817 jhuggins 1.7 // Description:
818     // Remarks :
819     // History :
820 astro 1.1 //-----------------------------------------------------------------------------
821     void LERR_irq_handler(void)
822     {
823     int val;
824     char buf[100];
825     TDMA_Cmd_Packet *cpl;
826    
827     del_timer(&DMA_timer); // Cancel DMA Time Out
828    
829     val = readl(baseaddr+DGCS);
830    
831 jhuggins 1.4 if (!(val & 0x00000800)) {
832 jhuggins 1.7 sprintf(buf,"<<ca91c042>> LERR_irq_handler DMA Read Error DGCS=%08X\n",val);
833 astro 1.1 printk(buf);
834    
835 jhuggins 1.4 if (DMAType == DMATYPE_LLIST) {
836 astro 1.1 cpl = (TDMA_Cmd_Packet*)readl(baseaddr+DCPP); // Command Packet Pointer
837     cpl = (TDMA_Cmd_Packet*)((int)cpl & ~0x03);
838     PrintCmdPacketList(cpl);
839    
840     sprintf(buf,"<<ca91c042>> DMAReadCallBack Request of cmdpack=0x%08X\n",(int)cpl);
841     printk(buf);
842     }
843     }
844    
845 jhuggins 1.4 if (DMACallBackFunc)
846 astro 1.1 DMACallBackFunc(1);
847     DMACallBackFunc = NULL;
848     }
849    
850     //-----------------------------------------------------------------------------
851     // Function : VERR_irq_handler
852     // Inputs : void
853     // Outputs : void
854 jhuggins 1.7 // Description:
855     // Remarks :
856     // History :
857 astro 1.1 //-----------------------------------------------------------------------------
858     void VERR_irq_handler(void)
859     {
860     int val;
861     char buf[100];
862     TDMA_Cmd_Packet *cpl;
863    
864     del_timer(&DMA_timer); // Cancel DMA Time Out
865    
866     val = readl(baseaddr+DGCS);
867    
868 jhuggins 1.4 if (!(val & 0x00000800)) {
869 jhuggins 1.7 sprintf(buf,"<<ca91c042>> VERR_irq_handler DMA Read Error DGCS=%08X\n",val);
870 astro 1.1 printk(buf);
871    
872 jhuggins 1.4 if (DMAType == DMATYPE_LLIST) {
873 astro 1.1 cpl = (TDMA_Cmd_Packet*)readl(baseaddr+DCPP); // Command Packet Pointer
874     cpl = (TDMA_Cmd_Packet*)((int)cpl & ~0x03);
875    
876     PrintCmdPacketList(cpl);
877    
878     sprintf(buf,"<<ca91c042>> DMAReadCallBack Request of cmdpack=0x%08X\n",(int)cpl);
879     printk(buf);
880     }
881     }
882    
883 jhuggins 1.4 if (DMACallBackFunc)
884 astro 1.1 DMACallBackFunc(1);
885     DMACallBackFunc = NULL;
886     }
887    
888     //-----------------------------------------------------------------------------
889     // Function : irq_handler
890     // Inputs : int irq, void *dev_id, struct pt_regs *regs
891     // Outputs : void
892 jhuggins 1.7 // Description:
893     // Remarks :
894     // History :
895 astro 1.1 //-----------------------------------------------------------------------------
896     static void irq_handler(int irq, void *dev_id, struct pt_regs *regs)
897     {
898     long stat, enable, i, vector;
899    
900     enable = readl(baseaddr+LINT_EN);
901     stat = readl(baseaddr+LINT_STAT);
902    
903 jhuggins 1.4 if (stat & 0x0100)
904 astro 1.1 DMA_irq_handler();
905 jhuggins 1.4 if (stat & 0x0200)
906 astro 1.1 LERR_irq_handler();
907 jhuggins 1.4 if (stat & 0x0400)
908 astro 1.1 VERR_irq_handler();
909    
910 jhuggins 1.4 for (i=0;i<7;i++) {
911 astro 1.1 vector = readl(baseaddr+vmevec[i]);
912 jhuggins 1.4 if (stat & vmeirqbit[i] & enable) {
913     if (vmeirqs[i] != NULL) {
914 astro 1.1 vmeirqs[i](i+1, vector, dev_id, regs);
915     }
916     }
917     }
918    
919     writel(stat, baseaddr+LINT_STAT); // Clear all pending ints
920     }
921    
922     //-----------------------------------------------------------------------------
923     // Function : cleanup_module
924     // Inputs : void
925     // Outputs : void
926 jhuggins 1.7 // Description:
927     // Remarks :
928     // History :
929 astro 1.1 //-----------------------------------------------------------------------------
930     void cleanup_module(void)
931 jhuggins 1.7 {
932 astro 1.1 int x;
933     int pcivector;
934    
935     writel(0,baseaddr+LINT_EN); // Turn off Ints
936 jhuggins 1.7 pcivector = readl(baseaddr+PCI_MISC1) & 0x000000FF;
937 astro 1.1 free_irq(pcivector,NULL); // Free Vector
938    
939 jhuggins 1.4 for (x=1;x<MAX_MINOR+1;x++) {
940     if (image_ba[x])
941 astro 1.1 iounmap(image_ba[x]);
942 jhuggins 1.7 }
943 astro 1.1 iounmap(baseaddr);
944     unregister_proc();
945     unregister_chrdev(UNI_MAJOR, "uni");
946     }
947    
948     //----------------------------------------------------------------------------
949     // init_module()
950     //----------------------------------------------------------------------------
951     int init_module(void)
952     {
953     int x, result;
954     unsigned int temp, ba;
955     char vstr[80];
956    
957     struct pci_dev *uni_pci_dev = NULL;
958    
959     sprintf(vstr,"Tundra Universe PCI-VME Bridge Driver %s\n",Version);
960     printk(vstr);
961 wyrick 1.6 printk(" Copyright 1997-2002, Michael J. Wyrick\n");
962 astro 1.1
963 jhuggins 1.4 if ((uni_pci_dev = pci_find_device(PCI_VENDOR_ID_TUNDRA,
964 jhuggins 1.7 PCI_DEVICE_ID_TUNDRA_CA91C042,
965 jhuggins 1.4 uni_pci_dev))) {
966 astro 1.1 printk(" Universe device found.");
967    
968     // Lets turn Latency off
969     pci_write_config_dword(uni_pci_dev, PCI_MISC0, 0);
970    
971 jhuggins 1.7 // Display PCI Registers
972 astro 1.1 pci_read_config_dword(uni_pci_dev, PCI_CSR, &status);
973     printk(" Vendor = %04X Device = %04X Status = %08X\n",
974     uni_pci_dev->vendor,uni_pci_dev->device,status);
975    
976     // Setup Universe Config Space
977     // This is a 4k wide memory area that need to be mapped into the kernel
978     // virtual memory space so we can access it.
979     pci_write_config_dword(uni_pci_dev, PCI_BS, CONFIG_REG_SPACE);
980 jhuggins 1.7 pci_read_config_dword(uni_pci_dev, PCI_BS, &ba);
981 astro 1.1 baseaddr = (char *)ioremap(ba,4096);
982 jhuggins 1.4 if (!baseaddr) {
983 astro 1.1 printk(" vremap failed to map Universe to Kernel Space.\r");
984     return 1;
985     }
986    
987     // Check to see if the Mapping Worked out
988     temp = readl(baseaddr);
989 jhuggins 1.7 printk(" Read via mapping, PCI_ID = %08X\n",temp);
990 jhuggins 1.4 if (temp != 0x000010E3) {
991 astro 1.1 printk(" Universe Chip Failed to Return PCI_ID in Memory Map.\n");
992     return 1;
993     }
994 jhuggins 1.7
995 wyrick 1.6 printk(" Class = %08X\n",readl(baseaddr+PCI_CLASS));
996     printk(" Misc0 = %08X\n",readl(baseaddr+PCI_MISC0));
997 jhuggins 1.7
998 wyrick 1.6 // Determine What Chip We have
999     temp = readl(baseaddr + PCI_CLASS);
1000     ChipType = temp & 0x000000FF;
1001     switch (ChipType) {
1002     case UNIVERSEI : printk(" Found Universe I\n"); break;
1003 jhuggins 1.7 case UNIVERSEII : printk(" Found Universe II\n"); break;
1004 wyrick 1.6 case UNIVERSEIIB : printk(" Found Universe IIB/D\n"); break;
1005     default : printk(" Unknown Universe\n"); break;
1006     }
1007 jhuggins 1.7
1008 astro 1.1 // OK, Every this is ok so lets turn off the windows
1009 jhuggins 1.7 writel(0x00800000,baseaddr+LSI0_CTL);
1010     writel(0x00800000,baseaddr+LSI1_CTL);
1011     writel(0x00800000,baseaddr+LSI2_CTL);
1012     writel(0x00800000,baseaddr+LSI3_CTL);
1013 astro 1.1
1014 jhuggins 1.4 // Write to Misc Register
1015     // Set VME Bus Time-out
1016     // Arbitration Mode
1017     // DTACK Enable
1018 jhuggins 1.7 writel(0x15060000,baseaddr+MISC_CTL);
1019 wyrick 1.6
1020     if (UNIVERSEIIFUNC) {
1021     printk(" U2SPEC = %08X\n", readl(baseaddr+U2SPEC));
1022     }
1023 jhuggins 1.4
1024 astro 1.1 // Lets turn off interrupts
1025     writel(0x00000000,baseaddr+LINT_EN); // Disable interrupts in the Universe first
1026     writel(0x0000FFFF,baseaddr+LINT_STAT); // Clear Any Pending Interrupts
1027    
1028     pci_read_config_dword(uni_pci_dev, PCI_INTERRUPT_LINE, &irq);
1029     irq &= 0x000000FF; // Only a byte in size
1030     result = request_irq(irq, irq_handler, SA_INTERRUPT, "VMEBus (ca91c042)", NULL);
1031 jhuggins 1.4 if (result) {
1032 astro 1.1 printk(" ca91c042: can't get assigned pci irq vector %02X\n", irq);
1033     } else {
1034     writel(0x0000, baseaddr+LINT_MAP0); // Map all ints to 0
1035     writel(0x0000, baseaddr+LINT_MAP1); // Map all ints to 0
1036     }
1037    
1038     } else {
1039     printk(" Universe device not found on PCI Bus.\n");
1040     return 1;
1041     }
1042    
1043 jhuggins 1.4 if (register_chrdev(UNI_MAJOR, "uni", &uni_fops)) {
1044 astro 1.1 printk(" Error getting Major Number for Drivers\n");
1045     iounmap(baseaddr);
1046     return(1);
1047     } else {
1048 jhuggins 1.7 printk(" Tundra Loaded.\n");
1049 astro 1.1 }
1050    
1051     register_proc();
1052    
1053 jhuggins 1.4 for (x=0;x<MAX_MINOR+1;x++) {
1054 astro 1.1 image_ba[x] = 0; // Not defined
1055     image_ptr[x] = 0; // Not defined
1056     opened[x] = 0; // Closed
1057     OkToWrite[x] = 0; // Not OK
1058     mode[x] = MODE_UNDEFINED; // Undefined
1059 jhuggins 1.7 }
1060 astro 1.1
1061     // Setup the DMA Timer
1062     init_timer(&DMA_timer);
1063     DMA_timer.function = DMA_status;
1064    
1065     // Enable DMA Interrupts
1066     writel(0x0700, baseaddr+LINT_EN);
1067    
1068     return 0;
1069     }
1070    
1071     //-----------------------------------------------------------------------------
1072     //
1073     // Public Interface
1074     //
1075     //-----------------------------------------------------------------------------
1076     //-----------------------------------------------------------------------------
1077     // Function : Universe_BaseAddr
1078     // Inputs : void
1079     // Outputs : char*
1080     // Description: Returns the Base Address of the Universe
1081     // Remarks : Used for direct access to the Universe for unsupported functions
1082 jhuggins 1.7 // History :
1083 astro 1.1 //-----------------------------------------------------------------------------
1084 jhuggins 1.7 char* Universe_BaseAddr(void)
1085 astro 1.1 {
1086     return baseaddr;
1087     }
1088    
1089     //-----------------------------------------------------------------------------
1090     // Function : Universe_IRQ
1091     // Inputs : void
1092     // Outputs : int
1093     // Description: Returns the PCI IRQ that the Universe is on
1094     // Remarks : Used mostly for Status and Debugging
1095 jhuggins 1.7 // History :
1096 astro 1.1 //-----------------------------------------------------------------------------
1097 jhuggins 1.7 int Universe_IRQ(void)
1098 astro 1.1 {
1099     return irq;
1100     }
1101    
1102     //-----------------------------------------------------------------------------
1103     // Function : enable_vmeirq
1104     // Inputs : int irq
1105     // Outputs : int
1106     // Description: Enable a VME IRQ
1107 jhuggins 1.7 // Remarks :
1108     // History :
1109 astro 1.1 //-----------------------------------------------------------------------------
1110     void enable_vmeirq(unsigned int irq)
1111     {
1112     int enable;
1113    
1114     enable = readl(baseaddr+LINT_EN);
1115     enable |= vmeirqbit[irq-1];
1116     writel(enable, baseaddr+LINT_EN);
1117     }
1118    
1119     //-----------------------------------------------------------------------------
1120     // Function : disable_vmeirq
1121     // Inputs : unsigned int irq
1122     // Outputs : void
1123     // Description: Disable a VME IRQ
1124 jhuggins 1.7 // Remarks :
1125     // History :
1126 astro 1.1 //-----------------------------------------------------------------------------
1127     void disable_vmeirq(unsigned int irq)
1128     {
1129     int enable;
1130    
1131     enable = readl(baseaddr+LINT_EN);
1132     enable &= ~vmeirqbit[irq-1];
1133     writel(enable, baseaddr+LINT_EN);
1134     }
1135    
1136     //-----------------------------------------------------------------------------
1137     // Function : request_vmeirq
1138     // Inputs : unsigned int irq, TirqHandler handler
1139     // Outputs : int, 0 if successful
1140     // Description: assign a handler to a vme interrupt
1141     // Remarks : uses a simple check to see if the interrupt is free, then
1142     // assigns a handler for the Interrupt
1143 jhuggins 1.7 // History :
1144 astro 1.1 //-----------------------------------------------------------------------------
1145     int request_vmeirq(unsigned int irq, TirqHandler handler)
1146     {
1147 jhuggins 1.4 if ((irq >= 1) && (irq <= 7)) {
1148     if (vmeirqs[irq-1] == NULL) {
1149 astro 1.1 vmeirqs[irq-1] = handler;
1150     return 0;
1151     }
1152     }
1153     return -1; // IRQ is already assigned or invalid
1154     }
1155    
1156     //-----------------------------------------------------------------------------
1157     // Function : free_vmeirq
1158     // Inputs : unsigned int irq
1159     // Outputs : void
1160     // Description: release the vmeirq
1161     // Remarks : This does not check that a module is freeing an interrupt it
1162     // owns. It is up to the programmer to make sure he knows what
1163     // what he is doing
1164 jhuggins 1.7 // History :
1165 astro 1.1 //-----------------------------------------------------------------------------
1166     void free_vmeirq(unsigned int irq)
1167     {
1168 jhuggins 1.4 if ((irq >= 1) && (irq <= 7))
1169 astro 1.1 vmeirqs[irq-1] = NULL;
1170     }
1171    
1172     //-----------------------------------------------------------------------------
1173     // Function : mapvme
1174     // Inputs : unsigned int pci - PCI Address of Image Map (See howto)
1175     // unsigned int vme - VME Address of Image (See howto)
1176     // unsigned int size - Size of Image
1177     // int image - Image Number to Use (See howto)
1178     // int ctl - VME Address Space (See howto)
1179     // Outputs : char*
1180 jhuggins 1.7 // Description:
1181     // Remarks :
1182     // History :
1183 astro 1.1 //-----------------------------------------------------------------------------
1184 jhuggins 1.7 char* mapvme(unsigned int pci,unsigned int vme, unsigned int size,
1185 astro 1.1 int image, int ctl)
1186     {
1187     char *ptr;
1188     unsigned int to;
1189    
1190 jhuggins 1.4 if ((image >=0) && (image <=3)) {
1191     if ((pci >= 0xB0000000) && (pci <= 0xE0000000)) {
1192 astro 1.1 to = vme-pci;
1193     // Setup the Mapping in the Universe
1194     writel(pci, baseaddr + aBS[image]);
1195     writel(pci + size, baseaddr + aBD[image]);
1196     writel(to, baseaddr + aTO[image]);
1197     writel(ctl | 0x80000000, baseaddr + aCTL[image]);
1198    
1199     // Get the Virtual address of the PCI Address map
1200     ptr = (char *)ioremap(pci,size);
1201 jhuggins 1.4 if (ptr == NULL) {
1202 astro 1.1 printk("<ca91c042> ioremap failed in mapvme\n");
1203     return NULL;
1204     } else {
1205     return ptr; // Everything went ok, return the address pointer
1206     }
1207     }
1208     }
1209     return NULL;
1210     }
1211    
1212     //-----------------------------------------------------------------------------
1213     // Function : unmapvme
1214     // Inputs : char *ptr, int image
1215     // Outputs : void
1216 jhuggins 1.7 // Description:
1217     // Remarks :
1218     // History :
1219 astro 1.1 //-----------------------------------------------------------------------------
1220     void unmapvme(char *ptr, int image)
1221     {
1222 jhuggins 1.4 if ((image >= 0) && (image <=3)) {
1223 astro 1.1 // Clear the Mapping in the Universe
1224     writel(0x00000000, baseaddr + aCTL[image]);
1225     writel(0x00000000, baseaddr + aBS[image]);
1226     writel(0x00000000, baseaddr + aBD[image]);
1227     writel(0x00000000, baseaddr + aTO[image]);
1228     }
1229    
1230     // Clear Mapping of PCI Memory
1231     iounmap(ptr);
1232     }
1233    
1234     //-----------------------------------------------------------------------------
1235     // Function : VME_DMA
1236     // Inputs : unsigned int pci - PCI Address of Image Map (See howto)
1237     // unsigned int vme - VME Address of Image (See howto)
1238     // unsigned int count - Size of Image
1239     // int image - Image Number to Use (See howto)
1240     // int ctl - VME Address Space (See howto)
1241     // Outputs : void
1242 jhuggins 1.7 // Description:
1243 astro 1.1 // Remarks : This is Like the CMD Packet Version but will do only one transfer
1244 jhuggins 1.7 // History :
1245 astro 1.1 //-----------------------------------------------------------------------------
1246     void VME_DMA(void* pci, void* vme, unsigned int count, int ctl, TDMAcallback cback)
1247     {
1248     #ifdef __DEBUG__
1249     char buf[256];
1250     sprintf(buf,"<<ca91c042>> DMA Request of virtpci=0x%08X vme=0x%08X cnt=%i ctl=0x%08X\n",
1251     pci,vme,count,ctl);
1252     printk(buf);
1253     #endif
1254    
1255     // Setup the DMA Transfer in the Universe
1256     writel(ctl, baseaddr + DCTL);
1257     writel(count, baseaddr + DTBC);
1258     writel(virt_to_bus(pci), baseaddr + DLA);
1259     writel((int)vme, baseaddr + DVA);
1260    
1261     // We need to build a timer to timeout DMA access
1262 jhuggins 1.7 DMA_timer.expires = jiffies + DMATIMEOUT;
1263 astro 1.1 add_timer(&DMA_timer);
1264    
1265     // Setup CallBack Function
1266     DMACallBackFunc = cback;
1267    
1268     // Start the Transfer,
1269     // Interrupt on Stop,Halt,Done,LERR,VERR,Prot Error
1270     DMAType = DMATYPE_SINGLE;
1271 jhuggins 1.7 writel(0x80216F6F,baseaddr+DGCS);
1272 astro 1.1
1273     // We are now all setup, so lets return to the calling function so it can
1274     // sleep or what ever until the DMA is done
1275     }
1276    
1277     //-----------------------------------------------------------------------------
1278     // Function : VME_DMA_LinkedList
1279     // Inputs : void* CmdPacketList,TDMAcallback cback
1280     // Outputs : int
1281 jhuggins 1.7 // Description:
1282 astro 1.1 // Remarks : CmdPacketList is a Phys Address
1283 jhuggins 1.7 // History :
1284 astro 1.1 //-----------------------------------------------------------------------------
1285     void VME_DMA_LinkedList(void* CmdPacketList,TDMAcallback cback)
1286     {
1287     debugptr = CmdPacketList;
1288    
1289     // Setup a DMA Transfer and once the Transfer is complete call cback
1290     writel(0x08316F00,baseaddr+DGCS);
1291     writel(0x00000000,baseaddr+DTBC);
1292     writel((int)CmdPacketList,baseaddr+DCPP); // Command Packet Pointer
1293    
1294     // We need to build a timer to timeout DMA access
1295 jhuggins 1.7 DMA_timer.expires = jiffies + DMATIMEOUT;
1296 astro 1.1 add_timer(&DMA_timer);
1297    
1298     // Setup CallBack Function
1299     DMACallBackFunc = cback;
1300    
1301     // Start the Transfer,
1302     // Interrupt on Stop,Halt,Done,LERR,VERR,Prot Error
1303     DMAType = DMATYPE_LLIST;
1304 jhuggins 1.7 writel(0x88216F6F,baseaddr+DGCS);
1305 astro 1.1
1306     // We are now all setup, so lets return to the calling function so it can
1307     // sleep or what ever until the DMA is done
1308     }
1309    
1310 jhuggins 1.4 //-----------------------------------------------------------------------------
1311     // Function : VME_Bus_Error
1312 jhuggins 1.7 // Inputs :
1313     // Outputs :
1314 jhuggins 1.4 // Description: Returns 1 if a Bus Error is Pending
1315 jhuggins 1.7 // Remarks :
1316 jhuggins 1.4 // History : 10/30/2000 mjw Started
1317     //-------------------------------------------------------------------------mjw-
1318     int VME_Bus_Error(void)
1319     {
1320     int pci_csr;
1321    
1322     pci_csr = readl(baseaddr+PCI_CSR); // Check for Bus Error
1323     writel(pci_csr,baseaddr+PCI_CSR); // Clear the Error
1324     return((pci_csr & 0x08000000) ? 1 : 0);
1325     }
1326 astro 1.1

  ViewVC Help
Powered by ViewVC 1.2-dev