Merge with Linux 2.5.48.
[linux-2.6/linux-mips.git] / drivers / isdn / hardware / eicon / s_bri.c
blobbbfba867544d3bd28928ee07bf15e28a7e0e5155
2 /*
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)
14 any later version.
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.
26 #include "platform.h"
27 #include "di_defs.h"
28 #include "pc.h"
29 #include "pr_pc.h"
30 #include "di.h"
31 #include "mi_pc.h"
32 #include "pc_maint.h"
33 #include "divasync.h"
34 #include "io.h"
35 #include "helpers.h"
36 #include "dsrv_bri.h"
37 #include "dsp_defs.h"
38 /*****************************************************************************/
39 #define MAX_XLOG_SIZE (64 * 1024)
40 /* --------------------------------------------------------------------------
41 Investigate card state, recovery trace buffer
42 -------------------------------------------------------------------------- */
43 static void bri_cpu_trapped (PISDN_ADAPTER IoAdapter) {
44 byte *addrHi, *addrLo, *ioaddr ;
45 word *Xlog ;
46 dword regs[4], i, size ;
47 Xdesc xlogDesc ;
49 * first read pointers and trap frame
51 if ( !(Xlog = (word *)diva_os_malloc (0, MAX_XLOG_SIZE)) )
52 return ;
53 addrHi = IoAdapter->port
54 + ((IoAdapter->Properties.Bus == BUS_PCI) ? M_PCI_ADDRH : ADDRH) ;
55 addrLo = IoAdapter->port + ADDR ;
56 ioaddr = IoAdapter->port + DATA ;
57 outpp (addrHi, 0) ;
58 outppw (addrLo, 0) ;
59 for ( i = 0 ; i < 0x100 ; Xlog[i++] = inppw(ioaddr) ) ;
61 * check for trapped MIPS 3xxx CPU, dump only exception frame
63 if ( READ_WORD(&Xlog[0x80 / sizeof(Xlog[0])]) == 0x99999999 )
65 dump_trap_frame (IoAdapter, &((byte *)Xlog)[0x90]) ;
66 IoAdapter->trapped = 1 ;
68 regs[0] = READ_DWORD(&((byte *)Xlog)[0x70]);
69 regs[1] = READ_DWORD(&((byte *)Xlog)[0x74]);
70 regs[2] = READ_DWORD(&((byte *)Xlog)[0x78]);
71 regs[3] = READ_DWORD(&((byte *)Xlog)[0x7c]);
72 outpp (addrHi, (regs[1] >> 16) & 0x7F) ;
73 outppw (addrLo, regs[1] & 0xFFFF) ;
74 xlogDesc.cnt = inppw(ioaddr) ;
75 outpp (addrHi, (regs[2] >> 16) & 0x7F) ;
76 outppw (addrLo, regs[2] & 0xFFFF) ;
77 xlogDesc.out = inppw(ioaddr) ;
78 xlogDesc.buf = Xlog ;
79 regs[0] &= IoAdapter->MemorySize - 1 ;
80 if ( (regs[0] < IoAdapter->MemorySize - 1) )
82 size = IoAdapter->MemorySize - regs[0] ;
83 if ( size > MAX_XLOG_SIZE )
84 size = MAX_XLOG_SIZE ;
85 for ( i = 0 ; i < (size / sizeof(*Xlog)) ; regs[0] += 2 )
87 outpp (addrHi, (regs[0] >> 16) & 0x7F) ;
88 outppw (addrLo, regs[0] & 0xFFFF) ;
89 Xlog[i++] = inppw(ioaddr) ;
91 dump_xlog_buffer (IoAdapter, &xlogDesc) ;
92 diva_os_free (0, Xlog) ;
93 IoAdapter->trapped = 2 ;
95 outpp (addrHi, (byte)((BRI_UNCACHED_ADDR (IoAdapter->MemoryBase + IoAdapter->MemorySize -
96 BRI_SHARED_RAM_SIZE)) >> 16)) ;
97 outppw (addrLo, 0x00) ;
99 /* ---------------------------------------------------------------------
100 Reset hardware
101 --------------------------------------------------------------------- */
102 static void reset_bri_hardware (PISDN_ADAPTER IoAdapter) {
103 outpp (IoAdapter->ctlReg, 0x00) ;
105 /* ---------------------------------------------------------------------
106 Halt system
107 --------------------------------------------------------------------- */
108 static void stop_bri_hardware (PISDN_ADAPTER IoAdapter) {
109 if (IoAdapter->reset) {
110 outpp (IoAdapter->reset, 0x00) ; /* disable interrupts ! */
112 outpp (IoAdapter->ctlReg, 0x00) ; /* clear int, halt cpu */
114 #if !defined(DIVA_USER_MODE_CARD_CONFIG) /* { */
115 /* ---------------------------------------------------------------------
116 Load protocol on the card
117 --------------------------------------------------------------------- */
118 static dword bri_protocol_load (PISDN_ADAPTER IoAdapter) {
119 dword FileLength ;
120 word test, *File = NULL ;
121 byte* addrHi, *addrLo, *ioaddr ;
122 char *FileName = &IoAdapter->Protocol[0] ;
123 dword Addr, i ;
124 /* -------------------------------------------------------------------
125 Try to load protocol code. 'File' points to memory location
126 that does contain entire protocol code
127 ------------------------------------------------------------------- */
128 if ( !(File = (word *)xdiLoadArchive (IoAdapter, &FileLength, 0)) )
129 return (0) ;
130 /* -------------------------------------------------------------------
131 Get protocol features and calculate load addresses
132 ------------------------------------------------------------------- */
133 IoAdapter->features = diva_get_protocol_file_features ((byte*)File,
134 OFFS_PROTOCOL_ID_STRING,
135 IoAdapter->ProtocolIdString,
136 sizeof(IoAdapter->ProtocolIdString));
137 IoAdapter->a.protocol_capabilities = IoAdapter->features ;
138 DBG_LOG(("Loading %s", IoAdapter->ProtocolIdString))
139 Addr = ((dword)(((byte *) File)[OFFS_PROTOCOL_END_ADDR]))
140 | (((dword)(((byte *) File)[OFFS_PROTOCOL_END_ADDR + 1])) << 8)
141 | (((dword)(((byte *) File)[OFFS_PROTOCOL_END_ADDR + 2])) << 16)
142 | (((dword)(((byte *) File)[OFFS_PROTOCOL_END_ADDR + 3])) << 24) ;
143 if ( Addr != 0 )
145 IoAdapter->DspCodeBaseAddr = (Addr + 3) & (~3) ;
146 IoAdapter->MaxDspCodeSize = (BRI_UNCACHED_ADDR (IoAdapter->MemoryBase + IoAdapter->MemorySize -
147 BRI_SHARED_RAM_SIZE)
148 - IoAdapter->DspCodeBaseAddr) & (IoAdapter->MemorySize - 1) ;
149 Addr = IoAdapter->DspCodeBaseAddr ;
150 ((byte *) File)[OFFS_DSP_CODE_BASE_ADDR] = (byte) Addr ;
151 ((byte *) File)[OFFS_DSP_CODE_BASE_ADDR + 1] = (byte)(Addr >> 8) ;
152 ((byte *) File)[OFFS_DSP_CODE_BASE_ADDR + 2] = (byte)(Addr >> 16) ;
153 ((byte *) File)[OFFS_DSP_CODE_BASE_ADDR + 3] = (byte)(Addr >> 24) ;
154 IoAdapter->InitialDspInfo = 0x80 ;
156 else
158 if ( IoAdapter->features & PROTCAP_V90D )
159 IoAdapter->MaxDspCodeSize = BRI_V90D_MAX_DSP_CODE_SIZE ;
160 else
161 IoAdapter->MaxDspCodeSize = BRI_ORG_MAX_DSP_CODE_SIZE ;
162 IoAdapter->DspCodeBaseAddr = BRI_CACHED_ADDR (IoAdapter->MemoryBase + IoAdapter->MemorySize -
163 BRI_SHARED_RAM_SIZE - IoAdapter->MaxDspCodeSize);
164 IoAdapter->InitialDspInfo = (IoAdapter->MaxDspCodeSize - BRI_ORG_MAX_DSP_CODE_SIZE) >> 14 ;
166 DBG_LOG(("DSP code base 0x%08lx, max size 0x%08lx (%08lx,%02x)",
167 IoAdapter->DspCodeBaseAddr, IoAdapter->MaxDspCodeSize,
168 Addr, IoAdapter->InitialDspInfo))
169 if ( FileLength > ((IoAdapter->DspCodeBaseAddr -
170 BRI_CACHED_ADDR (IoAdapter->MemoryBase)) & (IoAdapter->MemorySize - 1)) )
172 xdiFreeFile (File);
173 DBG_FTL(("Protocol code '%s' too big (%ld)", FileName, FileLength))
174 return (0) ;
176 addrHi = IoAdapter->port
177 + ((IoAdapter->Properties.Bus == BUS_PCI) ? M_PCI_ADDRH : ADDRH) ;
178 addrLo = IoAdapter->port + ADDR ;
179 ioaddr = IoAdapter->port + DATA ;
181 * set start address for download (use autoincrement mode !)
183 outpp (addrHi, 0) ;
184 outppw (addrLo, 0) ;
185 for ( i = 0 ; i < FileLength ; i += 2 )
187 if ( (i & 0x0000FFFF) == 0 )
189 outpp (addrHi, (byte)(i >> 16)) ;
191 outppw (ioaddr, File[i/2]) ;
194 * memory test without second load of file
196 outpp (addrHi, 0) ;
197 outppw (addrLo, 0) ;
198 for ( i = 0 ; i < FileLength ; i += 2 )
200 if ( (i & 0x0000FFFF) == 0 )
202 outpp (addrHi, (byte)(i >> 16)) ;
204 test = inppw (ioaddr) ;
205 if ( test != File[i/2] )
207 DBG_FTL(("%s: Memory test failed! (%d - 0x%04X/0x%04X)",
208 IoAdapter->Properties.Name, i, test, File[i/2]))
209 xdiFreeFile (File);
210 return (0) ;
213 xdiFreeFile (File);
214 return (FileLength) ;
216 /******************************************************************************/
217 typedef struct
219 PISDN_ADAPTER IoAdapter ;
220 byte* AddrLo ;
221 byte* AddrHi ;
222 word* Data ;
223 dword DownloadPos ;
224 } bri_download_info ;
225 static long bri_download_buffer (OsFileHandle *fp, long length, void **addr) {
226 int buffer_size = 2048*sizeof(word);
227 word *buffer = (word*)diva_os_malloc (0, buffer_size);
228 bri_download_info *info ;
229 word test ;
230 long i, len, page ;
231 if (!buffer) {
232 DBG_ERR(("A: out of memory, s_bri at %d", __LINE__))
233 return (-1);
235 info = (bri_download_info *)fp->sysLoadDesc ;
236 *addr = (void *)info->DownloadPos ;
237 if ( ((dword) length) > info->IoAdapter->DspCodeBaseAddr +
238 info->IoAdapter->MaxDspCodeSize - info->DownloadPos )
240 DBG_FTL(("%s: out of card memory during DSP download (0x%X)",
241 info->IoAdapter->Properties.Name,
242 info->DownloadPos + length))
243 diva_os_free (0, buffer);
244 return (-1) ;
246 for ( len = 0 ; length > 0 ; length -= len )
248 len = (length > buffer_size ? buffer_size : length) ;
249 page = ((long)(info->DownloadPos) + len) & 0xFFFF0000 ;
250 if ( page != (long)(info->DownloadPos & 0xFFFF0000) )
252 len = 0x00010000 - (((long)info->DownloadPos) & 0x0000FFFF) ;
254 if ( fp->sysFileRead (fp, &buffer[0], len) != len ) {
255 diva_os_free (0, buffer);
256 return (-1) ;
258 outpp (info->AddrHi, (byte)(info->DownloadPos >> 16)) ;
259 outppw (info->AddrLo, (word)info->DownloadPos) ;
260 outppw_buffer (info->Data, &buffer[0], (len + 1)) ;
262 * memory test without second load of file
264 outpp (info->AddrHi, (byte)(info->DownloadPos >> 16)) ;
265 outppw (info->AddrLo, (word)info->DownloadPos) ;
266 for ( i = 0 ; i < len ; i += 2 )
268 if ( (test = inppw (info->Data)) != buffer[i/2] )
270 DBG_FTL(("%s: Memory test failed! (0x%lX - 0x%04X/0x%04X)",
271 info->IoAdapter->Properties.Name,
272 info->DownloadPos + i, test, buffer[i/2]))
273 diva_os_free (0, buffer);
274 return (-2) ;
277 info->DownloadPos += len ;
279 info->DownloadPos = (info->DownloadPos + 3) & (~3) ;
280 diva_os_free (0, buffer);
281 return (0) ;
283 /******************************************************************************/
284 static dword bri_telindus_load (PISDN_ADAPTER IoAdapter, char *DspTelindusFile)
286 bri_download_info *pinfo =\
287 (bri_download_info*)diva_os_malloc(0, sizeof(*pinfo));
288 char *error ;
289 OsFileHandle *fp ;
290 t_dsp_portable_desc download_table[DSP_MAX_DOWNLOAD_COUNT] ;
291 word download_count ;
292 dword FileLength ;
293 if (!pinfo) {
294 DBG_ERR (("A: out of memory s_bri at %d", __LINE__))
295 return (0);
297 if (!(fp = OsOpenFile (DspTelindusFile))) {
298 diva_os_free (0, pinfo);
299 return (0) ;
301 FileLength = fp->sysFileSize ;
302 pinfo->IoAdapter = IoAdapter ;
303 pinfo->AddrLo = IoAdapter->port + ADDR ;
304 pinfo->AddrHi = IoAdapter->port +\
305 (IoAdapter->Properties.Bus == BUS_PCI ? M_PCI_ADDRH : ADDRH);
306 pinfo->Data = (word*)(IoAdapter->port + DATA) ;
307 pinfo->DownloadPos = (IoAdapter->DspCodeBaseAddr +\
308 sizeof(dword) + sizeof(download_table) + 3) & (~3) ;
309 fp->sysLoadDesc = (void *)pinfo;
310 fp->sysCardLoad = bri_download_buffer ;
311 download_count = DSP_MAX_DOWNLOAD_COUNT ;
312 memset (&download_table[0], '\0', sizeof(download_table)) ;
314 * set start address for download (use autoincrement mode !)
316 error = dsp_read_file (fp, (word)(IoAdapter->cardType),
317 &download_count, NULL, &download_table[0]) ;
318 if ( error )
320 DBG_FTL(("download file error: %s", error))
321 OsCloseFile (fp) ;
322 diva_os_free (0, pinfo);
323 return (0) ;
325 OsCloseFile (fp) ;
327 * store # of separate download files extracted from archive
329 pinfo->DownloadPos = IoAdapter->DspCodeBaseAddr ;
330 outpp (pinfo->AddrHi, (byte)(pinfo->DownloadPos >> 16)) ;
331 outppw (pinfo->AddrLo, (word)pinfo->DownloadPos) ;
332 outppw (pinfo->Data, (word)download_count) ;
333 outppw (pinfo->Data, (word)0) ;
335 * copy download table to board
337 outppw_buffer (pinfo->Data, &download_table[0], sizeof(download_table)) ;
338 diva_os_free (0, pinfo);
339 return (FileLength) ;
341 /******************************************************************************/
342 static int load_bri_hardware (PISDN_ADAPTER IoAdapter) {
343 dword i ;
344 byte* addrHi, *addrLo, *ioaddr ;
345 dword test ;
346 if ( IoAdapter->Properties.Card != CARD_MAE )
348 return (FALSE) ;
350 addrHi = IoAdapter->port \
351 + ((IoAdapter->Properties.Bus==BUS_PCI) ? M_PCI_ADDRH : ADDRH);
352 addrLo = IoAdapter->port + ADDR ;
353 ioaddr = IoAdapter->port + DATA ;
354 reset_bri_hardware (IoAdapter) ;
355 diva_os_wait (100);
357 * recover
359 outpp (addrHi, (byte) 0) ;
360 outppw (addrLo, (word) 0) ;
361 outppw (ioaddr, (word) 0) ;
363 * clear shared memory
365 outpp (addrHi, (byte)((BRI_UNCACHED_ADDR (IoAdapter->MemoryBase + \
366 IoAdapter->MemorySize - BRI_SHARED_RAM_SIZE)) >> 16)) ;
367 outppw (addrLo, 0) ;
368 for ( i = 0 ; i < 0x8000 ; outppw (ioaddr, 0), ++i ) ;
369 diva_os_wait (100) ;
371 * download protocol and dsp files
373 switch ( IoAdapter->protocol_id ) {
374 default:
375 if ( !xdiSetProtocol (IoAdapter, IoAdapter->ProtocolSuffix) )
376 return (FALSE) ;
377 if ( !bri_protocol_load (IoAdapter) )
378 return (FALSE) ;
379 if ( !bri_telindus_load (IoAdapter, DSP_TELINDUS_FILE) )
380 return (FALSE) ;
381 break ;
382 case PROTTYPE_QSIG:
383 case PROTTYPE_CORNETN:
384 if ( !xdiSetProtocol (IoAdapter, IoAdapter->ProtocolSuffix) )
385 return (FALSE) ;
386 if (IoAdapter->ProtocolSuffix && *IoAdapter->ProtocolSuffix) {
387 sprintf (&IoAdapter->Protocol[0],
388 "TE_QSIG.%s", IoAdapter->ProtocolSuffix) ;
390 DBG_TRC(("xdiSetProtocol: %s firmware '%s' archive '%s'",
391 IoAdapter->Properties.Name,
392 &IoAdapter->Protocol[0], &IoAdapter->Archive[0]))
393 if ( !bri_protocol_load (IoAdapter) )
394 return (FALSE) ;
395 if ( !bri_telindus_load (IoAdapter, DSP_QSIG_TELINDUS_FILE) )
396 return (FALSE) ;
397 break ;
400 * clear signature
402 outpp (addrHi, (byte)((BRI_UNCACHED_ADDR (IoAdapter->MemoryBase + \
403 IoAdapter->MemorySize - BRI_SHARED_RAM_SIZE)) >> 16)) ;
404 outppw (addrLo, 0x1e) ;
405 outpp (ioaddr, 0) ;
406 outpp (ioaddr, 0) ;
408 * copy parameters
410 diva_configure_protocol (IoAdapter);
412 * start the protocol code
414 outpp (IoAdapter->ctlReg, 0x08) ;
416 * wait for signature (max. 3 seconds)
418 for ( i = 0 ; i < 300 ; ++i )
420 diva_os_wait (10) ;
421 outpp (addrHi, (byte)((BRI_UNCACHED_ADDR (IoAdapter->MemoryBase + \
422 IoAdapter->MemorySize - BRI_SHARED_RAM_SIZE)) >> 16)) ;
423 outppw (addrLo, 0x1e) ;
424 test = (dword)inppw (ioaddr) ;
425 if ( test == 0x4447 )
427 DBG_TRC(("Protocol startup time %d.%02d seconds",
428 (i / 100), (i % 100) ))
429 return (TRUE) ;
432 DBG_FTL(("%s: Adapter selftest failed (0x%04X)!",
433 IoAdapter->Properties.Name, test))
434 bri_cpu_trapped (IoAdapter) ;
435 return (FALSE) ;
437 #else /* } { */
438 static int load_bri_hardware (PISDN_ADAPTER IoAdapter) {
439 return (0);
441 #endif /* } */
442 /******************************************************************************/
443 static int bri_ISR (struct _ISDN_ADAPTER* IoAdapter) {
444 if ( !(inpp (IoAdapter->ctlReg) & 0x01) )
445 return (0) ;
447 clear interrupt line
449 outpp (IoAdapter->ctlReg, 0x08) ;
450 IoAdapter->IrqCount++ ;
451 if ( IoAdapter->Initialized ) {
452 diva_os_schedule_soft_isr (&IoAdapter->isr_soft_isr);
454 return (1) ;
456 /* --------------------------------------------------------------------------
457 Disable IRQ in the card hardware
458 -------------------------------------------------------------------------- */
459 static void disable_bri_interrupt (PISDN_ADAPTER IoAdapter) {
460 if ( IoAdapter->reset )
462 outpp (IoAdapter->reset, 0x00) ; /* disable interrupts ! */
464 outpp (IoAdapter->ctlReg, 0x00) ; /* clear int, halt cpu */
466 /* -------------------------------------------------------------------------
467 Fill card entry points
468 ------------------------------------------------------------------------- */
469 void prepare_maestra_functions (PISDN_ADAPTER IoAdapter) {
470 ADAPTER *a = &IoAdapter->a ;
471 a->ram_in = io_in ;
472 a->ram_inw = io_inw ;
473 a->ram_in_buffer = io_in_buffer ;
474 a->ram_look_ahead = io_look_ahead ;
475 a->ram_out = io_out ;
476 a->ram_outw = io_outw ;
477 a->ram_out_buffer = io_out_buffer ;
478 a->ram_inc = io_inc ;
479 IoAdapter->MemoryBase = BRI_MEMORY_BASE ;
480 IoAdapter->MemorySize = BRI_MEMORY_SIZE ;
481 IoAdapter->out = pr_out ;
482 IoAdapter->dpc = pr_dpc ;
483 IoAdapter->tst_irq = scom_test_int ;
484 IoAdapter->clr_irq = scom_clear_int ;
485 IoAdapter->pcm = (struct pc_maint *)MIPS_MAINT_OFFS ;
486 IoAdapter->load = load_bri_hardware ;
487 IoAdapter->disIrq = disable_bri_interrupt ;
488 IoAdapter->rstFnc = reset_bri_hardware ;
489 IoAdapter->stop = stop_bri_hardware ;
490 IoAdapter->trapFnc = bri_cpu_trapped ;
491 IoAdapter->diva_isr_handler = bri_ISR;
493 Prepare OS dependent functions
495 diva_os_prepare_maestra_functions (IoAdapter);
497 /* -------------------------------------------------------------------------- */