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, NULL } 89 }; 90 91 /* 92 * cpunex_bus_ctl() 93 * This routine implements nexus bus ctl operations. Of importance are 94 * DDI_CTLOPS_REPORTDEV, DDI_CTLOPS_INITCHILD, DDI_CTLOPS_UNINITCHILD 95 * and DDI_CTLOPS_POWER. For DDI_CTLOPS_INITCHILD, it tries to lookup 96 * reg property on the child node and builds and sets the name. 97 */ 98 static int 99 cpunex_bus_ctl(dev_info_t *dip, dev_info_t *rdip, ddi_ctl_enum_t op, void *arg, 100 void *result) 101 { 102 switch (op) { 103 case DDI_CTLOPS_REPORTDEV: { 104 dev_info_t *pdip = ddi_get_parent(rdip); 105 cmn_err(CE_CONT, "?%s%d at %s%d", 106 ddi_node_name(rdip), ddi_get_instance(rdip), 107 ddi_node_name(pdip), ddi_get_instance(pdip)); 108 return (DDI_SUCCESS); 109 } 110 111 case DDI_CTLOPS_INITCHILD: { 112 dev_info_t *cdip = (dev_info_t *)arg; 113 int i; 114 char caddr[MAXNAMELEN]; 115 116 i = ddi_prop_get_int(DDI_DEV_T_ANY, cdip, 117 DDI_PROP_DONTPASS, "reg", -1); 118 119 if (i == -1) { 120 cmn_err(CE_NOTE, "!%s(%d): \"reg\" property " 121 "not found", ddi_node_name(cdip), 122 ddi_get_instance(cdip)); 123 return (DDI_NOT_WELL_FORMED); 124 } 125 126 (void) sprintf(caddr, "%d", i); 127 ddi_set_name_addr(cdip, caddr); 128 129 return (DDI_SUCCESS); 130 } 131 132 case DDI_CTLOPS_UNINITCHILD: { 133 ddi_prop_remove_all((dev_info_t *)arg); 134 ddi_set_name_addr((dev_info_t *)arg, NULL); 135 return (DDI_SUCCESS); 136 } 137 138 default: { 139 return (ddi_ctlops(dip, rdip, op, arg, result)); 140 } 141 } 142 } 143 144 /*ARGSUSED*/ 145 static int 146 cpunex_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) 147 { 148 switch (cmd) { 149 case DDI_ATTACH: 150 case DDI_RESUME: 151 break; 152 default: 153 return (DDI_FAILURE); 154 } 155 156 return (DDI_SUCCESS); 157 } 158 159 /*ARGSUSED*/ 160 static int 161 cpunex_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) 162 { 163 switch (cmd) { 164 case DDI_DETACH: 165 case DDI_SUSPEND: 166 break; 167 default: 168 return (DDI_FAILURE); 169 } 170 171 return (DDI_SUCCESS); 172 } 173 174 int 175 _init(void) 176 { 177 int error; 178 179 error = mod_install(&modlinkage); 180 return (error); 181 } 182 183 int 184 _fini(void) 185 { 186 int error; 187 188 error = mod_remove(&modlinkage); 189 return (error); 190 } 191 192 int 193 _info(struct modinfo *modinfop) 194 { 195 return (mod_info(&modlinkage, modinfop)); 196 }