1*eb7eaf8dSmpi /* $OpenBSD: vsw.c,v 1.2 2021/10/24 17:05:04 mpi Exp $ */
23046e9e3Skettenis /*
33046e9e3Skettenis * Copyright (c) 2009 Mark Kettenis
43046e9e3Skettenis *
53046e9e3Skettenis * Permission to use, copy, modify, and distribute this software for any
63046e9e3Skettenis * purpose with or without fee is hereby granted, provided that the above
73046e9e3Skettenis * copyright notice and this permission notice appear in all copies.
83046e9e3Skettenis *
93046e9e3Skettenis * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
103046e9e3Skettenis * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
113046e9e3Skettenis * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
123046e9e3Skettenis * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
133046e9e3Skettenis * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
143046e9e3Skettenis * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
153046e9e3Skettenis * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
163046e9e3Skettenis */
173046e9e3Skettenis
183046e9e3Skettenis #include <sys/param.h>
193046e9e3Skettenis #include <sys/buf.h>
203046e9e3Skettenis #include <sys/device.h>
213046e9e3Skettenis #include <sys/malloc.h>
223046e9e3Skettenis #include <sys/systm.h>
233046e9e3Skettenis
243046e9e3Skettenis #include <machine/autoconf.h>
253046e9e3Skettenis #include <machine/hypervisor.h>
263046e9e3Skettenis #include <machine/mdesc.h>
273046e9e3Skettenis
283046e9e3Skettenis #include <sparc64/dev/cbusvar.h>
293046e9e3Skettenis
303046e9e3Skettenis #ifdef VSW_DEBUG
313046e9e3Skettenis #define DPRINTF(x) printf x
323046e9e3Skettenis #else
333046e9e3Skettenis #define DPRINTF(x)
343046e9e3Skettenis #endif
353046e9e3Skettenis
363046e9e3Skettenis struct vsw_softc {
373046e9e3Skettenis struct device sc_dv;
383046e9e3Skettenis bus_space_tag_t sc_bustag;
393046e9e3Skettenis bus_dma_tag_t sc_dmatag;
403046e9e3Skettenis };
413046e9e3Skettenis
423046e9e3Skettenis int vsw_match(struct device *, void *, void *);
433046e9e3Skettenis void vsw_attach(struct device *, struct device *, void *);
443046e9e3Skettenis
45*eb7eaf8dSmpi const struct cfattach vsw_ca = {
463046e9e3Skettenis sizeof(struct vsw_softc), vsw_match, vsw_attach
473046e9e3Skettenis };
483046e9e3Skettenis
493046e9e3Skettenis struct cfdriver vsw_cd = {
503046e9e3Skettenis NULL, "vsw", DV_DULL
513046e9e3Skettenis };
523046e9e3Skettenis
533046e9e3Skettenis void vsw_get_channel_endpoint(int, struct cbus_attach_args *);
543046e9e3Skettenis
553046e9e3Skettenis int
vsw_match(struct device * parent,void * match,void * aux)563046e9e3Skettenis vsw_match(struct device *parent, void *match, void *aux)
573046e9e3Skettenis {
583046e9e3Skettenis struct cbus_attach_args *ca = aux;
593046e9e3Skettenis
603046e9e3Skettenis if (strcmp(ca->ca_name, "virtual-network-switch") == 0)
613046e9e3Skettenis return (1);
623046e9e3Skettenis
633046e9e3Skettenis return (0);
643046e9e3Skettenis }
653046e9e3Skettenis
663046e9e3Skettenis void
vsw_attach(struct device * parent,struct device * self,void * aux)673046e9e3Skettenis vsw_attach(struct device *parent, struct device *self, void *aux)
683046e9e3Skettenis {
693046e9e3Skettenis struct cbus_attach_args *ca = aux;
703046e9e3Skettenis struct cbus_attach_args nca;
713046e9e3Skettenis struct md_header *hdr;
723046e9e3Skettenis struct md_element *elem;
733046e9e3Skettenis const char *name_blk;
743046e9e3Skettenis const char *str;
753046e9e3Skettenis int idx;
763046e9e3Skettenis int arc;
773046e9e3Skettenis
783046e9e3Skettenis printf("\n");
793046e9e3Skettenis
803046e9e3Skettenis hdr = (struct md_header *)mdesc;
813046e9e3Skettenis elem = (struct md_element *)(mdesc + sizeof(struct md_header));
823046e9e3Skettenis name_blk = mdesc + sizeof(struct md_header) + hdr->node_blk_sz;
833046e9e3Skettenis
843046e9e3Skettenis idx = ca->ca_idx;
853046e9e3Skettenis for (; elem[idx].tag != 'E'; idx++) {
863046e9e3Skettenis str = name_blk + elem[idx].name_offset;
873046e9e3Skettenis if (elem[idx].tag != 'a' || strcmp(str, "fwd") != 0)
883046e9e3Skettenis continue;
893046e9e3Skettenis
903046e9e3Skettenis arc = elem[idx].d.val;
913046e9e3Skettenis str = name_blk + elem[arc].name_offset;
923046e9e3Skettenis if (strcmp(str, "virtual-device-port") == 0) {
933046e9e3Skettenis bzero(&nca, sizeof(nca));
943046e9e3Skettenis nca.ca_name = "network";
953046e9e3Skettenis nca.ca_node = ca->ca_node;
963046e9e3Skettenis nca.ca_bustag = ca->ca_bustag;
973046e9e3Skettenis nca.ca_dmatag = ca->ca_dmatag;
983046e9e3Skettenis vsw_get_channel_endpoint(arc, &nca);
993046e9e3Skettenis config_found(self, &nca, cbus_print);
1003046e9e3Skettenis }
1013046e9e3Skettenis }
1023046e9e3Skettenis }
1033046e9e3Skettenis
1043046e9e3Skettenis void
vsw_get_channel_endpoint(int idx,struct cbus_attach_args * ca)1053046e9e3Skettenis vsw_get_channel_endpoint(int idx, struct cbus_attach_args *ca)
1063046e9e3Skettenis {
1073046e9e3Skettenis struct md_header *hdr;
1083046e9e3Skettenis struct md_element *elem;
1093046e9e3Skettenis const char *name_blk;
1103046e9e3Skettenis const char *str;
1113046e9e3Skettenis int arc;
1123046e9e3Skettenis
1133046e9e3Skettenis hdr = (struct md_header *)mdesc;
1143046e9e3Skettenis elem = (struct md_element *)(mdesc + sizeof(struct md_header));
1153046e9e3Skettenis name_blk = mdesc + sizeof(struct md_header) + hdr->node_blk_sz;
1163046e9e3Skettenis
1173046e9e3Skettenis ca->ca_idx = idx;
1183046e9e3Skettenis
1193046e9e3Skettenis ca->ca_id = -1;
1203046e9e3Skettenis ca->ca_tx_ino = -1;
1213046e9e3Skettenis ca->ca_rx_ino = -1;
1223046e9e3Skettenis
1233046e9e3Skettenis for (; elem[idx].tag != 'E'; idx++) {
1243046e9e3Skettenis str = name_blk + elem[idx].name_offset;
1253046e9e3Skettenis if (elem[idx].tag != 'a' || strcmp(str, "fwd") != 0)
1263046e9e3Skettenis continue;
1273046e9e3Skettenis
1283046e9e3Skettenis arc = elem[idx].d.val;
1293046e9e3Skettenis str = name_blk + elem[arc].name_offset;
1303046e9e3Skettenis if (strcmp(str, "channel-endpoint") == 0) {
1313046e9e3Skettenis ca->ca_id = mdesc_get_prop_val(arc, "id");
1323046e9e3Skettenis ca->ca_tx_ino = mdesc_get_prop_val(arc, "tx-ino");
1333046e9e3Skettenis ca->ca_rx_ino = mdesc_get_prop_val(arc, "rx-ino");
1343046e9e3Skettenis return;
1353046e9e3Skettenis }
1363046e9e3Skettenis }
1373046e9e3Skettenis }
138