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

Contents of /driver/ca91c042.c

Parent Directory Parent Directory | Revision Log Revision Log


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

  ViewVC Help
Powered by ViewVC 1.2-dev