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