update atp870u driver to 0.78 from D-Link source
[linux-2.4.git] / drivers / isdn / eicon / linio.c
1 /*
2  * Copyright (C) Eicon Technology Corporation, 2000.
3  *
4  * Eicon File Revision :    1.16  
5  *
6  * This software may be used and distributed according to the terms
7  * of the GNU General Public License, incorporated herein by reference.
8  *
9  */
10
11 #define N_DATA
12
13 #include <asm/io.h>
14 #include <asm/system.h>
15 #include <linux/slab.h>
16 #include <linux/pci.h>
17 #include <linux/delay.h>
18 #undef N_DATA
19
20 #include "uxio.h"
21
22 static
23 int log_on=0;
24
25 int             Divasdevflag = 0;
26
27 //spinlock_t diva_lock = SPIN_LOCK_UNLOCKED;
28
29 static
30 ux_diva_card_t card_pool[MAX_CARDS];
31
32 void UxPause(long int ms)
33 {
34         int timeout = jiffies + ((ms * HZ) / 1000);
35
36         while (time_before(jiffies, timeout));
37 }
38
39 int UxCardHandleGet(ux_diva_card_t **card, dia_card_t *cfg)
40 {
41         int             i;
42         ux_diva_card_t  *c;
43
44         if (cfg->bus_type != DIA_BUS_TYPE_PCI)
45         {
46                 DPRINTF(("divas hw: type not PCI (%d)", cfg->bus_type));
47                 return -1;
48         }
49
50         for (i = 0; (i < DIM(card_pool)) && (card_pool[i].in_use); i++)
51         {
52                 ;
53         }
54
55         if (i == DIM(card_pool))
56         {
57                 DPRINTF(("divas hw: card_pool exhausted"));
58                 return -1;
59         }
60
61         c = *card = &card_pool[i];
62
63         switch (cfg->bus_type)
64         {
65         case DIA_BUS_TYPE_PCI:
66                 c->bus_num = cfg->bus_num;
67                 c->func_num = cfg->func_num;
68                 c->io_base = cfg->io_base;
69                 c->reset_base = cfg->reset_base;
70                 c->card_type    = cfg->card_type;
71                 c->mapped = NULL;
72                 c->slot         = cfg->slot;
73                 c->irq          = (int) cfg->irq;
74                 c->pDRAM        = cfg->memory[DIVAS_RAM_MEMORY];
75                 c->pDEVICES     = cfg->memory[DIVAS_REG_MEMORY];
76                 c->pCONFIG      = cfg->memory[DIVAS_CFG_MEMORY];
77                 c->pSHARED      = cfg->memory[DIVAS_SHARED_MEMORY];
78                 c->pCONTROL     = cfg->memory[DIVAS_CTL_MEMORY];
79
80         /*              c->bus_type     = DIA_BUS_TYPE_PCI;
81                 c->bus_num      = cfg->bus_num & 0x3f;
82                 c->slot         = cfg->slot;
83                 c->irq          = (int) cfg->irq;
84                 c->int_priority = (int) cfg->int_priority;
85                 c->card_type    = cfg->card_type;
86                 c->io_base      = cfg->io_base;
87                 c->reset_base   = cfg->reset_base;
88                 c->pDRAM        = cfg->memory[DIVAS_RAM_MEMORY];
89                 c->pDEVICES     = cfg->memory[DIVAS_REG_MEMORY];
90                 c->pCONFIG      = cfg->memory[DIVAS_CFG_MEMORY];
91                 c->pSHARED      = cfg->memory[DIVAS_SHARED_MEMORY];
92                 DPRINTF(("divas hw: pDRAM is 0x%x", c->pDRAM));
93                 DPRINTF(("divas hw: pSHARED is 0x%x", c->pSHARED));
94                 DPRINTF(("divas hw: pCONFIG is 0x%x", c->pCONFIG));
95                 c->cm_key               = cm_getbrdkey("Divas", cfg->card_id);*/
96                 break;
97         default:
98                 break;
99         }
100
101         c->in_use = TRUE;
102
103         return 0;
104 }
105
106 void UxCardHandleFree(ux_diva_card_t *card)
107 {
108         card->in_use = FALSE;
109 }
110
111
112 #define PLX_IOBASE 0
113 #define DIVAS_IOBASE 1
114 void *UxCardMemAttach(ux_diva_card_t *card, int id)
115 {
116         if (card->card_type == DIA_CARD_TYPE_DIVA_SERVER)
117         {
118                 switch (id)
119                 {
120                 case DIVAS_SHARED_MEMORY:
121                         card->mapped = card->pSHARED;
122                         return card->pSHARED;
123                         break;
124                 case DIVAS_RAM_MEMORY:
125                         card->mapped = card->pDRAM;
126                         return card->pDRAM;
127                         break;
128                 case DIVAS_REG_MEMORY:
129                         card->mapped = card->pDEVICES;
130                         return card->pDEVICES;
131                         break;
132                 case DIVAS_CFG_MEMORY:
133                         card->mapped = card->pCONFIG;
134                         return card->pCONFIG;
135                         break;
136                 default:
137                         ASSERT(FALSE);
138                         card->mapped = NULL;
139                         return (void *) 0;
140                 }
141         }
142         else if (card->card_type == DIA_CARD_TYPE_DIVA_SERVER_B)
143         {
144                 switch (id)
145                 {
146                 case PLX_IOBASE:
147                         return (void *) card->reset_base;
148                         break;
149                 case DIVAS_IOBASE:
150                         return (void *) card->io_base;
151                         break;
152                 default:
153                         ASSERT(FALSE);
154                         return 0;
155                 }
156         }
157         
158         else if (card->card_type == DIA_CARD_TYPE_DIVA_SERVER_Q)
159         {
160                 switch (id)
161                 {
162                 case DIVAS_SHARED_MEMORY:
163                         card->mapped = card->pSHARED;
164                         return card->pSHARED;
165                         break;
166                 case DIVAS_RAM_MEMORY:
167                         card->mapped = card->pDRAM;
168                         return card->pDRAM;
169                         break;
170                 case DIVAS_REG_MEMORY:
171                         card->mapped = (void *) card->io_base;
172                         return (void *) card->io_base;
173                         break;
174                 case DIVAS_CTL_MEMORY:
175                         card->mapped = card->pCONTROL;
176                         return card->pCONTROL;
177                         break;
178                 default:
179                         // ASSERT(FALSE);
180                         DPRINTF(("divas: Trying to attach to mem %d", id));
181                         card->mapped = NULL;
182                         return (void *) 0;
183                 }
184         } else
185                 DPRINTF(("divas: Tried to attach to unknown card"));
186
187         /* Unknown card type */
188         return NULL;
189 }
190
191 void UxCardMemDetach(ux_diva_card_t *card, void *address)
192 {
193         return; // Just a place holder. No un-mapping done.
194 }
195
196 void UxCardLog(int turn_on)
197 {
198         log_on = turn_on;
199 }
200
201 /*
202  * Control Register I/O Routines to be performed on Attached I/O ports
203  */
204
205 void UxCardPortIoOut(ux_diva_card_t *card, void *AttachedBase, int offset, byte the_byte)
206 {
207         word base = (word) (dword) AttachedBase;
208
209         base += offset;
210
211         outb(the_byte, base);
212 }
213
214 void UxCardPortIoOutW(ux_diva_card_t *card, void *AttachedBase, int offset, word the_word)
215 {
216         word base = (word) (dword) AttachedBase;
217
218         base += offset;
219
220         outw(the_word, base);
221 }
222
223 void UxCardPortIoOutD(ux_diva_card_t *card, void *AttachedBase, int offset, dword the_dword)
224 {
225         word base = (word) (dword) AttachedBase;
226
227         base += offset;
228
229         outl(the_dword, base);
230 }
231
232 byte UxCardPortIoIn(ux_diva_card_t *card, void *AttachedBase, int offset)
233 {
234         word base = (word) (dword) AttachedBase;
235
236         base += offset;
237
238         return inb(base);
239 }
240
241 word UxCardPortIoInW(ux_diva_card_t *card, void *AttachedBase, int offset)
242 {
243         word base = (word) (dword) AttachedBase;
244
245         base += offset;
246
247         return inw(base);
248 }
249
250 /*
251  * Memory mapped card I/O functions
252  */
253
254 byte UxCardMemIn(ux_diva_card_t *card, void *address)
255 {
256         byte    b;
257         volatile byte* t = (byte*)address;
258
259         b = *t;
260
261         if (log_on)
262         {
263                 byte *a = address;
264                 a -= (int) card->mapped;
265                 DPRINTF(("divas hw: read 0x%02x from 0x%x (memory mapped)", b & 0xff, a));
266         }
267
268     return(b); 
269 }
270
271 word UxCardMemInW(ux_diva_card_t *card, void *address)
272 {
273         word    w;
274         volatile word* t = (word*)address;
275
276     w = *t;
277
278         if (log_on)
279     {
280                 byte *a = address;
281                 a -= (int) card->mapped;
282                 DPRINTF(("divas hw: read 0x%04x from 0x%x (memory mapped)", w & 0xffff, a));
283     }
284
285     return (w);
286 }
287
288 dword UxCardMemInD(ux_diva_card_t *card, void *address)
289 {
290         dword   dw;
291         volatile dword* t = (dword*)address;
292
293     dw = *t;
294
295         if (log_on)
296     {
297                 byte *a = address;
298                 a -= (int) card->mapped;
299                 DPRINTF(("divas hw: read 0x%08x from 0x%x (memory mapped)", dw, a));
300     }
301
302     return (dw);
303 }
304
305 void UxCardMemInBuffer(ux_diva_card_t *card, void *address, void *buffer, int length)
306 {
307         volatile byte *pSource = address;
308         byte *pDest = buffer;
309
310         while (length--)
311         {
312                 *pDest++ = *pSource++;
313         }
314
315         if (log_on)
316     {
317                 byte *a = address;
318                 a -= (int) card->mapped;
319                 pDest = buffer;
320                 DPRINTF(("divas hw: read %02x %02x %02x %02x %02x %02x %02x %02x from 0x%x (memory mapped)", 
321                 pDest[0] & 0xff, pDest[1] & 0xff, pDest[2] & 0xff, pDest[3] & 0xff,
322                 pDest[4] & 0xff, pDest[5] & 0xff, pDest[6] & 0xff, pDest[7] & 0xff,
323                 a));
324     }
325
326     return;
327 }
328
329 void UxCardMemOut(ux_diva_card_t *card, void *address, byte data)
330 {
331         volatile byte* t = (byte*)address;
332
333         if (log_on)
334         {
335                 byte *a = address;
336                 a -= (int) card->mapped;
337                 DPRINTF(("divas hw: wrote 0x%02x to 0x%x (memory mapped)", data & 0xff, a));
338         }
339
340         *t = data;
341
342         return;
343 }
344
345 void UxCardMemOutW(ux_diva_card_t *card, void *address, word data)
346 {
347         volatile word* t = (word*)address;
348
349         if (log_on)
350         {
351                 byte *a = address;
352                 a -= (int) card->mapped;
353                 DPRINTF(("divas hw: wrote 0x%04x to 0x%x (memory mapped)", data & 0xffff, a));
354         }
355
356         *t = data;
357     return;
358 }
359
360 void UxCardMemOutD(ux_diva_card_t *card, void *address, dword data)
361 {
362         volatile dword* t = (dword*)address;
363
364         if (log_on)
365         {
366                 byte *a = address;
367                 a -= (int) card->mapped;
368                 DPRINTF(("divas hw: wrote 0x%08x to 0x%x (memory mapped)", data, a));
369         }
370
371         *t = data;
372     return;
373 }
374
375 void UxCardMemOutBuffer(ux_diva_card_t *card, void *address, void *buffer, int length)
376 {
377         byte    *pSource = buffer;
378         byte    *pDest = address;
379
380         while (length--)
381         {
382                 *pDest++ = *pSource++;
383         }
384
385         if (log_on)
386     {
387                 byte *a = address;
388                 a -= (int) card->mapped;
389                 pDest = buffer;
390                 DPRINTF(("divas hw: wrote %02x %02x %02x %02x %02x %02x %02x %02x to 0x%x (memory mapped)", 
391                 pDest[0] & 0xff, pDest[1] & 0xff, pDest[2] & 0xff, pDest[3] & 0xff,
392                 pDest[4] & 0xff, pDest[5] & 0xff, pDest[6] & 0xff, pDest[7] & 0xff,
393                 a));
394     }
395
396     return;
397 }
398
399 /*
400  * Memory mapped card I/O functions
401  */
402
403 byte UxCardIoIn(ux_diva_card_t *card, void *AttachedDivasIOBase, void *address)
404
405 {
406         byte the_byte;
407
408     outb(0xFF, card->io_base + 0xC);
409         outw((word) (dword) address, card->io_base + 4);
410
411         the_byte = inb(card->io_base);
412
413         if (log_on)
414     {
415                 DPRINTF(("divas hw: read 0x%02x from 0x%x (I/O mapped)", 
416                                         the_byte & 0xff, address));
417     }
418     
419         return the_byte;
420 }
421
422 word UxCardIoInW(ux_diva_card_t *card, void *AttachedDivasIOBase, void *address)
423
424 {
425         word the_word;
426
427         outb(0xFF, card->io_base + 0xC);
428         outw((word) (dword) address, card->io_base + 4);
429         the_word = inw(card->io_base);
430
431         if (log_on)
432     {
433                 DPRINTF(("divas hw: read 0x%04x from 0x%x (I/O mapped)", 
434                                         the_word & 0xffff, address));
435     }
436
437         return the_word;
438 }
439
440 dword UxCardIoInD(ux_diva_card_t *card, void *AttachedDivasIOBase, void *address)
441
442 {
443         dword the_dword;
444
445         outb(0xFF, card->io_base + 0xC);
446         outw((word) (dword) address, card->io_base + 4);
447         the_dword = inl(card->io_base);
448
449         if (log_on)
450     {
451                 DPRINTF(("divas hw: read 0x%08x from 0x%x (I/O mapped)", 
452                                         the_dword, address));
453     }
454
455     return the_dword;
456 }
457
458 void UxCardIoInBuffer(ux_diva_card_t *card, void *AttachedDivasIOBase, void *address, void *buffer, int length)
459
460 {
461         byte *pSource = address;
462         byte *pDest = buffer;
463
464         if ((word) (dword) address & 0x1)
465         {
466                 outb(0xFF, card->io_base + 0xC);
467                 outw((word) (dword) pSource, card->io_base + 4);
468                 *pDest = (byte) inb(card->io_base);
469                 pDest++;
470                 pSource++;
471                 length--;
472                 if (!length)
473         {
474             return;
475         }
476     }
477
478         outb(0xFF, card->io_base + 0xC);
479         outw((word) (dword) pSource, card->io_base + 4);
480         insw(card->io_base, (word *)pDest,length%2 ? (length+1)>>1 : length>>1);
481
482         if (log_on)
483     {
484                 pDest = buffer;
485                 DPRINTF(("divas hw: read %02x %02x %02x %02x %02x %02x %02x %02x from 0x%x (I/O mapped)", 
486                 pDest[0] & 0xff, pDest[1] & 0xff, pDest[2] & 0xff, pDest[3] & 0xff,
487                 pDest[4] & 0xff, pDest[5] & 0xff, pDest[6] & 0xff, pDest[7] & 0xff,
488                 address));
489     }
490
491     return;
492 }
493
494 /* Output */
495
496 void UxCardIoOut(ux_diva_card_t *card, void *AttachedDivasIOBase, void *address, byte data)
497 {
498         if (log_on)
499     {
500                 DPRINTF(("divas hw: wrote 0x%02x to 0x%x (I/O mapped)", 
501                                         data & 0xff, address));
502     }
503
504         outb(0xFF, card->io_base + 0xC);
505         outw((word) (dword) address, card->io_base + 4);
506         outb((byte) data & 0xFF, card->io_base);
507
508     return;
509 }
510
511 void UxCardIoOutW(ux_diva_card_t *card, void *AttachedDivasIOBase, void *address, word data)
512 {
513         if (log_on)
514     {
515                 DPRINTF(("divas hw: wrote 0x%04x to 0x%x (I/O mapped)", 
516                                         data & 0xffff, address));
517     }
518
519         outb(0xFF, card->io_base + 0xC);
520         outw((word) (dword) address, card->io_base + 4);
521         outw((word) data & 0xFFFF, card->io_base);
522
523     return;
524 }
525
526 void UxCardIoOutD(ux_diva_card_t *card, void *AttachedDivasIOBase, void *address, dword data)
527 {
528         if (log_on)
529     {
530                 DPRINTF(("divas hw: wrote 0x%08x to 0x%x (I/O mapped)", data, address));
531     }
532
533         outb(0xFF, card->io_base + 0xC);
534         outw((word) (dword) address, card->io_base + 4);
535         outl((dword) data & 0xFFFFFFFF, card->io_base);
536
537     return;
538 }
539
540 void UxCardIoOutBuffer(ux_diva_card_t *card, void *AttachedDivasIOBase, void *address, void *buffer, int length)
541
542 {
543         byte    *pSource = buffer;
544         byte    *pDest = address;
545
546         if ((word) (dword) address & 1)
547         {
548                 outb(0xFF, card->io_base + 0xC);
549                 outw((word) (dword) pDest, card->io_base + 4);
550                 outb(*pSource, card->io_base);
551                 pSource++;
552                 pDest++;
553                 length--;
554                 if (!length)
555         {
556                         return;
557         }
558         }
559
560     outb(0xFF, card->io_base + 0xC);
561         outw((word) (dword) pDest, card->io_base + 4);
562         outsw(card->io_base, (word *)pSource, length%2 ? (length+1)>>1 : length>>1);
563
564         if (log_on)
565     {
566                 pDest = buffer;
567                 DPRINTF(("divas hw: wrote %02x %02x %02x %02x %02x %02x %02x %02x to 0x%x (I/O mapped)", 
568                 pDest[0] & 0xff, pDest[1] & 0xff, pDest[2] & 0xff, pDest[3] & 0xff,
569                 pDest[4] & 0xff, pDest[5] & 0xff, pDest[6] & 0xff, pDest[7] & 0xff,
570                 address));
571     }
572
573     return;
574 }
575
576 void    Divasintr(int arg, void *unused, struct pt_regs *unused_regs)
577 {
578         int i;
579         card_t *card = NULL;
580         ux_diva_card_t *ux_ref = NULL;
581
582         for (i = 0; i < DivasCardNext; i++)
583         {
584
585                 if (arg == DivasCards[i].cfg.irq)
586                 {
587                         card = &DivasCards[i];
588                         ux_ref = card->hw;
589         
590                         if ((ux_ref) && (card->is_live))
591                         {
592                                 (*ux_ref->user_isr)(ux_ref->user_isr_arg);      
593                         }
594                         else 
595                         {
596                                 DPRINTF(("divas: ISR couldn't locate card"));
597                         }
598                 }
599         }
600
601         return;
602 }
603
604
605 int UxIsrInstall(ux_diva_card_t *card, isr_fn_t *isr_fn, void *isr_arg)
606 {
607         int result;
608
609         card->user_isr = isr_fn;
610         card->user_isr_arg = isr_arg;
611
612         result = request_irq(card->irq, Divasintr, SA_INTERRUPT | SA_SHIRQ, "Divas", (void *) isr_arg);
613
614         return result;
615 }
616
617 void UxIsrRemove(ux_diva_card_t *card, void *dev_id)
618 {
619         free_irq(card->irq, card->user_isr_arg);
620 }
621
622 void UxPciConfigWrite(ux_diva_card_t *card, int size, int offset, void *value)
623 {
624         switch (size)
625         {
626         case sizeof(byte):
627                 pcibios_write_config_byte(card->bus_num, card->func_num, offset, * (byte *) value);
628                 break;
629         case sizeof(word):
630                 pcibios_write_config_word(card->bus_num, card->func_num, offset, * (word *) value);
631                 break;
632         case sizeof(dword):
633                 pcibios_write_config_dword(card->bus_num, card->func_num, offset, * (dword *) value);
634                 break;
635         default:
636                 printk(KERN_WARNING "Divas: Invalid size in UxPciConfigWrite\n");
637         }
638 }
639
640 void UxPciConfigRead(ux_diva_card_t *card, int size, int offset, void *value)
641 {
642         switch (size)
643         {
644         case sizeof(byte):
645                 pcibios_read_config_byte(card->bus_num, card->func_num, offset, (byte *) value);
646                 break;
647         case sizeof(word):
648                 pcibios_read_config_word(card->bus_num, card->func_num, offset, (word *) value);
649                 break;
650         case sizeof(dword):
651                 pcibios_read_config_dword(card->bus_num, card->func_num, offset, (unsigned int *) value);
652                 break;
653         default:
654                 printk(KERN_WARNING "Divas: Invalid size in UxPciConfigRead\n");
655         }
656 }
657
658 void *UxAlloc(unsigned int size)
659 {
660         void *m;
661
662         m = kmalloc(size, GFP_ATOMIC);
663
664         return m;
665 }
666
667 void UxFree(void *ptr)
668 {
669         kfree(ptr);
670 }
671
672 long UxCardLock(ux_diva_card_t *card)
673 {
674         unsigned long flags;
675
676         //spin_lock_irqsave(&diva_lock, flags);
677         
678         save_flags(flags);
679         cli();
680         return flags;
681         
682 }
683
684 void UxCardUnlock(ux_diva_card_t *card, long ipl)
685 {
686         //spin_unlock_irqrestore(&diva_lock, ipl);
687
688         restore_flags(ipl);
689
690 }
691
692 dword UxTimeGet(void)
693 {
694         return jiffies;
695 }
696
697 long UxInterlockedIncrement(ux_diva_card_t *card, long *dst)
698 {
699         register volatile long *p;
700         register long ret;
701         int ipl;
702
703         p =dst;
704         
705         ipl = UxCardLock(card);
706
707         *p += 1;
708         ret = *p;
709
710         UxCardUnlock(card,ipl);
711
712         return(ret);
713
714 }
715
716 long UxInterlockedDecrement(ux_diva_card_t *card, long *dst)
717 {
718         register volatile long *p;
719         register long ret;
720         int ipl;
721
722         p =dst;
723         
724         ipl = UxCardLock(card);
725
726         *p -= 1;
727         ret = *p;
728
729         UxCardUnlock(card,ipl);
730
731         return(ret);
732
733 }