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 static 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 	 DIVA_XDI_EXTENDED_FEATURE_MANAGEMENT_DMA |
81 #endif
82 	 DIVA_XDI_EXTENDED_FEATURE_NO_CANCEL_RC),
83 	0
84 };
85 /*****************************************************************************/
86 void
dump_xlog_buffer(PISDN_ADAPTER IoAdapter,Xdesc * xlogDesc)87 dump_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)
122 static 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
158 void
dump_trap_frame(PISDN_ADAPTER IoAdapter,byte __iomem * exceptionFrame)159 dump_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    -------------------------------------------------------------------------- */
request(PISDN_ADAPTER IoAdapter,ENTITY * e)203 void 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    --------------------------------------------------------------------- */
DIDpcRoutine(struct _diva_os_soft_isr * psoft_isr,void * Context)452 void 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    -------------------------------------------------------------------------- */
501 static void
pcm_req(PISDN_ADAPTER IoAdapter,ENTITY * e)502 pcm_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 	}
571 Trapped:
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 /*------------------------------------------------------------------*/
mem_in(ADAPTER * a,void * addr)587 byte 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 }
mem_inw(ADAPTER * a,void * addr)595 word 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 }
mem_in_dw(ADAPTER * a,void * addr,dword * data,int dwords)603 void 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 }
mem_in_buffer(ADAPTER * a,void * addr,void * buffer,word length)612 void 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 }
mem_look_ahead(ADAPTER * a,PBUFFER * RBuffer,ENTITY * e)618 void 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 }
mem_out(ADAPTER * a,void * addr,byte data)626 void 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 }
mem_outw(ADAPTER * a,void * addr,word data)632 void 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 }
mem_out_dw(ADAPTER * a,void * addr,const dword * data,int dwords)638 void 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 }
mem_out_buffer(ADAPTER * a,void * addr,void * buffer,word length)648 void 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 }
mem_inc(ADAPTER * a,void * addr)654 void 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 /*------------------------------------------------------------------*/
io_in(ADAPTER * a,void * adr)664 byte 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 }
io_inw(ADAPTER * a,void * adr)673 word 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 }
io_in_buffer(ADAPTER * a,void * adr,void * buffer,word len)682 void 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 }
io_look_ahead(ADAPTER * a,PBUFFER * RBuffer,ENTITY * e)701 void 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 }
io_out(ADAPTER * a,void * adr,byte data)710 void 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 }
io_outw(ADAPTER * a,void * adr,word data)717 void 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 }
io_out_buffer(ADAPTER * a,void * adr,void * buffer,word len)724 void 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 }
io_inc(ADAPTER * a,void * adr)743 void 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 /*------------------------------------------------------------------*/
free_entity(ADAPTER * a,byte e_no)756 void 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 }
assign_queue(ADAPTER * a,byte e_no,word ref)766 void 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 }
get_assign(ADAPTER * a,word ref)777 byte 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 }
req_queue(ADAPTER * a,byte e_no)794 void 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 }
look_req(ADAPTER * a)811 byte look_req(ADAPTER *a)
812 {
813 	PISDN_ADAPTER IoAdapter;
814 	IoAdapter = (PISDN_ADAPTER) a->io;
815 	return ((byte)IoAdapter->head);
816 }
next_req(ADAPTER * a)817 void 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 /*------------------------------------------------------------------*/
entity_ptr(ADAPTER * a,byte e_no)830 ENTITY *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 }
PTR_X(ADAPTER * a,ENTITY * e)836 void *PTR_X(ADAPTER *a, ENTITY *e)
837 {
838 	return ((void *) e->X);
839 }
PTR_R(ADAPTER * a,ENTITY * e)840 void *PTR_R(ADAPTER *a, ENTITY *e)
841 {
842 	return ((void *) e->R);
843 }
PTR_P(ADAPTER * a,ENTITY * e,void * P)844 void *PTR_P(ADAPTER *a, ENTITY *e, void *P)
845 {
846 	return P;
847 }
CALLBACK(ADAPTER * a,ENTITY * e)848 void CALLBACK(ADAPTER *a, ENTITY *e)
849 {
850 	if (e && e->callback)
851 		e->callback(e);
852 }
853