import of upstream 2.4.34.4 from kernel.org
[linux-2.4.git] / drivers / isdn / eicon / fourbri.c
1 /*
2  * Diva Server 4BRI specific part of initialisation
3  *
4  * Copyright (C) Eicon Technology Corporation, 2000.
5  *
6  * Eicon File Revision :    1.7  
7  *
8  * This software may be used and distributed according to the terms
9  * of the GNU General Public License, incorporated herein by reference.
10  *
11  */
12
13 #include "sys.h"
14 #include "idi.h"
15 #include "divas.h"
16 #include "pc.h"
17 #include "pr_pc.h"
18 #include "dsp_defs.h"
19 #include "constant.h"
20 #include "adapter.h"
21 #include "uxio.h"
22
23 #define TEST_INT_DIVAS_Q        0x13
24
25 #define DIVAS_MAINT_OFFSET      0xff00  /* value for 4BRI card */
26 #define MQ_BOARD_DSP_OFFSET 0x00a00000
27 #define MQ_DSP1_ADDR_OFFSET 0x00000008
28 #define MQ_DSP_JUNK_OFFSET  0x00000400
29 #define MQ_DSP1_DATA_OFFSET 0x00000000
30 #define MQ_BOARD_ISAC_DSP_RESET  0x00800028
31 #define MQ_BREG_RISC  0x1200      /* RISC Reset */
32 #define MQ_ISAC_DSP_RESET 0x0028 /* ISAC and DSP reset address offset */
33 #define MQ_RISC_COLD_RESET_MASK         0x0001      /* RISC Cold reset                        */
34 #define MQ_RISC_WARM_RESET_MASK         0x0002      /* RISC Warm reset                        */
35 #define MQ_IRQ_REQ_ON                   0x1
36 #define MQ_IRQ_REQ_OFF                  0x0
37 #define MQ_BREG_IRQ_TEST                0x0608
38 #define PLX9054_INTCSR      0x69 
39 #define PLX9054_INT_ENA     0x09
40
41 #define DIVAS_IOBASE    0x01
42 #define M_PCI_RESET     0x10
43
44 byte mem_in(ADAPTER *a, void *adr);
45 word mem_inw(ADAPTER *a, void *adr);
46 void mem_in_buffer(ADAPTER *a, void *adr, void *P, word length);
47 void mem_look_ahead(ADAPTER *a, PBUFFER *RBuffer, ENTITY *e);
48 void mem_out(ADAPTER *a, void *adr, byte data);
49 void mem_outw(ADAPTER *a, void *adr, word data);
50 void mem_out_buffer(ADAPTER *a, void *adr, void *P, word length);
51 void mem_inc(ADAPTER *a, void *adr);
52
53 int Divas4BRIInitPCI(card_t *card, dia_card_t *cfg);
54 static int fourbri_ISR (card_t* card);
55
56 int FPGA_Download(word, dword, byte *, byte *, int);
57 extern byte FPGA_Bytes[];
58 extern void *get_card(int);
59
60 byte UxCardPortIoIn(ux_diva_card_t *card, byte *base, int offset);
61 void UxCardPortIoOut(ux_diva_card_t *card, byte *base, int offset, byte);
62 word GetProtFeatureValue(char *sw_id);
63
64 void memcp(byte *dst, byte *src, dword dwLen);
65 int memcm(byte *dst, byte *src, dword dwLen);
66
67 static int diva_server_4bri_reset(card_t *card)
68 {
69         byte *ctl;
70
71         DPRINTF(("divas: reset Diva Server 4BRI"));
72
73         ctl = UxCardMemAttach(card->hw, DIVAS_CTL_MEMORY);
74
75         /* stop RISC, DSP's and ISAC  */
76    UxCardMemOut(card->hw, &ctl[MQ_BREG_RISC], 0);
77    UxCardMemOut(card->hw, &ctl[MQ_ISAC_DSP_RESET], 0);
78
79         UxCardMemDetach(card->hw, ctl);
80
81         return 0;
82 }
83
84 static int diva_server_4bri_config(card_t *card, dia_config_t *config)
85 {
86         byte *shared;
87         int i, j;
88
89         DPRINTF(("divas: configure Diva Server 4BRI"));
90
91         shared = (byte *) UxCardMemAttach(card->hw, DIVAS_SHARED_MEMORY);
92         
93         for (i=0; i<256; i++)
94         {
95                 UxCardMemOut(card->hw, &shared[i], 0);
96         }
97
98         UxCardMemOut(card->hw, &shared[ 8], config->tei);
99         UxCardMemOut(card->hw, &shared[ 9], config->nt2);
100         UxCardMemOut(card->hw, &shared[10], config->sig_flags);
101         UxCardMemOut(card->hw, &shared[11], config->watchdog);
102         UxCardMemOut(card->hw, &shared[12], config->permanent);
103         UxCardMemOut(card->hw, &shared[13], config->x_interface);
104         UxCardMemOut(card->hw, &shared[14], config->stable_l2);
105         UxCardMemOut(card->hw, &shared[15], config->no_order_check);
106         UxCardMemOut(card->hw, &shared[16], config->handset_type);
107         UxCardMemOut(card->hw, &shared[17], 0);
108         UxCardMemOut(card->hw, &shared[18], config->low_channel);
109         UxCardMemOut(card->hw, &shared[19], config->prot_version);
110         UxCardMemOut(card->hw, &shared[20], config->crc4);
111
112         if ((card->hw->features) && (card->hw->features & PROTCAP_V90D))
113         {
114                 DPRINTF(("divas: Signifying V.90"));
115                 UxCardMemOut(card->hw, &shared[22], 4);
116         }
117         else
118         {
119                 UxCardMemOut(card->hw, &shared[22], 0);
120         }
121
122         for (i=0; i<2; i++)
123         {
124                 for (j=0; j<32; j++)
125                 {
126                         UxCardMemOut(card->hw, &shared[32+(i*96)+j],config->terminal[i].oad[j]);
127                 }
128
129                 for (j=0; j<32; j++)
130                 {
131                         UxCardMemOut(card->hw, &shared[64+(i*96)+j],config->terminal[i].osa[j]);
132                 }
133
134                 for (j=0; j<32; j++)
135                 {
136                         UxCardMemOut(card->hw, &shared[96+(i*96)+j],config->terminal[i].spid[j]);
137                 }
138         }
139
140         UxCardMemDetach(card->hw, shared);
141
142         return 0;
143 }
144
145 static
146 void diva_server_4bri_reset_int(card_t *card)
147 {
148         byte *ctl;
149
150         ctl = UxCardMemAttach(card->hw, DIVAS_CTL_MEMORY);
151
152         UxCardMemOut(card->hw, &ctl[MQ_BREG_IRQ_TEST], MQ_IRQ_REQ_OFF);
153
154         UxCardMemDetach(card->hw, ctl);
155
156         return;
157 }
158
159  
160 static int diva_server_4bri_test_int(card_t *card)
161 {
162         byte *ctl, i;
163         byte *reg;
164
165         DPRINTF(("divas: test interrupt for Diva Server 4BRI"));
166
167         /* We get the last (dummy) adapter in so we need to go back to the first */
168
169         card = get_card(card->cfg.card_id - 3);
170
171         /* Enable interrupts on PLX chip */
172
173         reg = UxCardMemAttach(card->hw, DIVAS_REG_MEMORY);
174
175         UxCardPortIoOut(card->hw, reg, PLX9054_INTCSR, PLX9054_INT_ENA);
176
177         UxCardMemDetach(card->hw, reg);
178
179         /* Set the test interrupt flag */
180         card->test_int_pend = TEST_INT_DIVAS_Q;
181
182         /* Now to trigger the interrupt */
183
184         ctl = UxCardMemAttach(card->hw, DIVAS_CTL_MEMORY);
185
186         UxCardMemOut(card->hw, &ctl[MQ_BREG_IRQ_TEST], MQ_IRQ_REQ_ON);
187
188         UxCardMemDetach(card->hw, ctl);
189
190         for (i = 0; i < 50; i++)
191         {
192                 if (!card->test_int_pend)
193                 {
194                         break;
195                 }
196                 UxPause(10);
197         }
198
199         if (card->test_int_pend)
200         {
201                 DPRINTF(("active: timeout waiting for card to interrupt"));
202                 return (-1);
203         }
204         
205         return 0;
206 }
207
208
209 static void print_hdr(unsigned char *code, int offset)
210 {
211         unsigned char hdr[80];
212         int i;
213
214         i = 0;
215
216         while ((i < (DIM(hdr) -1)) && 
217                 (code[offset + i] != '\0') &&
218                 (code[offset + i] != '\r') &&
219                 (code[offset + i] != '\n'))
220         {
221                 hdr[i] = code[offset + i];
222                 i++;
223         }
224
225         hdr[i] = '\0';
226
227         DPRINTF(("divas: loading %s", hdr));
228 }
229
230 static int diva_server_4bri_load(card_t *card, dia_load_t *load)
231 {
232         byte *pRAM=NULL;
233         int download_offset=0;
234         card_t *FirstCard;
235         byte sw_id[80];
236
237         DPRINTF(("divas: loading Diva Server 4BRI[%d]", load->card_id));
238
239         switch(load->code_type)
240         {
241                 case DIA_CPU_CODE:
242                         DPRINTF(("divas: RISC code"));
243                         print_hdr(load->code, 0x80);
244                         card->hw->features = GetProtFeatureValue((char *)&load->code[0x80]);
245                         download_offset = 0; // Protocol code written to offset 0
246                         pRAM = UxCardMemAttach(card->hw, DIVAS_RAM_MEMORY);
247                         break;
248
249                 case DIA_DSP_CODE:
250                         DPRINTF(("divas: DSP code"));
251                         print_hdr(load->code, 0x0); 
252                         FirstCard = get_card(load->card_id - 3);
253                         if ((card->hw->features) && (card->hw->features & PROTCAP_V90D))
254                         {
255                                 download_offset = MQ_V90D_DSP_CODE_BASE;
256                         }
257                         else
258                         {
259                                 download_offset = MQ_ORG_DSP_CODE_BASE;
260                         }
261                         pRAM = UxCardMemAttach(FirstCard->hw, DIVAS_RAM_MEMORY);
262                         download_offset += (((sizeof(dword) + (sizeof(t_dsp_download_desc)* DSP_MAX_DOWNLOAD_COUNT)) + 3) & 0xFFFFFFFC);
263
264                         break;
265
266                 case DIA_TABLE_CODE:
267                         DPRINTF(("divas: TABLE code"));
268                         FirstCard = get_card(load->card_id - 3);
269                         if ((card->hw->features) && (card->hw->features & PROTCAP_V90D))
270                         {
271                                 download_offset = MQ_V90D_DSP_CODE_BASE + sizeof(dword);
272                         }
273                         else
274                         {
275                                 download_offset = MQ_ORG_DSP_CODE_BASE + sizeof(dword);
276                         }
277                         pRAM = UxCardMemAttach(FirstCard->hw, DIVAS_RAM_MEMORY);
278                         break;
279
280                 case DIA_CONT_CODE:
281                         DPRINTF(("divas: continuation code"));
282                         break;
283
284         case DIA_DLOAD_CNT:
285                         DPRINTF(("divas: COUNT code"));
286                         FirstCard = get_card(load->card_id - 3);
287                         if ((card->hw->features) && (card->hw->features & PROTCAP_V90D))
288                         {
289                                 download_offset = MQ_V90D_DSP_CODE_BASE;
290                         }
291                         else
292                         {
293                                 download_offset = MQ_ORG_DSP_CODE_BASE;
294                         }
295                         pRAM = UxCardMemAttach(FirstCard->hw, DIVAS_RAM_MEMORY);
296                         break;
297
298                 case DIA_FPGA_CODE:
299                         DPRINTF(("divas: 4BRI FPGA download - %d bytes", load->length));
300                         if (FPGA_Download(IDI_ADAPTER_MAESTRAQ,
301                         card->hw->io_base,
302                          sw_id,
303                          load->code,
304                          load->length
305                         ) == -1)
306                         {
307                                 DPRINTF(("divas: FPGA download failed"));
308                                 return -1;
309                         }
310
311                         /* NOW reset the 4BRI */
312                         diva_server_4bri_reset(card);
313                         return 0; // No need for anything further loading
314
315                 default:
316                         DPRINTF(("divas: unknown code type"));
317                         return -1;
318         }
319
320    memcp(pRAM + (download_offset & 0x3FFFFF), load->code, load->length);
321
322         {
323                 int mism_off;
324         if ((mism_off = memcm(pRAM + (download_offset & 0x3FFFFF), load->code, load->length)))
325         {
326                 DPRINTF(("divas: memory mismatch at offset %d", mism_off));
327                 UxCardMemDetach(card->hw, pRAM);
328                 return -1;
329         }
330         }
331
332         UxCardMemDetach(card->hw, pRAM);
333
334         return 0;
335 }
336
337 static int diva_server_4bri_start(card_t *card, byte *channels)
338 {
339         byte *ctl;
340         byte *shared;
341         int i;
342         int adapter_num;
343
344         DPRINTF(("divas: start Diva Server 4BRI"));
345         *channels = 0;
346         card->is_live = FALSE;
347
348         ctl = UxCardMemAttach(card->hw, DIVAS_CTL_MEMORY);
349
350         UxCardMemOutW(card->hw, &ctl[MQ_BREG_RISC], MQ_RISC_COLD_RESET_MASK);
351
352         UxPause(2);
353
354         UxCardMemOutW(card->hw, &ctl[MQ_BREG_RISC], MQ_RISC_WARM_RESET_MASK | MQ_RISC_COLD_RESET_MASK);
355
356         UxPause(10);
357         
358         UxCardMemDetach(card->hw, ctl);
359
360         shared = (byte *) UxCardMemAttach(card->hw, DIVAS_SHARED_MEMORY);
361
362         for ( i = 0 ; i < 300 ; ++i )
363         {
364                 UxPause (10) ;
365
366                 if ( UxCardMemInW(card->hw, &shared[0x1E]) == 0x4447 )
367                 {
368                         DPRINTF(("divas: Protocol startup time %d.%02d seconds",
369                                  (i / 100), (i % 100) ));
370
371                         break;
372                 }
373         }
374
375         if (i==300)
376         {
377                 DPRINTF(("divas: Timeout starting card"));
378                 DPRINTF(("divas: Signature == 0x%04X", UxCardMemInW(card->hw, &shared[0x1E])));
379
380                 UxCardMemDetach(card->hw, shared);
381                 return -1;
382         }
383
384         UxCardMemDetach(card->hw, shared);
385
386         for (adapter_num=3; adapter_num >= 0; adapter_num--)
387         {
388                 card_t *qbri_card;
389
390                 qbri_card = get_card(card->cfg.card_id - adapter_num);
391
392                 if (qbri_card)
393                 {
394                         qbri_card->is_live = TRUE;
395                         shared = UxCardMemAttach(qbri_card->hw, DIVAS_SHARED_MEMORY);
396                         *channels += UxCardMemIn(qbri_card->hw, &shared[0x3F6]);
397                         UxCardMemDetach(qbri_card->hw, shared);
398                 }
399                 else
400                 {
401                         DPRINTF(("divas: Couldn't get card info %d", card->cfg.card_id));
402                 }
403         }
404
405         diva_server_4bri_test_int(card);
406
407         return 0;
408 }
409
410 static
411 int     diva_server_4bri_mem_get(card_t *card, mem_block_t *mem_block)
412
413 {
414         byte    *a;
415         byte    *card_addr;
416         word    length = 0;
417         int             i;
418
419         a = UxCardMemAttach(card->hw, DIVAS_RAM_MEMORY);
420
421         card_addr = a;
422         card_addr += mem_block->addr;
423
424         for (i=0; i < sizeof(mem_block->data); i++)
425         {
426                 mem_block->data[i] = UxCardMemIn(card->hw, card_addr);
427                 card_addr++;
428                 length++;
429         }
430
431         UxCardMemDetach(card->hw, a);
432
433         return length;
434 }
435
436 /*
437  * Initialise 4BRI specific entry points
438  */
439
440 int Divas4BriInit(card_t *card, dia_card_t *cfg)
441 {
442 //      byte sw_id[80];
443 //      extern int FPGA_Done;
444
445         DPRINTF(("divas: initialise Diva Server 4BRI"));
446
447         if (Divas4BRIInitPCI(card, cfg) == -1)
448         {
449                 return -1;
450         }
451
452         /* Need to download the FPGA */
453 /*      if (!FPGA_Done)
454         {
455                 int retVal;
456
457                 retVal=FPGA_Download(IDI_ADAPTER_MAESTRAQ,
458                         cfg->io_base,
459                          sw_id,
460                          FPGA_Bytes
461                         );
462                 if(retVal==-1)
463                 {
464                 
465                         DPRINTF(("divas: FPGA Download Failed"));
466                         return -1;
467
468                 }
469                 FPGA_Done = 1;
470         } */
471
472         card->card_reset = diva_server_4bri_reset;
473         card->card_load = diva_server_4bri_load;
474         card->card_config = diva_server_4bri_config;
475         card->card_start = diva_server_4bri_start;
476         card->reset_int = diva_server_4bri_reset_int;
477         card->card_mem_get = diva_server_4bri_mem_get;
478
479         card->xlog_offset = DIVAS_MAINT_OFFSET;
480
481         card->out = DivasOut;
482         card->test_int = DivasTestInt;
483         card->dpc = DivasDpc;
484         card->clear_int = DivasClearInt;
485         card->card_isr = fourbri_ISR;
486
487         card->a.ram_out = mem_out;
488         card->a.ram_outw = mem_outw;
489         card->a.ram_out_buffer = mem_out_buffer;
490         card->a.ram_inc = mem_inc;
491
492         card->a.ram_in = mem_in;
493         card->a.ram_inw = mem_inw;
494         card->a.ram_in_buffer = mem_in_buffer;
495         card->a.ram_look_ahead = mem_look_ahead;
496
497         return 0;
498 }
499
500 void memcp(byte *dst, byte *src, dword dwLen)
501 {
502         while (dwLen)
503         {
504                 *dst = *src;
505                 dst++; src++;
506                 dwLen--;
507         }
508 }
509
510 int memcm(byte *dst, byte *src, dword dwLen)
511 {
512         int offset = 0;
513
514         while (offset < dwLen)
515         {
516                 if(*dst != *src)
517                         return (offset+1);
518
519                 offset++;
520                 src++;
521                 dst++;
522         }
523
524         return 0;
525 }
526
527
528
529 /*int fourbri_ISR (card_t* card) 
530 {
531         int served = 0;
532         byte *DivasIOBase = UxCardMemAttach(card->hw, DIVAS_IOBASE);
533         
534
535         if (UxCardPortIoIn (card->hw, DivasIOBase, M_PCI_RESET) & 0x01) 
536         {
537                 served = 1;
538                 card->int_pend  += 1;
539                 DivasDpcSchedule(); 
540                 UxCardPortIoOut (card->hw, DivasIOBase, M_PCI_RESET, 0x08);
541         }
542
543         UxCardMemDetach(card->hw, DivasIOBase);
544
545         return (served != 0);
546 }*/
547
548
549 static int fourbri_ISR (card_t* card) 
550 {
551         byte *ctl;
552
553         card->int_pend  += 1;
554         DivasDpcSchedule(); /* ISR DPC */
555
556         ctl = UxCardMemAttach(card->hw, DIVAS_CTL_MEMORY);
557         UxCardMemOut(card->hw, &ctl[MQ_BREG_IRQ_TEST], MQ_IRQ_REQ_OFF);
558         UxCardMemDetach(card->hw, ctl);
559
560         return (1);
561 }