include upstream ip1000a driver version 2.09f
[linux-2.4.git] / drivers / isdn / eicon / common.c
1 /*
2  * Copyright (C) Eicon Technology Corporation, 2000.
3  *
4  * Eicon File Revision :    1.15  
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 #include "eicon.h"
12 #include "sys.h"
13 #include "idi.h"
14 #include "constant.h"
15 #include "divas.h"
16 #include "pc.h"
17 #include "pr_pc.h"
18
19 #include "uxio.h"
20
21 #define DIVAS_LOAD_CMD          0x02
22 #define DIVAS_START_CMD         0x03
23 #define DIVAS_IRQ_RESET         0xC18
24 #define DIVAS_IRQ_RESET_VAL     0xFE
25
26 #define TEST_INT_DIVAS          0x11
27 #define TEST_INT_DIVAS_BRI      0x12
28 #define TEST_INT_DIVAS_Q        0x13
29
30 #define DIVAS_RESET     0x81
31 #define DIVAS_LED1      0x04
32 #define DIVAS_LED2      0x08
33 #define DIVAS_LED3      0x20
34 #define DIVAS_LED4      0x40
35
36 #define DIVAS_SIGNATURE 0x4447
37
38 #define MP_PROTOCOL_ADDR 0xA0011000
39
40 #define PLX_IOBASE      0
41 #define DIVAS_IOBASE    1
42
43 typedef struct {
44                 dword cmd;
45                 dword addr;
46                 dword len;
47                 dword err;
48                 dword live;
49                 dword reserved[(0x1020>>2)-6];
50                 dword signature;
51                 byte  data[1];
52 } diva_server_boot_t;
53
54 int             DivasCardNext;
55 card_t  DivasCards[MAX_CARDS];
56
57 dia_config_t *DivasConfig(card_t *, dia_config_t *);
58
59 static
60 DESCRIPTOR DIDD_Table[32];
61
62 void    DIVA_DIDD_Read( DESCRIPTOR *table, int tablelength )
63 {
64         memset(table, 0, tablelength);
65
66         if (tablelength > sizeof(DIDD_Table))
67           tablelength = sizeof(DIDD_Table);
68
69         if(tablelength % sizeof(DESCRIPTOR)) {
70           tablelength /= sizeof(DESCRIPTOR);
71           tablelength *= sizeof(DESCRIPTOR);
72         }
73
74         if (tablelength > 0)
75           memcpy((void *)table, (void *)DIDD_Table, tablelength);
76
77         return;
78 }
79
80 void    DIVA_DIDD_Write(DESCRIPTOR *table, int tablelength)
81 {
82         if (tablelength > sizeof(DIDD_Table))
83           tablelength = sizeof(DIDD_Table);
84
85         memcpy((void *)DIDD_Table, (void *)table, tablelength);
86
87         return;
88 }
89
90 static
91 void    init_idi_tab(void)
92 {
93     DESCRIPTOR d[32];
94
95     memset(d, 0, sizeof(d));
96
97     d[0].type = IDI_DIMAINT;  /* identify the DIMAINT entry */
98     d[0].channels = 0; /* zero channels associated with dimaint*/
99     d[0].features = 0; /* no features associated with dimaint */
100     d[0].request = (IDI_CALL) DivasPrintf;
101     
102     DIVA_DIDD_Write(d, sizeof(d));
103
104     return;
105 }
106
107 /*
108  * I/O routines for memory mapped cards
109  */
110
111 byte mem_in(ADAPTER *a, void *adr)
112 {
113         card_t                  *card = a->io;
114         unsigned char   *b, *m;
115         byte                    value;
116
117         m = b = UxCardMemAttach(card->hw, DIVAS_SHARED_MEMORY);
118
119         m += (unsigned int) adr;
120
121         value = UxCardMemIn(card->hw, m);
122
123         UxCardMemDetach(card->hw, b);
124
125         return value;
126 }
127
128 word mem_inw(ADAPTER *a, void *adr)
129 {
130         card_t                  *card = a->io;
131         unsigned char   *b, *m;
132         word                    value;
133
134         m = b = UxCardMemAttach(card->hw, DIVAS_SHARED_MEMORY);
135
136         m += (unsigned int) adr;
137
138         value = UxCardMemInW(card->hw, m);
139
140         UxCardMemDetach(card->hw, b);
141
142         return value;
143 }
144
145 void mem_in_buffer(ADAPTER *a, void *adr, void *P, word length)
146 {
147         card_t                  *card = a->io;
148         unsigned char   *b, *m;
149
150         m = b = UxCardMemAttach(card->hw, DIVAS_SHARED_MEMORY);
151
152         m += (unsigned int) adr;
153
154         UxCardMemInBuffer(card->hw, m, P, length);
155
156         UxCardMemDetach(card->hw, b);
157
158         return;
159 }
160
161 void mem_look_ahead(ADAPTER *a, PBUFFER *RBuffer, ENTITY *e)
162 {
163         card_t                  *card = a->io;
164         unsigned char   *b, *m;
165
166         m = b = UxCardMemAttach(card->hw, DIVAS_SHARED_MEMORY);
167
168         m += (dword) &RBuffer->length;
169         card->RBuffer.length = UxCardMemInW(card->hw, m);
170
171         m = b;
172         m += (dword) &RBuffer->P;
173         UxCardMemInBuffer(card->hw, m, card->RBuffer.P, card->RBuffer.length);
174
175         e->RBuffer = (DBUFFER *) &card->RBuffer;
176
177         UxCardMemDetach(card->hw, b);
178
179         return;
180 }
181
182 void mem_out(ADAPTER *a, void *adr, byte data)
183 {
184         card_t                  *card = a->io;
185         unsigned char   *b, *m;
186
187         m = b = UxCardMemAttach(card->hw, DIVAS_SHARED_MEMORY);
188
189         m += (unsigned int) adr;
190
191         UxCardMemOut(card->hw, m, data);
192
193         UxCardMemDetach(card->hw, b);
194
195         return;
196 }
197
198 void mem_outw(ADAPTER *a, void *adr, word data)
199 {
200         card_t                  *card = a->io;
201         unsigned char   *b, *m;
202
203         m = b = UxCardMemAttach(card->hw, DIVAS_SHARED_MEMORY);
204
205         m += (unsigned int) adr;
206
207         UxCardMemOutW(card->hw, m, data);
208
209         UxCardMemDetach(card->hw, b);
210
211         return;
212 }
213
214 void mem_out_buffer(ADAPTER *a, void *adr, void *P, word length)
215 {
216         card_t                  *card = a->io;
217         unsigned char   *b, *m;
218
219         m = b = UxCardMemAttach(card->hw, DIVAS_SHARED_MEMORY);
220
221         m += (unsigned int) adr;
222
223         UxCardMemOutBuffer(card->hw, m, P, length);
224
225         UxCardMemDetach(card->hw, b);
226
227         return;
228 }
229
230 void mem_inc(ADAPTER *a, void *adr)
231 {
232         word                    value;
233         card_t                  *card = a->io;
234         unsigned char   *b, *m;
235
236         m = b = UxCardMemAttach(card->hw, DIVAS_SHARED_MEMORY);
237
238         m += (unsigned int) adr;
239
240         value = UxCardMemInW(card->hw, m);
241         value++;
242         UxCardMemOutW(card->hw, m, value);
243
244         UxCardMemDetach(card->hw, b);
245
246         return;
247 }
248
249 /*
250  * I/O routines for I/O mapped cards
251  */
252
253 byte io_in(ADAPTER *a, void *adr)
254 {
255         card_t              *card = a->io;
256         byte                value;
257         byte    *DivasIOBase = NULL;
258
259         DivasIOBase = UxCardMemAttach(card->hw, DIVAS_IOBASE);
260
261         value = UxCardIoIn(card->hw, DivasIOBase, adr);
262
263         UxCardMemDetach(card->hw, DivasIOBase);
264
265     return value;
266 }
267
268 word io_inw(ADAPTER *a, void *adr)
269 {
270         card_t          *card = a->io;
271         word            value;
272         byte    *DivasIOBase = NULL;
273
274         DivasIOBase = UxCardMemAttach(card->hw, DIVAS_IOBASE);
275
276         value = UxCardIoInW(card->hw, DivasIOBase, adr);
277
278         UxCardMemDetach(card->hw, DivasIOBase);
279
280         return value;
281 }
282
283 void io_in_buffer(ADAPTER *a, void *adr, void *P, word length)
284 {
285         card_t *card = a->io;
286         byte *DivasIOBase = NULL;
287
288         DivasIOBase = UxCardMemAttach(card->hw, DIVAS_IOBASE);
289
290         UxCardIoInBuffer(card->hw, DivasIOBase, adr, P,length);
291
292         UxCardMemDetach(card->hw, DivasIOBase);
293
294     return;
295 }
296
297 void io_look_ahead(ADAPTER *a, PBUFFER *RBuffer, ENTITY *e)
298 {
299         card_t *card = a->io;
300         byte *DivasIOBase = NULL;
301
302         DivasIOBase = UxCardMemAttach(card->hw, DIVAS_IOBASE);
303
304         card->RBuffer.length = UxCardIoInW(card->hw, DivasIOBase, (byte *) RBuffer);
305
306         UxCardIoInBuffer(card->hw, DivasIOBase, &RBuffer->P, card->RBuffer.P, card->RBuffer.length);
307
308         UxCardMemDetach(card->hw, DivasIOBase);
309
310         e->RBuffer = (DBUFFER *) &card->RBuffer;
311
312     return;
313 }
314
315 void io_out(ADAPTER *a, void *adr, byte data)
316 {
317         card_t          *card = a->io;
318         byte    *DivasIOBase = NULL;
319
320         DivasIOBase = UxCardMemAttach(card->hw, DIVAS_IOBASE);
321
322         UxCardIoOut(card->hw, DivasIOBase, adr, data);
323
324         UxCardMemDetach(card->hw, DivasIOBase);
325
326     return;
327 }
328
329 void io_outw(ADAPTER *a, void *adr, word data)
330 {
331         card_t          *card = a->io;
332         byte    *DivasIOBase = NULL;
333
334         DivasIOBase = UxCardMemAttach(card->hw, DIVAS_IOBASE);
335
336         UxCardIoOutW(card->hw, DivasIOBase, adr, data);
337
338         UxCardMemDetach(card->hw, DivasIOBase);
339
340     return;
341 }
342
343 void io_out_buffer(ADAPTER *a, void *adr, void *P, word length)
344 {
345         card_t          *card = a->io;
346         byte *DivasIOBase = NULL;
347
348         DivasIOBase = UxCardMemAttach(card->hw, DIVAS_IOBASE);
349
350         UxCardIoOutBuffer(card->hw, DivasIOBase, adr, P, length);
351
352         UxCardMemDetach(card->hw, DivasIOBase);
353
354     return;
355 }
356
357 void io_inc(ADAPTER *a, void *adr)
358 {
359         word            value;
360         card_t          *card = a->io;
361         byte *DivasIOBase;
362
363         DivasIOBase = UxCardMemAttach(card->hw, DIVAS_IOBASE);
364
365         value = UxCardIoInW(card->hw, DivasIOBase, adr);
366         
367         value++;
368
369         UxCardIoOutW(card->hw, DivasIOBase, adr, value);
370
371         UxCardMemDetach(card->hw, DivasIOBase);
372
373     return;
374 }
375
376 static
377 void test_int(card_t *card)
378
379 {
380         byte *shared, *DivasIOBase;
381
382         switch (card->test_int_pend)
383         {
384                 case TEST_INT_DIVAS:
385                         DPRINTF(("divas: test interrupt pending"));
386                         shared = UxCardMemAttach(card->hw, DIVAS_SHARED_MEMORY);
387
388                         if (UxCardMemIn(card->hw, &shared[0x3FE]))
389                         {
390                                 UxCardMemOut(card->hw, 
391                                                                 &(((struct pr_ram *)shared)->RcOutput), 0);
392                                 UxCardMemDetach(card->hw, shared);
393                 (*card->reset_int)(card);
394                                 shared = UxCardMemAttach(card->hw, DIVAS_SHARED_MEMORY);
395                                 UxCardMemOut(card->hw, &shared[0x3FE], 0);
396                                 DPRINTF(("divas: test interrupt cleared"));
397                         }
398
399                         UxCardMemDetach(card->hw, shared);
400
401                         card->test_int_pend = 0;
402                         break;
403
404                 case TEST_INT_DIVAS_BRI:
405                         DPRINTF(("divas: BRI test interrupt pending"));
406                         (*card->reset_int)(card);
407                         DivasIOBase = UxCardMemAttach(card->hw, DIVAS_IOBASE);
408                         UxCardIoOutW(card->hw, DivasIOBase, (void *) 0x3FE, 0);
409                         UxCardMemDetach(card->hw, DivasIOBase);
410                         DPRINTF(("divas: test interrupt cleared"));
411                         card->test_int_pend = 0;
412                         break;
413
414                 case TEST_INT_DIVAS_Q:
415                         DPRINTF(("divas: 4BRI test interrupt pending"));
416                         (*card->reset_int)(card);
417                         card->test_int_pend = 0;
418                         break;
419
420                 default:
421                         DPRINTF(("divas: unknown test interrupt pending"));
422                         return;
423         }
424         return;
425 }
426
427 void card_isr (void *dev_id)
428 {
429         card_t *card = (card_t *) dev_id;
430         ADAPTER *a = &card->a;
431         int ipl;
432
433         if (card->test_int_pend)
434         {
435                 ipl = UxCardLock(card->hw);
436                 card->int_pend=0;
437                 test_int(card);
438                 UxCardUnlock(card->hw,ipl);
439                 return;
440         }
441         
442         if(card->card_isr)
443         {
444                 (*(card->card_isr))(card);
445         }
446         else
447         {
448                 ipl = UxCardLock(card->hw);
449         
450                 if ((card->test_int)(a))
451                 {
452                         (card->reset_int)(card);
453                 }
454                 
455                 UxCardUnlock(card->hw,ipl);
456                 
457         }
458
459 }
460
461 int DivasCardNew(dia_card_t *card_info)
462 {
463         card_t *card;
464         static boolean_t first_call = TRUE;
465         boolean_t NeedISRandReset = FALSE;
466
467         DPRINTF(("divas: new card "));
468
469         if (first_call)
470         {
471                 first_call = FALSE;
472                 init_idi_tab();
473         }
474
475         DivasConfigGet(card_info);
476         
477         if (DivasCardNext == DIM(DivasCards))
478         {
479                 KDPRINTF((KERN_WARNING "Divas: no space available for new card"));
480                 return -1;
481         }
482
483         card = &DivasCards[DivasCardNext];
484
485         card->state = DIA_UNKNOWN;
486
487         card->cfg = *card_info;
488
489         card->a.io = card;
490
491         if (UxCardHandleGet(&card->hw, card_info))
492         {
493                 KDPRINTF((KERN_WARNING "Divas: cannot get OS specific handle for card"));
494                 return -1;
495         }
496
497         if (card_info->card_type == DIA_CARD_TYPE_DIVA_SERVER_B)
498         {
499                 DivasBriPatch(card);
500                 card_info->io_base = card->cfg.io_base;
501         }
502
503         switch (card_info->card_type)
504         {
505                 case DIA_CARD_TYPE_DIVA_SERVER:
506                         if (DivasPriInit(card, card_info))
507                         {
508                                 return -1;
509                         }
510                         NeedISRandReset = TRUE;
511                         break;
512
513                 case DIA_CARD_TYPE_DIVA_SERVER_B:
514                         if (DivasBriInit(card, card_info))
515                         {
516                                 return -1;
517                         }
518                         NeedISRandReset = TRUE;
519                         break;
520
521                 case DIA_CARD_TYPE_DIVA_SERVER_Q:
522                         if (Divas4BriInit(card, card_info))
523                         {
524                                 return -1;
525                         }
526
527                         if (card_info->name[6] == '0')
528                         {
529                                 NeedISRandReset = TRUE;
530                         }
531                         else // Need to set paramater for ISR anyway
532                         {
533                                 card->hw->user_isr_arg = card;
534                                 card->hw->user_isr = card_isr;
535                         }
536                         break;   
537
538                 default:
539                         KDPRINTF((KERN_WARNING "Divas: unsupported card type (%d)", card_info->card_type));
540                         return -1;
541         }
542
543         if (NeedISRandReset)
544         {
545                 if (UxIsrInstall(card->hw, card_isr, card))
546                 {
547                         KDPRINTF((KERN_WARNING "Divas: Install ISR failed (IRQ %d)", card->cfg.irq));
548                         UxCardHandleFree(card->hw);
549                         return -1;
550                 }
551
552                 if (card_info->card_type != DIA_CARD_TYPE_DIVA_SERVER_Q)
553                 {
554                         if ((*card->card_reset)(card))
555                         {
556                                 KDPRINTF((KERN_WARNING "Divas: Adapter reset failed"));
557                                 return -1;
558                         }
559                         card->state = DIA_RESET;
560                 }
561
562                 NeedISRandReset = FALSE;
563         }
564
565         DivasCardNext++;
566
567         return 0;
568 }
569
570 void    *get_card(int card_id)
571 {
572         int i;
573
574         for (i=0; i < DivasCardNext; i++)
575         {
576                 if (DivasCards[i].cfg.card_id == card_id)
577                 {
578                         return(&DivasCards[i]);
579                 }
580         }
581
582         DPRINTF(("divas: get_card() : no such card id (%d)", card_id));
583
584         return NULL;
585 }
586
587 int DivasCardConfig(dia_config_t *config)
588 {
589         card_t *card;
590         int status;
591
592         DPRINTF(("divas: configuring card"));
593
594         card = get_card(config->card_id);
595         if (!card)
596         {
597                 return -1;
598         }
599
600         config = DivasConfig(card, config);
601
602         status = (*card->card_config)(card, config);
603
604         if (!status)
605         {
606                 card->state = DIA_CONFIGURED;
607         }
608         return status;
609 }
610
611 int DivasCardLoad(dia_load_t *load)
612 {
613         card_t *card;
614         int     status;
615
616         card = get_card(load->card_id);
617         if (!card)
618         {
619                 return -1;
620         }
621
622         if (card->state == DIA_RUNNING)
623         {
624                 (*card->card_reset)(card);
625         }
626
627         status = (*card->card_load)(card, load);
628         if (!status)
629         {
630                 card->state = DIA_LOADED;
631         }
632         return status;
633 }
634
635 static int idi_register(card_t *card, byte channels)
636 {
637     DESCRIPTOR d[32];
638     int length, num_entities;
639
640         DPRINTF(("divas: registering card with IDI"));
641
642         num_entities = (channels > 2) ? MAX_PENTITIES : MAX_ENTITIES;
643         card->e_tbl = UxAlloc(sizeof(E_INFO) * num_entities);
644
645         if (!card->e_tbl)
646         {
647                 KDPRINTF((KERN_WARNING "Divas: IDI register failed - no memory available"));
648                 return -1;
649         }
650
651         memset(card->e_tbl, 0, sizeof(E_INFO) * num_entities);
652         card->e_max = num_entities;
653
654     DIVA_DIDD_Read(d, sizeof(d));
655
656         for(length=0; length < DIM(d); length++)
657           if (d[length].type == 0) break;
658
659         if (length >= DIM(d))
660         {
661                 KDPRINTF((KERN_WARNING "Divas: IDI register failed - table full"));
662                 return -1;
663         }
664
665         switch (card->cfg.card_type)
666         {
667                 case DIA_CARD_TYPE_DIVA_SERVER:
668                 d[length].type = IDI_ADAPTER_PR;
669                 /* d[length].serial = card->serial_no; */
670                 break;
671
672                 case DIA_CARD_TYPE_DIVA_SERVER_B:
673                 d[length].type = IDI_ADAPTER_MAESTRA;
674                 /* d[length].serial = card->serial_no; */
675                 break;
676
677                 // 4BRI is treated as 4 BRI adapters
678                 case DIA_CARD_TYPE_DIVA_SERVER_Q:
679                 d[length].type = IDI_ADAPTER_MAESTRA;
680                 /* d[length].serial = card->cfg.serial; */
681         }
682
683         d[length].features = 0;
684         d[length].features |= DI_FAX3|DI_MODEM|DI_POST|DI_V110|DI_V120;
685
686         if ( card->hw->features & PROTCAP_MANIF )
687         {
688                 d[length].features |= DI_MANAGE ;
689         }
690         if ( card->hw->features & PROTCAP_V_42 )
691         {
692                 d[length].features |= DI_V_42 ;
693         }
694         if ( card->hw->features & PROTCAP_EXTD_FAX )
695         {
696                 d[length].features |= DI_EXTD_FAX ;
697         }
698
699         d[length].channels = channels;
700         d[length].request = DivasIdiRequest[card - DivasCards];
701
702         length++;
703
704         DIVA_DIDD_Write(d, sizeof(d));
705
706     return 0;
707 }
708
709 int DivasCardStart(int card_id)
710 {
711         card_t *card;
712         byte channels;
713         int status;
714
715         DPRINTF(("divas: starting card"));
716
717         card = get_card(card_id);
718         if (!card)
719         {
720                 return -1;
721         }
722
723         status = (*card->card_start)(card, &channels);
724         if (status)
725         {
726                 return status;
727         }
728
729         /* 4BRI == 4 x BRI so call idi_register 4 times each with 2 channels */
730         if (card->cfg.card_type == DIA_CARD_TYPE_DIVA_SERVER_Q)
731         {
732                 int i;
733                 card_t *FourBRISlave;
734
735                 for (i=3; i >= 0; i--)
736                 {
737                         FourBRISlave = get_card(card_id - i); /* 0, 1, 2, 3 */
738                         if (FourBRISlave)
739                         {
740                                 idi_register(FourBRISlave, 2);
741                                 FourBRISlave->state = DIA_RUNNING;
742                         }
743                 }
744                 card->serial_no = card->cfg.serial;
745
746                 DPRINTF(("divas: card id %d (4BRI), serial no. 0x%x ready with %d channels", 
747                                 card_id - 3, card->serial_no, (int) channels));
748         }
749         else
750         {
751                 status = idi_register(card, channels);
752                 if (!status)
753                 {
754                         card->state = DIA_RUNNING;
755                         DPRINTF(("divas: card id %d, serial no. 0x%x ready with %d channels", 
756                                                 card_id, card->serial_no, (int) channels));
757                 }
758         }
759
760         return status;
761 }
762
763 int DivasGetMem(mem_block_t *mem_block)
764 {
765         card_t *card;
766         word    card_id = mem_block->card_id;
767
768         card = get_card(card_id);
769         if (!card)
770         {
771                 return 0;
772         }
773
774         return (*card->card_mem_get)(card, mem_block);
775 }
776
777
778 /*
779  * Deleyed Procedure Call for handling interrupts from card
780  */
781
782 void    DivaDoCardDpc(card_t *card)
783 {
784         ADAPTER *a;
785
786         a = &card->a;
787
788         if(UxInterlockedIncrement(card->hw, &card->dpc_reentered) > 1)
789         {
790                 return;
791         }
792
793         do{
794                 if((*(card->test_int))(a))
795                 {
796                         (*(card->dpc))(a);
797                         (*(card->clear_int))(a);
798                 }
799                         (*(card->out))(a);
800         }while(UxInterlockedDecrement(card->hw, &card->dpc_reentered));
801                         
802 }
803
804 void    DivasDoDpc(void *pData)
805 {
806         card_t  *card = DivasCards;
807         int     i = DivasCardNext;
808         
809         while(i--)
810         {
811             if (card->state == DIA_RUNNING)
812                 DivaDoCardDpc(card);
813             card++;
814         }
815 }
816
817 void    DivasDoRequestDpc(void *pData)
818 {
819         DivasDoDpc(pData);
820 }
821
822 /*
823  * DivasGetNum
824  * Returns the number of active adapters
825  */
826
827 int DivasGetNum(void)
828 {
829         return(DivasCardNext);
830 }
831
832 /*
833  * DivasGetList
834  * Returns a list of active adapters
835  */
836 int DivasGetList(dia_card_list_t *card_list)
837 {
838         int i;
839
840         memset(card_list, 0, sizeof(dia_card_list_t));
841
842         for(i = 0; i < DivasCardNext; i++)
843         {
844                 card_list->card_type = DivasCards[i].cfg.card_type;
845                 card_list->card_slot = DivasCards[i].cfg.slot;
846                 card_list->state     = DivasCards[i].state;
847                 card_list++;
848         }
849
850         return 0;
851
852 }
853
854 /*
855  * control logging for specified card
856  */
857
858 void    DivasLog(dia_log_t *log)
859 {
860         card_t *card;
861
862         card = get_card(log->card_id);
863         if (!card)
864         {
865                 return;
866         }
867
868         card->log_types = log->log_types;
869
870         return;
871 }
872