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.
 
  41 /*****************************************************************************/
 
  42 #define MAX_XLOG_SIZE   (64 * 1024)
 
  44 /* --------------------------------------------------------------------------
 
  45                 Recovery XLOG from QBRI Card
 
  46          -------------------------------------------------------------------------- */
 
  47 static void qBri_cpu_trapped (PISDN_ADAPTER IoAdapter) {
 
  50         dword   regs[4], TrapID, offset, size ;
 
  52         int factor = (IoAdapter->tasks == 1) ? 1 : 2;
 
  55  *      check for trapped MIPS 46xx CPU, dump exception frame
 
  58         base = DIVA_OS_MEM_ATTACH_CONTROL(IoAdapter);
 
  59         offset = IoAdapter->ControllerNumber * (IoAdapter->MemorySize >> factor) ;
 
  61         TrapID = READ_DWORD(&base[0x80]) ;
 
  63         if ( (TrapID == 0x99999999) || (TrapID == 0x99999901) )
 
  65                 dump_trap_frame (IoAdapter, &base[0x90]) ;
 
  66                 IoAdapter->trapped = 1 ;
 
  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 ;
 
  75         if ( (regs[0] >= offset)
 
  76           && (regs[0] < offset + (IoAdapter->MemorySize >> factor) - 1) )
 
  78                 if ( !(Xlog = (word *)diva_os_malloc (0, MAX_XLOG_SIZE)) ) {
 
  79                         DIVA_OS_MEM_DETACH_CONTROL(IoAdapter, base);
 
  83                 size = offset + (IoAdapter->MemorySize >> factor) - regs[0] ;
 
  84                 if ( size > MAX_XLOG_SIZE )
 
  85                         size = MAX_XLOG_SIZE ;
 
  86                 memcpy_fromio (Xlog, &base[regs[0]], size) ;
 
  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 ;
 
  94         DIVA_OS_MEM_DETACH_CONTROL(IoAdapter, base);
 
  97 /* --------------------------------------------------------------------------
 
  99          -------------------------------------------------------------------------- */
 
 100 static void reset_qBri_hardware (PISDN_ADAPTER IoAdapter) {
 
 101         word volatile __iomem *qBriReset ;
 
 102         byte  volatile __iomem *qBriCntrl ;
 
 103         byte  volatile __iomem *p ;
 
 105         qBriReset = (word volatile __iomem *)DIVA_OS_MEM_ATTACH_PROM(IoAdapter);
 
 106         WRITE_WORD(qBriReset, READ_WORD(qBriReset) | PLX9054_SOFT_RESET) ;
 
 108         WRITE_WORD(qBriReset, READ_WORD(qBriReset) & ~PLX9054_SOFT_RESET) ;
 
 110         WRITE_WORD(qBriReset, READ_WORD(qBriReset) | PLX9054_RELOAD_EEPROM) ;
 
 112         WRITE_WORD(qBriReset, READ_WORD(qBriReset) & ~PLX9054_RELOAD_EEPROM) ;
 
 114         DIVA_OS_MEM_DETACH_PROM(IoAdapter, qBriReset);
 
 116         qBriCntrl = DIVA_OS_MEM_ATTACH_CTLREG(IoAdapter);
 
 117         p = &qBriCntrl[DIVA_4BRI_REVISION(IoAdapter) ? (MQ2_BREG_RISC) : (MQ_BREG_RISC)];
 
 119         DIVA_OS_MEM_DETACH_CTLREG(IoAdapter, qBriCntrl);
 
 121         DBG_TRC(("resetted board @ reset addr 0x%08lx", qBriReset))
 
 122         DBG_TRC(("resetted board @ cntrl addr 0x%08lx", p))
 
 125 /* --------------------------------------------------------------------------
 
 127          -------------------------------------------------------------------------- */
 
 128 void start_qBri_hardware (PISDN_ADAPTER IoAdapter) {
 
 129         byte volatile __iomem *qBriReset ;
 
 130         byte volatile __iomem *p ;
 
 132         p = 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) ;
 
 136         WRITE_DWORD(qBriReset, MQ_RISC_WARM_RESET_MASK | MQ_RISC_COLD_RESET_MASK) ;
 
 138         DIVA_OS_MEM_DETACH_CTLREG(IoAdapter, p);
 
 140         DBG_TRC(("started processor @ addr 0x%08lx", qBriReset))
 
 143 /* --------------------------------------------------------------------------
 
 145          -------------------------------------------------------------------------- */
 
 146 static void stop_qBri_hardware (PISDN_ADAPTER IoAdapter) {
 
 147         byte volatile __iomem *p ;
 
 148         dword volatile __iomem *qBriReset ;
 
 149         dword volatile __iomem *qBriIrq ;
 
 150         dword volatile __iomem *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);
 
 156         if ( IoAdapter->ControllerNumber > 0 )
 
 158         p = DIVA_OS_MEM_ATTACH_CTLREG(IoAdapter);
 
 159         qBriReset = (dword volatile __iomem *)&p[reset_offset];
 
 160         qBriIsacDspReset = (dword volatile __iomem *)&p[hw_offset];
 
 162  *      clear interrupt line (reset Local Interrupt Test Register)
 
 164         WRITE_DWORD(qBriReset, 0) ;
 
 165         WRITE_DWORD(qBriIsacDspReset, 0) ;
 
 166         DIVA_OS_MEM_DETACH_CTLREG(IoAdapter, p);
 
 168         p = DIVA_OS_MEM_ATTACH_RESET(IoAdapter);
 
 169         WRITE_BYTE(&p[PLX9054_INTCSR], 0x00);   /* disable PCI interrupts */
 
 170         DIVA_OS_MEM_DETACH_RESET(IoAdapter, p);
 
 172         p = DIVA_OS_MEM_ATTACH_CTLREG(IoAdapter);
 
 173         qBriIrq   = (dword volatile __iomem *)&p[irq_offset];
 
 174         WRITE_DWORD(qBriIrq, MQ_IRQ_REQ_OFF) ;
 
 175         DIVA_OS_MEM_DETACH_CTLREG(IoAdapter, p);
 
 177         DBG_TRC(("stopped processor @ addr 0x%08lx", qBriReset))
 
 181 /* --------------------------------------------------------------------------
 
 183          -------------------------------------------------------------------------- */
 
 184 #define FPGA_NAME_OFFSET         0x10
 
 186 static byte * qBri_check_FPGAsrc (PISDN_ADAPTER IoAdapter, char *FileName,
 
 187                                   dword *Length, dword *code) {
 
 189         char  *fpgaFile, *fpgaType, *fpgaDate, *fpgaTime ;
 
 190         dword  fpgaFlen,  fpgaTlen,  fpgaDlen, cnt, year, i ;
 
 192         if (!(File = (byte *)xdiLoadFile (FileName, Length, 0))) {
 
 196  *       scan file until FF and put id string into buffer
 
 198         for ( i = 0 ; File[i] != 0xff ; )
 
 200                 if ( ++i >= *Length )
 
 202                         DBG_FTL(("FPGA download: start of data header not found"))
 
 209         if ( (File[i] & 0xF0) != 0x20 )
 
 211                 DBG_FTL(("FPGA download: data header corrupted"))
 
 215         fpgaFlen = (dword)  File[FPGA_NAME_OFFSET - 1] ;
 
 218         fpgaFile = (char *)&File[FPGA_NAME_OFFSET] ;
 
 219         fpgaTlen = (dword)  fpgaFile[fpgaFlen + 2] ;
 
 222         fpgaType = (char *)&fpgaFile[fpgaFlen + 3] ;
 
 223         fpgaDlen = (dword)  fpgaType[fpgaTlen + 2] ;
 
 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)) ;
 
 231         if ( (dword)(i + (cnt / 8)) > *Length )
 
 233                 DBG_FTL(("FPGA download: '%s' file too small (%ld < %ld)",
 
 234                          FileName, *Length, code + ((cnt + 7) / 8) ))
 
 241                 while ( (fpgaDate[i] != '\0')
 
 242                      && ((fpgaDate[i] < '0') || (fpgaDate[i] > '9')) )
 
 247                 while ( (fpgaDate[i] >= '0') && (fpgaDate[i] <= '9') )
 
 248                         year = year * 10 + (fpgaDate[i++] - '0') ;
 
 249         } while ( (year < 2000) && (fpgaDate[i] != '\0') );
 
 251         switch (IoAdapter->cardType) {
 
 252                 case CARDTYPE_DIVASRV_B_2F_PCI:
 
 256             if ( year >= 2001 ) {
 
 257                                 IoAdapter->fpga_features |= PCINIT_FPGA_PLX_ACCESS_SUPPORTED ;
 
 261         DBG_LOG(("FPGA[%s] file %s (%s %s) len %d",
 
 262                  fpgaType, fpgaFile, fpgaDate, fpgaTime, cnt))
 
 266 /******************************************************************************/
 
 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 */
 
 275 int qBri_FPGA_download (PISDN_ADAPTER IoAdapter) {
 
 278         dword          code, FileLength ;
 
 279         word volatile __iomem *addr = (word volatile __iomem *)DIVA_OS_MEM_ATTACH_PROM(IoAdapter);
 
 280         word           val, baseval = FPGA_CS | FPGA_PROG ;
 
 284         if (DIVA_4BRI_REVISION(IoAdapter))
 
 288                 switch (IoAdapter->cardType) {
 
 289                         case CARDTYPE_DIVASRV_B_2F_PCI:
 
 290                                 name = "dsbri2f.bit";
 
 293                         case CARDTYPE_DIVASRV_B_2M_V2_PCI:
 
 294                         case CARDTYPE_DIVASRV_VOICE_B_2M_V2_PCI:
 
 295                                 name = "dsbri2m.bit";
 
 299                                 name = "ds4bri2.bit";
 
 302                 File = qBri_check_FPGAsrc (IoAdapter, name,
 
 307                 File = qBri_check_FPGAsrc (IoAdapter, "ds4bri.bit",
 
 308                                            &FileLength, &code) ;
 
 311                 DIVA_OS_MEM_DETACH_PROM(IoAdapter, addr);
 
 315  *      prepare download, pulse PROGRAM pin down.
 
 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 */
 
 321  *      check done pin, must be low
 
 323         if ( READ_WORD(addr) & FPGA_BUSY )
 
 325                 DBG_FTL(("FPGA download: acknowledge for FPGA memory clear missing"))
 
 327                 DIVA_OS_MEM_DETACH_PROM(IoAdapter, addr);
 
 331  *      put data onto the FPGA
 
 333         while ( code < FileLength )
 
 335                 val = ((word)File[code++]) << 3 ;
 
 337                 for ( bit = 8 ; bit-- > 0 ; val <<= 1 ) /* put byte onto FPGA */
 
 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 */
 
 349         val = READ_WORD(addr) ;
 
 351         DIVA_OS_MEM_DETACH_PROM(IoAdapter, addr);
 
 353         if ( !(val & FPGA_BUSY) )
 
 355                 DBG_FTL(("FPGA download: chip remains in busy state (0x%04x)", val))
 
 362 static int load_qBri_hardware (PISDN_ADAPTER IoAdapter) {
 
 366 /* --------------------------------------------------------------------------
 
 368          -------------------------------------------------------------------------- */
 
 369 static int qBri_ISR (struct _ISDN_ADAPTER* IoAdapter) {
 
 370         dword volatile     __iomem *qBriIrq ;
 
 372         PADAPTER_LIST_ENTRY QuadroList = IoAdapter->QuadroList ;
 
 378         p = DIVA_OS_MEM_ATTACH_RESET(IoAdapter);
 
 380         if ( !(READ_BYTE(&p[PLX9054_INTCSR]) & 0x80) ) {
 
 381                 DIVA_OS_MEM_DETACH_RESET(IoAdapter, p);
 
 384         DIVA_OS_MEM_DETACH_RESET(IoAdapter, p);
 
 387  *      clear interrupt line (reset Local Interrupt Test Register)
 
 389         p = DIVA_OS_MEM_ATTACH_CTLREG(IoAdapter);
 
 390         qBriIrq = (dword volatile __iomem *)(&p[DIVA_4BRI_REVISION(IoAdapter) ? (MQ2_BREG_IRQ_TEST)  : (MQ_BREG_IRQ_TEST)]);
 
 391         WRITE_DWORD(qBriIrq, MQ_IRQ_REQ_OFF) ;
 
 392         DIVA_OS_MEM_DETACH_CTLREG(IoAdapter, p);
 
 394         for ( i = 0 ; i < IoAdapter->tasks; ++i )
 
 396                 IoAdapter = QuadroList->QuadroAdapter[i] ;
 
 398                 if ( IoAdapter && IoAdapter->Initialized
 
 399                   && IoAdapter->tst_irq (&IoAdapter->a) )
 
 401                         IoAdapter->IrqCount++ ;
 
 403                         diva_os_schedule_soft_isr (&IoAdapter->isr_soft_isr);
 
 410 /* --------------------------------------------------------------------------
 
 411                 Does disable the interrupt on the card
 
 412          -------------------------------------------------------------------------- */
 
 413 static void disable_qBri_interrupt (PISDN_ADAPTER IoAdapter) {
 
 414         dword volatile __iomem *qBriIrq ;
 
 417         if ( IoAdapter->ControllerNumber > 0 )
 
 420  *      clear interrupt line (reset Local Interrupt Test Register)
 
 422         p = DIVA_OS_MEM_ATTACH_RESET(IoAdapter);
 
 423         WRITE_BYTE(&p[PLX9054_INTCSR], 0x00);   /* disable PCI interrupts */
 
 424         DIVA_OS_MEM_DETACH_RESET(IoAdapter, p);
 
 426         p = DIVA_OS_MEM_ATTACH_CTLREG(IoAdapter);
 
 427         qBriIrq = (dword volatile __iomem *)(&p[DIVA_4BRI_REVISION(IoAdapter) ? (MQ2_BREG_IRQ_TEST)  : (MQ_BREG_IRQ_TEST)]);
 
 428         WRITE_DWORD(qBriIrq, MQ_IRQ_REQ_OFF) ;
 
 429         DIVA_OS_MEM_DETACH_CTLREG(IoAdapter, p);
 
 432 /* --------------------------------------------------------------------------
 
 433                 Install Adapter Entry Points
 
 434          -------------------------------------------------------------------------- */
 
 435 static void set_common_qBri_functions (PISDN_ADAPTER IoAdapter) {
 
 441         a->ram_inw          = mem_inw ;
 
 442         a->ram_in_buffer    = mem_in_buffer ;
 
 443         a->ram_look_ahead   = mem_look_ahead ;
 
 444         a->ram_out          = mem_out ;
 
 445         a->ram_outw         = mem_outw ;
 
 446         a->ram_out_buffer   = mem_out_buffer ;
 
 447         a->ram_inc          = mem_inc ;
 
 449         IoAdapter->out      = pr_out ;
 
 450         IoAdapter->dpc      = pr_dpc ;
 
 451         IoAdapter->tst_irq  = scom_test_int ;
 
 452         IoAdapter->clr_irq  = scom_clear_int ;
 
 453         IoAdapter->pcm      = (struct pc_maint *)MIPS_MAINT_OFFS ;
 
 455         IoAdapter->load     = load_qBri_hardware ;
 
 457         IoAdapter->disIrq   = disable_qBri_interrupt ;
 
 458         IoAdapter->rstFnc   = reset_qBri_hardware ;
 
 459         IoAdapter->stop     = stop_qBri_hardware ;
 
 460         IoAdapter->trapFnc  = qBri_cpu_trapped ;
 
 462         IoAdapter->diva_isr_handler = qBri_ISR;
 
 464         IoAdapter->a.io       = (void*)IoAdapter ;
 
 467 static void set_qBri_functions (PISDN_ADAPTER IoAdapter) {
 
 468         if (!IoAdapter->tasks) {
 
 469                 IoAdapter->tasks = MQ_INSTANCE_COUNT;
 
 471         IoAdapter->MemorySize = MQ_MEMORY_SIZE ;
 
 472         set_common_qBri_functions (IoAdapter) ;
 
 473         diva_os_set_qBri_functions (IoAdapter) ;
 
 476 static void set_qBri2_functions (PISDN_ADAPTER IoAdapter) {
 
 477         if (!IoAdapter->tasks) {
 
 478                 IoAdapter->tasks = MQ_INSTANCE_COUNT;
 
 480         IoAdapter->MemorySize = (IoAdapter->tasks == 1) ? BRI2_MEMORY_SIZE : MQ2_MEMORY_SIZE;
 
 481         set_common_qBri_functions (IoAdapter) ;
 
 482         diva_os_set_qBri2_functions (IoAdapter) ;
 
 485 /******************************************************************************/
 
 487 void prepare_qBri_functions (PISDN_ADAPTER IoAdapter) {
 
 489         set_qBri_functions (IoAdapter->QuadroList->QuadroAdapter[0]) ;
 
 490         set_qBri_functions (IoAdapter->QuadroList->QuadroAdapter[1]) ;
 
 491         set_qBri_functions (IoAdapter->QuadroList->QuadroAdapter[2]) ;
 
 492         set_qBri_functions (IoAdapter->QuadroList->QuadroAdapter[3]) ;
 
 496 void prepare_qBri2_functions (PISDN_ADAPTER IoAdapter) {
 
 497         if (!IoAdapter->tasks) {
 
 498                 IoAdapter->tasks = MQ_INSTANCE_COUNT;
 
 501         set_qBri2_functions (IoAdapter->QuadroList->QuadroAdapter[0]) ;
 
 502         if (IoAdapter->tasks > 1) {
 
 503                 set_qBri2_functions (IoAdapter->QuadroList->QuadroAdapter[1]) ;
 
 504                 set_qBri2_functions (IoAdapter->QuadroList->QuadroAdapter[2]) ;
 
 505                 set_qBri2_functions (IoAdapter->QuadroList->QuadroAdapter[3]) ;
 
 510 /* -------------------------------------------------------------------------- */