1 /* $OpenBSD: vldc.c,v 1.1 2012/03/17 20:07:18 kettenis Exp $ */ 2 /* 3 * Copyright (c) 2009, 2012 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 VLDC_DEBUG 31 #define DPRINTF(x) printf x 32 #else 33 #define DPRINTF(x) 34 #endif 35 36 struct vldc_softc { 37 struct device sc_dv; 38 bus_space_tag_t sc_bustag; 39 bus_dma_tag_t sc_dmatag; 40 }; 41 42 int vldc_match(struct device *, void *, void *); 43 void vldc_attach(struct device *, struct device *, void *); 44 45 struct cfattach vldc_ca = { 46 sizeof(struct vldc_softc), vldc_match, vldc_attach 47 }; 48 49 struct cfdriver vldc_cd = { 50 NULL, "vldc", DV_DULL 51 }; 52 53 void vldc_get_channel_endpoint(int, struct cbus_attach_args *); 54 55 int 56 vldc_match(struct device *parent, void *match, void *aux) 57 { 58 struct cbus_attach_args *ca = aux; 59 60 if (strcmp(ca->ca_name, "virtual-channel") == 0 || 61 strcmp(ca->ca_name, "virtual-channel-client") == 0) 62 return (1); 63 64 return (0); 65 } 66 67 void 68 vldc_attach(struct device *parent, struct device *self, void *aux) 69 { 70 struct cbus_attach_args *ca = aux; 71 struct cbus_attach_args nca; 72 struct md_header *hdr; 73 struct md_element *elem; 74 const char *name_blk; 75 const char *str; 76 int idx; 77 int arc; 78 79 printf("\n"); 80 81 hdr = (struct md_header *)mdesc; 82 elem = (struct md_element *)(mdesc + sizeof(struct md_header)); 83 name_blk = mdesc + sizeof(struct md_header) + hdr->node_blk_sz; 84 85 idx = ca->ca_idx; 86 for (; elem[idx].tag != 'E'; idx++) { 87 str = name_blk + elem[idx].name_offset; 88 if (elem[idx].tag != 'a' || strcmp(str, "fwd") != 0) 89 continue; 90 91 arc = elem[idx].d.val; 92 str = name_blk + elem[arc].name_offset; 93 if (strcmp(str, "virtual-device-port") == 0) { 94 str = mdesc_get_prop_str(arc, "vldc-svc-name"); 95 if (str) { 96 bzero(&nca, sizeof(nca)); 97 nca.ca_name = str; 98 nca.ca_node = ca->ca_node; 99 nca.ca_bustag = ca->ca_bustag; 100 nca.ca_dmatag = ca->ca_dmatag; 101 vldc_get_channel_endpoint(arc, &nca); 102 config_found(self, &nca, cbus_print); 103 } 104 } 105 } 106 } 107 108 void 109 vldc_get_channel_endpoint(int idx, struct cbus_attach_args *ca) 110 { 111 struct md_header *hdr; 112 struct md_element *elem; 113 const char *name_blk; 114 const char *str; 115 int arc; 116 117 hdr = (struct md_header *)mdesc; 118 elem = (struct md_element *)(mdesc + sizeof(struct md_header)); 119 name_blk = mdesc + sizeof(struct md_header) + hdr->node_blk_sz; 120 121 ca->ca_idx = idx; 122 123 ca->ca_id = -1; 124 ca->ca_tx_ino = -1; 125 ca->ca_rx_ino = -1; 126 127 for (; elem[idx].tag != 'E'; idx++) { 128 str = name_blk + elem[idx].name_offset; 129 if (elem[idx].tag != 'a' || strcmp(str, "fwd") != 0) 130 continue; 131 132 arc = elem[idx].d.val; 133 str = name_blk + elem[arc].name_offset; 134 if (strcmp(str, "channel-endpoint") == 0) { 135 ca->ca_id = mdesc_get_prop_val(arc, "id"); 136 ca->ca_tx_ino = mdesc_get_prop_val(arc, "tx-ino"); 137 ca->ca_rx_ino = mdesc_get_prop_val(arc, "rx-ino"); 138 return; 139 } 140 } 141 } 142