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, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 #include <sys/types.h> 30 #include <sys/byteorder.h> 31 #include <sys/systm.h> 32 #include <sys/ddi.h> 33 #include <sys/sunddi.h> 34 35 int pcs_getinfo(dev_info_t *, ddi_info_cmd_t, void *, void **); 36 int pcs_attach(dev_info_t *, ddi_attach_cmd_t); 37 int pcs_detach(dev_info_t *, ddi_detach_cmd_t); 38 dev_info_t *pcs_dip; 39 40 static struct dev_ops pcs_devops = { 41 DEVO_REV, 42 0, 43 pcs_getinfo, 44 nulldev, 45 nulldev, 46 pcs_attach, 47 pcs_detach, 48 nulldev, 49 NULL, 50 NULL 51 }; 52 /* 53 * This is the loadable module wrapper. 54 */ 55 #include <sys/modctl.h> 56 57 extern struct mod_ops mod_driverops; 58 59 static struct modldrv modldrv = { 60 &mod_driverops, /* Type of module. This one is a driver */ 61 "PCMCIA Socket Driver %I%", /* Name of the module. */ 62 &pcs_devops, /* driver ops */ 63 }; 64 65 static struct modlinkage modlinkage = { 66 MODREV_1, (void *)&modldrv, NULL 67 }; 68 69 struct pcs_inst { 70 dev_info_t *dip; 71 } *pcs_instances; 72 73 int 74 _init() 75 { 76 int ret; 77 if ((ret = ddi_soft_state_init((void **)&pcs_instances, 78 sizeof (struct pcs_inst), 1)) != 0) 79 return (ret); 80 if ((ret = mod_install(&modlinkage)) != 0) { 81 ddi_soft_state_fini((void **)&pcs_instances); 82 } 83 return (ret); 84 } 85 86 int 87 _fini() 88 { 89 int ret; 90 ret = mod_remove(&modlinkage); 91 if (ret == 0) { 92 ddi_soft_state_fini((void **)&pcs_instances); 93 } 94 return (ret); 95 } 96 97 int 98 _info(struct modinfo *modinfop) 99 { 100 return (mod_info(&modlinkage, modinfop)); 101 } 102 103 int 104 pcs_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **result) 105 { 106 int error = DDI_SUCCESS; 107 int inum; 108 struct pcs_inst *inst; 109 #ifdef lint 110 dip = dip; 111 #endif 112 113 switch (cmd) { 114 case DDI_INFO_DEVT2DEVINFO: 115 inum = getminor((dev_t)arg); 116 inst = (struct pcs_inst *)ddi_get_soft_state(pcs_instances, 117 inum); 118 if (inst == NULL) 119 error = DDI_FAILURE; 120 else 121 *result = inst->dip; 122 break; 123 case DDI_INFO_DEVT2INSTANCE: 124 inum = getminor((dev_t)arg); 125 inst = (struct pcs_inst *)ddi_get_soft_state(pcs_instances, 126 inum); 127 if (inst == NULL) 128 error = DDI_FAILURE; 129 else 130 *result = (void *)(uintptr_t)inum; 131 break; 132 default: 133 error = DDI_FAILURE; 134 } 135 return (error); 136 } 137 138 int 139 pcs_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) 140 { 141 int ret = DDI_SUCCESS; 142 int inum; 143 struct pcs_inst *inst; 144 #ifdef lint 145 dip = dip; 146 cmd = cmd; 147 #endif 148 149 inum = ddi_get_instance(dip); 150 151 if (ddi_soft_state_zalloc(pcs_instances, inum) == DDI_SUCCESS) { 152 inst = (struct pcs_inst *)ddi_get_soft_state(pcs_instances, 153 inum); 154 if (inst == NULL) 155 ret = DDI_FAILURE; 156 else 157 inst->dip = dip; 158 } 159 160 return (ret); 161 } 162 163 int 164 pcs_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) 165 { 166 if (cmd == DDI_DETACH) { 167 ddi_soft_state_free(pcs_instances, ddi_get_instance(dip)); 168 return (DDI_SUCCESS); 169 } 170 return (DDI_FAILURE); 171 } 172