ftp://ftp.kernel.org/pub/linux/kernel/v2.6/linux-2.6.6.tar.bz2
[linux-2.6.git] / drivers / isdn / hardware / eicon / s_4bri.c
1
2 /*
3  *
4   Copyright (c) Eicon Networks, 2002.
5  *
6   This source file is supplied for the use with
7   Eicon Networks range of DIVA Server Adapters.
8  *
9   Eicon File Revision :    2.1
10  *
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.
15  *
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.
20  *
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.
24  *
25  */
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 "pc_init.h"
35 #include "io.h"
36 #include "helpers.h"
37 #include "dsrv4bri.h"
38 #include "dsp_defs.h"
39 #include "sdp_hdr.h"
40
41 /*****************************************************************************/
42 #define MAX_XLOG_SIZE   (64 * 1024)
43
44 /* --------------------------------------------------------------------------
45                 Recovery XLOG from QBRI Card
46          -------------------------------------------------------------------------- */
47 static void qBri_cpu_trapped (PISDN_ADAPTER IoAdapter) {
48         byte  *base ;
49         word *Xlog ;
50         dword   regs[4], TrapID, offset, size ;
51         Xdesc   xlogDesc ;
52         int factor = (IoAdapter->tasks == 1) ? 1 : 2;
53
54 /*
55  *      check for trapped MIPS 46xx CPU, dump exception frame
56  */
57
58         base = DIVA_OS_MEM_ATTACH_CONTROL(IoAdapter);
59         offset = IoAdapter->ControllerNumber * (IoAdapter->MemorySize >> factor) ;
60
61         TrapID = READ_DWORD(&base[0x80]) ;
62
63         if ( (TrapID == 0x99999999) || (TrapID == 0x99999901) )
64         {
65                 dump_trap_frame (IoAdapter, &base[0x90]) ;
66                 IoAdapter->trapped = 1 ;
67         }
68
69         regs[0] = READ_DWORD((&base + offset) + 0x70);
70         regs[1] = READ_DWORD((&base + offset) + 0x74);
71         regs[2] = READ_DWORD((&base + offset) + 0x78);
72         regs[3] = READ_DWORD((&base + offset) + 0x7c);
73         regs[0] &= IoAdapter->MemorySize - 1 ;
74
75         if ( (regs[0] >= offset)
76           && (regs[0] < offset + (IoAdapter->MemorySize >> factor) - 1) )
77         {
78                 if ( !(Xlog = (word *)diva_os_malloc (0, MAX_XLOG_SIZE)) ) {
79                         DIVA_OS_MEM_DETACH_CONTROL(IoAdapter, base);
80                         return ;
81                 }
82
83                 size = offset + (IoAdapter->MemorySize >> factor) - regs[0] ;
84                 if ( size > MAX_XLOG_SIZE )
85                         size = MAX_XLOG_SIZE ;
86                 memcpy (Xlog, &base[regs[0]], size) ;
87                 xlogDesc.buf = Xlog ;
88                 xlogDesc.cnt = READ_WORD(&base[regs[1] & (IoAdapter->MemorySize - 1)]) ;
89                 xlogDesc.out = READ_WORD(&base[regs[2] & (IoAdapter->MemorySize - 1)]) ;
90                 dump_xlog_buffer (IoAdapter, &xlogDesc) ;
91                 diva_os_free (0, Xlog) ;
92                 IoAdapter->trapped = 2 ;
93         }
94         DIVA_OS_MEM_DETACH_CONTROL(IoAdapter, base);
95 }
96
97 /* --------------------------------------------------------------------------
98                 Reset QBRI Hardware
99          -------------------------------------------------------------------------- */
100 static void reset_qBri_hardware (PISDN_ADAPTER IoAdapter) {
101         word volatile *qBriReset ;
102         byte  volatile *qBriCntrl ;
103         byte  volatile *p ;
104
105         qBriReset = (word volatile *)DIVA_OS_MEM_ATTACH_PROM(IoAdapter);
106         WRITE_WORD(qBriReset, READ_WORD(qBriReset) | PLX9054_SOFT_RESET) ;
107         diva_os_wait (1) ;
108         WRITE_WORD(qBriReset, READ_WORD(qBriReset) & ~PLX9054_SOFT_RESET) ;
109         diva_os_wait (1);
110         WRITE_WORD(qBriReset, READ_WORD(qBriReset) | PLX9054_RELOAD_EEPROM) ;
111         diva_os_wait (1) ;
112         WRITE_WORD(qBriReset, READ_WORD(qBriReset) & ~PLX9054_RELOAD_EEPROM) ;
113         diva_os_wait (1);
114         DIVA_OS_MEM_DETACH_PROM(IoAdapter, qBriReset);
115
116         qBriCntrl = DIVA_OS_MEM_ATTACH_CTLREG(IoAdapter);
117         p = &qBriCntrl[DIVA_4BRI_REVISION(IoAdapter) ? (MQ2_BREG_RISC) : (MQ_BREG_RISC)];
118         WRITE_DWORD(p, 0) ;
119         DIVA_OS_MEM_DETACH_CTLREG(IoAdapter, qBriCntrl);
120
121         DBG_TRC(("resetted board @ reset addr 0x%08lx", qBriReset))
122         DBG_TRC(("resetted board @ cntrl addr 0x%08lx", p))
123 }
124
125 /* --------------------------------------------------------------------------
126                 Start Card CPU
127          -------------------------------------------------------------------------- */
128 void start_qBri_hardware (PISDN_ADAPTER IoAdapter) {
129         byte volatile *qBriReset ;
130         byte volatile *p ;
131
132         p = (byte volatile *)DIVA_OS_MEM_ATTACH_CTLREG(IoAdapter);
133         qBriReset = &p[(DIVA_4BRI_REVISION(IoAdapter)) ? (MQ2_BREG_RISC) : (MQ_BREG_RISC)];
134         WRITE_DWORD(qBriReset, MQ_RISC_COLD_RESET_MASK) ;
135         diva_os_wait (2) ;
136         WRITE_DWORD(qBriReset, MQ_RISC_WARM_RESET_MASK | MQ_RISC_COLD_RESET_MASK) ;
137         diva_os_wait (10) ;
138         DIVA_OS_MEM_DETACH_CTLREG(IoAdapter, p);
139
140         DBG_TRC(("started processor @ addr 0x%08lx", qBriReset))
141 }
142
143 /* --------------------------------------------------------------------------
144                 Stop Card CPU
145          -------------------------------------------------------------------------- */
146 static void stop_qBri_hardware (PISDN_ADAPTER IoAdapter) {
147         byte volatile *p ;
148         dword volatile *qBriReset ;
149         dword volatile *qBriIrq ;
150         dword volatile *qBriIsacDspReset ;
151         int rev2 = DIVA_4BRI_REVISION(IoAdapter);
152         int reset_offset = rev2 ? (MQ2_BREG_RISC)      : (MQ_BREG_RISC);
153         int irq_offset   = rev2 ? (MQ2_BREG_IRQ_TEST)  : (MQ_BREG_IRQ_TEST);
154         int hw_offset    = rev2 ? (MQ2_ISAC_DSP_RESET) : (MQ_ISAC_DSP_RESET);
155
156         if ( IoAdapter->ControllerNumber > 0 )
157                 return ;
158         p = (byte volatile *)DIVA_OS_MEM_ATTACH_CTLREG(IoAdapter);
159         qBriReset = (dword volatile *)&p[reset_offset];
160         qBriIsacDspReset = (dword volatile *)&p[hw_offset];
161 /*
162  *      clear interrupt line (reset Local Interrupt Test Register)
163  */
164         WRITE_DWORD(qBriReset, 0) ;
165         WRITE_DWORD(qBriIsacDspReset, 0) ;
166         DIVA_OS_MEM_DETACH_CTLREG(IoAdapter, p);
167         
168         p = (byte volatile *)DIVA_OS_MEM_ATTACH_RESET(IoAdapter);
169         p[PLX9054_INTCSR] = 0x00 ;      /* disable PCI interrupts */
170         DIVA_OS_MEM_DETACH_RESET(IoAdapter, p);
171         
172         p = (byte volatile *)DIVA_OS_MEM_ATTACH_CTLREG(IoAdapter);
173         qBriIrq   = (dword volatile *)&p[irq_offset];
174         WRITE_DWORD(qBriIrq, MQ_IRQ_REQ_OFF) ;
175         DIVA_OS_MEM_DETACH_CTLREG(IoAdapter, p);
176
177         DBG_TRC(("stopped processor @ addr 0x%08lx", qBriReset))
178
179 }
180
181 /* --------------------------------------------------------------------------
182                 FPGA download
183          -------------------------------------------------------------------------- */
184 #define FPGA_NAME_OFFSET         0x10
185
186 static byte * qBri_check_FPGAsrc (PISDN_ADAPTER IoAdapter, char *FileName,
187                                   dword *Length, dword *code) {
188         byte *File ;
189         char  *fpgaFile, *fpgaType, *fpgaDate, *fpgaTime ;
190         dword  fpgaFlen,  fpgaTlen,  fpgaDlen, cnt, year, i ;
191
192         if (!(File = (byte *)xdiLoadFile (FileName, Length, 0))) {
193                 return (NULL) ;
194         }
195 /*
196  *       scan file until FF and put id string into buffer
197  */
198         for ( i = 0 ; File[i] != 0xff ; )
199         {
200                 if ( ++i >= *Length )
201                 {
202                         DBG_FTL(("FPGA download: start of data header not found"))
203                         xdiFreeFile (File) ;
204                         return (NULL) ;
205                 }
206         }
207         *code = i++ ;
208
209         if ( (File[i] & 0xF0) != 0x20 )
210         {
211                 DBG_FTL(("FPGA download: data header corrupted"))
212                 xdiFreeFile (File) ;
213                 return (NULL) ;
214         }
215         fpgaFlen = (dword)  File[FPGA_NAME_OFFSET - 1] ;
216         if ( fpgaFlen == 0 )
217                 fpgaFlen = 12 ;
218         fpgaFile = (char *)&File[FPGA_NAME_OFFSET] ;
219         fpgaTlen = (dword)  fpgaFile[fpgaFlen + 2] ;
220         if ( fpgaTlen == 0 )
221                 fpgaTlen = 10 ;
222         fpgaType = (char *)&fpgaFile[fpgaFlen + 3] ;
223         fpgaDlen = (dword)  fpgaType[fpgaTlen + 2] ;
224         if ( fpgaDlen == 0 )
225                 fpgaDlen = 11 ;
226         fpgaDate = (char *)&fpgaType[fpgaTlen + 3] ;
227         fpgaTime = (char *)&fpgaDate[fpgaDlen + 3] ;
228         cnt = (dword)(((File[  i  ] & 0x0F) << 20) + (File[i + 1] << 12)
229                      + (File[i + 2]         <<  4) + (File[i + 3] >>  4)) ;
230
231         if ( (dword)(i + (cnt / 8)) > *Length )
232         {
233                 DBG_FTL(("FPGA download: '%s' file too small (%ld < %ld)",
234                          FileName, *Length, code + ((cnt + 7) / 8) ))
235                 xdiFreeFile (File) ;
236                 return (NULL) ;
237         }
238         i = 0 ;
239         do
240         {
241                 while ( (fpgaDate[i] != '\0')
242                      && ((fpgaDate[i] < '0') || (fpgaDate[i] > '9')) )
243                 {
244                         i++;
245                 }
246                 year = 0 ;
247                 while ( (fpgaDate[i] >= '0') && (fpgaDate[i] <= '9') )
248                         year = year * 10 + (fpgaDate[i++] - '0') ;
249         } while ( (year < 2000) && (fpgaDate[i] != '\0') );
250
251         switch (IoAdapter->cardType) {
252                 case CARDTYPE_DIVASRV_B_2F_PCI:
253                         break;
254
255                 default:
256             if ( year >= 2001 ) {
257                                 IoAdapter->fpga_features |= PCINIT_FPGA_PLX_ACCESS_SUPPORTED ;
258                         }
259         }
260
261         DBG_LOG(("FPGA[%s] file %s (%s %s) len %d",
262                  fpgaType, fpgaFile, fpgaDate, fpgaTime, cnt))
263         return (File) ;
264 }
265
266 /******************************************************************************/
267
268 #define FPGA_PROG   0x0001              /* PROG enable low */
269 #define FPGA_BUSY   0x0002              /* BUSY high, DONE low */
270 #define FPGA_CS     0x000C              /* Enable I/O pins */
271 #define FPGA_CCLK   0x0100
272 #define FPGA_DOUT   0x0400
273 #define FPGA_DIN    FPGA_DOUT   /* bidirectional I/O */
274
275 int qBri_FPGA_download (PISDN_ADAPTER IoAdapter) {
276         int            bit ;
277         byte           *File ;
278         dword          code, FileLength ;
279         word volatile *addr = (word volatile *)DIVA_OS_MEM_ATTACH_PROM(IoAdapter);
280         word           val, baseval = FPGA_CS | FPGA_PROG ;
281
282
283
284         if (DIVA_4BRI_REVISION(IoAdapter))
285         {
286                 char* name;
287
288                 switch (IoAdapter->cardType) {
289                         case CARDTYPE_DIVASRV_B_2F_PCI:
290                                 name = "dsbri2f.bit";
291                                 break;
292
293                         case CARDTYPE_DIVASRV_B_2M_V2_PCI:
294                         case CARDTYPE_DIVASRV_VOICE_B_2M_V2_PCI:
295                                 name = "dsbri2m.bit";
296                                 break;
297
298                         default:
299                                 name = "ds4bri2.bit";
300                 }
301
302                 File = qBri_check_FPGAsrc (IoAdapter, name,
303                                                 &FileLength, &code);
304         }
305         else
306         {
307                 File = qBri_check_FPGAsrc (IoAdapter, "ds4bri.bit",
308                                            &FileLength, &code) ;
309         }
310         if ( !File ) {
311                 DIVA_OS_MEM_DETACH_PROM(IoAdapter, addr);
312                 return (0) ;
313         }
314 /*
315  *      prepare download, pulse PROGRAM pin down.
316  */
317         WRITE_WORD(addr, baseval & ~FPGA_PROG) ; /* PROGRAM low pulse */
318         WRITE_WORD(addr, baseval) ;              /* release */
319         diva_os_wait (50) ;  /* wait until FPGA finished internal memory clear */
320 /*
321  *      check done pin, must be low
322  */
323         if ( READ_WORD(addr) & FPGA_BUSY )
324         {
325                 DBG_FTL(("FPGA download: acknowledge for FPGA memory clear missing"))
326                 xdiFreeFile (File) ;
327                 DIVA_OS_MEM_DETACH_PROM(IoAdapter, addr);
328                 return (0) ;
329         }
330 /*
331  *      put data onto the FPGA
332  */
333         while ( code < FileLength )
334         {
335                 val = ((word)File[code++]) << 3 ;
336
337                 for ( bit = 8 ; bit-- > 0 ; val <<= 1 ) /* put byte onto FPGA */
338                 {
339                         baseval &= ~FPGA_DOUT ;             /* clr  data bit */
340                         baseval |= (val & FPGA_DOUT) ;      /* copy data bit */
341                         WRITE_WORD(addr, baseval) ;
342                         WRITE_WORD(addr, baseval | FPGA_CCLK) ;     /* set CCLK hi */
343                         WRITE_WORD(addr, baseval | FPGA_CCLK) ;     /* set CCLK hi */
344                         WRITE_WORD(addr, baseval) ;                 /* set CCLK lo */
345                 }
346         }
347         xdiFreeFile (File) ;
348         diva_os_wait (100) ;
349         val = READ_WORD(addr) ;
350
351         DIVA_OS_MEM_DETACH_PROM(IoAdapter, addr);
352
353         if ( !(val & FPGA_BUSY) )
354         {
355                 DBG_FTL(("FPGA download: chip remains in busy state (0x%04x)", val))
356                 return (0) ;
357         }
358
359         return (1) ;
360 }
361
362 #if !defined(DIVA_USER_MODE_CARD_CONFIG) /* { */
363 /* --------------------------------------------------------------------------
364                 Download protocol code to the adapter
365          -------------------------------------------------------------------------- */
366
367 static int qBri_protocol_load (PISDN_ADAPTER BaseIoAdapter, PISDN_ADAPTER IoAdapter) {
368         PISDN_ADAPTER HighIoAdapter;
369
370         byte *p;
371         dword  FileLength ;
372         dword *sharedRam, *File;
373         dword  Addr, ProtOffset, SharedRamOffset, i;
374         dword tasks = BaseIoAdapter->tasks ;
375         int factor = (tasks == 1) ? 1 : 2;
376
377         if (!(File = (dword *)xdiLoadArchive (IoAdapter, &FileLength, 0))) {
378                 return (0) ;
379         }
380
381         IoAdapter->features = diva_get_protocol_file_features ((byte*)File,
382                                                OFFS_PROTOCOL_ID_STRING,
383                                                IoAdapter->ProtocolIdString,
384                                                sizeof(IoAdapter->ProtocolIdString)) ;
385         IoAdapter->a.protocol_capabilities = IoAdapter->features ;
386
387         DBG_LOG(("Loading %s", IoAdapter->ProtocolIdString))
388
389         ProtOffset = IoAdapter->ControllerNumber * (IoAdapter->MemorySize >> factor);
390         SharedRamOffset = (IoAdapter->MemorySize >> factor) - MQ_SHARED_RAM_SIZE;
391         Addr = ((dword)(((byte *) File)[OFFS_PROTOCOL_END_ADDR]))
392           | (((dword)(((byte *) File)[OFFS_PROTOCOL_END_ADDR + 1])) << 8)
393           | (((dword)(((byte *) File)[OFFS_PROTOCOL_END_ADDR + 2])) << 16)
394           | (((dword)(((byte *) File)[OFFS_PROTOCOL_END_ADDR + 3])) << 24) ;
395         if ( Addr != 0 )
396         {
397                 IoAdapter->DspCodeBaseAddr = (Addr + 3) & (~3) ;
398                 IoAdapter->MaxDspCodeSize = (MQ_UNCACHED_ADDR (ProtOffset + SharedRamOffset) -
399                                                                                 IoAdapter->DspCodeBaseAddr) & ((IoAdapter->MemorySize >> factor) - 1);
400
401                 i = 0 ;
402                 while ( BaseIoAdapter->QuadroList->QuadroAdapter[i]->ControllerNumber != tasks - 1 )
403                         i++ ;
404                 HighIoAdapter = BaseIoAdapter->QuadroList->QuadroAdapter[i] ;
405                 Addr = HighIoAdapter->DspCodeBaseAddr ;
406
407                 if (tasks == 1) {
408                         ((byte *) File)[OFFS_DIVA_INIT_TASK_COUNT]   =(byte)1;
409                         ((byte *) File)[OFFS_DIVA_INIT_TASK_COUNT+1] = (byte)BaseIoAdapter->cardType;
410                 }
411
412                 ((byte *) File)[OFFS_DSP_CODE_BASE_ADDR] = (byte) Addr ;
413                 ((byte *) File)[OFFS_DSP_CODE_BASE_ADDR + 1] = (byte)(Addr >> 8) ;
414                 ((byte *) File)[OFFS_DSP_CODE_BASE_ADDR + 2] = (byte)(Addr >> 16) ;
415                 ((byte *) File)[OFFS_DSP_CODE_BASE_ADDR + 3] = (byte)(Addr >> 24) ;
416                 IoAdapter->InitialDspInfo = 0x80 ;
417         }
418         else
419         {
420                 if ( IoAdapter->features & PROTCAP_VOIP )
421                 {
422                         IoAdapter->DspCodeBaseAddr = MQ_CACHED_ADDR (ProtOffset + SharedRamOffset - MQ_VOIP_MAX_DSP_CODE_SIZE) ;
423
424                         IoAdapter->MaxDspCodeSize = MQ_VOIP_MAX_DSP_CODE_SIZE ;
425
426                 }
427                 else if ( IoAdapter->features & PROTCAP_V90D )
428                 {
429                         IoAdapter->DspCodeBaseAddr = MQ_CACHED_ADDR (ProtOffset + SharedRamOffset - MQ_V90D_MAX_DSP_CODE_SIZE) ;
430
431                         IoAdapter->MaxDspCodeSize = (IoAdapter->ControllerNumber == tasks - 1) ? MQ_V90D_MAX_DSP_CODE_SIZE : 0 ;
432
433                 }
434                 else
435                 {
436                         IoAdapter->DspCodeBaseAddr = MQ_CACHED_ADDR (ProtOffset + SharedRamOffset - MQ_ORG_MAX_DSP_CODE_SIZE) ;
437
438                         IoAdapter->MaxDspCodeSize = (IoAdapter->ControllerNumber == tasks - 1) ? MQ_ORG_MAX_DSP_CODE_SIZE : 0 ;
439
440                 }
441                 IoAdapter->InitialDspInfo = (MQ_CACHED_ADDR (ProtOffset + SharedRamOffset -
442                                                                                                                         MQ_ORG_MAX_DSP_CODE_SIZE) - IoAdapter->DspCodeBaseAddr) >> 14 ;
443
444         }
445         DBG_LOG(("%d: DSP code base 0x%08lx, max size 0x%08lx (%08lx,%02x)",
446                  IoAdapter->ControllerNumber,
447                  IoAdapter->DspCodeBaseAddr, IoAdapter->MaxDspCodeSize,
448                  Addr, IoAdapter->InitialDspInfo))
449
450         if (FileLength > ((IoAdapter->DspCodeBaseAddr - MQ_CACHED_ADDR (ProtOffset)) & (IoAdapter->MemorySize - 1)) )
451         {
452                 xdiFreeFile (File) ;
453                 DBG_FTL(("Protocol code '%s' too long (%ld)",
454                          &IoAdapter->Protocol[0], FileLength))
455                 return (0) ;
456         }
457         IoAdapter->downloadAddr = 0 ;
458         p = DIVA_OS_MEM_ATTACH_RAM(IoAdapter);
459         sharedRam = (dword *)&p[IoAdapter->downloadAddr & (IoAdapter->MemorySize - 1)];
460         memcpy (sharedRam, File, FileLength) ;
461
462         DBG_TRC(("Download addr 0x%08x len %ld - virtual 0x%08x",
463                  IoAdapter->downloadAddr, FileLength, sharedRam))
464
465         if ( memcmp (sharedRam, File, FileLength) )
466         {
467                 DBG_FTL(("%s: Memory test failed!", IoAdapter->Properties.Name))
468
469                 DBG_FTL(("File=0x%x, sharedRam=0x%x", File, sharedRam))
470                 DBG_BLK(( (char *)File, 256))
471                 DBG_BLK(( (char *)sharedRam, 256))
472                 DIVA_OS_MEM_DETACH_RAM(IoAdapter, p);
473
474                 xdiFreeFile (File) ;
475                 return (0) ;
476         }
477         DIVA_OS_MEM_DETACH_RAM(IoAdapter, p);
478         xdiFreeFile (File) ;
479
480         return (1) ;
481 }
482
483 /* --------------------------------------------------------------------------
484                 DSP Code download
485          -------------------------------------------------------------------------- */
486 static long qBri_download_buffer (OsFileHandle *fp, long length, void **addr) {
487         PISDN_ADAPTER BaseIoAdapter = (PISDN_ADAPTER)fp->sysLoadDesc ;
488         PISDN_ADAPTER IoAdapter;
489         word        i ;
490         dword       *sharedRam ;
491         byte *p;
492
493         i = 0 ;
494
495         do
496         {
497                 IoAdapter = BaseIoAdapter->QuadroList->QuadroAdapter[i++] ;
498         } while ( (i < BaseIoAdapter->tasks)
499                && (((dword) length) > IoAdapter->DspCodeBaseAddr +
500                         IoAdapter->MaxDspCodeSize - IoAdapter->downloadAddr) );
501
502         *addr = (void *)IoAdapter->downloadAddr ;
503         if ( ((dword) length) > IoAdapter->DspCodeBaseAddr +
504                                 IoAdapter->MaxDspCodeSize - IoAdapter->downloadAddr )
505         {
506                 DBG_FTL(("%s: out of card memory during DSP download (0x%X)",
507                          IoAdapter->Properties.Name,
508                          IoAdapter->downloadAddr + length))
509                 return (-1) ;
510         }
511         p = DIVA_OS_MEM_ATTACH_RAM(BaseIoAdapter);
512         sharedRam = (dword*)&p[IoAdapter->downloadAddr & (IoAdapter->MemorySize - 1)];
513
514         if ( fp->sysFileRead (fp, sharedRam, length) != length ) {
515                 DIVA_OS_MEM_DETACH_RAM(BaseIoAdapter, p);
516                 return (-1) ;
517         }
518         DIVA_OS_MEM_DETACH_RAM(BaseIoAdapter, p);
519
520         IoAdapter->downloadAddr += length ;
521         IoAdapter->downloadAddr  = (IoAdapter->downloadAddr + 3) & (~3) ;
522
523         return (0) ;
524 }
525
526 /******************************************************************************/
527
528 static dword qBri_telindus_load (PISDN_ADAPTER BaseIoAdapter) {
529         PISDN_ADAPTER        IoAdapter = 0;
530         PISDN_ADAPTER        HighIoAdapter = NULL ;
531         char                *error ;
532         OsFileHandle        *fp ;
533         t_dsp_portable_desc  download_table[DSP_MAX_DOWNLOAD_COUNT] ;
534         word                 download_count, i ;
535         dword               *sharedRam ;
536         dword                FileLength ;
537         byte *p;
538
539         if ( !(fp = OsOpenFile (DSP_TELINDUS_FILE)) ) {
540                 DBG_FTL(("qBri_telindus_load: %s not found!", DSP_TELINDUS_FILE))
541                 return (0) ;
542         }
543
544
545         for ( i = 0 ; i < BaseIoAdapter->tasks ; ++i )
546         {
547                 IoAdapter = BaseIoAdapter->QuadroList->QuadroAdapter[i] ;
548                 IoAdapter->downloadAddr = IoAdapter->DspCodeBaseAddr ;
549                 if ( IoAdapter->ControllerNumber == BaseIoAdapter->tasks - 1 )
550                 {
551                         HighIoAdapter = IoAdapter ;
552                         HighIoAdapter->downloadAddr = (HighIoAdapter->downloadAddr
553                                    + sizeof(dword) + sizeof(download_table) + 3) & (~3) ;
554                 }
555         }
556
557
558         FileLength      = fp->sysFileSize ;
559         fp->sysLoadDesc = (void *)BaseIoAdapter ;
560         fp->sysCardLoad = qBri_download_buffer ;
561
562         download_count = DSP_MAX_DOWNLOAD_COUNT ;
563         memset (&download_table[0], '\0', sizeof(download_table)) ;
564 /*
565  *      set start address for download
566  */
567         error = dsp_read_file (fp, (word)(IoAdapter->cardType),
568                                &download_count, NULL, &download_table[0]) ;
569         if ( error )
570         {
571                 DBG_FTL(("download file error: %s", error))
572                 OsCloseFile (fp) ;
573                 return (0) ;
574         }
575         OsCloseFile (fp) ;
576
577
578         /*
579          *      store # of download files extracted from the archive and download table
580          */
581                 HighIoAdapter->downloadAddr = HighIoAdapter->DspCodeBaseAddr ;
582                 p = DIVA_OS_MEM_ATTACH_RAM(BaseIoAdapter);
583                 sharedRam = (dword *)&p[HighIoAdapter->downloadAddr & (IoAdapter->MemorySize - 1)];
584                 WRITE_DWORD(&(sharedRam[0]), (dword)download_count);
585                 memcpy (&sharedRam[1], &download_table[0], sizeof(download_table)) ;
586
587
588         /* memory check */
589         if ( memcmp (&sharedRam[1], &download_table, download_count) ) {
590                 DBG_FTL(("%s: Dsp Memory test failed!", IoAdapter->Properties.Name))
591         }
592         DIVA_OS_MEM_DETACH_RAM(BaseIoAdapter, p);
593
594         return (FileLength) ;
595 }
596
597 /*
598         Load SDP tasks to the card
599         Return start address of image on succesful load
600         Return zero in case of problem
601
602         INPUT:
603                 task                    ->      name of the image containing this task
604                 link_addr       ->      pointer to start of previous task
605         */
606 static byte* qBri_sdp_load (PISDN_ADAPTER BaseIoAdapter,
607                                                                                                         char* task,
608                                                                                                         byte*   link_addr) {
609         OsFileHandle *fp;
610         dword FileLength;
611         byte tmp[sizeof(dword)];
612         dword gp_addr;
613         dword entry_addr;
614         dword start_addr = 0;
615         dword phys_start_addr;
616         dword end_addr;
617         byte* sharedRam = 0;
618         byte *p;
619
620   if (task) {
621                 if (!(fp = OsOpenFile (task))) {
622                         DBG_ERR(("Can't open [%s] image", task))
623                         return (0);
624                 }
625                 if ((FileLength = fp->sysFileSize) < DIVA_MIPS_TASK_IMAGE_ID_STRING_OFFS) {
626                         OsCloseFile (fp) ;
627                         DBG_ERR(("Image [%s] too short", task))
628                         return (0);
629                 }
630
631                 fp->sysFileSeek (fp, DIVA_MIPS_TASK_IMAGE_GP_OFFS, OS_SEEK_SET);
632                 if (fp->sysFileRead (fp, tmp, sizeof(dword)) != sizeof(dword)) {
633                         OsCloseFile (fp) ;
634                         DBG_ERR(("Can't read image [%s]", task))
635                         return (0);
636                 }
637                 gp_addr = ((dword)tmp[0])                                       |
638                                                         (((dword)tmp[1]) << 8)  |
639                                                         (((dword)tmp[2]) << 16) |
640                                                         (((dword)tmp[3]) << 24);
641                 DBG_TRC(("Image [%s] GP = %08lx", task, gp_addr))
642
643                 fp->sysFileSeek (fp, DIVA_MIPS_TASK_IMAGE_ENTRY_OFFS, OS_SEEK_SET);
644                 if (fp->sysFileRead (fp, tmp, sizeof(dword)) != sizeof(dword)) {
645                         OsCloseFile (fp) ;
646                         DBG_ERR(("Can't read image [%s]", task))
647                         return (0);
648                 }
649                 entry_addr = ((dword)tmp[0])                                    |
650                                                                         (((dword)tmp[1]) << 8)  |
651                                                                         (((dword)tmp[2]) << 16) |
652                                                                         (((dword)tmp[3]) << 24);
653                 DBG_TRC(("Image [%s] entry = %08lx", task, entry_addr))
654
655                 fp->sysFileSeek (fp, DIVA_MIPS_TASK_IMAGE_LOAD_ADDR_OFFS, OS_SEEK_SET);
656                 if (fp->sysFileRead (fp, tmp, sizeof(dword)) != sizeof(dword)) {
657                         OsCloseFile (fp) ;
658                         DBG_ERR(("Can't read image [%s]", task))
659                         return (0);
660                 }
661                 start_addr = ((dword)tmp[0])                                    |
662                                                                         (((dword)tmp[1]) << 8)  |
663                                                                         (((dword)tmp[2]) << 16) |
664                                                                         (((dword)tmp[3]) << 24);
665                 DBG_TRC(("Image [%s] start = %08lx", task, start_addr))
666
667                 fp->sysFileSeek (fp, DIVA_MIPS_TASK_IMAGE_END_ADDR_OFFS, OS_SEEK_SET);
668                 if (fp->sysFileRead (fp, tmp, sizeof(dword)) != sizeof(dword)) {
669                         OsCloseFile (fp) ;
670                         DBG_ERR(("Can't read image [%s]", task))
671                         return (0);
672                 }
673                 end_addr = ((dword)tmp[0])                                      |
674                                                                 (((dword)tmp[1]) << 8)  |
675                                                                 (((dword)tmp[2]) << 16) |
676                                                                 (((dword)tmp[3]) << 24);
677                 DBG_TRC(("Image [%s] end = %08lx", task, end_addr))
678
679                 phys_start_addr = start_addr & 0x1fffffff;
680
681                 if ((phys_start_addr + FileLength) >= BaseIoAdapter->MemorySize) {
682                         OsCloseFile (fp) ;
683                         DBG_ERR(("Image [%s] too long", task))
684                         return (0);
685                 }
686
687                 fp->sysFileSeek (fp, 0, OS_SEEK_SET);
688                 p = DIVA_OS_MEM_ATTACH_RAM(BaseIoAdapter);
689                 sharedRam = &p[phys_start_addr];
690                 if ((dword)fp->sysFileRead (fp, sharedRam, FileLength) != FileLength) {
691                         DIVA_OS_MEM_DETACH_RAM(BaseIoAdapter, p);
692                         OsCloseFile (fp) ;
693                         DBG_ERR(("Can't read image [%s]", task))
694                         return (0);
695                 }
696                 DIVA_OS_MEM_DETACH_RAM(BaseIoAdapter, p);
697
698                 OsCloseFile (fp) ;
699   }
700
701         p = DIVA_OS_MEM_ATTACH_RAM(BaseIoAdapter);
702         if (!link_addr) {
703                 link_addr = &p[OFFS_DSP_CODE_BASE_ADDR];
704         }
705
706         DBG_TRC(("Write task [%s] link %08lx at %08lx",
707                                                 task ? task : "none",
708                                                 start_addr,
709                                                 link_addr - (byte*)&BaseIoAdapter->ram[0]))
710
711         link_addr[0] = (byte)(start_addr         & 0xff);
712         link_addr[1] = (byte)((start_addr >>  8) & 0xff);
713         link_addr[2] = (byte)((start_addr >> 16) & 0xff);
714         link_addr[3] = (byte)((start_addr >> 24) & 0xff);
715
716         DIVA_OS_MEM_DETACH_RAM(BaseIoAdapter, p);
717
718         return (task ? &sharedRam[DIVA_MIPS_TASK_IMAGE_LINK_OFFS] : 0);
719 }
720
721 /* --------------------------------------------------------------------------
722                 Load Card
723          -------------------------------------------------------------------------- */
724 static int load_qBri_hardware (PISDN_ADAPTER IoAdapter) {
725         dword         i, offset, controller ;
726         word         *signature ;
727         int           factor = (IoAdapter->tasks == 1) ? 1 : 2;
728         byte *p;
729
730         PISDN_ADAPTER Slave ;
731
732
733         if (
734
735                 !IoAdapter->QuadroList
736
737           || ( (IoAdapter->cardType != CARDTYPE_DIVASRV_Q_8M_PCI)
738             && (IoAdapter->cardType != CARDTYPE_DIVASRV_VOICE_Q_8M_PCI)
739             && (IoAdapter->cardType != CARDTYPE_DIVASRV_Q_8M_V2_PCI)
740      && (IoAdapter->cardType != CARDTYPE_DIVASRV_VOICE_Q_8M_V2_PCI)
741      && (IoAdapter->cardType != CARDTYPE_DIVASRV_B_2M_V2_PCI)
742      && (IoAdapter->cardType != CARDTYPE_DIVASRV_VOICE_B_2M_V2_PCI)
743      && (IoAdapter->cardType != CARDTYPE_DIVASRV_B_2F_PCI) ) )
744         {
745                 return (0) ;
746         }
747
748 /*
749  *      Check for first instance
750  */
751         if ( IoAdapter->ControllerNumber > 0 )
752                 return (1) ;
753
754 /*
755  *      first initialize the onboard FPGA
756  */
757         if ( !qBri_FPGA_download (IoAdapter) )
758                 return (0) ;
759
760
761         for ( i = 0; i < IoAdapter->tasks; i++ )
762         {
763                 Slave = IoAdapter->QuadroList->QuadroAdapter[i] ;
764                 Slave->fpga_features = IoAdapter->fpga_features ;
765         }
766
767
768 /*
769  *      download protocol code for all instances
770  */
771
772         controller = IoAdapter->tasks;
773         do
774         {
775                 controller-- ;
776                 i = 0 ;
777                 while ( IoAdapter->QuadroList->QuadroAdapter[i]->ControllerNumber != controller )
778                         i++ ;
779 /*
780  *      calculate base address for instance
781  */
782                 Slave          = IoAdapter->QuadroList->QuadroAdapter[i] ;
783                 offset         = Slave->ControllerNumber * (IoAdapter->MemorySize >> factor) ;
784                 Slave->Address = &IoAdapter->Address[offset] ;
785                 Slave->ram     = &IoAdapter->ram[offset] ;
786                 Slave->reset   = IoAdapter->reset ;
787                 Slave->ctlReg  = IoAdapter->ctlReg ;
788                 Slave->prom    = IoAdapter->prom ;
789                 Slave->Config  = IoAdapter->Config ;
790                 Slave->Control = IoAdapter->Control ;
791
792                 if ( !qBri_protocol_load (IoAdapter, Slave) )
793                         return (0) ;
794
795         } while (controller != 0) ;
796
797
798 /*
799  *      download only one copy of the DSP code
800  */
801  if (IoAdapter->cardType != CARDTYPE_DIVASRV_B_2F_PCI) {
802         if ( !qBri_telindus_load (IoAdapter) )
803                 return (0) ;
804  } else {
805    byte* link_addr = 0;
806    link_addr = qBri_sdp_load (IoAdapter, DIVA_BRI2F_SDP_1_NAME, link_addr);
807    link_addr = qBri_sdp_load (IoAdapter, DIVA_BRI2F_SDP_2_NAME, link_addr);
808    if (!link_addr) {
809      qBri_sdp_load (IoAdapter, 0, link_addr);
810    }
811  }
812
813 /*
814  *      copy configuration parameters
815  */
816
817         for ( i = 0 ; i < IoAdapter->tasks ; ++i )
818         {
819                 Slave = IoAdapter->QuadroList->QuadroAdapter[i] ;
820                 Slave->ram += (IoAdapter->MemorySize >> factor) - MQ_SHARED_RAM_SIZE ;
821                 p = DIVA_OS_MEM_ATTACH_RAM(Slave);
822                 DBG_TRC(("Configure instance %d shared memory @ 0x%08lx",
823                          Slave->ControllerNumber, p))
824                 memset (p, '\0', 256) ;
825                 DIVA_OS_MEM_DETACH_RAM(Slave, p);
826                 diva_configure_protocol (Slave);
827         }
828
829 /*
830  *      start adapter
831  */
832         start_qBri_hardware (IoAdapter) ;
833         p = DIVA_OS_MEM_ATTACH_RAM(IoAdapter);
834         signature = (word *)(&p[0x1E]) ;
835 /*
836  *      wait for signature in shared memory (max. 3 seconds)
837  */
838         for ( i = 0 ; i < 300 ; ++i )
839         {
840                 diva_os_wait (10) ;
841
842                 if ( signature[0] == 0x4447 )
843                 {
844                         DIVA_OS_MEM_DETACH_RAM(IoAdapter, p);
845                         DBG_TRC(("Protocol startup time %d.%02d seconds",
846                                  (i / 100), (i % 100) ))
847
848                         return (1) ;
849                 }
850         }
851         DIVA_OS_MEM_DETACH_RAM(IoAdapter, p);
852         DBG_FTL(("%s: Adapter selftest failed (0x%04X)!",
853                  IoAdapter->Properties.Name, signature[0] >> 16))
854         qBri_cpu_trapped (IoAdapter) ;
855         return (FALSE) ;
856 }
857 #else /* } { */
858 static int load_qBri_hardware (PISDN_ADAPTER IoAdapter) {
859         return (0);
860 }
861 #endif /* } */
862
863 /* --------------------------------------------------------------------------
864                 Card ISR
865          -------------------------------------------------------------------------- */
866 static int qBri_ISR (struct _ISDN_ADAPTER* IoAdapter) {
867         dword volatile     *qBriIrq ;
868
869         PADAPTER_LIST_ENTRY QuadroList = IoAdapter->QuadroList ;
870
871         word                    i ;
872         int                     serviced = 0 ;
873         byte *p;
874
875         p = DIVA_OS_MEM_ATTACH_RESET(IoAdapter);
876
877         if ( !(p[PLX9054_INTCSR] & 0x80) ) {
878                 DIVA_OS_MEM_DETACH_RESET(IoAdapter, p);
879                 return (0) ;
880         }
881         DIVA_OS_MEM_DETACH_RESET(IoAdapter, p);
882
883 /*
884  *      clear interrupt line (reset Local Interrupt Test Register)
885  */
886         p = DIVA_OS_MEM_ATTACH_CTLREG(IoAdapter);
887         qBriIrq = (dword volatile *)(&p[DIVA_4BRI_REVISION(IoAdapter) ? (MQ2_BREG_IRQ_TEST)  : (MQ_BREG_IRQ_TEST)]);
888         WRITE_DWORD(qBriIrq, MQ_IRQ_REQ_OFF) ;
889         DIVA_OS_MEM_DETACH_CTLREG(IoAdapter, p);
890
891         for ( i = 0 ; i < IoAdapter->tasks; ++i )
892         {
893                 IoAdapter = QuadroList->QuadroAdapter[i] ;
894
895                 if ( IoAdapter && IoAdapter->Initialized
896                   && IoAdapter->tst_irq (&IoAdapter->a) )
897                 {
898                         IoAdapter->IrqCount++ ;
899                         serviced = 1 ;
900                         diva_os_schedule_soft_isr (&IoAdapter->isr_soft_isr);
901                 }
902         }
903
904         return (serviced) ;
905 }
906
907 /* --------------------------------------------------------------------------
908                 Does disable the interrupt on the card
909          -------------------------------------------------------------------------- */
910 static void disable_qBri_interrupt (PISDN_ADAPTER IoAdapter) {
911         dword volatile *qBriIrq ;
912         byte *p;
913
914         if ( IoAdapter->ControllerNumber > 0 )
915                 return ;
916 /*
917  *      clear interrupt line (reset Local Interrupt Test Register)
918  */
919         p = DIVA_OS_MEM_ATTACH_RESET(IoAdapter);
920         p[PLX9054_INTCSR] = 0x00 ;      /* disable PCI interrupts */
921         DIVA_OS_MEM_DETACH_RESET(IoAdapter, p);
922
923         p = DIVA_OS_MEM_ATTACH_CTLREG(IoAdapter);
924         qBriIrq = (dword volatile *)(&p[DIVA_4BRI_REVISION(IoAdapter) ? (MQ2_BREG_IRQ_TEST)  : (MQ_BREG_IRQ_TEST)]);
925         WRITE_DWORD(qBriIrq, MQ_IRQ_REQ_OFF) ;
926         DIVA_OS_MEM_DETACH_CTLREG(IoAdapter, p);
927 }
928
929 /* --------------------------------------------------------------------------
930                 Install Adapter Entry Points
931          -------------------------------------------------------------------------- */
932 static void set_common_qBri_functions (PISDN_ADAPTER IoAdapter) {
933         ADAPTER *a;
934
935         a = &IoAdapter->a ;
936
937         a->ram_in           = mem_in ;
938         a->ram_inw          = mem_inw ;
939         a->ram_in_buffer    = mem_in_buffer ;
940         a->ram_look_ahead   = mem_look_ahead ;
941         a->ram_out          = mem_out ;
942         a->ram_outw         = mem_outw ;
943         a->ram_out_buffer   = mem_out_buffer ;
944         a->ram_inc          = mem_inc ;
945
946         IoAdapter->out      = pr_out ;
947         IoAdapter->dpc      = pr_dpc ;
948         IoAdapter->tst_irq  = scom_test_int ;
949         IoAdapter->clr_irq  = scom_clear_int ;
950         IoAdapter->pcm      = (struct pc_maint *)MIPS_MAINT_OFFS ;
951
952         IoAdapter->load     = load_qBri_hardware ;
953
954         IoAdapter->disIrq   = disable_qBri_interrupt ;
955         IoAdapter->rstFnc   = reset_qBri_hardware ;
956         IoAdapter->stop     = stop_qBri_hardware ;
957         IoAdapter->trapFnc  = qBri_cpu_trapped ;
958
959         IoAdapter->diva_isr_handler = qBri_ISR;
960
961         IoAdapter->a.io       = (void*)IoAdapter ;
962 }
963
964 static void set_qBri_functions (PISDN_ADAPTER IoAdapter) {
965         if (!IoAdapter->tasks) {
966                 IoAdapter->tasks = MQ_INSTANCE_COUNT;
967         }
968         IoAdapter->MemorySize = MQ_MEMORY_SIZE ;
969         set_common_qBri_functions (IoAdapter) ;
970         diva_os_set_qBri_functions (IoAdapter) ;
971 }
972
973 static void set_qBri2_functions (PISDN_ADAPTER IoAdapter) {
974         if (!IoAdapter->tasks) {
975                 IoAdapter->tasks = MQ_INSTANCE_COUNT;
976         }
977         IoAdapter->MemorySize = (IoAdapter->tasks == 1) ? BRI2_MEMORY_SIZE : MQ2_MEMORY_SIZE;
978         set_common_qBri_functions (IoAdapter) ;
979         diva_os_set_qBri2_functions (IoAdapter) ;
980 }
981
982 /******************************************************************************/
983
984 void prepare_qBri_functions (PISDN_ADAPTER IoAdapter) {
985
986         set_qBri_functions (IoAdapter->QuadroList->QuadroAdapter[0]) ;
987         set_qBri_functions (IoAdapter->QuadroList->QuadroAdapter[1]) ;
988         set_qBri_functions (IoAdapter->QuadroList->QuadroAdapter[2]) ;
989         set_qBri_functions (IoAdapter->QuadroList->QuadroAdapter[3]) ;
990
991 }
992
993 void prepare_qBri2_functions (PISDN_ADAPTER IoAdapter) {
994         if (!IoAdapter->tasks) {
995                 IoAdapter->tasks = MQ_INSTANCE_COUNT;
996         }
997
998         set_qBri2_functions (IoAdapter->QuadroList->QuadroAdapter[0]) ;
999         if (IoAdapter->tasks > 1) {
1000                 set_qBri2_functions (IoAdapter->QuadroList->QuadroAdapter[1]) ;
1001                 set_qBri2_functions (IoAdapter->QuadroList->QuadroAdapter[2]) ;
1002                 set_qBri2_functions (IoAdapter->QuadroList->QuadroAdapter[3]) ;
1003         }
1004
1005 }
1006
1007 /* -------------------------------------------------------------------------- */