linux/drivers/isdn/hardware/eicon/io.c
<<
>>
Prefs
   1
   2/*
   3 *
   4 Copyright (c) Eicon Networks, 2002.
   5 *
   6 This source file is supplied for the use with
   7 Eicon Networks range of DIVA Server Adapters.
   8 *
   9 Eicon File Revision :    2.1
  10 *
  11 This program is free software; you can redistribute it and/or modify
  12 it under the terms of the GNU General Public License as published by
  13 the Free Software Foundation; either version 2, or (at your option)
  14 any later version.
  15 *
  16 This program is distributed in the hope that it will be useful,
  17 but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
  18 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  19 See the GNU General Public License for more details.
  20 *
  21 You should have received a copy of the GNU General Public License
  22 along with this program; if not, write to the Free Software
  23 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  24 *
  25 */
  26#include "platform.h"
  27#include "di_defs.h"
  28#include "pc.h"
  29#include "pr_pc.h"
  30#include "divasync.h"
  31#define MIPS_SCOM
  32#include "pkmaint.h" /* pc_main.h, packed in os-dependent fashion */
  33#include "di.h"
  34#include "mi_pc.h"
  35#include "io.h"
  36extern ADAPTER *adapter[MAX_ADAPTER];
  37extern PISDN_ADAPTER IoAdapters[MAX_ADAPTER];
  38void request(PISDN_ADAPTER, ENTITY *);
  39static void pcm_req(PISDN_ADAPTER, ENTITY *);
  40/* --------------------------------------------------------------------------
  41   local functions
  42   -------------------------------------------------------------------------- */
  43#define ReqFunc(N)                                                      \
  44        static void Request##N(ENTITY *e)                               \
  45        { if (IoAdapters[N]) (*IoAdapters[N]->DIRequest)(IoAdapters[N], e); }
  46ReqFunc(0)
  47ReqFunc(1)
  48ReqFunc(2)
  49ReqFunc(3)
  50ReqFunc(4)
  51ReqFunc(5)
  52ReqFunc(6)
  53ReqFunc(7)
  54ReqFunc(8)
  55ReqFunc(9)
  56ReqFunc(10)
  57ReqFunc(11)
  58ReqFunc(12)
  59ReqFunc(13)
  60ReqFunc(14)
  61ReqFunc(15)
  62IDI_CALL Requests[MAX_ADAPTER] =
  63{ &Request0, &Request1, &Request2, &Request3,
  64  &Request4, &Request5, &Request6, &Request7,
  65  &Request8, &Request9, &Request10, &Request11,
  66  &Request12, &Request13, &Request14, &Request15
  67};
  68/*****************************************************************************/
  69/*
  70  This array should indicate all new services, that this version of XDI
  71  is able to provide to his clients
  72*/
  73static byte extended_xdi_features[DIVA_XDI_EXTENDED_FEATURES_MAX_SZ + 1] = {
  74        (DIVA_XDI_EXTENDED_FEATURES_VALID       |
  75         DIVA_XDI_EXTENDED_FEATURE_SDRAM_BAR    |
  76         DIVA_XDI_EXTENDED_FEATURE_CAPI_PRMS    |
  77#if defined(DIVA_IDI_RX_DMA)
  78         DIVA_XDI_EXTENDED_FEATURE_CMA          |
  79         DIVA_XDI_EXTENDED_FEATURE_RX_DMA       |
  80         DIVA_XDI_EXTENDED_FEATURE_MANAGEMENT_DMA |
  81#endif
  82         DIVA_XDI_EXTENDED_FEATURE_NO_CANCEL_RC),
  83        0
  84};
  85/*****************************************************************************/
  86void
  87dump_xlog_buffer(PISDN_ADAPTER IoAdapter, Xdesc *xlogDesc)
  88{
  89        dword   logLen;
  90        word *Xlog   = xlogDesc->buf;
  91        word  logCnt = xlogDesc->cnt;
  92        word  logOut = xlogDesc->out / sizeof(*Xlog);
  93        DBG_FTL(("%s: ************* XLOG recovery (%d) *************",
  94                 &IoAdapter->Name[0], (int)logCnt))
  95                DBG_FTL(("Microcode: %s", &IoAdapter->ProtocolIdString[0]))
  96                for (; logCnt > 0; --logCnt)
  97                {
  98                        if (!GET_WORD(&Xlog[logOut]))
  99                        {
 100                                if (--logCnt == 0)
 101                                        break;
 102                                logOut = 0;
 103                        }
 104                        if (GET_WORD(&Xlog[logOut]) <= (logOut * sizeof(*Xlog)))
 105                        {
 106                                if (logCnt > 2)
 107                                {
 108                                        DBG_FTL(("Possibly corrupted XLOG: %d entries left",
 109                                                 (int)logCnt))
 110                                                }
 111                                break;
 112                        }
 113                        logLen = (dword)(GET_WORD(&Xlog[logOut]) - (logOut * sizeof(*Xlog)));
 114                        DBG_FTL_MXLOG(((char *)&Xlog[logOut + 1], (dword)(logLen - 2)))
 115                                logOut = (GET_WORD(&Xlog[logOut]) + 1) / sizeof(*Xlog);
 116                }
 117        DBG_FTL(("%s: ***************** end of XLOG *****************",
 118                 &IoAdapter->Name[0]))
 119                }
 120/*****************************************************************************/
 121#if defined(XDI_USE_XLOG)
 122static char *(ExceptionCauseTable[]) =
 123{
 124        "Interrupt",
 125        "TLB mod /IBOUND",
 126        "TLB load /DBOUND",
 127        "TLB store",
 128        "Address error load",
 129        "Address error store",
 130        "Instruction load bus error",
 131        "Data load/store bus error",
 132        "Syscall",
 133        "Breakpoint",
 134        "Reverd instruction",
 135        "Coprocessor unusable",
 136        "Overflow",
 137        "TRAP",
 138        "VCEI",
 139        "Floating Point Exception",
 140        "CP2",
 141        "Reserved 17",
 142        "Reserved 18",
 143        "Reserved 19",
 144        "Reserved 20",
 145        "Reserved 21",
 146        "Reserved 22",
 147        "WATCH",
 148        "Reserved 24",
 149        "Reserved 25",
 150        "Reserved 26",
 151        "Reserved 27",
 152        "Reserved 28",
 153        "Reserved 29",
 154        "Reserved 30",
 155        "VCED"
 156};
 157#endif
 158void
 159dump_trap_frame(PISDN_ADAPTER IoAdapter, byte __iomem *exceptionFrame)
 160{
 161        MP_XCPTC __iomem *xcept = (MP_XCPTC __iomem *)exceptionFrame;
 162        dword    __iomem *regs;
 163        regs  = &xcept->regs[0];
 164        DBG_FTL(("%s: ***************** CPU TRAPPED *****************",
 165                 &IoAdapter->Name[0]))
 166                DBG_FTL(("Microcode: %s", &IoAdapter->ProtocolIdString[0]))
 167                DBG_FTL(("Cause: %s",
 168                         ExceptionCauseTable[(READ_DWORD(&xcept->cr) & 0x0000007c) >> 2]))
 169                DBG_FTL(("sr    0x%08x cr    0x%08x epc   0x%08x vaddr 0x%08x",
 170                         READ_DWORD(&xcept->sr), READ_DWORD(&xcept->cr),
 171                         READ_DWORD(&xcept->epc), READ_DWORD(&xcept->vaddr)))
 172                DBG_FTL(("zero  0x%08x at    0x%08x v0    0x%08x v1    0x%08x",
 173                         READ_DWORD(&regs[0]), READ_DWORD(&regs[1]),
 174                         READ_DWORD(&regs[2]), READ_DWORD(&regs[3])))
 175                DBG_FTL(("a0    0x%08x a1    0x%08x a2    0x%08x a3    0x%08x",
 176                         READ_DWORD(&regs[4]), READ_DWORD(&regs[5]),
 177                         READ_DWORD(&regs[6]), READ_DWORD(&regs[7])))
 178                DBG_FTL(("t0    0x%08x t1    0x%08x t2    0x%08x t3    0x%08x",
 179                         READ_DWORD(&regs[8]), READ_DWORD(&regs[9]),
 180                         READ_DWORD(&regs[10]), READ_DWORD(&regs[11])))
 181                DBG_FTL(("t4    0x%08x t5    0x%08x t6    0x%08x t7    0x%08x",
 182                         READ_DWORD(&regs[12]), READ_DWORD(&regs[13]),
 183                         READ_DWORD(&regs[14]), READ_DWORD(&regs[15])))
 184                DBG_FTL(("s0    0x%08x s1    0x%08x s2    0x%08x s3    0x%08x",
 185                         READ_DWORD(&regs[16]), READ_DWORD(&regs[17]),
 186                         READ_DWORD(&regs[18]), READ_DWORD(&regs[19])))
 187                DBG_FTL(("s4    0x%08x s5    0x%08x s6    0x%08x s7    0x%08x",
 188                         READ_DWORD(&regs[20]), READ_DWORD(&regs[21]),
 189                         READ_DWORD(&regs[22]), READ_DWORD(&regs[23])))
 190                DBG_FTL(("t8    0x%08x t9    0x%08x k0    0x%08x k1    0x%08x",
 191                         READ_DWORD(&regs[24]), READ_DWORD(&regs[25]),
 192                         READ_DWORD(&regs[26]), READ_DWORD(&regs[27])))
 193                DBG_FTL(("gp    0x%08x sp    0x%08x s8    0x%08x ra    0x%08x",
 194                         READ_DWORD(&regs[28]), READ_DWORD(&regs[29]),
 195                         READ_DWORD(&regs[30]), READ_DWORD(&regs[31])))
 196                DBG_FTL(("md    0x%08x|%08x         resvd 0x%08x class 0x%08x",
 197                         READ_DWORD(&xcept->mdhi), READ_DWORD(&xcept->mdlo),
 198                         READ_DWORD(&xcept->reseverd), READ_DWORD(&xcept->xclass)))
 199                }
 200/* --------------------------------------------------------------------------
 201   Real XDI Request function
 202   -------------------------------------------------------------------------- */
 203void request(PISDN_ADAPTER IoAdapter, ENTITY *e)
 204{
 205        byte i;
 206        diva_os_spin_lock_magic_t irql;
 207/*
 208 * if the Req field in the entity structure is 0,
 209 * we treat this request as a special function call
 210 */
 211        if (!e->Req)
 212        {
 213                IDI_SYNC_REQ *syncReq = (IDI_SYNC_REQ *)e;
 214                switch (e->Rc)
 215                {
 216#if defined(DIVA_IDI_RX_DMA)
 217                case IDI_SYNC_REQ_DMA_DESCRIPTOR_OPERATION: {
 218                        diva_xdi_dma_descriptor_operation_t *pI = \
 219                                &syncReq->xdi_dma_descriptor_operation.info;
 220                        if (!IoAdapter->dma_map) {
 221                                pI->operation         = -1;
 222                                pI->descriptor_number = -1;
 223                                return;
 224                        }
 225                        diva_os_enter_spin_lock(&IoAdapter->data_spin_lock, &irql, "dma_op");
 226                        if (pI->operation == IDI_SYNC_REQ_DMA_DESCRIPTOR_ALLOC) {
 227                                pI->descriptor_number = diva_alloc_dma_map_entry(\
 228                                        (struct _diva_dma_map_entry *)IoAdapter->dma_map);
 229                                if (pI->descriptor_number >= 0) {
 230                                        dword dma_magic;
 231                                        void *local_addr;
 232                                        diva_get_dma_map_entry(\
 233                                                (struct _diva_dma_map_entry *)IoAdapter->dma_map,
 234                                                pI->descriptor_number,
 235                                                &local_addr, &dma_magic);
 236                                        pI->descriptor_address  = local_addr;
 237                                        pI->descriptor_magic    = dma_magic;
 238                                        pI->operation           = 0;
 239                                } else {
 240                                        pI->operation           = -1;
 241                                }
 242                        } else if ((pI->operation == IDI_SYNC_REQ_DMA_DESCRIPTOR_FREE) &&
 243                                   (pI->descriptor_number >= 0)) {
 244                                diva_free_dma_map_entry((struct _diva_dma_map_entry *)IoAdapter->dma_map,
 245                                                        pI->descriptor_number);
 246                                pI->descriptor_number = -1;
 247                                pI->operation         = 0;
 248                        } else {
 249                                pI->descriptor_number = -1;
 250                                pI->operation         = -1;
 251                        }
 252                        diva_os_leave_spin_lock(&IoAdapter->data_spin_lock, &irql, "dma_op");
 253                } return;
 254#endif
 255                case IDI_SYNC_REQ_XDI_GET_LOGICAL_ADAPTER_NUMBER: {
 256                        diva_xdi_get_logical_adapter_number_s_t *pI = \
 257                                &syncReq->xdi_logical_adapter_number.info;
 258                        pI->logical_adapter_number = IoAdapter->ANum;
 259                        pI->controller = IoAdapter->ControllerNumber;
 260                        pI->total_controllers = IoAdapter->Properties.Adapters;
 261                } return;
 262                case IDI_SYNC_REQ_XDI_GET_CAPI_PARAMS: {
 263                        diva_xdi_get_capi_parameters_t prms, *pI = &syncReq->xdi_capi_prms.info;
 264                        memset(&prms, 0x00, sizeof(prms));
 265                        prms.structure_length = min_t(size_t, sizeof(prms), pI->structure_length);
 266                        memset(pI, 0x00, pI->structure_length);
 267                        prms.flag_dynamic_l1_down    = (IoAdapter->capi_cfg.cfg_1 & \
 268                                                        DIVA_XDI_CAPI_CFG_1_DYNAMIC_L1_ON) ? 1 : 0;
 269                        prms.group_optimization_enabled = (IoAdapter->capi_cfg.cfg_1 & \
 270                                                           DIVA_XDI_CAPI_CFG_1_GROUP_POPTIMIZATION_ON) ? 1 : 0;
 271                        memcpy(pI, &prms, prms.structure_length);
 272                } return;
 273                case IDI_SYNC_REQ_XDI_GET_ADAPTER_SDRAM_BAR:
 274                        syncReq->xdi_sdram_bar.info.bar = IoAdapter->sdram_bar;
 275                        return;
 276                case IDI_SYNC_REQ_XDI_GET_EXTENDED_FEATURES: {
 277                        dword i;
 278                        diva_xdi_get_extended_xdi_features_t *pI =\
 279                                &syncReq->xdi_extended_features.info;
 280                        pI->buffer_length_in_bytes &= ~0x80000000;
 281                        if (pI->buffer_length_in_bytes && pI->features) {
 282                                memset(pI->features, 0x00, pI->buffer_length_in_bytes);
 283                        }
 284                        for (i = 0; ((pI->features) && (i < pI->buffer_length_in_bytes) &&
 285                                     (i < DIVA_XDI_EXTENDED_FEATURES_MAX_SZ)); i++) {
 286                                pI->features[i] = extended_xdi_features[i];
 287                        }
 288                        if ((pI->buffer_length_in_bytes < DIVA_XDI_EXTENDED_FEATURES_MAX_SZ) ||
 289                            (!pI->features)) {
 290                                pI->buffer_length_in_bytes =\
 291                                        (0x80000000 | DIVA_XDI_EXTENDED_FEATURES_MAX_SZ);
 292                        }
 293                } return;
 294                case IDI_SYNC_REQ_XDI_GET_STREAM:
 295                        if (IoAdapter) {
 296                                diva_xdi_provide_istream_info(&IoAdapter->a,
 297                                                              &syncReq->xdi_stream_info.info);
 298                        } else {
 299                                syncReq->xdi_stream_info.info.provided_service = 0;
 300                        }
 301                        return;
 302                case IDI_SYNC_REQ_GET_NAME:
 303                        if (IoAdapter)
 304                        {
 305                                strcpy(&syncReq->GetName.name[0], IoAdapter->Name);
 306                                DBG_TRC(("xdi: Adapter %d / Name '%s'",
 307                                         IoAdapter->ANum, IoAdapter->Name))
 308                                        return;
 309                        }
 310                        syncReq->GetName.name[0] = '\0';
 311                        break;
 312                case IDI_SYNC_REQ_GET_SERIAL:
 313                        if (IoAdapter)
 314                        {
 315                                syncReq->GetSerial.serial = IoAdapter->serialNo;
 316                                DBG_TRC(("xdi: Adapter %d / SerialNo %ld",
 317                                         IoAdapter->ANum, IoAdapter->serialNo))
 318                                        return;
 319                        }
 320                        syncReq->GetSerial.serial = 0;
 321                        break;
 322                case IDI_SYNC_REQ_GET_CARDTYPE:
 323                        if (IoAdapter)
 324                        {
 325                                syncReq->GetCardType.cardtype = IoAdapter->cardType;
 326                                DBG_TRC(("xdi: Adapter %d / CardType %ld",
 327                                         IoAdapter->ANum, IoAdapter->cardType))
 328                                        return;
 329                        }
 330                        syncReq->GetCardType.cardtype = 0;
 331                        break;
 332                case IDI_SYNC_REQ_GET_XLOG:
 333                        if (IoAdapter)
 334                        {
 335                                pcm_req(IoAdapter, e);
 336                                return;
 337                        }
 338                        e->Ind = 0;
 339                        break;
 340                case IDI_SYNC_REQ_GET_DBG_XLOG:
 341                        if (IoAdapter)
 342                        {
 343                                pcm_req(IoAdapter, e);
 344                                return;
 345                        }
 346                        e->Ind = 0;
 347                        break;
 348                case IDI_SYNC_REQ_GET_FEATURES:
 349                        if (IoAdapter)
 350                        {
 351                                syncReq->GetFeatures.features =
 352                                        (unsigned short)IoAdapter->features;
 353                                return;
 354                        }
 355                        syncReq->GetFeatures.features = 0;
 356                        break;
 357                case IDI_SYNC_REQ_PORTDRV_HOOK:
 358                        if (IoAdapter)
 359                        {
 360                                DBG_TRC(("Xdi:IDI_SYNC_REQ_PORTDRV_HOOK - ignored"))
 361                                        return;
 362                        }
 363                        break;
 364                }
 365                if (IoAdapter)
 366                {
 367                        return;
 368                }
 369        }
 370        DBG_TRC(("xdi: Id 0x%x / Req 0x%x / Rc 0x%x", e->Id, e->Req, e->Rc))
 371                if (!IoAdapter)
 372                {
 373                        DBG_FTL(("xdi: uninitialized Adapter used - ignore request"))
 374                                return;
 375                }
 376        diva_os_enter_spin_lock(&IoAdapter->data_spin_lock, &irql, "data_req");
 377/*
 378 * assign an entity
 379 */
 380        if (!(e->Id & 0x1f))
 381        {
 382                if (IoAdapter->e_count >= IoAdapter->e_max)
 383                {
 384                        DBG_FTL(("xdi: all Ids in use (max=%d) --> Req ignored",
 385                                 IoAdapter->e_max))
 386                                diva_os_leave_spin_lock(&IoAdapter->data_spin_lock, &irql, "data_req");
 387                        return;
 388                }
 389/*
 390 * find a new free id
 391 */
 392                for (i = 1; IoAdapter->e_tbl[i].e; ++i);
 393                IoAdapter->e_tbl[i].e = e;
 394                IoAdapter->e_count++;
 395                e->No = (byte)i;
 396                e->More = 0;
 397                e->RCurrent = 0xff;
 398        }
 399        else
 400        {
 401                i = e->No;
 402        }
 403/*
 404 * if the entity is still busy, ignore the request call
 405 */
 406        if (e->More & XBUSY)
 407        {
 408                DBG_FTL(("xdi: Id 0x%x busy --> Req 0x%x ignored", e->Id, e->Req))
 409                        if (!IoAdapter->trapped && IoAdapter->trapFnc)
 410                        {
 411                                IoAdapter->trapFnc(IoAdapter);
 412                                /*
 413                                  Firs trap, also notify user if supported
 414                                */
 415                                if (IoAdapter->trapped && IoAdapter->os_trap_nfy_Fnc) {
 416                                        (*(IoAdapter->os_trap_nfy_Fnc))(IoAdapter, IoAdapter->ANum);
 417                                }
 418                        }
 419                diva_os_leave_spin_lock(&IoAdapter->data_spin_lock, &irql, "data_req");
 420                return;
 421        }
 422/*
 423 * initialize transmit status variables
 424 */
 425        e->More |= XBUSY;
 426        e->More &= ~XMOREF;
 427        e->XCurrent = 0;
 428        e->XOffset = 0;
 429/*
 430 * queue this entity in the adapter request queue
 431 */
 432        IoAdapter->e_tbl[i].next = 0;
 433        if (IoAdapter->head)
 434        {
 435                IoAdapter->e_tbl[IoAdapter->tail].next = i;
 436                IoAdapter->tail = i;
 437        }
 438        else
 439        {
 440                IoAdapter->head = i;
 441                IoAdapter->tail = i;
 442        }
 443/*
 444 * queue the DPC to process the request
 445 */
 446        diva_os_schedule_soft_isr(&IoAdapter->req_soft_isr);
 447        diva_os_leave_spin_lock(&IoAdapter->data_spin_lock, &irql, "data_req");
 448}
 449/* ---------------------------------------------------------------------
 450   Main DPC routine
 451   --------------------------------------------------------------------- */
 452void DIDpcRoutine(struct _diva_os_soft_isr *psoft_isr, void *Context) {
 453        PISDN_ADAPTER IoAdapter = (PISDN_ADAPTER)Context;
 454        ADAPTER *a = &IoAdapter->a;
 455        diva_os_atomic_t *pin_dpc = &IoAdapter->in_dpc;
 456        if (diva_os_atomic_increment(pin_dpc) == 1) {
 457                do {
 458                        if (IoAdapter->tst_irq(a))
 459                        {
 460                                if (!IoAdapter->Unavailable)
 461                                        IoAdapter->dpc(a);
 462                                IoAdapter->clr_irq(a);
 463                        }
 464                        IoAdapter->out(a);
 465                } while (diva_os_atomic_decrement(pin_dpc) > 0);
 466                /* ----------------------------------------------------------------
 467                   Look for XLOG request (cards with indirect addressing)
 468                   ---------------------------------------------------------------- */
 469                if (IoAdapter->pcm_pending) {
 470                        struct pc_maint *pcm;
 471                        diva_os_spin_lock_magic_t OldIrql;
 472                        diva_os_enter_spin_lock(&IoAdapter->data_spin_lock,
 473                                                &OldIrql,
 474                                                "data_dpc");
 475                        pcm = (struct pc_maint *)IoAdapter->pcm_data;
 476                        switch (IoAdapter->pcm_pending) {
 477                        case 1: /* ask card for XLOG */
 478                                a->ram_out(a, &IoAdapter->pcm->rc, 0);
 479                                a->ram_out(a, &IoAdapter->pcm->req, pcm->req);
 480                                IoAdapter->pcm_pending = 2;
 481                                break;
 482                        case 2: /* Try to get XLOG from the card */
 483                                if ((int)(a->ram_in(a, &IoAdapter->pcm->rc))) {
 484                                        a->ram_in_buffer(a, IoAdapter->pcm, pcm, sizeof(*pcm));
 485                                        IoAdapter->pcm_pending = 3;
 486                                }
 487                                break;
 488                        case 3: /* let XDI recovery XLOG */
 489                                break;
 490                        }
 491                        diva_os_leave_spin_lock(&IoAdapter->data_spin_lock,
 492                                                &OldIrql,
 493                                                "data_dpc");
 494                }
 495                /* ---------------------------------------------------------------- */
 496        }
 497}
 498/* --------------------------------------------------------------------------
 499   XLOG interface
 500   -------------------------------------------------------------------------- */
 501static void
 502pcm_req(PISDN_ADAPTER IoAdapter, ENTITY *e)
 503{
 504        diva_os_spin_lock_magic_t OldIrql;
 505        int              i, rc;
 506        ADAPTER         *a = &IoAdapter->a;
 507        struct pc_maint *pcm = (struct pc_maint *)&e->Ind;
 508/*
 509 * special handling of I/O based card interface
 510 * the memory access isn't an atomic operation !
 511 */
 512        if (IoAdapter->Properties.Card == CARD_MAE)
 513        {
 514                diva_os_enter_spin_lock(&IoAdapter->data_spin_lock,
 515                                        &OldIrql,
 516                                        "data_pcm_1");
 517                IoAdapter->pcm_data = (void *)pcm;
 518                IoAdapter->pcm_pending = 1;
 519                diva_os_schedule_soft_isr(&IoAdapter->req_soft_isr);
 520                diva_os_leave_spin_lock(&IoAdapter->data_spin_lock,
 521                                        &OldIrql,
 522                                        "data_pcm_1");
 523                for (rc = 0, i = (IoAdapter->trapped ? 3000 : 250); !rc && (i > 0); --i)
 524                {
 525                        diva_os_sleep(1);
 526                        if (IoAdapter->pcm_pending == 3) {
 527                                diva_os_enter_spin_lock(&IoAdapter->data_spin_lock,
 528                                                        &OldIrql,
 529                                                        "data_pcm_3");
 530                                IoAdapter->pcm_pending = 0;
 531                                IoAdapter->pcm_data    = NULL;
 532                                diva_os_leave_spin_lock(&IoAdapter->data_spin_lock,
 533                                                        &OldIrql,
 534                                                        "data_pcm_3");
 535                                return;
 536                        }
 537                        diva_os_enter_spin_lock(&IoAdapter->data_spin_lock,
 538                                                &OldIrql,
 539                                                "data_pcm_2");
 540                        diva_os_schedule_soft_isr(&IoAdapter->req_soft_isr);
 541                        diva_os_leave_spin_lock(&IoAdapter->data_spin_lock,
 542                                                &OldIrql,
 543                                                "data_pcm_2");
 544                }
 545                diva_os_enter_spin_lock(&IoAdapter->data_spin_lock,
 546                                        &OldIrql,
 547                                        "data_pcm_4");
 548                IoAdapter->pcm_pending = 0;
 549                IoAdapter->pcm_data    = NULL;
 550                diva_os_leave_spin_lock(&IoAdapter->data_spin_lock,
 551                                        &OldIrql,
 552                                        "data_pcm_4");
 553                goto Trapped;
 554        }
 555/*
 556 * memory based shared ram is accessible from different
 557 * processors without disturbing concurrent processes.
 558 */
 559        a->ram_out(a, &IoAdapter->pcm->rc, 0);
 560        a->ram_out(a, &IoAdapter->pcm->req, pcm->req);
 561        for (i = (IoAdapter->trapped ? 3000 : 250); --i > 0;)
 562        {
 563                diva_os_sleep(1);
 564                rc = (int)(a->ram_in(a, &IoAdapter->pcm->rc));
 565                if (rc)
 566                {
 567                        a->ram_in_buffer(a, IoAdapter->pcm, pcm, sizeof(*pcm));
 568                        return;
 569                }
 570        }
 571Trapped:
 572        if (IoAdapter->trapFnc)
 573        {
 574                int trapped = IoAdapter->trapped;
 575                IoAdapter->trapFnc(IoAdapter);
 576                /*
 577                  Firs trap, also notify user if supported
 578                */
 579                if (!trapped && IoAdapter->trapped && IoAdapter->os_trap_nfy_Fnc) {
 580                        (*(IoAdapter->os_trap_nfy_Fnc))(IoAdapter, IoAdapter->ANum);
 581                }
 582        }
 583}
 584/*------------------------------------------------------------------*/
 585/* ram access functions for memory mapped cards                     */
 586/*------------------------------------------------------------------*/
 587byte mem_in(ADAPTER *a, void *addr)
 588{
 589        byte val;
 590        volatile byte __iomem *Base = DIVA_OS_MEM_ATTACH_RAM((PISDN_ADAPTER)a->io);
 591        val = READ_BYTE(Base + (unsigned long)addr);
 592        DIVA_OS_MEM_DETACH_RAM((PISDN_ADAPTER)a->io, Base);
 593        return (val);
 594}
 595word mem_inw(ADAPTER *a, void *addr)
 596{
 597        word val;
 598        volatile byte __iomem *Base = DIVA_OS_MEM_ATTACH_RAM((PISDN_ADAPTER)a->io);
 599        val = READ_WORD((Base + (unsigned long)addr));
 600        DIVA_OS_MEM_DETACH_RAM((PISDN_ADAPTER)a->io, Base);
 601        return (val);
 602}
 603void mem_in_dw(ADAPTER *a, void *addr, dword *data, int dwords)
 604{
 605        volatile byte __iomem *Base = DIVA_OS_MEM_ATTACH_RAM((PISDN_ADAPTER)a->io);
 606        while (dwords--) {
 607                *data++ = READ_DWORD((Base + (unsigned long)addr));
 608                addr += 4;
 609        }
 610        DIVA_OS_MEM_DETACH_RAM((PISDN_ADAPTER)a->io, Base);
 611}
 612void mem_in_buffer(ADAPTER *a, void *addr, void *buffer, word length)
 613{
 614        volatile byte __iomem *Base = DIVA_OS_MEM_ATTACH_RAM((PISDN_ADAPTER)a->io);
 615        memcpy_fromio(buffer, (Base + (unsigned long)addr), length);
 616        DIVA_OS_MEM_DETACH_RAM((PISDN_ADAPTER)a->io, Base);
 617}
 618void mem_look_ahead(ADAPTER *a, PBUFFER *RBuffer, ENTITY *e)
 619{
 620        PISDN_ADAPTER IoAdapter = (PISDN_ADAPTER)a->io;
 621        IoAdapter->RBuffer.length = mem_inw(a, &RBuffer->length);
 622        mem_in_buffer(a, RBuffer->P, IoAdapter->RBuffer.P,
 623                      IoAdapter->RBuffer.length);
 624        e->RBuffer = (DBUFFER *)&IoAdapter->RBuffer;
 625}
 626void mem_out(ADAPTER *a, void *addr, byte data)
 627{
 628        volatile byte __iomem *Base = DIVA_OS_MEM_ATTACH_RAM((PISDN_ADAPTER)a->io);
 629        WRITE_BYTE(Base + (unsigned long)addr, data);
 630        DIVA_OS_MEM_DETACH_RAM((PISDN_ADAPTER)a->io, Base);
 631}
 632void mem_outw(ADAPTER *a, void *addr, word data)
 633{
 634        volatile byte __iomem *Base = DIVA_OS_MEM_ATTACH_RAM((PISDN_ADAPTER)a->io);
 635        WRITE_WORD((Base + (unsigned long)addr), data);
 636        DIVA_OS_MEM_DETACH_RAM((PISDN_ADAPTER)a->io, Base);
 637}
 638void mem_out_dw(ADAPTER *a, void *addr, const dword *data, int dwords)
 639{
 640        volatile byte __iomem *Base = DIVA_OS_MEM_ATTACH_RAM((PISDN_ADAPTER)a->io);
 641        while (dwords--) {
 642                WRITE_DWORD((Base + (unsigned long)addr), *data);
 643                addr += 4;
 644                data++;
 645        }
 646        DIVA_OS_MEM_DETACH_RAM((PISDN_ADAPTER)a->io, Base);
 647}
 648void mem_out_buffer(ADAPTER *a, void *addr, void *buffer, word length)
 649{
 650        volatile byte __iomem *Base = DIVA_OS_MEM_ATTACH_RAM((PISDN_ADAPTER)a->io);
 651        memcpy_toio((Base + (unsigned long)addr), buffer, length);
 652        DIVA_OS_MEM_DETACH_RAM((PISDN_ADAPTER)a->io, Base);
 653}
 654void mem_inc(ADAPTER *a, void *addr)
 655{
 656        volatile byte __iomem *Base = DIVA_OS_MEM_ATTACH_RAM((PISDN_ADAPTER)a->io);
 657        byte  x = READ_BYTE(Base + (unsigned long)addr);
 658        WRITE_BYTE(Base + (unsigned long)addr, x + 1);
 659        DIVA_OS_MEM_DETACH_RAM((PISDN_ADAPTER)a->io, Base);
 660}
 661/*------------------------------------------------------------------*/
 662/* ram access functions for io-mapped cards                         */
 663/*------------------------------------------------------------------*/
 664byte io_in(ADAPTER *a, void *adr)
 665{
 666        byte val;
 667        byte __iomem *Port = DIVA_OS_MEM_ATTACH_PORT((PISDN_ADAPTER)a->io);
 668        outppw(Port + 4, (word)(unsigned long)adr);
 669        val = inpp(Port);
 670        DIVA_OS_MEM_DETACH_PORT((PISDN_ADAPTER)a->io, Port);
 671        return (val);
 672}
 673word io_inw(ADAPTER *a, void *adr)
 674{
 675        word val;
 676        byte __iomem *Port = DIVA_OS_MEM_ATTACH_PORT((PISDN_ADAPTER)a->io);
 677        outppw(Port + 4, (word)(unsigned long)adr);
 678        val = inppw(Port);
 679        DIVA_OS_MEM_DETACH_PORT((PISDN_ADAPTER)a->io, Port);
 680        return (val);
 681}
 682void io_in_buffer(ADAPTER *a, void *adr, void *buffer, word len)
 683{
 684        byte __iomem *Port = DIVA_OS_MEM_ATTACH_PORT((PISDN_ADAPTER)a->io);
 685        byte *P = (byte *)buffer;
 686        if ((long)adr & 1) {
 687                outppw(Port + 4, (word)(unsigned long)adr);
 688                *P = inpp(Port);
 689                P++;
 690                adr = ((byte *) adr) + 1;
 691                len--;
 692                if (!len) {
 693                        DIVA_OS_MEM_DETACH_PORT((PISDN_ADAPTER)a->io, Port);
 694                        return;
 695                }
 696        }
 697        outppw(Port + 4, (word)(unsigned long)adr);
 698        inppw_buffer(Port, P, len + 1);
 699        DIVA_OS_MEM_DETACH_PORT((PISDN_ADAPTER)a->io, Port);
 700}
 701void io_look_ahead(ADAPTER *a, PBUFFER *RBuffer, ENTITY *e)
 702{
 703        byte __iomem *Port = DIVA_OS_MEM_ATTACH_PORT((PISDN_ADAPTER)a->io);
 704        outppw(Port + 4, (word)(unsigned long)RBuffer);
 705        ((PISDN_ADAPTER)a->io)->RBuffer.length = inppw(Port);
 706        inppw_buffer(Port, ((PISDN_ADAPTER)a->io)->RBuffer.P, ((PISDN_ADAPTER)a->io)->RBuffer.length + 1);
 707        e->RBuffer = (DBUFFER *) &(((PISDN_ADAPTER)a->io)->RBuffer);
 708        DIVA_OS_MEM_DETACH_PORT((PISDN_ADAPTER)a->io, Port);
 709}
 710void io_out(ADAPTER *a, void *adr, byte data)
 711{
 712        byte __iomem *Port = DIVA_OS_MEM_ATTACH_PORT((PISDN_ADAPTER)a->io);
 713        outppw(Port + 4, (word)(unsigned long)adr);
 714        outpp(Port, data);
 715        DIVA_OS_MEM_DETACH_PORT((PISDN_ADAPTER)a->io, Port);
 716}
 717void io_outw(ADAPTER *a, void *adr, word data)
 718{
 719        byte __iomem *Port = DIVA_OS_MEM_ATTACH_PORT((PISDN_ADAPTER)a->io);
 720        outppw(Port + 4, (word)(unsigned long)adr);
 721        outppw(Port, data);
 722        DIVA_OS_MEM_DETACH_PORT((PISDN_ADAPTER)a->io, Port);
 723}
 724void io_out_buffer(ADAPTER *a, void *adr, void *buffer, word len)
 725{
 726        byte __iomem *Port = DIVA_OS_MEM_ATTACH_PORT((PISDN_ADAPTER)a->io);
 727        byte *P = (byte *)buffer;
 728        if ((long)adr & 1) {
 729                outppw(Port + 4, (word)(unsigned long)adr);
 730                outpp(Port, *P);
 731                P++;
 732                adr = ((byte *) adr) + 1;
 733                len--;
 734                if (!len) {
 735                        DIVA_OS_MEM_DETACH_PORT((PISDN_ADAPTER)a->io, Port);
 736                        return;
 737                }
 738        }
 739        outppw(Port + 4, (word)(unsigned long)adr);
 740        outppw_buffer(Port, P, len + 1);
 741        DIVA_OS_MEM_DETACH_PORT((PISDN_ADAPTER)a->io, Port);
 742}
 743void io_inc(ADAPTER *a, void *adr)
 744{
 745        byte x;
 746        byte __iomem *Port = DIVA_OS_MEM_ATTACH_PORT((PISDN_ADAPTER)a->io);
 747        outppw(Port + 4, (word)(unsigned long)adr);
 748        x = inpp(Port);
 749        outppw(Port + 4, (word)(unsigned long)adr);
 750        outpp(Port, x + 1);
 751        DIVA_OS_MEM_DETACH_PORT((PISDN_ADAPTER)a->io, Port);
 752}
 753/*------------------------------------------------------------------*/
 754/* OS specific functions related to queuing of entities             */
 755/*------------------------------------------------------------------*/
 756void free_entity(ADAPTER *a, byte e_no)
 757{
 758        PISDN_ADAPTER IoAdapter;
 759        diva_os_spin_lock_magic_t irql;
 760        IoAdapter = (PISDN_ADAPTER) a->io;
 761        diva_os_enter_spin_lock(&IoAdapter->data_spin_lock, &irql, "data_free");
 762        IoAdapter->e_tbl[e_no].e = NULL;
 763        IoAdapter->e_count--;
 764        diva_os_leave_spin_lock(&IoAdapter->data_spin_lock, &irql, "data_free");
 765}
 766void assign_queue(ADAPTER *a, byte e_no, word ref)
 767{
 768        PISDN_ADAPTER IoAdapter;
 769        diva_os_spin_lock_magic_t irql;
 770        IoAdapter = (PISDN_ADAPTER) a->io;
 771        diva_os_enter_spin_lock(&IoAdapter->data_spin_lock, &irql, "data_assign");
 772        IoAdapter->e_tbl[e_no].assign_ref = ref;
 773        IoAdapter->e_tbl[e_no].next = (byte)IoAdapter->assign;
 774        IoAdapter->assign = e_no;
 775        diva_os_leave_spin_lock(&IoAdapter->data_spin_lock, &irql, "data_assign");
 776}
 777byte get_assign(ADAPTER *a, word ref)
 778{
 779        PISDN_ADAPTER IoAdapter;
 780        diva_os_spin_lock_magic_t irql;
 781        byte e_no;
 782        IoAdapter = (PISDN_ADAPTER) a->io;
 783        diva_os_enter_spin_lock(&IoAdapter->data_spin_lock,
 784                                &irql,
 785                                "data_assign_get");
 786        for (e_no = (byte)IoAdapter->assign;
 787            e_no && IoAdapter->e_tbl[e_no].assign_ref != ref;
 788            e_no = IoAdapter->e_tbl[e_no].next);
 789        diva_os_leave_spin_lock(&IoAdapter->data_spin_lock,
 790                                &irql,
 791                                "data_assign_get");
 792        return e_no;
 793}
 794void req_queue(ADAPTER *a, byte e_no)
 795{
 796        PISDN_ADAPTER IoAdapter;
 797        diva_os_spin_lock_magic_t irql;
 798        IoAdapter = (PISDN_ADAPTER) a->io;
 799        diva_os_enter_spin_lock(&IoAdapter->data_spin_lock, &irql, "data_req_q");
 800        IoAdapter->e_tbl[e_no].next = 0;
 801        if (IoAdapter->head) {
 802                IoAdapter->e_tbl[IoAdapter->tail].next = e_no;
 803                IoAdapter->tail = e_no;
 804        }
 805        else {
 806                IoAdapter->head = e_no;
 807                IoAdapter->tail = e_no;
 808        }
 809        diva_os_leave_spin_lock(&IoAdapter->data_spin_lock, &irql, "data_req_q");
 810}
 811byte look_req(ADAPTER *a)
 812{
 813        PISDN_ADAPTER IoAdapter;
 814        IoAdapter = (PISDN_ADAPTER) a->io;
 815        return ((byte)IoAdapter->head);
 816}
 817void next_req(ADAPTER *a)
 818{
 819        PISDN_ADAPTER IoAdapter;
 820        diva_os_spin_lock_magic_t irql;
 821        IoAdapter = (PISDN_ADAPTER) a->io;
 822        diva_os_enter_spin_lock(&IoAdapter->data_spin_lock, &irql, "data_req_next");
 823        IoAdapter->head = IoAdapter->e_tbl[IoAdapter->head].next;
 824        if (!IoAdapter->head) IoAdapter->tail = 0;
 825        diva_os_leave_spin_lock(&IoAdapter->data_spin_lock, &irql, "data_req_next");
 826}
 827/*------------------------------------------------------------------*/
 828/* memory map functions                                             */
 829/*------------------------------------------------------------------*/
 830ENTITY *entity_ptr(ADAPTER *a, byte e_no)
 831{
 832        PISDN_ADAPTER IoAdapter;
 833        IoAdapter = (PISDN_ADAPTER)a->io;
 834        return (IoAdapter->e_tbl[e_no].e);
 835}
 836void *PTR_X(ADAPTER *a, ENTITY *e)
 837{
 838        return ((void *) e->X);
 839}
 840void *PTR_R(ADAPTER *a, ENTITY *e)
 841{
 842        return ((void *) e->R);
 843}
 844void *PTR_P(ADAPTER *a, ENTITY *e, void *P)
 845{
 846        return P;
 847}
 848void CALLBACK(ADAPTER *a, ENTITY *e)
 849{
 850        if (e && e->callback)
 851                e->callback(e);
 852}
 853