File: /usr/src/linux/drivers/isdn/eicon/pri.c
1
2 /*
3 *
4 * Copyright (C) Eicon Technology Corporation, 2000.
5 *
6 * Eicon File Revision : 1.5
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 PRI 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
33 #include "adapter.h"
34 #include "uxio.h"
35
36 #define DIVAS_LOAD_CMD 0x02
37 #define DIVAS_START_CMD 0x03
38 #define DIVAS_IRQ_RESET 0xC18
39 #define DIVAS_IRQ_RESET_VAL 0xFE
40
41 #define TEST_INT_DIVAS 0x11
42 #define TEST_INT_DIVAS_BRI 0x12
43
44 #define DIVAS_RESET 0x81
45 #define DIVAS_LED1 0x04
46 #define DIVAS_LED2 0x08
47 #define DIVAS_LED3 0x20
48 #define DIVAS_LED4 0x40
49
50 #define DIVAS_RESET_REG 0x20
51
52 #define DIVAS_SIGNATURE 0x4447
53
54 /* offset to start of MAINT area (used by xlog) */
55
56 #define DIVAS_MAINT_OFFSET 0xef00 /* value for PRI card */
57
58 #define MP_PROTOCOL_ADDR 0xA0011000
59 #define MP_DSP_CODE_BASE 0xa03a0000
60
61 typedef struct {
62 dword cmd;
63 dword addr;
64 dword len;
65 dword err;
66 dword live;
67 dword reserved[(0x1020>>2)-6];
68 dword signature;
69 byte data[1];
70 } diva_server_boot_t;
71
72 byte mem_in(ADAPTER *a, void *adr);
73 word mem_inw(ADAPTER *a, void *adr);
74 void mem_in_buffer(ADAPTER *a, void *adr, void *P, word length);
75 void mem_look_ahead(ADAPTER *a, PBUFFER *RBuffer, ENTITY *e);
76 void mem_out(ADAPTER *a, void *adr, byte data);
77 void mem_outw(ADAPTER *a, void *adr, word data);
78 void mem_out_buffer(ADAPTER *a, void *adr, void *P, word length);
79 void mem_inc(ADAPTER *a, void *adr);
80
81 int DivasPRIInitPCI(card_t *card, dia_card_t *cfg);
82 static int pri_ISR (card_t* card);
83
84 static int diva_server_reset(card_t *card)
85 {
86 byte *reg;
87 diva_server_boot_t *boot = NULL;
88 dword live = 0;
89 int i = 0;
90 dword dwWait;
91
92 DPRINTF(("divas: reset Diva Server PRI"));
93
94 reg = UxCardMemAttach(card->hw, DIVAS_REG_MEMORY);
95
96 UxCardMemOut(card->hw, ®[DIVAS_RESET_REG], DIVAS_RESET |
97 DIVAS_LED1 | DIVAS_LED2 | DIVAS_LED3 | DIVAS_LED4);
98
99 for (dwWait = 0x000fffff; dwWait; dwWait--)
100 ;
101
102 UxCardMemOut(card->hw, ®[DIVAS_RESET_REG], 0x00);
103
104 for (dwWait = 0x000fffff; dwWait; dwWait--)
105 ;
106
107 UxCardMemDetach(card->hw, reg);
108
109 boot = UxCardMemAttach(card->hw, DIVAS_RAM_MEMORY);
110
111 UxCardMemOutD(card->hw, boot->reserved, 0);
112
113 live = UxCardMemInD(card->hw, &boot->live);
114
115 for (i=0; i<5; i++)
116 {
117 if (live != UxCardMemInD(card->hw, &boot->live))
118 {
119 break;
120 }
121 UxPause(10);
122 }
123
124 if (i == 5)
125 {
126 UxCardMemDetach(card->hw, boot);
127
128 DPRINTF(("divas: card is reset but CPU not running"));
129 return -1;
130 }
131
132 UxCardMemDetach(card->hw, boot);
133
134 DPRINTF(("divas: card reset after %d ms", i * 10));
135
136 return 0;
137 }
138
139 static int diva_server_config(card_t *card, dia_config_t *config)
140 {
141 byte *shared;
142 int i, j;
143
144 DPRINTF(("divas: configure Diva Server PRI"));
145
146 shared = UxCardMemAttach(card->hw, DIVAS_SHARED_MEMORY);
147
148 UxCardLog(0);
149 for (i=0; i<256; i++)
150 {
151 UxCardMemOut(card->hw, &shared[i], 0);
152 }
153
154 UxCardMemOut(card->hw, &shared[ 8], config->tei);
155 UxCardMemOut(card->hw, &shared[ 9], config->nt2);
156 UxCardMemOut(card->hw, &shared[10], config->sig_flags);
157 UxCardMemOut(card->hw, &shared[11], config->watchdog);
158 UxCardMemOut(card->hw, &shared[12], config->permanent);
159 UxCardMemOut(card->hw, &shared[13], config->x_interface);
160 UxCardMemOut(card->hw, &shared[14], config->stable_l2);
161 UxCardMemOut(card->hw, &shared[15], config->no_order_check);
162 UxCardMemOut(card->hw, &shared[16], config->handset_type);
163 UxCardMemOut(card->hw, &shared[17], 0);
164 UxCardMemOut(card->hw, &shared[18], config->low_channel);
165 UxCardMemOut(card->hw, &shared[19], config->prot_version);
166 UxCardMemOut(card->hw, &shared[20], config->crc4);
167
168 for (i=0; i<2; i++)
169 {
170 for (j=0; j<32; j++)
171 {
172 UxCardMemOut(card->hw, &shared[32+(i*96)+j],config->terminal[i].oad[j]);
173 }
174
175 for (j=0; j<32; j++)
176 {
177 UxCardMemOut(card->hw, &shared[64+(i*96)+j],config->terminal[i].osa[j]);
178 }
179
180 for (j=0; j<32; j++)
181 {
182 UxCardMemOut(card->hw, &shared[96+(i*96)+j],config->terminal[i].spid[j]);
183 }
184 }
185
186 UxCardMemDetach(card->hw, shared);
187
188 return 0;
189 }
190
191 static
192 void diva_server_reset_int(card_t *card)
193 {
194 byte *cfg;
195
196 cfg = UxCardMemAttach(card->hw, DIVAS_CFG_MEMORY);
197
198 UxCardMemOutW(card->hw, &cfg[DIVAS_IRQ_RESET], DIVAS_IRQ_RESET_VAL);
199 UxCardMemOutW(card->hw, &cfg[DIVAS_IRQ_RESET + 2], 0);
200 UxCardMemDetach(card->hw, cfg);
201
202 return;
203 }
204
205
206 static int diva_server_test_int(card_t *card)
207 {
208 int i;
209 byte *shared;
210 byte req_int;
211
212 DPRINTF(("divas: test interrupt for Diva Server PRI"));
213
214 shared = UxCardMemAttach(card->hw, DIVAS_SHARED_MEMORY);
215
216 UxCardMemIn(card->hw, &shared[0x3FE]);
217 UxCardMemOut(card->hw, &shared[0x3FE], 0);
218 UxCardMemIn(card->hw, &shared[0x3FE]);
219
220 UxCardMemDetach(card->hw, shared);
221
222 diva_server_reset_int(card);
223
224 shared = UxCardMemAttach(card->hw, DIVAS_SHARED_MEMORY);
225
226 card->test_int_pend = TEST_INT_DIVAS;
227
228 req_int = UxCardMemIn(card->hw, &(((struct pr_ram *)shared)->ReadyInt));
229
230 req_int++;
231
232 UxCardMemOut(card->hw, &(((struct pr_ram *)shared)->ReadyInt), req_int);
233
234 UxCardMemDetach(card->hw, shared);
235
236 UxCardLog(0);
237 for (i = 0; i < 50; i++)
238 {
239 if (!card->test_int_pend)
240 {
241 break;
242 }
243 UxPause(10);
244 }
245
246
247 if (card->test_int_pend)
248 {
249
250 DPRINTF(("active: timeout waiting for card to interrupt"));
251 return (-1);
252
253 }
254
255 return 0;
256 }
257
258
259 static void print_hdr(unsigned char *code, int offset)
260 {
261 unsigned char hdr[80];
262 int i;
263
264 i = 0;
265
266 while ((i < (DIM(hdr) -1)) &&
267 (code[offset + i] != '\0') &&
268 (code[offset + i] != '\r') &&
269 (code[offset + i] != '\n'))
270 {
271 hdr[i] = code[offset + i];
272 i++;
273 }
274
275 hdr[i] = '\0';
276
277 DPRINTF(("divas: loading %s", hdr));
278 }
279
280 static int diva_server_load(card_t *card, dia_load_t *load)
281 {
282 diva_server_boot_t *boot;
283 int i, offset, length;
284 dword cmd = 0;
285
286 DPRINTF(("divas: loading Diva Server PRI"));
287
288 boot = UxCardMemAttach(card->hw, DIVAS_RAM_MEMORY);
289
290 switch(load->code_type)
291 {
292 case DIA_CPU_CODE:
293 DPRINTF(("divas: RISC code"));
294 print_hdr(load->code, 0x80);
295
296 UxCardMemOutD(card->hw, &boot->addr, MP_PROTOCOL_ADDR);
297 break;
298
299 case DIA_DSP_CODE:
300 DPRINTF(("divas: DSP code"));
301 print_hdr(load->code, 0x0);
302
303 UxCardMemOutD(card->hw, &boot->addr,
304 (MP_DSP_CODE_BASE + (((sizeof(dword) +
305 (sizeof(t_dsp_download_desc) * DSP_MAX_DOWNLOAD_COUNT))
306 + ~ALIGNMENT_MASK_MAESTRA) & ALIGNMENT_MASK_MAESTRA)));
307 break;
308
309 case DIA_TABLE_CODE:
310 DPRINTF(("divas: TABLE code"));
311 UxCardMemOutD(card->hw, &boot->addr,
312 (MP_DSP_CODE_BASE + sizeof(dword)));
313 break;
314
315 case DIA_CONT_CODE:
316 DPRINTF(("divas: continuation code"));
317 break;
318
319 case DIA_DLOAD_CNT:
320 DPRINTF(("divas: COUNT code"));
321 UxCardMemOutD(card->hw, &boot->addr, MP_DSP_CODE_BASE);
322 break;
323
324 default:
325 DPRINTF(("divas: unknown code type"));
326 UxCardMemDetach(card->hw, boot);
327 return -1;
328 }
329
330 UxCardLog(0);
331 offset = 0;
332
333 do
334 {
335 length = (load->length - offset >= 400) ? 400 : load->length - offset;
336
337 for (i=0; i<length; i++)
338 {
339 UxCardMemOut(card->hw, &boot->data[i], load->code[offset+i]);
340 }
341
342 for (i=0; i<length; i++)
343 {
344 if (load->code[offset + i] != UxCardMemIn(card->hw, &boot->data[i]))
345 {
346 UxCardMemDetach(card->hw, boot);
347
348 DPRINTF(("divas: card code block verify failed"));
349 return -1;
350 }
351 }
352
353 UxCardMemOutD(card->hw, &boot->len, (length + 3) / 4);
354 UxCardMemOutD(card->hw, &boot->cmd, DIVAS_LOAD_CMD);
355
356 for (i=0; i<50000; i++)
357 {
358 cmd = UxCardMemInD(card->hw, &boot->cmd);
359 if (!cmd)
360 {
361 break;
362 }
363 /*UxPause(1);*/
364 }
365
366 if (cmd)
367 {
368 DPRINTF(("divas: timeout waiting for card to ACK load (offset = %d)", offset));
369 UxCardMemDetach(card->hw, boot);
370 return -1;
371 }
372
373 offset += length;
374
375 } while (offset < load->length);
376
377 UxCardMemDetach(card->hw, boot);
378
379 DPRINTF(("divas: DIVA Server card loaded"));
380
381 return 0;
382 }
383
384 static int diva_server_start(card_t *card, byte *channels)
385 {
386 diva_server_boot_t *boot;
387 byte *ram;
388 int i;
389 dword signature = 0;
390
391 DPRINTF(("divas: start Diva Server PRI"));
392
393 card->is_live = FALSE;
394
395 boot = UxCardMemAttach(card->hw, DIVAS_RAM_MEMORY);
396
397 UxCardMemOutD(card->hw, &boot->addr, MP_PROTOCOL_ADDR);
398 UxCardMemOutD(card->hw, &boot->cmd, DIVAS_START_CMD);
399
400 UxCardLog(0);
401
402 for (i = 0; i < 300; i++)
403 {
404 signature = UxCardMemInD(card->hw, &boot->signature);
405 if ((signature >> 16) == DIVAS_SIGNATURE)
406 {
407 DPRINTF(("divas: started card after %d ms", i * 10));
408 break;
409 }
410 UxPause(10);
411 }
412
413 if ((signature >> 16) != DIVAS_SIGNATURE)
414 {
415 UxCardMemDetach(card->hw, boot);
416 DPRINTF(("divas: timeout waiting for card to run protocol code (sig = 0x%x)", signature));
417 return -1;
418 }
419
420 card->is_live = TRUE;
421
422 ram = (byte *) boot;
423 ram += DIVAS_SHARED_OFFSET;
424
425 *channels = UxCardMemIn(card->hw, &ram[0x3F6]);
426 card->serial_no = UxCardMemInD(card->hw, &ram[0x3F0]);
427
428 UxCardMemDetach(card->hw, boot);
429
430 if (diva_server_test_int(card))
431 {
432 DPRINTF(("divas: interrupt test failed"));
433 return -1;
434 }
435
436 DPRINTF(("divas: DIVA Server card started"));
437
438 return 0;
439 }
440
441 static
442 int diva_server_mem_get(card_t *card, mem_block_t *mem_block)
443
444 {
445 byte *a;
446 byte *card_addr;
447 word length = 0;
448 int i;
449
450 a = UxCardMemAttach(card->hw, DIVAS_RAM_MEMORY);
451
452 card_addr = a;
453 card_addr += mem_block->addr;
454
455 for (i=0; i < sizeof(mem_block->data); i++)
456 {
457 mem_block->data[i] = UxCardMemIn(card->hw, card_addr);
458 card_addr++;
459 length++;
460 }
461
462 UxCardMemDetach(card->hw, a);
463
464 return length;
465 }
466
467 /*
468 * Initialise PRI specific entry points
469 */
470
471 int DivasPriInit(card_t *card, dia_card_t *cfg)
472 {
473 DPRINTF(("divas: initialise Diva Server PRI"));
474
475 if (DivasPRIInitPCI(card, cfg) == -1)
476 {
477 return -1;
478 }
479
480 card->card_reset = diva_server_reset;
481 card->card_load = diva_server_load;
482 card->card_config = diva_server_config;
483 card->card_start = diva_server_start;
484 card->reset_int = diva_server_reset_int;
485 card->card_mem_get = diva_server_mem_get;
486
487 card->xlog_offset = DIVAS_MAINT_OFFSET;
488
489 card->out = DivasOut;
490 card->test_int = DivasTestInt;
491 card->dpc = DivasDpc;
492 card->clear_int = DivasClearInt;
493 card->card_isr = pri_ISR;
494
495 card->a.ram_out = mem_out;
496 card->a.ram_outw = mem_outw;
497 card->a.ram_out_buffer = mem_out_buffer;
498 card->a.ram_inc = mem_inc;
499
500 card->a.ram_in = mem_in;
501 card->a.ram_inw = mem_inw;
502 card->a.ram_in_buffer = mem_in_buffer;
503 card->a.ram_look_ahead = mem_look_ahead;
504
505 return 0;
506 }
507
508
509 static int pri_ISR (card_t* card)
510 {
511 int served = 0;
512 byte* cfg = UxCardMemAttach(card->hw, DIVAS_CFG_MEMORY);
513 volatile unsigned long* isr = (unsigned long*)&cfg[DIVAS_IRQ_RESET];
514 register unsigned long val = *isr;
515
516 if (val & 0x80000000) /* our card had caused interrupt ??? */
517 {
518 served = 1;
519 card->int_pend += 1;
520 DivasDpcSchedule(); /* ISR DPC */
521
522 *isr = (unsigned long)~0x03E00000; /* Clear interrupt line */
523 }
524
525 UxCardMemDetach(card->hw, cfg);
526
527 return (served != 0);
528 }
529
530
531