4 Copyright (c) Eicon Networks, 2002.
6 This source file is supplied for the use with
7 Eicon Networks range of DIVA Server Adapters.
9 Eicon File Revision : 2.1
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 2, or (at your option)
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
18 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19 See the GNU General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
38 /*****************************************************************************/
39 #define MAX_XLOG_SIZE (64 * 1024)
40 /* -------------------------------------------------------------------------
41 Does return offset between ADAPTER->ram and real begin of memory
42 ------------------------------------------------------------------------- */
43 static dword pri_ram_offset (ADAPTER* a) {
44 return ((dword)MP_SHARED_RAM_OFFSET);
46 /* -------------------------------------------------------------------------
47 Recovery XLOG buffer from the card
48 ------------------------------------------------------------------------- */
49 static void pri_cpu_trapped (PISDN_ADAPTER IoAdapter) {
52 dword regs[4], TrapID, size ;
55 * check for trapped MIPS 46xx CPU, dump exception frame
57 base = DIVA_OS_MEM_ATTACH_ADDRESS(IoAdapter);
58 TrapID = READ_DWORD(&base[0x80]) ;
59 if ( (TrapID == 0x99999999) || (TrapID == 0x99999901) )
61 dump_trap_frame (IoAdapter, &base[0x90]) ;
62 IoAdapter->trapped = 1 ;
64 regs[0] = READ_DWORD(&base[MP_PROTOCOL_OFFSET + 0x70]);
65 regs[1] = READ_DWORD(&base[MP_PROTOCOL_OFFSET + 0x74]);
66 regs[2] = READ_DWORD(&base[MP_PROTOCOL_OFFSET + 0x78]);
67 regs[3] = READ_DWORD(&base[MP_PROTOCOL_OFFSET + 0x7c]);
68 regs[0] &= IoAdapter->MemorySize - 1 ;
69 if ( (regs[0] < IoAdapter->MemorySize - 1) )
71 if ( !(Xlog = (word *)diva_os_malloc (0, MAX_XLOG_SIZE)) ) {
72 DIVA_OS_MEM_DETACH_ADDRESS(IoAdapter, base);
75 size = IoAdapter->MemorySize - regs[0] ;
76 if ( size > MAX_XLOG_SIZE )
77 size = MAX_XLOG_SIZE ;
78 memcpy (Xlog, &base[regs[0]], size) ;
80 xlogDesc.cnt = READ_WORD(&base[regs[1] & (IoAdapter->MemorySize - 1)]) ;
81 xlogDesc.out = READ_WORD(&base[regs[2] & (IoAdapter->MemorySize - 1)]) ;
82 dump_xlog_buffer (IoAdapter, &xlogDesc) ;
83 diva_os_free (0, Xlog) ;
84 IoAdapter->trapped = 2 ;
86 DIVA_OS_MEM_DETACH_ADDRESS(IoAdapter, base);
88 /* -------------------------------------------------------------------------
89 Hardware reset of PRI card
90 ------------------------------------------------------------------------- */
91 static void reset_pri_hardware (PISDN_ADAPTER IoAdapter) {
92 byte *p = DIVA_OS_MEM_ATTACH_RESET(IoAdapter);
93 *p = _MP_RISC_RESET | _MP_LED1 | _MP_LED2 ;
97 DIVA_OS_MEM_DETACH_RESET(IoAdapter, p);
99 /* -------------------------------------------------------------------------
101 ------------------------------------------------------------------------- */
102 static void stop_pri_hardware (PISDN_ADAPTER IoAdapter) {
105 dword volatile *cfgReg = (dword volatile *)DIVA_OS_MEM_ATTACH_CFG(IoAdapter);
106 cfgReg[3] = 0x00000000 ;
107 cfgReg[1] = 0x00000000 ;
108 DIVA_OS_MEM_DETACH_CFG(IoAdapter, cfgReg);
109 IoAdapter->a.ram_out (&IoAdapter->a, &RAM->SWReg, SWREG_HALT_CPU) ;
111 while ( (i < 100) && (IoAdapter->a.ram_in (&IoAdapter->a, &RAM->SWReg) != 0) )
116 DBG_TRC(("%s: PRI stopped (%d)", IoAdapter->Name, i))
117 cfgReg = (dword volatile *)DIVA_OS_MEM_ATTACH_CFG(IoAdapter);
118 WRITE_DWORD(&cfgReg[0],((dword)(~0x03E00000)));
119 DIVA_OS_MEM_DETACH_CFG(IoAdapter, cfgReg);
121 p = DIVA_OS_MEM_ATTACH_RESET(IoAdapter);
122 *p = _MP_RISC_RESET | _MP_LED1 | _MP_LED2 ;
123 DIVA_OS_MEM_DETACH_RESET(IoAdapter, p);
125 #if !defined(DIVA_USER_MODE_CARD_CONFIG) /* { */
126 /* -------------------------------------------------------------------------
127 Load protocol code to the PRI Card
128 ------------------------------------------------------------------------- */
129 #define DOWNLOAD_ADDR(IoAdapter) (IoAdapter->downloadAddr & (IoAdapter->MemorySize - 1))
130 static int pri_protocol_load (PISDN_ADAPTER IoAdapter) {
136 if (!(File = (dword *)xdiLoadArchive (IoAdapter, &FileLength, 0))) {
139 IoAdapter->features = diva_get_protocol_file_features ((byte*)File,
140 OFFS_PROTOCOL_ID_STRING,
141 IoAdapter->ProtocolIdString,
142 sizeof(IoAdapter->ProtocolIdString)) ;
143 IoAdapter->a.protocol_capabilities = IoAdapter->features ;
144 DBG_LOG(("Loading %s", IoAdapter->ProtocolIdString))
145 Addr = ((dword)(((byte *) File)[OFFS_PROTOCOL_END_ADDR]))
146 | (((dword)(((byte *) File)[OFFS_PROTOCOL_END_ADDR + 1])) << 8)
147 | (((dword)(((byte *) File)[OFFS_PROTOCOL_END_ADDR + 2])) << 16)
148 | (((dword)(((byte *) File)[OFFS_PROTOCOL_END_ADDR + 3])) << 24) ;
151 IoAdapter->DspCodeBaseAddr = (Addr + 3) & (~3) ;
152 IoAdapter->MaxDspCodeSize = (MP_UNCACHED_ADDR (IoAdapter->MemorySize)
153 - IoAdapter->DspCodeBaseAddr) & (IoAdapter->MemorySize - 1) ;
154 Addr = IoAdapter->DspCodeBaseAddr ;
155 ((byte *) File)[OFFS_DSP_CODE_BASE_ADDR] = (byte) Addr ;
156 ((byte *) File)[OFFS_DSP_CODE_BASE_ADDR + 1] = (byte)(Addr >> 8) ;
157 ((byte *) File)[OFFS_DSP_CODE_BASE_ADDR + 2] = (byte)(Addr >> 16) ;
158 ((byte *) File)[OFFS_DSP_CODE_BASE_ADDR + 3] = (byte)(Addr >> 24) ;
159 IoAdapter->InitialDspInfo = 0x80 ;
163 if ( IoAdapter->features & PROTCAP_VOIP )
164 IoAdapter->MaxDspCodeSize = MP_VOIP_MAX_DSP_CODE_SIZE ;
165 else if ( IoAdapter->features & PROTCAP_V90D )
166 IoAdapter->MaxDspCodeSize = MP_V90D_MAX_DSP_CODE_SIZE ;
168 IoAdapter->MaxDspCodeSize = MP_ORG_MAX_DSP_CODE_SIZE ;
169 IoAdapter->DspCodeBaseAddr = MP_CACHED_ADDR (IoAdapter->MemorySize -
170 IoAdapter->MaxDspCodeSize) ;
171 IoAdapter->InitialDspInfo = (IoAdapter->MaxDspCodeSize
172 - MP_ORG_MAX_DSP_CODE_SIZE) >> 14 ;
174 DBG_LOG(("DSP code base 0x%08lx, max size 0x%08lx (%08lx,%02x)",
175 IoAdapter->DspCodeBaseAddr, IoAdapter->MaxDspCodeSize,
176 Addr, IoAdapter->InitialDspInfo))
177 if ( FileLength > ((IoAdapter->DspCodeBaseAddr -
178 MP_CACHED_ADDR (MP_PROTOCOL_OFFSET)) & (IoAdapter->MemorySize - 1)) )
181 DBG_FTL(("Protocol code '%s' too long (%ld)",
182 &IoAdapter->Protocol[0], FileLength))
185 IoAdapter->downloadAddr = MP_UNCACHED_ADDR (MP_PROTOCOL_OFFSET) ;
186 p = DIVA_OS_MEM_ATTACH_RAM(IoAdapter);
187 sharedRam = (dword *)(&p[DOWNLOAD_ADDR(IoAdapter)]);
188 memcpy (sharedRam, File, FileLength) ;
189 if ( memcmp (sharedRam, File, FileLength) )
191 DIVA_OS_MEM_DETACH_RAM(IoAdapter, p);
192 DBG_FTL(("%s: Memory test failed!", IoAdapter->Properties.Name))
196 DIVA_OS_MEM_DETACH_RAM(IoAdapter, p);
200 /******************************************************************************/
201 /*------------------------------------------------------------------
202 Dsp related definitions
203 ------------------------------------------------------------------ */
204 #define DSP_SIGNATURE_PROBE_WORD 0x5a5a
206 ** Checks presence of DSP on board
209 dsp_check_presence (volatile byte* addr, volatile byte* data, int dsp)
212 *(volatile word*)addr = 0x4000;
213 *(volatile word*)data = DSP_SIGNATURE_PROBE_WORD;
214 *(volatile word*)addr = 0x4000;
215 pattern = *(volatile word*)data;
216 if (pattern != DSP_SIGNATURE_PROBE_WORD) {
217 DBG_TRC(("W: DSP[%d] %04x(is) != %04x(should)",
218 dsp, pattern, DSP_SIGNATURE_PROBE_WORD))
221 *(volatile word*)addr = 0x4000;
222 *(volatile word*)data = ~DSP_SIGNATURE_PROBE_WORD;
223 *(volatile word*)addr = 0x4000;
224 pattern = *(volatile word*)data;
225 if (pattern != (word)~DSP_SIGNATURE_PROBE_WORD) {
226 DBG_ERR(("A: DSP[%d] %04x(is) != %04x(should)",
227 dsp, pattern, (word)~DSP_SIGNATURE_PROBE_WORD))
230 DBG_TRC (("DSP[%d] present", dsp))
234 ** Check if DSP's are present and operating
235 ** Information about detected DSP's is returned as bit mask
243 diva_pri_detect_dsps (PISDN_ADAPTER IoAdapter)
247 dword ret = 0, DspCount = 0 ;
248 dword row_offset[] = {
250 0x00000800, /* 1 - ROW 1 */
251 0x00000840, /* 2 - ROW 2 */
252 0x00001000, /* 3 - ROW 3 */
253 0x00001040, /* 4 - ROW 4 */
254 0x00000000 /* 5 - ROW 0 */
256 byte *dsp_addr_port, *dsp_data_port, row_state;
257 int dsp_row = 0, dsp_index, dsp_num;
258 IoAdapter->InitialDspInfo &= 0xffff ;
259 p = DIVA_OS_MEM_ATTACH_RESET(IoAdapter);
262 DIVA_OS_MEM_DETACH_RESET(IoAdapter, p);
265 *(volatile byte*)(p) = _MP_RISC_RESET | _MP_DSP_RESET;
266 DIVA_OS_MEM_DETACH_RESET(IoAdapter, p);
269 base = DIVA_OS_MEM_ATTACH_CONTROL(IoAdapter);
271 for (dsp_num = 0; dsp_num < 30; dsp_num++) {
272 dsp_row = dsp_num / 7 + 1;
273 dsp_index = dsp_num % 7;
274 dsp_data_port = base;
275 dsp_addr_port = base;
276 dsp_data_port += row_offset[dsp_row];
277 dsp_addr_port += row_offset[dsp_row];
278 dsp_data_port += (dsp_index * 8);
279 dsp_addr_port += (dsp_index * 8) + 0x80;
280 if (!dsp_check_presence (dsp_addr_port, dsp_data_port, dsp_num+1)) {
281 ret |= (1 << dsp_num);
285 DIVA_OS_MEM_DETACH_CONTROL(IoAdapter, base);
287 p = DIVA_OS_MEM_ATTACH_RESET(IoAdapter);
288 *(volatile byte*)(p) = _MP_RISC_RESET | _MP_LED1 | _MP_LED2;
293 for (dsp_row = 0; dsp_row < 4; dsp_row++) {
294 row_state = (byte)((ret >> (dsp_row*7)) & 0x7F);
295 if (row_state && (row_state != 0x7F)) {
296 for (dsp_index = 0; dsp_index < 7; dsp_index++) {
297 if (!(row_state & (1 << dsp_index))) {
298 DBG_ERR (("A: MODULE[%d]-DSP[%d] failed", dsp_row+1, dsp_index+1))
303 if (!(ret & 0x10000000)) {
304 DBG_ERR (("A: ON BOARD-DSP[1] failed"))
306 if (!(ret & 0x20000000)) {
307 DBG_ERR (("A: ON BOARD-DSP[2] failed"))
310 Print module population now
312 DBG_LOG(("+-----------------------+"))
313 DBG_LOG(("| DSP MODULE POPULATION |"))
314 DBG_LOG(("+-----------------------+"))
315 DBG_LOG(("| 1 | 2 | 3 | 4 |"))
316 DBG_LOG(("+-----------------------+"))
317 DBG_LOG(("| %s | %s | %s | %s |",
318 ((ret >> (0*7)) & 0x7F) ? "Y" : "N",
319 ((ret >> (1*7)) & 0x7F) ? "Y" : "N",
320 ((ret >> (2*7)) & 0x7F) ? "Y" : "N",
321 ((ret >> (3*7)) & 0x7F) ? "Y" : "N"))
322 DBG_LOG(("+-----------------------+"))
323 DBG_LOG(("DSP's(present-absent):%08x-%08x", ret, ~ret & 0x3fffffff))
324 *(volatile byte*)(p) = 0 ;
325 DIVA_OS_MEM_DETACH_RESET(IoAdapter, p);
327 IoAdapter->InitialDspInfo |= DspCount << 16 ;
330 /* -------------------------------------------------------------------------
331 helper used to download dsp code toi PRI Card
332 ------------------------------------------------------------------------- */
333 static long pri_download_buffer (OsFileHandle *fp, long length, void **addr) {
334 PISDN_ADAPTER IoAdapter = (PISDN_ADAPTER)fp->sysLoadDesc ;
337 *addr = (void *)IoAdapter->downloadAddr ;
338 if ( ((dword) length) > IoAdapter->DspCodeBaseAddr +
339 IoAdapter->MaxDspCodeSize - IoAdapter->downloadAddr )
341 DBG_FTL(("%s: out of card memory during DSP download (0x%X)",
342 IoAdapter->Properties.Name,
343 IoAdapter->downloadAddr + length))
346 p = DIVA_OS_MEM_ATTACH_RAM(IoAdapter);
347 sharedRam = (dword *)(&p[DOWNLOAD_ADDR(IoAdapter)]);
348 if ( fp->sysFileRead (fp, sharedRam, length) != length ) {
349 DIVA_OS_MEM_DETACH_RAM(IoAdapter, p);
352 IoAdapter->downloadAddr += length ;
353 IoAdapter->downloadAddr = (IoAdapter->downloadAddr + 3) & (~3) ;
354 DIVA_OS_MEM_DETACH_RAM(IoAdapter, p);
357 /* -------------------------------------------------------------------------
358 Download DSP code to PRI Card
359 ------------------------------------------------------------------------- */
360 static dword pri_telindus_load (PISDN_ADAPTER IoAdapter) {
363 t_dsp_portable_desc download_table[DSP_MAX_DOWNLOAD_COUNT] ;
364 word download_count ;
368 if ( !(fp = OsOpenFile (DSP_TELINDUS_FILE)) )
370 IoAdapter->downloadAddr = (IoAdapter->DspCodeBaseAddr
371 + sizeof(dword) + sizeof(download_table) + 3) & (~3) ;
372 FileLength = fp->sysFileSize ;
373 fp->sysLoadDesc = (void *)IoAdapter ;
374 fp->sysCardLoad = pri_download_buffer ;
375 download_count = DSP_MAX_DOWNLOAD_COUNT ;
376 memset (&download_table[0], '\0', sizeof(download_table)) ;
378 * set start address for download (use autoincrement mode !)
380 error = dsp_read_file (fp, (word)(IoAdapter->cardType),
381 &download_count, NULL, &download_table[0]) ;
384 DBG_FTL(("download file error: %s", error))
390 * store # of separate download files extracted from archive
392 IoAdapter->downloadAddr = IoAdapter->DspCodeBaseAddr ;
393 p = DIVA_OS_MEM_ATTACH_RAM(IoAdapter);
394 sharedRam = (dword *)(&p[DOWNLOAD_ADDR(IoAdapter)]);
395 WRITE_DWORD(&(sharedRam[0]), (dword)download_count);
396 memcpy (&sharedRam[1], &download_table[0], sizeof(download_table)) ;
397 DIVA_OS_MEM_DETACH_RAM(IoAdapter, p);
398 return (FileLength) ;
400 /* -------------------------------------------------------------------------
402 ------------------------------------------------------------------------- */
403 #define MIN_DSPS 0x30000000
404 static int load_pri_hardware (PISDN_ADAPTER IoAdapter) {
406 struct mp_load *boot = (struct mp_load *)DIVA_OS_MEM_ATTACH_RAM(IoAdapter);
407 if ( IoAdapter->Properties.Card != CARD_MAEP ) {
408 DIVA_OS_MEM_DETACH_RAM(IoAdapter, boot);
413 IoAdapter->rstFnc (IoAdapter) ;
415 if ( MIN_DSPS != (MIN_DSPS & diva_pri_detect_dsps(IoAdapter)) ) { /* makes reset */
416 DIVA_OS_MEM_DETACH_RAM(IoAdapter, boot);
417 DBG_FTL(("%s: DSP error!", IoAdapter->Properties.Name))
422 * check if CPU is alive
427 if ( i == boot->live )
429 DIVA_OS_MEM_DETACH_RAM(IoAdapter, boot);
430 DBG_FTL(("%s: CPU is not alive!", IoAdapter->Properties.Name))
435 DIVA_OS_MEM_DETACH_RAM(IoAdapter, boot);
436 DBG_FTL(("%s: Board Selftest failed!", IoAdapter->Properties.Name))
440 * download protocol and dsp files
442 if ( !xdiSetProtocol (IoAdapter, IoAdapter->ProtocolSuffix) ) {
443 DIVA_OS_MEM_DETACH_RAM(IoAdapter, boot);
446 if ( !pri_protocol_load (IoAdapter) ) {
447 DIVA_OS_MEM_DETACH_RAM(IoAdapter, boot);
450 if ( !pri_telindus_load (IoAdapter) ) {
451 DIVA_OS_MEM_DETACH_RAM(IoAdapter, boot);
455 * copy configuration parameters
457 IoAdapter->ram += MP_SHARED_RAM_OFFSET ;
458 memset (boot + MP_SHARED_RAM_OFFSET, '\0', 256) ;
459 diva_configure_protocol (IoAdapter);
463 boot->addr = MP_UNCACHED_ADDR (MP_PROTOCOL_OFFSET) ;
466 * wait for signature in shared memory (max. 3 seconds)
468 for ( i = 0 ; i < 300 ; ++i )
471 if ( (boot->signature >> 16) == 0x4447 )
473 DIVA_OS_MEM_DETACH_RAM(IoAdapter, boot);
474 DBG_TRC(("Protocol startup time %d.%02d seconds",
475 (i / 100), (i % 100) ))
479 DIVA_OS_MEM_DETACH_RAM(IoAdapter, boot);
480 DBG_FTL(("%s: Adapter selftest failed (0x%04X)!",
481 IoAdapter->Properties.Name, boot->signature >> 16))
482 pri_cpu_trapped (IoAdapter) ;
486 static int load_pri_hardware (PISDN_ADAPTER IoAdapter) {
490 /* --------------------------------------------------------------------------
491 PRI Adapter interrupt Service Routine
492 -------------------------------------------------------------------------- */
493 static int pri_ISR (struct _ISDN_ADAPTER* IoAdapter) {
494 byte *cfg = DIVA_OS_MEM_ATTACH_CFG(IoAdapter);
495 if ( !((READ_DWORD((dword *)cfg)) & 0x80000000) ) {
496 DIVA_OS_MEM_DETACH_CFG(IoAdapter, cfg);
502 WRITE_DWORD(((dword *)cfg), (dword)~0x03E00000) ;
503 DIVA_OS_MEM_DETACH_CFG(IoAdapter, cfg);
504 IoAdapter->IrqCount++ ;
505 if ( IoAdapter->Initialized )
507 diva_os_schedule_soft_isr (&IoAdapter->isr_soft_isr);
511 /* -------------------------------------------------------------------------
512 Disable interrupt in the card hardware
513 ------------------------------------------------------------------------- */
514 static void disable_pri_interrupt (PISDN_ADAPTER IoAdapter) {
515 dword volatile *cfgReg = (dword volatile *)DIVA_OS_MEM_ATTACH_CFG(IoAdapter) ;
516 cfgReg[3] = 0x00000000 ;
517 cfgReg[1] = 0x00000000 ;
518 WRITE_DWORD(&cfgReg[0], (dword)(~0x03E00000)) ;
519 DIVA_OS_MEM_DETACH_CFG(IoAdapter, cfgReg);
521 /* -------------------------------------------------------------------------
522 Install entry points for PRI Adapter
523 ------------------------------------------------------------------------- */
524 static void prepare_common_pri_functions (PISDN_ADAPTER IoAdapter) {
525 ADAPTER *a = &IoAdapter->a ;
527 a->ram_inw = mem_inw ;
528 a->ram_in_buffer = mem_in_buffer ;
529 a->ram_look_ahead = mem_look_ahead ;
530 a->ram_out = mem_out ;
531 a->ram_outw = mem_outw ;
532 a->ram_out_buffer = mem_out_buffer ;
533 a->ram_inc = mem_inc ;
534 a->ram_offset = pri_ram_offset ;
535 a->ram_out_dw = mem_out_dw;
536 a->ram_in_dw = mem_in_dw;
537 a->istream_wakeup = pr_stream;
538 IoAdapter->out = pr_out ;
539 IoAdapter->dpc = pr_dpc ;
540 IoAdapter->tst_irq = scom_test_int ;
541 IoAdapter->clr_irq = scom_clear_int ;
542 IoAdapter->pcm = (struct pc_maint *)(MIPS_MAINT_OFFS
543 - MP_SHARED_RAM_OFFSET) ;
544 IoAdapter->load = load_pri_hardware ;
545 IoAdapter->disIrq = disable_pri_interrupt ;
546 IoAdapter->rstFnc = reset_pri_hardware ;
547 IoAdapter->stop = stop_pri_hardware ;
548 IoAdapter->trapFnc = pri_cpu_trapped ;
549 IoAdapter->diva_isr_handler = pri_ISR;
551 /* -------------------------------------------------------------------------
552 Install entry points for PRI Adapter
553 ------------------------------------------------------------------------- */
554 void prepare_pri_functions (PISDN_ADAPTER IoAdapter) {
555 IoAdapter->MemorySize = MP_MEMORY_SIZE ;
556 prepare_common_pri_functions (IoAdapter) ;
557 diva_os_prepare_pri_functions (IoAdapter);
559 /* -------------------------------------------------------------------------
560 Install entry points for PRI Rev.2 Adapter
561 ------------------------------------------------------------------------- */
562 void prepare_pri2_functions (PISDN_ADAPTER IoAdapter) {
563 IoAdapter->MemorySize = MP2_MEMORY_SIZE ;
564 prepare_common_pri_functions (IoAdapter) ;
565 diva_os_prepare_pri2_functions (IoAdapter);
567 /* ------------------------------------------------------------------------- */