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