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