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