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

Contents of /driver/ca91c042.c

Parent Directory Parent Directory | Revision Log Revision Log


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

  ViewVC Help
Powered by ViewVC 1.2-dev