1 /* $OpenBSD: vcc.c,v 1.1 2009/05/10 12:24:04 kettenis Exp $ */ 2 /* 3 * Copyright (c) 2009 Mark Kettenis 4 * 5 * Permission to use, copy, modify, and distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18 #include <sys/param.h> 19 #include <sys/buf.h> 20 #include <sys/device.h> 21 #include <sys/malloc.h> 22 #include <sys/systm.h> 23 24 #include <machine/autoconf.h> 25 #include <machine/hypervisor.h> 26 #include <machine/mdesc.h> 27 28 #include <sparc64/dev/cbusvar.h> 29 30 #ifdef VCC_DEBUG 31 #define DPRINTF(x) printf x 32 #else 33 #define DPRINTF(x) 34 #endif 35 36 struct vcc_softc { 37 struct device sc_dv; 38 bus_space_tag_t sc_bustag; 39 bus_dma_tag_t sc_dmatag; 40 }; 41 42 int vcc_match(struct device *, void *, void *); 43 void vcc_attach(struct device *, struct device *, void *); 44 45 struct cfattach vcc_ca = { 46 sizeof(struct vcc_softc), vcc_match, vcc_attach 47 }; 48 49 struct cfdriver vcc_cd = { 50 NULL, "vcc", DV_DULL 51 }; 52 53 void vcc_get_channel_endpoint(int, struct cbus_attach_args *); 54 55 int 56 vcc_match(struct device *parent, void *match, void *aux) 57 { 58 struct cbus_attach_args *ca = aux; 59 60 if (strcmp(ca->ca_name, "virtual-console-concentrator") == 0) 61 return (1); 62 63 return (0); 64 } 65 66 void 67 vcc_attach(struct device *parent, struct device *self, void *aux) 68 { 69 struct cbus_attach_args *ca = aux; 70 struct cbus_attach_args nca; 71 struct md_header *hdr; 72 struct md_element *elem; 73 const char *name_blk; 74 const char *str; 75 int idx; 76 int arc; 77 78 printf("\n"); 79 80 hdr = (struct md_header *)mdesc; 81 elem = (struct md_element *)(mdesc + sizeof(struct md_header)); 82 name_blk = mdesc + sizeof(struct md_header) + hdr->node_blk_sz; 83 84 idx = ca->ca_idx; 85 for (; elem[idx].tag != 'E'; idx++) { 86 str = name_blk + elem[idx].name_offset; 87 if (elem[idx].tag != 'a' || strcmp(str, "fwd") != 0) 88 continue; 89 90 arc = elem[idx].d.val; 91 str = name_blk + elem[arc].name_offset; 92 if (strcmp(str, "virtual-device-port") == 0) { 93 str = mdesc_get_prop_str(arc, "vcc-domain-name"); 94 if (str) { 95 bzero(&nca, sizeof(nca)); 96 nca.ca_name = str; 97 nca.ca_node = ca->ca_node; 98 nca.ca_bustag = ca->ca_bustag; 99 nca.ca_dmatag = ca->ca_dmatag; 100 vcc_get_channel_endpoint(arc, &nca); 101 config_found(self, &nca, cbus_print); 102 } 103 } 104 } 105 } 106 107 void 108 vcc_get_channel_endpoint(int idx, struct cbus_attach_args *ca) 109 { 110 struct md_header *hdr; 111 struct md_element *elem; 112 const char *name_blk; 113 const char *str; 114 int arc; 115 116 hdr = (struct md_header *)mdesc; 117 elem = (struct md_element *)(mdesc + sizeof(struct md_header)); 118 name_blk = mdesc + sizeof(struct md_header) + hdr->node_blk_sz; 119 120 ca->ca_idx = idx; 121 122 ca->ca_id = -1; 123 ca->ca_tx_ino = -1; 124 ca->ca_rx_ino = -1; 125 126 for (; elem[idx].tag != 'E'; idx++) { 127 str = name_blk + elem[idx].name_offset; 128 if (elem[idx].tag != 'a' || strcmp(str, "fwd") != 0) 129 continue; 130 131 arc = elem[idx].d.val; 132 str = name_blk + elem[arc].name_offset; 133 if (strcmp(str, "channel-endpoint") == 0) { 134 ca->ca_id = mdesc_get_prop_val(arc, "id"); 135 ca->ca_tx_ino = mdesc_get_prop_val(arc, "tx-ino"); 136 ca->ca_rx_ino = mdesc_get_prop_val(arc, "rx-ino"); 137 return; 138 } 139 } 140 } 141