xref: /onnv-gate/usr/src/uts/sun4/io/fpc/fpc.c (revision 7656:2621e50fdf4a)
11370Sschwartz /*
21370Sschwartz  * CDDL HEADER START
31370Sschwartz  *
41370Sschwartz  * The contents of this file are subject to the terms of the
51370Sschwartz  * Common Development and Distribution License (the "License").
61370Sschwartz  * You may not use this file except in compliance with the License.
71370Sschwartz  *
81370Sschwartz  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
91370Sschwartz  * or http://www.opensolaris.org/os/licensing.
101370Sschwartz  * See the License for the specific language governing permissions
111370Sschwartz  * and limitations under the License.
121370Sschwartz  *
131370Sschwartz  * When distributing Covered Code, include this CDDL HEADER in each
141370Sschwartz  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
151370Sschwartz  * If applicable, add the following below this CDDL HEADER, with the
161370Sschwartz  * fields enclosed by brackets "[]" replaced with your own identifying
171370Sschwartz  * information: Portions Copyright [yyyy] [name of copyright owner]
181370Sschwartz  *
191370Sschwartz  * CDDL HEADER END
201370Sschwartz  */
211370Sschwartz 
221370Sschwartz /*
23*7656SSherry.Moore@Sun.COM  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
241370Sschwartz  * Use is subject to license terms.
251370Sschwartz  */
261370Sschwartz 
271370Sschwartz 
281370Sschwartz #include <sys/types.h>
291370Sschwartz #include <sys/sunddi.h>
301370Sschwartz #include <sys/sunndi.h>
311370Sschwartz #include <sys/conf.h>
321370Sschwartz #include <sys/modctl.h>
331370Sschwartz #include <sys/stat.h>
341370Sschwartz #include <fpc.h>
351370Sschwartz 
361370Sschwartz static int fpc_attach(dev_info_t *dip, ddi_attach_cmd_t cmd);
371370Sschwartz static int fpc_detach(dev_info_t *dip, ddi_detach_cmd_t cmd);
381370Sschwartz 
391370Sschwartz static struct dev_ops fpc_ops = {
401370Sschwartz 	DEVO_REV,
411370Sschwartz 	0,
421370Sschwartz 	nulldev,
431370Sschwartz 	nulldev,
441370Sschwartz 	nulldev,
451370Sschwartz 	fpc_attach,
461370Sschwartz 	fpc_detach,
471370Sschwartz 	nodev,
481370Sschwartz 	NULL,
491370Sschwartz 	NULL,
50*7656SSherry.Moore@Sun.COM 	nodev,
51*7656SSherry.Moore@Sun.COM 	ddi_quiesce_not_needed,		/* quiesce */
521370Sschwartz };
531370Sschwartz 
541370Sschwartz extern struct mod_ops mod_driverops;
551370Sschwartz 
561370Sschwartz static struct modldrv md = {
571370Sschwartz 	&mod_driverops,
58*7656SSherry.Moore@Sun.COM 	"IO Chip Perf Counter",
591370Sschwartz 	&fpc_ops,
601370Sschwartz };
611370Sschwartz 
621370Sschwartz static struct modlinkage ml = {
631370Sschwartz 	MODREV_1,
641370Sschwartz 	(void *)&md,
651370Sschwartz 	NULL
661370Sschwartz };
671370Sschwartz 
681370Sschwartz int
_init(void)691370Sschwartz _init(void)
701370Sschwartz {
711691Sschwartz 	if (fpc_init_platform_check() != SUCCESS)
721691Sschwartz 		return (ENODEV);
731370Sschwartz 	return (mod_install(&ml));
741370Sschwartz }
751370Sschwartz 
761370Sschwartz int
_info(struct modinfo * modinfop)771370Sschwartz _info(struct modinfo *modinfop)
781370Sschwartz {
791370Sschwartz 	return (mod_info(&ml, modinfop));
801370Sschwartz }
811370Sschwartz 
821370Sschwartz int
_fini(void)831370Sschwartz _fini(void)
841370Sschwartz {
851370Sschwartz 	return (mod_remove(&ml));
861370Sschwartz }
871370Sschwartz 
881370Sschwartz static int
fpc_attach(dev_info_t * dip,ddi_attach_cmd_t cmd)891370Sschwartz fpc_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
901370Sschwartz {
911370Sschwartz 	switch (cmd) {
921370Sschwartz 	/*
931370Sschwartz 	 * Since the driver saves no state between calls, we can fully detach
941370Sschwartz 	 * on suspend and fully attach on resume.
951370Sschwartz 	 *
961370Sschwartz 	 * An RFE might be to save event register states for restore.
971370Sschwartz 	 * The result of not doing this is that the kstat reader (busstat)
981370Sschwartz 	 * may quit upon resume, seeing that the events have changed out from
991370Sschwartz 	 * underneath it (since the registers were powered off upon suspend).
1001370Sschwartz 	 */
1011370Sschwartz 	case DDI_RESUME:
1021370Sschwartz 	case DDI_ATTACH:
1031370Sschwartz 		if (fpc_kstat_init(dip) != DDI_SUCCESS) {
1041370Sschwartz 			(void) fpc_detach(dip, DDI_DETACH);
1051370Sschwartz 			return (DDI_FAILURE);
1061370Sschwartz 		}
1071370Sschwartz 		return (DDI_SUCCESS);
1081370Sschwartz 	default:
1091370Sschwartz 		return (DDI_FAILURE);
1101370Sschwartz 	}
1111370Sschwartz }
1121370Sschwartz 
1131370Sschwartz static int
fpc_detach(dev_info_t * dip,ddi_detach_cmd_t cmd)1141370Sschwartz fpc_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
1151370Sschwartz {
1161370Sschwartz 	switch (cmd) {
1171370Sschwartz 	case DDI_SUSPEND:
1181370Sschwartz 	case DDI_DETACH:
1191370Sschwartz 		fpc_kstat_fini(dip);
1201370Sschwartz 		return (DDI_SUCCESS);
1211370Sschwartz 	default:
1221370Sschwartz 		return (DDI_FAILURE);
1231370Sschwartz 	}
1241370Sschwartz }
125