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