include upstream ip1000a driver version 2.09f
[linux-2.4.git] / drivers / isdn / eicon / pri.c
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
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, &reg[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, &reg[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
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
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  
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
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
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
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
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
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
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