1*eb7eaf8dSmpi /* $OpenBSD: vldc.c,v 1.2 2021/10/24 17:05:04 mpi Exp $ */
23d3c69d8Skettenis /*
33d3c69d8Skettenis * Copyright (c) 2009, 2012 Mark Kettenis
43d3c69d8Skettenis *
53d3c69d8Skettenis * Permission to use, copy, modify, and distribute this software for any
63d3c69d8Skettenis * purpose with or without fee is hereby granted, provided that the above
73d3c69d8Skettenis * copyright notice and this permission notice appear in all copies.
83d3c69d8Skettenis *
93d3c69d8Skettenis * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
103d3c69d8Skettenis * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
113d3c69d8Skettenis * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
123d3c69d8Skettenis * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
133d3c69d8Skettenis * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
143d3c69d8Skettenis * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
153d3c69d8Skettenis * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
163d3c69d8Skettenis */
173d3c69d8Skettenis
183d3c69d8Skettenis #include <sys/param.h>
193d3c69d8Skettenis #include <sys/buf.h>
203d3c69d8Skettenis #include <sys/device.h>
213d3c69d8Skettenis #include <sys/malloc.h>
223d3c69d8Skettenis #include <sys/systm.h>
233d3c69d8Skettenis
243d3c69d8Skettenis #include <machine/autoconf.h>
253d3c69d8Skettenis #include <machine/hypervisor.h>
263d3c69d8Skettenis #include <machine/mdesc.h>
273d3c69d8Skettenis
283d3c69d8Skettenis #include <sparc64/dev/cbusvar.h>
293d3c69d8Skettenis
303d3c69d8Skettenis #ifdef VLDC_DEBUG
313d3c69d8Skettenis #define DPRINTF(x) printf x
323d3c69d8Skettenis #else
333d3c69d8Skettenis #define DPRINTF(x)
343d3c69d8Skettenis #endif
353d3c69d8Skettenis
363d3c69d8Skettenis struct vldc_softc {
373d3c69d8Skettenis struct device sc_dv;
383d3c69d8Skettenis bus_space_tag_t sc_bustag;
393d3c69d8Skettenis bus_dma_tag_t sc_dmatag;
403d3c69d8Skettenis };
413d3c69d8Skettenis
423d3c69d8Skettenis int vldc_match(struct device *, void *, void *);
433d3c69d8Skettenis void vldc_attach(struct device *, struct device *, void *);
443d3c69d8Skettenis
45*eb7eaf8dSmpi const struct cfattach vldc_ca = {
463d3c69d8Skettenis sizeof(struct vldc_softc), vldc_match, vldc_attach
473d3c69d8Skettenis };
483d3c69d8Skettenis
493d3c69d8Skettenis struct cfdriver vldc_cd = {
503d3c69d8Skettenis NULL, "vldc", DV_DULL
513d3c69d8Skettenis };
523d3c69d8Skettenis
533d3c69d8Skettenis void vldc_get_channel_endpoint(int, struct cbus_attach_args *);
543d3c69d8Skettenis
553d3c69d8Skettenis int
vldc_match(struct device * parent,void * match,void * aux)563d3c69d8Skettenis vldc_match(struct device *parent, void *match, void *aux)
573d3c69d8Skettenis {
583d3c69d8Skettenis struct cbus_attach_args *ca = aux;
593d3c69d8Skettenis
603d3c69d8Skettenis if (strcmp(ca->ca_name, "virtual-channel") == 0 ||
613d3c69d8Skettenis strcmp(ca->ca_name, "virtual-channel-client") == 0)
623d3c69d8Skettenis return (1);
633d3c69d8Skettenis
643d3c69d8Skettenis return (0);
653d3c69d8Skettenis }
663d3c69d8Skettenis
673d3c69d8Skettenis void
vldc_attach(struct device * parent,struct device * self,void * aux)683d3c69d8Skettenis vldc_attach(struct device *parent, struct device *self, void *aux)
693d3c69d8Skettenis {
703d3c69d8Skettenis struct cbus_attach_args *ca = aux;
713d3c69d8Skettenis struct cbus_attach_args nca;
723d3c69d8Skettenis struct md_header *hdr;
733d3c69d8Skettenis struct md_element *elem;
743d3c69d8Skettenis const char *name_blk;
753d3c69d8Skettenis const char *str;
763d3c69d8Skettenis int idx;
773d3c69d8Skettenis int arc;
783d3c69d8Skettenis
793d3c69d8Skettenis printf("\n");
803d3c69d8Skettenis
813d3c69d8Skettenis hdr = (struct md_header *)mdesc;
823d3c69d8Skettenis elem = (struct md_element *)(mdesc + sizeof(struct md_header));
833d3c69d8Skettenis name_blk = mdesc + sizeof(struct md_header) + hdr->node_blk_sz;
843d3c69d8Skettenis
853d3c69d8Skettenis idx = ca->ca_idx;
863d3c69d8Skettenis for (; elem[idx].tag != 'E'; idx++) {
873d3c69d8Skettenis str = name_blk + elem[idx].name_offset;
883d3c69d8Skettenis if (elem[idx].tag != 'a' || strcmp(str, "fwd") != 0)
893d3c69d8Skettenis continue;
903d3c69d8Skettenis
913d3c69d8Skettenis arc = elem[idx].d.val;
923d3c69d8Skettenis str = name_blk + elem[arc].name_offset;
933d3c69d8Skettenis if (strcmp(str, "virtual-device-port") == 0) {
943d3c69d8Skettenis str = mdesc_get_prop_str(arc, "vldc-svc-name");
953d3c69d8Skettenis if (str) {
963d3c69d8Skettenis bzero(&nca, sizeof(nca));
973d3c69d8Skettenis nca.ca_name = str;
983d3c69d8Skettenis nca.ca_node = ca->ca_node;
993d3c69d8Skettenis nca.ca_bustag = ca->ca_bustag;
1003d3c69d8Skettenis nca.ca_dmatag = ca->ca_dmatag;
1013d3c69d8Skettenis vldc_get_channel_endpoint(arc, &nca);
1023d3c69d8Skettenis config_found(self, &nca, cbus_print);
1033d3c69d8Skettenis }
1043d3c69d8Skettenis }
1053d3c69d8Skettenis }
1063d3c69d8Skettenis }
1073d3c69d8Skettenis
1083d3c69d8Skettenis void
vldc_get_channel_endpoint(int idx,struct cbus_attach_args * ca)1093d3c69d8Skettenis vldc_get_channel_endpoint(int idx, struct cbus_attach_args *ca)
1103d3c69d8Skettenis {
1113d3c69d8Skettenis struct md_header *hdr;
1123d3c69d8Skettenis struct md_element *elem;
1133d3c69d8Skettenis const char *name_blk;
1143d3c69d8Skettenis const char *str;
1153d3c69d8Skettenis int arc;
1163d3c69d8Skettenis
1173d3c69d8Skettenis hdr = (struct md_header *)mdesc;
1183d3c69d8Skettenis elem = (struct md_element *)(mdesc + sizeof(struct md_header));
1193d3c69d8Skettenis name_blk = mdesc + sizeof(struct md_header) + hdr->node_blk_sz;
1203d3c69d8Skettenis
1213d3c69d8Skettenis ca->ca_idx = idx;
1223d3c69d8Skettenis
1233d3c69d8Skettenis ca->ca_id = -1;
1243d3c69d8Skettenis ca->ca_tx_ino = -1;
1253d3c69d8Skettenis ca->ca_rx_ino = -1;
1263d3c69d8Skettenis
1273d3c69d8Skettenis for (; elem[idx].tag != 'E'; idx++) {
1283d3c69d8Skettenis str = name_blk + elem[idx].name_offset;
1293d3c69d8Skettenis if (elem[idx].tag != 'a' || strcmp(str, "fwd") != 0)
1303d3c69d8Skettenis continue;
1313d3c69d8Skettenis
1323d3c69d8Skettenis arc = elem[idx].d.val;
1333d3c69d8Skettenis str = name_blk + elem[arc].name_offset;
1343d3c69d8Skettenis if (strcmp(str, "channel-endpoint") == 0) {
1353d3c69d8Skettenis ca->ca_id = mdesc_get_prop_val(arc, "id");
1363d3c69d8Skettenis ca->ca_tx_ino = mdesc_get_prop_val(arc, "tx-ino");
1373d3c69d8Skettenis ca->ca_rx_ino = mdesc_get_prop_val(arc, "rx-ino");
1383d3c69d8Skettenis return;
1393d3c69d8Skettenis }
1403d3c69d8Skettenis }
1413d3c69d8Skettenis }
142