1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 27 /* 28 * CPU nexus driver 29 */ 30 31 #include <sys/types.h> 32 #include <sys/param.h> 33 #include <sys/conf.h> 34 #include <sys/devops.h> 35 #include <sys/modctl.h> 36 #include <sys/cmn_err.h> 37 #include <sys/ddi.h> 38 #include <sys/sunddi.h> 39 #include <sys/sunndi.h> 40 41 static int cpunex_attach(dev_info_t *, ddi_attach_cmd_t); 42 static int cpunex_detach(dev_info_t *, ddi_detach_cmd_t); 43 static int cpunex_bus_ctl(dev_info_t *, dev_info_t *, ddi_ctl_enum_t, 44 void *, void *); 45 46 static struct bus_ops cpunex_bus_ops = { 47 BUSO_REV, 48 nullbusmap, 49 NULL, 50 NULL, 51 NULL, 52 i_ddi_map_fault, 53 ddi_no_dma_map, 54 ddi_no_dma_allochdl, 55 ddi_no_dma_freehdl, 56 ddi_no_dma_bindhdl, 57 ddi_no_dma_unbindhdl, 58 ddi_no_dma_flush, 59 ddi_no_dma_win, 60 ddi_no_dma_mctl, 61 cpunex_bus_ctl, 62 ddi_bus_prop_op, 63 }; 64 65 static struct dev_ops cpunex_ops = { 66 DEVO_REV, 67 0, 68 ddi_no_info, 69 nulldev, 70 nulldev, 71 cpunex_attach, 72 cpunex_detach, 73 nodev, 74 NULL, 75 &cpunex_bus_ops, 76 NULL, 77 ddi_quiesce_not_needed, /* quiesce */ 78 }; 79 80 static struct modldrv modldrv = { 81 &mod_driverops, 82 "cpu nexus driver", 83 &cpunex_ops 84 }; 85 86 static struct modlinkage modlinkage = { 87 MODREV_1, 88 &modldrv, 89 NULL 90 }; 91 92 /* 93 * cpunex_bus_ctl() 94 * This routine implements nexus bus ctl operations. Of importance are 95 * DDI_CTLOPS_REPORTDEV, DDI_CTLOPS_INITCHILD, DDI_CTLOPS_UNINITCHILD 96 * and DDI_CTLOPS_POWER. For DDI_CTLOPS_INITCHILD, it tries to lookup 97 * reg property on the child node and builds and sets the name. 98 */ 99 static int 100 cpunex_bus_ctl(dev_info_t *dip, dev_info_t *rdip, ddi_ctl_enum_t op, void *arg, 101 void *result) 102 { 103 switch (op) { 104 case DDI_CTLOPS_REPORTDEV: { 105 dev_info_t *pdip = ddi_get_parent(rdip); 106 cmn_err(CE_CONT, "?%s%d at %s%d", 107 ddi_node_name(rdip), ddi_get_instance(rdip), 108 ddi_node_name(pdip), ddi_get_instance(pdip)); 109 return (DDI_SUCCESS); 110 } 111 112 case DDI_CTLOPS_INITCHILD: { 113 dev_info_t *cdip = (dev_info_t *)arg; 114 int i; 115 char caddr[MAXNAMELEN]; 116 117 i = ddi_prop_get_int(DDI_DEV_T_ANY, cdip, 118 DDI_PROP_DONTPASS, "reg", -1); 119 120 if (i == -1) { 121 cmn_err(CE_NOTE, "!%s(%d): \"reg\" property " 122 "not found", ddi_node_name(cdip), 123 ddi_get_instance(cdip)); 124 return (DDI_NOT_WELL_FORMED); 125 } 126 127 (void) sprintf(caddr, "%d", i); 128 ddi_set_name_addr(cdip, caddr); 129 130 return (DDI_SUCCESS); 131 } 132 133 case DDI_CTLOPS_UNINITCHILD: { 134 ddi_prop_remove_all((dev_info_t *)arg); 135 ddi_set_name_addr((dev_info_t *)arg, NULL); 136 return (DDI_SUCCESS); 137 } 138 139 default: { 140 return (ddi_ctlops(dip, rdip, op, arg, result)); 141 } 142 } 143 } 144 145 /*ARGSUSED*/ 146 static int 147 cpunex_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) 148 { 149 switch (cmd) { 150 case DDI_ATTACH: 151 case DDI_RESUME: 152 break; 153 default: 154 return (DDI_FAILURE); 155 } 156 157 return (DDI_SUCCESS); 158 } 159 160 /*ARGSUSED*/ 161 static int 162 cpunex_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) 163 { 164 switch (cmd) { 165 case DDI_DETACH: 166 case DDI_SUSPEND: 167 break; 168 default: 169 return (DDI_FAILURE); 170 } 171 172 return (DDI_SUCCESS); 173 } 174 175 int 176 _init(void) 177 { 178 int error; 179 180 error = mod_install(&modlinkage); 181 return (error); 182 } 183 184 int 185 _fini(void) 186 { 187 int error; 188 189 error = mod_remove(&modlinkage); 190 return (error); 191 } 192 193 int 194 _info(struct modinfo *modinfop) 195 { 196 return (mod_info(&modlinkage, modinfop)); 197 } 198