xref: /onnv-gate/usr/src/uts/intel/io/pit_beep.c (revision 7542)
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 /*
22*7542SRichard.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 */
925129Smarx 	NULL			/* Power */
935129Smarx };
945129Smarx 
955129Smarx 
965129Smarx static struct modldrv modldrv = {
975129Smarx 	&mod_driverops, 		/* This one is a driver */
98*7542SRichard.Bean@Sun.COM 	"Intel Pit_beep Driver",	/* Name of the module. */
995129Smarx 	&pit_beep_ops,			/* Driver ops */
1005129Smarx };
1015129Smarx 
1025129Smarx 
1035129Smarx static struct modlinkage modlinkage = {
1045129Smarx 	MODREV_1, (void *)&modldrv, NULL
1055129Smarx };
1065129Smarx 
1075129Smarx 
1085129Smarx 
1095129Smarx int
1105129Smarx _init(void)
1115129Smarx {
1125129Smarx 	int error;
1135129Smarx 
1145129Smarx 	/* Initialize the soft state structures */
1155129Smarx 	if ((error = ddi_soft_state_init(&pit_beep_statep,
1165129Smarx 	    sizeof (pit_beep_state_t), 1)) != 0) {
1175129Smarx 
1185129Smarx 		return (error);
1195129Smarx 	}
1205129Smarx 
1215129Smarx 	/* Install the loadable module */
1225129Smarx 	if ((error = mod_install(&modlinkage)) != 0) {
1235129Smarx 		ddi_soft_state_fini(&pit_beep_statep);
1245129Smarx 	}
1255129Smarx 
1265129Smarx 	return (error);
1275129Smarx }
1285129Smarx 
1295129Smarx 
1305129Smarx int
1315129Smarx _info(struct modinfo *modinfop)
1325129Smarx {
1335129Smarx 	return (mod_info(&modlinkage, modinfop));
1345129Smarx }
1355129Smarx 
1365129Smarx int
1375129Smarx _fini(void)
1385129Smarx {
1395129Smarx 	int error;
1405129Smarx 
1415129Smarx 	error = mod_remove(&modlinkage);
1425129Smarx 
1435129Smarx 	if (error == 0) {
1445129Smarx 		/* Release per module resources */
1455129Smarx 		ddi_soft_state_fini(&pit_beep_statep);
1465129Smarx 	}
1475129Smarx 
1485129Smarx 	return (error);
1495129Smarx }
1505129Smarx 
1515129Smarx /*
1525129Smarx  * pit_beep_attach:
1535129Smarx  */
1545129Smarx static int
1555129Smarx pit_beep_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
1565129Smarx {
1575129Smarx 	switch (cmd) {
1585129Smarx 		case DDI_ATTACH:
1595129Smarx 			break;
1605129Smarx 		case DDI_RESUME:
1615129Smarx 
1625129Smarx 			return (DDI_SUCCESS);
1635129Smarx 		default:
1645129Smarx 
1655129Smarx 			return (DDI_FAILURE);
1665129Smarx 	}
1675129Smarx 
1685129Smarx 	pit_beep_off(dip);
1695129Smarx 
1705129Smarx 	(void) beep_init((void *)dip, pit_beep_on, pit_beep_off,
1715129Smarx 	    pit_beep_freq);
1725129Smarx 
1735129Smarx 	/* Display information in the banner */
1745129Smarx 	ddi_report_dev(dip);
1755129Smarx 
1765129Smarx 	return (DDI_SUCCESS);
1775129Smarx }
1785129Smarx 
1795129Smarx 
1805129Smarx /*
1815129Smarx  * pit_beep_detach:
1825129Smarx  */
1835129Smarx /* ARGSUSED */
1845129Smarx static int
1855129Smarx pit_beep_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
1865129Smarx {
1875129Smarx 	switch (cmd) {
1885129Smarx 		case DDI_SUSPEND:
1895129Smarx 
1905129Smarx 			/*
1915129Smarx 			 * If a beep is in progress; fail suspend
1925129Smarx 			 */
1935129Smarx 			if (!beep_busy()) {
1945129Smarx 
1955129Smarx 				return (DDI_SUCCESS);
1965129Smarx 			} else {
1975129Smarx 
1985129Smarx 				return (DDI_FAILURE);
1995129Smarx 			}
2005129Smarx 		default:
2015129Smarx 
2025129Smarx 			return (DDI_FAILURE);
2035129Smarx 	}
2045129Smarx }
2055129Smarx 
2065129Smarx 
2075129Smarx /*
2085129Smarx  * pit_beep_info:
2095129Smarx  */
2105129Smarx /* ARGSUSED */
2115129Smarx static int
2125129Smarx pit_beep_info(dev_info_t *dip, ddi_info_cmd_t infocmd,
2135129Smarx     void *arg, void **result)
2145129Smarx {
2155129Smarx 	dev_t dev;
2165129Smarx 	pit_beep_state_t  *statep;
2175129Smarx 	int instance, error;
2185129Smarx 
2195129Smarx 	switch (infocmd) {
2205129Smarx 	case DDI_INFO_DEVT2DEVINFO:
2215129Smarx 		dev = (dev_t)arg;
2225129Smarx 		instance = PIT_BEEP_UNIT(dev);
2235129Smarx 
2245129Smarx 		if ((statep = ddi_get_soft_state(pit_beep_statep,
2255129Smarx 		    instance)) == NULL) {
2265129Smarx 
2275129Smarx 			return (DDI_FAILURE);
2285129Smarx 		}
2295129Smarx 
2305129Smarx 		*result = (void *)statep->dip;
2315129Smarx 
2325129Smarx 		error = DDI_SUCCESS;
2335129Smarx 		break;
2345129Smarx 	case DDI_INFO_DEVT2INSTANCE:
2355129Smarx 		dev = (dev_t)arg;
2365129Smarx 		instance = PIT_BEEP_UNIT(dev);
2375129Smarx 
2385129Smarx 		*result = (void *)(uintptr_t)instance;
2395129Smarx 
2405129Smarx 		error = DDI_SUCCESS;
2415129Smarx 		break;
2425129Smarx 	default:
2435129Smarx 		error = DDI_FAILURE;
2445129Smarx 
2455129Smarx 	}
2465129Smarx 
2475129Smarx 	return (error);
2485129Smarx }
2495129Smarx 
2505129Smarx 
2515129Smarx /* ARGSUSED */
2525129Smarx static void
2535129Smarx pit_beep_freq(void *arg, int freq)
2545129Smarx {
2555129Smarx 	int counter;
2565129Smarx 
2575129Smarx 	if (freq == 0)
2585129Smarx 		counter = 0;
2595129Smarx 	else {
2605129Smarx 		counter = PIT_HZ / freq;
2615129Smarx 		if (counter > UINT16_MAX)
2625129Smarx 			counter = UINT16_MAX;
2635129Smarx 		else if (counter < 1)
2645129Smarx 			counter = 1;
2655129Smarx 	}
2665129Smarx 
2675129Smarx 	outb(PITCTL_PORT, PIT_C2 | PIT_READMODE | PIT_RATEMODE);
2685129Smarx 	outb(PITCTR2_PORT, counter & 0xff);
2695129Smarx 	outb(PITCTR2_PORT, counter >> 8);
2705129Smarx }
2715129Smarx 
2725129Smarx 
2735129Smarx /* ARGSUSED */
2745129Smarx static void
2755129Smarx pit_beep_on(void *arg)
2765129Smarx {
2775129Smarx 	outb(PITAUX_PORT, inb(PITAUX_PORT) | (PITAUX_OUT2 | PITAUX_GATE2));
2785129Smarx }
2795129Smarx 
2805129Smarx 
2815129Smarx /* ARGSUSED */
2825129Smarx static void
2835129Smarx pit_beep_off(void *arg)
2845129Smarx {
2855129Smarx 	outb(PITAUX_PORT, inb(PITAUX_PORT) & ~(PITAUX_OUT2 | PITAUX_GATE2));
2865129Smarx }
287