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