1/*-
2 * Copyright (c) 2011 Semihalf.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 */
26
27#include <sys/param.h>
28#include <sys/systm.h>
29#include <sys/kernel.h>
30#include <sys/malloc.h>
31#include <sys/bus.h>
32#include <sys/interrupt.h>
33#include <sys/lock.h>
34#include <sys/mutex.h>
35#include <sys/proc.h>
36#include <sys/queue.h>
37#include <sys/rman.h>
38#include <sys/sched.h>
39#include <sys/smp.h>
40
41#include <vm/vm.h>
42#include <vm/vm_param.h>
43#include <vm/vm_page.h>
44
45#include <machine/cpufunc.h>
46#include <machine/intr_machdep.h>
47#include <machine/pmap.h>
48#include <machine/stdarg.h>
49
50#include <dev/dpaa/bman.h>
51#include <dev/dpaa/qman.h>
52#include <dev/dpaa/portals.h>
53
54#include "error_ext.h"
55#include "std_ext.h"
56#include "list_ext.h"
57#include "mm_ext.h"
58
59/* Configuration */
60
61/* Define the number of dTSEC ports active in system */
62#define MALLOCSMART_DTSEC_IN_USE	4
63
64/*
65 * Calculate malloc's pool size for dTSEC's buffers.
66 * We reserve 1MB pool for each dTSEC port.
67 */
68#define	MALLOCSMART_POOL_SIZE		\
69    (MALLOCSMART_DTSEC_IN_USE * 1024 * 1024)
70
71#define MALLOCSMART_SLICE_SIZE		(PAGE_SIZE / 2)		/* 2kB */
72
73/* Defines */
74#define MALLOCSMART_SIZE_TO_SLICE(x)	\
75    (((x) + MALLOCSMART_SLICE_SIZE - 1) / MALLOCSMART_SLICE_SIZE)
76#define MALLOCSMART_SLICES		\
77    MALLOCSMART_SIZE_TO_SLICE(MALLOCSMART_POOL_SIZE)
78
79/* Malloc Pool for NetCommSW */
80MALLOC_DEFINE(M_NETCOMMSW, "NetCommSW", "NetCommSW software stack");
81MALLOC_DEFINE(M_NETCOMMSW_MT, "NetCommSWTrack",
82    "NetCommSW software allocation tracker");
83
84/* MallocSmart data structures */
85static void *XX_MallocSmartPool;
86static int XX_MallocSmartMap[MALLOCSMART_SLICES];
87
88static struct mtx XX_MallocSmartLock;
89static struct mtx XX_MallocTrackLock;
90MTX_SYSINIT(XX_MallocSmartLockInit, &XX_MallocSmartLock,
91    "NetCommSW MallocSmart Lock", MTX_DEF);
92MTX_SYSINIT(XX_MallocTrackLockInit, &XX_MallocTrackLock,
93    "NetCommSW MallocTrack Lock", MTX_DEF);
94
95/* Interrupt info */
96#define XX_INTR_FLAG_PREALLOCATED	(1 << 0)
97#define XX_INTR_FLAG_BOUND		(1 << 1)
98#define XX_INTR_FLAG_FMAN_FIX		(1 << 2)
99
100struct XX_IntrInfo {
101	driver_intr_t	*handler;
102	void		*arg;
103	int		cpu;
104	int		flags;
105	void		*cookie;
106};
107
108static struct XX_IntrInfo XX_IntrInfo[INTR_VECTORS];
109/* Portal type identifiers */
110enum XX_PortalIdent{
111	BM_PORTAL = 0,
112	QM_PORTAL,
113};
114/* Structure to store portals' properties */
115struct XX_PortalInfo {
116	vm_paddr_t	portal_ce_pa[2][MAXCPU];
117	vm_paddr_t	portal_ci_pa[2][MAXCPU];
118	uint32_t	portal_ce_size[2][MAXCPU];
119	uint32_t	portal_ci_size[2][MAXCPU];
120	vm_offset_t	portal_ce_va[2];
121	vm_offset_t	portal_ci_va[2];
122	uint32_t	portal_intr[2][MAXCPU];
123};
124
125static struct XX_PortalInfo XX_PInfo;
126
127/* The lower 9 bits, through emprical testing, tend to be 0. */
128#define	XX_MALLOC_TRACK_SHIFT	9
129
130typedef struct XX_MallocTrackStruct {
131	LIST_ENTRY(XX_MallocTrackStruct) entries;
132	physAddress_t pa;
133	void *va;
134} XX_MallocTrackStruct;
135
136LIST_HEAD(XX_MallocTrackerList, XX_MallocTrackStruct) *XX_MallocTracker;
137u_long XX_MallocHashMask;
138static XX_MallocTrackStruct * XX_FindTracker(physAddress_t pa);
139
140void
141XX_Exit(int status)
142{
143
144	panic("NetCommSW: Exit called with status %i", status);
145}
146
147void
148XX_Print(char *str, ...)
149{
150	va_list ap;
151
152	va_start(ap, str);
153	vprintf(str, ap);
154	va_end(ap);
155}
156
157void *
158XX_Malloc(uint32_t size)
159{
160	void *p = (malloc(size, M_NETCOMMSW, M_NOWAIT));
161
162	return (p);
163}
164
165static int
166XX_MallocSmartMapCheck(unsigned int start, unsigned int slices)
167{
168	unsigned int i;
169
170	mtx_assert(&XX_MallocSmartLock, MA_OWNED);
171	for (i = start; i < start + slices; i++)
172		if (XX_MallocSmartMap[i])
173			return (FALSE);
174	return (TRUE);
175}
176
177static void
178XX_MallocSmartMapSet(unsigned int start, unsigned int slices)
179{
180	unsigned int i;
181
182	mtx_assert(&XX_MallocSmartLock, MA_OWNED);
183
184	for (i = start; i < start + slices; i++)
185		XX_MallocSmartMap[i] = ((i == start) ? slices : -1);
186}
187
188static void
189XX_MallocSmartMapClear(unsigned int start, unsigned int slices)
190{
191	unsigned int i;
192
193	mtx_assert(&XX_MallocSmartLock, MA_OWNED);
194
195	for (i = start; i < start + slices; i++)
196		XX_MallocSmartMap[i] = 0;
197}
198
199int
200XX_MallocSmartInit(void)
201{
202	int error;
203
204	error = E_OK;
205	mtx_lock(&XX_MallocSmartLock);
206
207	if (XX_MallocSmartPool)
208		goto out;
209
210	/* Allocate MallocSmart pool */
211	XX_MallocSmartPool = contigmalloc(MALLOCSMART_POOL_SIZE, M_NETCOMMSW,
212	    M_NOWAIT, 0, 0xFFFFFFFFFull, MALLOCSMART_POOL_SIZE, 0);
213	if (!XX_MallocSmartPool) {
214		error = E_NO_MEMORY;
215		goto out;
216	}
217
218out:
219	mtx_unlock(&XX_MallocSmartLock);
220	return (error);
221}
222
223void *
224XX_MallocSmart(uint32_t size, int memPartitionId, uint32_t alignment)
225{
226	unsigned int i;
227	vm_offset_t addr;
228
229	addr = 0;
230
231	/* Convert alignment and size to number of slices */
232	alignment = MALLOCSMART_SIZE_TO_SLICE(alignment);
233	size = MALLOCSMART_SIZE_TO_SLICE(size);
234
235	/* Lock resources */
236	mtx_lock(&XX_MallocSmartLock);
237
238	/* Allocate region */
239	for (i = 0; i + size <= MALLOCSMART_SLICES; i += alignment) {
240		if (XX_MallocSmartMapCheck(i, size)) {
241			XX_MallocSmartMapSet(i, size);
242			addr = (vm_offset_t)XX_MallocSmartPool +
243			    (i * MALLOCSMART_SLICE_SIZE);
244			break;
245		}
246	}
247
248	/* Unlock resources */
249	mtx_unlock(&XX_MallocSmartLock);
250
251	return ((void *)addr);
252}
253
254void
255XX_FreeSmart(void *p)
256{
257	unsigned int start, slices;
258
259	/* Calculate first slice of region */
260	start = MALLOCSMART_SIZE_TO_SLICE((vm_offset_t)(p) -
261	    (vm_offset_t)XX_MallocSmartPool);
262
263	/* Lock resources */
264	mtx_lock(&XX_MallocSmartLock);
265
266	KASSERT(XX_MallocSmartMap[start] > 0,
267	    ("XX_FreeSmart: Double or mid-block free!\n"));
268
269	XX_UntrackAddress(p);
270	/* Free region */
271	slices = XX_MallocSmartMap[start];
272	XX_MallocSmartMapClear(start, slices);
273
274	/* Unlock resources */
275	mtx_unlock(&XX_MallocSmartLock);
276}
277
278void
279XX_Free(void *p)
280{
281
282	if (p != NULL)
283		XX_UntrackAddress(p);
284	free(p, M_NETCOMMSW);
285}
286
287uint32_t
288XX_DisableAllIntr(void)
289{
290
291	return (intr_disable());
292}
293
294void
295XX_RestoreAllIntr(uint32_t flags)
296{
297
298	intr_restore(flags);
299}
300
301t_Error
302XX_Call(uint32_t qid, t_Error (* f)(t_Handle), t_Handle id, t_Handle appId, uint16_t flags )
303{
304	/* Not referenced */
305	printf("NetCommSW: Unimplemented function %s() called!\n", __func__);
306	return (E_OK);
307}
308
309static bool
310XX_IsPortalIntr(int irq)
311{
312	int cpu, type;
313	/* Check interrupt numbers of all available portals */
314	for (cpu = 0, type = 0; XX_PInfo.portal_intr[type][cpu] != 0; cpu++) {
315		if (irq == XX_PInfo.portal_intr[type][cpu]) {
316			/* Found it! */
317			return (1);
318		}
319		if (XX_PInfo.portal_intr[type][cpu + 1] == 0) {
320			type++;
321			cpu = 0;
322		}
323	}
324
325	return (0);
326}
327
328void
329XX_FmanFixIntr(int irq)
330{
331
332	XX_IntrInfo[irq].flags |= XX_INTR_FLAG_FMAN_FIX;
333}
334
335static bool
336XX_FmanNeedsIntrFix(int irq)
337{
338
339	if (XX_IntrInfo[irq].flags & XX_INTR_FLAG_FMAN_FIX)
340		return (1);
341
342	return (0);
343}
344
345static void
346XX_Dispatch(void *arg)
347{
348	struct XX_IntrInfo *info;
349
350	info = arg;
351
352	/* Bind this thread to proper CPU when SMP has been already started. */
353	if ((info->flags & XX_INTR_FLAG_BOUND) == 0 && smp_started &&
354	    info->cpu >= 0) {
355		thread_lock(curthread);
356		sched_bind(curthread, info->cpu);
357		thread_unlock(curthread);
358
359		info->flags |= XX_INTR_FLAG_BOUND;
360	}
361
362	if (info->handler == NULL) {
363		printf("%s(): IRQ handler is NULL!\n", __func__);
364		return;
365	}
366
367	info->handler(info->arg);
368}
369
370t_Error
371XX_PreallocAndBindIntr(int irq, unsigned int cpu)
372{
373	struct resource *r;
374	unsigned int inum;
375	t_Error error;
376
377	r = (struct resource *)irq;
378	inum = rman_get_start(r);
379
380	error = XX_SetIntr(irq, XX_Dispatch, &XX_IntrInfo[inum]);
381	if (error != 0)
382		return (error);
383
384	XX_IntrInfo[inum].flags = XX_INTR_FLAG_PREALLOCATED;
385	XX_IntrInfo[inum].cpu = cpu;
386
387	return (E_OK);
388}
389
390t_Error
391XX_DeallocIntr(int irq)
392{
393	struct resource *r;
394	unsigned int inum;
395
396	r = (struct resource *)irq;
397	inum = rman_get_start(r);
398
399	if ((XX_IntrInfo[inum].flags & XX_INTR_FLAG_PREALLOCATED) == 0)
400		return (E_INVALID_STATE);
401
402	XX_IntrInfo[inum].flags = 0;
403	return (XX_FreeIntr(irq));
404}
405
406t_Error
407XX_SetIntr(int irq, t_Isr *f_Isr, t_Handle handle)
408{
409	struct device *dev;
410	struct resource *r;
411	unsigned int flags;
412	int err;
413
414	r = (struct resource *)irq;
415	dev = rman_get_device(r);
416	irq = rman_get_start(r);
417
418	/* Handle preallocated interrupts */
419	if (XX_IntrInfo[irq].flags & XX_INTR_FLAG_PREALLOCATED) {
420		if (XX_IntrInfo[irq].handler != NULL)
421			return (E_BUSY);
422
423		XX_IntrInfo[irq].handler = f_Isr;
424		XX_IntrInfo[irq].arg = handle;
425
426		return (E_OK);
427	}
428
429	flags = INTR_TYPE_NET | INTR_MPSAFE;
430
431	/* BMAN/QMAN Portal interrupts must be exlusive */
432	if (XX_IsPortalIntr(irq))
433		flags |= INTR_EXCL;
434
435	err = bus_setup_intr(dev, r, flags, NULL, f_Isr, handle,
436		    &XX_IntrInfo[irq].cookie);
437	if (err)
438		goto finish;
439
440	/*
441	 * XXX: Bind FMan IRQ to CPU0. Current interrupt subsystem directs each
442	 * interrupt to all CPUs. Race between an interrupt assertion and
443	 * masking may occur and interrupt handler may be called multiple times
444	 * per one interrupt. FMan doesn't support such a situation. Workaround
445	 * is to bind FMan interrupt to one CPU0 only.
446	 */
447#ifdef SMP
448	if (XX_FmanNeedsIntrFix(irq))
449		err = powerpc_bind_intr(irq, 0);
450#endif
451finish:
452	return (err);
453}
454
455t_Error
456XX_FreeIntr(int irq)
457{
458	struct device *dev;
459	struct resource *r;
460
461	r = (struct resource *)irq;
462	dev = rman_get_device(r);
463	irq = rman_get_start(r);
464
465	/* Handle preallocated interrupts */
466	if (XX_IntrInfo[irq].flags & XX_INTR_FLAG_PREALLOCATED) {
467		if (XX_IntrInfo[irq].handler == NULL)
468			return (E_INVALID_STATE);
469
470		XX_IntrInfo[irq].handler = NULL;
471		XX_IntrInfo[irq].arg = NULL;
472
473		return (E_OK);
474	}
475
476	return (bus_teardown_intr(dev, r, XX_IntrInfo[irq].cookie));
477}
478
479t_Error
480XX_EnableIntr(int irq)
481{
482	struct resource *r;
483
484	r = (struct resource *)irq;
485	irq = rman_get_start(r);
486
487	powerpc_intr_unmask(irq);
488
489	return (E_OK);
490}
491
492t_Error
493XX_DisableIntr(int irq)
494{
495	struct resource *r;
496
497	r = (struct resource *)irq;
498	irq = rman_get_start(r);
499
500	powerpc_intr_mask(irq);
501
502	return (E_OK);
503}
504
505t_TaskletHandle
506XX_InitTasklet (void (*routine)(void *), void *data)
507{
508	/* Not referenced */
509	printf("NetCommSW: Unimplemented function %s() called!\n", __func__);
510	return (NULL);
511}
512
513
514void
515XX_FreeTasklet (t_TaskletHandle h_Tasklet)
516{
517	/* Not referenced */
518	printf("NetCommSW: Unimplemented function %s() called!\n", __func__);
519}
520
521int
522XX_ScheduleTask(t_TaskletHandle h_Tasklet, int immediate)
523{
524	/* Not referenced */
525	printf("NetCommSW: Unimplemented function %s() called!\n", __func__);
526	return (0);
527}
528
529void
530XX_FlushScheduledTasks(void)
531{
532	/* Not referenced */
533	printf("NetCommSW: Unimplemented function %s() called!\n", __func__);
534}
535
536int
537XX_TaskletIsQueued(t_TaskletHandle h_Tasklet)
538{
539	/* Not referenced */
540	printf("NetCommSW: Unimplemented function %s() called!\n", __func__);
541	return (0);
542}
543
544void
545XX_SetTaskletData(t_TaskletHandle h_Tasklet, t_Handle data)
546{
547	/* Not referenced */
548	printf("NetCommSW: Unimplemented function %s() called!\n", __func__);
549}
550
551t_Handle
552XX_GetTaskletData(t_TaskletHandle h_Tasklet)
553{
554	/* Not referenced */
555	printf("NetCommSW: Unimplemented function %s() called!\n", __func__);
556	return (NULL);
557}
558
559t_Handle
560XX_InitSpinlock(void)
561{
562	struct mtx *m;
563
564	m = malloc(sizeof(*m), M_NETCOMMSW, M_NOWAIT | M_ZERO);
565	if (!m)
566		return (0);
567
568	mtx_init(m, "NetCommSW Lock", NULL, MTX_DEF | MTX_DUPOK);
569
570	return (m);
571}
572
573void
574XX_FreeSpinlock(t_Handle h_Spinlock)
575{
576	struct mtx *m;
577
578	m = h_Spinlock;
579
580	mtx_destroy(m);
581	free(m, M_NETCOMMSW);
582}
583
584void
585XX_LockSpinlock(t_Handle h_Spinlock)
586{
587	struct mtx *m;
588
589	m = h_Spinlock;
590	mtx_lock(m);
591}
592
593void
594XX_UnlockSpinlock(t_Handle h_Spinlock)
595{
596	struct mtx *m;
597
598	m = h_Spinlock;
599	mtx_unlock(m);
600}
601
602uint32_t
603XX_LockIntrSpinlock(t_Handle h_Spinlock)
604{
605
606	XX_LockSpinlock(h_Spinlock);
607	return (0);
608}
609
610void
611XX_UnlockIntrSpinlock(t_Handle h_Spinlock, uint32_t intrFlags)
612{
613
614	XX_UnlockSpinlock(h_Spinlock);
615}
616
617uint32_t
618XX_CurrentTime(void)
619{
620	/* Not referenced */
621	printf("NetCommSW: Unimplemented function %s() called!\n", __func__);
622	return (0);
623}
624
625
626t_Handle
627XX_CreateTimer(void)
628{
629	/* Not referenced */
630	printf("NetCommSW: Unimplemented function %s() called!\n", __func__);
631	return (NULL);
632}
633
634void
635XX_FreeTimer(t_Handle h_Timer)
636{
637	/* Not referenced */
638	printf("NetCommSW: Unimplemented function %s() called!\n", __func__);
639}
640
641void
642XX_StartTimer(t_Handle h_Timer,
643                   uint32_t msecs,
644                   bool     periodic,
645                   void     (*f_TimerExpired)(t_Handle),
646                   t_Handle h_Arg)
647{
648	/* Not referenced */
649	printf("NetCommSW: Unimplemented function %s() called!\n", __func__);
650}
651
652uint32_t
653XX_GetExpirationTime(t_Handle h_Timer)
654{
655	/* Not referenced */
656	printf("NetCommSW: Unimplemented function %s() called!\n", __func__);
657	return (0);
658}
659
660void
661XX_StopTimer(t_Handle h_Timer)
662{
663	/* Not referenced */
664	printf("NetCommSW: Unimplemented function %s() called!\n", __func__);
665}
666
667void
668XX_ModTimer(t_Handle h_Timer, uint32_t msecs)
669{
670	/* Not referenced */
671	printf("NetCommSW: Unimplemented function %s() called!\n", __func__);
672}
673
674int
675XX_TimerIsActive(t_Handle h_Timer)
676{
677	/* Not referenced */
678	printf("NetCommSW: Unimplemented function %s() called!\n", __func__);
679	return (0);
680}
681
682uint32_t
683XX_Sleep(uint32_t msecs)
684{
685
686	XX_UDelay(1000 * msecs);
687	return (0);
688}
689
690void
691XX_UDelay(uint32_t usecs)
692{
693	DELAY(usecs);
694}
695
696t_Error
697XX_IpcRegisterMsgHandler(char addr[XX_IPC_MAX_ADDR_NAME_LENGTH],
698    t_IpcMsgHandler *f_MsgHandler, t_Handle  h_Module, uint32_t replyLength)
699{
700
701	/*
702	 * This function returns fake E_OK status and does nothing
703	 * as NetCommSW IPC is not used by FreeBSD drivers.
704	 */
705	return (E_OK);
706}
707
708t_Error
709XX_IpcUnregisterMsgHandler(char addr[XX_IPC_MAX_ADDR_NAME_LENGTH])
710{
711	/*
712	 * This function returns fake E_OK status and does nothing
713	 * as NetCommSW IPC is not used by FreeBSD drivers.
714	 */
715	return (E_OK);
716}
717
718
719t_Error
720XX_IpcSendMessage(t_Handle h_Session,
721    uint8_t *p_Msg, uint32_t msgLength, uint8_t *p_Reply,
722    uint32_t *p_ReplyLength, t_IpcMsgCompletion *f_Completion, t_Handle h_Arg)
723{
724
725	/* Should not be called */
726	printf("NetCommSW: Unimplemented function %s() called!\n", __func__);
727	return (E_OK);
728}
729
730t_Handle
731XX_IpcInitSession(char destAddr[XX_IPC_MAX_ADDR_NAME_LENGTH],
732    char srcAddr[XX_IPC_MAX_ADDR_NAME_LENGTH])
733{
734
735	/* Should not be called */
736	printf("NetCommSW: Unimplemented function %s() called!\n", __func__);
737	return (E_OK);
738}
739
740t_Error
741XX_IpcFreeSession(t_Handle h_Session)
742{
743
744	/* Should not be called */
745	printf("NetCommSW: Unimplemented function %s() called!\n", __func__);
746	return (E_OK);
747}
748
749extern void db_trace_self(void);
750physAddress_t
751XX_VirtToPhys(void *addr)
752{
753	vm_paddr_t paddr;
754	int cpu;
755
756	cpu = PCPU_GET(cpuid);
757
758	/* Handle NULL address */
759	if (addr == NULL)
760		return (-1);
761
762	/* Handle BMAN mappings */
763	if (((vm_offset_t)addr >= XX_PInfo.portal_ce_va[BM_PORTAL]) &&
764	    ((vm_offset_t)addr < XX_PInfo.portal_ce_va[BM_PORTAL] +
765	    XX_PInfo.portal_ce_size[BM_PORTAL][cpu]))
766		return (XX_PInfo.portal_ce_pa[BM_PORTAL][cpu] +
767		    (vm_offset_t)addr - XX_PInfo.portal_ce_va[BM_PORTAL]);
768
769	if (((vm_offset_t)addr >= XX_PInfo.portal_ci_va[BM_PORTAL]) &&
770	    ((vm_offset_t)addr < XX_PInfo.portal_ci_va[BM_PORTAL] +
771	    XX_PInfo.portal_ci_size[BM_PORTAL][cpu]))
772		return (XX_PInfo.portal_ci_pa[BM_PORTAL][cpu] +
773		    (vm_offset_t)addr - XX_PInfo.portal_ci_va[BM_PORTAL]);
774
775	/* Handle QMAN mappings */
776	if (((vm_offset_t)addr >= XX_PInfo.portal_ce_va[QM_PORTAL]) &&
777	    ((vm_offset_t)addr < XX_PInfo.portal_ce_va[QM_PORTAL] +
778	    XX_PInfo.portal_ce_size[QM_PORTAL][cpu]))
779		return (XX_PInfo.portal_ce_pa[QM_PORTAL][cpu] +
780		    (vm_offset_t)addr - XX_PInfo.portal_ce_va[QM_PORTAL]);
781
782	if (((vm_offset_t)addr >= XX_PInfo.portal_ci_va[QM_PORTAL]) &&
783	    ((vm_offset_t)addr < XX_PInfo.portal_ci_va[QM_PORTAL] +
784	    XX_PInfo.portal_ci_size[QM_PORTAL][cpu]))
785		return (XX_PInfo.portal_ci_pa[QM_PORTAL][cpu] +
786		    (vm_offset_t)addr - XX_PInfo.portal_ci_va[QM_PORTAL]);
787
788	paddr = pmap_kextract((vm_offset_t)addr);
789	if (!paddr)
790		printf("NetCommSW: "
791		    "Unable to translate virtual address 0x%08X!\n", addr);
792	else
793	    XX_TrackAddress(addr);
794
795	return (paddr);
796}
797
798void *
799XX_PhysToVirt(physAddress_t addr)
800{
801	XX_MallocTrackStruct *ts;
802	int cpu;
803
804	cpu = PCPU_GET(cpuid);
805
806	/* Handle BMAN mappings */
807	if ((addr >= XX_PInfo.portal_ce_pa[BM_PORTAL][cpu]) &&
808	    (addr < XX_PInfo.portal_ce_pa[BM_PORTAL][cpu] +
809	    XX_PInfo.portal_ce_size[BM_PORTAL][cpu]))
810		return ((void *)(XX_PInfo.portal_ci_va[BM_PORTAL] +
811		    (vm_offset_t)(addr - XX_PInfo.portal_ci_pa[BM_PORTAL][cpu])));
812
813	if ((addr >= XX_PInfo.portal_ci_pa[BM_PORTAL][cpu]) &&
814	    (addr < XX_PInfo.portal_ci_pa[BM_PORTAL][cpu] +
815	    XX_PInfo.portal_ci_size[BM_PORTAL][cpu]))
816		return ((void *)(XX_PInfo.portal_ci_va[BM_PORTAL] +
817		    (vm_offset_t)(addr - XX_PInfo.portal_ci_pa[BM_PORTAL][cpu])));
818
819	/* Handle QMAN mappings */
820	if ((addr >= XX_PInfo.portal_ce_pa[QM_PORTAL][cpu]) &&
821	    (addr < XX_PInfo.portal_ce_pa[QM_PORTAL][cpu] +
822	    XX_PInfo.portal_ce_size[QM_PORTAL][cpu]))
823		return ((void *)(XX_PInfo.portal_ce_va[QM_PORTAL] +
824		    (vm_offset_t)(addr - XX_PInfo.portal_ce_pa[QM_PORTAL][cpu])));
825
826	if ((addr >= XX_PInfo.portal_ci_pa[QM_PORTAL][cpu]) &&
827	    (addr < XX_PInfo.portal_ci_pa[QM_PORTAL][cpu] +
828	    XX_PInfo.portal_ci_size[QM_PORTAL][cpu]))
829		return ((void *)(XX_PInfo.portal_ci_va[QM_PORTAL] +
830		    (vm_offset_t)(addr - XX_PInfo.portal_ci_pa[QM_PORTAL][cpu])));
831
832	mtx_lock(&XX_MallocTrackLock);
833	ts = XX_FindTracker(addr);
834	mtx_unlock(&XX_MallocTrackLock);
835
836	if (ts != NULL)
837		return ts->va;
838
839	printf("NetCommSW: "
840	    "Unable to translate physical address 0x%08llX!\n", addr);
841
842	return (NULL);
843}
844
845void
846XX_PortalSetInfo(device_t dev)
847{
848	char *dev_name;
849	struct dpaa_portals_softc *sc;
850	int i, type, len;
851
852	dev_name = malloc(sizeof(*dev_name), M_TEMP, M_WAITOK |
853	    M_ZERO);
854
855	len = strlen("bman-portals");
856
857	strncpy(dev_name, device_get_name(dev), len);
858
859	if (strncmp(dev_name, "bman-portals", len) && strncmp(dev_name,
860	    "qman-portals", len))
861		goto end;
862
863	if (strncmp(dev_name, "bman-portals", len) == 0)
864		type = BM_PORTAL;
865	else
866		type = QM_PORTAL;
867
868	sc = device_get_softc(dev);
869
870	for (i = 0; sc->sc_dp[i].dp_ce_pa != 0; i++) {
871		XX_PInfo.portal_ce_pa[type][i] = sc->sc_dp[i].dp_ce_pa;
872		XX_PInfo.portal_ci_pa[type][i] = sc->sc_dp[i].dp_ci_pa;
873		XX_PInfo.portal_ce_size[type][i] = sc->sc_dp[i].dp_ce_size;
874		XX_PInfo.portal_ci_size[type][i] = sc->sc_dp[i].dp_ci_size;
875		XX_PInfo.portal_intr[type][i] = sc->sc_dp[i].dp_intr_num;
876	}
877
878	XX_PInfo.portal_ce_va[type] = rman_get_bushandle(sc->sc_rres[0]);
879	XX_PInfo.portal_ci_va[type] = rman_get_bushandle(sc->sc_rres[1]);
880end:
881	free(dev_name, M_TEMP);
882}
883
884static XX_MallocTrackStruct *
885XX_FindTracker(physAddress_t pa)
886{
887	struct XX_MallocTrackerList *l;
888	XX_MallocTrackStruct *tp;
889
890	l = &XX_MallocTracker[(pa >> XX_MALLOC_TRACK_SHIFT) & XX_MallocHashMask];
891
892	LIST_FOREACH(tp, l, entries) {
893		if (tp->pa == pa)
894			return tp;
895	}
896
897	return NULL;
898}
899
900void
901XX_TrackInit(void)
902{
903	if (XX_MallocTracker == NULL) {
904		XX_MallocTracker = hashinit(64, M_NETCOMMSW_MT,
905		    &XX_MallocHashMask);
906	}
907}
908
909void
910XX_TrackAddress(void *addr)
911{
912	physAddress_t pa;
913	struct XX_MallocTrackerList *l;
914	XX_MallocTrackStruct *ts;
915
916	pa = pmap_kextract((vm_offset_t)addr);
917
918	ts = malloc(sizeof(*ts), M_NETCOMMSW_MT, M_NOWAIT);
919	ts->va = addr;
920	ts->pa = pa;
921
922	l = &XX_MallocTracker[(pa >> XX_MALLOC_TRACK_SHIFT) & XX_MallocHashMask];
923
924	mtx_lock(&XX_MallocTrackLock);
925	if (XX_FindTracker(pa) != NULL)
926		free(ts, M_NETCOMMSW_MT);
927	else
928		LIST_INSERT_HEAD(l, ts, entries);
929	mtx_unlock(&XX_MallocTrackLock);
930}
931
932void
933XX_UntrackAddress(void *addr)
934{
935	physAddress_t pa;
936	XX_MallocTrackStruct *ts;
937
938	pa = pmap_kextract((vm_offset_t)addr);
939
940	KASSERT(XX_MallocTracker != NULL,
941	    ("Untracking an address before it's even initialized!\n"));
942
943	mtx_lock(&XX_MallocTrackLock);
944	ts = XX_FindTracker(pa);
945	if (ts != NULL)
946		LIST_REMOVE(ts, entries);
947	mtx_unlock(&XX_MallocTrackLock);
948	free(ts, M_NETCOMMSW_MT);
949}
950