linux/drivers/isdn/hardware/eicon/diva.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/* $Id: diva.c,v 1.21.4.1 2004/05/08 14:33:43 armin Exp $ */
   3
   4#define CARDTYPE_H_WANT_DATA            1
   5#define CARDTYPE_H_WANT_IDI_DATA        0
   6#define CARDTYPE_H_WANT_RESOURCE_DATA   0
   7#define CARDTYPE_H_WANT_FILE_DATA       0
   8
   9#include "platform.h"
  10#include "debuglib.h"
  11#include "cardtype.h"
  12#include "pc.h"
  13#include "di_defs.h"
  14#include "di.h"
  15#include "io.h"
  16#include "pc_maint.h"
  17#include "xdi_msg.h"
  18#include "xdi_adapter.h"
  19#include "diva_pci.h"
  20#include "diva.h"
  21
  22#ifdef CONFIG_ISDN_DIVAS_PRIPCI
  23#include "os_pri.h"
  24#endif
  25#ifdef CONFIG_ISDN_DIVAS_BRIPCI
  26#include "os_bri.h"
  27#include "os_4bri.h"
  28#endif
  29
  30PISDN_ADAPTER IoAdapters[MAX_ADAPTER];
  31extern IDI_CALL Requests[MAX_ADAPTER];
  32extern int create_adapter_proc(diva_os_xdi_adapter_t *a);
  33extern void remove_adapter_proc(diva_os_xdi_adapter_t *a);
  34
  35#define DivaIdiReqFunc(N)                                               \
  36        static void DivaIdiRequest##N(ENTITY *e)                        \
  37        { if (IoAdapters[N]) (*IoAdapters[N]->DIRequest)(IoAdapters[N], e); }
  38
  39/*
  40**  Create own 32 Adapters
  41*/
  42DivaIdiReqFunc(0)
  43DivaIdiReqFunc(1)
  44DivaIdiReqFunc(2)
  45DivaIdiReqFunc(3)
  46DivaIdiReqFunc(4)
  47DivaIdiReqFunc(5)
  48DivaIdiReqFunc(6)
  49DivaIdiReqFunc(7)
  50DivaIdiReqFunc(8)
  51DivaIdiReqFunc(9)
  52DivaIdiReqFunc(10)
  53DivaIdiReqFunc(11)
  54DivaIdiReqFunc(12)
  55DivaIdiReqFunc(13)
  56DivaIdiReqFunc(14)
  57DivaIdiReqFunc(15)
  58DivaIdiReqFunc(16)
  59DivaIdiReqFunc(17)
  60DivaIdiReqFunc(18)
  61DivaIdiReqFunc(19)
  62DivaIdiReqFunc(20)
  63DivaIdiReqFunc(21)
  64DivaIdiReqFunc(22)
  65DivaIdiReqFunc(23)
  66DivaIdiReqFunc(24)
  67DivaIdiReqFunc(25)
  68DivaIdiReqFunc(26)
  69DivaIdiReqFunc(27)
  70DivaIdiReqFunc(28)
  71DivaIdiReqFunc(29)
  72DivaIdiReqFunc(30)
  73DivaIdiReqFunc(31)
  74
  75/*
  76**  LOCALS
  77*/
  78static LIST_HEAD(adapter_queue);
  79
  80typedef struct _diva_get_xlog {
  81        word command;
  82        byte req;
  83        byte rc;
  84        byte data[sizeof(struct mi_pc_maint)];
  85} diva_get_xlog_t;
  86
  87typedef struct _diva_supported_cards_info {
  88        int CardOrdinal;
  89        diva_init_card_proc_t init_card;
  90} diva_supported_cards_info_t;
  91
  92static diva_supported_cards_info_t divas_supported_cards[] = {
  93#ifdef CONFIG_ISDN_DIVAS_PRIPCI
  94        /*
  95          PRI Cards
  96        */
  97        {CARDTYPE_DIVASRV_P_30M_PCI, diva_pri_init_card},
  98        /*
  99          PRI Rev.2 Cards
 100        */
 101        {CARDTYPE_DIVASRV_P_30M_V2_PCI, diva_pri_init_card},
 102        /*
 103          PRI Rev.2 VoIP Cards
 104        */
 105        {CARDTYPE_DIVASRV_VOICE_P_30M_V2_PCI, diva_pri_init_card},
 106#endif
 107#ifdef CONFIG_ISDN_DIVAS_BRIPCI
 108        /*
 109          4BRI Rev 1 Cards
 110        */
 111        {CARDTYPE_DIVASRV_Q_8M_PCI, diva_4bri_init_card},
 112        {CARDTYPE_DIVASRV_VOICE_Q_8M_PCI, diva_4bri_init_card},
 113        /*
 114          4BRI Rev 2 Cards
 115        */
 116        {CARDTYPE_DIVASRV_Q_8M_V2_PCI, diva_4bri_init_card},
 117        {CARDTYPE_DIVASRV_VOICE_Q_8M_V2_PCI, diva_4bri_init_card},
 118        /*
 119          4BRI Based BRI Rev 2 Cards
 120        */
 121        {CARDTYPE_DIVASRV_B_2M_V2_PCI, diva_4bri_init_card},
 122        {CARDTYPE_DIVASRV_B_2F_PCI, diva_4bri_init_card},
 123        {CARDTYPE_DIVASRV_VOICE_B_2M_V2_PCI, diva_4bri_init_card},
 124        /*
 125          BRI
 126        */
 127        {CARDTYPE_MAESTRA_PCI, diva_bri_init_card},
 128#endif
 129
 130        /*
 131          EOL
 132        */
 133        {-1}
 134};
 135
 136static void diva_init_request_array(void);
 137static void *divas_create_pci_card(int handle, void *pci_dev_handle);
 138
 139static diva_os_spin_lock_t adapter_lock;
 140
 141static int diva_find_free_adapters(int base, int nr)
 142{
 143        int i;
 144
 145        for (i = 0; i < nr; i++) {
 146                if (IoAdapters[base + i]) {
 147                        return (-1);
 148                }
 149        }
 150
 151        return (0);
 152}
 153
 154static diva_os_xdi_adapter_t *diva_q_get_next(struct list_head *what)
 155{
 156        diva_os_xdi_adapter_t *a = NULL;
 157
 158        if (what && (what->next != &adapter_queue))
 159                a = list_entry(what->next, diva_os_xdi_adapter_t, link);
 160
 161        return (a);
 162}
 163
 164/* --------------------------------------------------------------------------
 165   Add card to the card list
 166   -------------------------------------------------------------------------- */
 167void *diva_driver_add_card(void *pdev, unsigned long CardOrdinal)
 168{
 169        diva_os_spin_lock_magic_t old_irql;
 170        diva_os_xdi_adapter_t *pdiva, *pa;
 171        int i, j, max, nr;
 172
 173        for (i = 0; divas_supported_cards[i].CardOrdinal != -1; i++) {
 174                if (divas_supported_cards[i].CardOrdinal == CardOrdinal) {
 175                        if (!(pdiva = divas_create_pci_card(i, pdev))) {
 176                                return NULL;
 177                        }
 178                        switch (CardOrdinal) {
 179                        case CARDTYPE_DIVASRV_Q_8M_PCI:
 180                        case CARDTYPE_DIVASRV_VOICE_Q_8M_PCI:
 181                        case CARDTYPE_DIVASRV_Q_8M_V2_PCI:
 182                        case CARDTYPE_DIVASRV_VOICE_Q_8M_V2_PCI:
 183                                max = MAX_ADAPTER - 4;
 184                                nr = 4;
 185                                break;
 186
 187                        default:
 188                                max = MAX_ADAPTER;
 189                                nr = 1;
 190                        }
 191
 192                        diva_os_enter_spin_lock(&adapter_lock, &old_irql, "add card");
 193
 194                        for (i = 0; i < max; i++) {
 195                                if (!diva_find_free_adapters(i, nr)) {
 196                                        pdiva->controller = i + 1;
 197                                        pdiva->xdi_adapter.ANum = pdiva->controller;
 198                                        IoAdapters[i] = &pdiva->xdi_adapter;
 199                                        diva_os_leave_spin_lock(&adapter_lock, &old_irql, "add card");
 200                                        create_adapter_proc(pdiva);     /* add adapter to proc file system */
 201
 202                                        DBG_LOG(("add %s:%d",
 203                                                 CardProperties
 204                                                 [CardOrdinal].Name,
 205                                                 pdiva->controller))
 206
 207                                                diva_os_enter_spin_lock(&adapter_lock, &old_irql, "add card");
 208                                        pa = pdiva;
 209                                        for (j = 1; j < nr; j++) {      /* slave adapters, if any */
 210                                                pa = diva_q_get_next(&pa->link);
 211                                                if (pa && !pa->interface.cleanup_adapter_proc) {
 212                                                        pa->controller = i + 1 + j;
 213                                                        pa->xdi_adapter.ANum = pa->controller;
 214                                                        IoAdapters[i + j] = &pa->xdi_adapter;
 215                                                        diva_os_leave_spin_lock(&adapter_lock, &old_irql, "add card");
 216                                                        DBG_LOG(("add slave adapter (%d)",
 217                                                                 pa->controller))
 218                                                                create_adapter_proc(pa);        /* add adapter to proc file system */
 219                                                        diva_os_enter_spin_lock(&adapter_lock, &old_irql, "add card");
 220                                                } else {
 221                                                        DBG_ERR(("slave adapter problem"))
 222                                                                break;
 223                                                }
 224                                        }
 225
 226                                        diva_os_leave_spin_lock(&adapter_lock, &old_irql, "add card");
 227                                        return (pdiva);
 228                                }
 229                        }
 230
 231                        diva_os_leave_spin_lock(&adapter_lock, &old_irql, "add card");
 232
 233                        /*
 234                          Not able to add adapter - remove it and return error
 235                        */
 236                        DBG_ERR(("can not alloc request array"))
 237                                diva_driver_remove_card(pdiva);
 238
 239                        return NULL;
 240                }
 241        }
 242
 243        return NULL;
 244}
 245
 246/* --------------------------------------------------------------------------
 247   Called on driver load, MAIN, main, DriverEntry
 248   -------------------------------------------------------------------------- */
 249int divasa_xdi_driver_entry(void)
 250{
 251        diva_os_initialize_spin_lock(&adapter_lock, "adapter");
 252        memset(&IoAdapters[0], 0x00, sizeof(IoAdapters));
 253        diva_init_request_array();
 254
 255        return (0);
 256}
 257
 258/* --------------------------------------------------------------------------
 259   Remove adapter from list
 260   -------------------------------------------------------------------------- */
 261static diva_os_xdi_adapter_t *get_and_remove_from_queue(void)
 262{
 263        diva_os_spin_lock_magic_t old_irql;
 264        diva_os_xdi_adapter_t *a = NULL;
 265
 266        diva_os_enter_spin_lock(&adapter_lock, &old_irql, "driver_unload");
 267
 268        if (!list_empty(&adapter_queue)) {
 269                a = list_entry(adapter_queue.next, diva_os_xdi_adapter_t, link);
 270                list_del(adapter_queue.next);
 271        }
 272
 273        diva_os_leave_spin_lock(&adapter_lock, &old_irql, "driver_unload");
 274        return (a);
 275}
 276
 277/* --------------------------------------------------------------------------
 278   Remove card from the card list
 279   -------------------------------------------------------------------------- */
 280void diva_driver_remove_card(void *pdiva)
 281{
 282        diva_os_spin_lock_magic_t old_irql;
 283        diva_os_xdi_adapter_t *a[4];
 284        diva_os_xdi_adapter_t *pa;
 285        int i;
 286
 287        pa = a[0] = (diva_os_xdi_adapter_t *) pdiva;
 288        a[1] = a[2] = a[3] = NULL;
 289
 290        diva_os_enter_spin_lock(&adapter_lock, &old_irql, "remode adapter");
 291
 292        for (i = 1; i < 4; i++) {
 293                if ((pa = diva_q_get_next(&pa->link))
 294                    && !pa->interface.cleanup_adapter_proc) {
 295                        a[i] = pa;
 296                } else {
 297                        break;
 298                }
 299        }
 300
 301        for (i = 0; ((i < 4) && a[i]); i++) {
 302                list_del(&a[i]->link);
 303        }
 304
 305        diva_os_leave_spin_lock(&adapter_lock, &old_irql, "driver_unload");
 306
 307        (*(a[0]->interface.cleanup_adapter_proc)) (a[0]);
 308
 309        for (i = 0; i < 4; i++) {
 310                if (a[i]) {
 311                        if (a[i]->controller) {
 312                                DBG_LOG(("remove adapter (%d)",
 313                                         a[i]->controller)) IoAdapters[a[i]->controller - 1] = NULL;
 314                                remove_adapter_proc(a[i]);
 315                        }
 316                        diva_os_free(0, a[i]);
 317                }
 318        }
 319}
 320
 321/* --------------------------------------------------------------------------
 322   Create diva PCI adapter and init internal adapter structures
 323   -------------------------------------------------------------------------- */
 324static void *divas_create_pci_card(int handle, void *pci_dev_handle)
 325{
 326        diva_supported_cards_info_t *pI = &divas_supported_cards[handle];
 327        diva_os_spin_lock_magic_t old_irql;
 328        diva_os_xdi_adapter_t *a;
 329
 330        DBG_LOG(("found %d-%s", pI->CardOrdinal, CardProperties[pI->CardOrdinal].Name))
 331
 332                if (!(a = (diva_os_xdi_adapter_t *) diva_os_malloc(0, sizeof(*a)))) {
 333                        DBG_ERR(("A: can't alloc adapter"));
 334                        return NULL;
 335                }
 336
 337        memset(a, 0x00, sizeof(*a));
 338
 339        a->CardIndex = handle;
 340        a->CardOrdinal = pI->CardOrdinal;
 341        a->Bus = DIVAS_XDI_ADAPTER_BUS_PCI;
 342        a->xdi_adapter.cardType = a->CardOrdinal;
 343        a->resources.pci.bus = diva_os_get_pci_bus(pci_dev_handle);
 344        a->resources.pci.func = diva_os_get_pci_func(pci_dev_handle);
 345        a->resources.pci.hdev = pci_dev_handle;
 346
 347        /*
 348          Add master adapter first, so slave adapters will receive higher
 349          numbers as master adapter
 350        */
 351        diva_os_enter_spin_lock(&adapter_lock, &old_irql, "found_pci_card");
 352        list_add_tail(&a->link, &adapter_queue);
 353        diva_os_leave_spin_lock(&adapter_lock, &old_irql, "found_pci_card");
 354
 355        if ((*(pI->init_card)) (a)) {
 356                diva_os_enter_spin_lock(&adapter_lock, &old_irql, "found_pci_card");
 357                list_del(&a->link);
 358                diva_os_leave_spin_lock(&adapter_lock, &old_irql, "found_pci_card");
 359                diva_os_free(0, a);
 360                DBG_ERR(("A: can't get adapter resources"));
 361                return NULL;
 362        }
 363
 364        return (a);
 365}
 366
 367/* --------------------------------------------------------------------------
 368   Called on driver unload FINIT, finit, Unload
 369   -------------------------------------------------------------------------- */
 370void divasa_xdi_driver_unload(void)
 371{
 372        diva_os_xdi_adapter_t *a;
 373
 374        while ((a = get_and_remove_from_queue())) {
 375                if (a->interface.cleanup_adapter_proc) {
 376                        (*(a->interface.cleanup_adapter_proc)) (a);
 377                }
 378                if (a->controller) {
 379                        IoAdapters[a->controller - 1] = NULL;
 380                        remove_adapter_proc(a);
 381                }
 382                diva_os_free(0, a);
 383        }
 384        diva_os_destroy_spin_lock(&adapter_lock, "adapter");
 385}
 386
 387/*
 388**  Receive and process command from user mode utility
 389*/
 390void *diva_xdi_open_adapter(void *os_handle, const void __user *src,
 391                            int length, void *mptr,
 392                            divas_xdi_copy_from_user_fn_t cp_fn)
 393{
 394        diva_xdi_um_cfg_cmd_t *msg = (diva_xdi_um_cfg_cmd_t *)mptr;
 395        diva_os_xdi_adapter_t *a = NULL;
 396        diva_os_spin_lock_magic_t old_irql;
 397        struct list_head *tmp;
 398
 399        if (length < sizeof(diva_xdi_um_cfg_cmd_t)) {
 400                DBG_ERR(("A: A(?) open, msg too small (%d < %d)",
 401                         length, sizeof(diva_xdi_um_cfg_cmd_t)))
 402                        return NULL;
 403        }
 404        if ((*cp_fn) (os_handle, msg, src, sizeof(*msg)) <= 0) {
 405                DBG_ERR(("A: A(?) open, write error"))
 406                        return NULL;
 407        }
 408        diva_os_enter_spin_lock(&adapter_lock, &old_irql, "open_adapter");
 409        list_for_each(tmp, &adapter_queue) {
 410                a = list_entry(tmp, diva_os_xdi_adapter_t, link);
 411                if (a->controller == (int)msg->adapter)
 412                        break;
 413                a = NULL;
 414        }
 415        diva_os_leave_spin_lock(&adapter_lock, &old_irql, "open_adapter");
 416
 417        if (!a) {
 418                DBG_ERR(("A: A(%d) open, adapter not found", msg->adapter))
 419                        }
 420
 421        return (a);
 422}
 423
 424/*
 425**  Easy cleanup mailbox status
 426*/
 427void diva_xdi_close_adapter(void *adapter, void *os_handle)
 428{
 429        diva_os_xdi_adapter_t *a = (diva_os_xdi_adapter_t *) adapter;
 430
 431        a->xdi_mbox.status &= ~DIVA_XDI_MBOX_BUSY;
 432        if (a->xdi_mbox.data) {
 433                diva_os_free(0, a->xdi_mbox.data);
 434                a->xdi_mbox.data = NULL;
 435        }
 436}
 437
 438int
 439diva_xdi_write(void *adapter, void *os_handle, const void __user *src,
 440               int length, void *mptr,
 441               divas_xdi_copy_from_user_fn_t cp_fn)
 442{
 443        diva_xdi_um_cfg_cmd_t *msg = (diva_xdi_um_cfg_cmd_t *)mptr;
 444        diva_os_xdi_adapter_t *a = (diva_os_xdi_adapter_t *) adapter;
 445        void *data;
 446
 447        if (a->xdi_mbox.status & DIVA_XDI_MBOX_BUSY) {
 448                DBG_ERR(("A: A(%d) write, mbox busy", a->controller))
 449                        return (-1);
 450        }
 451
 452        if (length < sizeof(diva_xdi_um_cfg_cmd_t)) {
 453                DBG_ERR(("A: A(%d) write, message too small (%d < %d)",
 454                         a->controller, length,
 455                         sizeof(diva_xdi_um_cfg_cmd_t)))
 456                        return (-3);
 457        }
 458
 459        if (!(data = diva_os_malloc(0, length))) {
 460                DBG_ERR(("A: A(%d) write, ENOMEM", a->controller))
 461                        return (-2);
 462        }
 463
 464        if (msg) {
 465                *(diva_xdi_um_cfg_cmd_t *)data = *msg;
 466                length = (*cp_fn) (os_handle, (char *)data + sizeof(*msg),
 467                                   src + sizeof(*msg), length - sizeof(*msg));
 468        } else {
 469                length = (*cp_fn) (os_handle, data, src, length);
 470        }
 471        if (length > 0) {
 472                if ((*(a->interface.cmd_proc))
 473                    (a, (diva_xdi_um_cfg_cmd_t *) data, length)) {
 474                        length = -3;
 475                }
 476        } else {
 477                DBG_ERR(("A: A(%d) write error (%d)", a->controller,
 478                         length))
 479                        }
 480
 481        diva_os_free(0, data);
 482
 483        return (length);
 484}
 485
 486/*
 487**  Write answers to user mode utility, if any
 488*/
 489int
 490diva_xdi_read(void *adapter, void *os_handle, void __user *dst,
 491              int max_length, divas_xdi_copy_to_user_fn_t cp_fn)
 492{
 493        diva_os_xdi_adapter_t *a = (diva_os_xdi_adapter_t *) adapter;
 494        int ret;
 495
 496        if (!(a->xdi_mbox.status & DIVA_XDI_MBOX_BUSY)) {
 497                DBG_ERR(("A: A(%d) rx mbox empty", a->controller))
 498                        return (-1);
 499        }
 500        if (!a->xdi_mbox.data) {
 501                a->xdi_mbox.status &= ~DIVA_XDI_MBOX_BUSY;
 502                DBG_ERR(("A: A(%d) rx ENOMEM", a->controller))
 503                        return (-2);
 504        }
 505
 506        if (max_length < a->xdi_mbox.data_length) {
 507                DBG_ERR(("A: A(%d) rx buffer too short(%d < %d)",
 508                         a->controller, max_length,
 509                         a->xdi_mbox.data_length))
 510                        return (-3);
 511        }
 512
 513        ret = (*cp_fn) (os_handle, dst, a->xdi_mbox.data,
 514                        a->xdi_mbox.data_length);
 515        if (ret > 0) {
 516                diva_os_free(0, a->xdi_mbox.data);
 517                a->xdi_mbox.data = NULL;
 518                a->xdi_mbox.status &= ~DIVA_XDI_MBOX_BUSY;
 519        }
 520
 521        return (ret);
 522}
 523
 524
 525irqreturn_t diva_os_irq_wrapper(int irq, void *context)
 526{
 527        diva_os_xdi_adapter_t *a = context;
 528        diva_xdi_clear_interrupts_proc_t clear_int_proc;
 529
 530        if (!a || !a->xdi_adapter.diva_isr_handler)
 531                return IRQ_NONE;
 532
 533        if ((clear_int_proc = a->clear_interrupts_proc)) {
 534                (*clear_int_proc) (a);
 535                a->clear_interrupts_proc = NULL;
 536                return IRQ_HANDLED;
 537        }
 538
 539        (*(a->xdi_adapter.diva_isr_handler)) (&a->xdi_adapter);
 540        return IRQ_HANDLED;
 541}
 542
 543static void diva_init_request_array(void)
 544{
 545        Requests[0] = DivaIdiRequest0;
 546        Requests[1] = DivaIdiRequest1;
 547        Requests[2] = DivaIdiRequest2;
 548        Requests[3] = DivaIdiRequest3;
 549        Requests[4] = DivaIdiRequest4;
 550        Requests[5] = DivaIdiRequest5;
 551        Requests[6] = DivaIdiRequest6;
 552        Requests[7] = DivaIdiRequest7;
 553        Requests[8] = DivaIdiRequest8;
 554        Requests[9] = DivaIdiRequest9;
 555        Requests[10] = DivaIdiRequest10;
 556        Requests[11] = DivaIdiRequest11;
 557        Requests[12] = DivaIdiRequest12;
 558        Requests[13] = DivaIdiRequest13;
 559        Requests[14] = DivaIdiRequest14;
 560        Requests[15] = DivaIdiRequest15;
 561        Requests[16] = DivaIdiRequest16;
 562        Requests[17] = DivaIdiRequest17;
 563        Requests[18] = DivaIdiRequest18;
 564        Requests[19] = DivaIdiRequest19;
 565        Requests[20] = DivaIdiRequest20;
 566        Requests[21] = DivaIdiRequest21;
 567        Requests[22] = DivaIdiRequest22;
 568        Requests[23] = DivaIdiRequest23;
 569        Requests[24] = DivaIdiRequest24;
 570        Requests[25] = DivaIdiRequest25;
 571        Requests[26] = DivaIdiRequest26;
 572        Requests[27] = DivaIdiRequest27;
 573        Requests[28] = DivaIdiRequest28;
 574        Requests[29] = DivaIdiRequest29;
 575        Requests[30] = DivaIdiRequest30;
 576        Requests[31] = DivaIdiRequest31;
 577}
 578
 579void diva_xdi_display_adapter_features(int card)
 580{
 581        dword features;
 582        if (!card || ((card - 1) >= MAX_ADAPTER) || !IoAdapters[card - 1]) {
 583                return;
 584        }
 585        card--;
 586        features = IoAdapters[card]->Properties.Features;
 587
 588        DBG_LOG(("FEATURES FOR ADAPTER: %d", card + 1))
 589                DBG_LOG((" DI_FAX3          :  %s",
 590                         (features & DI_FAX3) ? "Y" : "N"))
 591                DBG_LOG((" DI_MODEM         :  %s",
 592                         (features & DI_MODEM) ? "Y" : "N"))
 593                DBG_LOG((" DI_POST          :  %s",
 594                         (features & DI_POST) ? "Y" : "N"))
 595                DBG_LOG((" DI_V110          :  %s",
 596                         (features & DI_V110) ? "Y" : "N"))
 597                DBG_LOG((" DI_V120          :  %s",
 598                         (features & DI_V120) ? "Y" : "N"))
 599                DBG_LOG((" DI_POTS          :  %s",
 600                         (features & DI_POTS) ? "Y" : "N"))
 601                DBG_LOG((" DI_CODEC         :  %s",
 602                         (features & DI_CODEC) ? "Y" : "N"))
 603                DBG_LOG((" DI_MANAGE        :  %s",
 604                         (features & DI_MANAGE) ? "Y" : "N"))
 605                DBG_LOG((" DI_V_42          :  %s",
 606                         (features & DI_V_42) ? "Y" : "N"))
 607                DBG_LOG((" DI_EXTD_FAX      :  %s",
 608                         (features & DI_EXTD_FAX) ? "Y" : "N"))
 609                DBG_LOG((" DI_AT_PARSER     :  %s",
 610                         (features & DI_AT_PARSER) ? "Y" : "N"))
 611                DBG_LOG((" DI_VOICE_OVER_IP :  %s",
 612                         (features & DI_VOICE_OVER_IP) ? "Y" : "N"))
 613                }
 614
 615void diva_add_slave_adapter(diva_os_xdi_adapter_t *a)
 616{
 617        diva_os_spin_lock_magic_t old_irql;
 618
 619        diva_os_enter_spin_lock(&adapter_lock, &old_irql, "add_slave");
 620        list_add_tail(&a->link, &adapter_queue);
 621        diva_os_leave_spin_lock(&adapter_lock, &old_irql, "add_slave");
 622}
 623
 624int diva_card_read_xlog(diva_os_xdi_adapter_t *a)
 625{
 626        diva_get_xlog_t *req;
 627        byte *data;
 628
 629        if (!a->xdi_adapter.Initialized || !a->xdi_adapter.DIRequest) {
 630                return (-1);
 631        }
 632        if (!(data = diva_os_malloc(0, sizeof(struct mi_pc_maint)))) {
 633                return (-1);
 634        }
 635        memset(data, 0x00, sizeof(struct mi_pc_maint));
 636
 637        if (!(req = diva_os_malloc(0, sizeof(*req)))) {
 638                diva_os_free(0, data);
 639                return (-1);
 640        }
 641        req->command = 0x0400;
 642        req->req = LOG;
 643        req->rc = 0x00;
 644
 645        (*(a->xdi_adapter.DIRequest)) (&a->xdi_adapter, (ENTITY *) req);
 646
 647        if (!req->rc || req->req) {
 648                diva_os_free(0, data);
 649                diva_os_free(0, req);
 650                return (-1);
 651        }
 652
 653        memcpy(data, &req->req, sizeof(struct mi_pc_maint));
 654
 655        diva_os_free(0, req);
 656
 657        a->xdi_mbox.data_length = sizeof(struct mi_pc_maint);
 658        a->xdi_mbox.data = data;
 659        a->xdi_mbox.status = DIVA_XDI_MBOX_BUSY;
 660
 661        return (0);
 662}
 663
 664void xdiFreeFile(void *handle)
 665{
 666}
 667