linux/drivers/isdn/hardware/eicon/os_4bri.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/* $Id: os_4bri.c,v 1.28.4.4 2005/02/11 19:40:25 armin Exp $ */
   3
   4#include "platform.h"
   5#include "debuglib.h"
   6#include "cardtype.h"
   7#include "pc.h"
   8#include "pr_pc.h"
   9#include "di_defs.h"
  10#include "dsp_defs.h"
  11#include "di.h"
  12#include "io.h"
  13
  14#include "xdi_msg.h"
  15#include "xdi_adapter.h"
  16#include "os_4bri.h"
  17#include "diva_pci.h"
  18#include "mi_pc.h"
  19#include "dsrv4bri.h"
  20#include "helpers.h"
  21
  22static void *diva_xdiLoadFileFile = NULL;
  23static dword diva_xdiLoadFileLength = 0;
  24
  25/*
  26**  IMPORTS
  27*/
  28extern void prepare_qBri_functions(PISDN_ADAPTER IoAdapter);
  29extern void prepare_qBri2_functions(PISDN_ADAPTER IoAdapter);
  30extern void diva_xdi_display_adapter_features(int card);
  31extern void diva_add_slave_adapter(diva_os_xdi_adapter_t *a);
  32
  33extern int qBri_FPGA_download(PISDN_ADAPTER IoAdapter);
  34extern void start_qBri_hardware(PISDN_ADAPTER IoAdapter);
  35
  36extern int diva_card_read_xlog(diva_os_xdi_adapter_t *a);
  37
  38/*
  39**  LOCALS
  40*/
  41static unsigned long _4bri_bar_length[4] = {
  42        0x100,
  43        0x100,                  /* I/O */
  44        MQ_MEMORY_SIZE,
  45        0x2000
  46};
  47static unsigned long _4bri_v2_bar_length[4] = {
  48        0x100,
  49        0x100,                  /* I/O */
  50        MQ2_MEMORY_SIZE,
  51        0x10000
  52};
  53static unsigned long _4bri_v2_bri_bar_length[4] = {
  54        0x100,
  55        0x100,                  /* I/O */
  56        BRI2_MEMORY_SIZE,
  57        0x10000
  58};
  59
  60
  61static int diva_4bri_cleanup_adapter(diva_os_xdi_adapter_t *a);
  62static int _4bri_get_serial_number(diva_os_xdi_adapter_t *a);
  63static int diva_4bri_cmd_card_proc(struct _diva_os_xdi_adapter *a,
  64                                   diva_xdi_um_cfg_cmd_t *cmd,
  65                                   int length);
  66static int diva_4bri_cleanup_slave_adapters(diva_os_xdi_adapter_t *a);
  67static int diva_4bri_write_fpga_image(diva_os_xdi_adapter_t *a,
  68                                      byte *data, dword length);
  69static int diva_4bri_reset_adapter(PISDN_ADAPTER IoAdapter);
  70static int diva_4bri_write_sdram_block(PISDN_ADAPTER IoAdapter,
  71                                       dword address,
  72                                       const byte *data,
  73                                       dword length, dword limit);
  74static int diva_4bri_start_adapter(PISDN_ADAPTER IoAdapter,
  75                                   dword start_address, dword features);
  76static int check_qBri_interrupt(PISDN_ADAPTER IoAdapter);
  77static int diva_4bri_stop_adapter(diva_os_xdi_adapter_t *a);
  78
  79static int _4bri_is_rev_2_card(int card_ordinal)
  80{
  81        switch (card_ordinal) {
  82        case CARDTYPE_DIVASRV_Q_8M_V2_PCI:
  83        case CARDTYPE_DIVASRV_VOICE_Q_8M_V2_PCI:
  84        case CARDTYPE_DIVASRV_B_2M_V2_PCI:
  85        case CARDTYPE_DIVASRV_B_2F_PCI:
  86        case CARDTYPE_DIVASRV_VOICE_B_2M_V2_PCI:
  87                return (1);
  88        }
  89        return (0);
  90}
  91
  92static int _4bri_is_rev_2_bri_card(int card_ordinal)
  93{
  94        switch (card_ordinal) {
  95        case CARDTYPE_DIVASRV_B_2M_V2_PCI:
  96        case CARDTYPE_DIVASRV_B_2F_PCI:
  97        case CARDTYPE_DIVASRV_VOICE_B_2M_V2_PCI:
  98                return (1);
  99        }
 100        return (0);
 101}
 102
 103static void diva_4bri_set_addresses(diva_os_xdi_adapter_t *a)
 104{
 105        dword offset = a->resources.pci.qoffset;
 106        dword c_offset = offset * a->xdi_adapter.ControllerNumber;
 107
 108        a->resources.pci.mem_type_id[MEM_TYPE_RAM] = 2;
 109        a->resources.pci.mem_type_id[MEM_TYPE_ADDRESS] = 2;
 110        a->resources.pci.mem_type_id[MEM_TYPE_CONTROL] = 2;
 111        a->resources.pci.mem_type_id[MEM_TYPE_RESET] = 0;
 112        a->resources.pci.mem_type_id[MEM_TYPE_CTLREG] = 3;
 113        a->resources.pci.mem_type_id[MEM_TYPE_PROM] = 0;
 114
 115        /*
 116          Set up hardware related pointers
 117        */
 118        a->xdi_adapter.Address = a->resources.pci.addr[2];      /* BAR2 SDRAM  */
 119        a->xdi_adapter.Address += c_offset;
 120
 121        a->xdi_adapter.Control = a->resources.pci.addr[2];      /* BAR2 SDRAM  */
 122
 123        a->xdi_adapter.ram = a->resources.pci.addr[2];  /* BAR2 SDRAM  */
 124        a->xdi_adapter.ram += c_offset + (offset - MQ_SHARED_RAM_SIZE);
 125
 126        a->xdi_adapter.reset = a->resources.pci.addr[0];        /* BAR0 CONFIG */
 127        /*
 128          ctlReg contains the register address for the MIPS CPU reset control
 129        */
 130        a->xdi_adapter.ctlReg = a->resources.pci.addr[3];       /* BAR3 CNTRL  */
 131        /*
 132          prom contains the register address for FPGA and EEPROM programming
 133        */
 134        a->xdi_adapter.prom = &a->xdi_adapter.reset[0x6E];
 135}
 136
 137/*
 138**  BAR0 - MEM - 0x100    - CONFIG MEM
 139**  BAR1 - I/O - 0x100    - UNUSED
 140**  BAR2 - MEM - MQ_MEMORY_SIZE (MQ2_MEMORY_SIZE on Rev.2) - SDRAM
 141**  BAR3 - MEM - 0x2000 (0x10000 on Rev.2)   - CNTRL
 142**
 143**  Called by master adapter, that will initialize and add slave adapters
 144*/
 145int diva_4bri_init_card(diva_os_xdi_adapter_t *a)
 146{
 147        int bar, i;
 148        byte __iomem *p;
 149        PADAPTER_LIST_ENTRY quadro_list;
 150        diva_os_xdi_adapter_t *diva_current;
 151        diva_os_xdi_adapter_t *adapter_list[4];
 152        PISDN_ADAPTER Slave;
 153        unsigned long bar_length[ARRAY_SIZE(_4bri_bar_length)];
 154        int v2 = _4bri_is_rev_2_card(a->CardOrdinal);
 155        int tasks = _4bri_is_rev_2_bri_card(a->CardOrdinal) ? 1 : MQ_INSTANCE_COUNT;
 156        int factor = (tasks == 1) ? 1 : 2;
 157
 158        if (v2) {
 159                if (_4bri_is_rev_2_bri_card(a->CardOrdinal)) {
 160                        memcpy(bar_length, _4bri_v2_bri_bar_length,
 161                               sizeof(bar_length));
 162                } else {
 163                        memcpy(bar_length, _4bri_v2_bar_length,
 164                               sizeof(bar_length));
 165                }
 166        } else {
 167                memcpy(bar_length, _4bri_bar_length, sizeof(bar_length));
 168        }
 169        DBG_TRC(("SDRAM_LENGTH=%08x, tasks=%d, factor=%d",
 170                 bar_length[2], tasks, factor))
 171
 172                /*
 173                  Get Serial Number
 174                  The serial number of 4BRI is accessible in accordance with PCI spec
 175                  via command register located in configuration space, also we do not
 176                  have to map any BAR before we can access it
 177                */
 178                if (!_4bri_get_serial_number(a)) {
 179                        DBG_ERR(("A: 4BRI can't get Serial Number"))
 180                                diva_4bri_cleanup_adapter(a);
 181                        return (-1);
 182                }
 183
 184        /*
 185          Set properties
 186        */
 187        a->xdi_adapter.Properties = CardProperties[a->CardOrdinal];
 188        DBG_LOG(("Load %s, SN:%ld, bus:%02x, func:%02x",
 189                 a->xdi_adapter.Properties.Name,
 190                 a->xdi_adapter.serialNo,
 191                 a->resources.pci.bus, a->resources.pci.func))
 192
 193                /*
 194                  First initialization step: get and check hardware resoures.
 195                  Do not map resources and do not access card at this step
 196                */
 197                for (bar = 0; bar < 4; bar++) {
 198                        a->resources.pci.bar[bar] =
 199                                divasa_get_pci_bar(a->resources.pci.bus,
 200                                                   a->resources.pci.func, bar,
 201                                                   a->resources.pci.hdev);
 202                        if (!a->resources.pci.bar[bar]
 203                            || (a->resources.pci.bar[bar] == 0xFFFFFFF0)) {
 204                                DBG_ERR(
 205                                        ("A: invalid bar[%d]=%08x", bar,
 206                                         a->resources.pci.bar[bar]))
 207                                        return (-1);
 208                        }
 209                }
 210        a->resources.pci.irq =
 211                (byte) divasa_get_pci_irq(a->resources.pci.bus,
 212                                          a->resources.pci.func,
 213                                          a->resources.pci.hdev);
 214        if (!a->resources.pci.irq) {
 215                DBG_ERR(("A: invalid irq"));
 216                return (-1);
 217        }
 218
 219        a->xdi_adapter.sdram_bar = a->resources.pci.bar[2];
 220
 221        /*
 222          Map all MEMORY BAR's
 223        */
 224        for (bar = 0; bar < 4; bar++) {
 225                if (bar != 1) { /* ignore I/O */
 226                        a->resources.pci.addr[bar] =
 227                                divasa_remap_pci_bar(a, bar, a->resources.pci.bar[bar],
 228                                                     bar_length[bar]);
 229                        if (!a->resources.pci.addr[bar]) {
 230                                DBG_ERR(("A: 4BRI: can't map bar[%d]", bar))
 231                                        diva_4bri_cleanup_adapter(a);
 232                                return (-1);
 233                        }
 234                }
 235        }
 236
 237        /*
 238          Register I/O port
 239        */
 240        sprintf(&a->port_name[0], "DIVA 4BRI %ld", (long) a->xdi_adapter.serialNo);
 241
 242        if (diva_os_register_io_port(a, 1, a->resources.pci.bar[1],
 243                                     bar_length[1], &a->port_name[0], 1)) {
 244                DBG_ERR(("A: 4BRI: can't register bar[1]"))
 245                        diva_4bri_cleanup_adapter(a);
 246                return (-1);
 247        }
 248
 249        a->resources.pci.addr[1] =
 250                (void *) (unsigned long) a->resources.pci.bar[1];
 251
 252        /*
 253          Set cleanup pointer for base adapter only, so slave adapter
 254          will be unable to get cleanup
 255        */
 256        a->interface.cleanup_adapter_proc = diva_4bri_cleanup_adapter;
 257
 258        /*
 259          Create slave adapters
 260        */
 261        if (tasks > 1) {
 262                if (!(a->slave_adapters[0] =
 263                      (diva_os_xdi_adapter_t *) diva_os_malloc(0, sizeof(*a))))
 264                {
 265                        diva_4bri_cleanup_adapter(a);
 266                        return (-1);
 267                }
 268                if (!(a->slave_adapters[1] =
 269                      (diva_os_xdi_adapter_t *) diva_os_malloc(0, sizeof(*a))))
 270                {
 271                        diva_os_free(0, a->slave_adapters[0]);
 272                        a->slave_adapters[0] = NULL;
 273                        diva_4bri_cleanup_adapter(a);
 274                        return (-1);
 275                }
 276                if (!(a->slave_adapters[2] =
 277                      (diva_os_xdi_adapter_t *) diva_os_malloc(0, sizeof(*a))))
 278                {
 279                        diva_os_free(0, a->slave_adapters[0]);
 280                        diva_os_free(0, a->slave_adapters[1]);
 281                        a->slave_adapters[0] = NULL;
 282                        a->slave_adapters[1] = NULL;
 283                        diva_4bri_cleanup_adapter(a);
 284                        return (-1);
 285                }
 286                memset(a->slave_adapters[0], 0x00, sizeof(*a));
 287                memset(a->slave_adapters[1], 0x00, sizeof(*a));
 288                memset(a->slave_adapters[2], 0x00, sizeof(*a));
 289        }
 290
 291        adapter_list[0] = a;
 292        adapter_list[1] = a->slave_adapters[0];
 293        adapter_list[2] = a->slave_adapters[1];
 294        adapter_list[3] = a->slave_adapters[2];
 295
 296        /*
 297          Allocate slave list
 298        */
 299        quadro_list =
 300                (PADAPTER_LIST_ENTRY) diva_os_malloc(0, sizeof(*quadro_list));
 301        if (!(a->slave_list = quadro_list)) {
 302                for (i = 0; i < (tasks - 1); i++) {
 303                        diva_os_free(0, a->slave_adapters[i]);
 304                        a->slave_adapters[i] = NULL;
 305                }
 306                diva_4bri_cleanup_adapter(a);
 307                return (-1);
 308        }
 309        memset(quadro_list, 0x00, sizeof(*quadro_list));
 310
 311        /*
 312          Set interfaces
 313        */
 314        a->xdi_adapter.QuadroList = quadro_list;
 315        for (i = 0; i < tasks; i++) {
 316                adapter_list[i]->xdi_adapter.ControllerNumber = i;
 317                adapter_list[i]->xdi_adapter.tasks = tasks;
 318                quadro_list->QuadroAdapter[i] =
 319                        &adapter_list[i]->xdi_adapter;
 320        }
 321
 322        for (i = 0; i < tasks; i++) {
 323                diva_current = adapter_list[i];
 324
 325                diva_current->dsp_mask = 0x00000003;
 326
 327                diva_current->xdi_adapter.a.io =
 328                        &diva_current->xdi_adapter;
 329                diva_current->xdi_adapter.DIRequest = request;
 330                diva_current->interface.cmd_proc = diva_4bri_cmd_card_proc;
 331                diva_current->xdi_adapter.Properties =
 332                        CardProperties[a->CardOrdinal];
 333                diva_current->CardOrdinal = a->CardOrdinal;
 334
 335                diva_current->xdi_adapter.Channels =
 336                        CardProperties[a->CardOrdinal].Channels;
 337                diva_current->xdi_adapter.e_max =
 338                        CardProperties[a->CardOrdinal].E_info;
 339                diva_current->xdi_adapter.e_tbl =
 340                        diva_os_malloc(0,
 341                                       diva_current->xdi_adapter.e_max *
 342                                       sizeof(E_INFO));
 343
 344                if (!diva_current->xdi_adapter.e_tbl) {
 345                        diva_4bri_cleanup_slave_adapters(a);
 346                        diva_4bri_cleanup_adapter(a);
 347                        for (i = 1; i < (tasks - 1); i++) {
 348                                diva_os_free(0, adapter_list[i]);
 349                        }
 350                        return (-1);
 351                }
 352                memset(diva_current->xdi_adapter.e_tbl, 0x00,
 353                       diva_current->xdi_adapter.e_max * sizeof(E_INFO));
 354
 355                if (diva_os_initialize_spin_lock(&diva_current->xdi_adapter.isr_spin_lock, "isr")) {
 356                        diva_4bri_cleanup_slave_adapters(a);
 357                        diva_4bri_cleanup_adapter(a);
 358                        for (i = 1; i < (tasks - 1); i++) {
 359                                diva_os_free(0, adapter_list[i]);
 360                        }
 361                        return (-1);
 362                }
 363                if (diva_os_initialize_spin_lock(&diva_current->xdi_adapter.data_spin_lock, "data")) {
 364                        diva_4bri_cleanup_slave_adapters(a);
 365                        diva_4bri_cleanup_adapter(a);
 366                        for (i = 1; i < (tasks - 1); i++) {
 367                                diva_os_free(0, adapter_list[i]);
 368                        }
 369                        return (-1);
 370                }
 371
 372                strcpy(diva_current->xdi_adapter.req_soft_isr. dpc_thread_name, "kdivas4brid");
 373
 374                if (diva_os_initialize_soft_isr(&diva_current->xdi_adapter.req_soft_isr, DIDpcRoutine,
 375                                                &diva_current->xdi_adapter)) {
 376                        diva_4bri_cleanup_slave_adapters(a);
 377                        diva_4bri_cleanup_adapter(a);
 378                        for (i = 1; i < (tasks - 1); i++) {
 379                                diva_os_free(0, adapter_list[i]);
 380                        }
 381                        return (-1);
 382                }
 383
 384                /*
 385                  Do not initialize second DPC - only one thread will be created
 386                */
 387                diva_current->xdi_adapter.isr_soft_isr.object =
 388                        diva_current->xdi_adapter.req_soft_isr.object;
 389        }
 390
 391        if (v2) {
 392                prepare_qBri2_functions(&a->xdi_adapter);
 393        } else {
 394                prepare_qBri_functions(&a->xdi_adapter);
 395        }
 396
 397        for (i = 0; i < tasks; i++) {
 398                diva_current = adapter_list[i];
 399                if (i)
 400                        memcpy(&diva_current->resources, &a->resources, sizeof(divas_card_resources_t));
 401                diva_current->resources.pci.qoffset = (a->xdi_adapter.MemorySize >> factor);
 402        }
 403
 404        /*
 405          Set up hardware related pointers
 406        */
 407        a->xdi_adapter.cfg = (void *) (unsigned long) a->resources.pci.bar[0];  /* BAR0 CONFIG */
 408        a->xdi_adapter.port = (void *) (unsigned long) a->resources.pci.bar[1]; /* BAR1        */
 409        a->xdi_adapter.ctlReg = (void *) (unsigned long) a->resources.pci.bar[3];       /* BAR3 CNTRL  */
 410
 411        for (i = 0; i < tasks; i++) {
 412                diva_current = adapter_list[i];
 413                diva_4bri_set_addresses(diva_current);
 414                Slave = a->xdi_adapter.QuadroList->QuadroAdapter[i];
 415                Slave->MultiMaster = &a->xdi_adapter;
 416                Slave->sdram_bar = a->xdi_adapter.sdram_bar;
 417                if (i) {
 418                        Slave->serialNo = ((dword) (Slave->ControllerNumber << 24)) |
 419                                a->xdi_adapter.serialNo;
 420                        Slave->cardType = a->xdi_adapter.cardType;
 421                }
 422        }
 423
 424        /*
 425          reset contains the base address for the PLX 9054 register set
 426        */
 427        p = DIVA_OS_MEM_ATTACH_RESET(&a->xdi_adapter);
 428        WRITE_BYTE(&p[PLX9054_INTCSR], 0x00);   /* disable PCI interrupts */
 429        DIVA_OS_MEM_DETACH_RESET(&a->xdi_adapter, p);
 430
 431        /*
 432          Set IRQ handler
 433        */
 434        a->xdi_adapter.irq_info.irq_nr = a->resources.pci.irq;
 435        sprintf(a->xdi_adapter.irq_info.irq_name, "DIVA 4BRI %ld",
 436                (long) a->xdi_adapter.serialNo);
 437
 438        if (diva_os_register_irq(a, a->xdi_adapter.irq_info.irq_nr,
 439                                 a->xdi_adapter.irq_info.irq_name)) {
 440                diva_4bri_cleanup_slave_adapters(a);
 441                diva_4bri_cleanup_adapter(a);
 442                for (i = 1; i < (tasks - 1); i++) {
 443                        diva_os_free(0, adapter_list[i]);
 444                }
 445                return (-1);
 446        }
 447
 448        a->xdi_adapter.irq_info.registered = 1;
 449
 450        /*
 451          Add three slave adapters
 452        */
 453        if (tasks > 1) {
 454                diva_add_slave_adapter(adapter_list[1]);
 455                diva_add_slave_adapter(adapter_list[2]);
 456                diva_add_slave_adapter(adapter_list[3]);
 457        }
 458
 459        diva_log_info("%s IRQ:%d SerNo:%d", a->xdi_adapter.Properties.Name,
 460                      a->resources.pci.irq, a->xdi_adapter.serialNo);
 461
 462        return (0);
 463}
 464
 465/*
 466**  Cleanup function will be called for master adapter only
 467**  this is guaranteed by design: cleanup callback is set
 468**  by master adapter only
 469*/
 470static int diva_4bri_cleanup_adapter(diva_os_xdi_adapter_t *a)
 471{
 472        int bar;
 473
 474        /*
 475          Stop adapter if running
 476        */
 477        if (a->xdi_adapter.Initialized) {
 478                diva_4bri_stop_adapter(a);
 479        }
 480
 481        /*
 482          Remove IRQ handler
 483        */
 484        if (a->xdi_adapter.irq_info.registered) {
 485                diva_os_remove_irq(a, a->xdi_adapter.irq_info.irq_nr);
 486        }
 487        a->xdi_adapter.irq_info.registered = 0;
 488
 489        /*
 490          Free DPC's and spin locks on all adapters
 491        */
 492        diva_4bri_cleanup_slave_adapters(a);
 493
 494        /*
 495          Unmap all BARS
 496        */
 497        for (bar = 0; bar < 4; bar++) {
 498                if (bar != 1) {
 499                        if (a->resources.pci.bar[bar]
 500                            && a->resources.pci.addr[bar]) {
 501                                divasa_unmap_pci_bar(a->resources.pci.addr[bar]);
 502                                a->resources.pci.bar[bar] = 0;
 503                                a->resources.pci.addr[bar] = NULL;
 504                        }
 505                }
 506        }
 507
 508        /*
 509          Unregister I/O
 510        */
 511        if (a->resources.pci.bar[1] && a->resources.pci.addr[1]) {
 512                diva_os_register_io_port(a, 0, a->resources.pci.bar[1],
 513                                         _4bri_is_rev_2_card(a->
 514                                                             CardOrdinal) ?
 515                                         _4bri_v2_bar_length[1] :
 516                                         _4bri_bar_length[1],
 517                                         &a->port_name[0], 1);
 518                a->resources.pci.bar[1] = 0;
 519                a->resources.pci.addr[1] = NULL;
 520        }
 521
 522        if (a->slave_list) {
 523                diva_os_free(0, a->slave_list);
 524                a->slave_list = NULL;
 525        }
 526
 527        return (0);
 528}
 529
 530static int _4bri_get_serial_number(diva_os_xdi_adapter_t *a)
 531{
 532        dword data[64];
 533        dword serNo;
 534        word addr, status, i, j;
 535        byte Bus, Slot;
 536        void *hdev;
 537
 538        Bus = a->resources.pci.bus;
 539        Slot = a->resources.pci.func;
 540        hdev = a->resources.pci.hdev;
 541
 542        for (i = 0; i < 64; ++i) {
 543                addr = i * 4;
 544                for (j = 0; j < 5; ++j) {
 545                        PCIwrite(Bus, Slot, 0x4E, &addr, sizeof(addr),
 546                                 hdev);
 547                        diva_os_wait(1);
 548                        PCIread(Bus, Slot, 0x4E, &status, sizeof(status),
 549                                hdev);
 550                        if (status & 0x8000)
 551                                break;
 552                }
 553                if (j >= 5) {
 554                        DBG_ERR(("EEPROM[%d] read failed (0x%x)", i * 4, addr))
 555                                return (0);
 556                }
 557                PCIread(Bus, Slot, 0x50, &data[i], sizeof(data[i]), hdev);
 558        }
 559        DBG_BLK(((char *) &data[0], sizeof(data)))
 560
 561                serNo = data[32];
 562        if (serNo == 0 || serNo == 0xffffffff)
 563                serNo = data[63];
 564
 565        if (!serNo) {
 566                DBG_LOG(("W: Serial Number == 0, create one serial number"));
 567                serNo = a->resources.pci.bar[1] & 0xffff0000;
 568                serNo |= a->resources.pci.bus << 8;
 569                serNo |= a->resources.pci.func;
 570        }
 571
 572        a->xdi_adapter.serialNo = serNo;
 573
 574        DBG_REG(("Serial No.          : %ld", a->xdi_adapter.serialNo))
 575
 576                return (serNo);
 577}
 578
 579/*
 580**  Release resources of slave adapters
 581*/
 582static int diva_4bri_cleanup_slave_adapters(diva_os_xdi_adapter_t *a)
 583{
 584        diva_os_xdi_adapter_t *adapter_list[4];
 585        diva_os_xdi_adapter_t *diva_current;
 586        int i;
 587
 588        adapter_list[0] = a;
 589        adapter_list[1] = a->slave_adapters[0];
 590        adapter_list[2] = a->slave_adapters[1];
 591        adapter_list[3] = a->slave_adapters[2];
 592
 593        for (i = 0; i < a->xdi_adapter.tasks; i++) {
 594                diva_current = adapter_list[i];
 595                if (diva_current) {
 596                        diva_os_destroy_spin_lock(&diva_current->
 597                                                  xdi_adapter.
 598                                                  isr_spin_lock, "unload");
 599                        diva_os_destroy_spin_lock(&diva_current->
 600                                                  xdi_adapter.
 601                                                  data_spin_lock,
 602                                                  "unload");
 603
 604                        diva_os_cancel_soft_isr(&diva_current->xdi_adapter.
 605                                                req_soft_isr);
 606                        diva_os_cancel_soft_isr(&diva_current->xdi_adapter.
 607                                                isr_soft_isr);
 608
 609                        diva_os_remove_soft_isr(&diva_current->xdi_adapter.
 610                                                req_soft_isr);
 611                        diva_current->xdi_adapter.isr_soft_isr.object = NULL;
 612
 613                        if (diva_current->xdi_adapter.e_tbl) {
 614                                diva_os_free(0,
 615                                             diva_current->xdi_adapter.
 616                                             e_tbl);
 617                        }
 618                        diva_current->xdi_adapter.e_tbl = NULL;
 619                        diva_current->xdi_adapter.e_max = 0;
 620                        diva_current->xdi_adapter.e_count = 0;
 621                }
 622        }
 623
 624        return (0);
 625}
 626
 627static int
 628diva_4bri_cmd_card_proc(struct _diva_os_xdi_adapter *a,
 629                        diva_xdi_um_cfg_cmd_t *cmd, int length)
 630{
 631        int ret = -1;
 632
 633        if (cmd->adapter != a->controller) {
 634                DBG_ERR(("A: 4bri_cmd, invalid controller=%d != %d",
 635                         cmd->adapter, a->controller))
 636                        return (-1);
 637        }
 638
 639        switch (cmd->command) {
 640        case DIVA_XDI_UM_CMD_GET_CARD_ORDINAL:
 641                a->xdi_mbox.data_length = sizeof(dword);
 642                a->xdi_mbox.data =
 643                        diva_os_malloc(0, a->xdi_mbox.data_length);
 644                if (a->xdi_mbox.data) {
 645                        *(dword *) a->xdi_mbox.data =
 646                                (dword) a->CardOrdinal;
 647                        a->xdi_mbox.status = DIVA_XDI_MBOX_BUSY;
 648                        ret = 0;
 649                }
 650                break;
 651
 652        case DIVA_XDI_UM_CMD_GET_SERIAL_NR:
 653                a->xdi_mbox.data_length = sizeof(dword);
 654                a->xdi_mbox.data =
 655                        diva_os_malloc(0, a->xdi_mbox.data_length);
 656                if (a->xdi_mbox.data) {
 657                        *(dword *) a->xdi_mbox.data =
 658                                (dword) a->xdi_adapter.serialNo;
 659                        a->xdi_mbox.status = DIVA_XDI_MBOX_BUSY;
 660                        ret = 0;
 661                }
 662                break;
 663
 664        case DIVA_XDI_UM_CMD_GET_PCI_HW_CONFIG:
 665                if (!a->xdi_adapter.ControllerNumber) {
 666                        /*
 667                          Only master adapter can access hardware config
 668                        */
 669                        a->xdi_mbox.data_length = sizeof(dword) * 9;
 670                        a->xdi_mbox.data =
 671                                diva_os_malloc(0, a->xdi_mbox.data_length);
 672                        if (a->xdi_mbox.data) {
 673                                int i;
 674                                dword *data = (dword *) a->xdi_mbox.data;
 675
 676                                for (i = 0; i < 8; i++) {
 677                                        *data++ = a->resources.pci.bar[i];
 678                                }
 679                                *data++ = (dword) a->resources.pci.irq;
 680                                a->xdi_mbox.status = DIVA_XDI_MBOX_BUSY;
 681                                ret = 0;
 682                        }
 683                }
 684                break;
 685
 686        case DIVA_XDI_UM_CMD_GET_CARD_STATE:
 687                if (!a->xdi_adapter.ControllerNumber) {
 688                        a->xdi_mbox.data_length = sizeof(dword);
 689                        a->xdi_mbox.data =
 690                                diva_os_malloc(0, a->xdi_mbox.data_length);
 691                        if (a->xdi_mbox.data) {
 692                                dword *data = (dword *) a->xdi_mbox.data;
 693                                if (!a->xdi_adapter.ram
 694                                    || !a->xdi_adapter.reset
 695                                    || !a->xdi_adapter.cfg) {
 696                                        *data = 3;
 697                                } else if (a->xdi_adapter.trapped) {
 698                                        *data = 2;
 699                                } else if (a->xdi_adapter.Initialized) {
 700                                        *data = 1;
 701                                } else {
 702                                        *data = 0;
 703                                }
 704                                a->xdi_mbox.status = DIVA_XDI_MBOX_BUSY;
 705                                ret = 0;
 706                        }
 707                }
 708                break;
 709
 710        case DIVA_XDI_UM_CMD_WRITE_FPGA:
 711                if (!a->xdi_adapter.ControllerNumber) {
 712                        ret =
 713                                diva_4bri_write_fpga_image(a,
 714                                                           (byte *)&cmd[1],
 715                                                           cmd->command_data.
 716                                                           write_fpga.
 717                                                           image_length);
 718                }
 719                break;
 720
 721        case DIVA_XDI_UM_CMD_RESET_ADAPTER:
 722                if (!a->xdi_adapter.ControllerNumber) {
 723                        ret = diva_4bri_reset_adapter(&a->xdi_adapter);
 724                }
 725                break;
 726
 727        case DIVA_XDI_UM_CMD_WRITE_SDRAM_BLOCK:
 728                if (!a->xdi_adapter.ControllerNumber) {
 729                        ret = diva_4bri_write_sdram_block(&a->xdi_adapter,
 730                                                          cmd->
 731                                                          command_data.
 732                                                          write_sdram.
 733                                                          offset,
 734                                                          (byte *) &
 735                                                          cmd[1],
 736                                                          cmd->
 737                                                          command_data.
 738                                                          write_sdram.
 739                                                          length,
 740                                                          a->xdi_adapter.
 741                                                          MemorySize);
 742                }
 743                break;
 744
 745        case DIVA_XDI_UM_CMD_START_ADAPTER:
 746                if (!a->xdi_adapter.ControllerNumber) {
 747                        ret = diva_4bri_start_adapter(&a->xdi_adapter,
 748                                                      cmd->command_data.
 749                                                      start.offset,
 750                                                      cmd->command_data.
 751                                                      start.features);
 752                }
 753                break;
 754
 755        case DIVA_XDI_UM_CMD_SET_PROTOCOL_FEATURES:
 756                if (!a->xdi_adapter.ControllerNumber) {
 757                        a->xdi_adapter.features =
 758                                cmd->command_data.features.features;
 759                        a->xdi_adapter.a.protocol_capabilities =
 760                                a->xdi_adapter.features;
 761                        DBG_TRC(("Set raw protocol features (%08x)",
 762                                 a->xdi_adapter.features))
 763                                ret = 0;
 764                }
 765                break;
 766
 767        case DIVA_XDI_UM_CMD_STOP_ADAPTER:
 768                if (!a->xdi_adapter.ControllerNumber) {
 769                        ret = diva_4bri_stop_adapter(a);
 770                }
 771                break;
 772
 773        case DIVA_XDI_UM_CMD_READ_XLOG_ENTRY:
 774                ret = diva_card_read_xlog(a);
 775                break;
 776
 777        case DIVA_XDI_UM_CMD_READ_SDRAM:
 778                if (!a->xdi_adapter.ControllerNumber
 779                    && a->xdi_adapter.Address) {
 780                        if (
 781                                (a->xdi_mbox.data_length =
 782                                 cmd->command_data.read_sdram.length)) {
 783                                if (
 784                                        (a->xdi_mbox.data_length +
 785                                         cmd->command_data.read_sdram.offset) <
 786                                        a->xdi_adapter.MemorySize) {
 787                                        a->xdi_mbox.data =
 788                                                diva_os_malloc(0,
 789                                                               a->xdi_mbox.
 790                                                               data_length);
 791                                        if (a->xdi_mbox.data) {
 792                                                byte __iomem *p = DIVA_OS_MEM_ATTACH_ADDRESS(&a->xdi_adapter);
 793                                                byte __iomem *src = p;
 794                                                byte *dst = a->xdi_mbox.data;
 795                                                dword len = a->xdi_mbox.data_length;
 796
 797                                                src += cmd->command_data.read_sdram.offset;
 798
 799                                                while (len--) {
 800                                                        *dst++ = READ_BYTE(src++);
 801                                                }
 802                                                DIVA_OS_MEM_DETACH_ADDRESS(&a->xdi_adapter, p);
 803                                                a->xdi_mbox.status = DIVA_XDI_MBOX_BUSY;
 804                                                ret = 0;
 805                                        }
 806                                }
 807                        }
 808                }
 809                break;
 810
 811        default:
 812                DBG_ERR(("A: A(%d) invalid cmd=%d", a->controller,
 813                         cmd->command))
 814                        }
 815
 816        return (ret);
 817}
 818
 819void *xdiLoadFile(char *FileName, dword *FileLength,
 820                  unsigned long lim)
 821{
 822        void *ret = diva_xdiLoadFileFile;
 823
 824        if (FileLength) {
 825                *FileLength = diva_xdiLoadFileLength;
 826        }
 827        diva_xdiLoadFileFile = NULL;
 828        diva_xdiLoadFileLength = 0;
 829
 830        return (ret);
 831}
 832
 833void diva_os_set_qBri_functions(PISDN_ADAPTER IoAdapter)
 834{
 835}
 836
 837void diva_os_set_qBri2_functions(PISDN_ADAPTER IoAdapter)
 838{
 839}
 840
 841static int
 842diva_4bri_write_fpga_image(diva_os_xdi_adapter_t *a, byte *data,
 843                           dword length)
 844{
 845        int ret;
 846
 847        diva_xdiLoadFileFile = data;
 848        diva_xdiLoadFileLength = length;
 849
 850        ret = qBri_FPGA_download(&a->xdi_adapter);
 851
 852        diva_xdiLoadFileFile = NULL;
 853        diva_xdiLoadFileLength = 0;
 854
 855        return (ret ? 0 : -1);
 856}
 857
 858static int diva_4bri_reset_adapter(PISDN_ADAPTER IoAdapter)
 859{
 860        PISDN_ADAPTER Slave;
 861        int i;
 862
 863        if (!IoAdapter->Address || !IoAdapter->reset) {
 864                return (-1);
 865        }
 866        if (IoAdapter->Initialized) {
 867                DBG_ERR(("A: A(%d) can't reset 4BRI adapter - please stop first",
 868                         IoAdapter->ANum))
 869                        return (-1);
 870        }
 871
 872        /*
 873          Forget all entities on all adapters
 874        */
 875        for (i = 0; ((i < IoAdapter->tasks) && IoAdapter->QuadroList); i++) {
 876                Slave = IoAdapter->QuadroList->QuadroAdapter[i];
 877                Slave->e_count = 0;
 878                if (Slave->e_tbl) {
 879                        memset(Slave->e_tbl, 0x00,
 880                               Slave->e_max * sizeof(E_INFO));
 881                }
 882                Slave->head = 0;
 883                Slave->tail = 0;
 884                Slave->assign = 0;
 885                Slave->trapped = 0;
 886
 887                memset(&Slave->a.IdTable[0], 0x00,
 888                       sizeof(Slave->a.IdTable));
 889                memset(&Slave->a.IdTypeTable[0], 0x00,
 890                       sizeof(Slave->a.IdTypeTable));
 891                memset(&Slave->a.FlowControlIdTable[0], 0x00,
 892                       sizeof(Slave->a.FlowControlIdTable));
 893                memset(&Slave->a.FlowControlSkipTable[0], 0x00,
 894                       sizeof(Slave->a.FlowControlSkipTable));
 895                memset(&Slave->a.misc_flags_table[0], 0x00,
 896                       sizeof(Slave->a.misc_flags_table));
 897                memset(&Slave->a.rx_stream[0], 0x00,
 898                       sizeof(Slave->a.rx_stream));
 899                memset(&Slave->a.tx_stream[0], 0x00,
 900                       sizeof(Slave->a.tx_stream));
 901                memset(&Slave->a.tx_pos[0], 0x00, sizeof(Slave->a.tx_pos));
 902                memset(&Slave->a.rx_pos[0], 0x00, sizeof(Slave->a.rx_pos));
 903        }
 904
 905        return (0);
 906}
 907
 908
 909static int
 910diva_4bri_write_sdram_block(PISDN_ADAPTER IoAdapter,
 911                            dword address,
 912                            const byte *data, dword length, dword limit)
 913{
 914        byte __iomem *p = DIVA_OS_MEM_ATTACH_ADDRESS(IoAdapter);
 915        byte __iomem *mem = p;
 916
 917        if (((address + length) >= limit) || !mem) {
 918                DIVA_OS_MEM_DETACH_ADDRESS(IoAdapter, p);
 919                DBG_ERR(("A: A(%d) write 4BRI address=0x%08lx",
 920                         IoAdapter->ANum, address + length))
 921                        return (-1);
 922        }
 923        mem += address;
 924
 925        while (length--) {
 926                WRITE_BYTE(mem++, *data++);
 927        }
 928
 929        DIVA_OS_MEM_DETACH_ADDRESS(IoAdapter, p);
 930        return (0);
 931}
 932
 933static int
 934diva_4bri_start_adapter(PISDN_ADAPTER IoAdapter,
 935                        dword start_address, dword features)
 936{
 937        volatile word __iomem *signature;
 938        int started = 0;
 939        int i;
 940        byte __iomem *p;
 941
 942        /*
 943          start adapter
 944        */
 945        start_qBri_hardware(IoAdapter);
 946
 947        p = DIVA_OS_MEM_ATTACH_RAM(IoAdapter);
 948        /*
 949          wait for signature in shared memory (max. 3 seconds)
 950        */
 951        signature = (volatile word __iomem *) (&p[0x1E]);
 952
 953        for (i = 0; i < 300; ++i) {
 954                diva_os_wait(10);
 955                if (READ_WORD(&signature[0]) == 0x4447) {
 956                        DBG_TRC(("Protocol startup time %d.%02d seconds",
 957                                 (i / 100), (i % 100)))
 958                                started = 1;
 959                        break;
 960                }
 961        }
 962
 963        for (i = 1; i < IoAdapter->tasks; i++) {
 964                IoAdapter->QuadroList->QuadroAdapter[i]->features =
 965                        IoAdapter->features;
 966                IoAdapter->QuadroList->QuadroAdapter[i]->a.
 967                        protocol_capabilities = IoAdapter->features;
 968        }
 969
 970        if (!started) {
 971                DBG_FTL(("%s: Adapter selftest failed, signature=%04x",
 972                         IoAdapter->Properties.Name,
 973                         READ_WORD(&signature[0])))
 974                        DIVA_OS_MEM_DETACH_RAM(IoAdapter, p);
 975                (*(IoAdapter->trapFnc)) (IoAdapter);
 976                IoAdapter->stop(IoAdapter);
 977                return (-1);
 978        }
 979        DIVA_OS_MEM_DETACH_RAM(IoAdapter, p);
 980
 981        for (i = 0; i < IoAdapter->tasks; i++) {
 982                IoAdapter->QuadroList->QuadroAdapter[i]->Initialized = 1;
 983                IoAdapter->QuadroList->QuadroAdapter[i]->IrqCount = 0;
 984        }
 985
 986        if (check_qBri_interrupt(IoAdapter)) {
 987                DBG_ERR(("A: A(%d) interrupt test failed",
 988                         IoAdapter->ANum))
 989                        for (i = 0; i < IoAdapter->tasks; i++) {
 990                                IoAdapter->QuadroList->QuadroAdapter[i]->Initialized = 0;
 991                        }
 992                IoAdapter->stop(IoAdapter);
 993                return (-1);
 994        }
 995
 996        IoAdapter->Properties.Features = (word) features;
 997        diva_xdi_display_adapter_features(IoAdapter->ANum);
 998
 999        for (i = 0; i < IoAdapter->tasks; i++) {
1000                DBG_LOG(("A(%d) %s adapter successfully started",
1001                         IoAdapter->QuadroList->QuadroAdapter[i]->ANum,
1002                         (IoAdapter->tasks == 1) ? "BRI 2.0" : "4BRI"))
1003                        diva_xdi_didd_register_adapter(IoAdapter->QuadroList->QuadroAdapter[i]->ANum);
1004                IoAdapter->QuadroList->QuadroAdapter[i]->Properties.Features = (word) features;
1005        }
1006
1007        return (0);
1008}
1009
1010static int check_qBri_interrupt(PISDN_ADAPTER IoAdapter)
1011{
1012#ifdef  SUPPORT_INTERRUPT_TEST_ON_4BRI
1013        int i;
1014        ADAPTER *a = &IoAdapter->a;
1015        byte __iomem *p;
1016
1017        IoAdapter->IrqCount = 0;
1018
1019        if (IoAdapter->ControllerNumber > 0)
1020                return (-1);
1021
1022        p = DIVA_OS_MEM_ATTACH_RESET(IoAdapter);
1023        WRITE_BYTE(&p[PLX9054_INTCSR], PLX9054_INT_ENABLE);
1024        DIVA_OS_MEM_DETACH_RESET(IoAdapter, p);
1025        /*
1026          interrupt test
1027        */
1028        a->ReadyInt = 1;
1029        a->ram_out(a, &PR_RAM->ReadyInt, 1);
1030
1031        for (i = 100; !IoAdapter->IrqCount && (i-- > 0); diva_os_wait(10));
1032
1033        return ((IoAdapter->IrqCount > 0) ? 0 : -1);
1034#else
1035        dword volatile __iomem *qBriIrq;
1036        byte __iomem *p;
1037        /*
1038          Reset on-board interrupt register
1039        */
1040        IoAdapter->IrqCount = 0;
1041        p = DIVA_OS_MEM_ATTACH_CTLREG(IoAdapter);
1042        qBriIrq = (dword volatile __iomem *) (&p[_4bri_is_rev_2_card
1043                                                 (IoAdapter->
1044                                                  cardType) ? (MQ2_BREG_IRQ_TEST)
1045                                                 : (MQ_BREG_IRQ_TEST)]);
1046
1047        WRITE_DWORD(qBriIrq, MQ_IRQ_REQ_OFF);
1048        DIVA_OS_MEM_DETACH_CTLREG(IoAdapter, p);
1049
1050        p = DIVA_OS_MEM_ATTACH_RESET(IoAdapter);
1051        WRITE_BYTE(&p[PLX9054_INTCSR], PLX9054_INT_ENABLE);
1052        DIVA_OS_MEM_DETACH_RESET(IoAdapter, p);
1053
1054        diva_os_wait(100);
1055
1056        return (0);
1057#endif                          /* SUPPORT_INTERRUPT_TEST_ON_4BRI */
1058}
1059
1060static void diva_4bri_clear_interrupts(diva_os_xdi_adapter_t *a)
1061{
1062        PISDN_ADAPTER IoAdapter = &a->xdi_adapter;
1063
1064        /*
1065          clear any pending interrupt
1066        */
1067        IoAdapter->disIrq(IoAdapter);
1068
1069        IoAdapter->tst_irq(&IoAdapter->a);
1070        IoAdapter->clr_irq(&IoAdapter->a);
1071        IoAdapter->tst_irq(&IoAdapter->a);
1072
1073        /*
1074          kill pending dpcs
1075        */
1076        diva_os_cancel_soft_isr(&IoAdapter->req_soft_isr);
1077        diva_os_cancel_soft_isr(&IoAdapter->isr_soft_isr);
1078}
1079
1080static int diva_4bri_stop_adapter(diva_os_xdi_adapter_t *a)
1081{
1082        PISDN_ADAPTER IoAdapter = &a->xdi_adapter;
1083        int i;
1084
1085        if (!IoAdapter->ram) {
1086                return (-1);
1087        }
1088
1089        if (!IoAdapter->Initialized) {
1090                DBG_ERR(("A: A(%d) can't stop PRI adapter - not running",
1091                         IoAdapter->ANum))
1092                        return (-1);    /* nothing to stop */
1093        }
1094
1095        for (i = 0; i < IoAdapter->tasks; i++) {
1096                IoAdapter->QuadroList->QuadroAdapter[i]->Initialized = 0;
1097        }
1098
1099        /*
1100          Disconnect Adapters from DIDD
1101        */
1102        for (i = 0; i < IoAdapter->tasks; i++) {
1103                diva_xdi_didd_remove_adapter(IoAdapter->QuadroList->QuadroAdapter[i]->ANum);
1104        }
1105
1106        i = 100;
1107
1108        /*
1109          Stop interrupts
1110        */
1111        a->clear_interrupts_proc = diva_4bri_clear_interrupts;
1112        IoAdapter->a.ReadyInt = 1;
1113        IoAdapter->a.ram_inc(&IoAdapter->a, &PR_RAM->ReadyInt);
1114        do {
1115                diva_os_sleep(10);
1116        } while (i-- && a->clear_interrupts_proc);
1117
1118        if (a->clear_interrupts_proc) {
1119                diva_4bri_clear_interrupts(a);
1120                a->clear_interrupts_proc = NULL;
1121                DBG_ERR(("A: A(%d) no final interrupt from 4BRI adapter",
1122                         IoAdapter->ANum))
1123                        }
1124        IoAdapter->a.ReadyInt = 0;
1125
1126        /*
1127          Stop and reset adapter
1128        */
1129        IoAdapter->stop(IoAdapter);
1130
1131        return (0);
1132}
1133