linux/drivers/isdn/hardware/eicon/os_pri.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/* $Id: os_pri.c,v 1.32 2004/03/21 17:26:01 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_pri.h"
  17#include "diva_pci.h"
  18#include "mi_pc.h"
  19#include "pc_maint.h"
  20#include "dsp_tst.h"
  21#include "diva_dma.h"
  22#include "dsrv_pri.h"
  23
  24/* --------------------------------------------------------------------------
  25   OS Dependent part of XDI driver for DIVA PRI Adapter
  26
  27   DSP detection/validation by Anthony Booth (Eicon Networks, www.eicon.com)
  28   -------------------------------------------------------------------------- */
  29
  30#define DIVA_PRI_NO_PCI_BIOS_WORKAROUND 1
  31
  32extern int diva_card_read_xlog(diva_os_xdi_adapter_t *a);
  33
  34/*
  35**  IMPORTS
  36*/
  37extern void prepare_pri_functions(PISDN_ADAPTER IoAdapter);
  38extern void prepare_pri2_functions(PISDN_ADAPTER IoAdapter);
  39extern void diva_xdi_display_adapter_features(int card);
  40
  41static int diva_pri_cleanup_adapter(diva_os_xdi_adapter_t *a);
  42static int diva_pri_cmd_card_proc(struct _diva_os_xdi_adapter *a,
  43                                  diva_xdi_um_cfg_cmd_t *cmd, int length);
  44static int pri_get_serial_number(diva_os_xdi_adapter_t *a);
  45static int diva_pri_stop_adapter(diva_os_xdi_adapter_t *a);
  46static dword diva_pri_detect_dsps(diva_os_xdi_adapter_t *a);
  47
  48/*
  49**  Check card revision
  50*/
  51static int pri_is_rev_2_card(int card_ordinal)
  52{
  53        switch (card_ordinal) {
  54        case CARDTYPE_DIVASRV_P_30M_V2_PCI:
  55        case CARDTYPE_DIVASRV_VOICE_P_30M_V2_PCI:
  56                return (1);
  57        }
  58        return (0);
  59}
  60
  61static void diva_pri_set_addresses(diva_os_xdi_adapter_t *a)
  62{
  63        a->resources.pci.mem_type_id[MEM_TYPE_ADDRESS] = 0;
  64        a->resources.pci.mem_type_id[MEM_TYPE_CONTROL] = 2;
  65        a->resources.pci.mem_type_id[MEM_TYPE_CONFIG] = 4;
  66        a->resources.pci.mem_type_id[MEM_TYPE_RAM] = 0;
  67        a->resources.pci.mem_type_id[MEM_TYPE_RESET] = 2;
  68        a->resources.pci.mem_type_id[MEM_TYPE_CFG] = 4;
  69        a->resources.pci.mem_type_id[MEM_TYPE_PROM] = 3;
  70
  71        a->xdi_adapter.Address = a->resources.pci.addr[0];
  72        a->xdi_adapter.Control = a->resources.pci.addr[2];
  73        a->xdi_adapter.Config = a->resources.pci.addr[4];
  74
  75        a->xdi_adapter.ram = a->resources.pci.addr[0];
  76        a->xdi_adapter.ram += MP_SHARED_RAM_OFFSET;
  77
  78        a->xdi_adapter.reset = a->resources.pci.addr[2];
  79        a->xdi_adapter.reset += MP_RESET;
  80
  81        a->xdi_adapter.cfg = a->resources.pci.addr[4];
  82        a->xdi_adapter.cfg += MP_IRQ_RESET;
  83
  84        a->xdi_adapter.sdram_bar = a->resources.pci.bar[0];
  85
  86        a->xdi_adapter.prom = a->resources.pci.addr[3];
  87}
  88
  89/*
  90**  BAR0 - SDRAM, MP_MEMORY_SIZE, MP2_MEMORY_SIZE by Rev.2
  91**  BAR1 - DEVICES,                             0x1000
  92**  BAR2 - CONTROL (REG), 0x2000
  93**  BAR3 - FLASH (REG),         0x8000
  94**  BAR4 - CONFIG (CFG),        0x1000
  95*/
  96int diva_pri_init_card(diva_os_xdi_adapter_t *a)
  97{
  98        int bar = 0;
  99        int pri_rev_2;
 100        unsigned long bar_length[5] = {
 101                MP_MEMORY_SIZE,
 102                0x1000,
 103                0x2000,
 104                0x8000,
 105                0x1000
 106        };
 107
 108        pri_rev_2 = pri_is_rev_2_card(a->CardOrdinal);
 109
 110        if (pri_rev_2) {
 111                bar_length[0] = MP2_MEMORY_SIZE;
 112        }
 113        /*
 114          Set properties
 115        */
 116        a->xdi_adapter.Properties = CardProperties[a->CardOrdinal];
 117        DBG_LOG(("Load %s", a->xdi_adapter.Properties.Name))
 118
 119                /*
 120                  First initialization step: get and check hardware resoures.
 121                  Do not map resources and do not acecess card at this step
 122                */
 123                for (bar = 0; bar < 5; bar++) {
 124                        a->resources.pci.bar[bar] =
 125                                divasa_get_pci_bar(a->resources.pci.bus,
 126                                                   a->resources.pci.func, bar,
 127                                                   a->resources.pci.hdev);
 128                        if (!a->resources.pci.bar[bar]
 129                            || (a->resources.pci.bar[bar] == 0xFFFFFFF0)) {
 130                                DBG_ERR(("A: invalid bar[%d]=%08x", bar,
 131                                         a->resources.pci.bar[bar]))
 132                                        return (-1);
 133                        }
 134                }
 135        a->resources.pci.irq =
 136                (byte) divasa_get_pci_irq(a->resources.pci.bus,
 137                                          a->resources.pci.func,
 138                                          a->resources.pci.hdev);
 139        if (!a->resources.pci.irq) {
 140                DBG_ERR(("A: invalid irq"));
 141                return (-1);
 142        }
 143
 144        /*
 145          Map all BAR's
 146        */
 147        for (bar = 0; bar < 5; bar++) {
 148                a->resources.pci.addr[bar] =
 149                        divasa_remap_pci_bar(a, bar, a->resources.pci.bar[bar],
 150                                             bar_length[bar]);
 151                if (!a->resources.pci.addr[bar]) {
 152                        DBG_ERR(("A: A(%d), can't map bar[%d]",
 153                                 a->controller, bar))
 154                                diva_pri_cleanup_adapter(a);
 155                        return (-1);
 156                }
 157        }
 158
 159        /*
 160          Set all memory areas
 161        */
 162        diva_pri_set_addresses(a);
 163
 164        /*
 165          Get Serial Number of this adapter
 166        */
 167        if (pri_get_serial_number(a)) {
 168                dword serNo;
 169                serNo = a->resources.pci.bar[1] & 0xffff0000;
 170                serNo |= ((dword) a->resources.pci.bus) << 8;
 171                serNo += (a->resources.pci.func + a->controller + 1);
 172                a->xdi_adapter.serialNo = serNo & ~0xFF000000;
 173                DBG_ERR(("A: A(%d) can't get Serial Number, generated serNo=%ld",
 174                         a->controller, a->xdi_adapter.serialNo))
 175                        }
 176
 177
 178        /*
 179          Initialize os objects
 180        */
 181        if (diva_os_initialize_spin_lock(&a->xdi_adapter.isr_spin_lock, "isr")) {
 182                diva_pri_cleanup_adapter(a);
 183                return (-1);
 184        }
 185        if (diva_os_initialize_spin_lock
 186            (&a->xdi_adapter.data_spin_lock, "data")) {
 187                diva_pri_cleanup_adapter(a);
 188                return (-1);
 189        }
 190
 191        strcpy(a->xdi_adapter.req_soft_isr.dpc_thread_name, "kdivasprid");
 192
 193        if (diva_os_initialize_soft_isr(&a->xdi_adapter.req_soft_isr,
 194                                        DIDpcRoutine, &a->xdi_adapter)) {
 195                diva_pri_cleanup_adapter(a);
 196                return (-1);
 197        }
 198
 199        /*
 200          Do not initialize second DPC - only one thread will be created
 201        */
 202        a->xdi_adapter.isr_soft_isr.object =
 203                a->xdi_adapter.req_soft_isr.object;
 204
 205        /*
 206          Next step of card initialization:
 207          set up all interface pointers
 208        */
 209        a->xdi_adapter.Channels = CardProperties[a->CardOrdinal].Channels;
 210        a->xdi_adapter.e_max = CardProperties[a->CardOrdinal].E_info;
 211
 212        a->xdi_adapter.e_tbl =
 213                diva_os_malloc(0, a->xdi_adapter.e_max * sizeof(E_INFO));
 214        if (!a->xdi_adapter.e_tbl) {
 215                diva_pri_cleanup_adapter(a);
 216                return (-1);
 217        }
 218        memset(a->xdi_adapter.e_tbl, 0x00, a->xdi_adapter.e_max * sizeof(E_INFO));
 219
 220        a->xdi_adapter.a.io = &a->xdi_adapter;
 221        a->xdi_adapter.DIRequest = request;
 222        a->interface.cleanup_adapter_proc = diva_pri_cleanup_adapter;
 223        a->interface.cmd_proc = diva_pri_cmd_card_proc;
 224
 225        if (pri_rev_2) {
 226                prepare_pri2_functions(&a->xdi_adapter);
 227        } else {
 228                prepare_pri_functions(&a->xdi_adapter);
 229        }
 230
 231        a->dsp_mask = diva_pri_detect_dsps(a);
 232
 233        /*
 234          Allocate DMA map
 235        */
 236        if (pri_rev_2) {
 237                diva_init_dma_map(a->resources.pci.hdev,
 238                                  (struct _diva_dma_map_entry **) &a->xdi_adapter.dma_map, 32);
 239        }
 240
 241        /*
 242          Set IRQ handler
 243        */
 244        a->xdi_adapter.irq_info.irq_nr = a->resources.pci.irq;
 245        sprintf(a->xdi_adapter.irq_info.irq_name,
 246                "DIVA PRI %ld", (long) a->xdi_adapter.serialNo);
 247
 248        if (diva_os_register_irq(a, a->xdi_adapter.irq_info.irq_nr,
 249                                 a->xdi_adapter.irq_info.irq_name)) {
 250                diva_pri_cleanup_adapter(a);
 251                return (-1);
 252        }
 253        a->xdi_adapter.irq_info.registered = 1;
 254
 255        diva_log_info("%s IRQ:%d SerNo:%d", a->xdi_adapter.Properties.Name,
 256                      a->resources.pci.irq, a->xdi_adapter.serialNo);
 257
 258        return (0);
 259}
 260
 261static int diva_pri_cleanup_adapter(diva_os_xdi_adapter_t *a)
 262{
 263        int bar = 0;
 264
 265        /*
 266          Stop Adapter if adapter is running
 267        */
 268        if (a->xdi_adapter.Initialized) {
 269                diva_pri_stop_adapter(a);
 270        }
 271
 272        /*
 273          Remove ISR Handler
 274        */
 275        if (a->xdi_adapter.irq_info.registered) {
 276                diva_os_remove_irq(a, a->xdi_adapter.irq_info.irq_nr);
 277        }
 278        a->xdi_adapter.irq_info.registered = 0;
 279
 280        /*
 281          Step 1: unmap all BAR's, if any was mapped
 282        */
 283        for (bar = 0; bar < 5; bar++) {
 284                if (a->resources.pci.bar[bar]
 285                    && a->resources.pci.addr[bar]) {
 286                        divasa_unmap_pci_bar(a->resources.pci.addr[bar]);
 287                        a->resources.pci.bar[bar] = 0;
 288                        a->resources.pci.addr[bar] = NULL;
 289                }
 290        }
 291
 292        /*
 293          Free OS objects
 294        */
 295        diva_os_cancel_soft_isr(&a->xdi_adapter.isr_soft_isr);
 296        diva_os_cancel_soft_isr(&a->xdi_adapter.req_soft_isr);
 297
 298        diva_os_remove_soft_isr(&a->xdi_adapter.req_soft_isr);
 299        a->xdi_adapter.isr_soft_isr.object = NULL;
 300
 301        diva_os_destroy_spin_lock(&a->xdi_adapter.isr_spin_lock, "rm");
 302        diva_os_destroy_spin_lock(&a->xdi_adapter.data_spin_lock, "rm");
 303
 304        /*
 305          Free memory accupied by XDI adapter
 306        */
 307        if (a->xdi_adapter.e_tbl) {
 308                diva_os_free(0, a->xdi_adapter.e_tbl);
 309                a->xdi_adapter.e_tbl = NULL;
 310        }
 311        a->xdi_adapter.Channels = 0;
 312        a->xdi_adapter.e_max = 0;
 313
 314
 315        /*
 316          Free adapter DMA map
 317        */
 318        diva_free_dma_map(a->resources.pci.hdev,
 319                          (struct _diva_dma_map_entry *) a->xdi_adapter.
 320                          dma_map);
 321        a->xdi_adapter.dma_map = NULL;
 322
 323
 324        /*
 325          Detach this adapter from debug driver
 326        */
 327
 328        return (0);
 329}
 330
 331/*
 332**  Activate On Board Boot Loader
 333*/
 334static int diva_pri_reset_adapter(PISDN_ADAPTER IoAdapter)
 335{
 336        dword i;
 337        struct mp_load __iomem *boot;
 338
 339        if (!IoAdapter->Address || !IoAdapter->reset) {
 340                return (-1);
 341        }
 342        if (IoAdapter->Initialized) {
 343                DBG_ERR(("A: A(%d) can't reset PRI adapter - please stop first",
 344                         IoAdapter->ANum))
 345                        return (-1);
 346        }
 347
 348        boot = (struct mp_load __iomem *) DIVA_OS_MEM_ATTACH_ADDRESS(IoAdapter);
 349        WRITE_DWORD(&boot->err, 0);
 350        DIVA_OS_MEM_DETACH_ADDRESS(IoAdapter, boot);
 351
 352        IoAdapter->rstFnc(IoAdapter);
 353
 354        diva_os_wait(10);
 355
 356        boot = (struct mp_load __iomem *) DIVA_OS_MEM_ATTACH_ADDRESS(IoAdapter);
 357        i = READ_DWORD(&boot->live);
 358
 359        diva_os_wait(10);
 360        if (i == READ_DWORD(&boot->live)) {
 361                DIVA_OS_MEM_DETACH_ADDRESS(IoAdapter, boot);
 362                DBG_ERR(("A: A(%d) CPU on PRI %ld is not alive!",
 363                         IoAdapter->ANum, IoAdapter->serialNo))
 364                        return (-1);
 365        }
 366        if (READ_DWORD(&boot->err)) {
 367                DBG_ERR(("A: A(%d) PRI %ld Board Selftest failed, error=%08lx",
 368                         IoAdapter->ANum, IoAdapter->serialNo,
 369                         READ_DWORD(&boot->err)))
 370                        DIVA_OS_MEM_DETACH_ADDRESS(IoAdapter, boot);
 371                return (-1);
 372        }
 373        DIVA_OS_MEM_DETACH_ADDRESS(IoAdapter, boot);
 374
 375        /*
 376          Forget all outstanding entities
 377        */
 378        IoAdapter->e_count = 0;
 379        if (IoAdapter->e_tbl) {
 380                memset(IoAdapter->e_tbl, 0x00,
 381                       IoAdapter->e_max * sizeof(E_INFO));
 382        }
 383        IoAdapter->head = 0;
 384        IoAdapter->tail = 0;
 385        IoAdapter->assign = 0;
 386        IoAdapter->trapped = 0;
 387
 388        memset(&IoAdapter->a.IdTable[0], 0x00,
 389               sizeof(IoAdapter->a.IdTable));
 390        memset(&IoAdapter->a.IdTypeTable[0], 0x00,
 391               sizeof(IoAdapter->a.IdTypeTable));
 392        memset(&IoAdapter->a.FlowControlIdTable[0], 0x00,
 393               sizeof(IoAdapter->a.FlowControlIdTable));
 394        memset(&IoAdapter->a.FlowControlSkipTable[0], 0x00,
 395               sizeof(IoAdapter->a.FlowControlSkipTable));
 396        memset(&IoAdapter->a.misc_flags_table[0], 0x00,
 397               sizeof(IoAdapter->a.misc_flags_table));
 398        memset(&IoAdapter->a.rx_stream[0], 0x00,
 399               sizeof(IoAdapter->a.rx_stream));
 400        memset(&IoAdapter->a.tx_stream[0], 0x00,
 401               sizeof(IoAdapter->a.tx_stream));
 402        memset(&IoAdapter->a.tx_pos[0], 0x00, sizeof(IoAdapter->a.tx_pos));
 403        memset(&IoAdapter->a.rx_pos[0], 0x00, sizeof(IoAdapter->a.rx_pos));
 404
 405        return (0);
 406}
 407
 408static int
 409diva_pri_write_sdram_block(PISDN_ADAPTER IoAdapter,
 410                           dword address,
 411                           const byte *data, dword length, dword limit)
 412{
 413        byte __iomem *p = DIVA_OS_MEM_ATTACH_ADDRESS(IoAdapter);
 414        byte __iomem *mem = p;
 415
 416        if (((address + length) >= limit) || !mem) {
 417                DIVA_OS_MEM_DETACH_ADDRESS(IoAdapter, p);
 418                DBG_ERR(("A: A(%d) write PRI address=0x%08lx",
 419                         IoAdapter->ANum, address + length))
 420                        return (-1);
 421        }
 422        mem += address;
 423
 424        /* memcpy_toio(), maybe? */
 425        while (length--) {
 426                WRITE_BYTE(mem++, *data++);
 427        }
 428
 429        DIVA_OS_MEM_DETACH_ADDRESS(IoAdapter, p);
 430        return (0);
 431}
 432
 433static int
 434diva_pri_start_adapter(PISDN_ADAPTER IoAdapter,
 435                       dword start_address, dword features)
 436{
 437        dword i;
 438        int started = 0;
 439        byte __iomem *p;
 440        struct mp_load __iomem *boot = (struct mp_load __iomem *) DIVA_OS_MEM_ATTACH_ADDRESS(IoAdapter);
 441        ADAPTER *a = &IoAdapter->a;
 442
 443        if (IoAdapter->Initialized) {
 444                DIVA_OS_MEM_DETACH_ADDRESS(IoAdapter, boot);
 445                DBG_ERR(("A: A(%d) pri_start_adapter, adapter already running",
 446                         IoAdapter->ANum))
 447                        return (-1);
 448        }
 449        if (!boot) {
 450                DIVA_OS_MEM_DETACH_ADDRESS(IoAdapter, boot);
 451                DBG_ERR(("A: PRI %ld can't start, adapter not mapped",
 452                         IoAdapter->serialNo))
 453                        return (-1);
 454        }
 455
 456        sprintf(IoAdapter->Name, "A(%d)", (int) IoAdapter->ANum);
 457        DBG_LOG(("A(%d) start PRI at 0x%08lx", IoAdapter->ANum,
 458                 start_address))
 459
 460                WRITE_DWORD(&boot->addr, start_address);
 461        WRITE_DWORD(&boot->cmd, 3);
 462
 463        for (i = 0; i < 300; ++i) {
 464                diva_os_wait(10);
 465                if ((READ_DWORD(&boot->signature) >> 16) == 0x4447) {
 466                        DBG_LOG(("A(%d) Protocol startup time %d.%02d seconds",
 467                                 IoAdapter->ANum, (i / 100), (i % 100)))
 468                                started = 1;
 469                        break;
 470                }
 471        }
 472
 473        if (!started) {
 474                byte __iomem *p = (byte __iomem *)boot;
 475                dword TrapId;
 476                dword debug;
 477                TrapId = READ_DWORD(&p[0x80]);
 478                debug = READ_DWORD(&p[0x1c]);
 479                DBG_ERR(("A(%d) Adapter start failed 0x%08lx, TrapId=%08lx, debug=%08lx",
 480                         IoAdapter->ANum, READ_DWORD(&boot->signature),
 481                         TrapId, debug))
 482                        DIVA_OS_MEM_DETACH_ADDRESS(IoAdapter, boot);
 483                if (IoAdapter->trapFnc) {
 484                        (*(IoAdapter->trapFnc)) (IoAdapter);
 485                }
 486                IoAdapter->stop(IoAdapter);
 487                return (-1);
 488        }
 489        DIVA_OS_MEM_DETACH_ADDRESS(IoAdapter, boot);
 490
 491        IoAdapter->Initialized = true;
 492
 493        /*
 494          Check Interrupt
 495        */
 496        IoAdapter->IrqCount = 0;
 497        p = DIVA_OS_MEM_ATTACH_CFG(IoAdapter);
 498        WRITE_DWORD(p, (dword)~0x03E00000);
 499        DIVA_OS_MEM_DETACH_CFG(IoAdapter, p);
 500        a->ReadyInt = 1;
 501        a->ram_out(a, &PR_RAM->ReadyInt, 1);
 502
 503        for (i = 100; !IoAdapter->IrqCount && (i-- > 0); diva_os_wait(10));
 504
 505        if (!IoAdapter->IrqCount) {
 506                DBG_ERR(("A: A(%d) interrupt test failed",
 507                         IoAdapter->ANum))
 508                        IoAdapter->Initialized = false;
 509                IoAdapter->stop(IoAdapter);
 510                return (-1);
 511        }
 512
 513        IoAdapter->Properties.Features = (word) features;
 514
 515        diva_xdi_display_adapter_features(IoAdapter->ANum);
 516
 517        DBG_LOG(("A(%d) PRI adapter successfully started", IoAdapter->ANum))
 518                /*
 519                  Register with DIDD
 520                */
 521                diva_xdi_didd_register_adapter(IoAdapter->ANum);
 522
 523        return (0);
 524}
 525
 526static void diva_pri_clear_interrupts(diva_os_xdi_adapter_t *a)
 527{
 528        PISDN_ADAPTER IoAdapter = &a->xdi_adapter;
 529
 530        /*
 531          clear any pending interrupt
 532        */
 533        IoAdapter->disIrq(IoAdapter);
 534
 535        IoAdapter->tst_irq(&IoAdapter->a);
 536        IoAdapter->clr_irq(&IoAdapter->a);
 537        IoAdapter->tst_irq(&IoAdapter->a);
 538
 539        /*
 540          kill pending dpcs
 541        */
 542        diva_os_cancel_soft_isr(&IoAdapter->req_soft_isr);
 543        diva_os_cancel_soft_isr(&IoAdapter->isr_soft_isr);
 544}
 545
 546/*
 547**  Stop Adapter, but do not unmap/unregister - adapter
 548**  will be restarted later
 549*/
 550static int diva_pri_stop_adapter(diva_os_xdi_adapter_t *a)
 551{
 552        PISDN_ADAPTER IoAdapter = &a->xdi_adapter;
 553        int i = 100;
 554
 555        if (!IoAdapter->ram) {
 556                return (-1);
 557        }
 558        if (!IoAdapter->Initialized) {
 559                DBG_ERR(("A: A(%d) can't stop PRI adapter - not running",
 560                         IoAdapter->ANum))
 561                        return (-1);    /* nothing to stop */
 562        }
 563        IoAdapter->Initialized = 0;
 564
 565        /*
 566          Disconnect Adapter from DIDD
 567        */
 568        diva_xdi_didd_remove_adapter(IoAdapter->ANum);
 569
 570        /*
 571          Stop interrupts
 572        */
 573        a->clear_interrupts_proc = diva_pri_clear_interrupts;
 574        IoAdapter->a.ReadyInt = 1;
 575        IoAdapter->a.ram_inc(&IoAdapter->a, &PR_RAM->ReadyInt);
 576        do {
 577                diva_os_sleep(10);
 578        } while (i-- && a->clear_interrupts_proc);
 579
 580        if (a->clear_interrupts_proc) {
 581                diva_pri_clear_interrupts(a);
 582                a->clear_interrupts_proc = NULL;
 583                DBG_ERR(("A: A(%d) no final interrupt from PRI adapter",
 584                         IoAdapter->ANum))
 585                        }
 586        IoAdapter->a.ReadyInt = 0;
 587
 588        /*
 589          Stop and reset adapter
 590        */
 591        IoAdapter->stop(IoAdapter);
 592
 593        return (0);
 594}
 595
 596/*
 597**  Process commands form configuration/download framework and from
 598**  user mode
 599**
 600**  return 0 on success
 601*/
 602static int
 603diva_pri_cmd_card_proc(struct _diva_os_xdi_adapter *a,
 604                       diva_xdi_um_cfg_cmd_t *cmd, int length)
 605{
 606        int ret = -1;
 607
 608        if (cmd->adapter != a->controller) {
 609                DBG_ERR(("A: pri_cmd, invalid controller=%d != %d",
 610                         cmd->adapter, a->controller))
 611                        return (-1);
 612        }
 613
 614        switch (cmd->command) {
 615        case DIVA_XDI_UM_CMD_GET_CARD_ORDINAL:
 616                a->xdi_mbox.data_length = sizeof(dword);
 617                a->xdi_mbox.data =
 618                        diva_os_malloc(0, a->xdi_mbox.data_length);
 619                if (a->xdi_mbox.data) {
 620                        *(dword *) a->xdi_mbox.data =
 621                                (dword) a->CardOrdinal;
 622                        a->xdi_mbox.status = DIVA_XDI_MBOX_BUSY;
 623                        ret = 0;
 624                }
 625                break;
 626
 627        case DIVA_XDI_UM_CMD_GET_SERIAL_NR:
 628                a->xdi_mbox.data_length = sizeof(dword);
 629                a->xdi_mbox.data =
 630                        diva_os_malloc(0, a->xdi_mbox.data_length);
 631                if (a->xdi_mbox.data) {
 632                        *(dword *) a->xdi_mbox.data =
 633                                (dword) a->xdi_adapter.serialNo;
 634                        a->xdi_mbox.status = DIVA_XDI_MBOX_BUSY;
 635                        ret = 0;
 636                }
 637                break;
 638
 639        case DIVA_XDI_UM_CMD_GET_PCI_HW_CONFIG:
 640                a->xdi_mbox.data_length = sizeof(dword) * 9;
 641                a->xdi_mbox.data =
 642                        diva_os_malloc(0, a->xdi_mbox.data_length);
 643                if (a->xdi_mbox.data) {
 644                        int i;
 645                        dword *data = (dword *) a->xdi_mbox.data;
 646
 647                        for (i = 0; i < 8; i++) {
 648                                *data++ = a->resources.pci.bar[i];
 649                        }
 650                        *data++ = (dword) a->resources.pci.irq;
 651                        a->xdi_mbox.status = DIVA_XDI_MBOX_BUSY;
 652                        ret = 0;
 653                }
 654                break;
 655
 656        case DIVA_XDI_UM_CMD_RESET_ADAPTER:
 657                ret = diva_pri_reset_adapter(&a->xdi_adapter);
 658                break;
 659
 660        case DIVA_XDI_UM_CMD_WRITE_SDRAM_BLOCK:
 661                ret = diva_pri_write_sdram_block(&a->xdi_adapter,
 662                                                 cmd->command_data.
 663                                                 write_sdram.offset,
 664                                                 (byte *)&cmd[1],
 665                                                 cmd->command_data.
 666                                                 write_sdram.length,
 667                                                 pri_is_rev_2_card(a->
 668                                                                   CardOrdinal)
 669                                                 ? MP2_MEMORY_SIZE :
 670                                                 MP_MEMORY_SIZE);
 671                break;
 672
 673        case DIVA_XDI_UM_CMD_STOP_ADAPTER:
 674                ret = diva_pri_stop_adapter(a);
 675                break;
 676
 677        case DIVA_XDI_UM_CMD_START_ADAPTER:
 678                ret = diva_pri_start_adapter(&a->xdi_adapter,
 679                                             cmd->command_data.start.
 680                                             offset,
 681                                             cmd->command_data.start.
 682                                             features);
 683                break;
 684
 685        case DIVA_XDI_UM_CMD_SET_PROTOCOL_FEATURES:
 686                a->xdi_adapter.features =
 687                        cmd->command_data.features.features;
 688                a->xdi_adapter.a.protocol_capabilities =
 689                        a->xdi_adapter.features;
 690                DBG_TRC(("Set raw protocol features (%08x)",
 691                         a->xdi_adapter.features))
 692                        ret = 0;
 693                break;
 694
 695        case DIVA_XDI_UM_CMD_GET_CARD_STATE:
 696                a->xdi_mbox.data_length = sizeof(dword);
 697                a->xdi_mbox.data =
 698                        diva_os_malloc(0, a->xdi_mbox.data_length);
 699                if (a->xdi_mbox.data) {
 700                        dword *data = (dword *) a->xdi_mbox.data;
 701                        if (!a->xdi_adapter.ram ||
 702                            !a->xdi_adapter.reset ||
 703                            !a->xdi_adapter.cfg) {
 704                                *data = 3;
 705                        } else if (a->xdi_adapter.trapped) {
 706                                *data = 2;
 707                        } else if (a->xdi_adapter.Initialized) {
 708                                *data = 1;
 709                        } else {
 710                                *data = 0;
 711                        }
 712                        a->xdi_mbox.status = DIVA_XDI_MBOX_BUSY;
 713                        ret = 0;
 714                }
 715                break;
 716
 717        case DIVA_XDI_UM_CMD_READ_XLOG_ENTRY:
 718                ret = diva_card_read_xlog(a);
 719                break;
 720
 721        case DIVA_XDI_UM_CMD_READ_SDRAM:
 722                if (a->xdi_adapter.Address) {
 723                        if (
 724                                (a->xdi_mbox.data_length =
 725                                 cmd->command_data.read_sdram.length)) {
 726                                if (
 727                                        (a->xdi_mbox.data_length +
 728                                         cmd->command_data.read_sdram.offset) <
 729                                        a->xdi_adapter.MemorySize) {
 730                                        a->xdi_mbox.data =
 731                                                diva_os_malloc(0,
 732                                                               a->xdi_mbox.
 733                                                               data_length);
 734                                        if (a->xdi_mbox.data) {
 735                                                byte __iomem *p = DIVA_OS_MEM_ATTACH_ADDRESS(&a->xdi_adapter);
 736                                                byte __iomem *src = p;
 737                                                byte *dst = a->xdi_mbox.data;
 738                                                dword len = a->xdi_mbox.data_length;
 739
 740                                                src += cmd->command_data.read_sdram.offset;
 741
 742                                                while (len--) {
 743                                                        *dst++ = READ_BYTE(src++);
 744                                                }
 745                                                a->xdi_mbox.status = DIVA_XDI_MBOX_BUSY;
 746                                                DIVA_OS_MEM_DETACH_ADDRESS(&a->xdi_adapter, p);
 747                                                ret = 0;
 748                                        }
 749                                }
 750                        }
 751                }
 752                break;
 753
 754        default:
 755                DBG_ERR(("A: A(%d) invalid cmd=%d", a->controller,
 756                         cmd->command))
 757                        }
 758
 759        return (ret);
 760}
 761
 762/*
 763**  Get Serial Number
 764*/
 765static int pri_get_serial_number(diva_os_xdi_adapter_t *a)
 766{
 767        byte data[64];
 768        int i;
 769        dword len = sizeof(data);
 770        volatile byte __iomem *config;
 771        volatile byte __iomem *flash;
 772        byte c;
 773
 774/*
 775 *  First set some GT6401x config registers before accessing the BOOT-ROM
 776 */
 777        config = DIVA_OS_MEM_ATTACH_CONFIG(&a->xdi_adapter);
 778        c = READ_BYTE(&config[0xc3c]);
 779        if (!(c & 0x08)) {
 780                WRITE_BYTE(&config[0xc3c], c);  /* Base Address enable register */
 781        }
 782        WRITE_BYTE(&config[LOW_BOOTCS_DREG], 0x00);
 783        WRITE_BYTE(&config[HI_BOOTCS_DREG], 0xFF);
 784        DIVA_OS_MEM_DETACH_CONFIG(&a->xdi_adapter, config);
 785/*
 786 *  Read only the last 64 bytes of manufacturing data
 787 */
 788        memset(data, '\0', len);
 789        flash = DIVA_OS_MEM_ATTACH_PROM(&a->xdi_adapter);
 790        for (i = 0; i < len; i++) {
 791                data[i] = READ_BYTE(&flash[0x8000 - len + i]);
 792        }
 793        DIVA_OS_MEM_DETACH_PROM(&a->xdi_adapter, flash);
 794
 795        config = DIVA_OS_MEM_ATTACH_CONFIG(&a->xdi_adapter);
 796        WRITE_BYTE(&config[LOW_BOOTCS_DREG], 0xFC);     /* Disable FLASH EPROM access */
 797        WRITE_BYTE(&config[HI_BOOTCS_DREG], 0xFF);
 798        DIVA_OS_MEM_DETACH_CONFIG(&a->xdi_adapter, config);
 799
 800        if (memcmp(&data[48], "DIVAserverPR", 12)) {
 801#if !defined(DIVA_PRI_NO_PCI_BIOS_WORKAROUND)   /* { */
 802                word cmd = 0, cmd_org;
 803                void *addr;
 804                dword addr1, addr3, addr4;
 805                byte Bus, Slot;
 806                void *hdev;
 807                addr4 = a->resources.pci.bar[4];
 808                addr3 = a->resources.pci.bar[3];        /* flash  */
 809                addr1 = a->resources.pci.bar[1];        /* unused */
 810
 811                DBG_ERR(("A: apply Compaq BIOS workaround"))
 812                        DBG_LOG(("%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
 813                                 data[0], data[1], data[2], data[3],
 814                                 data[4], data[5], data[6], data[7]))
 815
 816                        Bus = a->resources.pci.bus;
 817                Slot = a->resources.pci.func;
 818                hdev = a->resources.pci.hdev;
 819                PCIread(Bus, Slot, 0x04, &cmd_org, sizeof(cmd_org), hdev);
 820                PCIwrite(Bus, Slot, 0x04, &cmd, sizeof(cmd), hdev);
 821
 822                PCIwrite(Bus, Slot, 0x14, &addr4, sizeof(addr4), hdev);
 823                PCIwrite(Bus, Slot, 0x20, &addr1, sizeof(addr1), hdev);
 824
 825                PCIwrite(Bus, Slot, 0x04, &cmd_org, sizeof(cmd_org), hdev);
 826
 827                addr = a->resources.pci.addr[1];
 828                a->resources.pci.addr[1] = a->resources.pci.addr[4];
 829                a->resources.pci.addr[4] = addr;
 830
 831                addr1 = a->resources.pci.bar[1];
 832                a->resources.pci.bar[1] = a->resources.pci.bar[4];
 833                a->resources.pci.bar[4] = addr1;
 834
 835                /*
 836                  Try to read Flash again
 837                */
 838                len = sizeof(data);
 839
 840                config = DIVA_OS_MEM_ATTACH_CONFIG(&a->xdi_adapter);
 841                if (!(config[0xc3c] & 0x08)) {
 842                        config[0xc3c] |= 0x08;  /* Base Address enable register */
 843                }
 844                config[LOW_BOOTCS_DREG] = 0x00;
 845                config[HI_BOOTCS_DREG] = 0xFF;
 846                DIVA_OS_MEM_DETACH_CONFIG(&a->xdi_adapter, config);
 847
 848                memset(data, '\0', len);
 849                flash = DIVA_OS_MEM_ATTACH_PROM(&a->xdi_adapter);
 850                for (i = 0; i < len; i++) {
 851                        data[i] = flash[0x8000 - len + i];
 852                }
 853                DIVA_OS_MEM_ATTACH_PROM(&a->xdi_adapter, flash);
 854                config = DIVA_OS_MEM_ATTACH_CONFIG(&a->xdi_adapter);
 855                config[LOW_BOOTCS_DREG] = 0xFC;
 856                config[HI_BOOTCS_DREG] = 0xFF;
 857                DIVA_OS_MEM_DETACH_CONFIG(&a->xdi_adapter, config);
 858
 859                if (memcmp(&data[48], "DIVAserverPR", 12)) {
 860                        DBG_ERR(("A: failed to read serial number"))
 861                                DBG_LOG(("%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
 862                                         data[0], data[1], data[2], data[3],
 863                                         data[4], data[5], data[6], data[7]))
 864                                return (-1);
 865                }
 866#else                           /* } { */
 867                DBG_ERR(("A: failed to read DIVA signature word"))
 868                        DBG_LOG(("%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
 869                                 data[0], data[1], data[2], data[3],
 870                                 data[4], data[5], data[6], data[7]))
 871                        DBG_LOG(("%02x:%02x:%02x:%02x", data[47], data[46],
 872                                 data[45], data[44]))
 873#endif                          /* } */
 874                        }
 875
 876        a->xdi_adapter.serialNo =
 877                (data[47] << 24) | (data[46] << 16) | (data[45] << 8) |
 878                data[44];
 879        if (!a->xdi_adapter.serialNo
 880            || (a->xdi_adapter.serialNo == 0xffffffff)) {
 881                a->xdi_adapter.serialNo = 0;
 882                DBG_ERR(("A: failed to read serial number"))
 883                        return (-1);
 884        }
 885
 886        DBG_LOG(("Serial No.          : %ld", a->xdi_adapter.serialNo))
 887                DBG_TRC(("Board Revision      : %d.%02d", (int) data[41],
 888                         (int) data[40]))
 889                DBG_TRC(("PLD revision        : %d.%02d", (int) data[33],
 890                         (int) data[32]))
 891                DBG_TRC(("Boot loader version : %d.%02d", (int) data[37],
 892                         (int) data[36]))
 893
 894                DBG_TRC(("Manufacturing Date  : %d/%02d/%02d  (yyyy/mm/dd)",
 895                         (int) ((data[28] > 90) ? 1900 : 2000) +
 896                         (int) data[28], (int) data[29], (int) data[30]))
 897
 898                return (0);
 899}
 900
 901void diva_os_prepare_pri2_functions(PISDN_ADAPTER IoAdapter)
 902{
 903}
 904
 905void diva_os_prepare_pri_functions(PISDN_ADAPTER IoAdapter)
 906{
 907}
 908
 909/*
 910**  Checks presence of DSP on board
 911*/
 912static int
 913dsp_check_presence(volatile byte __iomem *addr, volatile byte __iomem *data, int dsp)
 914{
 915        word pattern;
 916
 917        WRITE_WORD(addr, 0x4000);
 918        WRITE_WORD(data, DSP_SIGNATURE_PROBE_WORD);
 919
 920        WRITE_WORD(addr, 0x4000);
 921        pattern = READ_WORD(data);
 922
 923        if (pattern != DSP_SIGNATURE_PROBE_WORD) {
 924                DBG_TRC(("W: DSP[%d] %04x(is) != %04x(should)",
 925                         dsp, pattern, DSP_SIGNATURE_PROBE_WORD))
 926                        return (-1);
 927        }
 928
 929        WRITE_WORD(addr, 0x4000);
 930        WRITE_WORD(data, ~DSP_SIGNATURE_PROBE_WORD);
 931
 932        WRITE_WORD(addr, 0x4000);
 933        pattern = READ_WORD(data);
 934
 935        if (pattern != (word)~DSP_SIGNATURE_PROBE_WORD) {
 936                DBG_ERR(("A: DSP[%d] %04x(is) != %04x(should)",
 937                         dsp, pattern, (word)~DSP_SIGNATURE_PROBE_WORD))
 938                        return (-2);
 939        }
 940
 941        DBG_TRC(("DSP[%d] present", dsp))
 942
 943                return (0);
 944}
 945
 946
 947/*
 948**  Check if DSP's are present and operating
 949**  Information about detected DSP's is returned as bit mask
 950**  Bit 0  - DSP1
 951**  ...
 952**  ...
 953**  ...
 954**  Bit 29 - DSP30
 955*/
 956static dword diva_pri_detect_dsps(diva_os_xdi_adapter_t *a)
 957{
 958        byte __iomem *base;
 959        byte __iomem *p;
 960        dword ret = 0;
 961        dword row_offset[7] = {
 962                0x00000000,
 963                0x00000800,     /* 1 - ROW 1 */
 964                0x00000840,     /* 2 - ROW 2 */
 965                0x00001000,     /* 3 - ROW 3 */
 966                0x00001040,     /* 4 - ROW 4 */
 967                0x00000000      /* 5 - ROW 0 */
 968        };
 969
 970        byte __iomem *dsp_addr_port;
 971        byte __iomem *dsp_data_port;
 972        byte row_state;
 973        int dsp_row = 0, dsp_index, dsp_num;
 974
 975        if (!a->xdi_adapter.Control || !a->xdi_adapter.reset) {
 976                return (0);
 977        }
 978
 979        p = DIVA_OS_MEM_ATTACH_RESET(&a->xdi_adapter);
 980        WRITE_BYTE(p, _MP_RISC_RESET | _MP_DSP_RESET);
 981        DIVA_OS_MEM_DETACH_RESET(&a->xdi_adapter, p);
 982        diva_os_wait(5);
 983
 984        base = DIVA_OS_MEM_ATTACH_CONTROL(&a->xdi_adapter);
 985
 986        for (dsp_num = 0; dsp_num < 30; dsp_num++) {
 987                dsp_row = dsp_num / 7 + 1;
 988                dsp_index = dsp_num % 7;
 989
 990                dsp_data_port = base;
 991                dsp_addr_port = base;
 992
 993                dsp_data_port += row_offset[dsp_row];
 994                dsp_addr_port += row_offset[dsp_row];
 995
 996                dsp_data_port += (dsp_index * 8);
 997                dsp_addr_port += (dsp_index * 8) + 0x80;
 998
 999                if (!dsp_check_presence
1000                    (dsp_addr_port, dsp_data_port, dsp_num + 1)) {
1001                        ret |= (1 << dsp_num);
1002                }
1003        }
1004        DIVA_OS_MEM_DETACH_CONTROL(&a->xdi_adapter, base);
1005
1006        p = DIVA_OS_MEM_ATTACH_RESET(&a->xdi_adapter);
1007        WRITE_BYTE(p, _MP_RISC_RESET | _MP_LED1 | _MP_LED2);
1008        DIVA_OS_MEM_DETACH_RESET(&a->xdi_adapter, p);
1009        diva_os_wait(5);
1010
1011        /*
1012          Verify modules
1013        */
1014        for (dsp_row = 0; dsp_row < 4; dsp_row++) {
1015                row_state = ((ret >> (dsp_row * 7)) & 0x7F);
1016                if (row_state && (row_state != 0x7F)) {
1017                        for (dsp_index = 0; dsp_index < 7; dsp_index++) {
1018                                if (!(row_state & (1 << dsp_index))) {
1019                                        DBG_ERR(("A: MODULE[%d]-DSP[%d] failed",
1020                                                 dsp_row + 1,
1021                                                 dsp_index + 1))
1022                                                }
1023                        }
1024                }
1025        }
1026
1027        if (!(ret & 0x10000000)) {
1028                DBG_ERR(("A: ON BOARD-DSP[1] failed"))
1029                        }
1030        if (!(ret & 0x20000000)) {
1031                DBG_ERR(("A: ON BOARD-DSP[2] failed"))
1032                        }
1033
1034        /*
1035          Print module population now
1036        */
1037        DBG_LOG(("+-----------------------+"))
1038                DBG_LOG(("| DSP MODULE POPULATION |"))
1039                DBG_LOG(("+-----------------------+"))
1040                DBG_LOG(("|  1  |  2  |  3  |  4  |"))
1041                DBG_LOG(("+-----------------------+"))
1042                DBG_LOG(("|  %s  |  %s  |  %s  |  %s  |",
1043                         ((ret >> (0 * 7)) & 0x7F) ? "Y" : "N",
1044                         ((ret >> (1 * 7)) & 0x7F) ? "Y" : "N",
1045                         ((ret >> (2 * 7)) & 0x7F) ? "Y" : "N",
1046                         ((ret >> (3 * 7)) & 0x7F) ? "Y" : "N"))
1047                DBG_LOG(("+-----------------------+"))
1048
1049                DBG_LOG(("DSP's(present-absent):%08x-%08x", ret,
1050                         ~ret & 0x3fffffff))
1051
1052                return (ret);
1053}
1054