xref: /onnv-gate/usr/src/uts/intel/io/pit_beep.c (revision 7656:2621e50fdf4a)
15129Smarx /*
25129Smarx  * CDDL HEADER START
35129Smarx  *
45129Smarx  * The contents of this file are subject to the terms of the
55129Smarx  * Common Development and Distribution License (the "License").
65129Smarx  * You may not use this file except in compliance with the License.
75129Smarx  *
85129Smarx  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
95129Smarx  * or http://www.opensolaris.org/os/licensing.
105129Smarx  * See the License for the specific language governing permissions
115129Smarx  * and limitations under the License.
125129Smarx  *
135129Smarx  * When distributing Covered Code, include this CDDL HEADER in each
145129Smarx  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
155129Smarx  * If applicable, add the following below this CDDL HEADER, with the
165129Smarx  * fields enclosed by brackets "[]" replaced with your own identifying
175129Smarx  * information: Portions Copyright [yyyy] [name of copyright owner]
185129Smarx  *
195129Smarx  * CDDL HEADER END
205129Smarx  */
215129Smarx /*
227542SRichard.Bean@Sun.COM  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
235129Smarx  * Use is subject to license terms.
245129Smarx  */
255129Smarx 
265129Smarx /*
275129Smarx  * Simple beeper support for PC platform, using standard timer 2 beeper.
285129Smarx  */
295129Smarx 
305129Smarx #include <sys/types.h>
315129Smarx #include <sys/conf.h>
325129Smarx #include <sys/beep.h>
335129Smarx #include <sys/ksynch.h>
345129Smarx #include <sys/ddi.h>
355129Smarx #include <sys/sunddi.h>
365129Smarx #include <sys/modctl.h>
375129Smarx #include <sys/pit.h>
385129Smarx #include <sys/inttypes.h>
395129Smarx 
405129Smarx #define	PIT_BEEP_UNIT(dev)	(getminor((dev)))
415129Smarx 
425129Smarx typedef struct pit_beep_state {
435129Smarx 	/* Dip of pit_beep device */
445129Smarx 	dev_info_t	*dip;
455129Smarx 
465129Smarx } pit_beep_state_t;
475129Smarx 
485129Smarx #define	PIT_BEEP_ON	1
495129Smarx #define	PIT_BEEP_OFF	0
505129Smarx 
515129Smarx /* Pointer to the state structure */
525129Smarx static void *pit_beep_statep;
535129Smarx 
545129Smarx static int pit_beep_attach(dev_info_t *dip, ddi_attach_cmd_t cmd);
555129Smarx static int pit_beep_detach(dev_info_t *dip, ddi_detach_cmd_t cmd);
565129Smarx static int pit_beep_info(dev_info_t *dip, ddi_info_cmd_t infocmd,
575129Smarx     void *arg, void **result);
585129Smarx static void pit_beep_freq(void *arg, int freq);
595129Smarx static void pit_beep_on(void *arg);
605129Smarx static void pit_beep_off(void *arg);
615129Smarx 
625129Smarx struct cb_ops pit_beep_cb_ops = {
635129Smarx 	nulldev,	/* open  */
645129Smarx 	nulldev,	/* close */
655129Smarx 	nulldev,	/* strategy */
665129Smarx 	nulldev,	/* print */
675129Smarx 	nulldev,	/* dump */
685129Smarx 	nulldev,	/* read */
695129Smarx 	nulldev,	/* write */
705129Smarx 	nulldev,	/* ioctl */
715129Smarx 	nulldev,	/* devmap */
725129Smarx 	nulldev,	/* mmap */
735129Smarx 	nulldev,	/* segmap */
745129Smarx 	nochpoll,	/* poll */
755129Smarx 	ddi_prop_op,	/* cb_prop_op */
765129Smarx 	NULL,		/* streamtab  */
775129Smarx 	D_MP | D_NEW
785129Smarx };
795129Smarx 
805129Smarx 
815129Smarx static struct dev_ops pit_beep_ops = {
825129Smarx 	DEVO_REV,		/* Devo_rev */
835129Smarx 	0,			/* Refcnt */
845129Smarx 	pit_beep_info,		/* Info */
855129Smarx 	nulldev,		/* Identify */
865129Smarx 	nulldev,		/* Probe */
875129Smarx 	pit_beep_attach,	/* Attach */
885129Smarx 	pit_beep_detach,	/* Detach */
895129Smarx 	nodev,			/* Reset */
905129Smarx 	&pit_beep_cb_ops,	/* Driver operations */
915129Smarx 	0,			/* Bus operations */
92*7656SSherry.Moore@Sun.COM 	NULL,			/* Power */
93*7656SSherry.Moore@Sun.COM 	ddi_quiesce_not_needed,		/* quiesce */
945129Smarx };
955129Smarx 
965129Smarx 
975129Smarx static struct modldrv modldrv = {
985129Smarx 	&mod_driverops, 		/* This one is a driver */
997542SRichard.Bean@Sun.COM 	"Intel Pit_beep Driver",	/* Name of the module. */
1005129Smarx 	&pit_beep_ops,			/* Driver ops */
1015129Smarx };
1025129Smarx 
1035129Smarx 
1045129Smarx static struct modlinkage modlinkage = {
1055129Smarx 	MODREV_1, (void *)&modldrv, NULL
1065129Smarx };
1075129Smarx 
1085129Smarx 
1095129Smarx 
1105129Smarx int
_init(void)1115129Smarx _init(void)
1125129Smarx {
1135129Smarx 	int error;
1145129Smarx 
1155129Smarx 	/* Initialize the soft state structures */
1165129Smarx 	if ((error = ddi_soft_state_init(&pit_beep_statep,
1175129Smarx 	    sizeof (pit_beep_state_t), 1)) != 0) {
1185129Smarx 
1195129Smarx 		return (error);
1205129Smarx 	}
1215129Smarx 
1225129Smarx 	/* Install the loadable module */
1235129Smarx 	if ((error = mod_install(&modlinkage)) != 0) {
1245129Smarx 		ddi_soft_state_fini(&pit_beep_statep);
1255129Smarx 	}
1265129Smarx 
1275129Smarx 	return (error);
1285129Smarx }
1295129Smarx 
1305129Smarx 
1315129Smarx int
_info(struct modinfo * modinfop)1325129Smarx _info(struct modinfo *modinfop)
1335129Smarx {
1345129Smarx 	return (mod_info(&modlinkage, modinfop));
1355129Smarx }
1365129Smarx 
1375129Smarx int
_fini(void)1385129Smarx _fini(void)
1395129Smarx {
1405129Smarx 	int error;
1415129Smarx 
1425129Smarx 	error = mod_remove(&modlinkage);
1435129Smarx 
1445129Smarx 	if (error == 0) {
1455129Smarx 		/* Release per module resources */
1465129Smarx 		ddi_soft_state_fini(&pit_beep_statep);
1475129Smarx 	}
1485129Smarx 
1495129Smarx 	return (error);
1505129Smarx }
1515129Smarx 
1525129Smarx /*
1535129Smarx  * pit_beep_attach:
1545129Smarx  */
1555129Smarx static int
pit_beep_attach(dev_info_t * dip,ddi_attach_cmd_t cmd)1565129Smarx pit_beep_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
1575129Smarx {
1585129Smarx 	switch (cmd) {
1595129Smarx 		case DDI_ATTACH:
1605129Smarx 			break;
1615129Smarx 		case DDI_RESUME:
1625129Smarx 
1635129Smarx 			return (DDI_SUCCESS);
1645129Smarx 		default:
1655129Smarx 
1665129Smarx 			return (DDI_FAILURE);
1675129Smarx 	}
1685129Smarx 
1695129Smarx 	pit_beep_off(dip);
1705129Smarx 
1715129Smarx 	(void) beep_init((void *)dip, pit_beep_on, pit_beep_off,
1725129Smarx 	    pit_beep_freq);
1735129Smarx 
1745129Smarx 	/* Display information in the banner */
1755129Smarx 	ddi_report_dev(dip);
1765129Smarx 
1775129Smarx 	return (DDI_SUCCESS);
1785129Smarx }
1795129Smarx 
1805129Smarx 
1815129Smarx /*
1825129Smarx  * pit_beep_detach:
1835129Smarx  */
1845129Smarx /* ARGSUSED */
1855129Smarx static int
pit_beep_detach(dev_info_t * dip,ddi_detach_cmd_t cmd)1865129Smarx pit_beep_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
1875129Smarx {
1885129Smarx 	switch (cmd) {
1895129Smarx 		case DDI_SUSPEND:
1905129Smarx 
1915129Smarx 			/*
1925129Smarx 			 * If a beep is in progress; fail suspend
1935129Smarx 			 */
1945129Smarx 			if (!beep_busy()) {
1955129Smarx 
1965129Smarx 				return (DDI_SUCCESS);
1975129Smarx 			} else {
1985129Smarx 
1995129Smarx 				return (DDI_FAILURE);
2005129Smarx 			}
2015129Smarx 		default:
2025129Smarx 
2035129Smarx 			return (DDI_FAILURE);
2045129Smarx 	}
2055129Smarx }
2065129Smarx 
2075129Smarx 
2085129Smarx /*
2095129Smarx  * pit_beep_info:
2105129Smarx  */
2115129Smarx /* ARGSUSED */
2125129Smarx static int
pit_beep_info(dev_info_t * dip,ddi_info_cmd_t infocmd,void * arg,void ** result)2135129Smarx pit_beep_info(dev_info_t *dip, ddi_info_cmd_t infocmd,
2145129Smarx     void *arg, void **result)
2155129Smarx {
2165129Smarx 	dev_t dev;
2175129Smarx 	pit_beep_state_t  *statep;
2185129Smarx 	int instance, error;
2195129Smarx 
2205129Smarx 	switch (infocmd) {
2215129Smarx 	case DDI_INFO_DEVT2DEVINFO:
2225129Smarx 		dev = (dev_t)arg;
2235129Smarx 		instance = PIT_BEEP_UNIT(dev);
2245129Smarx 
2255129Smarx 		if ((statep = ddi_get_soft_state(pit_beep_statep,
2265129Smarx 		    instance)) == NULL) {
2275129Smarx 
2285129Smarx 			return (DDI_FAILURE);
2295129Smarx 		}
2305129Smarx 
2315129Smarx 		*result = (void *)statep->dip;
2325129Smarx 
2335129Smarx 		error = DDI_SUCCESS;
2345129Smarx 		break;
2355129Smarx 	case DDI_INFO_DEVT2INSTANCE:
2365129Smarx 		dev = (dev_t)arg;
2375129Smarx 		instance = PIT_BEEP_UNIT(dev);
2385129Smarx 
2395129Smarx 		*result = (void *)(uintptr_t)instance;
2405129Smarx 
2415129Smarx 		error = DDI_SUCCESS;
2425129Smarx 		break;
2435129Smarx 	default:
2445129Smarx 		error = DDI_FAILURE;
2455129Smarx 
2465129Smarx 	}
2475129Smarx 
2485129Smarx 	return (error);
2495129Smarx }
2505129Smarx 
2515129Smarx 
2525129Smarx /* ARGSUSED */
2535129Smarx static void
pit_beep_freq(void * arg,int freq)2545129Smarx pit_beep_freq(void *arg, int freq)
2555129Smarx {
2565129Smarx 	int counter;
2575129Smarx 
2585129Smarx 	if (freq == 0)
2595129Smarx 		counter = 0;
2605129Smarx 	else {
2615129Smarx 		counter = PIT_HZ / freq;
2625129Smarx 		if (counter > UINT16_MAX)
2635129Smarx 			counter = UINT16_MAX;
2645129Smarx 		else if (counter < 1)
2655129Smarx 			counter = 1;
2665129Smarx 	}
2675129Smarx 
2685129Smarx 	outb(PITCTL_PORT, PIT_C2 | PIT_READMODE | PIT_RATEMODE);
2695129Smarx 	outb(PITCTR2_PORT, counter & 0xff);
2705129Smarx 	outb(PITCTR2_PORT, counter >> 8);
2715129Smarx }
2725129Smarx 
2735129Smarx 
2745129Smarx /* ARGSUSED */
2755129Smarx static void
pit_beep_on(void * arg)2765129Smarx pit_beep_on(void *arg)
2775129Smarx {
2785129Smarx 	outb(PITAUX_PORT, inb(PITAUX_PORT) | (PITAUX_OUT2 | PITAUX_GATE2));
2795129Smarx }
2805129Smarx 
2815129Smarx 
2825129Smarx /* ARGSUSED */
2835129Smarx static void
pit_beep_off(void * arg)2845129Smarx pit_beep_off(void *arg)
2855129Smarx {
2865129Smarx 	outb(PITAUX_PORT, inb(PITAUX_PORT) & ~(PITAUX_OUT2 | PITAUX_GATE2));
2875129Smarx }
288