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 <powerpc/mpc85xx/mpc85xx.h>
55#include "error_ext.h"
56#include "std_ext.h"
57#include "list_ext.h"
58#include "mm_ext.h"
59
60/* Configuration */
61
62/* Define the number of dTSEC ports active in system */
63#define MALLOCSMART_DTSEC_IN_USE	4
64
65/*
66 * Calculate malloc's pool size for dTSEC's buffers.
67 * We reserve 1MB pool for each dTSEC port.
68 */
69#define	MALLOCSMART_POOL_SIZE		\
70    (MALLOCSMART_DTSEC_IN_USE * 1024 * 1024)
71
72#define MALLOCSMART_SLICE_SIZE		(PAGE_SIZE / 2)		/* 2kB */
73
74/* Defines */
75#define MALLOCSMART_SIZE_TO_SLICE(x)	\
76    (((x) + MALLOCSMART_SLICE_SIZE - 1) / MALLOCSMART_SLICE_SIZE)
77#define MALLOCSMART_SLICES		\
78    MALLOCSMART_SIZE_TO_SLICE(MALLOCSMART_POOL_SIZE)
79
80/* Malloc Pool for NetCommSW */
81MALLOC_DEFINE(M_NETCOMMSW, "NetCommSW", "NetCommSW software stack");
82MALLOC_DEFINE(M_NETCOMMSW_MT, "NetCommSWTrack",
83    "NetCommSW software allocation tracker");
84
85/* MallocSmart data structures */
86static void *XX_MallocSmartPool;
87static int XX_MallocSmartMap[MALLOCSMART_SLICES];
88
89static struct mtx XX_MallocSmartLock;
90static struct mtx XX_MallocTrackLock;
91MTX_SYSINIT(XX_MallocSmartLockInit, &XX_MallocSmartLock,
92    "NetCommSW MallocSmart Lock", MTX_DEF);
93MTX_SYSINIT(XX_MallocTrackLockInit, &XX_MallocTrackLock,
94    "NetCommSW MallocTrack Lock", MTX_DEF);
95
96/* Interrupt info */
97#define XX_INTR_FLAG_PREALLOCATED	(1 << 0)
98#define XX_INTR_FLAG_BOUND		(1 << 1)
99#define XX_INTR_FLAG_FMAN_FIX		(1 << 2)
100
101struct XX_IntrInfo {
102	driver_intr_t	*handler;
103	void		*arg;
104	int		cpu;
105	int		flags;
106	void		*cookie;
107};
108
109static struct XX_IntrInfo XX_IntrInfo[INTR_VECTORS];
110/* Portal type identifiers */
111enum XX_PortalIdent{
112	BM_PORTAL = 0,
113	QM_PORTAL,
114};
115/* Structure to store portals' properties */
116struct XX_PortalInfo {
117	vm_paddr_t	portal_ce_pa[2][MAXCPU];
118	vm_paddr_t	portal_ci_pa[2][MAXCPU];
119	uint32_t	portal_ce_size[2][MAXCPU];
120	uint32_t	portal_ci_size[2][MAXCPU];
121	vm_offset_t	portal_ce_va[2];
122	vm_offset_t	portal_ci_va[2];
123	uintptr_t	portal_intr[2][MAXCPU];
124};
125
126static struct XX_PortalInfo XX_PInfo;
127
128void
129XX_Exit(int status)
130{
131
132	panic("NetCommSW: Exit called with status %i", status);
133}
134
135void
136XX_Print(char *str, ...)
137{
138	va_list ap;
139
140	va_start(ap, str);
141	vprintf(str, ap);
142	va_end(ap);
143}
144
145void *
146XX_Malloc(uint32_t size)
147{
148	void *p = (malloc(size, M_NETCOMMSW, M_NOWAIT));
149
150	return (p);
151}
152
153static int
154XX_MallocSmartMapCheck(unsigned int start, unsigned int slices)
155{
156	unsigned int i;
157
158	mtx_assert(&XX_MallocSmartLock, MA_OWNED);
159	for (i = start; i < start + slices; i++)
160		if (XX_MallocSmartMap[i])
161			return (FALSE);
162	return (TRUE);
163}
164
165static void
166XX_MallocSmartMapSet(unsigned int start, unsigned int slices)
167{
168	unsigned int i;
169
170	mtx_assert(&XX_MallocSmartLock, MA_OWNED);
171
172	for (i = start; i < start + slices; i++)
173		XX_MallocSmartMap[i] = ((i == start) ? slices : -1);
174}
175
176static void
177XX_MallocSmartMapClear(unsigned int start, unsigned int slices)
178{
179	unsigned int i;
180
181	mtx_assert(&XX_MallocSmartLock, MA_OWNED);
182
183	for (i = start; i < start + slices; i++)
184		XX_MallocSmartMap[i] = 0;
185}
186
187int
188XX_MallocSmartInit(void)
189{
190	int error;
191
192	error = E_OK;
193	mtx_lock(&XX_MallocSmartLock);
194
195	if (XX_MallocSmartPool)
196		goto out;
197
198	/* Allocate MallocSmart pool */
199	XX_MallocSmartPool = contigmalloc(MALLOCSMART_POOL_SIZE, M_NETCOMMSW,
200	    M_NOWAIT, 0, 0xFFFFFFFFFull, MALLOCSMART_POOL_SIZE, 0);
201	if (!XX_MallocSmartPool) {
202		error = E_NO_MEMORY;
203		goto out;
204	}
205
206out:
207	mtx_unlock(&XX_MallocSmartLock);
208	return (error);
209}
210
211void *
212XX_MallocSmart(uint32_t size, int memPartitionId, uint32_t alignment)
213{
214	unsigned int i;
215	vm_offset_t addr;
216
217	addr = 0;
218
219	/* Convert alignment and size to number of slices */
220	alignment = MALLOCSMART_SIZE_TO_SLICE(alignment);
221	size = MALLOCSMART_SIZE_TO_SLICE(size);
222
223	/* Lock resources */
224	mtx_lock(&XX_MallocSmartLock);
225
226	/* Allocate region */
227	for (i = 0; i + size <= MALLOCSMART_SLICES; i += alignment) {
228		if (XX_MallocSmartMapCheck(i, size)) {
229			XX_MallocSmartMapSet(i, size);
230			addr = (vm_offset_t)XX_MallocSmartPool +
231			    (i * MALLOCSMART_SLICE_SIZE);
232			break;
233		}
234	}
235
236	/* Unlock resources */
237	mtx_unlock(&XX_MallocSmartLock);
238
239	return ((void *)addr);
240}
241
242void
243XX_FreeSmart(void *p)
244{
245	unsigned int start, slices;
246
247	/* Calculate first slice of region */
248	start = MALLOCSMART_SIZE_TO_SLICE((vm_offset_t)(p) -
249	    (vm_offset_t)XX_MallocSmartPool);
250
251	/* Lock resources */
252	mtx_lock(&XX_MallocSmartLock);
253
254	KASSERT(XX_MallocSmartMap[start] > 0,
255	    ("XX_FreeSmart: Double or mid-block free!\n"));
256
257	/* Free region */
258	slices = XX_MallocSmartMap[start];
259	XX_MallocSmartMapClear(start, slices);
260
261	/* Unlock resources */
262	mtx_unlock(&XX_MallocSmartLock);
263}
264
265void
266XX_Free(void *p)
267{
268
269	free(p, M_NETCOMMSW);
270}
271
272uint32_t
273XX_DisableAllIntr(void)
274{
275
276	return (intr_disable());
277}
278
279void
280XX_RestoreAllIntr(uint32_t flags)
281{
282
283	intr_restore(flags);
284}
285
286static bool
287XX_IsPortalIntr(uintptr_t irq)
288{
289	int cpu, type;
290	/* Check interrupt numbers of all available portals */
291	for (cpu = 0, type = 0; XX_PInfo.portal_intr[type][cpu] != 0; cpu++) {
292		if (irq == XX_PInfo.portal_intr[type][cpu]) {
293			/* Found it! */
294			return (1);
295		}
296		if (XX_PInfo.portal_intr[type][cpu + 1] == 0) {
297			type++;
298			cpu = 0;
299		}
300	}
301
302	return (0);
303}
304
305void
306XX_FmanFixIntr(int irq)
307{
308
309	XX_IntrInfo[irq].flags |= XX_INTR_FLAG_FMAN_FIX;
310}
311
312static bool
313XX_FmanNeedsIntrFix(int irq)
314{
315
316	if (XX_IntrInfo[irq].flags & XX_INTR_FLAG_FMAN_FIX)
317		return (1);
318
319	return (0);
320}
321
322static void
323XX_Dispatch(void *arg)
324{
325	struct XX_IntrInfo *info;
326
327	info = arg;
328
329	/* Bind this thread to proper CPU when SMP has been already started. */
330	if ((info->flags & XX_INTR_FLAG_BOUND) == 0 && smp_started &&
331	    info->cpu >= 0) {
332		thread_lock(curthread);
333		sched_bind(curthread, info->cpu);
334		thread_unlock(curthread);
335
336		info->flags |= XX_INTR_FLAG_BOUND;
337	}
338
339	if (info->handler == NULL) {
340		printf("%s(): IRQ handler is NULL!\n", __func__);
341		return;
342	}
343
344	info->handler(info->arg);
345}
346
347t_Error
348XX_PreallocAndBindIntr(uintptr_t irq, unsigned int cpu)
349{
350	struct resource *r;
351	unsigned int inum;
352	t_Error error;
353
354	r = (struct resource *)irq;
355	inum = rman_get_start(r);
356
357	error = XX_SetIntr(irq, XX_Dispatch, &XX_IntrInfo[inum]);
358	if (error != 0)
359		return (error);
360
361	XX_IntrInfo[inum].flags = XX_INTR_FLAG_PREALLOCATED;
362	XX_IntrInfo[inum].cpu = cpu;
363
364	return (E_OK);
365}
366
367t_Error
368XX_DeallocIntr(uintptr_t irq)
369{
370	struct resource *r;
371	unsigned int inum;
372
373	r = (struct resource *)irq;
374	inum = rman_get_start(r);
375
376	if ((XX_IntrInfo[inum].flags & XX_INTR_FLAG_PREALLOCATED) == 0)
377		return (E_INVALID_STATE);
378
379	XX_IntrInfo[inum].flags = 0;
380	return (XX_FreeIntr(irq));
381}
382
383t_Error
384XX_SetIntr(uintptr_t irq, t_Isr *f_Isr, t_Handle handle)
385{
386	device_t dev;
387	struct resource *r;
388	unsigned int flags;
389	int err;
390
391	r = (struct resource *)irq;
392	dev = rman_get_device(r);
393	irq = rman_get_start(r);
394
395	/* Handle preallocated interrupts */
396	if (XX_IntrInfo[irq].flags & XX_INTR_FLAG_PREALLOCATED) {
397		if (XX_IntrInfo[irq].handler != NULL)
398			return (E_BUSY);
399
400		XX_IntrInfo[irq].handler = f_Isr;
401		XX_IntrInfo[irq].arg = handle;
402
403		return (E_OK);
404	}
405
406	flags = INTR_TYPE_NET | INTR_MPSAFE;
407
408	/* BMAN/QMAN Portal interrupts must be exlusive */
409	if (XX_IsPortalIntr(irq))
410		flags |= INTR_EXCL;
411
412	err = bus_setup_intr(dev, r, flags, NULL, f_Isr, handle,
413		    &XX_IntrInfo[irq].cookie);
414	if (err)
415		goto finish;
416
417	/*
418	 * XXX: Bind FMan IRQ to CPU0. Current interrupt subsystem directs each
419	 * interrupt to all CPUs. Race between an interrupt assertion and
420	 * masking may occur and interrupt handler may be called multiple times
421	 * per one interrupt. FMan doesn't support such a situation. Workaround
422	 * is to bind FMan interrupt to one CPU0 only.
423	 */
424#ifdef SMP
425	if (XX_FmanNeedsIntrFix(irq))
426		err = powerpc_bind_intr(irq, 0);
427#endif
428finish:
429	return (err);
430}
431
432t_Error
433XX_FreeIntr(uintptr_t irq)
434{
435	device_t dev;
436	struct resource *r;
437
438	r = (struct resource *)irq;
439	dev = rman_get_device(r);
440	irq = rman_get_start(r);
441
442	/* Handle preallocated interrupts */
443	if (XX_IntrInfo[irq].flags & XX_INTR_FLAG_PREALLOCATED) {
444		if (XX_IntrInfo[irq].handler == NULL)
445			return (E_INVALID_STATE);
446
447		XX_IntrInfo[irq].handler = NULL;
448		XX_IntrInfo[irq].arg = NULL;
449
450		return (E_OK);
451	}
452
453	return (bus_teardown_intr(dev, r, XX_IntrInfo[irq].cookie));
454}
455
456t_Error
457XX_EnableIntr(uintptr_t irq)
458{
459	struct resource *r;
460
461	r = (struct resource *)irq;
462	irq = rman_get_start(r);
463
464	powerpc_intr_unmask(irq);
465
466	return (E_OK);
467}
468
469t_Error
470XX_DisableIntr(uintptr_t irq)
471{
472	struct resource *r;
473
474	r = (struct resource *)irq;
475	irq = rman_get_start(r);
476
477	powerpc_intr_mask(irq);
478
479	return (E_OK);
480}
481
482t_TaskletHandle
483XX_InitTasklet (void (*routine)(void *), void *data)
484{
485	/* Not referenced */
486	printf("NetCommSW: Unimplemented function %s() called!\n", __func__);
487	return (NULL);
488}
489
490
491void
492XX_FreeTasklet (t_TaskletHandle h_Tasklet)
493{
494	/* Not referenced */
495	printf("NetCommSW: Unimplemented function %s() called!\n", __func__);
496}
497
498int
499XX_ScheduleTask(t_TaskletHandle h_Tasklet, int immediate)
500{
501	/* Not referenced */
502	printf("NetCommSW: Unimplemented function %s() called!\n", __func__);
503	return (0);
504}
505
506void
507XX_FlushScheduledTasks(void)
508{
509	/* Not referenced */
510	printf("NetCommSW: Unimplemented function %s() called!\n", __func__);
511}
512
513int
514XX_TaskletIsQueued(t_TaskletHandle h_Tasklet)
515{
516	/* Not referenced */
517	printf("NetCommSW: Unimplemented function %s() called!\n", __func__);
518	return (0);
519}
520
521void
522XX_SetTaskletData(t_TaskletHandle h_Tasklet, t_Handle data)
523{
524	/* Not referenced */
525	printf("NetCommSW: Unimplemented function %s() called!\n", __func__);
526}
527
528t_Handle
529XX_GetTaskletData(t_TaskletHandle h_Tasklet)
530{
531	/* Not referenced */
532	printf("NetCommSW: Unimplemented function %s() called!\n", __func__);
533	return (NULL);
534}
535
536t_Handle
537XX_InitSpinlock(void)
538{
539	struct mtx *m;
540
541	m = malloc(sizeof(*m), M_NETCOMMSW, M_NOWAIT | M_ZERO);
542	if (!m)
543		return (0);
544
545	mtx_init(m, "NetCommSW Lock", NULL, MTX_DEF | MTX_DUPOK);
546
547	return (m);
548}
549
550void
551XX_FreeSpinlock(t_Handle h_Spinlock)
552{
553	struct mtx *m;
554
555	m = h_Spinlock;
556
557	mtx_destroy(m);
558	free(m, M_NETCOMMSW);
559}
560
561void
562XX_LockSpinlock(t_Handle h_Spinlock)
563{
564	struct mtx *m;
565
566	m = h_Spinlock;
567	mtx_lock(m);
568}
569
570void
571XX_UnlockSpinlock(t_Handle h_Spinlock)
572{
573	struct mtx *m;
574
575	m = h_Spinlock;
576	mtx_unlock(m);
577}
578
579uint32_t
580XX_LockIntrSpinlock(t_Handle h_Spinlock)
581{
582
583	XX_LockSpinlock(h_Spinlock);
584	return (0);
585}
586
587void
588XX_UnlockIntrSpinlock(t_Handle h_Spinlock, uint32_t intrFlags)
589{
590
591	XX_UnlockSpinlock(h_Spinlock);
592}
593
594uint32_t
595XX_Sleep(uint32_t msecs)
596{
597
598	XX_UDelay(1000 * msecs);
599	return (0);
600}
601
602void
603XX_UDelay(uint32_t usecs)
604{
605	DELAY(usecs);
606}
607
608t_Error
609XX_IpcRegisterMsgHandler(char addr[XX_IPC_MAX_ADDR_NAME_LENGTH],
610    t_IpcMsgHandler *f_MsgHandler, t_Handle  h_Module, uint32_t replyLength)
611{
612
613	/*
614	 * This function returns fake E_OK status and does nothing
615	 * as NetCommSW IPC is not used by FreeBSD drivers.
616	 */
617	return (E_OK);
618}
619
620t_Error
621XX_IpcUnregisterMsgHandler(char addr[XX_IPC_MAX_ADDR_NAME_LENGTH])
622{
623	/*
624	 * This function returns fake E_OK status and does nothing
625	 * as NetCommSW IPC is not used by FreeBSD drivers.
626	 */
627	return (E_OK);
628}
629
630
631t_Error
632XX_IpcSendMessage(t_Handle h_Session,
633    uint8_t *p_Msg, uint32_t msgLength, uint8_t *p_Reply,
634    uint32_t *p_ReplyLength, t_IpcMsgCompletion *f_Completion, t_Handle h_Arg)
635{
636
637	/* Should not be called */
638	printf("NetCommSW: Unimplemented function %s() called!\n", __func__);
639	return (E_OK);
640}
641
642t_Handle
643XX_IpcInitSession(char destAddr[XX_IPC_MAX_ADDR_NAME_LENGTH],
644    char srcAddr[XX_IPC_MAX_ADDR_NAME_LENGTH])
645{
646
647	/* Should not be called */
648	printf("NetCommSW: Unimplemented function %s() called!\n", __func__);
649	return (E_OK);
650}
651
652t_Error
653XX_IpcFreeSession(t_Handle h_Session)
654{
655
656	/* Should not be called */
657	printf("NetCommSW: Unimplemented function %s() called!\n", __func__);
658	return (E_OK);
659}
660
661physAddress_t
662XX_VirtToPhys(void *addr)
663{
664	vm_paddr_t paddr;
665	int cpu;
666
667	cpu = PCPU_GET(cpuid);
668
669	/* Handle NULL address */
670	if (addr == NULL)
671		return (-1);
672
673	/* Check CCSR */
674	if ((vm_offset_t)addr >= ccsrbar_va &&
675	    (vm_offset_t)addr < ccsrbar_va + ccsrbar_size)
676		return (((vm_offset_t)addr - ccsrbar_va) + ccsrbar_pa);
677
678	/* Handle BMAN mappings */
679	if (((vm_offset_t)addr >= XX_PInfo.portal_ce_va[BM_PORTAL]) &&
680	    ((vm_offset_t)addr < XX_PInfo.portal_ce_va[BM_PORTAL] +
681	    XX_PInfo.portal_ce_size[BM_PORTAL][cpu]))
682		return (XX_PInfo.portal_ce_pa[BM_PORTAL][cpu] +
683		    (vm_offset_t)addr - XX_PInfo.portal_ce_va[BM_PORTAL]);
684
685	if (((vm_offset_t)addr >= XX_PInfo.portal_ci_va[BM_PORTAL]) &&
686	    ((vm_offset_t)addr < XX_PInfo.portal_ci_va[BM_PORTAL] +
687	    XX_PInfo.portal_ci_size[BM_PORTAL][cpu]))
688		return (XX_PInfo.portal_ci_pa[BM_PORTAL][cpu] +
689		    (vm_offset_t)addr - XX_PInfo.portal_ci_va[BM_PORTAL]);
690
691	/* Handle QMAN mappings */
692	if (((vm_offset_t)addr >= XX_PInfo.portal_ce_va[QM_PORTAL]) &&
693	    ((vm_offset_t)addr < XX_PInfo.portal_ce_va[QM_PORTAL] +
694	    XX_PInfo.portal_ce_size[QM_PORTAL][cpu]))
695		return (XX_PInfo.portal_ce_pa[QM_PORTAL][cpu] +
696		    (vm_offset_t)addr - XX_PInfo.portal_ce_va[QM_PORTAL]);
697
698	if (((vm_offset_t)addr >= XX_PInfo.portal_ci_va[QM_PORTAL]) &&
699	    ((vm_offset_t)addr < XX_PInfo.portal_ci_va[QM_PORTAL] +
700	    XX_PInfo.portal_ci_size[QM_PORTAL][cpu]))
701		return (XX_PInfo.portal_ci_pa[QM_PORTAL][cpu] +
702		    (vm_offset_t)addr - XX_PInfo.portal_ci_va[QM_PORTAL]);
703
704	if (PMAP_HAS_DMAP && (vm_offset_t)addr >= DMAP_BASE_ADDRESS &&
705	    (vm_offset_t)addr <= DMAP_MAX_ADDRESS)
706		return (DMAP_TO_PHYS((vm_offset_t)addr));
707	else
708		paddr = pmap_kextract((vm_offset_t)addr);
709
710	if (paddr == 0)
711		printf("NetCommSW: "
712		    "Unable to translate virtual address %p!\n", addr);
713	else
714		pmap_track_page(kernel_pmap, (vm_offset_t)addr);
715
716	return (paddr);
717}
718
719void *
720XX_PhysToVirt(physAddress_t addr)
721{
722	struct pv_entry *pv;
723	vm_page_t page;
724	int cpu;
725
726	/* Check CCSR */
727	if (addr >= ccsrbar_pa && addr < ccsrbar_pa + ccsrbar_size)
728		return ((void *)((vm_offset_t)(addr - ccsrbar_pa) +
729		    ccsrbar_va));
730
731	cpu = PCPU_GET(cpuid);
732
733	/* Handle BMAN mappings */
734	if ((addr >= XX_PInfo.portal_ce_pa[BM_PORTAL][cpu]) &&
735	    (addr < XX_PInfo.portal_ce_pa[BM_PORTAL][cpu] +
736	    XX_PInfo.portal_ce_size[BM_PORTAL][cpu]))
737		return ((void *)(XX_PInfo.portal_ci_va[BM_PORTAL] +
738		    (vm_offset_t)(addr - XX_PInfo.portal_ci_pa[BM_PORTAL][cpu])));
739
740	if ((addr >= XX_PInfo.portal_ci_pa[BM_PORTAL][cpu]) &&
741	    (addr < XX_PInfo.portal_ci_pa[BM_PORTAL][cpu] +
742	    XX_PInfo.portal_ci_size[BM_PORTAL][cpu]))
743		return ((void *)(XX_PInfo.portal_ci_va[BM_PORTAL] +
744		    (vm_offset_t)(addr - XX_PInfo.portal_ci_pa[BM_PORTAL][cpu])));
745
746	/* Handle QMAN mappings */
747	if ((addr >= XX_PInfo.portal_ce_pa[QM_PORTAL][cpu]) &&
748	    (addr < XX_PInfo.portal_ce_pa[QM_PORTAL][cpu] +
749	    XX_PInfo.portal_ce_size[QM_PORTAL][cpu]))
750		return ((void *)(XX_PInfo.portal_ce_va[QM_PORTAL] +
751		    (vm_offset_t)(addr - XX_PInfo.portal_ce_pa[QM_PORTAL][cpu])));
752
753	if ((addr >= XX_PInfo.portal_ci_pa[QM_PORTAL][cpu]) &&
754	    (addr < XX_PInfo.portal_ci_pa[QM_PORTAL][cpu] +
755	    XX_PInfo.portal_ci_size[QM_PORTAL][cpu]))
756		return ((void *)(XX_PInfo.portal_ci_va[QM_PORTAL] +
757		    (vm_offset_t)(addr - XX_PInfo.portal_ci_pa[QM_PORTAL][cpu])));
758
759	page = PHYS_TO_VM_PAGE(addr);
760	pv = TAILQ_FIRST(&page->md.pv_list);
761
762	if (pv != NULL)
763		return ((void *)(pv->pv_va + ((vm_offset_t)addr & PAGE_MASK)));
764
765	if (PMAP_HAS_DMAP)
766		return ((void *)(uintptr_t)PHYS_TO_DMAP(addr));
767
768	printf("NetCommSW: "
769	    "Unable to translate physical address 0x%09jx!\n", (uintmax_t)addr);
770
771	return (NULL);
772}
773
774void
775XX_PortalSetInfo(device_t dev)
776{
777	char *dev_name;
778	struct dpaa_portals_softc *sc;
779	int i, type, len;
780
781	dev_name = malloc(sizeof(*dev_name), M_TEMP, M_WAITOK |
782	    M_ZERO);
783
784	len = strlen("bman-portals");
785
786	strncpy(dev_name, device_get_name(dev), len);
787
788	if (strncmp(dev_name, "bman-portals", len) && strncmp(dev_name,
789	    "qman-portals", len))
790		goto end;
791
792	if (strncmp(dev_name, "bman-portals", len) == 0)
793		type = BM_PORTAL;
794	else
795		type = QM_PORTAL;
796
797	sc = device_get_softc(dev);
798
799	for (i = 0; sc->sc_dp[i].dp_ce_pa != 0; i++) {
800		XX_PInfo.portal_ce_pa[type][i] = sc->sc_dp[i].dp_ce_pa;
801		XX_PInfo.portal_ci_pa[type][i] = sc->sc_dp[i].dp_ci_pa;
802		XX_PInfo.portal_ce_size[type][i] = sc->sc_dp[i].dp_ce_size;
803		XX_PInfo.portal_ci_size[type][i] = sc->sc_dp[i].dp_ci_size;
804		XX_PInfo.portal_intr[type][i] = sc->sc_dp[i].dp_intr_num;
805	}
806
807	XX_PInfo.portal_ce_va[type] = rman_get_bushandle(sc->sc_rres[0]);
808	XX_PInfo.portal_ci_va[type] = rman_get_bushandle(sc->sc_rres[1]);
809end:
810	free(dev_name, M_TEMP);
811}
812