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