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