1/*-
2 * SPDX-License-Identifier: BSD-2-Clause
3 *
4 * Copyright �� 2021-2022 Dmitry Salychev
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in the
13 *    documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 */
27
28#include <sys/cdefs.h>
29/*
30 * The DPAA2 Resource Container (DPRC) bus driver.
31 *
32 * DPRC holds all the resources and object information that a software context
33 * (kernel, virtual machine, etc.) can access or use.
34 */
35
36#include <sys/param.h>
37#include <sys/kernel.h>
38#include <sys/bus.h>
39#include <sys/rman.h>
40#include <sys/module.h>
41#include <sys/malloc.h>
42#include <sys/mutex.h>
43#include <sys/condvar.h>
44#include <sys/lock.h>
45#include <sys/time.h>
46#include <sys/types.h>
47#include <sys/systm.h>
48#include <sys/smp.h>
49
50#include <machine/bus.h>
51#include <machine/resource.h>
52
53#include "pcib_if.h"
54#include "pci_if.h"
55
56#include "dpaa2_mcp.h"
57#include "dpaa2_mc.h"
58#include "dpaa2_ni.h"
59#include "dpaa2_mc_if.h"
60#include "dpaa2_cmd_if.h"
61
62/* Timeouts to wait for a command response from MC. */
63#define CMD_SPIN_TIMEOUT	100u	/* us */
64#define CMD_SPIN_ATTEMPTS	2000u	/* max. 200 ms */
65
66#define TYPE_LEN_MAX		16u
67#define LABEL_LEN_MAX		16u
68
69MALLOC_DEFINE(M_DPAA2_RC, "dpaa2_rc", "DPAA2 Resource Container");
70
71/* Discover and add devices to the resource container. */
72static int dpaa2_rc_discover(struct dpaa2_rc_softc *);
73static int dpaa2_rc_add_child(struct dpaa2_rc_softc *, struct dpaa2_cmd *,
74    struct dpaa2_obj *);
75static int dpaa2_rc_add_managed_child(struct dpaa2_rc_softc *,
76    struct dpaa2_cmd *, struct dpaa2_obj *);
77
78/* Helper routines. */
79static int dpaa2_rc_enable_irq(struct dpaa2_mcp *, struct dpaa2_cmd *, uint8_t,
80    bool, uint16_t);
81static int dpaa2_rc_configure_irq(device_t, device_t, int, uint64_t, uint32_t);
82static int dpaa2_rc_add_res(device_t, device_t, enum dpaa2_dev_type, int *, int);
83static int dpaa2_rc_print_type(struct resource_list *, enum dpaa2_dev_type);
84static struct dpaa2_mcp *dpaa2_rc_select_portal(device_t, device_t);
85
86/* Routines to send commands to MC. */
87static int dpaa2_rc_exec_cmd(struct dpaa2_mcp *, struct dpaa2_cmd *, uint16_t);
88static int dpaa2_rc_send_cmd(struct dpaa2_mcp *, struct dpaa2_cmd *);
89static int dpaa2_rc_wait_for_cmd(struct dpaa2_mcp *, struct dpaa2_cmd *);
90static int dpaa2_rc_reset_cmd_params(struct dpaa2_cmd *);
91
92static int
93dpaa2_rc_probe(device_t dev)
94{
95	/* DPRC device will be added by the parent DPRC or MC bus itself. */
96	device_set_desc(dev, "DPAA2 Resource Container");
97	return (BUS_PROBE_DEFAULT);
98}
99
100static int
101dpaa2_rc_detach(device_t dev)
102{
103	struct dpaa2_devinfo *dinfo;
104	int error;
105
106	error = bus_generic_detach(dev);
107	if (error)
108		return (error);
109
110	dinfo = device_get_ivars(dev);
111
112	if (dinfo->portal)
113		dpaa2_mcp_free_portal(dinfo->portal);
114	if (dinfo)
115		free(dinfo, M_DPAA2_RC);
116
117	return (device_delete_children(dev));
118}
119
120static int
121dpaa2_rc_attach(device_t dev)
122{
123	device_t pdev;
124	struct dpaa2_mc_softc *mcsc;
125	struct dpaa2_rc_softc *sc;
126	struct dpaa2_devinfo *dinfo = NULL;
127	int error;
128
129	sc = device_get_softc(dev);
130	sc->dev = dev;
131	sc->unit = device_get_unit(dev);
132
133	if (sc->unit == 0) {
134		/* Root DPRC should be attached directly to the MC bus. */
135		pdev = device_get_parent(dev);
136		mcsc = device_get_softc(pdev);
137
138		KASSERT(strcmp(device_get_name(pdev), "dpaa2_mc") == 0,
139		    ("root DPRC should be attached to the MC bus"));
140
141		/*
142		 * Allocate devinfo to let the parent MC bus access ICID of the
143		 * DPRC object.
144		 */
145		dinfo = malloc(sizeof(struct dpaa2_devinfo), M_DPAA2_RC,
146		    M_WAITOK | M_ZERO);
147		if (!dinfo) {
148			device_printf(dev, "%s: failed to allocate "
149			    "dpaa2_devinfo\n", __func__);
150			dpaa2_rc_detach(dev);
151			return (ENXIO);
152		}
153		device_set_ivars(dev, dinfo);
154
155		dinfo->pdev = pdev;
156		dinfo->dev = dev;
157		dinfo->dtype = DPAA2_DEV_RC;
158		dinfo->portal = NULL;
159
160		/* Prepare helper portal object to send commands to MC. */
161		error = dpaa2_mcp_init_portal(&dinfo->portal, mcsc->res[0],
162		    &mcsc->map[0], DPAA2_PORTAL_DEF);
163		if (error) {
164			device_printf(dev, "%s: failed to initialize dpaa2_mcp: "
165			    "error=%d\n", __func__, error);
166			dpaa2_rc_detach(dev);
167			return (ENXIO);
168		}
169	} else {
170		/* TODO: Child DPRCs aren't supported yet. */
171		return (ENXIO);
172	}
173
174	/* Create DPAA2 devices for objects in this container. */
175	error = dpaa2_rc_discover(sc);
176	if (error) {
177		device_printf(dev, "%s: failed to discover objects in "
178		    "container: error=%d\n", __func__, error);
179		dpaa2_rc_detach(dev);
180		return (error);
181	}
182
183	return (0);
184}
185
186/*
187 * Bus interface.
188 */
189
190static struct resource_list *
191dpaa2_rc_get_resource_list(device_t rcdev, device_t child)
192{
193	struct dpaa2_devinfo *dinfo = device_get_ivars(child);
194
195	return (&dinfo->resources);
196}
197
198static void
199dpaa2_rc_delete_resource(device_t rcdev, device_t child, int type, int rid)
200{
201	struct resource_list *rl;
202	struct resource_list_entry *rle;
203	struct dpaa2_devinfo *dinfo;
204
205	if (device_get_parent(child) != rcdev)
206		return;
207
208	dinfo = device_get_ivars(child);
209	rl = &dinfo->resources;
210	rle = resource_list_find(rl, type, rid);
211	if (rle == NULL)
212		return;
213
214	if (rle->res) {
215		if (rman_get_flags(rle->res) & RF_ACTIVE ||
216		    resource_list_busy(rl, type, rid)) {
217			device_printf(rcdev, "%s: resource still owned by "
218			    "child: type=%d, rid=%d, start=%jx\n", __func__,
219			    type, rid, rman_get_start(rle->res));
220			return;
221		}
222		resource_list_unreserve(rl, rcdev, child, type, rid);
223	}
224	resource_list_delete(rl, type, rid);
225}
226
227static struct resource *
228dpaa2_rc_alloc_multi_resource(device_t rcdev, device_t child, int type, int *rid,
229    rman_res_t start, rman_res_t end, rman_res_t count, u_int flags)
230{
231	struct resource_list *rl;
232	struct dpaa2_devinfo *dinfo;
233
234	dinfo = device_get_ivars(child);
235	rl = &dinfo->resources;
236
237	/*
238	 * By default, software portal interrupts are message-based, that is,
239	 * they are issued from QMan using a 4 byte write.
240	 *
241	 * TODO: However this default behavior can be changed by programming one
242	 *	 or more software portals to issue their interrupts via a
243	 *	 dedicated software portal interrupt wire.
244	 *	 See registers SWP_INTW0_CFG to SWP_INTW3_CFG for details.
245	 */
246	if (type == SYS_RES_IRQ && *rid == 0)
247		return (NULL);
248
249	return (resource_list_alloc(rl, rcdev, child, type, rid,
250	    start, end, count, flags));
251}
252
253static struct resource *
254dpaa2_rc_alloc_resource(device_t rcdev, device_t child, int type, int *rid,
255    rman_res_t start, rman_res_t end, rman_res_t count, u_int flags)
256{
257	if (device_get_parent(child) != rcdev)
258		return (BUS_ALLOC_RESOURCE(device_get_parent(rcdev), child,
259		    type, rid, start, end, count, flags));
260
261	return (dpaa2_rc_alloc_multi_resource(rcdev, child, type, rid, start,
262	    end, count, flags));
263}
264
265static int
266dpaa2_rc_release_resource(device_t rcdev, device_t child, struct resource *r)
267{
268	struct resource_list *rl;
269	struct dpaa2_devinfo *dinfo;
270
271	if (device_get_parent(child) != rcdev)
272		return (BUS_RELEASE_RESOURCE(device_get_parent(rcdev), child,
273		    r));
274
275	dinfo = device_get_ivars(child);
276	rl = &dinfo->resources;
277	return (resource_list_release(rl, rcdev, child, r));
278}
279
280static void
281dpaa2_rc_child_deleted(device_t rcdev, device_t child)
282{
283	struct dpaa2_devinfo *dinfo;
284	struct resource_list *rl;
285	struct resource_list_entry *rle;
286
287	dinfo = device_get_ivars(child);
288	rl = &dinfo->resources;
289
290	/* Free all allocated resources */
291	STAILQ_FOREACH(rle, rl, link) {
292		if (rle->res) {
293			if (rman_get_flags(rle->res) & RF_ACTIVE ||
294			    resource_list_busy(rl, rle->type, rle->rid)) {
295				device_printf(child, "%s: resource still owned: "
296				    "type=%d, rid=%d, addr=%lx\n", __func__,
297				    rle->type, rle->rid,
298				    rman_get_start(rle->res));
299				bus_release_resource(child, rle->type, rle->rid,
300				    rle->res);
301			}
302			resource_list_unreserve(rl, rcdev, child, rle->type,
303			    rle->rid);
304		}
305	}
306	resource_list_free(rl);
307
308	if (dinfo)
309		free(dinfo, M_DPAA2_RC);
310}
311
312static void
313dpaa2_rc_child_detached(device_t rcdev, device_t child)
314{
315	struct dpaa2_devinfo *dinfo;
316	struct resource_list *rl;
317
318	dinfo = device_get_ivars(child);
319	rl = &dinfo->resources;
320
321	if (resource_list_release_active(rl, rcdev, child, SYS_RES_IRQ) != 0)
322		device_printf(child, "%s: leaked IRQ resources!\n", __func__);
323	if (dinfo->msi.msi_alloc != 0) {
324		device_printf(child, "%s: leaked %d MSI vectors!\n", __func__,
325		    dinfo->msi.msi_alloc);
326		PCI_RELEASE_MSI(rcdev, child);
327	}
328	if (resource_list_release_active(rl, rcdev, child, SYS_RES_MEMORY) != 0)
329		device_printf(child, "%s: leaked memory resources!\n", __func__);
330}
331
332static int
333dpaa2_rc_setup_intr(device_t rcdev, device_t child, struct resource *irq,
334    int flags, driver_filter_t *filter, driver_intr_t *intr, void *arg,
335    void **cookiep)
336{
337	struct dpaa2_devinfo *dinfo;
338	uint64_t addr;
339	uint32_t data;
340	void *cookie;
341	int error, rid;
342
343	error = bus_generic_setup_intr(rcdev, child, irq, flags, filter, intr,
344	    arg, &cookie);
345	if (error) {
346		device_printf(rcdev, "%s: bus_generic_setup_intr() failed: "
347		    "error=%d\n", __func__, error);
348		return (error);
349	}
350
351	/* If this is not a direct child, just bail out. */
352	if (device_get_parent(child) != rcdev) {
353		*cookiep = cookie;
354		return (0);
355	}
356
357	rid = rman_get_rid(irq);
358	if (rid == 0) {
359		if (bootverbose)
360			device_printf(rcdev, "%s: cannot setup interrupt with "
361			    "rid=0: INTx are not supported by DPAA2 objects "
362			    "yet\n", __func__);
363		return (EINVAL);
364	} else {
365		dinfo = device_get_ivars(child);
366		KASSERT(dinfo->msi.msi_alloc > 0,
367		    ("No MSI interrupts allocated"));
368
369		/*
370		 * Ask our parent to map the MSI and give us the address and
371		 * data register values. If we fail for some reason, teardown
372		 * the interrupt handler.
373		 */
374		error = PCIB_MAP_MSI(device_get_parent(rcdev), child,
375		    rman_get_start(irq), &addr, &data);
376		if (error) {
377			device_printf(rcdev, "%s: PCIB_MAP_MSI failed: "
378			    "error=%d\n", __func__, error);
379			(void)bus_generic_teardown_intr(rcdev, child, irq,
380			    cookie);
381			return (error);
382		}
383
384		/* Configure MSI for this DPAA2 object. */
385		error = dpaa2_rc_configure_irq(rcdev, child, rid, addr, data);
386		if (error) {
387			device_printf(rcdev, "%s: failed to configure IRQ for "
388			    "DPAA2 object: rid=%d, type=%s, unit=%d\n", __func__,
389			    rid, dpaa2_ttos(dinfo->dtype),
390			    device_get_unit(child));
391			return (error);
392		}
393		dinfo->msi.msi_handlers++;
394	}
395	*cookiep = cookie;
396	return (0);
397}
398
399static int
400dpaa2_rc_teardown_intr(device_t rcdev, device_t child, struct resource *irq,
401    void *cookie)
402{
403	struct resource_list_entry *rle;
404	struct dpaa2_devinfo *dinfo;
405	int error, rid;
406
407	if (irq == NULL || !(rman_get_flags(irq) & RF_ACTIVE))
408		return (EINVAL);
409
410	/* If this isn't a direct child, just bail out */
411	if (device_get_parent(child) != rcdev)
412		return(bus_generic_teardown_intr(rcdev, child, irq, cookie));
413
414	rid = rman_get_rid(irq);
415	if (rid == 0) {
416		if (bootverbose)
417			device_printf(rcdev, "%s: cannot teardown interrupt "
418			    "with rid=0: INTx are not supported by DPAA2 "
419			    "objects yet\n", __func__);
420		return (EINVAL);
421	} else {
422		dinfo = device_get_ivars(child);
423		rle = resource_list_find(&dinfo->resources, SYS_RES_IRQ, rid);
424		if (rle->res != irq)
425			return (EINVAL);
426		dinfo->msi.msi_handlers--;
427	}
428
429	error = bus_generic_teardown_intr(rcdev, child, irq, cookie);
430	if (rid > 0)
431		KASSERT(error == 0,
432		    ("%s: generic teardown failed for MSI", __func__));
433	return (error);
434}
435
436static int
437dpaa2_rc_print_child(device_t rcdev, device_t child)
438{
439	struct dpaa2_devinfo *dinfo = device_get_ivars(child);
440	struct resource_list *rl = &dinfo->resources;
441	int retval = 0;
442
443	retval += bus_print_child_header(rcdev, child);
444
445	retval += resource_list_print_type(rl, "port", SYS_RES_IOPORT, "%#jx");
446	retval += resource_list_print_type(rl, "iomem", SYS_RES_MEMORY, "%#jx");
447	retval += resource_list_print_type(rl, "irq", SYS_RES_IRQ, "%jd");
448
449	/* Print DPAA2-specific resources. */
450	retval += dpaa2_rc_print_type(rl, DPAA2_DEV_IO);
451	retval += dpaa2_rc_print_type(rl, DPAA2_DEV_BP);
452	retval += dpaa2_rc_print_type(rl, DPAA2_DEV_CON);
453	retval += dpaa2_rc_print_type(rl, DPAA2_DEV_MCP);
454
455	retval += printf(" at %s (id=%u)", dpaa2_ttos(dinfo->dtype), dinfo->id);
456
457	retval += bus_print_child_domain(rcdev, child);
458	retval += bus_print_child_footer(rcdev, child);
459
460	return (retval);
461}
462
463/*
464 * Pseudo-PCI interface.
465 */
466
467/*
468 * Attempt to allocate *count MSI messages. The actual number allocated is
469 * returned in *count. After this function returns, each message will be
470 * available to the driver as SYS_RES_IRQ resources starting at a rid 1.
471 *
472 * NOTE: Implementation is similar to sys/dev/pci/pci.c.
473 */
474static int
475dpaa2_rc_alloc_msi(device_t rcdev, device_t child, int *count)
476{
477	struct dpaa2_devinfo *rcinfo = device_get_ivars(rcdev);
478	struct dpaa2_devinfo *dinfo = device_get_ivars(child);
479	int error, actual, i, run, irqs[32];
480
481	/* Don't let count == 0 get us into trouble. */
482	if (*count == 0)
483		return (EINVAL);
484
485	/* MSI should be allocated by the resource container. */
486	if (rcinfo->dtype != DPAA2_DEV_RC)
487		return (ENODEV);
488
489	/* Already have allocated messages? */
490	if (dinfo->msi.msi_alloc != 0)
491		return (ENXIO);
492
493	/* Don't ask for more than the device supports. */
494	actual = min(*count, dinfo->msi.msi_msgnum);
495
496	/* Don't ask for more than 32 messages. */
497	actual = min(actual, 32);
498
499	/* MSI requires power of 2 number of messages. */
500	if (!powerof2(actual))
501		return (EINVAL);
502
503	for (;;) {
504		/* Try to allocate N messages. */
505		error = PCIB_ALLOC_MSI(device_get_parent(rcdev), child, actual,
506		    actual, irqs);
507		if (error == 0)
508			break;
509		if (actual == 1)
510			return (error);
511
512		/* Try N / 2. */
513		actual >>= 1;
514	}
515
516	/*
517	 * We now have N actual messages mapped onto SYS_RES_IRQ resources in
518	 * the irqs[] array, so add new resources starting at rid 1.
519	 */
520	for (i = 0; i < actual; i++)
521		resource_list_add(&dinfo->resources, SYS_RES_IRQ, i + 1,
522		    irqs[i], irqs[i], 1);
523
524	if (bootverbose) {
525		if (actual == 1) {
526			device_printf(child, "using IRQ %d for MSI\n", irqs[0]);
527		} else {
528			/*
529			 * Be fancy and try to print contiguous runs
530			 * of IRQ values as ranges.  'run' is true if
531			 * we are in a range.
532			 */
533			device_printf(child, "using IRQs %d", irqs[0]);
534			run = 0;
535			for (i = 1; i < actual; i++) {
536				/* Still in a run? */
537				if (irqs[i] == irqs[i - 1] + 1) {
538					run = 1;
539					continue;
540				}
541
542				/* Finish previous range. */
543				if (run) {
544					printf("-%d", irqs[i - 1]);
545					run = 0;
546				}
547
548				/* Start new range. */
549				printf(",%d", irqs[i]);
550			}
551
552			/* Unfinished range? */
553			if (run)
554				printf("-%d", irqs[actual - 1]);
555			printf(" for MSI\n");
556		}
557	}
558
559	/* Update counts of alloc'd messages. */
560	dinfo->msi.msi_alloc = actual;
561	dinfo->msi.msi_handlers = 0;
562	*count = actual;
563	return (0);
564}
565
566/*
567 * Release the MSI messages associated with this DPAA2 device.
568 *
569 * NOTE: Implementation is similar to sys/dev/pci/pci.c.
570 */
571static int
572dpaa2_rc_release_msi(device_t rcdev, device_t child)
573{
574	struct dpaa2_devinfo *rcinfo = device_get_ivars(rcdev);
575	struct dpaa2_devinfo *dinfo = device_get_ivars(child);
576	struct resource_list_entry *rle;
577	int i, irqs[32];
578
579	/* MSI should be released by the resource container. */
580	if (rcinfo->dtype != DPAA2_DEV_RC)
581		return (ENODEV);
582
583	/* Do we have any messages to release? */
584	if (dinfo->msi.msi_alloc == 0)
585		return (ENODEV);
586	KASSERT(dinfo->msi.msi_alloc <= 32,
587	    ("more than 32 alloc'd MSI messages"));
588
589	/* Make sure none of the resources are allocated. */
590	if (dinfo->msi.msi_handlers > 0)
591		return (EBUSY);
592	for (i = 0; i < dinfo->msi.msi_alloc; i++) {
593		rle = resource_list_find(&dinfo->resources, SYS_RES_IRQ, i + 1);
594		KASSERT(rle != NULL, ("missing MSI resource"));
595		if (rle->res != NULL)
596			return (EBUSY);
597		irqs[i] = rle->start;
598	}
599
600	/* Release the messages. */
601	PCIB_RELEASE_MSI(device_get_parent(rcdev), child, dinfo->msi.msi_alloc,
602	    irqs);
603	for (i = 0; i < dinfo->msi.msi_alloc; i++)
604		resource_list_delete(&dinfo->resources, SYS_RES_IRQ, i + 1);
605
606	/* Update alloc count. */
607	dinfo->msi.msi_alloc = 0;
608	return (0);
609}
610
611/**
612 * @brief Return the maximum number of the MSI supported by this DPAA2 device.
613 */
614static int
615dpaa2_rc_msi_count(device_t rcdev, device_t child)
616{
617	struct dpaa2_devinfo *dinfo = device_get_ivars(child);
618
619	return (dinfo->msi.msi_msgnum);
620}
621
622static int
623dpaa2_rc_get_id(device_t rcdev, device_t child, enum pci_id_type type,
624    uintptr_t *id)
625{
626	struct dpaa2_devinfo *rcinfo = device_get_ivars(rcdev);
627
628	if (rcinfo->dtype != DPAA2_DEV_RC)
629		return (ENODEV);
630
631	return (PCIB_GET_ID(device_get_parent(rcdev), child, type, id));
632}
633
634/*
635 * DPAA2 MC command interface.
636 */
637
638static int
639dpaa2_rc_mng_get_version(device_t dev, device_t child, struct dpaa2_cmd *cmd,
640    uint32_t *major, uint32_t *minor, uint32_t *rev)
641{
642	struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
643	int error;
644
645	if (portal == NULL || cmd == NULL || major == NULL || minor == NULL ||
646	    rev == NULL)
647		return (DPAA2_CMD_STAT_ERR);
648
649	error = dpaa2_rc_exec_cmd(portal, cmd, CMDID_MNG_GET_VER);
650	if (!error) {
651		*major = cmd->params[0] >> 32;
652		*minor = cmd->params[1] & 0xFFFFFFFF;
653		*rev = cmd->params[0] & 0xFFFFFFFF;
654	}
655
656	return (error);
657}
658
659static int
660dpaa2_rc_mng_get_soc_version(device_t dev, device_t child, struct dpaa2_cmd *cmd,
661    uint32_t *pvr, uint32_t *svr)
662{
663	struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
664	int error;
665
666	if (portal == NULL || cmd == NULL || pvr == NULL || svr == NULL)
667		return (DPAA2_CMD_STAT_ERR);
668
669	error = dpaa2_rc_exec_cmd(portal, cmd, CMDID_MNG_GET_SOC_VER);
670	if (!error) {
671		*pvr = cmd->params[0] >> 32;
672		*svr = cmd->params[0] & 0xFFFFFFFF;
673	}
674
675	return (error);
676}
677
678static int
679dpaa2_rc_mng_get_container_id(device_t dev, device_t child,
680    struct dpaa2_cmd *cmd, uint32_t *cont_id)
681{
682	struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
683	int error;
684
685	if (portal == NULL || cmd == NULL || cont_id == NULL)
686		return (DPAA2_CMD_STAT_ERR);
687
688	error = dpaa2_rc_exec_cmd(portal, cmd, CMDID_MNG_GET_CONT_ID);
689	if (!error)
690		*cont_id = cmd->params[0] & 0xFFFFFFFF;
691
692	return (error);
693}
694
695static int
696dpaa2_rc_open(device_t dev, device_t child, struct dpaa2_cmd *cmd,
697    uint32_t cont_id, uint16_t *token)
698{
699	struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
700	struct dpaa2_cmd_header *hdr;
701	int error;
702
703	if (portal == NULL || cmd == NULL || token == NULL)
704		return (DPAA2_CMD_STAT_ERR);
705
706	cmd->params[0] = cont_id;
707
708	error = dpaa2_rc_exec_cmd(portal, cmd, CMDID_RC_OPEN);
709	if (!error) {
710		hdr = (struct dpaa2_cmd_header *) &cmd->header;
711		*token = hdr->token;
712	}
713
714	return (error);
715}
716
717static int
718dpaa2_rc_close(device_t dev, device_t child, struct dpaa2_cmd *cmd)
719{
720	struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
721
722	if (portal == NULL || cmd == NULL)
723		return (DPAA2_CMD_STAT_ERR);
724
725	return (dpaa2_rc_exec_cmd(portal, cmd, CMDID_RC_CLOSE));
726}
727
728static int
729dpaa2_rc_get_obj_count(device_t dev, device_t child, struct dpaa2_cmd *cmd,
730    uint32_t *obj_count)
731{
732	struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
733	int error;
734
735	if (portal == NULL || cmd == NULL || obj_count == NULL)
736		return (DPAA2_CMD_STAT_ERR);
737
738	error = dpaa2_rc_exec_cmd(portal, cmd, CMDID_RC_GET_OBJ_COUNT);
739	if (!error)
740		*obj_count = (uint32_t)(cmd->params[0] >> 32);
741
742	return (error);
743}
744
745static int
746dpaa2_rc_get_obj(device_t dev, device_t child, struct dpaa2_cmd *cmd,
747    uint32_t obj_idx, struct dpaa2_obj *obj)
748{
749	struct __packed dpaa2_obj_resp {
750		uint32_t	_reserved1;
751		uint32_t	id;
752		uint16_t	vendor;
753		uint8_t		irq_count;
754		uint8_t		reg_count;
755		uint32_t	state;
756		uint16_t	ver_major;
757		uint16_t	ver_minor;
758		uint16_t	flags;
759		uint16_t	_reserved2;
760		uint8_t		type[16];
761		uint8_t		label[16];
762	} *pobj;
763	struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
764	int error;
765
766	if (portal == NULL || cmd == NULL || obj == NULL)
767		return (DPAA2_CMD_STAT_ERR);
768
769	cmd->params[0] = obj_idx;
770
771	error = dpaa2_rc_exec_cmd(portal, cmd, CMDID_RC_GET_OBJ);
772	if (!error) {
773		pobj = (struct dpaa2_obj_resp *) &cmd->params[0];
774		obj->id = pobj->id;
775		obj->vendor = pobj->vendor;
776		obj->irq_count = pobj->irq_count;
777		obj->reg_count = pobj->reg_count;
778		obj->state = pobj->state;
779		obj->ver_major = pobj->ver_major;
780		obj->ver_minor = pobj->ver_minor;
781		obj->flags = pobj->flags;
782		obj->type = dpaa2_stot((const char *) pobj->type);
783		memcpy(obj->label, pobj->label, sizeof(pobj->label));
784	}
785
786	/* Some DPAA2 objects might not be supported by the driver yet. */
787	if (obj->type == DPAA2_DEV_NOTYPE)
788		error = DPAA2_CMD_STAT_UNKNOWN_OBJ;
789
790	return (error);
791}
792
793static int
794dpaa2_rc_get_obj_descriptor(device_t dev, device_t child,
795    struct dpaa2_cmd *cmd, uint32_t obj_id, enum dpaa2_dev_type dtype,
796    struct dpaa2_obj *obj)
797{
798	struct __packed get_obj_desc_args {
799		uint32_t	obj_id;
800		uint32_t	_reserved1;
801		uint8_t		type[16];
802	} *args;
803	struct __packed dpaa2_obj_resp {
804		uint32_t	_reserved1;
805		uint32_t	id;
806		uint16_t	vendor;
807		uint8_t		irq_count;
808		uint8_t		reg_count;
809		uint32_t	state;
810		uint16_t	ver_major;
811		uint16_t	ver_minor;
812		uint16_t	flags;
813		uint16_t	_reserved2;
814		uint8_t		type[16];
815		uint8_t		label[16];
816	} *pobj;
817	struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
818	const char *type = dpaa2_ttos(dtype);
819	int error;
820
821	if (portal == NULL || cmd == NULL || obj == NULL)
822		return (DPAA2_CMD_STAT_ERR);
823
824	args = (struct get_obj_desc_args *) &cmd->params[0];
825	args->obj_id = obj_id;
826	memcpy(args->type, type, min(strlen(type) + 1, TYPE_LEN_MAX));
827
828	error = dpaa2_rc_exec_cmd(portal, cmd, CMDID_RC_GET_OBJ_DESC);
829	if (!error) {
830		pobj = (struct dpaa2_obj_resp *) &cmd->params[0];
831		obj->id = pobj->id;
832		obj->vendor = pobj->vendor;
833		obj->irq_count = pobj->irq_count;
834		obj->reg_count = pobj->reg_count;
835		obj->state = pobj->state;
836		obj->ver_major = pobj->ver_major;
837		obj->ver_minor = pobj->ver_minor;
838		obj->flags = pobj->flags;
839		obj->type = dpaa2_stot((const char *) pobj->type);
840		memcpy(obj->label, pobj->label, sizeof(pobj->label));
841	}
842
843	/* Some DPAA2 objects might not be supported by the driver yet. */
844	if (obj->type == DPAA2_DEV_NOTYPE)
845		error = DPAA2_CMD_STAT_UNKNOWN_OBJ;
846
847	return (error);
848}
849
850static int
851dpaa2_rc_get_attributes(device_t dev, device_t child, struct dpaa2_cmd *cmd,
852    struct dpaa2_rc_attr *attr)
853{
854	struct __packed dpaa2_rc_attr {
855		uint32_t	cont_id;
856		uint32_t	icid;
857		uint32_t	options;
858		uint32_t	portal_id;
859	} *pattr;
860	struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
861	int error;
862
863	if (portal == NULL || cmd == NULL || attr == NULL)
864		return (DPAA2_CMD_STAT_ERR);
865
866	error = dpaa2_rc_exec_cmd(portal, cmd, CMDID_RC_GET_ATTR);
867	if (!error) {
868		pattr = (struct dpaa2_rc_attr *) &cmd->params[0];
869		attr->cont_id = pattr->cont_id;
870		attr->portal_id = pattr->portal_id;
871		attr->options = pattr->options;
872		attr->icid = pattr->icid;
873	}
874
875	return (error);
876}
877
878static int
879dpaa2_rc_get_obj_region(device_t dev, device_t child, struct dpaa2_cmd *cmd,
880    uint32_t obj_id, uint8_t reg_idx, enum dpaa2_dev_type dtype,
881    struct dpaa2_rc_obj_region *reg)
882{
883	struct __packed obj_region_args {
884		uint32_t	obj_id;
885		uint16_t	_reserved1;
886		uint8_t		reg_idx;
887		uint8_t		_reserved2;
888		uint64_t	_reserved3;
889		uint64_t	_reserved4;
890		uint8_t		type[16];
891	} *args;
892	struct __packed obj_region {
893		uint64_t	_reserved1;
894		uint64_t	base_offset;
895		uint32_t	size;
896		uint32_t	type;
897		uint32_t	flags;
898		uint32_t	_reserved2;
899		uint64_t	base_paddr;
900	} *resp;
901	struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
902	uint16_t cmdid, api_major, api_minor;
903	const char *type = dpaa2_ttos(dtype);
904	int error;
905
906	if (portal == NULL || cmd == NULL || reg == NULL)
907		return (DPAA2_CMD_STAT_ERR);
908
909	/*
910	 * If the DPRC object version was not yet cached, cache it now.
911	 * Otherwise use the already cached value.
912	 */
913	if (!portal->rc_api_major && !portal->rc_api_minor) {
914		error = DPAA2_CMD_RC_GET_API_VERSION(dev, child, cmd,
915		    &api_major, &api_minor);
916		if (error)
917			return (error);
918		portal->rc_api_major = api_major;
919		portal->rc_api_minor = api_minor;
920	} else {
921		api_major = portal->rc_api_major;
922		api_minor = portal->rc_api_minor;
923	}
924
925	/* TODO: Remove magic numbers. */
926	if (api_major > 6u || (api_major == 6u && api_minor >= 6u))
927		/*
928		 * MC API version 6.6 changed the size of the MC portals and
929		 * software portals to 64K (as implemented by hardware).
930		 */
931		cmdid = CMDID_RC_GET_OBJ_REG_V3;
932	else if (api_major == 6u && api_minor >= 3u)
933		/*
934		 * MC API version 6.3 introduced a new field to the region
935		 * descriptor: base_address.
936		 */
937		cmdid = CMDID_RC_GET_OBJ_REG_V2;
938	else
939		cmdid = CMDID_RC_GET_OBJ_REG;
940
941	args = (struct obj_region_args *) &cmd->params[0];
942	args->obj_id = obj_id;
943	args->reg_idx = reg_idx;
944	memcpy(args->type, type, min(strlen(type) + 1, TYPE_LEN_MAX));
945
946	error = dpaa2_rc_exec_cmd(portal, cmd, cmdid);
947	if (!error) {
948		resp = (struct obj_region *) &cmd->params[0];
949		reg->base_paddr = resp->base_paddr;
950		reg->base_offset = resp->base_offset;
951		reg->size = resp->size;
952		reg->flags = resp->flags;
953		reg->type = resp->type & 0xFu;
954	}
955
956	return (error);
957}
958
959static int
960dpaa2_rc_get_api_version(device_t dev, device_t child, struct dpaa2_cmd *cmd,
961    uint16_t *major, uint16_t *minor)
962{
963	struct __packed rc_api_version {
964		uint16_t	major;
965		uint16_t	minor;
966	} *resp;
967	struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
968	int error;
969
970	if (portal == NULL || cmd == NULL || major == NULL || minor == NULL)
971		return (DPAA2_CMD_STAT_ERR);
972
973	error = dpaa2_rc_exec_cmd(portal, cmd, CMDID_RC_GET_API_VERSION);
974	if (!error) {
975		resp = (struct rc_api_version *) &cmd->params[0];
976		*major = resp->major;
977		*minor = resp->minor;
978	}
979
980	return (error);
981}
982
983static int
984dpaa2_rc_set_irq_enable(device_t dev, device_t child, struct dpaa2_cmd *cmd,
985    uint8_t irq_idx, uint8_t enable)
986{
987	struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
988
989	if (portal == NULL || cmd == NULL)
990		return (DPAA2_CMD_STAT_ERR);
991
992	return (dpaa2_rc_enable_irq(portal, cmd, irq_idx, enable,
993	    CMDID_RC_SET_IRQ_ENABLE));
994}
995
996static int
997dpaa2_rc_set_obj_irq(device_t dev, device_t child, struct dpaa2_cmd *cmd,
998    uint8_t irq_idx, uint64_t addr, uint32_t data, uint32_t irq_usr,
999    uint32_t obj_id, enum dpaa2_dev_type dtype)
1000{
1001	struct __packed set_obj_irq_args {
1002		uint32_t	data;
1003		uint8_t		irq_idx;
1004		uint8_t		_reserved1[3];
1005		uint64_t	addr;
1006		uint32_t	irq_usr;
1007		uint32_t	obj_id;
1008		uint8_t		type[16];
1009	} *args;
1010	struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
1011	const char *type = dpaa2_ttos(dtype);
1012
1013	if (portal == NULL || cmd == NULL)
1014		return (DPAA2_CMD_STAT_ERR);
1015
1016	args = (struct set_obj_irq_args *) &cmd->params[0];
1017	args->irq_idx = irq_idx;
1018	args->addr = addr;
1019	args->data = data;
1020	args->irq_usr = irq_usr;
1021	args->obj_id = obj_id;
1022	memcpy(args->type, type, min(strlen(type) + 1, TYPE_LEN_MAX));
1023
1024	return (dpaa2_rc_exec_cmd(portal, cmd, CMDID_RC_SET_OBJ_IRQ));
1025}
1026
1027static int
1028dpaa2_rc_get_conn(device_t dev, device_t child, struct dpaa2_cmd *cmd,
1029    struct dpaa2_ep_desc *ep1_desc, struct dpaa2_ep_desc *ep2_desc,
1030    uint32_t *link_stat)
1031{
1032	struct __packed get_conn_args {
1033		uint32_t ep1_id;
1034		uint32_t ep1_ifid;
1035		uint8_t  ep1_type[16];
1036		uint64_t _reserved[4];
1037	} *args;
1038	struct __packed get_conn_resp {
1039		uint64_t _reserved1[3];
1040		uint32_t ep2_id;
1041		uint32_t ep2_ifid;
1042		uint8_t  ep2_type[16];
1043		uint32_t link_stat;
1044		uint32_t _reserved2;
1045	} *resp;
1046	struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
1047	int error;
1048
1049	if (portal == NULL || cmd == NULL || ep1_desc == NULL ||
1050	    ep2_desc == NULL)
1051		return (DPAA2_CMD_STAT_ERR);
1052
1053	args = (struct get_conn_args *) &cmd->params[0];
1054	args->ep1_id = ep1_desc->obj_id;
1055	args->ep1_ifid = ep1_desc->if_id;
1056	/* TODO: Remove magic number. */
1057	strncpy(args->ep1_type, dpaa2_ttos(ep1_desc->type), 16);
1058
1059	error = dpaa2_rc_exec_cmd(portal, cmd, CMDID_RC_GET_CONN);
1060	if (!error) {
1061		resp = (struct get_conn_resp *) &cmd->params[0];
1062		ep2_desc->obj_id = resp->ep2_id;
1063		ep2_desc->if_id = resp->ep2_ifid;
1064		ep2_desc->type = dpaa2_stot((const char *) resp->ep2_type);
1065		if (link_stat != NULL)
1066			*link_stat = resp->link_stat;
1067	}
1068
1069	return (error);
1070}
1071
1072static int
1073dpaa2_rc_ni_open(device_t dev, device_t child, struct dpaa2_cmd *cmd,
1074    uint32_t dpni_id, uint16_t *token)
1075{
1076	struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
1077	struct dpaa2_cmd_header *hdr;
1078	int error;
1079
1080	if (portal == NULL || cmd == NULL || token == NULL)
1081		return (DPAA2_CMD_STAT_ERR);
1082
1083	cmd->params[0] = dpni_id;
1084	error = dpaa2_rc_exec_cmd(portal, cmd, CMDID_NI_OPEN);
1085 	if (!error) {
1086		hdr = (struct dpaa2_cmd_header *) &cmd->header;
1087		*token = hdr->token;
1088	}
1089
1090	return (error);
1091}
1092
1093static int
1094dpaa2_rc_ni_close(device_t dev, device_t child, struct dpaa2_cmd *cmd)
1095{
1096	struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
1097
1098	if (portal == NULL || cmd == NULL)
1099		return (DPAA2_CMD_STAT_ERR);
1100
1101	return (dpaa2_rc_exec_cmd(portal, cmd, CMDID_NI_CLOSE));
1102}
1103
1104static int
1105dpaa2_rc_ni_enable(device_t dev, device_t child, struct dpaa2_cmd *cmd)
1106{
1107	struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
1108
1109	if (portal == NULL || cmd == NULL)
1110		return (DPAA2_CMD_STAT_ERR);
1111
1112	return (dpaa2_rc_exec_cmd(portal, cmd, CMDID_NI_ENABLE));
1113}
1114
1115static int
1116dpaa2_rc_ni_disable(device_t dev, device_t child, struct dpaa2_cmd *cmd)
1117{
1118	struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
1119
1120	if (portal == NULL || cmd == NULL)
1121		return (DPAA2_CMD_STAT_ERR);
1122
1123	return (dpaa2_rc_exec_cmd(portal, cmd, CMDID_NI_DISABLE));
1124}
1125
1126static int
1127dpaa2_rc_ni_get_api_version(device_t dev, device_t child, struct dpaa2_cmd *cmd,
1128    uint16_t *major, uint16_t *minor)
1129{
1130	struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
1131	int error;
1132
1133	if (portal == NULL || cmd == NULL || major == NULL || minor == NULL)
1134		return (DPAA2_CMD_STAT_ERR);
1135
1136	error = dpaa2_rc_exec_cmd(portal, cmd, CMDID_NI_GET_API_VER);
1137	if (!error) {
1138		*major = cmd->params[0] & 0xFFFFU;
1139		*minor = (cmd->params[0] >> 16) & 0xFFFFU;
1140	}
1141
1142	return (error);
1143}
1144
1145static int
1146dpaa2_rc_ni_reset(device_t dev, device_t child, struct dpaa2_cmd *cmd)
1147{
1148	struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
1149
1150	if (portal == NULL || cmd == NULL)
1151		return (DPAA2_CMD_STAT_ERR);
1152
1153	return (dpaa2_rc_exec_cmd(portal, cmd, CMDID_NI_RESET));
1154}
1155
1156static int
1157dpaa2_rc_ni_get_attributes(device_t dev, device_t child, struct dpaa2_cmd *cmd,
1158    struct dpaa2_ni_attr *attr)
1159{
1160	struct __packed ni_attr {
1161		uint32_t	options;
1162		uint8_t		num_queues;
1163		uint8_t		num_rx_tcs;
1164		uint8_t		mac_entries;
1165		uint8_t		num_tx_tcs;
1166		uint8_t		vlan_entries;
1167		uint8_t		num_channels;
1168		uint8_t		qos_entries;
1169		uint8_t		_reserved1;
1170		uint16_t	fs_entries;
1171		uint16_t	_reserved2;
1172		uint8_t		qos_key_size;
1173		uint8_t		fs_key_size;
1174		uint16_t	wriop_ver;
1175		uint8_t		num_cgs;
1176		uint8_t		_reserved3;
1177		uint16_t	_reserved4;
1178		uint64_t	_reserved5[4];
1179	} *resp;
1180	struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
1181	int error;
1182
1183	if (portal == NULL || cmd == NULL || attr == NULL)
1184		return (DPAA2_CMD_STAT_ERR);
1185
1186	error = dpaa2_rc_exec_cmd(portal, cmd, CMDID_NI_GET_ATTR);
1187	if (!error) {
1188		resp = (struct ni_attr *) &cmd->params[0];
1189
1190		attr->options =	     resp->options;
1191		attr->wriop_ver =    resp->wriop_ver;
1192
1193		attr->entries.fs =   resp->fs_entries;
1194		attr->entries.mac =  resp->mac_entries;
1195		attr->entries.vlan = resp->vlan_entries;
1196		attr->entries.qos =  resp->qos_entries;
1197
1198		attr->num.queues =   resp->num_queues;
1199		attr->num.rx_tcs =   resp->num_rx_tcs;
1200		attr->num.tx_tcs =   resp->num_tx_tcs;
1201		attr->num.channels = resp->num_channels;
1202		attr->num.cgs =      resp->num_cgs;
1203
1204		attr->key_size.fs =  resp->fs_key_size;
1205		attr->key_size.qos = resp->qos_key_size;
1206	}
1207
1208	return (error);
1209}
1210
1211static int
1212dpaa2_rc_ni_set_buf_layout(device_t dev, device_t child, struct dpaa2_cmd *cmd,
1213    struct dpaa2_ni_buf_layout *bl)
1214{
1215	struct __packed set_buf_layout_args {
1216		uint8_t		queue_type;
1217		uint8_t		_reserved1;
1218		uint16_t	_reserved2;
1219		uint16_t	options;
1220		uint8_t		params;
1221		uint8_t		_reserved3;
1222		uint16_t	priv_data_size;
1223		uint16_t	data_align;
1224		uint16_t	head_room;
1225		uint16_t	tail_room;
1226		uint64_t	_reserved4[5];
1227	} *args;
1228	struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
1229
1230	if (portal == NULL || cmd == NULL || bl == NULL)
1231		return (DPAA2_CMD_STAT_ERR);
1232
1233	args = (struct set_buf_layout_args *) &cmd->params[0];
1234	args->queue_type = (uint8_t) bl->queue_type;
1235	args->options = bl->options;
1236	args->params = 0;
1237	args->priv_data_size = bl->pd_size;
1238	args->data_align = bl->fd_align;
1239	args->head_room = bl->head_size;
1240	args->tail_room = bl->tail_size;
1241
1242	args->params |= bl->pass_timestamp	? 1U : 0U;
1243	args->params |= bl->pass_parser_result	? 2U : 0U;
1244	args->params |= bl->pass_frame_status	? 4U : 0U;
1245	args->params |= bl->pass_sw_opaque	? 8U : 0U;
1246
1247	return (dpaa2_rc_exec_cmd(portal, cmd, CMDID_NI_SET_BUF_LAYOUT));
1248}
1249
1250static int
1251dpaa2_rc_ni_get_tx_data_offset(device_t dev, device_t child,
1252    struct dpaa2_cmd *cmd, uint16_t *offset)
1253{
1254	struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
1255	int error;
1256
1257	if (portal == NULL || cmd == NULL || offset == NULL)
1258		return (DPAA2_CMD_STAT_ERR);
1259
1260	error = dpaa2_rc_exec_cmd(portal, cmd, CMDID_NI_GET_TX_DATA_OFF);
1261	if (!error)
1262		*offset = cmd->params[0] & 0xFFFFU;
1263
1264	return (error);
1265}
1266
1267static int
1268dpaa2_rc_ni_get_port_mac_addr(device_t dev, device_t child,
1269    struct dpaa2_cmd *cmd, uint8_t *mac)
1270{
1271	struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
1272	int error;
1273
1274	if (portal == NULL || cmd == NULL || mac == NULL)
1275		return (DPAA2_CMD_STAT_ERR);
1276
1277	error = dpaa2_rc_exec_cmd(portal, cmd, CMDID_NI_GET_PORT_MAC_ADDR);
1278	if (!error) {
1279		mac[0] = (cmd->params[0] >> 56) & 0xFFU;
1280		mac[1] = (cmd->params[0] >> 48) & 0xFFU;
1281		mac[2] = (cmd->params[0] >> 40) & 0xFFU;
1282		mac[3] = (cmd->params[0] >> 32) & 0xFFU;
1283		mac[4] = (cmd->params[0] >> 24) & 0xFFU;
1284		mac[5] = (cmd->params[0] >> 16) & 0xFFU;
1285	}
1286
1287	return (error);
1288}
1289
1290static int
1291dpaa2_rc_ni_set_prim_mac_addr(device_t dev, device_t child,
1292    struct dpaa2_cmd *cmd, uint8_t *mac)
1293{
1294	struct __packed set_prim_mac_args {
1295		uint8_t		_reserved[2];
1296		uint8_t		mac[ETHER_ADDR_LEN];
1297	} *args;
1298	struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
1299
1300	if (portal == NULL || cmd == NULL || mac == NULL)
1301		return (DPAA2_CMD_STAT_EINVAL);
1302
1303	args = (struct set_prim_mac_args *) &cmd->params[0];
1304	for (int i = 1; i <= ETHER_ADDR_LEN; i++)
1305		args->mac[i - 1] = mac[ETHER_ADDR_LEN - i];
1306
1307	return (dpaa2_rc_exec_cmd(portal, cmd, CMDID_NI_SET_PRIM_MAC_ADDR));
1308}
1309
1310static int
1311dpaa2_rc_ni_get_prim_mac_addr(device_t dev, device_t child,
1312    struct dpaa2_cmd *cmd, uint8_t *mac)
1313{
1314	struct __packed get_prim_mac_resp {
1315		uint8_t		_reserved[2];
1316		uint8_t		mac[ETHER_ADDR_LEN];
1317	} *resp;
1318	struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
1319	int error;
1320
1321	if (portal == NULL || cmd == NULL || mac == NULL)
1322		return (DPAA2_CMD_STAT_EINVAL);
1323
1324	error = dpaa2_rc_exec_cmd(portal, cmd, CMDID_NI_GET_PRIM_MAC_ADDR);
1325	if (!error) {
1326		resp = (struct get_prim_mac_resp *) &cmd->params[0];
1327		for (int i = 1; i <= ETHER_ADDR_LEN; i++)
1328			mac[ETHER_ADDR_LEN - i] = resp->mac[i - 1];
1329	}
1330
1331	return (error);
1332}
1333
1334static int
1335dpaa2_rc_ni_set_link_cfg(device_t dev, device_t child, struct dpaa2_cmd *cmd,
1336    struct dpaa2_ni_link_cfg *cfg)
1337{
1338	struct __packed link_cfg_args {
1339		uint64_t	_reserved1;
1340		uint32_t	rate;
1341		uint32_t	_reserved2;
1342		uint64_t	options;
1343		uint64_t	adv_speeds;
1344		uint64_t	_reserved3[3];
1345	} *args;
1346	struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
1347
1348	if (portal == NULL || cmd == NULL || cfg == NULL)
1349		return (DPAA2_CMD_STAT_EINVAL);
1350
1351	args = (struct link_cfg_args *) &cmd->params[0];
1352	args->rate = cfg->rate;
1353	args->options = cfg->options;
1354	args->adv_speeds = cfg->adv_speeds;
1355
1356	return (dpaa2_rc_exec_cmd(portal, cmd, CMDID_NI_SET_LINK_CFG));
1357}
1358
1359static int
1360dpaa2_rc_ni_get_link_cfg(device_t dev, device_t child, struct dpaa2_cmd *cmd,
1361    struct dpaa2_ni_link_cfg *cfg)
1362{
1363	struct __packed link_cfg_resp {
1364		uint64_t	_reserved1;
1365		uint32_t	rate;
1366		uint32_t	_reserved2;
1367		uint64_t	options;
1368		uint64_t	adv_speeds;
1369		uint64_t	_reserved3[3];
1370	} *resp;
1371	struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
1372	int error;
1373
1374	if (portal == NULL || cmd == NULL || cfg == NULL)
1375		return (DPAA2_CMD_STAT_EINVAL);
1376
1377	error = dpaa2_rc_exec_cmd(portal, cmd, CMDID_NI_GET_LINK_CFG);
1378	if (!error) {
1379		resp = (struct link_cfg_resp *) &cmd->params[0];
1380		cfg->rate = resp->rate;
1381		cfg->options = resp->options;
1382		cfg->adv_speeds = resp->adv_speeds;
1383	}
1384
1385	return (error);
1386}
1387
1388static int
1389dpaa2_rc_ni_get_link_state(device_t dev, device_t child, struct dpaa2_cmd *cmd,
1390    struct dpaa2_ni_link_state *state)
1391{
1392	struct __packed link_state_resp {
1393		uint32_t	_reserved1;
1394		uint32_t	flags;
1395		uint32_t	rate;
1396		uint32_t	_reserved2;
1397		uint64_t	options;
1398		uint64_t	supported;
1399		uint64_t	advert;
1400	} *resp;
1401	struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
1402	int error;
1403
1404	if (portal == NULL || cmd == NULL || state == NULL)
1405		return (DPAA2_CMD_STAT_EINVAL);
1406
1407	dpaa2_rc_reset_cmd_params(cmd);
1408
1409	error = dpaa2_rc_exec_cmd(portal, cmd, CMDID_NI_GET_LINK_STATE);
1410	if (!error) {
1411		resp = (struct link_state_resp *) &cmd->params[0];
1412		state->options = resp->options;
1413		state->adv_speeds = resp->advert;
1414		state->sup_speeds = resp->supported;
1415		state->rate = resp->rate;
1416
1417		state->link_up = resp->flags & 0x1u ? true : false;
1418		state->state_valid = resp->flags & 0x2u ? true : false;
1419	}
1420
1421	return (error);
1422}
1423
1424static int
1425dpaa2_rc_ni_set_qos_table(device_t dev, device_t child, struct dpaa2_cmd *cmd,
1426    struct dpaa2_ni_qos_table *tbl)
1427{
1428	struct __packed qos_table_args {
1429		uint32_t	_reserved1;
1430		uint8_t		default_tc;
1431		uint8_t		options;
1432		uint16_t	_reserved2;
1433		uint64_t	_reserved[5];
1434		uint64_t	kcfg_busaddr;
1435	} *args;
1436	struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
1437
1438	if (portal == NULL || cmd == NULL || tbl == NULL)
1439		return (DPAA2_CMD_STAT_EINVAL);
1440
1441	dpaa2_rc_reset_cmd_params(cmd);
1442
1443	args = (struct qos_table_args *) &cmd->params[0];
1444	args->default_tc = tbl->default_tc;
1445	args->kcfg_busaddr = tbl->kcfg_busaddr;
1446
1447	args->options |= tbl->discard_on_miss	? 1U : 0U;
1448	args->options |= tbl->keep_entries	? 2U : 0U;
1449
1450	return (dpaa2_rc_exec_cmd(portal, cmd, CMDID_NI_SET_QOS_TABLE));
1451}
1452
1453static int
1454dpaa2_rc_ni_clear_qos_table(device_t dev, device_t child, struct dpaa2_cmd *cmd)
1455{
1456	struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
1457
1458	if (portal == NULL || cmd == NULL)
1459		return (DPAA2_CMD_STAT_EINVAL);
1460
1461	return (dpaa2_rc_exec_cmd(portal, cmd, CMDID_NI_CLEAR_QOS_TABLE));
1462}
1463
1464static int
1465dpaa2_rc_ni_set_pools(device_t dev, device_t child, struct dpaa2_cmd *cmd,
1466    struct dpaa2_ni_pools_cfg *cfg)
1467{
1468	struct __packed set_pools_args {
1469		uint8_t		pools_num;
1470		uint8_t		backup_pool_mask;
1471		uint8_t		_reserved1;
1472		uint8_t		pool_as; /* assigning: 0 - QPRI, 1 - QDBIN */
1473		uint32_t	bp_obj_id[DPAA2_NI_MAX_POOLS];
1474		uint16_t	buf_sz[DPAA2_NI_MAX_POOLS];
1475		uint32_t	_reserved2;
1476	} *args;
1477	struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
1478
1479	if (portal == NULL || cmd == NULL || cfg == NULL)
1480		return (DPAA2_CMD_STAT_EINVAL);
1481
1482	dpaa2_rc_reset_cmd_params(cmd);
1483
1484	args = (struct set_pools_args *) &cmd->params[0];
1485	args->pools_num = cfg->pools_num < DPAA2_NI_MAX_POOLS
1486	    ? cfg->pools_num : DPAA2_NI_MAX_POOLS;
1487	for (uint32_t i = 0; i < args->pools_num; i++) {
1488		args->bp_obj_id[i] = cfg->pools[i].bp_obj_id;
1489		args->buf_sz[i] = cfg->pools[i].buf_sz;
1490		args->backup_pool_mask |= (cfg->pools[i].backup_flag & 1) << i;
1491	}
1492
1493	return (dpaa2_rc_exec_cmd(portal, cmd, CMDID_NI_SET_POOLS));
1494}
1495
1496static int
1497dpaa2_rc_ni_set_err_behavior(device_t dev, device_t child, struct dpaa2_cmd *cmd,
1498    struct dpaa2_ni_err_cfg *cfg)
1499{
1500	struct __packed err_behavior_args {
1501		uint32_t	err_mask;
1502		uint8_t		flags;
1503	} *args;
1504	struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
1505
1506	if (portal == NULL || cmd == NULL || cfg == NULL)
1507		return (DPAA2_CMD_STAT_EINVAL);
1508
1509	dpaa2_rc_reset_cmd_params(cmd);
1510
1511	args = (struct err_behavior_args *) &cmd->params[0];
1512	args->err_mask = cfg->err_mask;
1513
1514	args->flags |= cfg->set_err_fas ? 0x10u : 0u;
1515	args->flags |= ((uint8_t) cfg->action) & 0x0Fu;
1516
1517	return (dpaa2_rc_exec_cmd(portal, cmd, CMDID_NI_SET_ERR_BEHAVIOR));
1518}
1519
1520static int
1521dpaa2_rc_ni_get_queue(device_t dev, device_t child, struct dpaa2_cmd *cmd,
1522    struct dpaa2_ni_queue_cfg *cfg)
1523{
1524	struct __packed get_queue_args {
1525		uint8_t		queue_type;
1526		uint8_t		tc;
1527		uint8_t		idx;
1528		uint8_t		chan_id;
1529	} *args;
1530	struct __packed get_queue_resp {
1531		uint64_t	_reserved1;
1532		uint32_t	dest_id;
1533		uint16_t	_reserved2;
1534		uint8_t		priority;
1535		uint8_t		flags;
1536		uint64_t	flc;
1537		uint64_t	user_ctx;
1538		uint32_t	fqid;
1539		uint16_t	qdbin;
1540		uint16_t	_reserved3;
1541		uint8_t		cgid;
1542		uint8_t		_reserved[15];
1543	} *resp;
1544	struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
1545	int error;
1546
1547	if (portal == NULL || cmd == NULL || cfg == NULL)
1548		return (DPAA2_CMD_STAT_EINVAL);
1549
1550	dpaa2_rc_reset_cmd_params(cmd);
1551
1552	args = (struct get_queue_args *) &cmd->params[0];
1553	args->queue_type = (uint8_t) cfg->type;
1554	args->tc = cfg->tc;
1555	args->idx = cfg->idx;
1556	args->chan_id = cfg->chan_id;
1557
1558	error = dpaa2_rc_exec_cmd(portal, cmd, CMDID_NI_GET_QUEUE);
1559	if (!error) {
1560		resp = (struct get_queue_resp *) &cmd->params[0];
1561
1562		cfg->dest_id = resp->dest_id;
1563		cfg->priority = resp->priority;
1564		cfg->flow_ctx = resp->flc;
1565		cfg->user_ctx = resp->user_ctx;
1566		cfg->fqid = resp->fqid;
1567		cfg->qdbin = resp->qdbin;
1568		cfg->cgid = resp->cgid;
1569
1570		cfg->dest_type = (enum dpaa2_ni_dest_type) resp->flags & 0x0Fu;
1571		cfg->cgid_valid = (resp->flags & 0x20u) > 0u ? true : false;
1572		cfg->stash_control = (resp->flags & 0x40u) > 0u ? true : false;
1573		cfg->hold_active = (resp->flags & 0x80u) > 0u ? true : false;
1574	}
1575
1576	return (error);
1577}
1578
1579static int
1580dpaa2_rc_ni_set_queue(device_t dev, device_t child, struct dpaa2_cmd *cmd,
1581    struct dpaa2_ni_queue_cfg *cfg)
1582{
1583	struct __packed set_queue_args {
1584		uint8_t		queue_type;
1585		uint8_t		tc;
1586		uint8_t		idx;
1587		uint8_t		options;
1588		uint32_t	_reserved1;
1589		uint32_t	dest_id;
1590		uint16_t	_reserved2;
1591		uint8_t		priority;
1592		uint8_t		flags;
1593		uint64_t	flc;
1594		uint64_t	user_ctx;
1595		uint8_t		cgid;
1596		uint8_t		chan_id;
1597		uint8_t		_reserved[23];
1598	} *args;
1599	struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
1600
1601	if (portal == NULL || cmd == NULL || cfg == NULL)
1602		return (DPAA2_CMD_STAT_EINVAL);
1603
1604	dpaa2_rc_reset_cmd_params(cmd);
1605
1606	args = (struct set_queue_args *) &cmd->params[0];
1607	args->queue_type = (uint8_t) cfg->type;
1608	args->tc = cfg->tc;
1609	args->idx = cfg->idx;
1610	args->options = cfg->options;
1611	args->dest_id = cfg->dest_id;
1612	args->priority = cfg->priority;
1613	args->flc = cfg->flow_ctx;
1614	args->user_ctx = cfg->user_ctx;
1615	args->cgid = cfg->cgid;
1616	args->chan_id = cfg->chan_id;
1617
1618	args->flags |= (uint8_t)(cfg->dest_type & 0x0Fu);
1619	args->flags |= cfg->stash_control ? 0x40u : 0u;
1620	args->flags |= cfg->hold_active ? 0x80u : 0u;
1621
1622	return (dpaa2_rc_exec_cmd(portal, cmd, CMDID_NI_SET_QUEUE));
1623}
1624
1625static int
1626dpaa2_rc_ni_get_qdid(device_t dev, device_t child, struct dpaa2_cmd *cmd,
1627    enum dpaa2_ni_queue_type type, uint16_t *qdid)
1628{
1629	struct __packed get_qdid_args {
1630		uint8_t		queue_type;
1631	} *args;
1632	struct __packed get_qdid_resp {
1633		uint16_t	qdid;
1634	} *resp;
1635	struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
1636	int error;
1637
1638	if (portal == NULL || cmd == NULL || qdid == NULL)
1639		return (DPAA2_CMD_STAT_EINVAL);
1640
1641	dpaa2_rc_reset_cmd_params(cmd);
1642
1643	args = (struct get_qdid_args *) &cmd->params[0];
1644	args->queue_type = (uint8_t) type;
1645
1646	error = dpaa2_rc_exec_cmd(portal, cmd, CMDID_NI_GET_QDID);
1647	if (!error) {
1648		resp = (struct get_qdid_resp *) &cmd->params[0];
1649		*qdid = resp->qdid;
1650	}
1651
1652	return (error);
1653}
1654
1655static int
1656dpaa2_rc_ni_add_mac_addr(device_t dev, device_t child, struct dpaa2_cmd *cmd,
1657    uint8_t *mac)
1658{
1659	struct __packed add_mac_args {
1660		uint8_t		flags;
1661		uint8_t		_reserved;
1662		uint8_t		mac[ETHER_ADDR_LEN];
1663		uint8_t		tc_id;
1664		uint8_t		fq_id;
1665	} *args;
1666	struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
1667
1668	if (portal == NULL || cmd == NULL || mac == NULL)
1669		return (DPAA2_CMD_STAT_EINVAL);
1670
1671	dpaa2_rc_reset_cmd_params(cmd);
1672
1673	args = (struct add_mac_args *) &cmd->params[0];
1674	for (int i = 1; i <= ETHER_ADDR_LEN; i++)
1675		args->mac[i - 1] = mac[ETHER_ADDR_LEN - i];
1676
1677	return (dpaa2_rc_exec_cmd(portal, cmd, CMDID_NI_ADD_MAC_ADDR));
1678}
1679
1680static int
1681dpaa2_rc_ni_remove_mac_addr(device_t dev, device_t child, struct dpaa2_cmd *cmd,
1682    uint8_t *mac)
1683{
1684	struct __packed rem_mac_args {
1685		uint16_t	_reserved;
1686		uint8_t		mac[ETHER_ADDR_LEN];
1687		uint64_t	_reserved1[6];
1688	} *args;
1689	struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
1690
1691	if (portal == NULL || cmd == NULL || mac == NULL)
1692		return (DPAA2_CMD_STAT_EINVAL);
1693
1694	dpaa2_rc_reset_cmd_params(cmd);
1695
1696	args = (struct rem_mac_args *) &cmd->params[0];
1697	for (int i = 1; i <= ETHER_ADDR_LEN; i++)
1698		args->mac[i - 1] = mac[ETHER_ADDR_LEN - i];
1699
1700	return (dpaa2_rc_exec_cmd(portal, cmd, CMDID_NI_REMOVE_MAC_ADDR));
1701}
1702
1703static int
1704dpaa2_rc_ni_clear_mac_filters(device_t dev, device_t child,
1705    struct dpaa2_cmd *cmd, bool rm_uni, bool rm_multi)
1706{
1707	struct __packed clear_mac_filters_args {
1708		uint8_t		flags;
1709	} *args;
1710	struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
1711
1712	if (portal == NULL || cmd == NULL)
1713		return (DPAA2_CMD_STAT_EINVAL);
1714
1715	dpaa2_rc_reset_cmd_params(cmd);
1716
1717	args = (struct clear_mac_filters_args *) &cmd->params[0];
1718	args->flags |= rm_uni ? 0x1 : 0x0;
1719	args->flags |= rm_multi ? 0x2 : 0x0;
1720
1721	return (dpaa2_rc_exec_cmd(portal, cmd, CMDID_NI_CLEAR_MAC_FILTERS));
1722}
1723
1724static int
1725dpaa2_rc_ni_set_mfl(device_t dev, device_t child, struct dpaa2_cmd *cmd,
1726    uint16_t length)
1727{
1728	struct __packed set_mfl_args {
1729		uint16_t length;
1730	} *args;
1731	struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
1732
1733	if (portal == NULL || cmd == NULL)
1734		return (DPAA2_CMD_STAT_EINVAL);
1735
1736	dpaa2_rc_reset_cmd_params(cmd);
1737
1738	args = (struct set_mfl_args *) &cmd->params[0];
1739	args->length = length;
1740
1741	return (dpaa2_rc_exec_cmd(portal, cmd, CMDID_NI_SET_MFL));
1742}
1743
1744static int
1745dpaa2_rc_ni_set_offload(device_t dev, device_t child, struct dpaa2_cmd *cmd,
1746    enum dpaa2_ni_ofl_type ofl_type, bool en)
1747{
1748	struct __packed set_ofl_args {
1749		uint8_t		_reserved[3];
1750		uint8_t		ofl_type;
1751		uint32_t	config;
1752	} *args;
1753	struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
1754
1755	if (portal == NULL || cmd == NULL)
1756		return (DPAA2_CMD_STAT_EINVAL);
1757
1758	dpaa2_rc_reset_cmd_params(cmd);
1759
1760	args = (struct set_ofl_args *) &cmd->params[0];
1761	args->ofl_type = (uint8_t) ofl_type;
1762	args->config = en ? 1u : 0u;
1763
1764	return (dpaa2_rc_exec_cmd(portal, cmd, CMDID_NI_SET_OFFLOAD));
1765}
1766
1767static int
1768dpaa2_rc_ni_set_irq_mask(device_t dev, device_t child, struct dpaa2_cmd *cmd,
1769    uint8_t irq_idx, uint32_t mask)
1770{
1771	struct __packed set_irq_mask_args {
1772		uint32_t	mask;
1773		uint8_t		irq_idx;
1774	} *args;
1775	struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
1776
1777	if (portal == NULL || cmd == NULL)
1778		return (DPAA2_CMD_STAT_EINVAL);
1779
1780	dpaa2_rc_reset_cmd_params(cmd);
1781
1782	args = (struct set_irq_mask_args *) &cmd->params[0];
1783	args->mask = mask;
1784	args->irq_idx = irq_idx;
1785
1786	return (dpaa2_rc_exec_cmd(portal, cmd, CMDID_NI_SET_IRQ_MASK));
1787}
1788
1789static int
1790dpaa2_rc_ni_set_irq_enable(device_t dev, device_t child, struct dpaa2_cmd *cmd,
1791    uint8_t irq_idx, bool en)
1792{
1793	struct __packed set_irq_enable_args {
1794		uint32_t	en;
1795		uint8_t		irq_idx;
1796	} *args;
1797	struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
1798
1799	if (portal == NULL || cmd == NULL)
1800		return (DPAA2_CMD_STAT_EINVAL);
1801
1802	dpaa2_rc_reset_cmd_params(cmd);
1803
1804	args = (struct set_irq_enable_args *) &cmd->params[0];
1805	args->en = en ? 1u : 0u;
1806	args->irq_idx = irq_idx;
1807
1808	return (dpaa2_rc_exec_cmd(portal, cmd, CMDID_NI_SET_IRQ_ENABLE));
1809}
1810
1811static int
1812dpaa2_rc_ni_get_irq_status(device_t dev, device_t child, struct dpaa2_cmd *cmd,
1813    uint8_t irq_idx, uint32_t *status)
1814{
1815	struct __packed get_irq_stat_args {
1816		uint32_t	status;
1817		uint8_t		irq_idx;
1818	} *args;
1819	struct __packed get_irq_stat_resp {
1820		uint32_t	status;
1821	} *resp;
1822	struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
1823	int error;
1824
1825	if (portal == NULL || cmd == NULL || status == NULL)
1826		return (DPAA2_CMD_STAT_EINVAL);
1827
1828	dpaa2_rc_reset_cmd_params(cmd);
1829
1830	args = (struct get_irq_stat_args *) &cmd->params[0];
1831	args->status = *status;
1832	args->irq_idx = irq_idx;
1833
1834	error = dpaa2_rc_exec_cmd(portal, cmd, CMDID_NI_GET_IRQ_STATUS);
1835	if (!error) {
1836		resp = (struct get_irq_stat_resp *) &cmd->params[0];
1837		*status = resp->status;
1838	}
1839
1840	return (error);
1841}
1842
1843static int
1844dpaa2_rc_ni_set_uni_promisc(device_t dev, device_t child, struct dpaa2_cmd *cmd,
1845    bool en)
1846{
1847	struct __packed set_uni_promisc_args {
1848		uint8_t	en;
1849	} *args;
1850	struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
1851
1852	if (portal == NULL || cmd == NULL)
1853		return (DPAA2_CMD_STAT_EINVAL);
1854
1855	dpaa2_rc_reset_cmd_params(cmd);
1856
1857	args = (struct set_uni_promisc_args *) &cmd->params[0];
1858	args->en = en ? 1u : 0u;
1859
1860	return (dpaa2_rc_exec_cmd(portal, cmd, CMDID_NI_SET_UNI_PROMISC));
1861}
1862
1863static int
1864dpaa2_rc_ni_set_multi_promisc(device_t dev, device_t child,
1865    struct dpaa2_cmd *cmd, bool en)
1866{
1867	/* TODO: Implementation is the same as for ni_set_uni_promisc(). */
1868	struct __packed set_multi_promisc_args {
1869		uint8_t	en;
1870	} *args;
1871	struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
1872
1873	if (portal == NULL || cmd == NULL)
1874		return (DPAA2_CMD_STAT_EINVAL);
1875
1876	dpaa2_rc_reset_cmd_params(cmd);
1877
1878	args = (struct set_multi_promisc_args *) &cmd->params[0];
1879	args->en = en ? 1u : 0u;
1880
1881	return (dpaa2_rc_exec_cmd(portal, cmd, CMDID_NI_SET_MULTI_PROMISC));
1882}
1883
1884static int
1885dpaa2_rc_ni_get_statistics(device_t dev, device_t child, struct dpaa2_cmd *cmd,
1886    uint8_t page, uint16_t param, uint64_t *cnt)
1887{
1888	struct __packed get_statistics_args {
1889		uint8_t		page;
1890		uint16_t	param;
1891	} *args;
1892	struct __packed get_statistics_resp {
1893		uint64_t	cnt[7];
1894	} *resp;
1895	struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
1896	int error;
1897
1898	if (portal == NULL || cmd == NULL || cnt == NULL)
1899		return (DPAA2_CMD_STAT_EINVAL);
1900
1901	dpaa2_rc_reset_cmd_params(cmd);
1902
1903	args = (struct get_statistics_args *) &cmd->params[0];
1904	args->page = page;
1905	args->param = param;
1906
1907	error = dpaa2_rc_exec_cmd(portal, cmd, CMDID_NI_GET_STATISTICS);
1908	if (!error) {
1909		resp = (struct get_statistics_resp *) &cmd->params[0];
1910		for (int i = 0; i < DPAA2_NI_STAT_COUNTERS; i++)
1911			cnt[i] = resp->cnt[i];
1912	}
1913
1914	return (error);
1915}
1916
1917static int
1918dpaa2_rc_ni_set_rx_tc_dist(device_t dev, device_t child, struct dpaa2_cmd *cmd,
1919    uint16_t dist_size, uint8_t tc, enum dpaa2_ni_dist_mode dist_mode,
1920    bus_addr_t key_cfg_buf)
1921{
1922	struct __packed set_rx_tc_dist_args {
1923		uint16_t	dist_size;
1924		uint8_t		tc;
1925		uint8_t		ma_dm; /* miss action + dist. mode */
1926		uint32_t	_reserved1;
1927		uint64_t	_reserved2[5];
1928		uint64_t	key_cfg_iova;
1929	} *args;
1930	struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
1931
1932	if (portal == NULL || cmd == NULL)
1933		return (DPAA2_CMD_STAT_EINVAL);
1934
1935	dpaa2_rc_reset_cmd_params(cmd);
1936
1937	args = (struct set_rx_tc_dist_args *) &cmd->params[0];
1938	args->dist_size = dist_size;
1939	args->tc = tc;
1940	args->ma_dm = ((uint8_t) dist_mode) & 0x0Fu;
1941	args->key_cfg_iova = key_cfg_buf;
1942
1943	return (dpaa2_rc_exec_cmd(portal, cmd, CMDID_NI_SET_RX_TC_DIST));
1944}
1945
1946static int
1947dpaa2_rc_io_open(device_t dev, device_t child, struct dpaa2_cmd *cmd,
1948    uint32_t dpio_id, uint16_t *token)
1949{
1950	struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
1951	struct dpaa2_cmd_header *hdr;
1952	int error;
1953
1954	if (portal == NULL || cmd == NULL || token == NULL)
1955		return (DPAA2_CMD_STAT_ERR);
1956
1957	cmd->params[0] = dpio_id;
1958	error = dpaa2_rc_exec_cmd(portal, cmd, CMDID_IO_OPEN);
1959	if (!error) {
1960		hdr = (struct dpaa2_cmd_header *) &cmd->header;
1961		*token = hdr->token;
1962	}
1963
1964	return (error);
1965}
1966
1967static int
1968dpaa2_rc_io_close(device_t dev, device_t child, struct dpaa2_cmd *cmd)
1969{
1970	struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
1971
1972	if (portal == NULL || cmd == NULL)
1973		return (DPAA2_CMD_STAT_ERR);
1974
1975	return (dpaa2_rc_exec_cmd(portal, cmd, CMDID_IO_CLOSE));
1976}
1977
1978static int
1979dpaa2_rc_io_enable(device_t dev, device_t child, struct dpaa2_cmd *cmd)
1980{
1981	struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
1982
1983	if (portal == NULL || cmd == NULL)
1984		return (DPAA2_CMD_STAT_ERR);
1985
1986	return (dpaa2_rc_exec_cmd(portal, cmd, CMDID_IO_ENABLE));
1987}
1988
1989static int
1990dpaa2_rc_io_disable(device_t dev, device_t child, struct dpaa2_cmd *cmd)
1991{
1992	struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
1993
1994	if (portal == NULL || cmd == NULL)
1995		return (DPAA2_CMD_STAT_ERR);
1996
1997	return (dpaa2_rc_exec_cmd(portal, cmd, CMDID_IO_DISABLE));
1998}
1999
2000static int
2001dpaa2_rc_io_reset(device_t dev, device_t child, struct dpaa2_cmd *cmd)
2002{
2003	struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
2004
2005	if (portal == NULL || cmd == NULL)
2006		return (DPAA2_CMD_STAT_ERR);
2007
2008	return (dpaa2_rc_exec_cmd(portal, cmd, CMDID_IO_RESET));
2009}
2010
2011static int
2012dpaa2_rc_io_get_attributes(device_t dev, device_t child, struct dpaa2_cmd *cmd,
2013    struct dpaa2_io_attr *attr)
2014{
2015	struct __packed dpaa2_io_attr {
2016		uint32_t	id;
2017		uint16_t	swp_id;
2018		uint8_t		priors_num;
2019		uint8_t		chan_mode;
2020		uint64_t	swp_ce_paddr;
2021		uint64_t	swp_ci_paddr;
2022		uint32_t	swp_version;
2023		uint32_t	_reserved1;
2024		uint32_t	swp_clk;
2025		uint32_t	_reserved2[5];
2026	} *pattr;
2027	struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
2028	int error;
2029
2030	if (portal == NULL || cmd == NULL || attr == NULL)
2031		return (DPAA2_CMD_STAT_ERR);
2032
2033	error = dpaa2_rc_exec_cmd(portal, cmd, CMDID_IO_GET_ATTR);
2034	if (!error) {
2035		pattr = (struct dpaa2_io_attr *) &cmd->params[0];
2036
2037		attr->swp_ce_paddr = pattr->swp_ce_paddr;
2038		attr->swp_ci_paddr = pattr->swp_ci_paddr;
2039		attr->swp_version = pattr->swp_version;
2040		attr->swp_clk = pattr->swp_clk;
2041		attr->id = pattr->id;
2042		attr->swp_id = pattr->swp_id;
2043		attr->priors_num = pattr->priors_num;
2044		attr->chan_mode = (enum dpaa2_io_chan_mode)
2045		    pattr->chan_mode;
2046	}
2047
2048	return (error);
2049}
2050
2051static int
2052dpaa2_rc_io_set_irq_mask(device_t dev, device_t child, struct dpaa2_cmd *cmd,
2053    uint8_t irq_idx, uint32_t mask)
2054{
2055	/* TODO: Extract similar *_set_irq_mask() into one function. */
2056	struct __packed set_irq_mask_args {
2057		uint32_t	mask;
2058		uint8_t		irq_idx;
2059	} *args;
2060	struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
2061
2062	if (portal == NULL || cmd == NULL)
2063		return (DPAA2_CMD_STAT_EINVAL);
2064
2065	dpaa2_rc_reset_cmd_params(cmd);
2066
2067	args = (struct set_irq_mask_args *) &cmd->params[0];
2068	args->mask = mask;
2069	args->irq_idx = irq_idx;
2070
2071	return (dpaa2_rc_exec_cmd(portal, cmd, CMDID_IO_SET_IRQ_MASK));
2072}
2073
2074static int
2075dpaa2_rc_io_get_irq_status(device_t dev, device_t child, struct dpaa2_cmd *cmd,
2076    uint8_t irq_idx, uint32_t *status)
2077{
2078	/* TODO: Extract similar *_get_irq_status() into one function. */
2079	struct __packed get_irq_stat_args {
2080		uint32_t	status;
2081		uint8_t		irq_idx;
2082	} *args;
2083	struct __packed get_irq_stat_resp {
2084		uint32_t	status;
2085	} *resp;
2086	struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
2087	int error;
2088
2089	if (portal == NULL || cmd == NULL || status == NULL)
2090		return (DPAA2_CMD_STAT_EINVAL);
2091
2092	dpaa2_rc_reset_cmd_params(cmd);
2093
2094	args = (struct get_irq_stat_args *) &cmd->params[0];
2095	args->status = *status;
2096	args->irq_idx = irq_idx;
2097
2098	error = dpaa2_rc_exec_cmd(portal, cmd, CMDID_IO_GET_IRQ_STATUS);
2099	if (!error) {
2100		resp = (struct get_irq_stat_resp *) &cmd->params[0];
2101		*status = resp->status;
2102	}
2103
2104	return (error);
2105}
2106
2107static int
2108dpaa2_rc_io_set_irq_enable(device_t dev, device_t child, struct dpaa2_cmd *cmd,
2109    uint8_t irq_idx, bool en)
2110{
2111	/* TODO: Extract similar *_set_irq_enable() into one function. */
2112	struct __packed set_irq_enable_args {
2113		uint32_t	en;
2114		uint8_t		irq_idx;
2115	} *args;
2116	struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
2117
2118	if (portal == NULL || cmd == NULL)
2119		return (DPAA2_CMD_STAT_EINVAL);
2120
2121	dpaa2_rc_reset_cmd_params(cmd);
2122
2123	args = (struct set_irq_enable_args *) &cmd->params[0];
2124	args->en = en ? 1u : 0u;
2125	args->irq_idx = irq_idx;
2126
2127	return (dpaa2_rc_exec_cmd(portal, cmd, CMDID_IO_SET_IRQ_ENABLE));
2128}
2129
2130static int
2131dpaa2_rc_io_add_static_dq_chan(device_t dev, device_t child,
2132    struct dpaa2_cmd *cmd, uint32_t dpcon_id, uint8_t *chan_idx)
2133{
2134	struct __packed add_static_dq_chan_args {
2135		uint32_t	dpcon_id;
2136	} *args;
2137	struct __packed add_static_dq_chan_resp {
2138		uint8_t		chan_idx;
2139	} *resp;
2140	struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
2141	int error;
2142
2143	if (portal == NULL || cmd == NULL || chan_idx == NULL)
2144		return (DPAA2_CMD_STAT_EINVAL);
2145
2146	dpaa2_rc_reset_cmd_params(cmd);
2147
2148	args = (struct add_static_dq_chan_args *) &cmd->params[0];
2149	args->dpcon_id = dpcon_id;
2150
2151	error = dpaa2_rc_exec_cmd(portal, cmd, CMDID_IO_ADD_STATIC_DQ_CHAN);
2152	if (!error) {
2153		resp = (struct add_static_dq_chan_resp *) &cmd->params[0];
2154		*chan_idx = resp->chan_idx;
2155	}
2156
2157	return (error);
2158}
2159
2160static int
2161dpaa2_rc_bp_open(device_t dev, device_t child, struct dpaa2_cmd *cmd,
2162    uint32_t dpbp_id, uint16_t *token)
2163{
2164	struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
2165	struct dpaa2_cmd_header *hdr;
2166	int error;
2167
2168	if (portal == NULL || cmd == NULL || token == NULL)
2169		return (DPAA2_CMD_STAT_ERR);
2170
2171	cmd->params[0] = dpbp_id;
2172	error = dpaa2_rc_exec_cmd(portal, cmd, CMDID_BP_OPEN);
2173	if (!error) {
2174		hdr = (struct dpaa2_cmd_header *) &cmd->header;
2175		*token = hdr->token;
2176	}
2177
2178	return (error);
2179}
2180
2181static int
2182dpaa2_rc_bp_close(device_t dev, device_t child, struct dpaa2_cmd *cmd)
2183{
2184	struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
2185
2186	if (portal == NULL || cmd == NULL)
2187		return (DPAA2_CMD_STAT_ERR);
2188
2189	return (dpaa2_rc_exec_cmd(portal, cmd, CMDID_BP_CLOSE));
2190}
2191
2192static int
2193dpaa2_rc_bp_enable(device_t dev, device_t child, struct dpaa2_cmd *cmd)
2194{
2195	struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
2196
2197	if (portal == NULL || cmd == NULL)
2198		return (DPAA2_CMD_STAT_ERR);
2199
2200	return (dpaa2_rc_exec_cmd(portal, cmd, CMDID_BP_ENABLE));
2201}
2202
2203static int
2204dpaa2_rc_bp_disable(device_t dev, device_t child, struct dpaa2_cmd *cmd)
2205{
2206	struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
2207
2208	if (portal == NULL || cmd == NULL)
2209		return (DPAA2_CMD_STAT_ERR);
2210
2211	return (dpaa2_rc_exec_cmd(portal, cmd, CMDID_BP_DISABLE));
2212}
2213
2214static int
2215dpaa2_rc_bp_reset(device_t dev, device_t child, struct dpaa2_cmd *cmd)
2216{
2217	struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
2218
2219	if (portal == NULL || cmd == NULL)
2220		return (DPAA2_CMD_STAT_ERR);
2221
2222	return (dpaa2_rc_exec_cmd(portal, cmd, CMDID_BP_RESET));
2223}
2224
2225static int
2226dpaa2_rc_bp_get_attributes(device_t dev, device_t child, struct dpaa2_cmd *cmd,
2227    struct dpaa2_bp_attr *attr)
2228{
2229	struct __packed dpaa2_bp_attr {
2230		uint16_t	_reserved1;
2231		uint16_t	bpid;
2232		uint32_t	id;
2233	} *pattr;
2234	struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
2235	int error;
2236
2237	if (portal == NULL || cmd == NULL || attr == NULL)
2238		return (DPAA2_CMD_STAT_ERR);
2239
2240	error = dpaa2_rc_exec_cmd(portal, cmd, CMDID_BP_GET_ATTR);
2241	if (!error) {
2242		pattr = (struct dpaa2_bp_attr *) &cmd->params[0];
2243		attr->id = pattr->id;
2244		attr->bpid = pattr->bpid;
2245	}
2246
2247	return (error);
2248}
2249
2250static int
2251dpaa2_rc_mac_open(device_t dev, device_t child, struct dpaa2_cmd *cmd,
2252    uint32_t dpmac_id, uint16_t *token)
2253{
2254	struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
2255	struct dpaa2_cmd_header *hdr;
2256	int error;
2257
2258	if (portal == NULL || cmd == NULL || token == NULL)
2259		return (DPAA2_CMD_STAT_ERR);
2260
2261	cmd->params[0] = dpmac_id;
2262	error = dpaa2_rc_exec_cmd(portal, cmd, CMDID_MAC_OPEN);
2263	if (!error) {
2264		hdr = (struct dpaa2_cmd_header *) &cmd->header;
2265		*token = hdr->token;
2266	}
2267
2268	return (error);
2269}
2270
2271static int
2272dpaa2_rc_mac_close(device_t dev, device_t child, struct dpaa2_cmd *cmd)
2273{
2274	struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
2275
2276	if (portal == NULL || cmd == NULL)
2277		return (DPAA2_CMD_STAT_ERR);
2278
2279	return (dpaa2_rc_exec_cmd(portal, cmd, CMDID_MAC_CLOSE));
2280}
2281
2282static int
2283dpaa2_rc_mac_reset(device_t dev, device_t child, struct dpaa2_cmd *cmd)
2284{
2285	struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
2286
2287	if (portal == NULL || cmd == NULL)
2288		return (DPAA2_CMD_STAT_ERR);
2289
2290	return (dpaa2_rc_exec_cmd(portal, cmd, CMDID_MAC_RESET));
2291}
2292
2293static int
2294dpaa2_rc_mac_mdio_read(device_t dev, device_t child, struct dpaa2_cmd *cmd,
2295    uint8_t phy, uint16_t reg, uint16_t *val)
2296{
2297	struct __packed mdio_read_args {
2298		uint8_t		clause; /* set to 0 by default */
2299		uint8_t		phy;
2300		uint16_t	reg;
2301		uint32_t	_reserved1;
2302		uint64_t	_reserved2[6];
2303	} *args;
2304	struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
2305	int error;
2306
2307	if (portal == NULL || cmd == NULL || val == NULL)
2308		return (DPAA2_CMD_STAT_ERR);
2309
2310	args = (struct mdio_read_args *) &cmd->params[0];
2311	args->phy = phy;
2312	args->reg = reg;
2313	args->clause = 0;
2314
2315	error = dpaa2_rc_exec_cmd(portal, cmd, CMDID_MAC_MDIO_READ);
2316	if (!error)
2317		*val = cmd->params[0] & 0xFFFF;
2318
2319	return (error);
2320}
2321
2322static int
2323dpaa2_rc_mac_mdio_write(device_t dev, device_t child, struct dpaa2_cmd *cmd,
2324    uint8_t phy, uint16_t reg, uint16_t val)
2325{
2326	struct __packed mdio_write_args {
2327		uint8_t		clause; /* set to 0 by default */
2328		uint8_t		phy;
2329		uint16_t	reg;
2330		uint16_t	val;
2331		uint16_t	_reserved1;
2332		uint64_t	_reserved2[6];
2333	} *args;
2334	struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
2335
2336	if (portal == NULL || cmd == NULL)
2337		return (DPAA2_CMD_STAT_ERR);
2338
2339	args = (struct mdio_write_args *) &cmd->params[0];
2340	args->phy = phy;
2341	args->reg = reg;
2342	args->val = val;
2343	args->clause = 0;
2344
2345	return (dpaa2_rc_exec_cmd(portal, cmd, CMDID_MAC_MDIO_WRITE));
2346}
2347
2348static int
2349dpaa2_rc_mac_get_addr(device_t dev, device_t child, struct dpaa2_cmd *cmd,
2350    uint8_t *mac)
2351{
2352	struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
2353	int error;
2354
2355	if (portal == NULL || cmd == NULL || mac == NULL)
2356		return (DPAA2_CMD_STAT_ERR);
2357
2358	error = dpaa2_rc_exec_cmd(portal, cmd, CMDID_MAC_GET_ADDR);
2359	if (!error) {
2360		mac[0] = (cmd->params[0] >> 56) & 0xFFU;
2361		mac[1] = (cmd->params[0] >> 48) & 0xFFU;
2362		mac[2] = (cmd->params[0] >> 40) & 0xFFU;
2363		mac[3] = (cmd->params[0] >> 32) & 0xFFU;
2364		mac[4] = (cmd->params[0] >> 24) & 0xFFU;
2365		mac[5] = (cmd->params[0] >> 16) & 0xFFU;
2366	}
2367
2368	return (error);
2369}
2370
2371static int
2372dpaa2_rc_mac_get_attributes(device_t dev, device_t child, struct dpaa2_cmd *cmd,
2373    struct dpaa2_mac_attr *attr)
2374{
2375	struct __packed mac_attr_resp {
2376		uint8_t		eth_if;
2377		uint8_t		link_type;
2378		uint16_t	id;
2379		uint32_t	max_rate;
2380
2381		uint8_t		fec_mode;
2382		uint8_t		ifg_mode;
2383		uint8_t		ifg_len;
2384		uint8_t		_reserved1;
2385		uint32_t	_reserved2;
2386
2387		uint8_t		sgn_post_pre;
2388		uint8_t		serdes_cfg_mode;
2389		uint8_t		eq_amp_red;
2390		uint8_t		eq_post1q;
2391		uint8_t		eq_preq;
2392		uint8_t		eq_type;
2393		uint16_t	_reserved3;
2394
2395		uint64_t	_reserved[4];
2396	} *resp;
2397	struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
2398	int error;
2399
2400	if (portal == NULL || cmd == NULL || attr == NULL)
2401		return (DPAA2_CMD_STAT_EINVAL);
2402
2403	error = dpaa2_rc_exec_cmd(portal, cmd, CMDID_MAC_GET_ATTR);
2404	if (!error) {
2405		resp = (struct mac_attr_resp *) &cmd->params[0];
2406		attr->id = resp->id;
2407		attr->max_rate = resp->max_rate;
2408		attr->eth_if = resp->eth_if;
2409		attr->link_type = resp->link_type;
2410	}
2411
2412	return (error);
2413}
2414
2415static int
2416dpaa2_rc_mac_set_link_state(device_t dev, device_t child, struct dpaa2_cmd *cmd,
2417    struct dpaa2_mac_link_state *state)
2418{
2419	struct __packed mac_set_link_args {
2420		uint64_t	options;
2421		uint32_t	rate;
2422		uint32_t	_reserved1;
2423		uint32_t	flags;
2424		uint32_t	_reserved2;
2425		uint64_t	supported;
2426		uint64_t	advert;
2427	} *args;
2428	struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
2429
2430	if (portal == NULL || cmd == NULL || state == NULL)
2431		return (DPAA2_CMD_STAT_EINVAL);
2432
2433	dpaa2_rc_reset_cmd_params(cmd);
2434
2435	args = (struct mac_set_link_args *) &cmd->params[0];
2436	args->options = state->options;
2437	args->rate = state->rate;
2438	args->supported = state->supported;
2439	args->advert = state->advert;
2440
2441	args->flags |= state->up ? 0x1u : 0u;
2442	args->flags |= state->state_valid ? 0x2u : 0u;
2443
2444	return (dpaa2_rc_exec_cmd(portal, cmd, CMDID_MAC_SET_LINK_STATE));
2445}
2446
2447static int
2448dpaa2_rc_mac_set_irq_mask(device_t dev, device_t child, struct dpaa2_cmd *cmd,
2449    uint8_t irq_idx, uint32_t mask)
2450{
2451	/* TODO: Implementation is the same as for ni_set_irq_mask(). */
2452	struct __packed set_irq_mask_args {
2453		uint32_t	mask;
2454		uint8_t		irq_idx;
2455	} *args;
2456	struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
2457
2458	if (portal == NULL || cmd == NULL)
2459		return (DPAA2_CMD_STAT_EINVAL);
2460
2461	dpaa2_rc_reset_cmd_params(cmd);
2462
2463	args = (struct set_irq_mask_args *) &cmd->params[0];
2464	args->mask = mask;
2465	args->irq_idx = irq_idx;
2466
2467	return (dpaa2_rc_exec_cmd(portal, cmd, CMDID_MAC_SET_IRQ_MASK));
2468}
2469
2470static int
2471dpaa2_rc_mac_set_irq_enable(device_t dev, device_t child, struct dpaa2_cmd *cmd,
2472    uint8_t irq_idx, bool en)
2473{
2474	/* TODO: Implementation is the same as for ni_set_irq_enable(). */
2475	struct __packed set_irq_enable_args {
2476		uint32_t	en;
2477		uint8_t		irq_idx;
2478	} *args;
2479	struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
2480
2481	if (portal == NULL || cmd == NULL)
2482		return (DPAA2_CMD_STAT_EINVAL);
2483
2484	dpaa2_rc_reset_cmd_params(cmd);
2485
2486	args = (struct set_irq_enable_args *) &cmd->params[0];
2487	args->en = en ? 1u : 0u;
2488	args->irq_idx = irq_idx;
2489
2490	return (dpaa2_rc_exec_cmd(portal, cmd, CMDID_MAC_SET_IRQ_ENABLE));
2491}
2492
2493static int
2494dpaa2_rc_mac_get_irq_status(device_t dev, device_t child, struct dpaa2_cmd *cmd,
2495    uint8_t irq_idx, uint32_t *status)
2496{
2497	/* TODO: Implementation is the same as ni_get_irq_status(). */
2498	struct __packed get_irq_stat_args {
2499		uint32_t	status;
2500		uint8_t		irq_idx;
2501	} *args;
2502	struct __packed get_irq_stat_resp {
2503		uint32_t	status;
2504	} *resp;
2505	struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
2506	int error;
2507
2508	if (portal == NULL || cmd == NULL || status == NULL)
2509		return (DPAA2_CMD_STAT_EINVAL);
2510
2511	dpaa2_rc_reset_cmd_params(cmd);
2512
2513	args = (struct get_irq_stat_args *) &cmd->params[0];
2514	args->status = *status;
2515	args->irq_idx = irq_idx;
2516
2517	error = dpaa2_rc_exec_cmd(portal, cmd, CMDID_MAC_GET_IRQ_STATUS);
2518	if (!error) {
2519		resp = (struct get_irq_stat_resp *) &cmd->params[0];
2520		*status = resp->status;
2521	}
2522
2523	return (error);
2524}
2525
2526static int
2527dpaa2_rc_con_open(device_t dev, device_t child, struct dpaa2_cmd *cmd,
2528    uint32_t dpcon_id, uint16_t *token)
2529{
2530	struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
2531	struct dpaa2_cmd_header *hdr;
2532	int error;
2533
2534	if (portal == NULL || cmd == NULL || token == NULL)
2535		return (DPAA2_CMD_STAT_ERR);
2536
2537	cmd->params[0] = dpcon_id;
2538	error = dpaa2_rc_exec_cmd(portal, cmd, CMDID_CON_OPEN);
2539	if (!error) {
2540		hdr = (struct dpaa2_cmd_header *) &cmd->header;
2541		*token = hdr->token;
2542	}
2543
2544	return (error);
2545}
2546
2547
2548static int
2549dpaa2_rc_con_close(device_t dev, device_t child, struct dpaa2_cmd *cmd)
2550{
2551	struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
2552
2553	if (portal == NULL || cmd == NULL)
2554		return (DPAA2_CMD_STAT_ERR);
2555
2556	return (dpaa2_rc_exec_cmd(portal, cmd, CMDID_CON_CLOSE));
2557}
2558
2559static int
2560dpaa2_rc_con_reset(device_t dev, device_t child, struct dpaa2_cmd *cmd)
2561{
2562	struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
2563
2564	if (portal == NULL || cmd == NULL)
2565		return (DPAA2_CMD_STAT_ERR);
2566
2567	return (dpaa2_rc_exec_cmd(portal, cmd, CMDID_CON_RESET));
2568}
2569
2570static int
2571dpaa2_rc_con_enable(device_t dev, device_t child, struct dpaa2_cmd *cmd)
2572{
2573	struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
2574
2575	if (portal == NULL || cmd == NULL)
2576		return (DPAA2_CMD_STAT_ERR);
2577
2578	return (dpaa2_rc_exec_cmd(portal, cmd, CMDID_CON_ENABLE));
2579}
2580
2581static int
2582dpaa2_rc_con_disable(device_t dev, device_t child, struct dpaa2_cmd *cmd)
2583{
2584	struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
2585
2586	if (portal == NULL || cmd == NULL)
2587		return (DPAA2_CMD_STAT_ERR);
2588
2589	return (dpaa2_rc_exec_cmd(portal, cmd, CMDID_CON_DISABLE));
2590}
2591
2592static int
2593dpaa2_rc_con_get_attributes(device_t dev, device_t child, struct dpaa2_cmd *cmd,
2594    struct dpaa2_con_attr *attr)
2595{
2596	struct __packed con_attr_resp {
2597		uint32_t	id;
2598		uint16_t	chan_id;
2599		uint8_t		prior_num;
2600		uint8_t		_reserved1;
2601		uint64_t	_reserved2[6];
2602	} *resp;
2603	struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
2604	int error;
2605
2606	if (portal == NULL || cmd == NULL || attr == NULL)
2607		return (DPAA2_CMD_STAT_EINVAL);
2608
2609	error = dpaa2_rc_exec_cmd(portal, cmd, CMDID_CON_GET_ATTR);
2610	if (!error) {
2611		resp = (struct con_attr_resp *) &cmd->params[0];
2612		attr->id = resp->id;
2613		attr->chan_id = resp->chan_id;
2614		attr->prior_num = resp->prior_num;
2615	}
2616
2617	return (error);
2618}
2619
2620static int
2621dpaa2_rc_con_set_notif(device_t dev, device_t child, struct dpaa2_cmd *cmd,
2622    struct dpaa2_con_notif_cfg *cfg)
2623{
2624	struct __packed set_notif_args {
2625		uint32_t	dpio_id;
2626		uint8_t		prior;
2627		uint8_t		_reserved1;
2628		uint16_t	_reserved2;
2629		uint64_t	ctx;
2630		uint64_t	_reserved3[5];
2631	} *args;
2632	struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
2633
2634	if (portal == NULL || cmd == NULL || cfg == NULL)
2635		return (DPAA2_CMD_STAT_ERR);
2636
2637	args = (struct set_notif_args *) &cmd->params[0];
2638	args->dpio_id = cfg->dpio_id;
2639	args->prior = cfg->prior;
2640	args->ctx = cfg->qman_ctx;
2641
2642	return (dpaa2_rc_exec_cmd(portal, cmd, CMDID_CON_SET_NOTIF));
2643}
2644
2645static int
2646dpaa2_rc_mcp_create(device_t dev, device_t child, struct dpaa2_cmd *cmd,
2647    uint32_t portal_id, uint32_t options, uint32_t *dpmcp_id)
2648{
2649	struct __packed mcp_create_args {
2650		uint32_t	portal_id;
2651		uint32_t	options;
2652		uint64_t	_reserved[6];
2653	} *args;
2654	struct __packed mcp_create_resp {
2655		uint32_t	dpmcp_id;
2656	} *resp;
2657	struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
2658	int error;
2659
2660	if (portal == NULL || cmd == NULL || dpmcp_id == NULL)
2661		return (DPAA2_CMD_STAT_ERR);
2662
2663	args = (struct mcp_create_args *) &cmd->params[0];
2664	args->portal_id = portal_id;
2665	args->options = options;
2666
2667	error = dpaa2_rc_exec_cmd(portal, cmd, CMDID_MCP_CREATE);
2668	if (!error) {
2669		resp = (struct mcp_create_resp *) &cmd->params[0];
2670		*dpmcp_id = resp->dpmcp_id;
2671	}
2672
2673	return (error);
2674}
2675
2676static int
2677dpaa2_rc_mcp_destroy(device_t dev, device_t child, struct dpaa2_cmd *cmd,
2678    uint32_t dpmcp_id)
2679{
2680	struct __packed mcp_destroy_args {
2681		uint32_t	dpmcp_id;
2682	} *args;
2683	struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
2684
2685	if (portal == NULL || cmd == NULL)
2686		return (DPAA2_CMD_STAT_ERR);
2687
2688	args = (struct mcp_destroy_args *) &cmd->params[0];
2689	args->dpmcp_id = dpmcp_id;
2690
2691	return (dpaa2_rc_exec_cmd(portal, cmd, CMDID_MCP_DESTROY));
2692}
2693
2694static int
2695dpaa2_rc_mcp_open(device_t dev, device_t child, struct dpaa2_cmd *cmd,
2696    uint32_t dpmcp_id, uint16_t *token)
2697{
2698	struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
2699	struct dpaa2_cmd_header *hdr;
2700	int error;
2701
2702	if (portal == NULL || cmd == NULL || token == NULL)
2703		return (DPAA2_CMD_STAT_ERR);
2704
2705	cmd->params[0] = dpmcp_id;
2706	error = dpaa2_rc_exec_cmd(portal, cmd, CMDID_MCP_OPEN);
2707	if (!error) {
2708		hdr = (struct dpaa2_cmd_header *) &cmd->header;
2709		*token = hdr->token;
2710	}
2711
2712	return (error);
2713}
2714
2715static int
2716dpaa2_rc_mcp_close(device_t dev, device_t child, struct dpaa2_cmd *cmd)
2717{
2718	struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
2719
2720	if (portal == NULL || cmd == NULL)
2721		return (DPAA2_CMD_STAT_ERR);
2722
2723	return (dpaa2_rc_exec_cmd(portal, cmd, CMDID_MCP_CLOSE));
2724}
2725
2726static int
2727dpaa2_rc_mcp_reset(device_t dev, device_t child, struct dpaa2_cmd *cmd)
2728{
2729	struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
2730
2731	if (portal == NULL || cmd == NULL)
2732		return (DPAA2_CMD_STAT_ERR);
2733
2734	return (dpaa2_rc_exec_cmd(portal, cmd, CMDID_MCP_RESET));
2735}
2736
2737/**
2738 * @brief Create and add devices for DPAA2 objects in this resource container.
2739 */
2740static int
2741dpaa2_rc_discover(struct dpaa2_rc_softc *sc)
2742{
2743	device_t rcdev = sc->dev;
2744	device_t child = sc->dev;
2745	struct dpaa2_devinfo *rcinfo = device_get_ivars(rcdev);
2746	struct dpaa2_cmd cmd;
2747	struct dpaa2_rc_attr dprc_attr;
2748	struct dpaa2_obj obj;
2749	uint32_t major, minor, rev, obj_count;
2750	uint16_t rc_token;
2751	int rc;
2752
2753	DPAA2_CMD_INIT(&cmd);
2754
2755	/* Print MC firmware version. */
2756	rc = DPAA2_CMD_MNG_GET_VERSION(rcdev, child, &cmd, &major, &minor, &rev);
2757	if (rc) {
2758		device_printf(rcdev, "%s: failed to get MC firmware version: "
2759		    "error=%d\n", __func__, rc);
2760		return (ENXIO);
2761	}
2762	device_printf(rcdev, "MC firmware version: %u.%u.%u\n", major, minor,
2763	    rev);
2764
2765	/* Obtain container ID associated with a given MC portal. */
2766	rc = DPAA2_CMD_MNG_GET_CONTAINER_ID(rcdev, child, &cmd, &sc->cont_id);
2767	if (rc) {
2768		device_printf(rcdev, "%s: failed to get container id: "
2769		    "error=%d\n", __func__, rc);
2770		return (ENXIO);
2771	}
2772	if (bootverbose) {
2773		device_printf(rcdev, "Resource container ID: %u\n", sc->cont_id);
2774	}
2775
2776	/* Open the resource container. */
2777	rc = DPAA2_CMD_RC_OPEN(rcdev, child, &cmd, sc->cont_id, &rc_token);
2778	if (rc) {
2779		device_printf(rcdev, "%s: failed to open container: cont_id=%u, "
2780		    "error=%d\n", __func__, sc->cont_id, rc);
2781		return (ENXIO);
2782	}
2783
2784	/* Obtain a number of objects in this container. */
2785	rc = DPAA2_CMD_RC_GET_OBJ_COUNT(rcdev, child, &cmd, &obj_count);
2786	if (rc) {
2787		device_printf(rcdev, "%s: failed to count objects in container: "
2788		    "cont_id=%u, error=%d\n", __func__, sc->cont_id, rc);
2789		(void)DPAA2_CMD_RC_CLOSE(rcdev, child, &cmd);
2790		return (ENXIO);
2791	}
2792	if (bootverbose) {
2793		device_printf(rcdev, "Objects in container: %u\n", obj_count);
2794	}
2795
2796	rc = DPAA2_CMD_RC_GET_ATTRIBUTES(rcdev, child, &cmd, &dprc_attr);
2797	if (rc) {
2798		device_printf(rcdev, "%s: failed to get attributes of the "
2799		    "container: cont_id=%u, error=%d\n", __func__, sc->cont_id,
2800		    rc);
2801		DPAA2_CMD_RC_CLOSE(rcdev, child, &cmd);
2802		return (ENXIO);
2803	}
2804	if (bootverbose) {
2805		device_printf(rcdev, "Isolation context ID: %u\n",
2806		    dprc_attr.icid);
2807	}
2808	if (rcinfo) {
2809		rcinfo->id = dprc_attr.cont_id;
2810		rcinfo->portal_id = dprc_attr.portal_id;
2811		rcinfo->icid = dprc_attr.icid;
2812	}
2813
2814	/*
2815	 * Add MC portals before everything else.
2816	 * TODO: Discover DPAA2 objects on-demand.
2817	 */
2818	for (uint32_t i = 0; i < obj_count; i++) {
2819		rc = DPAA2_CMD_RC_GET_OBJ(rcdev, child, &cmd, i, &obj);
2820		if (rc) {
2821			continue; /* Skip silently for now. */
2822		}
2823		if (obj.type != DPAA2_DEV_MCP) {
2824			continue;
2825		}
2826		dpaa2_rc_add_managed_child(sc, &cmd, &obj);
2827	}
2828	/* Probe and attach MC portals. */
2829	bus_generic_probe(rcdev);
2830	rc = bus_generic_attach(rcdev);
2831	if (rc) {
2832		DPAA2_CMD_RC_CLOSE(rcdev, child, &cmd);
2833		return (rc);
2834	}
2835
2836	/* Add managed devices (except DPMCPs) to the resource container. */
2837	for (uint32_t i = 0; i < obj_count; i++) {
2838		rc = DPAA2_CMD_RC_GET_OBJ(rcdev, child, &cmd, i, &obj);
2839		if (rc && bootverbose) {
2840			if (rc == DPAA2_CMD_STAT_UNKNOWN_OBJ) {
2841				device_printf(rcdev, "%s: skip unsupported "
2842				    "DPAA2 object: idx=%u\n", __func__, i);
2843				continue;
2844			} else {
2845				device_printf(rcdev, "%s: failed to get "
2846				    "information about DPAA2 object: idx=%u, "
2847				    "error=%d\n", __func__, i, rc);
2848				continue;
2849			}
2850		}
2851		if (obj.type == DPAA2_DEV_MCP) {
2852			continue; /* Already added. */
2853		}
2854		dpaa2_rc_add_managed_child(sc, &cmd, &obj);
2855	}
2856	/* Probe and attach managed devices properly. */
2857	bus_generic_probe(rcdev);
2858	rc = bus_generic_attach(rcdev);
2859	if (rc) {
2860		DPAA2_CMD_RC_CLOSE(rcdev, child, &cmd);
2861		return (rc);
2862	}
2863
2864	/* Add other devices to the resource container. */
2865	for (uint32_t i = 0; i < obj_count; i++) {
2866		rc = DPAA2_CMD_RC_GET_OBJ(rcdev, child, &cmd, i, &obj);
2867		if (rc == DPAA2_CMD_STAT_UNKNOWN_OBJ && bootverbose) {
2868			device_printf(rcdev, "%s: skip unsupported DPAA2 "
2869			    "object: idx=%u\n", __func__, i);
2870			continue;
2871		} else if (rc) {
2872			device_printf(rcdev, "%s: failed to get object: "
2873			    "idx=%u, error=%d\n", __func__, i, rc);
2874			continue;
2875		}
2876		dpaa2_rc_add_child(sc, &cmd, &obj);
2877	}
2878
2879	DPAA2_CMD_RC_CLOSE(rcdev, child, &cmd);
2880
2881	/* Probe and attach the rest of devices. */
2882	bus_generic_probe(rcdev);
2883	return (bus_generic_attach(rcdev));
2884}
2885
2886/**
2887 * @brief Add a new DPAA2 device to the resource container bus.
2888 */
2889static int
2890dpaa2_rc_add_child(struct dpaa2_rc_softc *sc, struct dpaa2_cmd *cmd,
2891    struct dpaa2_obj *obj)
2892{
2893	device_t rcdev, dev;
2894	struct dpaa2_devinfo *rcinfo;
2895	struct dpaa2_devinfo *dinfo;
2896	struct resource_spec *res_spec;
2897	const char *devclass;
2898	int dpio_n = 0; /* to limit DPIOs by # of CPUs */
2899	int dpcon_n = 0; /* to limit DPCONs by # of CPUs */
2900	int rid, error;
2901
2902	rcdev = sc->dev;
2903	rcinfo = device_get_ivars(rcdev);
2904
2905	switch (obj->type) {
2906	case DPAA2_DEV_NI:
2907		devclass = "dpaa2_ni";
2908		res_spec = dpaa2_ni_spec;
2909		break;
2910	default:
2911		return (ENXIO);
2912	}
2913
2914	/* Add a device for the DPAA2 object. */
2915	dev = device_add_child(rcdev, devclass, -1);
2916	if (dev == NULL) {
2917		device_printf(rcdev, "%s: failed to add a device for DPAA2 "
2918		    "object: type=%s, id=%u\n", __func__, dpaa2_ttos(obj->type),
2919		    obj->id);
2920		return (ENXIO);
2921	}
2922
2923	/* Allocate devinfo for a child. */
2924	dinfo = malloc(sizeof(struct dpaa2_devinfo), M_DPAA2_RC,
2925	    M_WAITOK | M_ZERO);
2926	if (!dinfo) {
2927		device_printf(rcdev, "%s: failed to allocate dpaa2_devinfo "
2928		    "for: type=%s, id=%u\n", __func__, dpaa2_ttos(obj->type),
2929		    obj->id);
2930		return (ENXIO);
2931	}
2932	device_set_ivars(dev, dinfo);
2933
2934	dinfo->pdev = rcdev;
2935	dinfo->dev = dev;
2936	dinfo->id = obj->id;
2937	dinfo->dtype = obj->type;
2938	dinfo->portal = NULL;
2939	/* Children share their parent container's ICID and portal ID. */
2940	dinfo->icid = rcinfo->icid;
2941	dinfo->portal_id = rcinfo->portal_id;
2942	/* MSI configuration */
2943	dinfo->msi.msi_msgnum = obj->irq_count;
2944	dinfo->msi.msi_alloc = 0;
2945	dinfo->msi.msi_handlers = 0;
2946
2947	/* Initialize a resource list for the child. */
2948	resource_list_init(&dinfo->resources);
2949
2950	/* Add DPAA2-specific resources to the resource list. */
2951	for (; res_spec && res_spec->type != -1; res_spec++) {
2952		if (res_spec->type < DPAA2_DEV_MC)
2953			continue; /* Skip non-DPAA2 resource. */
2954		rid = res_spec->rid;
2955
2956		/* Limit DPIOs and DPCONs by number of CPUs. */
2957		if (res_spec->type == DPAA2_DEV_IO && dpio_n >= mp_ncpus) {
2958			dpio_n++;
2959			continue;
2960		}
2961		if (res_spec->type == DPAA2_DEV_CON && dpcon_n >= mp_ncpus) {
2962			dpcon_n++;
2963			continue;
2964		}
2965
2966		error = dpaa2_rc_add_res(rcdev, dev, res_spec->type, &rid,
2967		    res_spec->flags);
2968		if (error)
2969			device_printf(rcdev, "%s: dpaa2_rc_add_res() failed: "
2970			    "error=%d\n", __func__, error);
2971
2972		if (res_spec->type == DPAA2_DEV_IO)
2973			dpio_n++;
2974		if (res_spec->type == DPAA2_DEV_CON)
2975			dpcon_n++;
2976	}
2977
2978	return (0);
2979}
2980
2981/**
2982 * @brief Add a new managed DPAA2 device to the resource container bus.
2983 *
2984 * There are DPAA2 objects (DPIO, DPBP) which have their own drivers and can be
2985 * allocated as resources or associated with the other DPAA2 objects. This
2986 * function is supposed to discover such managed objects in the resource
2987 * container and add them as children to perform a proper initialization.
2988 *
2989 * NOTE: It must be called together with bus_generic_probe() and
2990 *       bus_generic_attach() before dpaa2_rc_add_child().
2991 */
2992static int
2993dpaa2_rc_add_managed_child(struct dpaa2_rc_softc *sc, struct dpaa2_cmd *cmd,
2994    struct dpaa2_obj *obj)
2995{
2996	device_t rcdev, dev, child;
2997	struct dpaa2_devinfo *rcinfo, *dinfo;
2998	struct dpaa2_rc_obj_region reg;
2999	struct resource_spec *res_spec;
3000	const char *devclass;
3001	uint64_t start, end, count;
3002	uint32_t flags = 0;
3003	int rid, error;
3004
3005	rcdev = sc->dev;
3006	child = sc->dev;
3007	rcinfo = device_get_ivars(rcdev);
3008
3009	switch (obj->type) {
3010	case DPAA2_DEV_IO:
3011		devclass = "dpaa2_io";
3012		res_spec = dpaa2_io_spec;
3013		flags = DPAA2_MC_DEV_ALLOCATABLE | DPAA2_MC_DEV_SHAREABLE;
3014		break;
3015	case DPAA2_DEV_BP:
3016		devclass = "dpaa2_bp";
3017		res_spec = dpaa2_bp_spec;
3018		flags = DPAA2_MC_DEV_ALLOCATABLE;
3019		break;
3020	case DPAA2_DEV_CON:
3021		devclass = "dpaa2_con";
3022		res_spec = dpaa2_con_spec;
3023		flags = DPAA2_MC_DEV_ALLOCATABLE;
3024		break;
3025	case DPAA2_DEV_MAC:
3026		devclass = "dpaa2_mac";
3027		res_spec = dpaa2_mac_spec;
3028		flags = DPAA2_MC_DEV_ASSOCIATED;
3029		break;
3030	case DPAA2_DEV_MCP:
3031		devclass = "dpaa2_mcp";
3032		res_spec = NULL;
3033		flags = DPAA2_MC_DEV_ALLOCATABLE | DPAA2_MC_DEV_SHAREABLE;
3034		break;
3035	default:
3036		/* Only managed devices above are supported. */
3037		return (EINVAL);
3038	}
3039
3040	/* Add a device for the DPAA2 object. */
3041	dev = device_add_child(rcdev, devclass, -1);
3042	if (dev == NULL) {
3043		device_printf(rcdev, "%s: failed to add a device for DPAA2 "
3044		    "object: type=%s, id=%u\n", __func__, dpaa2_ttos(obj->type),
3045		    obj->id);
3046		return (ENXIO);
3047	}
3048
3049	/* Allocate devinfo for the child. */
3050	dinfo = malloc(sizeof(struct dpaa2_devinfo), M_DPAA2_RC,
3051	    M_WAITOK | M_ZERO);
3052	if (!dinfo) {
3053		device_printf(rcdev, "%s: failed to allocate dpaa2_devinfo "
3054		    "for: type=%s, id=%u\n", __func__, dpaa2_ttos(obj->type),
3055		    obj->id);
3056		return (ENXIO);
3057	}
3058	device_set_ivars(dev, dinfo);
3059
3060	dinfo->pdev = rcdev;
3061	dinfo->dev = dev;
3062	dinfo->id = obj->id;
3063	dinfo->dtype = obj->type;
3064	dinfo->portal = NULL;
3065	/* Children share their parent container's ICID and portal ID. */
3066	dinfo->icid = rcinfo->icid;
3067	dinfo->portal_id = rcinfo->portal_id;
3068	/* MSI configuration */
3069	dinfo->msi.msi_msgnum = obj->irq_count;
3070	dinfo->msi.msi_alloc = 0;
3071	dinfo->msi.msi_handlers = 0;
3072
3073	/* Initialize a resource list for the child. */
3074	resource_list_init(&dinfo->resources);
3075
3076	/* Add memory regions to the resource list. */
3077	for (uint8_t i = 0; i < obj->reg_count; i++) {
3078		error = DPAA2_CMD_RC_GET_OBJ_REGION(rcdev, child, cmd, obj->id,
3079		    i, obj->type, &reg);
3080		if (error) {
3081			device_printf(rcdev, "%s: failed to obtain memory "
3082			    "region for type=%s, id=%u, reg_idx=%u: error=%d\n",
3083			    __func__, dpaa2_ttos(obj->type), obj->id, i, error);
3084			continue;
3085		}
3086		count = reg.size;
3087		start = reg.base_paddr + reg.base_offset;
3088		end = reg.base_paddr + reg.base_offset + reg.size - 1;
3089
3090		resource_list_add(&dinfo->resources, SYS_RES_MEMORY, i, start,
3091		    end, count);
3092	}
3093
3094	/* Add DPAA2-specific resources to the resource list. */
3095	for (; res_spec && res_spec->type != -1; res_spec++) {
3096		if (res_spec->type < DPAA2_DEV_MC)
3097			continue; /* Skip non-DPAA2 resource. */
3098		rid = res_spec->rid;
3099
3100		error = dpaa2_rc_add_res(rcdev, dev, res_spec->type, &rid,
3101		    res_spec->flags);
3102		if (error)
3103			device_printf(rcdev, "%s: dpaa2_rc_add_res() failed: "
3104			    "error=%d\n", __func__, error);
3105	}
3106
3107	/* Inform MC about a new managed device. */
3108	error = DPAA2_MC_MANAGE_DEV(rcdev, dev, flags);
3109	if (error) {
3110		device_printf(rcdev, "%s: failed to add a managed DPAA2 device: "
3111		    "type=%s, id=%u, error=%d\n", __func__,
3112		    dpaa2_ttos(obj->type), obj->id, error);
3113		return (ENXIO);
3114	}
3115
3116	return (0);
3117}
3118
3119/**
3120 * @brief Configure given IRQ using MC command interface.
3121 */
3122static int
3123dpaa2_rc_configure_irq(device_t rcdev, device_t child, int rid, uint64_t addr,
3124    uint32_t data)
3125{
3126	struct dpaa2_devinfo *rcinfo;
3127	struct dpaa2_devinfo *dinfo;
3128	struct dpaa2_cmd cmd;
3129	uint16_t rc_token;
3130	int rc = EINVAL;
3131
3132	DPAA2_CMD_INIT(&cmd);
3133
3134	if (device_get_parent(child) == rcdev && rid >= 1) {
3135		rcinfo = device_get_ivars(rcdev);
3136		dinfo = device_get_ivars(child);
3137
3138		rc = DPAA2_CMD_RC_OPEN(rcdev, child, &cmd, rcinfo->id,
3139		    &rc_token);
3140		if (rc) {
3141			device_printf(rcdev, "%s: failed to open DPRC: "
3142			    "error=%d\n", __func__, rc);
3143			return (ENODEV);
3144		}
3145		/* Set MSI address and value. */
3146		rc = DPAA2_CMD_RC_SET_OBJ_IRQ(rcdev, child, &cmd, rid - 1, addr,
3147		    data, rid, dinfo->id, dinfo->dtype);
3148		if (rc) {
3149			device_printf(rcdev, "%s: failed to setup IRQ: "
3150			    "rid=%d, addr=%jx, data=%x, error=%d\n", __func__,
3151			    rid, addr, data, rc);
3152			return (ENODEV);
3153		}
3154		rc = DPAA2_CMD_RC_CLOSE(rcdev, child, &cmd);
3155		if (rc) {
3156			device_printf(rcdev, "%s: failed to close DPRC: "
3157			    "error=%d\n", __func__, rc);
3158			return (ENODEV);
3159		}
3160		rc = 0;
3161	}
3162
3163	return (rc);
3164}
3165
3166/**
3167 * @brief General implementation of the MC command to enable IRQ.
3168 */
3169static int
3170dpaa2_rc_enable_irq(struct dpaa2_mcp *mcp, struct dpaa2_cmd *cmd,
3171    uint8_t irq_idx, bool enable, uint16_t cmdid)
3172{
3173	struct __packed enable_irq_args {
3174		uint8_t		enable;
3175		uint8_t		_reserved1;
3176		uint16_t	_reserved2;
3177		uint8_t		irq_idx;
3178		uint8_t		_reserved3;
3179		uint16_t	_reserved4;
3180		uint64_t	_reserved5[6];
3181	} *args;
3182
3183	if (!mcp || !cmd)
3184		return (DPAA2_CMD_STAT_ERR);
3185
3186	args = (struct enable_irq_args *) &cmd->params[0];
3187	args->irq_idx = irq_idx;
3188	args->enable = enable == 0u ? 0u : 1u;
3189
3190	return (dpaa2_rc_exec_cmd(mcp, cmd, cmdid));
3191}
3192
3193/**
3194 * @brief Sends a command to MC and waits for response.
3195 */
3196static int
3197dpaa2_rc_exec_cmd(struct dpaa2_mcp *mcp, struct dpaa2_cmd *cmd, uint16_t cmdid)
3198{
3199	struct dpaa2_cmd_header *hdr;
3200	uint16_t flags;
3201	int error;
3202
3203	if (!mcp || !cmd)
3204		return (DPAA2_CMD_STAT_ERR);
3205
3206	/* Prepare a command for the MC hardware. */
3207	hdr = (struct dpaa2_cmd_header *) &cmd->header;
3208	hdr->cmdid = cmdid;
3209	hdr->status = DPAA2_CMD_STAT_READY;
3210
3211	DPAA2_MCP_LOCK(mcp, &flags);
3212	if (flags & DPAA2_PORTAL_DESTROYED) {
3213		/* Terminate operation if portal is destroyed. */
3214		DPAA2_MCP_UNLOCK(mcp);
3215		return (DPAA2_CMD_STAT_INVALID_STATE);
3216	}
3217
3218	/* Send a command to MC and wait for the result. */
3219	dpaa2_rc_send_cmd(mcp, cmd);
3220	error = dpaa2_rc_wait_for_cmd(mcp, cmd);
3221	if (error) {
3222		DPAA2_MCP_UNLOCK(mcp);
3223		return (DPAA2_CMD_STAT_ERR);
3224	}
3225	if (hdr->status != DPAA2_CMD_STAT_OK) {
3226		DPAA2_MCP_UNLOCK(mcp);
3227		return (int)(hdr->status);
3228	}
3229
3230	DPAA2_MCP_UNLOCK(mcp);
3231
3232	return (DPAA2_CMD_STAT_OK);
3233}
3234
3235/**
3236 * @brief Writes a command to the MC command portal.
3237 */
3238static int
3239dpaa2_rc_send_cmd(struct dpaa2_mcp *mcp, struct dpaa2_cmd *cmd)
3240{
3241	/* Write command parameters. */
3242	for (uint32_t i = 1; i <= DPAA2_CMD_PARAMS_N; i++)
3243		bus_write_8(mcp->map, sizeof(uint64_t) * i, cmd->params[i-1]);
3244
3245	bus_barrier(mcp->map, 0, sizeof(struct dpaa2_cmd),
3246	    BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
3247
3248	/* Write command header to trigger execution. */
3249	bus_write_8(mcp->map, 0, cmd->header);
3250
3251	return (0);
3252}
3253
3254/**
3255 * @brief Polls the MC command portal in order to receive a result of the
3256 *        command execution.
3257 */
3258static int
3259dpaa2_rc_wait_for_cmd(struct dpaa2_mcp *mcp, struct dpaa2_cmd *cmd)
3260{
3261	struct dpaa2_cmd_header *hdr;
3262	uint64_t val;
3263	uint32_t i;
3264
3265	/* Wait for a command execution result from the MC hardware. */
3266	for (i = 1; i <= CMD_SPIN_ATTEMPTS; i++) {
3267		val = bus_read_8(mcp->map, 0);
3268		hdr = (struct dpaa2_cmd_header *) &val;
3269		if (hdr->status != DPAA2_CMD_STAT_READY) {
3270			break;
3271		}
3272		DELAY(CMD_SPIN_TIMEOUT);
3273	}
3274
3275	if (i > CMD_SPIN_ATTEMPTS) {
3276		/* Return an error on expired timeout. */
3277		return (DPAA2_CMD_STAT_TIMEOUT);
3278	} else {
3279		/* Read command response. */
3280		cmd->header = val;
3281		for (i = 1; i <= DPAA2_CMD_PARAMS_N; i++) {
3282			cmd->params[i-1] =
3283			    bus_read_8(mcp->map, i * sizeof(uint64_t));
3284		}
3285	}
3286
3287	return (DPAA2_CMD_STAT_OK);
3288}
3289
3290/**
3291 * @brief Reserve a DPAA2-specific device of the given devtype for the child.
3292 */
3293static int
3294dpaa2_rc_add_res(device_t rcdev, device_t child, enum dpaa2_dev_type devtype,
3295    int *rid, int flags)
3296{
3297	device_t dpaa2_dev;
3298	struct dpaa2_devinfo *dinfo = device_get_ivars(child);
3299	struct resource *res;
3300	bool shared = false;
3301	int error;
3302
3303	/* Request a free DPAA2 device of the given type from MC. */
3304	error = DPAA2_MC_GET_FREE_DEV(rcdev, &dpaa2_dev, devtype);
3305	if (error && !(flags & RF_SHAREABLE)) {
3306		device_printf(rcdev, "%s: failed to obtain a free %s (rid=%d) "
3307		    "for: %s (id=%u)\n", __func__, dpaa2_ttos(devtype), *rid,
3308		    dpaa2_ttos(dinfo->dtype), dinfo->id);
3309		return (error);
3310	}
3311
3312	/* Request a shared DPAA2 device of the given type from MC. */
3313	if (error) {
3314		error = DPAA2_MC_GET_SHARED_DEV(rcdev, &dpaa2_dev, devtype);
3315		if (error) {
3316			device_printf(rcdev, "%s: failed to obtain a shared "
3317			    "%s (rid=%d) for: %s (id=%u)\n", __func__,
3318			    dpaa2_ttos(devtype), *rid, dpaa2_ttos(dinfo->dtype),
3319			    dinfo->id);
3320			return (error);
3321		}
3322		shared = true;
3323	}
3324
3325	/* Add DPAA2 device to the resource list of the child device. */
3326	resource_list_add(&dinfo->resources, devtype, *rid,
3327	    (rman_res_t) dpaa2_dev, (rman_res_t) dpaa2_dev, 1);
3328
3329	/* Reserve a newly added DPAA2 resource. */
3330	res = resource_list_reserve(&dinfo->resources, rcdev, child, devtype,
3331	    rid, (rman_res_t) dpaa2_dev, (rman_res_t) dpaa2_dev, 1,
3332	    flags & ~RF_ACTIVE);
3333	if (!res) {
3334		device_printf(rcdev, "%s: failed to reserve %s (rid=%d) for: %s "
3335		    "(id=%u)\n", __func__, dpaa2_ttos(devtype), *rid,
3336		    dpaa2_ttos(dinfo->dtype), dinfo->id);
3337		return (EBUSY);
3338	}
3339
3340	/* Reserve a shared DPAA2 device of the given type. */
3341	if (shared) {
3342		error = DPAA2_MC_RESERVE_DEV(rcdev, dpaa2_dev, devtype);
3343		if (error) {
3344			device_printf(rcdev, "%s: failed to reserve a shared "
3345			    "%s (rid=%d) for: %s (id=%u)\n", __func__,
3346			    dpaa2_ttos(devtype), *rid, dpaa2_ttos(dinfo->dtype),
3347			    dinfo->id);
3348			return (error);
3349		}
3350	}
3351
3352	return (0);
3353}
3354
3355static int
3356dpaa2_rc_print_type(struct resource_list *rl, enum dpaa2_dev_type type)
3357{
3358	struct dpaa2_devinfo *dinfo;
3359	struct resource_list_entry *rle;
3360	uint32_t prev_id;
3361	int printed = 0, series = 0;
3362	int retval = 0;
3363
3364	STAILQ_FOREACH(rle, rl, link) {
3365		if (rle->type == type) {
3366			dinfo = device_get_ivars((device_t) rle->start);
3367
3368			if (printed == 0) {
3369				retval += printf(" %s (id=",
3370				    dpaa2_ttos(dinfo->dtype));
3371			} else {
3372				if (dinfo->id == prev_id + 1) {
3373					if (series == 0) {
3374						series = 1;
3375						retval += printf("-");
3376					}
3377				} else {
3378					if (series == 1) {
3379						retval += printf("%u", prev_id);
3380						series = 0;
3381					}
3382					retval += printf(",");
3383				}
3384			}
3385			printed++;
3386
3387			if (series == 0)
3388				retval += printf("%u", dinfo->id);
3389			prev_id = dinfo->id;
3390		}
3391	}
3392	if (printed) {
3393		if (series == 1)
3394			retval += printf("%u", prev_id);
3395		retval += printf(")");
3396	}
3397
3398	return (retval);
3399}
3400
3401static int
3402dpaa2_rc_reset_cmd_params(struct dpaa2_cmd *cmd)
3403{
3404	if (cmd != NULL) {
3405		memset(cmd->params, 0, sizeof(cmd->params[0]) *
3406		    DPAA2_CMD_PARAMS_N);
3407	}
3408	return (0);
3409}
3410
3411static struct dpaa2_mcp *
3412dpaa2_rc_select_portal(device_t dev, device_t child)
3413{
3414	struct dpaa2_devinfo *dinfo = device_get_ivars(dev);
3415	struct dpaa2_devinfo *cinfo = device_get_ivars(child);
3416
3417	if (cinfo == NULL || dinfo == NULL || dinfo->dtype != DPAA2_DEV_RC)
3418		return (NULL);
3419	return (cinfo->portal != NULL ? cinfo->portal : dinfo->portal);
3420}
3421
3422static device_method_t dpaa2_rc_methods[] = {
3423	/* Device interface */
3424	DEVMETHOD(device_probe,			dpaa2_rc_probe),
3425	DEVMETHOD(device_attach,		dpaa2_rc_attach),
3426	DEVMETHOD(device_detach,		dpaa2_rc_detach),
3427
3428	/* Bus interface */
3429	DEVMETHOD(bus_get_resource_list,	dpaa2_rc_get_resource_list),
3430	DEVMETHOD(bus_delete_resource,		dpaa2_rc_delete_resource),
3431	DEVMETHOD(bus_alloc_resource,		dpaa2_rc_alloc_resource),
3432	DEVMETHOD(bus_release_resource,		dpaa2_rc_release_resource),
3433	DEVMETHOD(bus_child_deleted,		dpaa2_rc_child_deleted),
3434	DEVMETHOD(bus_child_detached,		dpaa2_rc_child_detached),
3435	DEVMETHOD(bus_setup_intr,		dpaa2_rc_setup_intr),
3436	DEVMETHOD(bus_teardown_intr,		dpaa2_rc_teardown_intr),
3437	DEVMETHOD(bus_print_child,		dpaa2_rc_print_child),
3438	DEVMETHOD(bus_add_child,		device_add_child_ordered),
3439	DEVMETHOD(bus_set_resource,		bus_generic_rl_set_resource),
3440	DEVMETHOD(bus_get_resource,		bus_generic_rl_get_resource),
3441	DEVMETHOD(bus_activate_resource, 	bus_generic_activate_resource),
3442	DEVMETHOD(bus_deactivate_resource, 	bus_generic_deactivate_resource),
3443	DEVMETHOD(bus_adjust_resource,		bus_generic_adjust_resource),
3444
3445	/* Pseudo-PCI interface */
3446	DEVMETHOD(pci_alloc_msi,		dpaa2_rc_alloc_msi),
3447	DEVMETHOD(pci_release_msi,		dpaa2_rc_release_msi),
3448	DEVMETHOD(pci_msi_count,		dpaa2_rc_msi_count),
3449	DEVMETHOD(pci_get_id,			dpaa2_rc_get_id),
3450
3451	/* DPAA2 MC command interface */
3452	DEVMETHOD(dpaa2_cmd_mng_get_version,	dpaa2_rc_mng_get_version),
3453	DEVMETHOD(dpaa2_cmd_mng_get_soc_version, dpaa2_rc_mng_get_soc_version),
3454	DEVMETHOD(dpaa2_cmd_mng_get_container_id, dpaa2_rc_mng_get_container_id),
3455	/*	DPRC commands */
3456	DEVMETHOD(dpaa2_cmd_rc_open,		dpaa2_rc_open),
3457	DEVMETHOD(dpaa2_cmd_rc_close,		dpaa2_rc_close),
3458	DEVMETHOD(dpaa2_cmd_rc_get_obj_count,	dpaa2_rc_get_obj_count),
3459	DEVMETHOD(dpaa2_cmd_rc_get_obj,		dpaa2_rc_get_obj),
3460	DEVMETHOD(dpaa2_cmd_rc_get_obj_descriptor, dpaa2_rc_get_obj_descriptor),
3461	DEVMETHOD(dpaa2_cmd_rc_get_attributes,	dpaa2_rc_get_attributes),
3462	DEVMETHOD(dpaa2_cmd_rc_get_obj_region,	dpaa2_rc_get_obj_region),
3463	DEVMETHOD(dpaa2_cmd_rc_get_api_version, dpaa2_rc_get_api_version),
3464	DEVMETHOD(dpaa2_cmd_rc_set_irq_enable,	dpaa2_rc_set_irq_enable),
3465	DEVMETHOD(dpaa2_cmd_rc_set_obj_irq,	dpaa2_rc_set_obj_irq),
3466	DEVMETHOD(dpaa2_cmd_rc_get_conn,	dpaa2_rc_get_conn),
3467	/*	DPNI commands */
3468	DEVMETHOD(dpaa2_cmd_ni_open,		dpaa2_rc_ni_open),
3469	DEVMETHOD(dpaa2_cmd_ni_close,		dpaa2_rc_ni_close),
3470	DEVMETHOD(dpaa2_cmd_ni_enable,		dpaa2_rc_ni_enable),
3471	DEVMETHOD(dpaa2_cmd_ni_disable,		dpaa2_rc_ni_disable),
3472	DEVMETHOD(dpaa2_cmd_ni_get_api_version,	dpaa2_rc_ni_get_api_version),
3473	DEVMETHOD(dpaa2_cmd_ni_reset,		dpaa2_rc_ni_reset),
3474	DEVMETHOD(dpaa2_cmd_ni_get_attributes,	dpaa2_rc_ni_get_attributes),
3475	DEVMETHOD(dpaa2_cmd_ni_set_buf_layout,	dpaa2_rc_ni_set_buf_layout),
3476	DEVMETHOD(dpaa2_cmd_ni_get_tx_data_off, dpaa2_rc_ni_get_tx_data_offset),
3477	DEVMETHOD(dpaa2_cmd_ni_get_port_mac_addr, dpaa2_rc_ni_get_port_mac_addr),
3478	DEVMETHOD(dpaa2_cmd_ni_set_prim_mac_addr, dpaa2_rc_ni_set_prim_mac_addr),
3479	DEVMETHOD(dpaa2_cmd_ni_get_prim_mac_addr, dpaa2_rc_ni_get_prim_mac_addr),
3480	DEVMETHOD(dpaa2_cmd_ni_set_link_cfg,	dpaa2_rc_ni_set_link_cfg),
3481	DEVMETHOD(dpaa2_cmd_ni_get_link_cfg,	dpaa2_rc_ni_get_link_cfg),
3482	DEVMETHOD(dpaa2_cmd_ni_get_link_state,	dpaa2_rc_ni_get_link_state),
3483	DEVMETHOD(dpaa2_cmd_ni_set_qos_table,	dpaa2_rc_ni_set_qos_table),
3484	DEVMETHOD(dpaa2_cmd_ni_clear_qos_table, dpaa2_rc_ni_clear_qos_table),
3485	DEVMETHOD(dpaa2_cmd_ni_set_pools,	dpaa2_rc_ni_set_pools),
3486	DEVMETHOD(dpaa2_cmd_ni_set_err_behavior,dpaa2_rc_ni_set_err_behavior),
3487	DEVMETHOD(dpaa2_cmd_ni_get_queue,	dpaa2_rc_ni_get_queue),
3488	DEVMETHOD(dpaa2_cmd_ni_set_queue,	dpaa2_rc_ni_set_queue),
3489	DEVMETHOD(dpaa2_cmd_ni_get_qdid,	dpaa2_rc_ni_get_qdid),
3490	DEVMETHOD(dpaa2_cmd_ni_add_mac_addr,	dpaa2_rc_ni_add_mac_addr),
3491	DEVMETHOD(dpaa2_cmd_ni_remove_mac_addr,	dpaa2_rc_ni_remove_mac_addr),
3492	DEVMETHOD(dpaa2_cmd_ni_clear_mac_filters, dpaa2_rc_ni_clear_mac_filters),
3493	DEVMETHOD(dpaa2_cmd_ni_set_mfl,		dpaa2_rc_ni_set_mfl),
3494	DEVMETHOD(dpaa2_cmd_ni_set_offload,	dpaa2_rc_ni_set_offload),
3495	DEVMETHOD(dpaa2_cmd_ni_set_irq_mask,	dpaa2_rc_ni_set_irq_mask),
3496	DEVMETHOD(dpaa2_cmd_ni_set_irq_enable,	dpaa2_rc_ni_set_irq_enable),
3497	DEVMETHOD(dpaa2_cmd_ni_get_irq_status,	dpaa2_rc_ni_get_irq_status),
3498	DEVMETHOD(dpaa2_cmd_ni_set_uni_promisc,	dpaa2_rc_ni_set_uni_promisc),
3499	DEVMETHOD(dpaa2_cmd_ni_set_multi_promisc, dpaa2_rc_ni_set_multi_promisc),
3500	DEVMETHOD(dpaa2_cmd_ni_get_statistics,	dpaa2_rc_ni_get_statistics),
3501	DEVMETHOD(dpaa2_cmd_ni_set_rx_tc_dist,	dpaa2_rc_ni_set_rx_tc_dist),
3502	/*	DPIO commands */
3503	DEVMETHOD(dpaa2_cmd_io_open,		dpaa2_rc_io_open),
3504	DEVMETHOD(dpaa2_cmd_io_close,		dpaa2_rc_io_close),
3505	DEVMETHOD(dpaa2_cmd_io_enable,		dpaa2_rc_io_enable),
3506	DEVMETHOD(dpaa2_cmd_io_disable,		dpaa2_rc_io_disable),
3507	DEVMETHOD(dpaa2_cmd_io_reset,		dpaa2_rc_io_reset),
3508	DEVMETHOD(dpaa2_cmd_io_get_attributes,	dpaa2_rc_io_get_attributes),
3509	DEVMETHOD(dpaa2_cmd_io_set_irq_mask,	dpaa2_rc_io_set_irq_mask),
3510	DEVMETHOD(dpaa2_cmd_io_get_irq_status,	dpaa2_rc_io_get_irq_status),
3511	DEVMETHOD(dpaa2_cmd_io_set_irq_enable,	dpaa2_rc_io_set_irq_enable),
3512	DEVMETHOD(dpaa2_cmd_io_add_static_dq_chan, dpaa2_rc_io_add_static_dq_chan),
3513	/*	DPBP commands */
3514	DEVMETHOD(dpaa2_cmd_bp_open,		dpaa2_rc_bp_open),
3515	DEVMETHOD(dpaa2_cmd_bp_close,		dpaa2_rc_bp_close),
3516	DEVMETHOD(dpaa2_cmd_bp_enable,		dpaa2_rc_bp_enable),
3517	DEVMETHOD(dpaa2_cmd_bp_disable,		dpaa2_rc_bp_disable),
3518	DEVMETHOD(dpaa2_cmd_bp_reset,		dpaa2_rc_bp_reset),
3519	DEVMETHOD(dpaa2_cmd_bp_get_attributes,	dpaa2_rc_bp_get_attributes),
3520	/*	DPMAC commands */
3521	DEVMETHOD(dpaa2_cmd_mac_open,		dpaa2_rc_mac_open),
3522	DEVMETHOD(dpaa2_cmd_mac_close,		dpaa2_rc_mac_close),
3523	DEVMETHOD(dpaa2_cmd_mac_reset,		dpaa2_rc_mac_reset),
3524	DEVMETHOD(dpaa2_cmd_mac_mdio_read,	dpaa2_rc_mac_mdio_read),
3525	DEVMETHOD(dpaa2_cmd_mac_mdio_write,	dpaa2_rc_mac_mdio_write),
3526	DEVMETHOD(dpaa2_cmd_mac_get_addr,	dpaa2_rc_mac_get_addr),
3527	DEVMETHOD(dpaa2_cmd_mac_get_attributes, dpaa2_rc_mac_get_attributes),
3528	DEVMETHOD(dpaa2_cmd_mac_set_link_state,	dpaa2_rc_mac_set_link_state),
3529	DEVMETHOD(dpaa2_cmd_mac_set_irq_mask,	dpaa2_rc_mac_set_irq_mask),
3530	DEVMETHOD(dpaa2_cmd_mac_set_irq_enable,	dpaa2_rc_mac_set_irq_enable),
3531	DEVMETHOD(dpaa2_cmd_mac_get_irq_status,	dpaa2_rc_mac_get_irq_status),
3532	/*	DPCON commands */
3533	DEVMETHOD(dpaa2_cmd_con_open,		dpaa2_rc_con_open),
3534	DEVMETHOD(dpaa2_cmd_con_close,		dpaa2_rc_con_close),
3535	DEVMETHOD(dpaa2_cmd_con_reset,		dpaa2_rc_con_reset),
3536	DEVMETHOD(dpaa2_cmd_con_enable,		dpaa2_rc_con_enable),
3537	DEVMETHOD(dpaa2_cmd_con_disable,	dpaa2_rc_con_disable),
3538	DEVMETHOD(dpaa2_cmd_con_get_attributes,	dpaa2_rc_con_get_attributes),
3539	DEVMETHOD(dpaa2_cmd_con_set_notif,	dpaa2_rc_con_set_notif),
3540	/*	DPMCP commands */
3541	DEVMETHOD(dpaa2_cmd_mcp_create,		dpaa2_rc_mcp_create),
3542	DEVMETHOD(dpaa2_cmd_mcp_destroy,	dpaa2_rc_mcp_destroy),
3543	DEVMETHOD(dpaa2_cmd_mcp_open,		dpaa2_rc_mcp_open),
3544	DEVMETHOD(dpaa2_cmd_mcp_close,		dpaa2_rc_mcp_close),
3545	DEVMETHOD(dpaa2_cmd_mcp_reset,		dpaa2_rc_mcp_reset),
3546
3547	DEVMETHOD_END
3548};
3549
3550static driver_t dpaa2_rc_driver = {
3551	"dpaa2_rc",
3552	dpaa2_rc_methods,
3553	sizeof(struct dpaa2_rc_softc),
3554};
3555
3556/* For root container */
3557DRIVER_MODULE(dpaa2_rc, dpaa2_mc, dpaa2_rc_driver, 0, 0);
3558/* For child containers */
3559DRIVER_MODULE(dpaa2_rc, dpaa2_rc, dpaa2_rc_driver, 0, 0);
3560