xref: /openbsd-src/sys/arch/sparc64/dev/vsw.c (revision eb7eaf8de3ff431d305450f61b441e5460c82246)
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